make the update of the period level QA safe (by running in a temp location and only...
[u/mrichter/AliRoot.git] / TPC / Base / AliDigits.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 /* $Id$ */
17
18 /*MI change -- for Rule checker
19           -- added copy constructor and assignmet operator 
20           -- new GetSize return size of object in Bytes
21           -- added GetDigitSize and GetOverTh function
22           -- added GetNRows, GetNCols function
23           -- for Marek -I had it in my code  
24 */ 
25
26 ///////////////////////////////////////////////////////////////////////////////
27 //                                                                           //
28 //   Alice  digits array  object  AliDigits                                  //
29 //                                                                           //
30 //                                                                           //
31 //                                                                           //
32 ///////////////////////////////////////////////////////////////////////////////
33
34
35 #include "TClass.h"
36 #include <Riostream.h>
37 #include "TError.h"
38 #include "AliSegmentID.h"
39 #include "AliH2F.h"
40 #include <TArrayI.h>
41 #include <TArrayS.h>
42 #include "AliDigits.h"
43
44
45
46 //_____________________________________________________________________________
47 //_____________________________________________________________________________
48 //_____________________________________________________________________________
49 ClassImp(AliDigits)
50
51
52  AliDigits::AliDigits()
53            :AliSegmentID(),
54             fNrows(0),
55             fNcols(0),
56             fElements(0),
57             fIndex(0),
58             fBufType(0),
59             fThreshold(0),
60             fNelems(0),
61             fCurrentRow(0),
62             fCurrentCol(0),
63             fCurrentIndex(0) 
64 {
65   // 
66   //default constructor
67   //
68   Invalidate();
69 }
70
71 AliDigits::AliDigits(const AliDigits& digits)
72           :AliSegmentID(digits),
73             fNrows(0),
74             fNcols(0),
75             fElements(0),
76             fIndex(0),
77             fBufType(0),
78             fThreshold(0),
79             fNelems(0),
80             fCurrentRow(0),
81             fCurrentCol(0),
82             fCurrentIndex(0)
83 {
84   //
85   //copy constructor
86   //
87   fNrows = digits.fNrows;
88   fNcols = digits.fNcols;
89   fElements = new TArrayS(*(digits.fElements));
90   fIndex = new TArrayI(*(digits.fIndex));
91   fBufType = digits.fBufType;
92   fThreshold = digits.fThreshold;
93   fNelems    = digits.fNelems;
94 }
95
96 AliDigits & AliDigits::operator =(const AliDigits & digits)
97 {
98   //assignment operator
99   if (this == &digits) return (*this); 
100
101   fNrows = digits.fNrows;
102   fNcols = digits.fNcols;
103   if (fElements) delete fElements;
104   fElements = new TArrayS(*(digits.fElements));
105   if (fIndex) delete fIndex;
106   fIndex = new TArrayI(*(digits.fIndex));
107   fBufType = digits.fBufType;
108   fThreshold = digits.fThreshold;
109   fNelems    = digits.fNelems; 
110   return (*this);
111 }
112
113 AliDigits::~AliDigits()
114 {
115   //
116   //default destructor
117   if (fIndex !=0 ) {
118     delete fIndex;
119   }
120   if (fElements != 0) {
121     delete fElements;
122   }
123   
124   
125 }
126
127
128 Bool_t AliDigits::OutOfBoundsError(const char *where, Int_t row, Int_t column) 
129 {
130    // Generate an out-of-bounds error. Always returns false.
131    ::Error(where, "row %d  col %d out of bounds (size: %d x %d, this: 0x%08lx)", 
132            row, column, fNrows, fNcols, (ULong_t) this);
133    return kFALSE;
134 }
135
136
137 void AliDigits::Invalidate() 
138
139   //
140   //set default (invalid parameters)
141   if (fIndex != 0)  delete  fIndex;
142   fIndex = new TArrayI;
143   
144   if (fElements!= 0)     delete  fElements;
145   
146   fElements = new TArrayS;
147   
148   fNrows = fNcols =fNelems= -1; 
149   fElements->Set(0); 
150   fIndex->Set(0); 
151   fBufType = -1;
152 }
153
154 void AliDigits::Allocate(Int_t rows, Int_t columns)
155 {
156   //
157   //construct empty buffer fDigits with size rows x columns
158   Invalidate();
159   if (rows <= 0) {
160       Error("Allocate", "no of rows has to be positive");
161       return;
162    }
163    if (columns <= 0) {
164       Error("Allocate", "no of columns has to be positive");
165       return;
166    }
167   fNrows = rows;
168   fNcols=columns;
169   fNelems = fNrows * fNcols;
170   fElements->Set(fNelems);
171   fIndex->Set(fNcols);
172   for (Int_t i =0,k=0; i<fNcols;i++,k+=fNrows) 
173   (*fIndex)[i]=k;
174   fBufType =0;
175 }
176
177
178 Int_t AliDigits::GetSize()
179 {
180   //
181   //return size of object as represented in the memory
182   //
183   //  Int_t size = sizeof(this);
184   Int_t size = 0;   // COVERITY consider the previous statment as bug 
185                     // 
186   if (fIndex!=0) size+= sizeof(fIndex)+fIndex->GetSize()*sizeof(Int_t);
187   if (fElements!=0) size+= sizeof(fElements)+fElements->GetSize()*sizeof(Short_t);
188   return size;
189 }
190
191 Int_t AliDigits::GetDigitSize() //return total size of pure digit
192 {
193   //
194   //return size of PURE DIGITS
195   //
196   if (fElements==0) return 0;
197   else return sizeof(fElements)+fElements->GetSize()*sizeof(Short_t);
198 }
199
200 Int_t AliDigits::GetOverTh(Float_t threshold,Float_t x1, Float_t x2, Float_t y1, Float_t y2)
201 {
202   //
203   //return number of digits over threshold
204   // 
205  if ( (fElements==0) || (fElements->GetSize()<=0)) return 0;
206  
207  if (x1<=x2) {
208     x1=0;
209     x2=fNrows;
210   }
211   if (y1<=y2) {
212      y1=0;
213      y2=fNcols;
214   }
215   Int_t over=0;
216
217   Bool_t cont=First();
218   for ( cont=First(); cont==kTRUE;cont=Next()) {
219     if ( (CurrentRow()<x1) || (CurrentRow()>x2)) continue;
220     if ( (CurrentColumn()<y1) || (CurrentColumn()>y2)) continue;
221     if (CurrentDigit()>threshold) over++;
222   }
223   return over;
224 }
225
226
227 Short_t AliDigits::GetDigit(Int_t row, Int_t column)
228 {
229   //
230   // return digit for given row and collumn
231   if (fBufType ==0) return GetDigitFast(row,column);
232   if (fBufType ==1) return GetDigit1(row,column);
233
234   return 0;
235 }
236
237
238 void AliDigits::ExpandBuffer()
239 {  
240   //
241   //expand buffer to two dimensional array
242   if (fBufType<0)  {
243     Error("ExpandBuffer", "buffer doesn't exist");
244     return;
245   }
246   if (fBufType==0)      return;
247   
248   //expanding of buffer type 1
249   if (fBufType==1) ExpandBuffer1();
250   
251   fBufType = 0;
252 }
253
254 void AliDigits::CompresBuffer(Int_t bufferType,Int_t threshold)
255 {
256   //
257   //compres buffer according buffertype algorithm
258   if (fBufType<0)  {
259     Error("CompressBuffer", "buffer doesn't exist");
260     return;
261   }
262   if (fBufType == bufferType) return;
263   //
264   if (fBufType>0) ExpandBuffer();
265   if (fBufType !=0)  {
266     Error("CompressBuffer", "buffer doesn't exist");
267     return;
268   }
269   fThreshold = threshold;
270   //compress buffer of type 1
271   if ( bufferType == 1) CompresBuffer1();//end of compresing bufer of type 1 
272 }
273
274 Bool_t AliDigits::First()
275 {
276   //adjust  first valid current digit
277   if (fBufType ==0) return First0();
278   if (fBufType ==1) return First1();
279   return kFALSE;
280 }
281
282 Bool_t  AliDigits::Next()
283 {
284   //addjust next valid current digit
285   if (fBufType ==0) return Next0();
286   if (fBufType ==1) return Next1();
287   return kFALSE;
288 }
289  
290 void AliDigits::AcceptHisto(AliH2F * his)
291 {
292   //
293   //make digits buffer with value according histograms values
294   //for testing purpose  
295   Int_t idim =his->GetNbinsX();
296   Int_t jdim =his->GetNbinsY();
297   if ( (idim<1)|| (jdim<1)) {
298     return;
299   }
300   //allocate proper buffer size
301   Allocate(idim,jdim);
302   //set digits values
303   for (Int_t i = 0; i<idim;i++)    
304     for (Int_t j = 0; j<jdim;j++)
305       {
306         Int_t index = his->GetBin(i+1,j+1);     
307         SetDigitFast((Short_t)his->GetBinContent(index),i,j);
308       }   
309 }
310
311 AliH2F *  AliDigits::GenerHisto()
312 {
313   //
314   //make digits histo 
315   char ch[30];
316   snprintf(ch,30, "Segment_%d ",GetID());
317   if ( (fNrows<1)|| (fNcols<1)) {
318     return 0;
319   }
320   AliH2F * his  = new AliH2F("Digit histo",ch,fNrows,0,fNrows,fNcols,0,fNcols);
321   ExpandBuffer();
322   //set histogram  values
323   for (Int_t i = 0; i<fNrows;i++)    
324     for (Int_t j = 0; j<fNcols;j++)
325         his->Fill(i,j,GetDigitFast(i,j));
326   return his;
327 }
328
329 AliH2F *AliDigits::DrawDigits(const char *option,Float_t x1, Float_t x2, Float_t y1, Float_t y2)
330 {
331   //
332   //draw digits in given array
333   //
334   AliH2F *h2f = GenerHisto();
335   if (x1>=0) {
336       AliH2F *h2fsub = h2f->GetSubrange2d(x1,x2,y1,y2);
337       delete h2f;
338       h2f=h2fsub;
339   }
340   if (h2f==0) return 0;
341   if (option!=0) h2f->Draw(option);
342   else h2f->Draw();
343   return h2f;  
344 }
345
346 void AliDigits::ExpandBuffer1()
347 {
348   //
349   //expand buffer of type to twodimensional array
350   Int_t i,k;
351   fNelems = fNrows*fNcols;
352   Short_t * buf = new Short_t[fNelems];
353   memset(buf,0,fNelems*sizeof(Short_t)); //MI change - 4.12.2000
354   fIndex->Set(fNcols);
355   for (i =0,k=0 ;i<fNcols;i++,k+=fNrows) (*fIndex)[i]=k;
356   Int_t col=0;
357   Int_t row = 0;
358   Int_t n=fElements->fN;
359   for (i=0;i<n;i++){
360     //oposite signa means how many unwrited (under threshold) values
361     if ((*fElements)[i]<0) row-=fElements->At(i); 
362     else {
363       buf[(*fIndex)[col]+row]=fElements->At(i);
364       row++;
365     }
366     if (row==fNrows) {
367       row=0;
368       col++;
369     }else 
370       if (row>fNrows){
371         Invalidate();
372         delete [] buf;
373         return;
374       }      
375   }
376   fElements->Adopt(fNelems,buf);    
377 }
378
379 void AliDigits::CompresBuffer1()
380 {
381   //
382   //compres buffer according  algorithm 1
383   //
384   TArrayS  buf;  //lets have the nearly the "worst case"
385   buf.Set(fNelems);
386   TArrayI  index;
387   index.Set(fNcols);
388   Int_t icurrent=-1;
389   Int_t izero;
390   Short_t * cbuff = fElements->GetArray();  //MI change
391
392   for (Int_t col = 0; col<fNcols; col++){      
393     index[col]=icurrent+1;//set collumn pointer
394     izero = 0;  //reset zer counter at the begining of the column
395     for (Int_t row = 0; row< fNrows;row++){
396       //if under threshold
397       //if (GetDigitFast(row,col)<=fThreshold)  izero++;
398       if (*cbuff<=fThreshold)  izero++;
399
400       else{
401         if (izero>0) {
402           //if we have currently izero count under threshold
403           icurrent++;     
404           if (icurrent>=buf.fN) buf.Set(icurrent*2);
405           buf[icurrent]= -izero;  //write how many under zero
406           izero = 0;
407         } //end of reseting izero
408         icurrent++;
409         if (icurrent>=buf.fN) buf.Set(icurrent*2);
410         //buf[icurrent] = GetDigitFast(row,col);            
411         buf[icurrent] = *cbuff;     
412       }//if signal bigger then threshold        
413        cbuff++;
414     } //end of loop over rows
415     if (izero>0) {
416       icurrent++;         
417       if (icurrent>=buf.fN) buf.Set(icurrent*2);
418       buf[icurrent]= -izero;  //write how many under zero
419     }
420   }//end of lopping over digits
421   buf.Set(icurrent+1);
422   (*fElements)=buf;
423   fNelems = fElements->fN;
424   fBufType = 1;
425   (*fIndex) =index;
426   //end of compresing bufer of type 1 
427 }
428
429
430
431 Bool_t AliDigits::First0()
432 {
433   //
434   //first for the buffer type 0
435   fCurrentRow = -1;
436   fCurrentCol = -1;
437   fCurrentIndex = -1;
438   Int_t i;
439   for (i=0; (( i<fNelems) && (fElements->At(i)<=fThreshold));i++) {}  //MI1211
440   if (i == fNelems) return kFALSE;
441   fCurrentCol =i/fNrows;
442   fCurrentRow =i%fNrows;
443   fCurrentIndex = i;
444   return kTRUE; 
445 }
446
447 Bool_t AliDigits::Next0()
448 {
449   //
450   //next for the buffer type 0
451   //
452   if (fCurrentIndex<0) return kFALSE;  // if we didn't adjust first 
453   Int_t i;
454   for (i=fCurrentIndex+1; ( (i<fNelems) && (fElements->At(i)<=fThreshold) ) ;i++) {}
455   if (i >= fNelems)  {
456     fCurrentIndex = -1;
457     return kFALSE;
458   }
459   fCurrentCol =i/fNrows;
460   fCurrentRow =i%fNrows;
461   fCurrentIndex = i;
462   return kTRUE; 
463 }
464
465 Bool_t AliDigits::First1()
466 {
467   //
468   //first for the buffer type 1
469   fCurrentRow = -1;
470   fCurrentCol = 0;
471   fCurrentIndex = -1;
472   Int_t i;
473   for (i=0; i<fNelems; i++){
474     if (fElements->At(i) < 0) fCurrentRow-=fElements->At(i);
475     else      
476       fCurrentRow++;
477     if (fCurrentRow>=fNrows) {
478        fCurrentCol++;
479        fCurrentRow-=fNrows;
480     }
481     if (fElements->At(i)>fThreshold) break;
482   }
483   fCurrentIndex = i;
484   if (fCurrentIndex>=0&&i<fNelems) return kTRUE;
485   fCurrentRow =-1;
486   fCurrentCol =-1;
487   return kFALSE;        
488 }
489
490 Bool_t AliDigits::Next1()
491 {
492   //
493   //next for the buffer type 1
494   if (fCurrentIndex<0) return kFALSE;  // if we didn't adjust first 
495   Int_t i;
496   for (i=fCurrentIndex+1; i<fNelems;i++){
497     if (fElements->At(i) < 0) fCurrentRow-=fElements->At(i);
498     else      
499       fCurrentRow++;
500     if (fCurrentRow>=fNrows) {
501       fCurrentCol++;
502       fCurrentRow-=fNrows;
503     }
504     if (fElements->At(i)>fThreshold) break;
505   }
506   fCurrentIndex = i;
507   if ( (i>=0) && (i<fNelems) ) return kTRUE;
508   fCurrentRow =-1;
509   fCurrentCol =-1;
510   return kFALSE;
511 }
512
513 Short_t AliDigits::GetDigit1(Int_t row, Int_t column)
514 {
515   //
516   //return digit for given row and column  the buffer type 1
517   //no control performed
518   
519   Int_t i,n2;
520   if ( (column+1)>=fNcols) n2 = fNelems;
521   else
522     n2 = fIndex->At(column+1);
523   Int_t irow = 0; //current row    
524  
525   for (i=fIndex->At(column); ( (i<n2) && (irow<row) );i++){
526     if (fElements->At(i) < 0) irow-=fElements->At(i);
527     else      
528       irow++;
529   }
530   if ( irow == row ) return fElements->At(i);
531   return -1;
532 }
533