Merge from EVE-dev to HEAD.
[u/mrichter/AliRoot.git] / EVE / Alieve / TPCSectorData.cxx
1 // $Header$
2
3 #include "TPCSectorData.h"
4 #include <AliTPCParamSR.h>
5
6 #include <string.h>
7
8 //______________________________________________________________________
9 // TPCSectorData
10 //
11 // Stores data from a fiven TPC sector.
12 //
13 // Row addresses grow linearly by radius, there is no separation on
14 // inner/outer segments. The SegmentInfo objects can be used to get
15 // information about low-level segments.
16 //
17 // A lot of TPC-sector information is stored as static data.
18 //
19 // For accessing data, see for example TPCSector2DGL::CreateTexture()
20 // and LoadPadrow().
21 //
22
23 using namespace Reve;
24 using namespace Alieve;
25
26 ClassImp(TPCSectorData)
27
28 AliTPCParam* TPCSectorData::fgParam    = 0;
29 Int_t        TPCSectorData::fgNAllRows = 0;
30 Int_t        TPCSectorData::fgNAllPads = 0;
31 Int_t*       TPCSectorData::fgRowBegs  = 0;
32
33 TPCSectorData::SegmentInfo TPCSectorData::fgInnSeg;
34 TPCSectorData::SegmentInfo TPCSectorData::fgOut1Seg;
35 TPCSectorData::SegmentInfo TPCSectorData::fgOut2Seg;
36
37 TPCSectorData::SegmentInfo* TPCSectorData::fgSegInfoPtrs[3] = {0};
38
39 /**************************************************************************/
40
41 void TPCSectorData::InitStatics()
42 {
43   if(fgParam != 0) return;
44
45   fgParam    = new AliTPCParamSR;
46   fgNAllRows = fgParam->GetNRowLow() + fgParam->GetNRowUp();
47   fgNAllPads = 0;
48   fgRowBegs  = new Int_t[fgNAllRows + 1];
49
50   Int_t row = 0;
51   for(Int_t i=0; i<fgParam->GetNRowLow(); ++i, ++row) {
52     fgRowBegs[row] = fgNAllPads;
53     fgNAllPads += fgParam->GetNPadsLow(i);
54   }
55   for(Int_t i=0; i<fgParam->GetNRowUp(); ++i, ++row) {
56     fgRowBegs[row] = fgNAllPads;
57     fgNAllPads += fgParam->GetNPadsUp(i);
58   }
59   fgRowBegs[fgNAllRows] = fgNAllPads;
60
61
62   // Fill SegmentInfos, used by rendering classes.
63
64   // General paramameters
65   fgInnSeg.fPadWidth   = fgParam->GetInnerPadPitchWidth();
66   fgInnSeg.fPadHeight  = fgParam->GetInnerPadPitchLength();
67   fgInnSeg.fRLow       = fgParam->GetPadRowRadiiLow(0);
68   fgInnSeg.fNRows      = fgParam->GetNRowLow();
69   fgInnSeg.fFirstRow   = 0;
70   fgInnSeg.fLastRow    = fgInnSeg.fNRows - 1;
71   fgInnSeg.fNMaxPads   = fgParam->GetNPadsLow(fgInnSeg.fNRows - 1);
72   fgSegInfoPtrs[0]     = &fgInnSeg;
73
74   fgOut1Seg.fPadWidth  = fgParam->GetOuterPadPitchWidth();
75   fgOut1Seg.fPadHeight = fgParam->GetOuter1PadPitchLength();
76   fgOut1Seg.fRLow      = fgParam->GetPadRowRadiiUp(0);
77   fgOut1Seg.fNRows     = fgParam->GetNRowUp1();
78   fgOut1Seg.fFirstRow  = fgInnSeg.fNRows;
79   fgOut1Seg.fLastRow   = fgOut1Seg.fFirstRow + fgOut1Seg.fNRows - 1;
80   fgOut1Seg.fNMaxPads  = fgParam->GetNPadsUp(fgOut1Seg.fNRows - 1);
81   fgSegInfoPtrs[1]     = &fgOut1Seg;
82  
83   fgOut2Seg.fPadWidth  = fgParam->GetOuterPadPitchWidth();
84   fgOut2Seg.fPadHeight = fgParam->GetOuter2PadPitchLength();
85   fgOut2Seg.fRLow      = fgParam->GetPadRowRadiiUp(fgOut1Seg.fNRows);
86   fgOut2Seg.fNRows     = fgParam->GetNRowUp() - fgOut1Seg.fNRows;
87   fgOut2Seg.fFirstRow  = fgOut1Seg.fLastRow + 1;
88   fgOut2Seg.fLastRow   = fgOut2Seg.fFirstRow + fgOut2Seg.fNRows - 1;
89   fgOut2Seg.fNMaxPads  = fgParam->GetNPadsUp(fgParam->GetNRowUp() - 1);
90   fgSegInfoPtrs[2]     = &fgOut2Seg;
91
92   // Set stepsize array
93   Int_t k, npads;
94   // Inn
95   k=0, npads = fgParam->GetNPadsLow(0);
96   for (int row = 0; row < fgInnSeg.fNRows; ++row) {
97     if (fgParam->GetNPadsLow(row) > npads) {
98       npads = fgParam->GetNPadsLow(row);
99       fgInnSeg.fYStep[k] = row*fgInnSeg.fPadHeight + fgInnSeg.fRLow;
100       k++;
101     }
102   }
103   fgInnSeg.fNYSteps = k;
104   // Out1 seg 
105   k=0; npads = fgParam->GetNPadsUp(0);
106   for (int row = 0; row < fgOut1Seg.fNRows; ++row) {
107     if (fgParam->GetNPadsUp(row) > npads) {
108       npads = fgParam->GetNPadsUp(row);
109       fgOut1Seg.fYStep[k] = row*fgOut1Seg.fPadHeight + fgOut1Seg.fRLow ;
110       k++;
111     }
112   }
113   fgOut1Seg.fNYSteps = k;
114   // Out2 seg
115   k=0; npads = fgParam->GetNPadsUp(fgOut1Seg.fNRows);
116   for (int row = fgOut1Seg.fNRows; row < fgParam->GetNRowUp() ;row++ ) {
117     if (fgParam->GetNPadsUp(row) > npads) {
118       npads = fgParam->GetNPadsUp(row);
119       fgOut2Seg.fYStep[k] = (row - fgOut1Seg.fNRows)*fgOut2Seg.fPadHeight + fgOut2Seg.fRLow ;
120       k++;
121     }
122   }
123   fgOut2Seg.fNYSteps = k;
124 }
125
126 Int_t TPCSectorData::GetNPadsInRow(Int_t row)
127 {
128   if(row < 0 || row >= fgNAllRows) return 0;
129   return fgRowBegs[row + 1] - fgRowBegs[row];
130 }
131
132 const TPCSectorData::SegmentInfo& TPCSectorData::GetSeg(Int_t seg)
133 {
134   static const SegmentInfo null;
135
136   if(seg < 0 || seg > 2)
137     return null;
138   else
139     return *fgSegInfoPtrs[seg];
140 }
141
142 /**************************************************************************/
143 // True member functions start here.
144 /**************************************************************************/
145
146 void TPCSectorData::NewBlock()
147 {
148   fBlocks.push_back(new Short_t[fBlockSize]);
149   fBlockPos = 0;
150 }
151
152 /**************************************************************************/
153
154 TPCSectorData::TPCSectorData(Int_t sector, Int_t bsize) :
155   fSectorID(sector), fNPadsFilled(0),
156   fBlockSize(bsize), fBlockPos(0),
157   fCurrentRow(0), fCurrentPad(0), fCurrentPos(0)
158 {
159   if(fgParam == 0) InitStatics();
160
161   fPads.assign(fgNAllPads, PadData());
162   fBlocks.reserve(16);
163   fBlockPos = fBlockSize; // Enforce creation of a new block.
164 }
165
166
167 TPCSectorData::~TPCSectorData()
168 {
169   for(std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
170     delete [] *b;
171 }
172
173 void TPCSectorData::DropData()
174 {
175   fPads.assign(fgNAllPads, PadData());
176   for(std::vector<Short_t*>::iterator b=fBlocks.begin(); b!=fBlocks.end(); ++b)
177     delete [] *b;
178   fBlocks.clear();
179   fBlockPos = fBlockSize; // Enforce creation of a new block.
180 }
181
182 /**************************************************************************/
183
184 void TPCSectorData::Print(Option_t* /*opt*/) const
185 {
186   printf("TPCSectorData sector=%d, NPadsFilled=%d, NBlocks=%d, BlockPos=%d\n",
187          fSectorID, fNPadsFilled, fBlocks.size(), fBlockPos);
188 }
189
190 /**************************************************************************/
191
192 void TPCSectorData::BeginPad(Int_t row, Int_t pad, Bool_t reverseTime)
193 {
194   fCurrentRow = row;
195   fCurrentPad = pad;
196   if(reverseTime) {
197     fCurrentPos  = 2046;
198     fCurrentStep = -2;
199   } else {
200     fCurrentPos  = 0;
201     fCurrentStep = 2;
202   }
203   //printf("begpad for row=%d pad=%d\n  buf=%p pos=%d step=%d\n",
204   //     fCurrentRow, fCurrentPad,
205   //     fPadBuffer, fCurrentPos, fCurrentStep);
206 }
207
208 void TPCSectorData::EndPad(Bool_t autoPedestal, Short_t threshold)
209 {
210   Short_t *beg, *end;
211   if(fCurrentStep > 0) {
212     beg = fPadBuffer;
213     end = fPadBuffer + fCurrentPos;
214   } else {
215     beg = fPadBuffer + fCurrentPos + 2;
216     end = fPadBuffer + 2048;
217   }
218
219   //printf("endpad for row=%d pad=%d\n  buf=%p beg=%p end=%p pos=%d step=%d\n",
220   //     fCurrentRow, fCurrentPad,
221   //     fPadBuffer, beg, end, fCurrentPos, fCurrentStep);
222   if(beg >= end)
223     return;
224
225   if(autoPedestal) {
226     Short_t array[1024];
227     Short_t* val;
228     val = beg + 1;    
229     while(val <= end) {
230       array[(val-beg)/2] = *val;
231       val += 2;
232     }    
233     Short_t pedestal = TMath::Nint(TMath::Median((end-beg)/2, array));
234     val = beg + 1;
235     while(val <= end) {
236       *val -= pedestal;
237       val += 2;
238     }
239     Short_t* wpos = beg;
240     Short_t* rpos = beg;
241     while(rpos < end) {
242       if(rpos[1] > threshold) {
243         wpos[0] = rpos[0];
244         wpos[1] = rpos[1];
245         wpos += 2;
246       }
247       rpos += 2;
248     }
249     end = wpos;
250   }
251
252   Short_t* wpos = beg;
253   Short_t* rpos = beg;
254
255   // Compress pad buffer
256   while(rpos < end) {
257     Short_t* spos = rpos;
258     Short_t  t    = spos[0];
259     while(true) {
260       rpos += 2;
261       if(rpos >= end || *rpos > t + 1 || t == 0)
262         break;
263       ++t;
264     }
265     Short_t n = t - spos[0] + 1;
266     if(n == 1) {
267       wpos[0] = -spos[0];
268       wpos[1] =  spos[1];
269       wpos += 2;
270     } else {
271       wpos[0] = spos[0];
272       wpos[2] = spos[1];
273       wpos[1] = n;
274       wpos += 3; spos += 3;
275       while(--n) {
276         *wpos = *spos;
277         ++wpos; spos += 2;
278       }
279     }
280   }
281
282   // Copy buffer to storage, set PadData
283   if(wpos > beg) {
284     Short_t len = wpos - beg;
285     if(len > fBlockSize - fBlockPos)
286       NewBlock();
287     Short_t *dest = fBlocks.back() + fBlockPos;
288     memcpy(dest, beg, len*sizeof(Short_t));
289     fBlockPos += len;
290
291     PadData& pad = fPads[PadIndex(fCurrentRow, fCurrentPad)];
292     pad.SetDataLength(dest, len);
293   }
294
295   ++fNPadsFilled;
296 }
297
298 /**************************************************************************/
299
300 const TPCSectorData::PadData& TPCSectorData::GetPadData(Int_t padAddr)
301 {
302   static const PadData null;
303
304   if(padAddr < 0 || padAddr >= fgNAllPads) return null;
305   return fPads[padAddr];
306 }
307
308 const TPCSectorData::PadData& TPCSectorData::GetPadData(Int_t row, Int_t pad)
309 {
310   static const PadData null;
311
312   Int_t np = GetNPadsInRow(row);
313   if(np == 0 || pad < 0 || pad >= np) return null;
314   return GetPadData(fgRowBegs[row] + pad);
315 }
316
317 TPCSectorData::PadIterator TPCSectorData::MakePadIterator(Int_t padAddr, Short_t thr)
318 {
319   return PadIterator(GetPadData(padAddr), thr);
320 }
321
322 TPCSectorData::PadIterator TPCSectorData::MakePadIterator(Int_t row, Int_t pad, Short_t thr)
323 {
324   return PadIterator(GetPadData(row, pad), thr);
325 }
326
327 TPCSectorData::RowIterator TPCSectorData::MakeRowIterator(Int_t row, Short_t thr)
328 {
329   Short_t npads = GetNPadsInRow(row);
330   if(npads > 0)
331     return RowIterator(&fPads[fgRowBegs[row]], npads, thr);
332   else
333     return RowIterator(0, 0);
334 }
335
336 /**************************************************************************/
337 // TPCSectorData::PadData
338 /**************************************************************************/
339
340 void TPCSectorData::PadData::Print(Option_t* /*opt*/)
341 {
342   printf("addr=%p, len=%hd>\n", (void*)fData, fLength);
343   for(Int_t i=0; i<fLength; ++i)
344     printf("  %3d %hd\n", i, fData[i]);
345 }
346
347 /**************************************************************************/
348 // TPCSectorData::PadIterator
349 /**************************************************************************/
350
351 Bool_t TPCSectorData::PadIterator::Next()
352 {
353   if(fPos >= fEnd) return kFALSE;
354   if(fNChunk > 0) {
355     ++fTime;
356     --fNChunk;
357     fSignal = *fPos; ++fPos;
358   } else {
359     fTime = fPos[0];
360     if(fTime <= 0) {
361       fTime   = -fTime;
362       fSignal = fPos[1];
363       fPos += 2;
364     } else {
365       fNChunk = fPos[1] - 1;
366       fSignal = fPos[2];
367       fPos += 3;
368     }
369   }
370   return (fSignal > fThreshold) ? kTRUE : Next();
371 }
372
373 void TPCSectorData::PadIterator::Reset()
374 {
375   // Return to the beginning of the pad-data. Must call Next() to get to
376   // the first stored signal.
377
378   fPos    = fBeg;
379   fTime   = -1;
380   fSignal = -1;
381   fNChunk = 0;
382 }
383
384 void TPCSectorData::PadIterator::Reset(const PadData& pd)
385 {
386   // Reinitialize to new pad-data. Must call Next() to get to the
387   // first stored signal.
388
389   fBeg = pd.Data();
390   fEnd = pd.Data() + pd.Length();
391   fPos = pd.Data();
392   Reset();
393 }
394
395 void TPCSectorData::PadIterator::Test()
396 {
397   while(Next())
398     printf("  %3d %d\n", fTime, fSignal);
399 }
400
401 /**************************************************************************/
402 // TPCSectorData::RowIterator
403 /**************************************************************************/
404
405 Bool_t TPCSectorData::RowIterator::NextPad()
406 {
407   ++fPad;
408   if(fPad >= fNPads) return kFALSE;
409   Reset(fPadArray[fPad]);
410   return kTRUE;
411 }
412
413 void TPCSectorData::RowIterator::ResetRow()
414 {
415   // Return to the beginning of the row. Must call NextPad() to get to
416   // the zeroth pad.
417
418   fPad = -1;
419 }
420
421 void TPCSectorData::RowIterator::ResetRow(const PadData* first, Short_t npads)
422 {
423   // Reinitialize to another pad-data array. Must call NextPad() to
424   // get to the zeroth pad.
425
426   fPadArray =  first;
427   fNPads    =  npads;
428   fPad      = -1;
429 }
430
431 void TPCSectorData::RowIterator::Test()
432 {
433   while(NextPad()) {
434     printf("Pad %d\n", fPad);
435     PadIterator::Test();
436   }
437 }
438
439 /**************************************************************************/
440 // TPCSectorData::SegmentInfo
441 /**************************************************************************/
442
443 ClassImp(TPCSectorData::SegmentInfo)
444
445 TPCSectorData::SegmentInfo::SegmentInfo()
446 {
447   memset(this, sizeof(SegmentInfo), 0);
448 }