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