c4975916993c48602a2aca99d41435563e5392ed
[u/mrichter/AliRoot.git] / CONTAINERS / 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 /*
17
18 $Log$
19 Revision 1.4  2000/10/05 16:01:49  kowal2
20 Corrected for memory leaks.
21
22 Revision 1.3  2000/06/30 12:07:49  kowal2
23 Updated from the TPC-PreRelease branch
24
25 Revision 1.2.4.3  2000/06/26 07:39:42  kowal2
26 Changes to obey the coding rules
27
28 Revision 1.2.4.2  2000/06/25 08:38:41  kowal2
29 Splitted from AliTPCtracking
30
31 Revision 1.2.4.1  2000/06/14 16:45:13  kowal2
32 Improved algorithms. Compiler warnings removed.
33
34 Revision 1.2  2000/04/17 09:37:33  kowal2
35 removed obsolete AliTPCDigitsDisplay.C
36
37 Revision 1.1.4.2  2000/04/10 11:37:42  kowal2
38
39 Digits handling in a new data structure
40
41 */
42
43 /*MI change -- for Rule checker
44           -- added copy constructor and assignmet operator 
45           -- new GetSize return size of object in Bytes
46           -- added GetDigitSize and GetOverTh function
47           -- added GetNRows, GetNCols function
48           -- for Marek -I had it in my code  
49 */ 
50
51 ///////////////////////////////////////////////////////////////////////////////
52 //                                                                           //
53 //   Alice  digits array  object  AliDigits                                  //
54 //                                                                           //
55 //                                                                           //
56 //                                                                           //
57 ///////////////////////////////////////////////////////////////////////////////
58
59
60 #include "TClass.h"
61 #include <iostream.h>
62 #include "TError.h"
63 #include "AliSegmentID.h"
64 #include "AliH2F.h"
65 #include "AliArrayI.h"
66 #include "AliArrayS.h"
67 #include "AliDigits.h"
68
69
70
71 //_____________________________________________________________________________
72 //_____________________________________________________________________________
73 //_____________________________________________________________________________
74 ClassImp(AliDigits)
75
76
77 AliDigits::AliDigits()
78 {
79   // 
80   //default constructor
81   fIndex = 0;
82   fElements = 0;
83   fThreshold =0;
84   Invalidate();
85 }
86
87 AliDigits::AliDigits(const AliDigits& digits)
88 {
89   //
90   //copy constructor
91   fNrows = digits.fNrows;
92   fNcols = digits.fNcols;
93   fElements = new AliArrayS(*(digits.fElements));
94   fIndex = new AliArrayI(*(digits.fIndex));
95   fBufType = digits.fBufType;
96   fThreshold = digits.fThreshold;
97   fNelems    = digits.fNelems;
98 }
99
100 AliDigits & AliDigits::operator =(const AliDigits & digits)
101 {
102  //assignment operator
103   fNrows = digits.fNrows;
104   fNcols = digits.fNcols;
105   if (fElements) delete fElements;
106   fElements = new AliArrayS(*(digits.fElements));
107   if (fIndex) delete fIndex;
108   fIndex = new AliArrayI(*(digits.fIndex));
109   fBufType = digits.fBufType;
110   fThreshold = digits.fThreshold;
111   fNelems    = digits.fNelems; 
112   return (*this);
113 }
114
115 AliDigits::~AliDigits()
116 {
117   //
118   //default destructor
119   if (fIndex !=0 ) {
120     delete fIndex;
121   }
122   if (fElements != 0) {
123     delete fElements;
124   }
125   
126   
127 }
128
129
130 Bool_t AliDigits::OutOfBoundsError(const char *where, Int_t row, Int_t column) 
131 {
132    // Generate an out-of-bounds error. Always returns false.
133    ::Error(where, "row %d  col %d out of bounds (size: %d x %d, this: 0x%08x)", 
134            row, column, fNrows, fNcols, this);
135    return kFALSE;
136 }
137
138
139 void AliDigits::Invalidate() 
140
141   //
142   //set default (invalid parameters)
143   if (fIndex != 0)  delete  fIndex;
144   fIndex = new AliArrayI;
145   
146   if (fElements!= 0)     delete  fElements;
147   
148   fElements = new AliArrayS;
149   
150   fNrows = fNcols =fNelems= -1; 
151   fElements->Set(0); 
152   fIndex->Set(0); 
153   fBufType = -1;
154 }
155
156 void AliDigits::Allocate(Int_t rows, Int_t columns)
157 {
158   //
159   //construct empty buffer fDigits with size rows x columns
160   Invalidate();
161   if (rows <= 0) {
162       Error("Allocate", "no of rows has to be positive");
163       return;
164    }
165    if (columns <= 0) {
166       Error("Allocate", "no of columns has to be positive");
167       return;
168    }
169   fNrows = rows;
170   fNcols=columns;
171   fNelems = fNrows * fNcols;
172   fElements->Set(fNelems);
173   fIndex->Set(fNcols);
174   for (Int_t i =0,k=0; i<fNcols;i++,k+=fNrows) 
175   (*fIndex)[i]=k;
176   fBufType =0;
177 }
178
179
180 Int_t AliDigits::GetSize()
181 {
182   //
183   //return size of object
184   //
185   Int_t size = sizeof(this);
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   sprintf(ch,"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   fIndex->Set(fNcols);
354   for (i =0,k=0 ;i<fNcols;i++,k+=fNrows) (*fIndex)[i]=k;
355   Int_t col=0;
356   Int_t row = 0;
357   Int_t n=fElements->fN;
358   for (i=0;i<n;i++){
359     //oposite signa means how many unwrited (under threshold) values
360     if ((*fElements)[i]<0) row-=fElements->At(i); 
361     else {
362       buf[(*fIndex)[col]+row]=fElements->At(i);
363       row++;
364     }
365     if (row==fNrows) {
366       row=0;
367       col++;
368     }else 
369       if (row>fNrows){
370         Invalidate();
371         return;
372       }      
373   }
374   fElements->Adopt(fNelems,buf);    
375 }
376 void AliDigits::CompresBuffer1()
377 {
378   //
379   //compres buffer according  algorithm 1
380   //
381   AliArrayS  buf;  //lets have the nearly the "worst case"
382   buf.Set(fNelems);
383   AliArrayI  index;
384   index.Set(fNcols);
385   Int_t icurrent=-1;
386   Int_t izero;
387   for (Int_t col = 0; col<fNcols; col++){      
388     index[col]=icurrent+1;//set collumn pointer
389     izero = 0;  //reset zer counter at the begining of the column
390     for (Int_t row = 0; row< fNrows;row++){
391       //if under threshold
392       if (GetDigitFast(row,col)<=fThreshold)  izero++;
393       else{
394         if (izero>0) {
395           //if we have currently izero count under threshold
396           icurrent++;     
397           if (icurrent>=buf.fN) buf.Expand(icurrent*2);
398           buf[icurrent]= -izero;  //write how many under zero
399           izero = 0;
400         } //end of reseting izero
401         icurrent++;
402         if (icurrent>=buf.fN) buf.Expand(icurrent*2);
403         buf[icurrent] = GetDigitFast(row,col);      
404       }//if signal bigger then threshold                
405     } //end of loop over rows
406     if (izero>0) {
407       icurrent++;         
408       if (icurrent>=buf.fN) buf.Expand(icurrent*2);
409       buf[icurrent]= -izero;  //write how many under zero
410     }
411   }//end of lopping over digits
412   buf.Expand(icurrent+1);
413   (*fElements)=buf;
414   fNelems = fElements->fN;
415   fBufType = 1;
416   (*fIndex) =index;
417   //end of compresing bufer of type 1 
418 }
419
420
421
422 Bool_t AliDigits::First0()
423 {
424   //
425   //first for the buffer type 0
426   fCurrentRow = -1;
427   fCurrentCol = -1;
428   fCurrentIndex = -1;
429   Int_t i;
430   for (i=0; (( i<fNelems) && (fElements->At(i)<=fThreshold));i++)
431   if (i == fNelems) return kFALSE;
432   fCurrentCol =i/fNrows;
433   fCurrentRow =i%fNrows;
434   fCurrentIndex = i;
435   return kTRUE; 
436 }
437
438 Bool_t AliDigits::Next0()
439 {
440   //
441   //next for the buffer type 0
442   //
443   if (fCurrentIndex<0) return kFALSE;  // if we didn't adjust first 
444   Int_t i;
445   for (i=fCurrentIndex+1; ( (i<fNelems) && (fElements->At(i)<=fThreshold) ) ;i++);
446   if (i >= fNelems)  {
447     fCurrentIndex = -1;
448     return kFALSE;
449   }
450   fCurrentCol =i/fNrows;
451   fCurrentRow =i%fNrows;
452   fCurrentIndex = i;
453   return kTRUE; 
454 }
455
456 Bool_t AliDigits::First1()
457 {
458   //
459   //first for the buffer type 1
460   fCurrentRow = -1;
461   fCurrentCol = 0;
462   fCurrentIndex = -1;
463   Int_t i;
464   for (i=0; i<fNelems; i++){
465     if (fElements->At(i) < 0) fCurrentRow-=fElements->At(i);
466     else      
467       fCurrentRow++;
468     if (fCurrentRow>=fNrows) {
469        fCurrentCol++;
470        fCurrentRow-=fNrows;
471     }
472     if (fElements->At(i)>fThreshold) break;
473   }
474   fCurrentIndex = i;
475   if (fCurrentIndex>=0) return kTRUE;
476   fCurrentRow =-1;
477   fCurrentCol =-1;
478   return kFALSE;        
479 }
480
481 Bool_t AliDigits::Next1()
482 {
483   //
484   //next for the buffer type 1
485   if (fCurrentIndex<0) return kFALSE;  // if we didn't adjust first 
486   Int_t i;
487   for (i=fCurrentIndex+1; i<fNelems;i++){
488     if (fElements->At(i) < 0) fCurrentRow-=fElements->At(i);
489     else      
490       fCurrentRow++;
491     if (fCurrentRow>=fNrows) {
492       fCurrentCol++;
493       fCurrentRow-=fNrows;
494     }
495     if (fElements->At(i)>fThreshold) break;
496   }
497   fCurrentIndex = i;
498   if ( (i>=0) && (i<fNelems) ) return kTRUE;
499   fCurrentRow =-1;
500   fCurrentCol =-1;
501   return kFALSE;
502 }
503
504 Short_t AliDigits::GetDigit1(Int_t row, Int_t column)
505 {
506   //
507   //return digit for given row and column  the buffer type 1
508   //no control performed
509   
510   Int_t i,n2;
511   if ( (column+1)>=fNcols) n2 = fNelems;
512   else
513     n2 = fIndex->At(column+1);
514   Int_t irow = 0; //current row    
515  
516   for (i=fIndex->At(column); ( (i<n2) && (irow<row) );i++){
517     if (fElements->At(i) < 0) irow-=fElements->At(i);
518     else      
519       irow++;
520   }
521   if ( irow == row ) return fElements->At(i);
522   return -1;
523 }
524