memory leak in the unpacking of compressed HLT TPC clusters fixed
[u/mrichter/AliRoot.git] / HLT / TPCLib / comp / AliHLTTPCDataCompressionDecoder.h
CommitLineData
f899e060 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 */
30class 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>
8a3426fd 39 int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion=0);
f899e060 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
a4fad4be 47 template<typename T>
48 int ReadClustersPartition(T& c, const AliHLTUInt8_t* pData, unsigned dataSize, AliHLTUInt32_t specification);
49
f899e060 50 AliHLTDataInflater* CreateInflater(int deflater, int mode) const;
51
52 protected:
53 private:
54 ClassDef(AliHLTTPCDataCompressionDecoder, 0)
55};
56
57template<typename T>
58int 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
8a3426fd 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 }
6dc3748f 79 std::auto_ptr<AliHLTDataInflater> inflater(CreateInflater(deflaterMode, 1));
80 if (!inflater.get()) return -ENODEV;
f899e060 81
82 if ((iResult=inflater->InitBitDataInput(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
83 size-sizeof(AliHLTTPCRawClusterData)))<0) {
84 return iResult;
85 }
86
6dc3748f 87 iResult=ReadRemainingClustersCompressed(c, inflater.get(), nCount, specification, formatVersion);
f899e060 88
89 return iResult;
90}
91
92template<typename T>
8a3426fd 93int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion)
f899e060 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
bf1a9c81 105 int rowOffset=AliHLTTPCTransform::GetFirstRow(partition);
f899e060 106
8a3426fd 107 int parameterId=pInflater->NextParameter();
108 if (parameterId<0) return parameterId;
f899e060 109 int outClusterCnt=0;
110 AliHLTUInt64_t value=0;
111 AliHLTUInt32_t length=0;
112 AliHLTUInt32_t lastPadRow=0;
8a3426fd 113 AliHLTUInt64_t lastPad64=0;
114 AliHLTUInt64_t lastTime64=0;
115 AliHLTUInt8_t isSinglePad=0;
116 AliHLTUInt8_t sign=0;
bf1a9c81 117 bool bNextCluster=true;
8a3426fd 118 bool bReadSuccess=true;
119 while (outClusterCnt<nofClusters && bReadSuccess && pInflater->NextValue(value, length)) {
bf1a9c81 120 if (bNextCluster) {
121 // switch to next cluster
122 c.Next(slice, partition);
123 bNextCluster=false;
124 }
f899e060 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;}
8a3426fd 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 }
f899e060 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) {
bf1a9c81 180 bNextCluster=true;
f899e060 181 outClusterCnt++;
f899e060 182 }
8a3426fd 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 }
f899e060 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
205template<typename T>
206int 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
284template<typename T>
285int 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 }
88c75640 320 AliHLTUInt8_t slice = AliHLTTPCSpacePointData::GetSlice(currentTrackPoint->GetId());
321 AliHLTUInt8_t partition = AliHLTTPCSpacePointData::GetPatch(currentTrackPoint->GetId());
f899e060 322 AliHLTUInt8_t nofClusters=0;
323 bReadSuccess=bReadSuccess && pInflater->InputBits(nofClusters, clusterCountBitLength);
324 if (!bReadSuccess) break;
88c75640 325 HLTDebug("slice %02d partition %d row %03d: %d cluster(s)", slice, partition, row, nofClusters);
f899e060 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;
bf1a9c81 340 bool bNextCluster=true;
f899e060 341 while (bReadSuccess && inClusterCnt<nofClusters && pInflater->NextValue(value, length)) {
bf1a9c81 342 if (bNextCluster) {
343 // switch to next cluster
344 c.Next(slice, partition);
8a3426fd 345 c.SetPadRow(row);
bf1a9c81 346 bNextCluster=false;
347 }
f899e060 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);
8a3426fd 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;
f899e060 376 c.SetPad(pad);
377 break;
378 }
379 case AliHLTTPCDefinitions::kResidualTime:
380 {
381 AliHLTUInt8_t sign=0;
382 bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
8a3426fd 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);
f899e060 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
f899e060 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;
bf1a9c81 420 bNextCluster=true;
f899e060 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}
a4fad4be 435
436template<typename T>
437int 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}
f899e060 464#endif