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 *
9 /// @file AliHLTTPCDataCompressionDecoder.h
10 /// @author Matthias Richter
12 /// @brief Generic decoder class for compressed TPC data, works on a container
13 /// class implementation which fills the actual target data struct
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"
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
32 class AliHLTTPCDataCompressionDecoder : public AliHLTLogging {
34 AliHLTTPCDataCompressionDecoder();
35 ~AliHLTTPCDataCompressionDecoder();
38 int ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
41 int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion=0);
44 int ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
47 int ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints);
50 int ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification);
52 AliHLTDataInflater* CreateInflater(int deflater, int mode) const;
54 void SetPadShift(float padShift) {fPadShift=padShift;}
55 float PadShift() const {return fPadShift;}
56 void SetVerbosity(int verbosity) {fVerbosity=verbosity;}
57 void EnableClusterMerger() {if (!fpClusterMerger) fpClusterMerger=new AliHLTTPCHWClusterMerger;}
59 int InitPartitionClusterDecoding(AliHLTUInt32_t specification);
60 int InitTrackModelClusterClusterDecoding();
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;
66 void Clear(const char* option);
68 struct AliClusterIdBlock {
69 AliClusterIdBlock() : fIds(NULL), fSize(0) {}
70 AliHLTUInt32_t* fIds; //!
71 AliHLTUInt32_t fSize; //!
76 AliHLTTPCDataCompressionDecoder(const AliHLTTPCDataCompressionDecoder&);
77 AliHLTTPCDataCompressionDecoder& operator=(const AliHLTTPCDataCompressionDecoder&);
79 float fPadShift; //! pad shift
80 int fVerbosity; //! verbosity level
81 AliHLTDataInflater* fpDataInflaterPartition; //! instance of inflater for partition clusters
82 AliHLTDataInflater* fpDataInflaterTrack; //! instance of inflater for track clusters
83 AliHLTTPCHWClusterMerger* fpClusterMerger; //! merger instance
85 vector<AliClusterIdBlock> fRemainingClusterIds; //! clusters ids for remaining cluster ids
86 AliClusterIdBlock fTrackModelClusterIds; //! cluster ids for track model clusters
87 AliClusterIdBlock* fCurrentClusterIds; //! id block currently active in the iteration
88 vector<const AliHLTTPCClusterMCData*> fClusterMCData; //! references to MC data blocks
90 ClassDef(AliHLTTPCDataCompressionDecoder, 0)
94 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification)
96 // read cluster data from AliHLTTPCClusterData
98 if (!pData || dataSize<4) return -EINVAL;
100 const AliHLTUInt8_t* pBuffer=pData;
101 AliHLTUInt32_t size=dataSize;
102 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
103 Int_t nCount = (Int_t) clusterData->fCount;
107 switch (clusterData->fVersion) {
108 case 1: deflaterMode=1; formatVersion=0; break;
109 case 2: deflaterMode=2; formatVersion=0; break;
110 case 3: deflaterMode=1; formatVersion=1; break;
111 case 4: deflaterMode=2; formatVersion=1; break;
115 if (!fpDataInflaterPartition)
116 fpDataInflaterPartition=CreateInflater(deflaterMode, 1);
118 fpDataInflaterPartition->Clear();
119 if (!fpDataInflaterPartition) return -ENODEV;
121 if ((iResult=fpDataInflaterPartition->InitBitDataInput(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
122 size-sizeof(AliHLTTPCRawClusterData)))<0) {
126 iResult=ReadRemainingClustersCompressed(c, fpDataInflaterPartition, nCount, specification, formatVersion);
132 int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion)
137 if (!pInflater) return -EINVAL;
139 if ((iResult= InitPartitionClusterDecoding(specification))<0)
142 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
143 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
144 // the compressed format stores the difference of the local row number in
145 // the partition to the row of the last cluster
146 // add the first row in the partition to get global row number
147 int rowOffset=AliHLTTPCTransform::GetFirstRow(partition);
149 int parameterId=pInflater->NextParameter();
150 if (parameterId<0) return parameterId;
151 int decodedClusterCnt=0;
153 AliHLTUInt64_t value=0;
154 AliHLTUInt32_t length=0;
155 AliHLTUInt32_t lastPadRow=0;
156 AliHLTUInt64_t lastPad64=0;
157 AliHLTUInt64_t lastTime64=0;
158 AliHLTUInt8_t isSinglePad=0;
159 AliHLTUInt8_t sign=0;
160 bool bNextCluster=true;
161 bool bReadSuccess=true;
162 AliHLTTPCRawCluster rawCluster;
164 fpClusterMerger->Clear();
166 while (decodedClusterCnt<nofClusters && bReadSuccess && pInflater->NextValue(value, length)) {
168 // switch to next cluster
172 const AliHLTTPCDefinitions::AliClusterParameter& parameter
173 =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
175 if (parameter.fBitLength!=(int)length) {
176 HLTError("decode error: expecting length %d for parameter %s, but got %d",
177 parameter.fBitLength, parameter.fName, length);
181 switch (parameterId) {
182 case AliHLTTPCDefinitions::kPadRow:
183 {rawCluster.SetPadRow(value+lastPadRow); lastPadRow+=value;break;}
184 case AliHLTTPCDefinitions::kPad: {
185 if (formatVersion==1) {
186 bReadSuccess=bReadSuccess && pInflater->InputBit(isSinglePad);
187 if (isSinglePad==0) {
188 bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
190 value=lastPad64-value;
198 if (isSinglePad==0) pad/=parameter.fScale;
199 else pad/=2; // for the sake of the 0.5 pad offset (see AliHLTTPCHWCFSpacePointContainer::WriteSorted for details)
200 rawCluster.SetPad(pad+PadShift());
203 case AliHLTTPCDefinitions::kTime: {
204 if (formatVersion==1) {
205 bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
207 value=lastTime64-value;
213 float time=value; time/=parameter.fScale;
214 rawCluster.SetTime(time);
217 case AliHLTTPCDefinitions::kSigmaY2:
218 {float sigmaY2=value; sigmaY2/=parameter.fScale; rawCluster.SetSigmaY2(sigmaY2); break;}
219 case AliHLTTPCDefinitions::kSigmaZ2:
220 {float sigmaZ2=value; sigmaZ2/=parameter.fScale; rawCluster.SetSigmaZ2(sigmaZ2); break;}
221 case AliHLTTPCDefinitions::kCharge:
222 {rawCluster.SetCharge(value); break;}
223 case AliHLTTPCDefinitions::kQMax:
224 {rawCluster.SetQMax(value); break;}
226 if (parameterId>=AliHLTTPCDefinitions::kLast) {
227 AliHLTUInt32_t id=GetClusterId(decodedClusterCnt);
228 const AliHLTTPCClusterMCLabel* pMC=GetMCLabel(id);
229 if (fpClusterMerger && fpClusterMerger->CheckCandidate(slice, partition, rawCluster)) {
230 fpClusterMerger->AddCandidate(slice, partition, id, rawCluster, pMC);
232 c.Next(slice, partition);
233 c.SetPadRow(rawCluster.GetPadRow()+rowOffset);
234 c.SetPad(rawCluster.GetPad());
235 c.SetTime(rawCluster.GetTime());
236 c.SetSigmaY2(rawCluster.GetSigmaY2());
237 c.SetSigmaZ2(rawCluster.GetSigmaZ2());
238 c.SetCharge(rawCluster.GetCharge());
239 c.SetQMax(rawCluster.GetQMax());
240 if (pMC) c.SetMC(pMC);
246 parameterId=pInflater->NextParameter();
247 if (parameterId==AliHLTTPCDefinitions::kSigmaY2 && isSinglePad==1) {
248 // skip sigmaY for single pad clusters in format version 1
249 parameterId=pInflater->NextParameter();
251 rawCluster.SetSigmaY2(0.);
254 pInflater->Pad8Bits();
256 if (pInflater->InputBit(bit)) {
257 HLTWarning("format error of compressed clusters, there is more data than expected");
259 pInflater->CloseBitDataInput();
260 int mergedClusterCnt=0;
261 if (fpClusterMerger) {
262 mergedClusterCnt=fpClusterMerger->Merge();
264 if (mergedClusterCnt>=0) {
265 for (AliHLTTPCHWClusterMerger::iterator i=fpClusterMerger->begin();
266 i!=fpClusterMerger->end(); i++) {
267 c.Next((*i).GetSlice(), (*i).GetPartition());
268 const AliHLTTPCRawCluster& mergedCluster=(*i).GetCluster();
269 const AliHLTTPCClusterMCLabel& mc=(*i).MCLabel();
270 c.SetPadRow(mergedCluster.GetPadRow()+rowOffset);
271 c.SetPad(mergedCluster.GetPad());
272 c.SetTime(mergedCluster.GetTime());
273 c.SetSigmaY2(mergedCluster.GetSigmaY2());
274 c.SetSigmaZ2(mergedCluster.GetSigmaZ2());
275 c.SetCharge(mergedCluster.GetCharge());
276 c.SetQMax(mergedCluster.GetQMax());
282 iResult=mergedClusterCnt;
284 HLTDebug("copied %d cluster(s) from merger, %d merged, specification 0x%08x", remainingCnt, mergedClusterCnt, specification);
285 fpClusterMerger->Clear();
287 if (iResult>=0 && nofClusters!=outClusterCnt+mergedClusterCnt) {
289 HLTError("error reading compressed cluster format of block 0x%08x: expected %d, read %d cluster(s), merged %d cluster(s)", specification, nofClusters, outClusterCnt, mergedClusterCnt);
292 if (iResult<0) return iResult;
293 return outClusterCnt;
297 int AliHLTTPCDataCompressionDecoder::ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t /*specification*/)
299 // read cluster data from the track model data block
301 int dataOffset=sizeof(AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock);
302 if (!pData || dataSize<dataOffset) return -EINVAL;
304 const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock* trackModelBlock=reinterpret_cast<const AliHLTTPCDataCompressionComponent::AliHLTTPCTrackModelBlock*>(pData);
305 if (trackModelBlock->fVersion!=1) {
306 HLTError("unknown version %d", trackModelBlock->fVersion);
309 if (!fpDataInflaterTrack)
310 fpDataInflaterTrack=CreateInflater(trackModelBlock->fDeflaterMode, 2);
312 fpDataInflaterTrack->Clear();
313 if (!fpDataInflaterTrack) {
314 HLTError("failed to create the data inflater for mode %d", trackModelBlock->fDeflaterMode);
317 int nofTracks=trackModelBlock->fTrackCount;
318 dataOffset+=trackModelBlock->fGlobalParameterCnt*sizeof(trackModelBlock->fGlobalParameters);
319 if (dataSize<dataOffset) {
320 HLTError("inconsistent data block, size %d, expecting at least %d to read AliHLTTPCTrackModelBlock with %d global parameters", dataSize, dataOffset, trackModelBlock->fGlobalParameterCnt);
324 float driftTimeFactorA=0.;
325 float driftTimeOffsetA=0.;
326 float driftTimeFactorC=0.;
327 float driftTimeOffsetC=0.;
329 AliHLTUInt32_t parameterIndex=0;
330 switch (trackModelBlock->fGlobalParameterCnt) {
332 bz =trackModelBlock->fGlobalParameters[parameterIndex++];
333 driftTimeFactorA=trackModelBlock->fGlobalParameters[parameterIndex++];
334 driftTimeOffsetA=trackModelBlock->fGlobalParameters[parameterIndex++];
335 driftTimeFactorC=trackModelBlock->fGlobalParameters[parameterIndex++];
336 driftTimeOffsetC=trackModelBlock->fGlobalParameters[parameterIndex++];
339 HLTError("unknown version of global parameters %d", trackModelBlock->fGlobalParameterCnt);
343 if (parameterIndex!=trackModelBlock->fGlobalParameterCnt) {
344 HLTError("internal error, size of parameter array has changed without providing all values");
348 for (int trackno=0; trackno<nofTracks; trackno++) {
349 AliHLTTPCTrackGeometry trackpoints;
350 trackpoints.InitDriftTimeTransformation(driftTimeFactorA, driftTimeOffsetA, driftTimeFactorC, driftTimeOffsetC);
351 AliHLTUInt32_t clusterBlockSize=0;
352 if ((iResult=trackpoints.Read(pData+dataOffset, dataSize-dataOffset, bz, clusterBlockSize))<0) {
356 if (dataSize-dataOffset<(int)clusterBlockSize) {
357 HLTError("to little data in buffer to read cluster block of size %d for track no %d", clusterBlockSize, trackno);
360 if ((iResult=fpDataInflaterTrack->InitBitDataInput(pData+dataOffset, clusterBlockSize))<0) {
363 if ((iResult=ReadTrackClustersCompressed(c, fpDataInflaterTrack, &trackpoints))<0) {
364 HLTError("reading of associated clusters failed for track %d", trackno);
367 fpDataInflaterTrack->Pad8Bits();
369 if (fpDataInflaterTrack->InputBit(bit)) {
370 HLTWarning("format error of compressed clusters, there is more data than expected");
372 fpDataInflaterTrack->CloseBitDataInput();
373 dataOffset+=clusterBlockSize;
380 int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDataInflater* pInflater, AliHLTTPCTrackGeometry* pTrackPoints)
385 if (!pInflater || !pTrackPoints) return -EINVAL;
387 if ((iResult= InitTrackModelClusterClusterDecoding())<0)
390 const vector<AliHLTTrackGeometry::AliHLTTrackPoint>& rawTrackPoints=pTrackPoints->GetRawPoints();
391 vector<AliHLTTrackGeometry::AliHLTTrackPoint>::const_iterator currentTrackPoint=rawTrackPoints.begin();
393 bool bReadSuccess=true;
394 AliHLTUInt32_t clusterCountBitLength=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kClusterCount].fBitLength;
395 //unsigned long dataPosition=pInflater->GetCurrentByteInputPosition();
396 for (unsigned row=0; row<159 && bReadSuccess; row++) {
397 AliHLTUInt8_t haveClusters=0;
398 // 1 bit for clusters on that padrow
399 bReadSuccess=bReadSuccess && pInflater->InputBit(haveClusters);
400 if (!haveClusters) continue;
403 if (currentTrackPoint==rawTrackPoints.end()) {
404 if (bEscape || rawTrackPoints.begin()==rawTrackPoints.end()) break;
405 currentTrackPoint=rawTrackPoints.begin();
408 if (AliHLTTPCTransform::GetFirstRow(AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId())) +
409 AliHLTTPCSpacePointData::GetNumber(currentTrackPoint->GetId()) == row) {
414 if (currentTrackPoint==rawTrackPoints.end()) {
415 HLTError("decoding error, can not find track point on row %d", row);
418 AliHLTUInt8_t slice = AliHLTTPCSpacePointData::GetSlice(currentTrackPoint->GetId());
419 AliHLTUInt8_t partition = AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId());
420 AliHLTUInt8_t nofClusters=0;
421 bReadSuccess=bReadSuccess && pInflater->InputBits(nofClusters, clusterCountBitLength);
422 if (!bReadSuccess) break;
423 HLTDebug("slice %02d partition %d row %03d: %d cluster(s)", slice, partition, row, nofClusters);
425 static const AliHLTTPCDefinitions::AliClusterParameterId_t kParameterIdMapping[] = {
426 AliHLTTPCDefinitions::kResidualPad,
427 AliHLTTPCDefinitions::kResidualTime,
428 AliHLTTPCDefinitions::kSigmaY2,
429 AliHLTTPCDefinitions::kSigmaZ2,
430 AliHLTTPCDefinitions::kCharge,
431 AliHLTTPCDefinitions::kQMax,
436 AliHLTUInt64_t value=0;
437 AliHLTUInt32_t length=0;
438 bool bNextCluster=true;
439 while (bReadSuccess && inClusterCnt<nofClusters && pInflater->NextValue(value, length)) {
441 // switch to next cluster
442 c.Next(slice, partition);
446 const AliHLTTPCDefinitions::AliClusterParameter& parameter
447 =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[kParameterIdMapping[parameterId]];
449 if (parameter.fBitLength!=(int)length) {
450 HLTError("decode error: expecting length %d for parameter %s, but got %d",
451 parameter.fBitLength, parameter.fName, length);
455 static float deltapad=0.;
456 static float deltatime=0.;
457 bool lastParameter=false;
458 switch (kParameterIdMapping[parameterId]) {
459 case AliHLTTPCDefinitions::kResidualPad:
461 AliHLTUInt8_t sign=0;
462 bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
463 deltapad=((float)value)*(sign?-1.:1.)/parameter.fScale;
464 AliHLTUInt64_t trackpad64=0;
465 double trackpad=currentTrackPoint->GetU();
466 trackpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
467 if (currentTrackPoint->GetU()>0.) trackpad64=(AliHLTUInt64_t)round(trackpad);
469 value=trackpad64-value;
473 float pad=((float)value)/parameter.fScale;
474 c.SetPad(pad+PadShift());
477 case AliHLTTPCDefinitions::kResidualTime:
479 AliHLTUInt8_t sign=0;
480 bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
481 deltatime=((float)value)*(sign?-1.:1.)/parameter.fScale;
482 AliHLTUInt64_t tracktime64=0;
483 double tracktime=currentTrackPoint->GetV();
484 tracktime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
485 if (currentTrackPoint->GetV()>0.) tracktime64=(AliHLTUInt64_t)round(tracktime);
487 value=tracktime64-value;
491 float time=((float)value)/parameter.fScale;
495 case AliHLTTPCDefinitions::kSigmaY2:
496 {float sigmaY2=value; sigmaY2/=parameter.fScale; c.SetSigmaY2(sigmaY2); break;}
497 case AliHLTTPCDefinitions::kSigmaZ2:
498 {float sigmaZ2=value; sigmaZ2/=parameter.fScale; c.SetSigmaZ2(sigmaZ2); break;}
499 case AliHLTTPCDefinitions::kCharge:
500 {c.SetCharge(value); break;}
501 case AliHLTTPCDefinitions::kQMax:
502 {c.SetQMax(value); lastParameter=true; break;}
505 HLTError("parameter %d not expected", kParameterIdMapping[parameterId]);
509 // switch to next cluster
510 // cout << " row " << setfill(' ') << setw(3) << fixed << right << c.GetRow()
511 // << " pad " << setfill(' ') << setw(7) << fixed << right << setprecision (4) << c.GetPad()
512 // << " dpad " << setfill(' ') << setw(7) << fixed << right << setprecision (4) << deltapad
513 // << " time " << setfill(' ') << setw(7) << fixed << right << setprecision (4) << c.GetTimeBin()
514 // << " dtime " << setfill(' ') << setw(7) << fixed << right << setprecision (4) << deltatime
515 // << " charge " << setfill(' ') << setw(5) << fixed << right << setprecision (0) << c.GetQ()
516 // << " qmax " << setfill(' ') << setw(4) << fixed << right << setprecision (0) << c.GetMax()
524 if (iResult>=0 && nofClusters!=inClusterCnt) {
526 HLTError("error reading track model compressed cluster format of track: expected %d, read only %d cluster(s)", nofClusters, inClusterCnt);
535 int AliHLTTPCDataCompressionDecoder::ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification)
537 // read raw cluster data
538 if (!pData) return -EINVAL;
539 if (dataSize<sizeof(AliHLTTPCRawClusterData)) return -ENODATA;
540 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pData);
541 Int_t nCount = (Int_t) clusterData->fCount;
542 if (clusterData->fVersion!=0) {
543 int iResult=ReadRemainingClustersCompressed(c, pData, dataSize, specification);
544 if (iResult>=0 && fVerbosity>0) {
545 HLTInfo("extracted %d cluster(s) from block 0x%08x", iResult, specification);
549 if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != dataSize) return -EBADF;
550 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
551 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
553 const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
554 for (int i=0; i<nCount; i++) {
555 c.Next(slice, partition);
556 c.SetPadRow(clusters[i].GetPadRow());
557 c.SetPad(clusters[i].GetPad()+PadShift());
558 c.SetTime(clusters[i].GetTime());
559 c.SetSigmaY2(clusters[i].GetSigmaY2());
560 c.SetSigmaZ2(clusters[i].GetSigmaZ2());
561 c.SetCharge(clusters[i].GetCharge());
562 c.SetQMax(clusters[i].GetQMax());