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