]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/comp/AliHLTTPCDataCompressionDecoder.h
implementing backward compatible reading for compressed clusters recorded with v5...
[u/mrichter/AliRoot.git] / HLT / TPCLib / comp / AliHLTTPCDataCompressionDecoder.h
1 //-*- Mode: C++ -*-
2 // $Id$
3 #ifndef ALIHLTTPCDATACOMPRESSIONDECODER_H
4 #define ALIHLTTPCDATACOMPRESSIONDECODER_H
5 //* This file is property of and copyright by the ALICE HLT Project        * 
6 //* ALICE Experiment at CERN, All rights reserved.                         *
7 //* See cxx source for full Copyright notice                               *
8
9 /// @file   AliHLTTPCDataCompressionDecoder.h
10 /// @author Matthias Richter
11 /// @date   2011-10-04
12 /// @brief  Generic decoder class for compressed TPC data, works on a container
13 ///         class implementation which fills the actual target data struct
14
15 #include "AliHLTLogging.h"
16 #include "AliHLTMisc.h"
17 #include "AliHLTTPCDataCompressionComponent.h"
18 #include "AliHLTTPCDefinitions.h"
19 #include "AliHLTTPCClusterDataFormat.h"
20 #include "AliHLTTPCRawCluster.h"
21 #include "AliHLTTPCTransform.h"
22 #include "AliHLTTPCTrackGeometry.h"
23 #include "AliHLTDataInflater.h"
24
25 /**
26  * @class AliHLTTPCDataCompressionDecoder
27  * Generic decoder class for compressed TPC data, works on a container
28  * class implementation which fills the actual target data struct
29  */
30 class AliHLTTPCDataCompressionDecoder : public AliHLTLogging {
31  public:
32   AliHLTTPCDataCompressionDecoder();
33   ~AliHLTTPCDataCompressionDecoder();
34
35   template<typename T>
36   int ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
37
38   template<typename T>
39   int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion=0);
40
41   template<typename T>
42   int ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
43
44   template<typename T>
45   int ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints);
46
47   template<typename T>
48   int ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification);
49
50   AliHLTDataInflater* CreateInflater(int deflater, int mode) const;
51
52   void SetPadShift(float padShift) {fPadShift=padShift;}
53   float PadShift() const {return fPadShift;}
54   void SetVerbosity(int verbosity) {fVerbosity=verbosity;}
55  protected:
56  private:
57   float fPadShift; //! pad shift
58   int fVerbosity; //! verbosity level
59
60   ClassDef(AliHLTTPCDataCompressionDecoder, 0)
61 };
62
63 template<typename T>
64 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification)
65 {
66   // read cluster data from AliHLTTPCClusterData
67   int iResult=0;
68   if (!pData  || dataSize<4) return -EINVAL;
69
70   const AliHLTUInt8_t* pBuffer=pData;
71   AliHLTUInt32_t size=dataSize;
72   const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
73   Int_t nCount = (Int_t) clusterData->fCount;
74
75   int formatVersion=1;
76   int deflaterMode=2;
77   switch (clusterData->fVersion) {
78   case 1: deflaterMode=1; formatVersion=0; break;
79   case 2: deflaterMode=2; formatVersion=0; break;
80   case 3: deflaterMode=1; formatVersion=1; break;
81   case 4: deflaterMode=2; formatVersion=1; break;
82   default:
83     return -EBADF;
84   }
85   std::auto_ptr<AliHLTDataInflater> inflater(CreateInflater(deflaterMode, 1));
86   if (!inflater.get()) return -ENODEV;
87
88   if ((iResult=inflater->InitBitDataInput(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
89                                           size-sizeof(AliHLTTPCRawClusterData)))<0) {
90     return iResult;
91   }
92
93   iResult=ReadRemainingClustersCompressed(c, inflater.get(), nCount, specification, formatVersion);
94
95   return iResult;
96 }
97
98 template<typename T>
99 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion)
100 {
101   // read cluster data
102
103   int iResult=0;
104   if (!pInflater) return -EINVAL;
105
106   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
107   AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
108   // the compressed format stores the difference of the local row number in
109   // the partition to the row of the last cluster
110   // add the first row in the partition to get global row number
111   int rowOffset=AliHLTTPCTransform::GetFirstRow(partition);
112
113   int parameterId=pInflater->NextParameter();
114   if (parameterId<0) return parameterId;
115   int outClusterCnt=0;
116   AliHLTUInt64_t value=0;
117   AliHLTUInt32_t length=0;
118   AliHLTUInt32_t lastPadRow=0;
119   AliHLTUInt64_t lastPad64=0;
120   AliHLTUInt64_t lastTime64=0;
121   AliHLTUInt8_t isSinglePad=0;
122   AliHLTUInt8_t sign=0;
123   bool bNextCluster=true;
124   bool bReadSuccess=true;
125   while (outClusterCnt<nofClusters && bReadSuccess && pInflater->NextValue(value, length)) {
126     if (bNextCluster) {
127       // switch to next cluster
128       c.Next(slice, partition);
129       bNextCluster=false;
130     }
131     const AliHLTTPCDefinitions::AliClusterParameter& parameter
132       =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
133
134     if (parameter.fBitLength!=(int)length) {
135       HLTError("decode error: expecting length %d for parameter %s, but got %d",
136                parameter.fBitLength, parameter.fName, length);
137       break;
138     }
139
140     switch (parameterId) {
141     case AliHLTTPCDefinitions::kPadRow:
142       {c.SetPadRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
143     case AliHLTTPCDefinitions::kPad: {
144       if (formatVersion==1) {
145         bReadSuccess=bReadSuccess && pInflater->InputBit(isSinglePad);
146         if (isSinglePad==0) {
147           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
148           if (sign) {
149             value=lastPad64-value;
150           } else {
151             value+=lastPad64;
152           }
153           lastPad64=value;
154         }
155       }
156       float pad=value;
157       if (isSinglePad==0) pad/=parameter.fScale;
158       else pad/=2; // for the sake of the 0.5 pad offset (see AliHLTTPCHWCFSpacePointContainer::WriteSorted for details)
159       c.SetPad(pad+PadShift());
160       break;
161     }
162     case AliHLTTPCDefinitions::kTime: {
163       if (formatVersion==1) {
164         bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
165         if (sign) {
166           value=lastTime64-value;
167         } else {
168           value+=lastTime64;
169         }
170         lastTime64=value;
171       }
172       float time=value; time/=parameter.fScale;
173       c.SetTime(time);
174       break;
175     }
176     case AliHLTTPCDefinitions::kSigmaY2:
177       {float sigmaY2=value; sigmaY2/=parameter.fScale; c.SetSigmaY2(sigmaY2); break;}
178     case AliHLTTPCDefinitions::kSigmaZ2:
179       {float sigmaZ2=value; sigmaZ2/=parameter.fScale; c.SetSigmaZ2(sigmaZ2); break;}
180     case AliHLTTPCDefinitions::kCharge:
181       {c.SetCharge(value); break;}
182     case AliHLTTPCDefinitions::kQMax:
183       {c.SetQMax(value); break;}
184     }
185     if (parameterId>=AliHLTTPCDefinitions::kLast) {
186       bNextCluster=true;
187       outClusterCnt++;
188     }
189     parameterId=pInflater->NextParameter();
190     if (parameterId==AliHLTTPCDefinitions::kSigmaY2 && isSinglePad==1) {
191       // skip sigmaY for single pad clusters in format version 1
192       parameterId=pInflater->NextParameter();
193       isSinglePad=0;
194       c.SetSigmaY2(0.);
195     }
196   }
197   pInflater->Pad8Bits();
198   AliHLTUInt8_t bit=0;
199   if (pInflater->InputBit(bit)) {
200     HLTWarning("format error of compressed clusters, there is more data than expected");
201   }
202   pInflater->CloseBitDataInput();
203   if (iResult>=0 && nofClusters!=outClusterCnt) {
204     // is this a Fatal?
205     HLTError("error reading compressed cluster format of block 0x%08x: expected %d, read only %d cluster(s)", specification, nofClusters, outClusterCnt);
206     return -EPROTO;
207   }
208   if (iResult<0) return iResult;
209   return nofClusters;
210 }
211
212 template<typename T>
213 int AliHLTTPCDataCompressionDecoder::ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t /*specification*/)
214 {
215   // read cluster data from the track model data block
216   int iResult=0;
217   int dataOffset=sizeof(AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock);
218   if (!pData  || dataSize<dataOffset) return -EINVAL;
219
220   const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock* trackModelBlock=reinterpret_cast<const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock*>(pData);
221   if (trackModelBlock->fVersion!=1) {
222     HLTError("unknown version %d", trackModelBlock->fVersion);
223     return -EINVAL;
224   }
225   std::auto_ptr<AliHLTDataInflater> pInflater(CreateInflater(trackModelBlock->fDeflaterMode, 2));
226   if (!pInflater.get()) {
227     HLTError("failed to create the data inflater for mode %d", trackModelBlock->fDeflaterMode);
228   }
229   int nofTracks=trackModelBlock->fTrackCount;
230   dataOffset+=trackModelBlock->fGlobalParameterCnt*sizeof(trackModelBlock->fGlobalParameters);
231   if (dataSize<dataOffset) {
232     HLTError("inconsistent data block, size %d, expecting at least %d to read AliHLTTPCTrackModelBlock with %d global parameters", dataSize, dataOffset, trackModelBlock->fGlobalParameterCnt);
233     return -ENOSPC;
234   }
235   float bz=0.0;
236   float driftTimeFactorA=0.;
237   float driftTimeOffsetA=0.;
238   float driftTimeFactorC=0.;
239   float driftTimeOffsetC=0.;
240
241   AliHLTUInt32_t parameterIndex=0;
242   switch (trackModelBlock->fGlobalParameterCnt) {
243   case 5:
244     bz              =trackModelBlock->fGlobalParameters[parameterIndex++];
245     driftTimeFactorA=trackModelBlock->fGlobalParameters[parameterIndex++];
246     driftTimeOffsetA=trackModelBlock->fGlobalParameters[parameterIndex++];
247     driftTimeFactorC=trackModelBlock->fGlobalParameters[parameterIndex++];
248     driftTimeOffsetC=trackModelBlock->fGlobalParameters[parameterIndex++];
249     break;
250   default:
251     HLTError("unknown version of global parameters %d", trackModelBlock->fGlobalParameterCnt);
252     return -ENODATA;
253   }
254
255   if (parameterIndex!=trackModelBlock->fGlobalParameterCnt) {
256     HLTError("internal error, size of parameter array has changed without providing all values");
257     return -EFAULT;
258   }
259
260   for (int trackno=0; trackno<nofTracks; trackno++) {
261     AliHLTTPCTrackGeometry trackpoints;
262     trackpoints.InitDriftTimeTransformation(driftTimeFactorA, driftTimeOffsetA, driftTimeFactorC, driftTimeOffsetC);
263     AliHLTUInt32_t  clusterBlockSize=0;
264     if ((iResult=trackpoints.Read(pData+dataOffset, dataSize-dataOffset, bz, clusterBlockSize))<0) {
265       return iResult;
266     }
267     dataOffset+=iResult;
268     if (dataSize-dataOffset<(int)clusterBlockSize) {
269       HLTError("to little data in buffer to read cluster block of size %d for track no %d", clusterBlockSize, trackno);
270       return -ENODATA;
271     }
272     if ((iResult=pInflater->InitBitDataInput(pData+dataOffset, clusterBlockSize))<0) {
273       return iResult;
274     }
275     if ((iResult=ReadTrackClustersCompressed(c, pInflater.get(), &trackpoints))<0) {
276       HLTError("reading of associated clusters failed for track %d", trackno);
277       return iResult;
278     }
279     pInflater->Pad8Bits();
280     AliHLTUInt8_t bit=0;
281     if (pInflater->InputBit(bit)) {
282       HLTWarning("format error of compressed clusters, there is more data than expected");
283     }
284     pInflater->CloseBitDataInput();
285     dataOffset+=clusterBlockSize;
286   }
287
288   return iResult;
289 }
290
291 template<typename T>
292 int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints)
293 {
294   // read cluster data
295
296   int iResult=0;
297   if (!pInflater || !pTrackPoints) return -EINVAL;
298
299   const vector<AliHLTTrackGeometry::AliHLTTrackPoint>& rawTrackPoints=pTrackPoints->GetRawPoints();
300   vector<AliHLTTrackGeometry::AliHLTTrackPoint>::const_iterator currentTrackPoint=rawTrackPoints.begin();
301
302   bool bReadSuccess=true;
303   AliHLTUInt32_t clusterCountBitLength=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kClusterCount].fBitLength;
304   //unsigned long dataPosition=pInflater->GetCurrentByteInputPosition();
305   for (unsigned row=0; row<159 && bReadSuccess; row++) {
306     AliHLTUInt8_t haveClusters=0;
307     // 1 bit for clusters on that padrow
308     bReadSuccess=bReadSuccess && pInflater->InputBit(haveClusters);
309     if (!haveClusters) continue;
310     bool bEscape=false;
311     do {
312       if (currentTrackPoint==rawTrackPoints.end()) {
313         if (bEscape || rawTrackPoints.begin()==rawTrackPoints.end()) break;
314         currentTrackPoint=rawTrackPoints.begin();
315         bEscape=true;
316       }
317       if (AliHLTTPCTransform::GetFirstRow(AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId())) +
318           AliHLTTPCSpacePointData::GetNumber(currentTrackPoint->GetId()) == row) {
319         break;
320       }
321       currentTrackPoint++;
322     } while (!bEscape);
323     if (currentTrackPoint==rawTrackPoints.end()) {
324       HLTError("decoding error, can not find track point on row %d", row);
325       return -EFAULT;
326     }
327     AliHLTUInt8_t slice = AliHLTTPCSpacePointData::GetSlice(currentTrackPoint->GetId());
328     AliHLTUInt8_t partition = AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId());
329     AliHLTUInt8_t nofClusters=0;
330     bReadSuccess=bReadSuccess && pInflater->InputBits(nofClusters, clusterCountBitLength);
331     if (!bReadSuccess) break;
332     HLTDebug("slice %02d partition %d row %03d: %d cluster(s)", slice, partition, row, nofClusters);
333
334     static const AliHLTTPCDefinitions::AliClusterParameterId_t kParameterIdMapping[] = {
335       AliHLTTPCDefinitions::kResidualPad,
336       AliHLTTPCDefinitions::kResidualTime,
337       AliHLTTPCDefinitions::kSigmaY2,
338       AliHLTTPCDefinitions::kSigmaZ2,
339       AliHLTTPCDefinitions::kCharge,
340       AliHLTTPCDefinitions::kQMax,
341     };
342
343     int parameterId=0;
344     int inClusterCnt=0;
345     AliHLTUInt64_t value=0;
346     AliHLTUInt32_t length=0;
347     bool bNextCluster=true;
348     while (bReadSuccess && inClusterCnt<nofClusters && pInflater->NextValue(value, length)) {
349       if (bNextCluster) {
350         // switch to next cluster
351         c.Next(slice, partition);
352         c.SetPadRow(row);
353         bNextCluster=false;
354       }
355       const AliHLTTPCDefinitions::AliClusterParameter& parameter
356         =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[kParameterIdMapping[parameterId]];
357
358       if (parameter.fBitLength!=(int)length) {
359         HLTError("decode error: expecting length %d for parameter %s, but got %d",
360                  parameter.fBitLength, parameter.fName, length);
361         break;
362       }
363
364       static float deltapad=0.;
365       static float deltatime=0.;
366       bool lastParameter=false;
367       switch (kParameterIdMapping[parameterId]) {
368       case AliHLTTPCDefinitions::kResidualPad:
369         {
370           AliHLTUInt8_t sign=0;
371           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
372           deltapad=((float)value)*(sign?-1.:1.)/parameter.fScale;
373           AliHLTUInt64_t trackpad64=0;
374           double trackpad=currentTrackPoint->GetU();
375           trackpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
376           if (currentTrackPoint->GetU()>0.) trackpad64=(AliHLTUInt64_t)round(trackpad);
377           if (sign) {
378             value=trackpad64-value;
379           } else {
380             value+=trackpad64;
381           }
382           float pad=((float)value)/parameter.fScale;
383           c.SetPad(pad+PadShift()); 
384           break;
385         }
386       case AliHLTTPCDefinitions::kResidualTime:
387         {
388           AliHLTUInt8_t sign=0;
389           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
390           deltatime=((float)value)*(sign?-1.:1.)/parameter.fScale;
391           AliHLTUInt64_t tracktime64=0;
392           double tracktime=currentTrackPoint->GetV();
393           tracktime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
394           if (currentTrackPoint->GetV()>0.) tracktime64=(AliHLTUInt64_t)round(tracktime);
395           if (sign) {
396             value=tracktime64-value;
397           } else {
398             value+=tracktime64;
399           }
400           float time=((float)value)/parameter.fScale;
401           c.SetTime(time); 
402           break;
403         }
404       case AliHLTTPCDefinitions::kSigmaY2:
405         {float sigmaY2=value; sigmaY2/=parameter.fScale; c.SetSigmaY2(sigmaY2); break;}
406       case AliHLTTPCDefinitions::kSigmaZ2:
407         {float sigmaZ2=value; sigmaZ2/=parameter.fScale; c.SetSigmaZ2(sigmaZ2); break;}
408       case AliHLTTPCDefinitions::kCharge:
409         {c.SetCharge(value); break;}
410       case AliHLTTPCDefinitions::kQMax:
411         {c.SetQMax(value); lastParameter=true; break;}
412       default:
413         {
414           HLTError("parameter %d not expected", kParameterIdMapping[parameterId]);
415         }
416       }
417       if (lastParameter) {
418         // switch to next cluster
419         // cout << "  row "    << setfill(' ') << setw(3) << fixed << right                     << c.GetRow()
420         //      << "  pad "    << setfill(' ') << setw(7) << fixed << right << setprecision (4) << c.GetPad()
421         //      << "  dpad "   << setfill(' ') << setw(7) << fixed << right << setprecision (4) << deltapad
422         //      << "  time "   << setfill(' ') << setw(7) << fixed << right << setprecision (4) << c.GetTimeBin()
423         //      << "  dtime "  << setfill(' ') << setw(7) << fixed << right << setprecision (4) << deltatime
424         //      << "  charge " << setfill(' ') << setw(5) << fixed << right << setprecision (0) << c.GetQ()
425         //      << "  qmax "   << setfill(' ') << setw(4) << fixed << right << setprecision (0) << c.GetMax()
426         //      << endl;
427         bNextCluster=true;
428         inClusterCnt++;
429         parameterId=-1;
430       }
431       parameterId++;
432     }
433     if (iResult>=0 && nofClusters!=inClusterCnt) {
434       // is this a Fatal?
435       HLTError("error reading track model compressed cluster format of track: expected %d, read only %d cluster(s)", nofClusters, inClusterCnt);
436       return -EPROTO;
437     }
438     currentTrackPoint++;
439   }
440   return iResult;
441 }
442
443 template<typename T>
444 int AliHLTTPCDataCompressionDecoder::ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification)
445 {
446   // read raw cluster data
447   if (!pData) return -EINVAL;
448   if (dataSize<sizeof(AliHLTTPCRawClusterData)) return -ENODATA;
449   const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pData);
450   Int_t nCount = (Int_t) clusterData->fCount;
451   if (clusterData->fVersion!=0) {
452     int iResult=ReadRemainingClustersCompressed(c, pData, dataSize, specification);
453     if (iResult>=0 && fVerbosity>0) {
454       HLTInfo("extracted %d cluster(s) from block 0x%08x", iResult, specification);
455     }
456     return iResult;
457   }
458   if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != dataSize) return -EBADF;
459   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
460   AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
461
462   const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
463   for (int i=0; i<nCount; i++) {
464     c.Next(slice, partition);
465     c.SetPadRow(clusters[i].GetPadRow());
466     c.SetPad(clusters[i].GetPad()+PadShift());
467     c.SetTime(clusters[i].GetTime());
468     c.SetSigmaY2(clusters[i].GetSigmaY2());
469     c.SetSigmaZ2(clusters[i].GetSigmaZ2());
470     c.SetCharge(clusters[i].GetCharge());
471     c.SetQMax(clusters[i].GetQMax());
472   }
473   return nCount;
474 }
475 #endif