]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/comp/AliHLTTPCDataCompressionDecoder.h
e4d01438e3a38b7e133d4000f8ce04472074403d
[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                          * 
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 #include "AliHLTTPCHWClusterMerger.h"
25 #include <vector>
26
27 /**
28  * @class AliHLTTPCDataCompressionDecoder
29  * Generic decoder class for compressed TPC data, works on a container
30  * class implementation which fills the actual target data struct
31  */
32 class AliHLTTPCDataCompressionDecoder : public AliHLTLogging {
33  public:
34   AliHLTTPCDataCompressionDecoder();
35   ~AliHLTTPCDataCompressionDecoder();
36
37   template<typename T>
38   int ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
39
40   template<typename T>
41   int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion=0);
42
43   template<typename T>
44   int ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
45
46   template<typename T>
47   int ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints);
48
49   template<typename T>
50   int ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification);
51
52   AliHLTDataInflater* CreateInflater(int deflater, int mode) const;
53
54   void SetPadShift(float padShift) {fPadShift=padShift;}
55   float PadShift() const {return fPadShift;}
56   void SetVerbosity(int verbosity) {fVerbosity=verbosity;}
57
58   int InitPartitionClusterDecoding(AliHLTUInt32_t specification);
59   int InitTrackModelClusterClusterDecoding();
60   int AddCompressionDescriptor(const AliHLTComponentBlockData* pDesc);
61   int AddClusterMCData(const AliHLTComponentBlockData* pDesc);
62   int AddClusterIds(const AliHLTComponentBlockData* pDesc);
63   AliHLTUInt32_t GetClusterId(int clusterNo) const;
64   const AliHLTTPCClusterMCLabel* GetMCLabel(AliHLTUInt32_t clusterId) const;
65
66   void Clear(const char* option="");
67
68   struct AliClusterIdBlock {
69     AliClusterIdBlock() : fIds(NULL), fSize(0) {}
70     AliHLTUInt32_t* fIds; //!
71     AliHLTUInt32_t  fSize; //!
72
73     void Clear() {fIds=NULL; fSize=0;}
74   };
75
76  protected:
77  private:
78   AliHLTTPCDataCompressionDecoder(const AliHLTTPCDataCompressionDecoder&);
79   AliHLTTPCDataCompressionDecoder& operator=(const AliHLTTPCDataCompressionDecoder&);
80
81   float fPadShift; //! pad shift
82   int fVerbosity; //! verbosity level
83   Bool_t fUseClusterMerger; // flag to run the cluster merger
84   AliHLTDataInflater* fpDataInflaterPartition; //! instance of inflater for partition clusters
85   AliHLTDataInflater* fpDataInflaterTrack; //! instance of inflater for track clusters
86   AliHLTTPCHWClusterMerger* fpClusterMerger; //! merger instance
87
88   vector<AliClusterIdBlock> fPartitionClusterIds; //! clusters ids for clusters of individual partitions
89   AliClusterIdBlock fTrackModelClusterIds; //! cluster ids for track model clusters
90   AliClusterIdBlock* fCurrentClusterIds; //! id block currently active in the iteration
91   vector<const AliHLTTPCClusterMCData*> fClusterMCData; //! references to MC data blocks
92
93   ClassDef(AliHLTTPCDataCompressionDecoder, 0)
94 };
95
96 template<typename T>
97 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification)
98 {
99   // read cluster data from AliHLTTPCClusterData
100   int iResult=0;
101   if (!pData  || dataSize<4) return -EINVAL;
102
103   const AliHLTUInt8_t* pBuffer=pData;
104   AliHLTUInt32_t size=dataSize;
105   const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
106   Int_t nCount = (Int_t) clusterData->fCount;
107
108   int formatVersion=1;
109   int deflaterMode=2;
110   switch (clusterData->fVersion) {
111   case 1: deflaterMode=1; formatVersion=0; break;
112   case 2: deflaterMode=2; formatVersion=0; break;
113   case 3: deflaterMode=1; formatVersion=1; break;
114   case 4: deflaterMode=2; formatVersion=1; break;
115   default:
116     return -EBADF;
117   }
118   if (!fpDataInflaterPartition)
119     fpDataInflaterPartition=CreateInflater(deflaterMode, 1);
120   else
121     fpDataInflaterPartition->Clear();
122   if (!fpDataInflaterPartition) return -ENODEV;
123
124   if ((iResult=fpDataInflaterPartition->InitBitDataInput(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
125                                                 size-sizeof(AliHLTTPCRawClusterData)))<0) {
126     return iResult;
127   }
128
129   iResult=ReadRemainingClustersCompressed(c, fpDataInflaterPartition, nCount, specification, formatVersion);
130   if (iResult<0) {
131     HLTError("cluster decoding of block 0x%08x failed, error %d", specification, iResult);
132   }
133
134   return iResult;
135 }
136
137 template<typename T>
138 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion)
139 {
140   // read cluster data
141
142   int iResult=0;
143   if (!pInflater) return -EINVAL;
144
145   if ((iResult= InitPartitionClusterDecoding(specification))<0)
146     return iResult;
147
148   int slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
149   int partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
150   if (slice<0 || slice>=AliHLTTPCTransform::GetNSlice()) {
151     HLTError("invalid slice %d decoded from specification 0x%08x", slice, specification);
152     return -EINVAL;
153   }
154   if (partition<0 || partition>=AliHLTTPCTransform::GetNumberOfPatches()) {
155     HLTError("invalid partition %d decoded from specification 0x%08x", partition, specification);
156     return -EINVAL;
157   }
158   // the compressed format stores the difference of the local row number in
159   // the partition to the row of the last cluster
160   // add the first row in the partition to get global row number
161   int rowOffset=AliHLTTPCTransform::GetFirstRow(partition);
162
163   int parameterId=pInflater->NextParameter();
164   if (parameterId<0) return parameterId;
165   int decodedClusterCnt=0;
166   int outClusterCnt=0;
167   AliHLTUInt64_t value=0;
168   AliHLTUInt32_t length=0;
169   AliHLTUInt32_t lastPadRow=0;
170   AliHLTUInt64_t lastPad64=0;
171   AliHLTUInt64_t lastTime64=0;
172   AliHLTUInt8_t isSinglePad=0;
173   AliHLTUInt8_t sign=0;
174   bool bNextCluster=true;
175   bool bReadSuccess=true;
176   AliHLTTPCRawCluster rawCluster;
177
178   if( fUseClusterMerger && !fpClusterMerger ){
179     fpClusterMerger = new AliHLTTPCHWClusterMerger;
180   }
181
182   if (fpClusterMerger)
183     fpClusterMerger->Clear();
184
185   while (decodedClusterCnt<nofClusters && bReadSuccess && pInflater->NextValue(value, length)) {
186     if (bNextCluster) {
187       // switch to next cluster
188       rawCluster.Clear();
189       bNextCluster=false;
190     }
191     const AliHLTTPCDefinitions::AliClusterParameter& parameter
192       =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
193
194     if (parameter.fBitLength!=(int)length) {
195       HLTError("decode error: expecting length %d for parameter %s, but got %d",
196                parameter.fBitLength, parameter.fName, length);
197       break;
198     }
199
200     switch (parameterId) {
201     case AliHLTTPCDefinitions::kPadRow:
202       {rawCluster.SetPadRow(value+lastPadRow); lastPadRow+=value;break;}
203     case AliHLTTPCDefinitions::kPad: {
204       if (formatVersion==1) {
205         bReadSuccess=bReadSuccess && pInflater->InputBit(isSinglePad);
206         if (isSinglePad==0) {
207           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
208           if (sign) {
209             value=lastPad64-value;
210           } else {
211             value+=lastPad64;
212           }
213           lastPad64=value;
214         }
215       }
216       float pad=value;
217       if (isSinglePad==0) pad/=parameter.fScale;
218       else pad/=2; // for the sake of the 0.5 pad offset (see AliHLTTPCHWCFSpacePointContainer::WriteSorted for details)
219       rawCluster.SetPad(pad+PadShift());
220       break;
221     }
222     case AliHLTTPCDefinitions::kTime: {
223       if (formatVersion==1) {
224         bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
225         if (sign) {
226           value=lastTime64-value;
227         } else {
228           value+=lastTime64;
229         }
230         lastTime64=value;
231       }
232       float time=value; time/=parameter.fScale;
233       rawCluster.SetTime(time);
234       break;
235     }
236     case AliHLTTPCDefinitions::kSigmaY2:
237       {float sigmaY2=value; sigmaY2/=parameter.fScale; rawCluster.SetSigmaY2(sigmaY2); break;}
238     case AliHLTTPCDefinitions::kSigmaZ2:
239       {float sigmaZ2=value; sigmaZ2/=parameter.fScale; rawCluster.SetSigmaZ2(sigmaZ2); break;}
240     case AliHLTTPCDefinitions::kCharge:
241       {rawCluster.SetCharge(value); break;}
242     case AliHLTTPCDefinitions::kQMax:
243       {rawCluster.SetQMax(value); break;}
244     }
245     if (parameterId>=AliHLTTPCDefinitions::kLast) {
246       AliHLTUInt32_t id=GetClusterId(decodedClusterCnt);
247       const AliHLTTPCClusterMCLabel* pMC=GetMCLabel(id);
248       if (fUseClusterMerger && fpClusterMerger && fpClusterMerger->CheckCandidate(slice, partition, rawCluster)) {
249         fpClusterMerger->AddCandidate(slice, partition, id, rawCluster, pMC);
250       } else {
251       c.Next(slice, partition);
252       c.SetPadRow(rawCluster.GetPadRow()+rowOffset);
253       c.SetPad(rawCluster.GetPad());
254       c.SetTime(rawCluster.GetTime());
255       c.SetSigmaY2(rawCluster.GetSigmaY2());
256       c.SetSigmaZ2(rawCluster.GetSigmaZ2());
257       c.SetCharge(rawCluster.GetCharge());
258       c.SetQMax(rawCluster.GetQMax());
259       if (pMC) c.SetMC(pMC);
260       outClusterCnt++;
261       }
262       bNextCluster=true;
263       decodedClusterCnt++;
264     }
265     parameterId=pInflater->NextParameter();
266     if (parameterId==AliHLTTPCDefinitions::kSigmaY2 && isSinglePad==1) {
267       // skip sigmaY for single pad clusters in format version 1
268       parameterId=pInflater->NextParameter();
269       isSinglePad=0;
270       rawCluster.SetSigmaY2(0.);
271     }
272   }
273   pInflater->Pad8Bits();
274   AliHLTUInt8_t bit=0;
275   if (pInflater->InputBit(bit)) {
276     HLTWarning("format error of compressed clusters, there is more data than expected");
277   }
278   pInflater->CloseBitDataInput();
279   int mergedClusterCnt=0;
280   if (fUseClusterMerger && fpClusterMerger) {
281     mergedClusterCnt=fpClusterMerger->Merge();
282     int remainingCnt=0;
283     if (mergedClusterCnt>=0) {
284       for (AliHLTTPCHWClusterMerger::iterator i=fpClusterMerger->begin();
285            i!=fpClusterMerger->end(); i++) {
286         c.Next((*i).GetSlice(), (*i).GetPartition());
287         const AliHLTTPCRawCluster& mergedCluster=(*i).GetCluster();
288         const AliHLTTPCClusterMCLabel& mc=(*i).MCLabel();
289         c.SetPadRow(mergedCluster.GetPadRow()+rowOffset);
290         c.SetPad(mergedCluster.GetPad());
291         c.SetTime(mergedCluster.GetTime());
292         c.SetSigmaY2(mergedCluster.GetSigmaY2());
293         c.SetSigmaZ2(mergedCluster.GetSigmaZ2());
294         c.SetCharge(mergedCluster.GetCharge());
295         c.SetQMax(mergedCluster.GetQMax());
296         c.SetMC(&mc);
297         outClusterCnt++;
298         remainingCnt++;
299       }
300     } else {
301       iResult=mergedClusterCnt;
302     }
303     HLTDebug("copied %d cluster(s) from merger, %d merged, specification 0x%08x", remainingCnt, mergedClusterCnt, specification);
304     fpClusterMerger->Clear();
305   }
306   if (iResult>=0 && nofClusters!=outClusterCnt+mergedClusterCnt) {
307     // is this a Fatal?
308     HLTError("error reading compressed cluster format of block 0x%08x: expected %d, read %d cluster(s), merged %d cluster(s)", specification, nofClusters, outClusterCnt, mergedClusterCnt);
309     return -EPROTO;
310   }
311   if (iResult<0) return iResult;
312   return outClusterCnt;
313 }
314
315 template<typename T>
316 int AliHLTTPCDataCompressionDecoder::ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t /*specification*/)
317 {
318   // read cluster data from the track model data block
319   int iResult=0;
320   int dataOffset=sizeof(AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock);
321   if (!pData  || dataSize<dataOffset) return -EINVAL;
322
323   const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock* trackModelBlock=reinterpret_cast<const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock*>(pData);
324   if (trackModelBlock->fVersion!=1) {
325     HLTError("unknown version %d", trackModelBlock->fVersion);
326     return -EINVAL;
327   }
328   if (!fpDataInflaterTrack)
329     fpDataInflaterTrack=CreateInflater(trackModelBlock->fDeflaterMode, 2);
330   else
331     fpDataInflaterTrack->Clear();
332   if (!fpDataInflaterTrack) {
333     HLTError("failed to create the data inflater for mode %d", trackModelBlock->fDeflaterMode);
334     return -ENODEV;
335   }
336   int nofTracks=trackModelBlock->fTrackCount;
337   dataOffset+=trackModelBlock->fGlobalParameterCnt*sizeof(trackModelBlock->fGlobalParameters);
338   if (dataSize<dataOffset) {
339     HLTError("inconsistent data block, size %d, expecting at least %d to read AliHLTTPCTrackModelBlock with %d global parameters", dataSize, dataOffset, trackModelBlock->fGlobalParameterCnt);
340     return -ENOSPC;
341   }
342   float bz=0.0;
343   float driftTimeFactorA=0.;
344   float driftTimeOffsetA=0.;
345   float driftTimeFactorC=0.;
346   float driftTimeOffsetC=0.;
347
348   AliHLTUInt32_t parameterIndex=0;
349   switch (trackModelBlock->fGlobalParameterCnt) {
350   case 5:
351     bz              =trackModelBlock->fGlobalParameters[parameterIndex++];
352     driftTimeFactorA=trackModelBlock->fGlobalParameters[parameterIndex++];
353     driftTimeOffsetA=trackModelBlock->fGlobalParameters[parameterIndex++];
354     driftTimeFactorC=trackModelBlock->fGlobalParameters[parameterIndex++];
355     driftTimeOffsetC=trackModelBlock->fGlobalParameters[parameterIndex++];
356     break;
357   default:
358     HLTError("unknown version of global parameters %d", trackModelBlock->fGlobalParameterCnt);
359     return -ENODATA;
360   }
361
362   if (parameterIndex!=trackModelBlock->fGlobalParameterCnt) {
363     HLTError("internal error, size of parameter array has changed without providing all values");
364     return -EFAULT;
365   }
366
367   for (int trackno=0; trackno<nofTracks; trackno++) {
368     AliHLTTPCTrackGeometry trackpoints;
369     trackpoints.InitDriftTimeTransformation(driftTimeFactorA, driftTimeOffsetA, driftTimeFactorC, driftTimeOffsetC);
370     AliHLTUInt32_t  clusterBlockSize=0;
371     if ((iResult=trackpoints.Read(pData+dataOffset, dataSize-dataOffset, bz, clusterBlockSize))<0) {
372       return iResult;
373     }
374     dataOffset+=iResult;
375     if (dataSize-dataOffset<(int)clusterBlockSize) {
376       HLTError("to little data in buffer to read cluster block of size %d for track no %d", clusterBlockSize, trackno);
377       return -ENODATA;
378     }
379     if ((iResult=fpDataInflaterTrack->InitBitDataInput(pData+dataOffset, clusterBlockSize))<0) {
380       return iResult;
381     }
382     if ((iResult=ReadTrackClustersCompressed(c, fpDataInflaterTrack, &trackpoints))<0) {
383       HLTError("reading of associated clusters failed for track %d", trackno);
384       return iResult;
385     }
386     fpDataInflaterTrack->Pad8Bits();
387     AliHLTUInt8_t bit=0;
388     if (fpDataInflaterTrack->InputBit(bit)) {
389       HLTWarning("format error of compressed clusters, there is more data than expected");
390     }
391     fpDataInflaterTrack->CloseBitDataInput();
392     dataOffset+=clusterBlockSize;
393   }
394
395   return iResult;
396 }
397
398 template<typename T>
399 int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints)
400 {
401   // read cluster data
402
403   int iResult=0;
404   if (!pInflater || !pTrackPoints) return -EINVAL;
405
406   if ((iResult= InitTrackModelClusterClusterDecoding())<0)
407     return iResult;
408
409   const vector<AliHLTTrackGeometry::AliHLTTrackPoint>& rawTrackPoints=pTrackPoints->GetRawPoints();
410   vector<AliHLTTrackGeometry::AliHLTTrackPoint>::const_iterator currentTrackPoint=rawTrackPoints.begin();
411
412   bool bReadSuccess=true;
413   AliHLTUInt32_t clusterCountBitLength=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kClusterCount].fBitLength;
414   //unsigned long dataPosition=pInflater->GetCurrentByteInputPosition();
415   for (unsigned row=0; row<159 && bReadSuccess; row++) {
416     AliHLTUInt8_t haveClusters=0;
417     // 1 bit for clusters on that padrow
418     bReadSuccess=bReadSuccess && pInflater->InputBit(haveClusters);
419     if (!haveClusters) continue;
420     bool bEscape=false;
421     do {
422       if (currentTrackPoint==rawTrackPoints.end()) {
423         if (bEscape || rawTrackPoints.begin()==rawTrackPoints.end()) break;
424         currentTrackPoint=rawTrackPoints.begin();
425         bEscape=true;
426       }
427       if (AliHLTTPCTransform::GetFirstRow(AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId())) +
428           AliHLTTPCSpacePointData::GetNumber(currentTrackPoint->GetId()) == row) {
429         break;
430       }
431       currentTrackPoint++;
432     } while (!bEscape);
433     if (currentTrackPoint==rawTrackPoints.end()) {
434       HLTError("decoding error, can not find track point on row %d", row);
435       return -EFAULT;
436     }
437     AliHLTUInt8_t slice = AliHLTTPCSpacePointData::GetSlice(currentTrackPoint->GetId());
438     AliHLTUInt8_t partition = AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId());
439     AliHLTUInt8_t nofClusters=0;
440     bReadSuccess=bReadSuccess && pInflater->InputBits(nofClusters, clusterCountBitLength);
441     if (!bReadSuccess) break;
442     HLTDebug("slice %02d partition %d row %03d: %d cluster(s)", slice, partition, row, nofClusters);
443
444     static const AliHLTTPCDefinitions::AliClusterParameterId_t kParameterIdMapping[] = {
445       AliHLTTPCDefinitions::kResidualPad,
446       AliHLTTPCDefinitions::kResidualTime,
447       AliHLTTPCDefinitions::kSigmaY2,
448       AliHLTTPCDefinitions::kSigmaZ2,
449       AliHLTTPCDefinitions::kCharge,
450       AliHLTTPCDefinitions::kQMax,
451     };
452
453     int parameterId=0;
454     int inClusterCnt=0;
455     AliHLTUInt64_t value=0;
456     AliHLTUInt32_t length=0;
457     bool bNextCluster=true;
458     while (bReadSuccess && inClusterCnt<nofClusters && pInflater->NextValue(value, length)) {
459       if (bNextCluster) {
460         // switch to next cluster
461         c.Next(slice, partition);
462         c.SetPadRow(row);
463         bNextCluster=false;
464       }
465       const AliHLTTPCDefinitions::AliClusterParameter& parameter
466         =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[kParameterIdMapping[parameterId]];
467
468       if (parameter.fBitLength!=(int)length) {
469         HLTError("decode error: expecting length %d for parameter %s, but got %d",
470                  parameter.fBitLength, parameter.fName, length);
471         break;
472       }
473
474       bool lastParameter=false;
475       switch (kParameterIdMapping[parameterId]) {
476       case AliHLTTPCDefinitions::kResidualPad:
477         {
478           AliHLTUInt8_t sign=0;
479           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
480           AliHLTUInt64_t trackpad64=0;
481           double trackpad=currentTrackPoint->GetU();
482           trackpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
483           if (currentTrackPoint->GetU()>0.) trackpad64=(AliHLTUInt64_t)round(trackpad);
484           if (sign) {
485             value=trackpad64-value;
486           } else {
487             value+=trackpad64;
488           }
489           float pad=((float)value)/parameter.fScale;
490           c.SetPad(pad+PadShift()); 
491           break;
492         }
493       case AliHLTTPCDefinitions::kResidualTime:
494         {
495           AliHLTUInt8_t sign=0;
496           bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
497           AliHLTUInt64_t tracktime64=0;
498           double tracktime=currentTrackPoint->GetV();
499           tracktime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
500           if (currentTrackPoint->GetV()>0.) tracktime64=(AliHLTUInt64_t)round(tracktime);
501           if (sign) {
502             value=tracktime64-value;
503           } else {
504             value+=tracktime64;
505           }
506           float time=((float)value)/parameter.fScale;
507           c.SetTime(time); 
508           break;
509         }
510       case AliHLTTPCDefinitions::kSigmaY2:
511         {float sigmaY2=value; sigmaY2/=parameter.fScale; c.SetSigmaY2(sigmaY2); break;}
512       case AliHLTTPCDefinitions::kSigmaZ2:
513         {float sigmaZ2=value; sigmaZ2/=parameter.fScale; c.SetSigmaZ2(sigmaZ2); break;}
514       case AliHLTTPCDefinitions::kCharge:
515         {c.SetCharge(value); break;}
516       case AliHLTTPCDefinitions::kQMax:
517         {c.SetQMax(value); lastParameter=true; break;}
518       default:
519         {
520           HLTError("parameter %d not expected", kParameterIdMapping[parameterId]);
521         }
522       }
523       if (lastParameter) {
524         // switch to next cluster
525         bNextCluster=true;
526         inClusterCnt++;
527         parameterId=-1;
528       }
529       parameterId++;
530     }
531     if (iResult>=0 && nofClusters!=inClusterCnt) {
532       // is this a Fatal?
533       HLTError("error reading track model compressed cluster format of track: expected %d, read only %d cluster(s)", nofClusters, inClusterCnt);
534       return -EPROTO;
535     }
536     currentTrackPoint++;
537   }
538   return iResult;
539 }
540
541 template<typename T>
542 int AliHLTTPCDataCompressionDecoder::ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification)
543 {
544   // read raw cluster data
545   if (!pData) return -EINVAL;
546   if (dataSize<sizeof(AliHLTTPCRawClusterData)) return -ENODATA;
547   const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pData);
548   Int_t nCount = (Int_t) clusterData->fCount;
549   if (clusterData->fVersion!=0) {
550     int iResult=ReadRemainingClustersCompressed(c, pData, dataSize, specification);
551     if (iResult>=0 && fVerbosity>0) {
552       HLTInfo("extracted %d cluster(s) from block 0x%08x", iResult, specification);
553     }
554     if (iResult<0) {
555       HLTError("cluster decoding of block 0x%08x failed, error %d", specification, iResult);
556     }
557     return iResult;
558   }
559   if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != dataSize) return -EBADF;
560   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
561   AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
562
563   const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
564   for (int i=0; i<nCount; i++) {
565     AliHLTUInt32_t id=GetClusterId(i);
566     const AliHLTTPCClusterMCLabel* pMC=GetMCLabel(id);
567     c.Next(slice, partition);
568     c.SetPadRow(clusters[i].GetPadRow());
569     c.SetPad(clusters[i].GetPad()+PadShift());
570     c.SetTime(clusters[i].GetTime());
571     c.SetSigmaY2(clusters[i].GetSigmaY2());
572     c.SetSigmaZ2(clusters[i].GetSigmaZ2());
573     c.SetCharge(clusters[i].GetCharge());
574     c.SetQMax(clusters[i].GetQMax());
575     if (pMC) c.SetMC(pMC);
576   }
577   return nCount;
578 }
579 #endif