771932cbc9517f3c4e3027a858c77fe59135bf7e
[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   if (fgParam == 0) InitStatics();
195
196   fPads.assign(fgNAllPads, PadData());
197   fBlocks.reserve(16);
198   fBlockPos = fkBlockSize; // Enforce creation of a new block.
199 }
200
201
202 AliEveTPCSectorData::~AliEveTPCSectorData()
203 {
204   // Destructor.
205
206   for (std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
207     delete [] *b;
208 }
209
210 void AliEveTPCSectorData::DropData()
211 {
212   // Drop data, deallocate data-blocks.
213
214   fPads.assign(fgNAllPads, PadData());
215   for (std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
216     delete [] *b;
217   fBlocks.clear();
218   fBlockPos = fkBlockSize; // Enforce creation of a new block.
219 }
220
221 /******************************************************************************/
222
223 void AliEveTPCSectorData::Print(Option_t* /*opt*/) const
224 {
225   // Print summary information.
226
227   printf("AliEveTPCSectorData sector=%d, NPadsFilled=%d, NBlocks=%d, BlockPos=%d\n",
228          fSectorID, fNPadsFilled, (Int_t) fBlocks.size(), fBlockPos);
229 }
230
231 /******************************************************************************/
232
233 void AliEveTPCSectorData::BeginPad(Int_t row, Int_t pad, Bool_t reverseTime)
234 {
235   // Begin filling of pad-data as specified with arguments.
236
237   fCurrentRow = row;
238   fCurrentPad = pad;
239   if (reverseTime) {
240     fCurrentPos  = 2046;
241     fCurrentStep = -2;
242   } else {
243     fCurrentPos  = 0;
244     fCurrentStep = 2;
245   }
246   //printf("begpad for row=%d pad=%d\n  buf=%p pos=%d step=%d\n",
247   //     fCurrentRow, fCurrentPad,
248   //     fPadBuffer, fCurrentPos, fCurrentStep);
249 }
250
251 void AliEveTPCSectorData::EndPad(Bool_t autoPedestal, Short_t threshold)
252 {
253   // End filling of pad-data. At this point data is compressed and moved
254   // into the cuurent position in memory block.
255
256   Short_t *beg, *end;
257   if (fCurrentStep > 0) {
258     beg = fPadBuffer;
259     end = fPadBuffer + fCurrentPos;
260   } else {
261     beg = fPadBuffer + fCurrentPos + 2;
262     end = fPadBuffer + 2048;
263   }
264
265   //printf("endpad for row=%d pad=%d\n  buf=%p beg=%p end=%p pos=%d step=%d\n",
266   //     fCurrentRow, fCurrentPad,
267   //     fPadBuffer, beg, end, fCurrentPos, fCurrentStep);
268   if (beg >= end)
269     return;
270
271   if (autoPedestal) {
272     Short_t array[1024];
273     Short_t* val;
274     val = beg + 1;
275     while (val <= end) {
276       array[(val-beg)/2] = *val;
277       val += 2;
278     }
279     Short_t pedestal = TMath::Nint(TMath::Median((end-beg)/2, array));
280     val = beg + 1;
281     while (val <= end) {
282       *val -= pedestal;
283       val += 2;
284     }
285     Short_t* wpos = beg;
286     Short_t* rpos = beg;
287     while (rpos < end) {
288       if (rpos[1] >= threshold) {
289         wpos[0] = rpos[0];
290         wpos[1] = rpos[1];
291         wpos += 2;
292       }
293       rpos += 2;
294     }
295     end = wpos;
296   }
297
298   Short_t* wpos = beg;
299   Short_t* rpos = beg;
300
301   // Compress pad buffer
302   while (rpos < end) {
303     Short_t* spos = rpos;
304     Short_t  t    = spos[0];
305     while (true) {
306       rpos += 2;
307       if (rpos >= end || *rpos > t + 1 || t == 0)
308         break;
309       ++t;
310     }
311     Short_t n = t - spos[0] + 1;
312     if (n == 1) {
313       wpos[0] = -spos[0];
314       wpos[1] =  spos[1];
315       wpos += 2;
316     } else {
317       wpos[0] = spos[0];
318       wpos[2] = spos[1];
319       wpos[1] = n;
320       wpos += 3; spos += 3;
321       while (--n) {
322         *wpos = *spos;
323         ++wpos; spos += 2;
324       }
325     }
326   }
327
328   // Copy buffer to storage, set PadData
329   if (wpos > beg) {
330     Short_t len = wpos - beg;
331     if (len > fkBlockSize - fBlockPos)
332       NewBlock();
333     Short_t *dest = fBlocks.back() + fBlockPos;
334     memcpy(dest, beg, len*sizeof(Short_t));
335     fBlockPos += len;
336
337     PadData& pad = fPads[PadIndex(fCurrentRow, fCurrentPad)];
338     pad.SetDataLength(dest, len);
339   }
340
341   ++fNPadsFilled;
342 }
343
344 /******************************************************************************/
345
346 const AliEveTPCSectorData::PadData& AliEveTPCSectorData::GetPadData(Int_t padAddr) const
347 {
348   // Get pad-data reference by absolute index.
349
350   static const PadData kNull;
351
352   if (padAddr < 0 || padAddr >= fgNAllPads) return kNull;
353   return fPads[padAddr];
354 }
355
356 const AliEveTPCSectorData::PadData& AliEveTPCSectorData::GetPadData(Int_t row, Int_t pad) const
357 {
358   // Get pad-data reference by row and pad number.
359
360   static const PadData kNull;
361
362   Int_t np = GetNPadsInRow(row);
363   if (np == 0 || pad < 0 || pad >= np) return kNull;
364   return GetPadData(fgRowBegs[row] + pad);
365 }
366
367 AliEveTPCSectorData::PadIterator AliEveTPCSectorData::MakePadIterator(Int_t padAddr, Short_t thr)
368 {
369   // Get pad-data iterator by absolute index.
370
371   return PadIterator(GetPadData(padAddr), thr);
372 }
373
374 AliEveTPCSectorData::PadIterator AliEveTPCSectorData::MakePadIterator(Int_t row, Int_t pad, Short_t thr)
375 {
376   // Get pad-data iterator by row and pad number.
377
378   return PadIterator(GetPadData(row, pad), thr);
379 }
380
381 AliEveTPCSectorData::RowIterator AliEveTPCSectorData::MakeRowIterator(Int_t row, Short_t thr)
382 {
383   // Get row iterator.
384
385   Short_t npads = GetNPadsInRow(row);
386   if (npads > 0)
387     return RowIterator(&fPads[fgRowBegs[row]], npads, thr);
388   else
389     return RowIterator(0, 0);
390 }
391
392 /******************************************************************************/
393 // AliEveTPCSectorData::PadData
394 /******************************************************************************/
395
396 void AliEveTPCSectorData::PadData::Print(Option_t* /*opt*/)
397 {
398   // Print summary information.
399
400   printf("addr=%p, len=%hd>\n", (void*)fData, fLength);
401   for (Int_t i=0; i<fLength; ++i)
402     printf("  %3d %hd\n", i, fData[i]);
403 }
404
405 /******************************************************************************/
406 // AliEveTPCSectorData::PadIterator
407 /******************************************************************************/
408
409 Bool_t AliEveTPCSectorData::PadIterator::Next()
410 {
411   // Move iterator to next signal above the iteration threshold.
412   // Returns false when the end of data is reached.
413
414   if (fPos >= fEnd) return kFALSE;
415   if (fNChunk > 0) {
416     ++fTime;
417     --fNChunk;
418     fSignal = *fPos; ++fPos;
419   } else {
420     fTime = fPos[0];
421     if (fTime <= 0) {
422       fTime   = -fTime;
423       fSignal = fPos[1];
424       fPos += 2;
425     } else {
426       fNChunk = fPos[1] - 1;
427       fSignal = fPos[2];
428       fPos += 3;
429     }
430   }
431   return (fSignal > fThreshold) ? kTRUE : Next();
432 }
433
434 void AliEveTPCSectorData::PadIterator::Reset()
435 {
436   // Return to the beginning of the pad-data. Must call Next() to get to
437   // the first stored signal.
438
439   fPos    = fBeg;
440   fTime   = -1;
441   fSignal = -1;
442   fNChunk = 0;
443 }
444
445 void AliEveTPCSectorData::PadIterator::Reset(const PadData& pd)
446 {
447   // Reinitialize to new pad-data. Must call Next() to get to the
448   // first stored signal.
449
450   fBeg = pd.Data();
451   fEnd = pd.Data() + pd.Length();
452   fPos = pd.Data();
453   Reset();
454 }
455
456 void AliEveTPCSectorData::PadIterator::Test()
457 {
458   while (Next())
459     printf("  %3d %d\n", fTime, fSignal);
460 }
461
462 /******************************************************************************/
463 // AliEveTPCSectorData::RowIterator
464 /******************************************************************************/
465
466 Bool_t AliEveTPCSectorData::RowIterator::NextPad()
467 {
468   // Move iterator to next pad.
469
470   ++fPad;
471   if(fPad >= fNPads) return kFALSE;
472   Reset(fPadArray[fPad]);
473   return kTRUE;
474 }
475
476 void AliEveTPCSectorData::RowIterator::ResetRow()
477 {
478   // Return to the beginning of the row. Must call NextPad() to get to
479   // the zeroth pad.
480
481   fPad = -1;
482 }
483
484 void AliEveTPCSectorData::RowIterator::ResetRow(const PadData* first, Short_t npads)
485 {
486   // Reinitialize to another pad-data array. Must call NextPad() to
487   // get to the zeroth pad.
488
489   fPadArray =  first;
490   fNPads    =  npads;
491   fPad      = -1;
492 }
493
494 /******************************************************************************/
495 // AliEveTPCSectorData::SegmentInfo
496 /******************************************************************************/
497
498 //______________________________________________________________________________
499 //
500 // Stores geometry data about a segment needed for fast data-access
501 // and rendering
502
503 ClassImp(AliEveTPCSectorData::SegmentInfo)
504
505 AliEveTPCSectorData::SegmentInfo::SegmentInfo() :
506   TObject(),
507
508   fPadWidth(0), fPadHeight(0),
509   fRLow(0), fNRows(0), fFirstRow(0), fLastRow(0),
510   fNMaxPads(0),
511   fNYSteps(0)
512 {
513   // Constructor.
514
515   memset(fYStep, 0, sizeof(fYStep));
516 }