5459b06a8374dc664f95af47813143ab5a99e0a9
[u/mrichter/AliRoot.git] / ITS / AliITSBadChannelsAuxSPD.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 */
19
20 ///////////////////////////////////////////////////////////////////////////
21 // AliITSBadChannelsAuxSPD implementation by P. Nilsson 2005
22 // AUTHOR/CONTACT: Paul.Nilsson@cern.ch
23 //
24 // Auxiliary algorithms for the SPD
25 //
26 // This class contains converter methods and general algorithms for
27 // handling digit <-> channel convertions and methods for identifying
28 // changes (diff's) in arrays of bad channels, and for finding channels
29 // or digits in arrays of bad channels.
30 //
31 // The Diff algorithm can be used to check if there are any changes among
32 // the noisy channels. It returns two arrays, one with noisy channels
33 // are no longer visible (less likely to happen) and one with newly found
34 // noisy channels (more likely to happen).
35 //
36 // The Find algorithms looks for a given digit or channel in an array of
37 // known channels. It can be used by the clustering algorithms to check
38 // if a given digit that is about to be clustered, is in fact a known
39 // noisy channel. It should not be used in a normal cluster.
40 //
41 // Examples - Converters
42 //
43 // root [0] AliITSdigitSPD *d = new AliITSdigitSPD();
44 // root [1] d->SetCoord1(1);
45 // root [2] d->SetCoord2(2);
46 // root [3] d->SetSignal(1);
47 // root [4] AliITSBadChannelsAuxSPD *aux = new AliITSBadChannelsAuxSPD();
48 // root [5] AliITSChannelSPD *c = aux->CreateChannelFromDigit(d);
49 // root [6] cout << c->GetColumn() << endl;
50 // 1
51 // root [7] cout << c->GetRow() << endl;
52 // 2
53 // root [8] AliITSdigitSPD *d2 = aux->CreateDigitFromChannel(c);
54 // root [9] cout << d2->GetCoord1() << endl;
55 // 1
56 // root [10] cout << d2->GetCoord2() << endl;
57 // 2
58 // root [11] cout << d2->GetSignal() << endl;
59 // 1
60 // root [12] delete d2;
61 // root [13] delete d;
62 // root [14] delete c;
63 //
64 // The signal member of the digit is not a member of the channel class.
65 // It is artificially introduced by the CreateDigitFromChannel method and
66 // is per default set to 1.
67 ///////////////////////////////////////////////////////////////////////////
68
69 #include "AliITSBadChannelsAuxSPD.h"
70
71 ClassImp(AliITSBadChannelsAuxSPD)
72
73 //__________________________________________________________________________
74 AliITSBadChannelsAuxSPD::AliITSBadChannelsAuxSPD(void)
75 {
76   // Default constructor
77 }
78
79 //__________________________________________________________________________
80 Bool_t AliITSBadChannelsAuxSPD::Diff(TObjArray *&inputArray1, TObjArray *&inputArray2,
81                                      TObjArray *&outputArray1, TObjArray *&outputArray2) const
82 {
83   // Make a diff between the input TObjArrays
84   // 
85   // Input: Two input TObjArrays of AliITSChannelSPD objects to be tested, two output TObjArrays corresponding
86   //        to 
87   // Output: Two output TObjArrays where outputArray1 contains the AliITSChannelSPD objects from inputArray1
88   //         that are not in inputArray2, vice versa for outputArray2.
89   // Return: kTRUE if the arrays differ
90
91   Bool_t status = kFALSE;
92
93   const Int_t kInputArray1Size = inputArray1->GetEntries();
94   const Int_t kInputArray2Size = inputArray2->GetEntries();
95   AliITSChannelSPD *ch1 = 0;
96   AliITSChannelSPD *ch2 = 0;
97   Bool_t found = kFALSE;
98
99   Int_t i = 0, j = 0;
100
101   // Pass 1
102   Int_t lastFoundAtJ = -1;
103   for (i = 0; i < kInputArray1Size; i++)
104     {
105       // Get the next channel from array 1
106       ch1 = (AliITSChannelSPD *) inputArray1->At(i);
107
108       // Is ch1 also in array 2?
109       for (j = lastFoundAtJ + 1; j < kInputArray2Size; j++)
110         {
111           ch2 = (AliITSChannelSPD *) inputArray2->At(j);
112           if (*ch1 == *ch2)
113             {
114               // Abort, go to next i
115               found = kTRUE;
116               lastFoundAtJ = j;
117               break;
118             }
119         }
120
121       // If ch1 was not found in array 2, store it
122       if (!found)
123         {
124           outputArray1->Add(ch1);
125         }
126       else
127         {
128           found = kFALSE;
129         }
130     }
131
132   // Pass 2
133   lastFoundAtJ = -1;
134   for (i = 0; i < kInputArray2Size; i++)
135     {
136       // Get the next channel from array 2
137       ch2 = (AliITSChannelSPD *) inputArray2->At(i);
138
139       // Is ch2 also in array 1?
140       for (j = lastFoundAtJ + 1; j < kInputArray1Size; j++)
141         {
142           ch1 = (AliITSChannelSPD *) inputArray1->At(j);
143           if (*ch1 == *ch2)
144             {
145               // Abort, go to next i
146               found = kTRUE;
147               lastFoundAtJ = j;
148               break;
149             }
150         }
151
152       // If ch1 was not found in array 1, store it
153       if (!found)
154         {
155           outputArray2->Add(ch2);
156         }
157       else
158         {
159           found = kFALSE;
160         }
161     }
162
163   if (outputArray1->GetEntries() > 0 || outputArray2->GetEntries() > 0) status = kTRUE;
164
165   return status;
166 }
167
168 //__________________________________________________________________________
169 Bool_t AliITSBadChannelsAuxSPD::Find(AliITSChannelSPD *&channel, TObjArray *&array) const
170 {
171   // Find the channel in the array
172   //
173   // Input: AliITSChannelSPD channel object, TObjArray of AliITSChannelSPD channel objects
174   // Ouput: (none)
175   // Return: kTRUE if channel is found in the array, kFALSE otherwise
176
177   Bool_t status = kFALSE;
178
179   // Loop over all channels in the array
180   Int_t channelNr = 0;
181   const Int_t kN = array->GetEntries();
182   while (channelNr < kN)
183     {
184       if (*channel == *(AliITSChannelSPD *)array->At(channelNr))
185         {
186           status = kTRUE;
187           break;
188         }
189
190       // Go to next channel
191       channelNr++;
192     }
193
194   return status;
195 }
196
197 //__________________________________________________________________________
198 Bool_t AliITSBadChannelsAuxSPD::Find(AliITSdigitSPD *&digit, TObjArray *&array) const
199 {
200   // Find the digit in the array
201   //
202   // WARNING: Using AliITSdigitSPD digits in this way is roughly 10% slower than to use AliITSChannelSPD channels
203   //
204   // Input: AliITSdigitSPD digit object, TObjArray of AliITSChannelSPD channel objects
205   // Ouput: (none)
206   // Return: kTRUE if digit is found in the array, kFALSE otherwise
207
208   Bool_t status = kFALSE;
209
210   AliITSChannelSPD *channel = 0;
211   const Int_t kN = array->GetEntries();
212   Int_t channelNr = 0;
213   Int_t column = digit->GetCoord1();
214   Int_t row = digit->GetCoord1();
215
216   // Loop over all channels in the array
217   while (channelNr < kN)
218     {
219       channel = (AliITSChannelSPD *)array->At(channelNr);
220       if ( (channel->GetColumn() == column) && (channel->GetRow() == row) )
221         {
222           status = kTRUE;
223           break;
224         }
225
226       // Go to next channel
227       channelNr++;
228     }
229
230   return status;
231 }
232
233 //__________________________________________________________________________
234 AliITSdigitSPD* AliITSBadChannelsAuxSPD::CreateDigitFromChannel(const AliITSChannelSPD *&channel) const
235 {
236   // Create a digit from a channel
237   //
238   // Input: AliITSChannelSPD object
239   // Ouput: (none)
240   // Return: AliITSdigitSPD object
241
242   AliITSdigitSPD *digit = new AliITSdigitSPD();
243
244   digit->SetCoord1(channel->GetColumn());
245   digit->SetCoord2(channel->GetRow());
246   digit->SetSignal(1);
247
248   return digit;
249 }
250
251 //__________________________________________________________________________
252 AliITSChannelSPD* AliITSBadChannelsAuxSPD::CreateChannelFromDigit(const AliITSdigitSPD *&digit) const
253 {
254   // Create a channel from a digit
255   //
256   // Input: AliITSdigitSPD object
257   // Ouput: (none)
258   // Return: AliITSChannelSPD object
259
260   AliITSChannelSPD *channel = new AliITSChannelSPD();
261
262   channel->SetColumn(digit->GetCoord1());
263   channel->SetRow(digit->GetCoord2());
264
265   return channel;
266 }
267
268 //__________________________________________________________________________
269 Int_t AliITSBadChannelsAuxSPD::GetNumberOfBadChannels(Int_t* &badChannelsArray, Int_t* &indexArray, Int_t size) const
270 {
271   // Get the total number of bad channels
272
273   Int_t n = 0;
274
275   // Loop over all modules
276   for (Int_t module = 0; module < size; module++)
277     {
278       // Get the module size (i.e. the number of bad channels)
279       n += badChannelsArray[indexArray[module]];
280     }
281
282   return n;
283 }
284
285 //__________________________________________________________________________
286 Bool_t AliITSBadChannelsAuxSPD::CreateHTMLReport(char *name, Int_t* &badChannelsArray, Int_t* &indexArray,
287                                                  const Int_t indexArraySize, TString *buffer, Bool_t tags)
288 {
289   // Create an HTML report from the bad channels array
290   //
291   // Input : file name, badChannelsArray, indexArray, size of indexArray (i.e. number of modules),
292   //         tags boolean (if true, html tags will be added; if false, only formatted text will be created)
293   // Output: TString (buffer) containing the html code/ASCII text
294   // Return: kTRUE if a report has been created
295
296   Bool_t status = kFALSE;
297
298   Int_t totalNumberOfBadChannels = 0;
299   Int_t numberOfModulesWithBadChannels = 0;
300
301   if (tags)
302     {
303       buffer->Append("<html>");
304       buffer->Append("<head><title>SPD bad channels</title></head>\n");
305       buffer->Append("<body>\n");
306     }
307
308   buffer->Append("HTML report for file: ");
309   buffer->Append(name);
310
311   tags ? buffer->Append("<br>\n<br>\n") : buffer->Append("\n\n");
312
313   char temp[10];
314
315   // Loop over all modules
316   for (Int_t module = 0; module < indexArraySize; module++)
317     {
318       // Get the start position of the data
319       Int_t position = indexArray[module];
320
321       // Get the module size (i.e. the number of bad channels)
322       Int_t size = badChannelsArray[position++];
323
324       // Only continue if there are bad channels in this module
325       if (size > 0)
326         {
327           // There are bad channels in this file
328           status = kTRUE;
329           numberOfModulesWithBadChannels++;
330           totalNumberOfBadChannels += size;
331
332           // Create report
333           buffer->Append("SPD module = ");
334           sprintf(temp,"%d",module);
335           buffer->Append(temp);
336           buffer->Append("<br>\n");
337           buffer->Append("Number of bad channels = ");
338           sprintf(temp,"%d",size);
339           buffer->Append(temp);
340
341           tags ? buffer->Append("<br>\n") : buffer->Append("\n");
342
343           buffer->Append("(column, row) = ");
344
345           // Get all bad channels
346           Int_t i = 0;
347           while (i < size)
348             {
349               // Create and add the current channel
350               buffer->Append("(");
351               sprintf(temp,"%d",badChannelsArray[position++]);
352               buffer->Append(temp);
353               buffer->Append(", ");
354               sprintf(temp,"%d",badChannelsArray[position++]);
355               buffer->Append(temp);
356               buffer->Append(")");
357
358               if (i < size - 1)
359                 {
360                   buffer->Append(", ");
361                 }
362               else
363                 {
364                   tags ? buffer->Append("<br>\n") : buffer->Append("\n");
365                 }
366
367               // Go to next bad channel
368               i++;
369             }
370
371           tags ? buffer->Append("<br>\n") : buffer->Append("\n");
372
373         } // if size > 0
374     } // end loop over modules
375
376   if (!status)
377     {
378       buffer->Append("(Data does not contain any known bad channels)");
379     }
380
381   tags ? buffer->Append("<br>\n") : buffer->Append("\n");
382
383   buffer->Append("Total number of bad channels = ");
384   sprintf(temp,"%d",totalNumberOfBadChannels);
385   buffer->Append(temp);
386
387   tags ? buffer->Append("<br>\n") : buffer->Append("\n");
388
389   buffer->Append("Number of modules with bad channels = ");
390   sprintf(temp,"%d",numberOfModulesWithBadChannels);
391   buffer->Append(temp);
392
393   tags ? buffer->Append("<br>\n") : buffer->Append("\n");
394
395   buffer->Append("Number of modules = ");
396   sprintf(temp,"%d",indexArraySize);
397   buffer->Append(temp);
398
399   if (tags)
400     {
401       buffer->Append("<br>\n");
402       buffer->Append("</body>\n");
403       buffer->Append("</html>");
404     }
405   else
406     {
407       buffer->Append("\n");
408     }
409
410   return status;
411 }