Coverity 15169
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveTPCSectorData.cxx
1 // $Id$
2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3
4 /**************************************************************************
5  * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
6  * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
7  * full copyright notice.                                                 *
8  **************************************************************************/
9
10 #include "AliEveTPCSectorData.h"
11 #include <AliTPCParamSR.h>
12
13 #include <set>
14
15 //==============================================================================
16 //==============================================================================
17 // AliEveTPCSectorData
18 //==============================================================================
19
20 //______________________________________________________________________________
21 //
22 // Stores data from a fiven TPC sector.
23 //
24 // Row addresses grow linearly by radius, there is no separation on
25 // inner/outer segments. The SegmentInfo objects can be used to get
26 // information about low-level segments.
27 //
28 // A lot of TPC-sector geometry information is stored as static data.
29 //
30 // For accessing data, see for example AliEveTPCSector2DGL::CreateTexture()
31 // and LoadPadrow().
32 //
33
34 ClassImp(AliEveTPCSectorData)
35
36 AliTPCParam* AliEveTPCSectorData::fgParam    = 0;
37 Float_t      AliEveTPCSectorData::fgZLength  = 0;
38 Int_t        AliEveTPCSectorData::fgNAllRows = 0;
39 Int_t        AliEveTPCSectorData::fgNAllPads = 0;
40 Int_t*       AliEveTPCSectorData::fgRowBegs  = 0;
41
42 AliEveTPCSectorData::SegmentInfo AliEveTPCSectorData::fgInnSeg;
43 AliEveTPCSectorData::SegmentInfo AliEveTPCSectorData::fgOut1Seg;
44 AliEveTPCSectorData::SegmentInfo AliEveTPCSectorData::fgOut2Seg;
45
46 AliEveTPCSectorData::SegmentInfo* AliEveTPCSectorData::fgSegInfoPtrs[3] = {0};
47
48 /******************************************************************************/
49
50 void AliEveTPCSectorData::InitStatics()
51 {
52   // Initialize static variables.
53
54   if (fgParam != 0) return;
55
56   fgParam    = new AliTPCParamSR;
57   fgZLength  = fgParam->GetZLength(0) + 0.275;
58   fgNAllRows = fgParam->GetNRowLow()  + fgParam->GetNRowUp();
59   fgNAllPads = 0;
60   fgRowBegs  = new Int_t[fgNAllRows + 1];
61
62   {
63     Int_t row = 0;
64     for (Int_t i=0; i<fgParam->GetNRowLow(); ++i, ++row)
65     {
66       fgRowBegs[row] = fgNAllPads;
67       fgNAllPads += fgParam->GetNPadsLow(i);
68     }
69     for (Int_t i=0; i<fgParam->GetNRowUp(); ++i, ++row)
70     {
71       fgRowBegs[row] = fgNAllPads;
72       fgNAllPads += fgParam->GetNPadsUp(i);
73     }
74     fgRowBegs[fgNAllRows] = fgNAllPads;
75   }
76
77   // Fill SegmentInfos, used by rendering classes.
78
79   // General paramameters
80   fgInnSeg.fPadWidth   = fgParam->GetInnerPadPitchWidth();
81   fgInnSeg.fPadHeight  = fgParam->GetInnerPadPitchLength();
82   fgInnSeg.fRLow       = fgParam->GetPadRowRadiiLow(0);
83   fgInnSeg.fNRows      = fgParam->GetNRowLow();
84   fgInnSeg.fFirstRow   = 0;
85   fgInnSeg.fLastRow    = fgInnSeg.fNRows - 1;
86   fgInnSeg.fNMaxPads   = fgParam->GetNPadsLow(fgInnSeg.fNRows - 1);
87   fgSegInfoPtrs[0]     = &fgInnSeg;
88
89   fgOut1Seg.fPadWidth  = fgParam->GetOuterPadPitchWidth();
90   fgOut1Seg.fPadHeight = fgParam->GetOuter1PadPitchLength();
91   fgOut1Seg.fRLow      = fgParam->GetPadRowRadiiUp(0);
92   fgOut1Seg.fNRows     = fgParam->GetNRowUp1();
93   fgOut1Seg.fFirstRow  = fgInnSeg.fNRows;
94   fgOut1Seg.fLastRow   = fgOut1Seg.fFirstRow + fgOut1Seg.fNRows - 1;
95   fgOut1Seg.fNMaxPads  = fgParam->GetNPadsUp(fgOut1Seg.fNRows - 1);
96   fgSegInfoPtrs[1]     = &fgOut1Seg;
97
98   fgOut2Seg.fPadWidth  = fgParam->GetOuterPadPitchWidth();
99   fgOut2Seg.fPadHeight = fgParam->GetOuter2PadPitchLength();
100   fgOut2Seg.fRLow      = fgParam->GetPadRowRadiiUp(fgOut1Seg.fNRows);
101   fgOut2Seg.fNRows     = fgParam->GetNRowUp() - fgOut1Seg.fNRows;
102   fgOut2Seg.fFirstRow  = fgOut1Seg.fLastRow + 1;
103   fgOut2Seg.fLastRow   = fgOut2Seg.fFirstRow + fgOut2Seg.fNRows - 1;
104   fgOut2Seg.fNMaxPads  = fgParam->GetNPadsUp(fgParam->GetNRowUp() - 1);
105   fgSegInfoPtrs[2]     = &fgOut2Seg;
106
107   // Set stepsize arrays
108
109   { // Inner
110     Int_t k=0, npads = fgParam->GetNPadsLow(0);
111     for (Int_t row = 0; row < fgInnSeg.fNRows; ++row)
112     {
113       if (fgParam->GetNPadsLow(row) > npads)
114       {
115         npads = fgParam->GetNPadsLow(row);
116         fgInnSeg.fYStep[k] = row*fgInnSeg.fPadHeight + fgInnSeg.fRLow;
117         k++;
118       }
119     }
120     fgInnSeg.fNYSteps = k;
121   }
122
123   {  // Outer 1 seg
124     Int_t k=0, npads = fgParam->GetNPadsUp(0);
125     for (Int_t row = 0; row < fgOut1Seg.fNRows; ++row)
126     {
127       if (fgParam->GetNPadsUp(row) > npads)
128       {
129         npads = fgParam->GetNPadsUp(row);
130         fgOut1Seg.fYStep[k] = row*fgOut1Seg.fPadHeight + fgOut1Seg.fRLow ;
131         k++;
132       }
133     }
134     fgOut1Seg.fNYSteps = k;
135   }
136
137   {  // Outer 2 seg
138     Int_t k=0, npads = fgParam->GetNPadsUp(fgOut1Seg.fNRows);
139     for (Int_t row = fgOut1Seg.fNRows; row < fgParam->GetNRowUp(); ++row)
140     {
141       if (fgParam->GetNPadsUp(row) > npads)
142       {
143         npads = fgParam->GetNPadsUp(row);
144         fgOut2Seg.fYStep[k] = (row - fgOut1Seg.fNRows)*fgOut2Seg.fPadHeight + fgOut2Seg.fRLow ;
145         k++;
146       }
147     }
148     fgOut2Seg.fNYSteps = k;
149   }
150 }
151
152 Int_t AliEveTPCSectorData::GetNPadsInRow(Int_t row)
153 {
154   // Return number of pads in given row.
155
156   if (row < 0 || row >= fgNAllRows) return 0;
157   return fgRowBegs[row + 1] - fgRowBegs[row];
158 }
159
160 const AliEveTPCSectorData::SegmentInfo& AliEveTPCSectorData::GetSeg(Int_t seg)
161 {
162   // Return reference to segment geometry information.
163   // 0 ~ inner, 1 ~ middle, 2 ~ outer.
164
165   static const SegmentInfo null;
166
167   if (seg < 0 || seg > 2)
168     return null;
169   else
170     return *fgSegInfoPtrs[seg];
171 }
172
173 /******************************************************************************/
174 // True member functions start here.
175 /******************************************************************************/
176
177 void AliEveTPCSectorData::NewBlock()
178 {
179   // Create new data-block. Position is set to the beginning.
180
181   fBlocks.push_back(new Short_t[fkBlockSize]);
182   fBlockPos = 0;
183 }
184
185 /******************************************************************************/
186
187 AliEveTPCSectorData::AliEveTPCSectorData(Int_t sector, Int_t bsize) :
188   fSectorID(sector),  fNPadsFilled(0), fPads(),
189   fkBlockSize(bsize), fBlockPos(0),    fBlocks(),
190   fCurrentRow(0), fCurrentPad(0), fCurrentPos(0), fCurrentStep(0)
191 {
192   // Constructor.
193         
194   memset(fPadBuffer,0,2048*sizeof(Short_t));
195
196   if (fgParam == 0) InitStatics();
197
198   fPads.assign(fgNAllPads, PadData());
199   fBlocks.reserve(16);
200   fBlockPos = fkBlockSize; // Enforce creation of a new block.
201 }
202
203
204 AliEveTPCSectorData::~AliEveTPCSectorData()
205 {
206   // Destructor.
207
208   for (std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
209     delete [] *b;
210 }
211
212 void AliEveTPCSectorData::DropData()
213 {
214   // Drop data, deallocate data-blocks.
215
216   fPads.assign(fgNAllPads, PadData());
217   for (std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
218     delete [] *b;
219   fBlocks.clear();
220   fBlockPos = fkBlockSize; // Enforce creation of a new block.
221 }
222
223 /******************************************************************************/
224
225 void AliEveTPCSectorData::Print(Option_t* /*opt*/) const
226 {
227   // Print summary information.
228
229   printf("AliEveTPCSectorData sector=%d, NPadsFilled=%d, NBlocks=%d, BlockPos=%d\n",
230          fSectorID, fNPadsFilled, (Int_t) fBlocks.size(), fBlockPos);
231 }
232
233 /******************************************************************************/
234
235 void AliEveTPCSectorData::BeginPad(Int_t row, Int_t pad, Bool_t reverseTime)
236 {
237   // Begin filling of pad-data as specified with arguments.
238
239   fCurrentRow = row;
240   fCurrentPad = pad;
241   if (reverseTime) {
242     fCurrentPos  = 2046;
243     fCurrentStep = -2;
244   } else {
245     fCurrentPos  = 0;
246     fCurrentStep = 2;
247   }
248   //printf("begpad for row=%d pad=%d\n  buf=%p pos=%d step=%d\n",
249   //     fCurrentRow, fCurrentPad,
250   //     fPadBuffer, fCurrentPos, fCurrentStep);
251 }
252
253 void AliEveTPCSectorData::EndPad(Bool_t autoPedestal, Short_t threshold)
254 {
255   // End filling of pad-data. At this point data is compressed and moved
256   // into the cuurent position in memory block.
257
258   Short_t *beg, *end;
259   if (fCurrentStep > 0) {
260     beg = fPadBuffer;
261     end = fPadBuffer + fCurrentPos;
262   } else {
263     beg = fPadBuffer + fCurrentPos + 2;
264     end = fPadBuffer + 2048;
265   }
266
267   //printf("endpad for row=%d pad=%d\n  buf=%p beg=%p end=%p pos=%d step=%d\n",
268   //     fCurrentRow, fCurrentPad,
269   //     fPadBuffer, beg, end, fCurrentPos, fCurrentStep);
270   if (beg >= end)
271     return;
272
273   if (autoPedestal) {
274     Short_t array[1024];
275     Short_t* val;
276     val = beg + 1;
277     while (val <= end) {
278       array[(val-beg)/2] = *val;
279       val += 2;
280     }
281     Short_t pedestal = TMath::Nint(TMath::Median((end-beg)/2, array));
282     val = beg + 1;
283     while (val <= end) {
284       *val -= pedestal;
285       val += 2;
286     }
287     Short_t* wpos = beg;
288     Short_t* rpos = beg;
289     while (rpos < end) {
290       if (rpos[1] >= threshold) {
291         wpos[0] = rpos[0];
292         wpos[1] = rpos[1];
293         wpos += 2;
294       }
295       rpos += 2;
296     }
297     end = wpos;
298   }
299
300   Short_t* wpos = beg;
301   Short_t* rpos = beg;
302
303   // Compress pad buffer
304   while (rpos < end) {
305     Short_t* spos = rpos;
306     Short_t  t    = spos[0];
307     while (true) {
308       rpos += 2;
309       if (rpos >= end || *rpos > t + 1 || t == 0)
310         break;
311       ++t;
312     }
313     Short_t n = t - spos[0] + 1;
314     if (n == 1) {
315       wpos[0] = -spos[0];
316       wpos[1] =  spos[1];
317       wpos += 2;
318     } else {
319       wpos[0] = spos[0];
320       wpos[2] = spos[1];
321       wpos[1] = n;
322       wpos += 3; spos += 3;
323       while (--n) {
324         *wpos = *spos;
325         ++wpos; spos += 2;
326       }
327     }
328   }
329
330   // Copy buffer to storage, set PadData
331   if (wpos > beg) {
332     Short_t len = wpos - beg;
333     if (len > fkBlockSize - fBlockPos)
334       NewBlock();
335     Short_t *dest = fBlocks.back() + fBlockPos;
336     memcpy(dest, beg, len*sizeof(Short_t));
337     fBlockPos += len;
338
339     PadData& pad = fPads[PadIndex(fCurrentRow, fCurrentPad)];
340     pad.SetDataLength(dest, len);
341   }
342
343   ++fNPadsFilled;
344 }
345
346 /******************************************************************************/
347
348 const AliEveTPCSectorData::PadData& AliEveTPCSectorData::GetPadData(Int_t padAddr) const
349 {
350   // Get pad-data reference by absolute index.
351
352   static const PadData kNull;
353
354   if (padAddr < 0 || padAddr >= fgNAllPads) return kNull;
355   return fPads[padAddr];
356 }
357
358 const AliEveTPCSectorData::PadData& AliEveTPCSectorData::GetPadData(Int_t row, Int_t pad) const
359 {
360   // Get pad-data reference by row and pad number.
361
362   static const PadData kNull;
363
364   Int_t np = GetNPadsInRow(row);
365   if (np == 0 || pad < 0 || pad >= np) return kNull;
366   return GetPadData(fgRowBegs[row] + pad);
367 }
368
369 AliEveTPCSectorData::PadIterator AliEveTPCSectorData::MakePadIterator(Int_t padAddr, Short_t thr)
370 {
371   // Get pad-data iterator by absolute index.
372
373   return PadIterator(GetPadData(padAddr), thr);
374 }
375
376 AliEveTPCSectorData::PadIterator AliEveTPCSectorData::MakePadIterator(Int_t row, Int_t pad, Short_t thr)
377 {
378   // Get pad-data iterator by row and pad number.
379
380   return PadIterator(GetPadData(row, pad), thr);
381 }
382
383 AliEveTPCSectorData::RowIterator AliEveTPCSectorData::MakeRowIterator(Int_t row, Short_t thr)
384 {
385   // Get row iterator.
386
387   Short_t npads = GetNPadsInRow(row);
388   if (npads > 0)
389     return RowIterator(&fPads[fgRowBegs[row]], npads, thr);
390   else
391     return RowIterator(0, 0);
392 }
393
394 /******************************************************************************/
395 // AliEveTPCSectorData::PadData
396 /******************************************************************************/
397
398 void AliEveTPCSectorData::PadData::Print(Option_t* /*opt*/)
399 {
400   // Print summary information.
401
402   printf("addr=%p, len=%hd>\n", (void*)fData, fLength);
403   for (Int_t i=0; i<fLength; ++i)
404     printf("  %3d %hd\n", i, fData[i]);
405 }
406
407 /******************************************************************************/
408 // AliEveTPCSectorData::PadIterator
409 /******************************************************************************/
410
411 Bool_t AliEveTPCSectorData::PadIterator::Next()
412 {
413   // Move iterator to next signal above the iteration threshold.
414   // Returns false when the end of data is reached.
415
416   if (fPos >= fEnd) return kFALSE;
417   if (fNChunk > 0) {
418     ++fTime;
419     --fNChunk;
420     fSignal = *fPos; ++fPos;
421   } else {
422     fTime = fPos[0];
423     if (fTime <= 0) {
424       fTime   = -fTime;
425       fSignal = fPos[1];
426       fPos += 2;
427     } else {
428       fNChunk = fPos[1] - 1;
429       fSignal = fPos[2];
430       fPos += 3;
431     }
432   }
433   return (fSignal > fThreshold) ? kTRUE : Next();
434 }
435
436 void AliEveTPCSectorData::PadIterator::Reset()
437 {
438   // Return to the beginning of the pad-data. Must call Next() to get to
439   // the first stored signal.
440
441   fPos    = fBeg;
442   fTime   = -1;
443   fSignal = -1;
444   fNChunk = 0;
445 }
446
447 void AliEveTPCSectorData::PadIterator::Reset(const PadData& pd)
448 {
449   // Reinitialize to new pad-data. Must call Next() to get to the
450   // first stored signal.
451
452   fBeg = pd.Data();
453   fEnd = pd.Data() + pd.Length();
454   fPos = pd.Data();
455   Reset();
456 }
457
458 void AliEveTPCSectorData::PadIterator::Test()
459 {
460   while (Next())
461     printf("  %3d %d\n", fTime, fSignal);
462 }
463
464 /******************************************************************************/
465 // AliEveTPCSectorData::RowIterator
466 /******************************************************************************/
467
468 Bool_t AliEveTPCSectorData::RowIterator::NextPad()
469 {
470   // Move iterator to next pad.
471
472   ++fPad;
473   if(fPad >= fNPads) return kFALSE;
474   Reset(fPadArray[fPad]);
475   return kTRUE;
476 }
477
478 void AliEveTPCSectorData::RowIterator::ResetRow()
479 {
480   // Return to the beginning of the row. Must call NextPad() to get to
481   // the zeroth pad.
482
483   fPad = -1;
484 }
485
486 void AliEveTPCSectorData::RowIterator::ResetRow(const PadData* first, Short_t npads)
487 {
488   // Reinitialize to another pad-data array. Must call NextPad() to
489   // get to the zeroth pad.
490
491   fPadArray =  first;
492   fNPads    =  npads;
493   fPad      = -1;
494 }
495
496 /******************************************************************************/
497 // AliEveTPCSectorData::SegmentInfo
498 /******************************************************************************/
499
500 //______________________________________________________________________________
501 //
502 // Stores geometry data about a segment needed for fast data-access
503 // and rendering
504
505 ClassImp(AliEveTPCSectorData::SegmentInfo)
506
507 AliEveTPCSectorData::SegmentInfo::SegmentInfo() :
508   TObject(),
509
510   fPadWidth(0), fPadHeight(0),
511   fRLow(0), fNRows(0), fFirstRow(0), fLastRow(0),
512   fNMaxPads(0),
513   fNYSteps(0)
514 {
515   // Constructor.
516
517   memset(fYStep, 0, sizeof(fYStep));
518 }