6463134720a03d7b9edcee5d4acd63667daf4c6e
[u/mrichter/AliRoot.git] / HLT / TPCLib / comp / AliHLTTPCDataCompressionComponent.cxx
1 // $Id$
2 //**************************************************************************
3 //* This file is property of and copyright by the                          * 
4 //* ALICE Experiment at CERN, All rights reserved.                         *
5 //*                                                                        *
6 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
7 //*                  for The ALICE HLT Project.                            *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 /// @file   AliHLTTPCDataCompressionComponent.cxx
19 /// @author Matthias Richter
20 /// @date   2011-08-08
21 /// @brief  TPC component for data compression
22 ///
23
24 #include "AliHLTTPCDataCompressionComponent.h"
25 #include "AliHLTTPCDefinitions.h"
26 #include "AliHLTTPCDataCompressionDescriptor.h"
27 #include "AliHLTTPCRawClustersDescriptor.h"
28 #include "AliHLTTPCTrackGeometry.h"
29 #include "AliHLTTPCSpacePointContainer.h"
30 #include "AliHLTTPCRawSpacePointContainer.h"
31 #include "AliHLTGlobalBarrelTrack.h"
32 #include "AliHLTComponentBenchmark.h"
33 #include "AliHLTDataDeflaterSimple.h"
34 #include "AliHLTDataDeflaterHuffman.h"
35 #include "AliHLTTPCTransform.h"
36 #include "AliHLTTPCClusterMCData.h"
37 #include "AliHLTTPCClusterTransformation.h"
38 #include "AliHLTErrorGuard.h"
39 #include "AliRawDataHeader.h"
40 #include "AliCDBManager.h"
41 #include "AliCDBPath.h"
42 #include "AliCDBId.h"
43 #include "AliCDBMetaData.h"
44 #include "AliCDBEntry.h"
45 #include "TH1F.h"
46 #include "TFile.h"
47 #include <memory>
48
49 ClassImp(AliHLTTPCDataCompressionComponent)
50
51 AliHLTTPCDataCompressionComponent::AliHLTTPCDataCompressionComponent()
52   : AliHLTProcessor()
53   , fMode(kCompressionModeNone)
54   , fDeflaterMode(kDeflaterModeNone)
55   , fVerificationMode(0)
56   , fMaxDeltaPad(AliHLTTPCDefinitions::GetMaxClusterDeltaPad())
57   , fMaxDeltaTime(AliHLTTPCDefinitions::GetMaxClusterDeltaTime())
58   , fRawInputClusters(NULL)
59   , fInputClusters(NULL)
60   , fTrackGrid(NULL)
61   , fSpacePointGrid(NULL)
62   , fpDataDeflater(NULL)
63   , fHistoCompFactor(NULL)
64   , fHistoResidualPad(NULL)
65   , fHistoResidualTime(NULL)
66   , fHistoClustersOnTracks(NULL)
67   , fHistoClusterRatio(NULL)
68   , fHistoTrackClusterRatio(NULL)
69   , fHistogramFile()
70   , fTrainingTableOutput()
71   , fpBenchmark(NULL)
72   , fpWrittenAssociatedClusterIds(NULL)
73   , fDriftTimeFactorA(1.)
74   , fDriftTimeOffsetA(0.)
75   , fDriftTimeFactorC(1.)
76   , fDriftTimeOffsetC(0.)
77   , fVerbosity(0)
78 {
79 }
80
81 AliHLTTPCDataCompressionComponent::~AliHLTTPCDataCompressionComponent()
82 {
83   /// destructor
84   if (fpWrittenAssociatedClusterIds) delete fpWrittenAssociatedClusterIds;
85 }
86
87
88 const char* AliHLTTPCDataCompressionComponent::GetComponentID()
89 {
90   /// inherited from AliHLTComponent: id of the component
91   return "TPCDataCompressor";
92 }
93
94
95 void AliHLTTPCDataCompressionComponent::GetInputDataTypes( AliHLTComponentDataTypeList& tgtList)
96 {
97   /// inherited from AliHLTComponent: list of data types in the vector reference
98   tgtList.clear();
99   tgtList.push_back(AliHLTTPCDefinitions::RawClustersDataType());
100   tgtList.push_back(AliHLTTPCDefinitions::RawClustersDescriptorDataType());
101   tgtList.push_back(AliHLTTPCDefinitions::ClustersDataType());
102   tgtList.push_back(kAliHLTDataTypeTrack|kAliHLTDataOriginTPC);
103 }
104
105 AliHLTComponentDataType AliHLTTPCDataCompressionComponent::GetOutputDataType()
106 {
107   /// inherited from AliHLTComponent: output data type of the component.
108   return kAliHLTMultipleDataType;
109 }
110
111 int AliHLTTPCDataCompressionComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
112 {
113   /// inherited from AliHLTComponent: multiple output data types of the component.
114   tgtList.clear();
115   tgtList.push_back(AliHLTTPCDefinitions::DataCompressionDescriptorDataType());
116   tgtList.push_back(AliHLTTPCDefinitions::RawClustersDataType());
117   tgtList.push_back(AliHLTTPCDefinitions::RemainingClustersCompressedDataType());
118   tgtList.push_back(AliHLTTPCDefinitions::RemainingClusterIdsDataType());
119   tgtList.push_back(AliHLTTPCDefinitions::ClusterTracksCompressedDataType());
120   tgtList.push_back(AliHLTTPCDefinitions::ClusterIdTracksDataType());
121   return tgtList.size();
122 }
123
124 void AliHLTTPCDataCompressionComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
125 {
126   /// inherited from AliHLTComponent: output data size estimator
127   constBase=0;
128   inputMultiplier=1.;  // there should not be more data than input
129   inputMultiplier+=.3; // slightly more data when using the old HWCF data with 20 Byte and raw clusters 22 Byte
130   if (fpWrittenAssociatedClusterIds) inputMultiplier+=.3; // space for optional cluster id array
131 }
132
133 AliHLTComponent* AliHLTTPCDataCompressionComponent::Spawn()
134 {
135   /// inherited from AliHLTComponent: spawn function.
136   return new AliHLTTPCDataCompressionComponent;
137 }
138
139 void AliHLTTPCDataCompressionComponent::GetOCDBObjectDescription(TMap* const targetMap)
140 {
141   /// Get a list of OCDB object needed for the particular component
142   if (!targetMap) return;
143
144   targetMap->Add(new TObjString("HLT/ConfigTPC/TPCDataCompressor"),
145                  new TObjString("component arguments"));
146   if (fDeflaterMode==kDeflaterModeHuffman) {
147     targetMap->Add(new TObjString("HLT/ConfigTPC/TPCDataCompressorHuffmanTables"),
148                    new TObjString("huffman tables for deflater mode 'huffman'"));
149   }
150 }
151
152 int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData& /*evtData*/, 
153                                                 const AliHLTComponentBlockData* /*inputBlocks*/, 
154                                                 AliHLTComponentTriggerData& /*trigData*/,
155                                                 AliHLTUInt8_t* outputPtr,
156                                                 AliHLTUInt32_t& size,
157                                                 AliHLTComponentBlockDataList& outputBlocks )
158 {
159   /// inherited from AliHLTProcessor: data processing
160   int iResult=0;
161   AliHLTUInt32_t capacity=size;
162   size=0;
163
164   if (!IsDataEvent()) return 0;
165
166   if (!fRawInputClusters) {
167     return -ENODEV;
168   }
169
170   if (GetBenchmarkInstance()) {
171     GetBenchmarkInstance()->StartNewEvent();
172     GetBenchmarkInstance()->Start(0);
173   }
174
175   // Process an event
176
177   // Loop over all input blocks in the event
178   bool bHaveMC=(GetFirstInputBlock(AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC))!=NULL;
179   if ((bHaveMC || fVerificationMode>0) && fpWrittenAssociatedClusterIds==NULL) {
180     fpWrittenAssociatedClusterIds=new vector<AliHLTUInt32_t>;
181   }
182
183   const AliHLTComponentBlockData* pDesc=NULL;
184
185   AliHLTUInt8_t minSlice=0xFF, maxSlice=0xFF, minPatch=0xFF, maxPatch=0xFF;
186   AliHLTUInt32_t inputRawClusterSize=0;
187   AliHLTUInt32_t outputDataSize=0;
188   int allClusters=0;
189   int associatedClusters=0;
190   float bz=GetBz();
191
192   /// input track array
193   vector<AliHLTGlobalBarrelTrack> inputTrackArray;
194
195   if (GetBenchmarkInstance()) {
196     GetBenchmarkInstance()->Start(2);
197   }
198
199   bool isInputPresent = kFALSE;
200
201   // transformed clusters
202   // the transformed clusters have not been used yet
203   if (false) { // FIXME: condition to be adjusted
204     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::fgkClustersDataType);
205          pDesc!=NULL; pDesc=GetNextInputBlock()) {
206       if (GetBenchmarkInstance()) {
207         GetBenchmarkInstance()->AddInput(pDesc->fSize);
208       }
209       isInputPresent = kTRUE;
210       AliHLTUInt8_t slice = 0;
211       AliHLTUInt8_t patch = 0;
212       slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
213       patch = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
214       if ( minSlice==0xFF || slice<minSlice )   minSlice = slice;
215       if ( maxSlice==0xFF || slice>maxSlice )   maxSlice = slice;
216       if ( minPatch==0xFF || patch<minPatch )   minPatch = patch;
217       if ( maxPatch==0xFF || patch>maxPatch )   maxPatch = patch;
218       if (fInputClusters) {
219         fInputClusters->AddInputBlock(pDesc);
220       }
221     }
222     if (GetBenchmarkInstance()) {
223       GetBenchmarkInstance()->Stop(2);
224       GetBenchmarkInstance()->Start(3);
225     }
226   }
227
228   vector<int> trackindexmap; // stores index for every track id
229
230   // track data input
231   if (fMode==kCompressionModeV1TrackModel || fMode==kCompressionModeV2TrackModel) {
232     for (pDesc=GetFirstInputBlock(kAliHLTDataTypeTrack|kAliHLTDataOriginTPC);
233          pDesc!=NULL; pDesc=GetNextInputBlock()) {
234       if (GetBenchmarkInstance()) {
235         GetBenchmarkInstance()->AddInput(pDesc->fSize);
236       }
237       AliHLTUInt8_t slice = 0;
238       AliHLTUInt8_t patch = 0;
239       slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
240       patch = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
241       if ( minSlice==0xFF || slice<minSlice )   minSlice = slice;
242       if ( maxSlice==0xFF || slice>maxSlice )   maxSlice = slice;
243       if ( minPatch==0xFF || patch<minPatch )   minPatch = patch;
244       if ( maxPatch==0xFF || patch>maxPatch )   maxPatch = patch;
245       const AliHLTTracksData* pTracks=reinterpret_cast<const AliHLTTracksData*>(pDesc->fPtr);
246       if ((iResult=AliHLTGlobalBarrelTrack::ConvertTrackDataArray(pTracks, pDesc->fSize, inputTrackArray))<0) {
247         return iResult;
248       }
249       trackindexmap.resize(inputTrackArray.size(), -1);
250     }
251   }
252
253   if (GetBenchmarkInstance()) {
254     GetBenchmarkInstance()->Stop(3);
255     GetBenchmarkInstance()->Start(4);
256   }
257
258   // processing
259   int trackindex=0;
260   for (vector<AliHLTGlobalBarrelTrack>::iterator track=inputTrackArray.begin();
261        track!=inputTrackArray.end();
262        track++, trackindex++) {
263     int trackID=track->GetID();
264     if (trackID<0) {
265       // FIXME: error guard
266       HLTError("invalid track ID");
267       continue;
268     }
269     if (trackID>=(int)trackindexmap.size())
270       trackindexmap.resize(trackID+1, -1);
271     trackindexmap[trackID]=trackindex;
272
273     if (fVerbosity>0) {
274       UInt_t nofPoints=track->GetNumberOfPoints();
275       const UInt_t* points=track->GetPoints();
276       for (unsigned i=0; i<nofPoints; i++) {
277         int slice=AliHLTTPCSpacePointData::GetSlice(points[i]);
278         int partition=AliHLTTPCSpacePointData::GetPatch(points[i]);
279         int number=AliHLTTPCSpacePointData::GetNumber(points[i]);
280         HLTInfo("track %d point %d id 0x%08x slice %d partition %d number %d", track->GetID(), i, points[i], slice, partition, number);
281       }
282     }
283
284     AliHLTTPCTrackGeometry* trackpoints=new AliHLTTPCTrackGeometry;
285     if (!trackpoints) continue;
286     HLTDebug("track %d id %d:", trackindex, trackID);
287
288     // in order to avoid rounding errors the track points are
289     // calculated in exactly the same way as in the decoding
290     // Thats why the track instance can not be used directly
291     // but a new instance is created from the values in the
292     // storage format.
293     // think about moving that to some common code used by
294     // both compression and decoding
295     AliHLTExternalTrackParam param;
296     memset(&param, 0, sizeof(param));    
297     float alpha=track->GetAlpha();
298     while (alpha<0.) alpha+=TMath::TwoPi();
299     while (alpha>TMath::TwoPi()) alpha-=TMath::TwoPi();
300     AliHLTUInt8_t tSlice=AliHLTUInt8_t(9*alpha/TMath::Pi());
301     param.fAlpha   =( tSlice + 0.5 ) * TMath::Pi() / 9.0;
302     if (param.fAlpha>TMath::TwoPi()) param.fAlpha-=TMath::TwoPi();
303     param.fX       = track->GetX();
304     param.fY       = track->GetY();
305     param.fZ       = track->GetZ();
306     param.fSinPsi  = track->GetSnp();
307     param.fTgl     = track->GetTgl();
308     param.fq1Pt    = track->GetSigned1Pt();
309     AliHLTGlobalBarrelTrack ctrack(param);
310     ctrack.CalculateHelixParams(bz);
311     trackpoints->InitDriftTimeTransformation(fDriftTimeFactorA, fDriftTimeOffsetA, fDriftTimeFactorC, fDriftTimeOffsetC);
312     trackpoints->SetTrackId(trackID);
313     trackpoints->CalculateTrackPoints(ctrack);
314     trackpoints->RegisterTrackPoints(fTrackGrid);
315     track->SetTrackGeometry(trackpoints);
316   }
317
318   for (vector<AliHLTGlobalBarrelTrack>::const_iterator track=inputTrackArray.begin();
319        track!=inputTrackArray.end();
320        track++) {
321     AliHLTTrackGeometry* trackpoints=track->GetTrackGeometry();
322     if (!trackpoints) continue;
323     trackpoints->FillTrackPoints(fTrackGrid);
324   }
325   if (fVerbosity>0) {
326     fTrackGrid->Print();
327   }
328
329   if (GetBenchmarkInstance()) {
330     GetBenchmarkInstance()->Stop(4);
331     GetBenchmarkInstance()->Start(5);
332   }
333
334   // loop over raw cluster blocks, assign to tracks and write
335   // unassigned clusters
336   for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::fgkRawClustersDataType);
337        pDesc!=NULL; pDesc=GetNextInputBlock()) {    
338     if (GetBenchmarkInstance()) {
339       GetBenchmarkInstance()->Start(1);
340       GetBenchmarkInstance()->AddInput(pDesc->fSize);
341     }
342     isInputPresent = kTRUE;
343     AliHLTUInt8_t slice = 0;
344     AliHLTUInt8_t patch = 0;
345     slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
346     patch = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
347     if ( minSlice==0xFF || slice<minSlice )     minSlice = slice;
348     if ( maxSlice==0xFF || slice>maxSlice )     maxSlice = slice;
349     if ( minPatch==0xFF || patch<minPatch )     minPatch = patch;
350     if ( maxPatch==0xFF || patch>maxPatch )     maxPatch = patch;
351     inputRawClusterSize+=pDesc->fSize;
352
353     // add the data and populate the index grid
354     fRawInputClusters->AddInputBlock(pDesc);
355     fRawInputClusters->PopulateAccessGrid(fSpacePointGrid, pDesc->fSpecification);
356     if (fVerbosity>0 && fSpacePointGrid->GetNumberOfSpacePoints()>0) {
357       HLTInfo("index grid slice %d partition %d", slice, patch);
358       fSpacePointGrid->Print();
359       for (AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid::iterator& cl=fSpacePointGrid->begin();
360            cl!=fSpacePointGrid->end(); cl++) {
361         AliHLTUInt32_t id=cl.Data().fId;
362         float row=fRawInputClusters->GetX(id);
363         float pad=fRawInputClusters->GetY(id);
364         float time=fRawInputClusters->GetZ(id);
365         HLTInfo("    cluster id 0x%08x: row %f  pad %f  time %f", id, row, pad, time);
366       }
367     }
368     if (GetBenchmarkInstance()) {
369       GetBenchmarkInstance()->Stop(1);
370       GetBenchmarkInstance()->Start(4);
371     }
372
373     // process the clusters per padrow and check the track grid
374     // for tracks crossing that particular padrow
375     if (GetBenchmarkInstance()) {
376       GetBenchmarkInstance()->Stop(4);
377       GetBenchmarkInstance()->Start(5);
378     }
379     allClusters+=fSpacePointGrid->GetNumberOfSpacePoints();
380     iResult=ProcessTrackClusters(&inputTrackArray[0], inputTrackArray.size(), fTrackGrid, trackindexmap, fSpacePointGrid, fRawInputClusters, slice, patch);
381     int assignedInThisPartition=0;
382     if (iResult>=0) {
383       assignedInThisPartition=iResult;
384       associatedClusters+=iResult;
385     }
386     iResult=ProcessRemainingClusters(&inputTrackArray[0], inputTrackArray.size(), fTrackGrid, trackindexmap, fSpacePointGrid, fRawInputClusters, slice, patch);
387     if (iResult>=0) {
388       if (fSpacePointGrid->GetNumberOfSpacePoints()>0) {
389         if (fVerbosity>0) HLTInfo("associated %d (%d) of %d clusters in slice %d partition %d", iResult+assignedInThisPartition, assignedInThisPartition, fSpacePointGrid->GetNumberOfSpacePoints(), slice, patch);
390       }
391       associatedClusters+=iResult;
392     }
393
394     // write all remaining clusters not yet assigned to tracks
395     // the index grid is used to write sorted in padrow
396     // FIXME: decoder index instead of data specification to be used
397     // use an external access grid to reduce allocated memory
398     // set to NULL after writing the clusters
399     const char* writeoptions="";
400     if (fpWrittenAssociatedClusterIds) {
401       writeoptions="write-cluster-ids";
402     }
403     fRawInputClusters->SetSpacePointPropertyGrid(pDesc->fSpecification, fSpacePointGrid);
404     iResult=fRawInputClusters->Write(outputPtr+size, capacity-size, outputBlocks, fpDataDeflater, writeoptions);
405     fRawInputClusters->SetSpacePointPropertyGrid(pDesc->fSpecification, NULL);
406     if (iResult>=0) {
407       size+=iResult;
408       outputDataSize+=iResult;
409       // the size of the optional cluster id array must be subtracted
410       if (fpWrittenAssociatedClusterIds && outputBlocks.size()>0 &&
411           outputBlocks.back().fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType()) {
412         outputDataSize-=outputBlocks.back().fSize;
413       }
414       if (GetBenchmarkInstance()) GetBenchmarkInstance()->AddOutput(iResult);
415     }
416     if (GetBenchmarkInstance()) {
417       GetBenchmarkInstance()->Stop(5);
418     }
419
420     fSpacePointGrid->Clear();
421   }
422   if (fHistoClusterRatio && allClusters>0) {
423     if (fVerbosity>0) HLTInfo("associated %d of %d clusters to tracks", associatedClusters, allClusters);
424     float ratio=associatedClusters; ratio/=allClusters;
425     fHistoClusterRatio->Fill(ratio);
426   }
427
428   // output of track model clusters
429   if (iResult>=0) do {
430     AliHLTUInt32_t tracksBufferOffset=sizeof(AliHLTTPCTrackModelBlock);
431     if (capacity-size<tracksBufferOffset) {
432       iResult=-ENOSPC;
433       break;
434     }
435     if (fpWrittenAssociatedClusterIds) fpWrittenAssociatedClusterIds->clear();
436     AliHLTTPCTrackModelBlock* trackModelBlock=reinterpret_cast<AliHLTTPCTrackModelBlock*>(outputPtr+size);
437     trackModelBlock->fVersion=1;
438     trackModelBlock->fDeflaterMode=fpDataDeflater?fpDataDeflater->GetDeflaterVersion():0;
439     trackModelBlock->fTrackCount=inputTrackArray.size();
440     trackModelBlock->fClusterCount=0;
441     trackModelBlock->fGlobalParameterCnt=5;
442     tracksBufferOffset+=trackModelBlock->fGlobalParameterCnt*sizeof(trackModelBlock->fGlobalParameters);
443     if (capacity-size<tracksBufferOffset) {
444       iResult=-ENOSPC;
445       break;
446     }
447
448     AliHLTUInt32_t parameterIndex=0;
449     trackModelBlock->fGlobalParameters[parameterIndex++]=bz;
450     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeFactorA;
451     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeOffsetA;
452     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeFactorC;
453     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeOffsetC;
454     if (parameterIndex!=trackModelBlock->fGlobalParameterCnt) {
455       HLTError("internal error, size of parameter array has changed without providing all values");
456       iResult=-EFAULT;
457       break;
458     }
459
460     if (trackindexmap.size()>0) {// condition for track model compression
461     iResult=WriteTrackClusters(inputTrackArray, fRawInputClusters, fpDataDeflater, outputPtr+size+tracksBufferOffset, capacity-size-tracksBufferOffset);
462     if (iResult>=0) {
463       AliHLTComponent_BlockData bd;
464       FillBlockData(bd);
465       bd.fOffset        = size;
466       bd.fSize          = tracksBufferOffset+iResult;
467       bd.fDataType      = AliHLTTPCDefinitions::ClusterTracksCompressedDataType();
468       bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(minSlice, maxSlice, minPatch, maxPatch);
469       outputBlocks.push_back(bd);
470       size += bd.fSize;
471       outputDataSize+=bd.fSize;
472       HLTBenchmark("track data block of %d tracks: size %d", inputTrackArray.size(), bd.fSize);
473
474       if (fpWrittenAssociatedClusterIds && fpWrittenAssociatedClusterIds->size()>0) {
475         AliHLTComponent::FillBlockData(bd);
476         bd.fOffset        = size;
477         bd.fSize        = fpWrittenAssociatedClusterIds->size()*sizeof(vector<AliHLTUInt32_t>::value_type);
478         if (capacity-size>bd.fSize) {
479           memcpy(outputPtr+bd.fOffset, &(*fpWrittenAssociatedClusterIds)[0], bd.fSize);
480           bd.fDataType    = AliHLTTPCDefinitions::ClusterIdTracksDataType();
481           bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(minSlice, maxSlice, minPatch, maxPatch);
482           outputBlocks.push_back(bd);    
483           size += bd.fSize;
484         } else {
485           iResult=-ENOSPC;
486         }
487         
488         fpWrittenAssociatedClusterIds->clear();
489       }
490     }
491     }
492   } while (0);
493
494   fRawInputClusters->Clear();
495
496   // Write header block 
497   
498   if( isInputPresent ){
499     pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::RawClustersDescriptorDataType() );
500     if( pDesc ){
501       const AliHLTTPCRawClustersDescriptor &clDesc = *reinterpret_cast<const AliHLTTPCRawClustersDescriptor*>(pDesc->fPtr);
502       if( !clDesc.CheckSize( pDesc->fSize ) ){
503         HLTError("Corrupted cluster descriptor");
504       }
505      
506       AliHLTComponent_BlockData bd;
507       FillBlockData(bd);
508       bd.fOffset        = size;
509       bd.fSize          = sizeof(AliHLTTPCDataCompressionDescriptor);
510       bd.fDataType      = AliHLTTPCDefinitions::DataCompressionDescriptorDataType();
511       if( capacity < size + bd.fSize ){
512         iResult = -ENOSPC;
513         return iResult;
514       }
515
516       AliHLTTPCDataCompressionDescriptor compDesc;
517       compDesc.SetMergedClustersFlag( clDesc.GetMergedClustersFlag() );
518       *(AliHLTTPCDataCompressionDescriptor*)(outputPtr + bd.fOffset ) = compDesc; 
519
520       outputBlocks.push_back(bd);
521       size += bd.fSize;
522       outputDataSize+=bd.fSize;
523       //HLTBenchmark("header data block of size %d", bd.fSize);
524     }
525   }
526
527   float compressionFactor=(float)inputRawClusterSize;
528   if ((outputDataSize)>0) compressionFactor/=outputDataSize;
529   else compressionFactor=0.;
530   if (fHistoCompFactor) fHistoCompFactor->Fill(compressionFactor);
531
532   if (GetBenchmarkInstance() && allClusters>0) {
533     GetBenchmarkInstance()->Stop(0);
534     if (fDeflaterMode!=kDeflaterModeHuffmanTrainer) {
535       HLTBenchmark("%s - compression factor %.2f", GetBenchmarkInstance()->GetStatistics(), compressionFactor);
536     } else {
537       HLTBenchmark("%s", GetBenchmarkInstance()->GetStatistics());
538     }
539   }
540
541   if (fInputClusters) {
542     fInputClusters->Clear();
543   }
544   if (fRawInputClusters) {
545     fRawInputClusters->Clear();
546   }
547   if (fTrackGrid) {
548     fTrackGrid->Clear();
549   }
550
551   // forward MC labels
552   for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC);
553        pDesc!=NULL; pDesc=GetNextInputBlock()) {
554     outputBlocks.push_back(*pDesc);
555   }
556
557   return iResult;
558 }
559
560 int AliHLTTPCDataCompressionComponent::ProcessTrackClusters(AliHLTGlobalBarrelTrack* pTracks, unsigned nofTracks,
561                                                             AliHLTTrackGeometry::AliHLTTrackGrid* pTrackIndex,
562                                                             const vector<int>& trackIndexMap,
563                                                             AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pClusterIndex,
564                                                             AliHLTSpacePointContainer* pClusters,
565                                                             int slice, int partition) const
566 {
567   // process to assigned track clusters
568   int iResult=0;
569   int assignedClusters=0;
570   if (!pTracks || nofTracks==0) return 0;
571
572   vector<int> processedTracks(nofTracks, -1);
573   for (AliHLTTrackGeometry::AliHLTTrackGrid::iterator& trackId=pTrackIndex->begin(slice, partition, -1);
574        trackId!=pTrackIndex->end(); trackId++) {
575     if (trackId.Data()>=trackIndexMap.size()) {
576       HLTError("can not find track id %d in index map of size %d", trackId.Data(), trackIndexMap.size());
577       continue;
578     }
579     int trackindex=trackIndexMap[trackId.Data()];
580     if (trackindex<0 || trackindex>=(int)nofTracks) {
581       HLTError("invalid index %d found for track id %d", trackindex, trackId.Data());
582       continue;
583     }
584     if (processedTracks[trackindex]>0) continue;
585     processedTracks[trackindex]=1;
586     AliHLTGlobalBarrelTrack& track=pTracks[trackindex];
587     if (!track.GetTrackGeometry()) {
588       HLTError("can not find track geometry for track %d", trackId.Data());
589       continue;
590     }
591     AliHLTTPCTrackGeometry* pTrackPoints=dynamic_cast<AliHLTTPCTrackGeometry*>(track.GetTrackGeometry());
592     if (!pTrackPoints) {
593       HLTError("invalid track geometry type for track %d, expecting AliHLTTPCTrackGeometry", trackId.Data());
594       continue; 
595     }
596
597     UInt_t nofTrackPoints=track.GetNumberOfPoints();
598     const UInt_t* trackPoints=track.GetPoints();
599     for (unsigned i=0; i<nofTrackPoints; i++) {
600       const AliHLTUInt32_t& clusterId=trackPoints[i];
601       if (AliHLTTPCSpacePointData::GetSlice(clusterId)!=(unsigned)slice ||
602           AliHLTTPCSpacePointData::GetPatch(clusterId)!=(unsigned)partition) {
603         // not in the current partition;
604         continue;
605       }
606
607       int clusterrow=(int)pClusters->GetX(clusterId);
608       AliHLTUInt32_t pointId=AliHLTTPCSpacePointData::GetID(slice, partition, clusterrow);
609       AliHLTTrackGeometry::AliHLTTrackPoint* point=pTrackPoints->GetRawTrackPoint(pointId);
610       if (!point) {
611         //HLTError("can not find track point slice %d partition %d padrow %d (0x%08x) of track %d", slice, partition, clusterrow, pointId, trackId.Data());
612         continue;
613       }
614       float pad=point->GetU();
615       float time=point->GetV();
616
617       iResult=FindCellClusters(trackId.Data(), clusterrow, pad, time, pClusterIndex, pClusters, point, clusterId);
618       if (iResult>0) assignedClusters+=iResult;
619     }
620   }
621   return assignedClusters;
622 }
623
624 int AliHLTTPCDataCompressionComponent::ProcessRemainingClusters(AliHLTGlobalBarrelTrack* pTracks, unsigned nofTracks,
625                                                                 AliHLTTrackGeometry::AliHLTTrackGrid* pTrackIndex,
626                                                                 const vector<int>& trackIndexMap,
627                                                                 AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pClusterIndex,
628                                                                 AliHLTSpacePointContainer* pClusters,
629                                                                 int slice, int partition) const
630 {
631   // assign remaining clusters to tracks
632   int iResult=0;
633   int associatedClusters=0;
634   if (!pTracks || nofTracks==0) return 0;
635
636   for (int padrow=0; padrow<AliHLTTPCTransform::GetNRows(partition); padrow++) {
637     for (AliHLTTrackGeometry::AliHLTTrackGrid::iterator& trackId=pTrackIndex->begin(slice, partition, padrow);
638          trackId!=pTrackIndex->end(); trackId++) {
639       if (trackId.Data()>=trackIndexMap.size()) {
640         HLTError("can not find track id %d in index map of size %d", trackId.Data(), trackIndexMap.size());
641         continue;
642       }
643       int trackindex=trackIndexMap[trackId.Data()];
644       if (trackindex<0 || trackindex>=(int)nofTracks) {
645         HLTError("invalid index %d found for track id %d", trackindex, trackId.Data());
646         continue;
647       }
648       AliHLTGlobalBarrelTrack& track=pTracks[trackindex];
649       if (!track.GetTrackGeometry()) {
650         HLTError("can not find track geometry for track %d", trackId.Data());
651         continue;
652       }
653       AliHLTTPCTrackGeometry* pTrackPoints=dynamic_cast<AliHLTTPCTrackGeometry*>(track.GetTrackGeometry());
654       if (!pTrackPoints) {
655         HLTError("invalid track geometry type for track %d, expecting AliHLTTPCTrackGeometry", trackId.Data());
656         continue;       
657       }
658       AliHLTUInt32_t pointId=AliHLTTPCSpacePointData::GetID(slice, partition, padrow);
659       AliHLTTrackGeometry::AliHLTTrackPoint* point=pTrackPoints->GetRawTrackPoint(pointId);
660       if (!point) {
661         //HLTError("can not find track point slice %d partition %d padrow %d (0x%08x) of track %d", slice, partition, padrow, pointId, trackId.Data());
662         continue;
663       }
664       float pad=point->GetU();
665       float time=point->GetV();
666
667       iResult=FindCellClusters(trackId.Data(), padrow, pad, time, pClusterIndex, pClusters, point);
668       if (iResult>0) associatedClusters+=iResult;
669       if (fVerbosity>0) {
670         HLTInfo("trackpoint track %d slice %d partition %d padrow %d: %.3f \t%.3f - associated %d", track.GetID(), slice, partition, padrow, pad, time, iResult);
671       }
672     }
673   }
674   if (iResult<0) return iResult;
675   return associatedClusters;
676 }
677
678 int AliHLTTPCDataCompressionComponent::FindCellClusters(int trackId, int padrow, float pad, float time,
679                                                         AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pClusterIndex,
680                                                         AliHLTSpacePointContainer* pClusters,
681                                                         AliHLTTrackGeometry::AliHLTTrackPoint* pTrackPoint,
682                                                         AliHLTUInt32_t clusterId) const
683 {
684   // check index cell for entries and assign to track
685   int count=0;
686   // search a 4x4 matrix out of the 9x9 matrix around the cell addressed by
687   // pad and time
688   int rowindex=pClusterIndex->GetXIndex((float)padrow);
689   int padstartindex=pClusterIndex->GetYIndex(pad);
690   int timestartindex=pClusterIndex->GetZIndex(time);
691   int cellindex=pClusterIndex->Index(rowindex, padstartindex, timestartindex);
692   float centerpad=pClusterIndex->GetCenterY(cellindex);
693   float centertime=pClusterIndex->GetCenterZ(cellindex);
694   if ((TMath::Abs(centerpad-pad)>fMaxDeltaPad && pad>0.) ||
695       (TMath::Abs(centertime-time)>fMaxDeltaTime && time>0.)) {
696     ALIHLTERRORGUARD(20, "invalid pad center calculation, please check dimensions if dimensions of index grid match the maximum possible deviation");
697   }
698
699   int paddirection=1;
700   int timedirection=1;
701   if (centerpad>pad) paddirection=-1;
702   if (centertime>time) timedirection=-1;
703   for (int padcount=0, padindex=padstartindex; padcount<2; padcount++, padindex+=paddirection) {
704     if (padindex<0) continue;
705     if (padindex>=pClusterIndex->GetDimensionY()) break;
706     for (int timecount=0, timeindex=timestartindex; timecount<2; timecount++, timeindex+=timedirection) {
707       if (timeindex<0) continue;
708       if (timeindex>=pClusterIndex->GetDimensionZ()) break;
709       cellindex=pClusterIndex->Index(rowindex, padindex, timeindex);
710       float cellpad=pClusterIndex->GetCenterY(cellindex);
711       float celltime=pClusterIndex->GetCenterZ(cellindex);
712       for (AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid::iterator& cl=pClusterIndex->begin((float)padrow, cellpad, celltime);
713            cl!=pClusterIndex->end(); cl++) {
714         if (cl.Data().fTrackId>=0) continue;
715         if (clusterId!=(~(AliHLTUInt32_t)0) && clusterId!=cl.Data().fId) continue;
716         if (TMath::Abs(padrow-pClusters->GetX(cl.Data().fId))>=1.) {
717           HLTError("cluster 0x%08x: mismatch on padrow: trackpoint %d  cluster %f", cl.Data().fId, padrow, pClusters->GetX(cl.Data().fId));
718           continue;
719         }
720         float clusterpad=pClusters->GetY(cl.Data().fId);
721         float clustertime=pClusters->GetZ(cl.Data().fId);
722         if (TMath::Abs(clusterpad-pad)<fMaxDeltaPad &&
723             TMath::Abs(clustertime-time)<fMaxDeltaTime) {
724           // add this cluster to the track point and mark in the index grid
725           cl.Data().fTrackId=trackId;
726           pTrackPoint->AddAssociatedSpacePoint(cl.Data().fId, clusterpad-pad, clustertime-time);
727           count++;
728         }
729         if (clusterId!=(~(AliHLTUInt32_t)0)) break;
730       }
731     }
732   }
733   return count;
734 }
735
736 int AliHLTTPCDataCompressionComponent::WriteTrackClusters(const vector<AliHLTGlobalBarrelTrack>& tracks,
737                                                           AliHLTSpacePointContainer* pSpacePoints,
738                                                           AliHLTDataDeflater* pDeflater,
739                                                           AliHLTUInt8_t* outputPtr,
740                                                           AliHLTUInt32_t capacity) const
741 {
742   // write the track data block including all associated clusters
743   AliHLTUInt32_t size=0;
744   for (vector<AliHLTGlobalBarrelTrack>::const_iterator track=tracks.begin();
745        track!=tracks.end();
746        track++) {
747     if (!track->GetTrackGeometry()) {
748       HLTError("can not find track geometry for track %d", track->GetID());
749       return -EBADF;
750     }
751     AliHLTTPCTrackGeometry* pTrackPoints=dynamic_cast<AliHLTTPCTrackGeometry*>(track->GetTrackGeometry());
752     if (!pTrackPoints) {
753       HLTError("invalid track geometry type for track %d, expecting AliHLTTPCTrackGeometry", track->GetID());
754       return -EBADF;
755     }
756
757     int result=pTrackPoints->Write(*track, pSpacePoints, pDeflater, outputPtr+size, capacity-size, fpWrittenAssociatedClusterIds);
758     if (result<0) return result;
759     size+=result;
760
761     UInt_t nofTrackPoints=track->GetNumberOfPoints();
762     const UInt_t* trackPoints=track->GetPoints();
763
764     int assignedPoints=0;
765     int assignedTrackPoints=0;
766     const vector<AliHLTTrackGeometry::AliHLTTrackPoint>& rawPoints=pTrackPoints->GetRawPoints();
767     for (vector<AliHLTTrackGeometry::AliHLTTrackPoint>::const_iterator point=rawPoints.begin();
768          point!=rawPoints.end(); point++) {
769       const vector<AliHLTTrackGeometry::AliHLTTrackSpacepoint>& spacePoints=point->GetSpacepoints();
770       for (vector<AliHLTTrackGeometry::AliHLTTrackSpacepoint>::const_iterator spacePoint=spacePoints.begin();
771            spacePoint!=spacePoints.end(); spacePoint++) {
772         float dpad=spacePoint->GetResidual(0);
773         float dtime=spacePoint->GetResidual(1);
774         if (dpad>-1000 && dtime>-1000 && fHistoResidualPad && fHistoResidualTime) {
775           fHistoResidualPad->Fill(dpad);
776           fHistoResidualTime->Fill(dtime);
777         }
778         assignedPoints++;
779         for (unsigned i=0; i<nofTrackPoints; i++) {
780           if (trackPoints[i]==spacePoint->fId) {
781             assignedTrackPoints++;
782             break;
783           }
784         }
785       }
786     }
787     if (fHistoClustersOnTracks) {
788       fHistoClustersOnTracks->Fill(assignedPoints);
789     }
790     if (fHistoTrackClusterRatio && nofTrackPoints>0) {
791       float ratio=assignedTrackPoints; ratio/=nofTrackPoints;
792       fHistoTrackClusterRatio->Fill(ratio);
793     }
794   }
795   return size;
796 }
797
798 int AliHLTTPCDataCompressionComponent::DoInit( int argc, const char** argv )
799 {
800   /// inherited from AliHLTComponent: component initialisation and argument scan.
801   int iResult=0;
802
803   // component configuration
804   //Stage 1: default initialization.
805   //Default values.
806
807   //Stage 2: OCDB.
808   TString cdbPath("HLT/ConfigTPC/");
809   cdbPath += GetComponentID();
810   //
811   iResult = ConfigureFromCDBTObjString(cdbPath);
812   if (iResult < 0) 
813     return iResult;
814
815   //Stage 3: command line arguments.
816   int mode=fMode; // just a backup for the info message below
817   int deflaterMode=fDeflaterMode;
818   if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
819     return iResult;
820
821   if (mode!=fMode || deflaterMode!=fDeflaterMode) {
822     HLTInfo("configured from command line: mode %d, deflater mode %d", fMode, fDeflaterMode);
823   }
824
825   std::auto_ptr<AliHLTComponentBenchmark> benchmark(new AliHLTComponentBenchmark);
826   if (benchmark.get()) {
827     benchmark->SetTimer(0,"total");
828     benchmark->SetTimer(1,"rawclusterinput");
829     benchmark->SetTimer(2,"clusterinput");
830     benchmark->SetTimer(3,"trackinput");
831     benchmark->SetTimer(4,"processing");
832     benchmark->SetTimer(5,"output");
833   } else {
834     return -ENOMEM;
835   }
836
837   unsigned spacePointContainerMode=0;
838   if (fMode==kCompressionModeV1TrackModel || fMode==kCompressionModeV2TrackModel) {
839     // initialize map data for cluster access in the track association loop
840     spacePointContainerMode|=AliHLTTPCRawSpacePointContainer::kModeCreateMap;
841   }
842   if (fMode==kCompressionModeV2 || fMode==kCompressionModeV2TrackModel) {
843     // optimized storage format: differential pad and time storage
844     spacePointContainerMode|=AliHLTTPCRawSpacePointContainer::kModeDifferentialPadTime;
845   }
846   std::auto_ptr<AliHLTTPCRawSpacePointContainer> rawInputClusters(new AliHLTTPCRawSpacePointContainer(spacePointContainerMode));
847   std::auto_ptr<AliHLTTPCSpacePointContainer> inputClusters(new AliHLTTPCSpacePointContainer);
848
849   std::auto_ptr<TH1F> histoCompFactor(new TH1F("CompressionFactor",
850                                                "HLT TPC data compression factor",
851                                                100, 0., 10.));
852   std::auto_ptr<TH1F> histoResidualPad(new TH1F("PadResidual",
853                                                 "HLT TPC pad residual",
854                                                 100, -fMaxDeltaPad, fMaxDeltaPad));
855   std::auto_ptr<TH1F> histoResidualTime(new TH1F("TimeResidual",
856                                                  "HLT TPC time residual",
857                                                  100, -fMaxDeltaTime, fMaxDeltaTime));
858   std::auto_ptr<TH1F> histoClustersOnTracks(new TH1F("ClustersOnTracks",
859                                                  "Clusters in track model compression",
860                                                  200, 0., 600));
861   std::auto_ptr<TH1F> histoClusterRatio(new TH1F("ClusterRatio",
862                                                  "Fraction of clusters in track model compression",
863                                                  100, 0., 1.));
864   std::auto_ptr<TH1F> histoTrackClusterRatio(new TH1F("UsedTrackClusters",
865                                                  "Fraction of track clusters in track model compression",
866                                                  100, 0., 1.));
867
868   // track grid: 36 slices, each 6 partitions with max 33 rows
869   fTrackGrid=new AliHLTTrackGeometry::AliHLTTrackGrid(36, 1, 6, 1, 33, 1, 20000);
870   fSpacePointGrid=AliHLTTPCRawSpacePointContainer::AllocateIndexGrid();
871
872   if (!rawInputClusters.get() ||
873       !inputClusters.get() ||
874       !fTrackGrid ||
875       !fSpacePointGrid) {
876     if (fTrackGrid) delete fTrackGrid; fTrackGrid=NULL;
877     if (fSpacePointGrid) delete fSpacePointGrid; fSpacePointGrid=NULL;
878     return -ENOMEM;
879   }
880
881   if (fDeflaterMode>0 && (iResult=InitDeflater(fDeflaterMode))<0)
882     return iResult;
883
884   fpBenchmark=benchmark.release();
885   fRawInputClusters=rawInputClusters.release();
886   fInputClusters=inputClusters.release();
887
888   // initialize the histograms if stored at the end
889   // condition might be extended
890   if (!fHistogramFile.IsNull()) {
891     fHistoCompFactor=histoCompFactor.release();
892     fHistoResidualPad=histoResidualPad.release();
893     fHistoResidualTime=histoResidualTime.release();
894     fHistoClustersOnTracks=histoClustersOnTracks.release();
895     fHistoClusterRatio=histoClusterRatio.release();
896     fHistoTrackClusterRatio=histoTrackClusterRatio.release();
897   }
898
899   if (iResult>=0 && (iResult=InitDriftTimeTransformation())<0) return iResult;
900
901   return iResult;
902 }
903
904 int AliHLTTPCDataCompressionComponent::InitDeflater(int mode)
905 {
906   /// init the data deflater
907   int iResult=0;
908   if (mode==kDeflaterModeHuffman || mode==kDeflaterModeHuffmanTrainer) {
909     // huffman deflater
910     std::auto_ptr<AliHLTDataDeflaterHuffman> deflater(new AliHLTDataDeflaterHuffman(mode==kDeflaterModeHuffmanTrainer));
911     if (!deflater.get()) return -ENOMEM;
912
913     if (!deflater->IsTrainingMode()) {
914       TString cdbPath("HLT/ConfigTPC/");
915       cdbPath += GetComponentID();
916       cdbPath += "HuffmanTables";
917       TObject* pConf=LoadAndExtractOCDBObject(cdbPath);
918       if (!pConf) return -ENOENT;
919       if (dynamic_cast<TList*>(pConf)==NULL) {
920         HLTError("huffman table configuration object of inconsistent type");
921         return -EINVAL;
922       }
923       iResult=deflater->InitDecoders(dynamic_cast<TList*>(pConf));
924       if (iResult<0) return iResult;
925     }
926     
927     if (!fHistogramFile.IsNull())
928       deflater->EnableStatistics();
929
930     unsigned nofParameters=AliHLTTPCDefinitions::GetNumberOfClusterParameterDefinitions();
931     unsigned p=0;
932     for (; p<nofParameters; p++) {
933       const AliHLTTPCDefinitions::AliClusterParameter& parameter=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[p];
934       // use the pad/time length as reference for the calculation of ratio for residuals
935       unsigned refLength=0;
936       unsigned refLengthPad=0;
937       unsigned refLengthTime=0;
938       if (parameter.fId==AliHLTTPCDefinitions::kPad)               refLengthPad=parameter.fBitLength;
939       else if (parameter.fId==AliHLTTPCDefinitions::kTime)         refLengthTime=parameter.fBitLength;
940       else if (parameter.fId==AliHLTTPCDefinitions::kResidualPad)  refLength=refLengthPad;
941       else if (parameter.fId==AliHLTTPCDefinitions::kResidualTime) refLength=refLengthTime;
942
943       if (deflater->AddParameterDefinition(parameter.fName,
944                                            parameter.fBitLength,
945                                            refLength)!=(int)parameter.fId) {
946         // for performance reason the parameter id is simply used as index in the array of
947         // definitions, the position must match the id
948         HLTFatal("mismatch between parameter id and position in array for parameter %s, rearrange definitions!", parameter.fName);
949         return -EFAULT;
950       }
951     }
952     fpDataDeflater=deflater.release();
953     return 0;
954   }
955   if (mode==kDeflaterModeSimple) {
956     std::auto_ptr<AliHLTDataDeflaterSimple> deflater(new AliHLTDataDeflaterSimple);
957     if (!deflater.get()) return -ENOMEM;
958
959     if (!fHistogramFile.IsNull())
960       deflater->EnableStatistics();
961
962     unsigned nofParameters=AliHLTTPCDefinitions::GetNumberOfClusterParameterDefinitions();
963     unsigned p=0;
964     for (; p<nofParameters; p++) {
965       const AliHLTTPCDefinitions::AliClusterParameter& parameter=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[p];
966       if (deflater->AddParameterDefinition(parameter.fName,
967                                            parameter.fBitLength,
968                                            parameter.fOptional)!=(int)parameter.fId) {
969         // for performance reason the parameter id is simply used as index in the array of
970         // definitions, the position must match the id
971         HLTFatal("mismatch between parameter id and position in array for parameter %s, rearrange definitions!", parameter.fName);
972         return -EFAULT;
973       }
974     }
975     fpDataDeflater=deflater.release();
976     return 0;
977   }
978   HLTError("invalid deflater mode %d, allowed 1=simple 2=huffman", mode);
979   return -EINVAL;
980 }
981
982 int AliHLTTPCDataCompressionComponent::DoDeinit()
983 {
984   /// inherited from AliHLTComponent: component cleanup
985   int iResult=0;
986   if (fpBenchmark) delete fpBenchmark; fpBenchmark=NULL;
987   if (fRawInputClusters) delete fRawInputClusters; fRawInputClusters=NULL;
988   if (fInputClusters) delete fInputClusters; fInputClusters=NULL;
989   if (!fHistogramFile.IsNull()) {
990     TFile out(fHistogramFile, "RECREATE");
991     if (!out.IsZombie()) {
992       out.cd();
993       if (fHistoCompFactor) fHistoCompFactor->Write();
994       if (fHistoResidualPad) fHistoResidualPad->Write();
995       if (fHistoResidualTime) fHistoResidualTime->Write();
996       if (fHistoClusterRatio) fHistoClusterRatio->Write();
997       if (fHistoClustersOnTracks) fHistoClustersOnTracks->Write();
998       if (fHistoTrackClusterRatio) fHistoTrackClusterRatio->Write();
999       out.Close();
1000     }
1001   }
1002   if (fHistoCompFactor) delete fHistoCompFactor;
1003   fHistoCompFactor=NULL;
1004   if (fHistoResidualPad) delete fHistoResidualPad;
1005   fHistoResidualPad=NULL;
1006   if (fHistoResidualTime) delete fHistoResidualTime;
1007   fHistoResidualTime=NULL;
1008   if (fHistoClustersOnTracks) delete fHistoClustersOnTracks;
1009   fHistoClustersOnTracks=NULL;
1010   if (fHistoClusterRatio) delete fHistoClusterRatio;
1011   fHistoClusterRatio=NULL;
1012   if (fHistoTrackClusterRatio) delete fHistoTrackClusterRatio;
1013   fHistoTrackClusterRatio=NULL;
1014
1015   if (fpDataDeflater) {
1016     if (!fHistogramFile.IsNull()) {
1017       TString filename=fHistogramFile;
1018       filename.ReplaceAll(".root", "-deflater.root");
1019       fpDataDeflater->SaveAs(filename);
1020     }
1021     if (fDeflaterMode==kDeflaterModeHuffmanTrainer) {
1022       if (fTrainingTableOutput.IsNull()) {
1023         fTrainingTableOutput=GetComponentID();
1024         fTrainingTableOutput+="-huffman.root";
1025       }
1026       // TODO: currently, the code tables are also calculated in FindObject
1027       // check if a different function is more appropriate
1028       TObject* pConf=fpDataDeflater->FindObject("DeflaterConfiguration");
1029       if (pConf) {
1030         TString cdbEntryPath("HLT/ConfigTPC/");
1031         cdbEntryPath += GetComponentID();
1032         cdbEntryPath += "HuffmanTables";
1033         AliCDBPath cdbPath(cdbEntryPath);
1034         AliCDBId cdbId(cdbPath, AliCDBManager::Instance()->GetRun(), AliCDBRunRange::Infinity(), 0, 0);
1035         AliCDBMetaData* cdbMetaData=new AliCDBMetaData;
1036         cdbMetaData->SetResponsible("ALICE HLT Matthias.Richter@cern.ch");
1037         cdbMetaData->SetComment("Huffman encoder configuration");
1038         AliCDBEntry* entry=new AliCDBEntry(pConf, cdbId, cdbMetaData, kTRUE);
1039
1040         entry->SaveAs(fTrainingTableOutput);
1041         // this is a small memory leak
1042         // seg fault in ROOT object handling if the two objects are deleted
1043         // investigate later
1044         //delete entry;
1045         //delete cdbMetaData;
1046       }
1047     }
1048     delete fpDataDeflater;
1049   }
1050   fpDataDeflater=NULL;
1051
1052
1053   if (fTrackGrid) delete fTrackGrid; fTrackGrid=NULL;
1054   if (fSpacePointGrid) delete fSpacePointGrid; fSpacePointGrid=NULL;
1055
1056   return iResult;
1057 }
1058
1059 int AliHLTTPCDataCompressionComponent::ScanConfigurationArgument(int argc, const char** argv)
1060 {
1061   /// inherited from AliHLTComponent: argument scan
1062   int iResult=0;
1063   if (argc<1) return 0;
1064   int bMissingParam=0;
1065   int i=0;
1066   TString argument=argv[i];
1067
1068   do {
1069     // -mode
1070     if (argument.CompareTo("-mode")==0) {
1071       if ((bMissingParam=(++i>=argc))) break;
1072       TString parameter=argv[i];
1073       if (parameter.IsDigit()) {
1074         fMode=parameter.Atoi();
1075         return 2;
1076       } else {
1077         HLTError("invalid parameter for argument %s, expecting number instead of %s", argument.Data(), parameter.Data());
1078         return -EPROTO;
1079       }
1080     }
1081
1082     // -deflater-mode
1083     if (argument.CompareTo("-deflater-mode")==0) {
1084       if ((bMissingParam=(++i>=argc))) break;
1085       TString parameter=argv[i];
1086       if (parameter.IsDigit()) {
1087         fDeflaterMode=parameter.Atoi();
1088         return 2;
1089       } else {
1090         HLTError("invalid parameter for argument %s, expecting number instead of %s", argument.Data(), parameter.Data());
1091         return -EPROTO;
1092       }
1093     }
1094
1095     // -histogram-file
1096     if (argument.CompareTo("-histogram-file")==0) {
1097       if ((bMissingParam=(++i>=argc))) break;
1098       fHistogramFile=argv[i++];
1099       return 2;
1100     }
1101     // -save-histogram-table
1102     if (argument.CompareTo("-save-huffman-table")==0) {
1103       if ((bMissingParam=(++i>=argc))) break;
1104       fTrainingTableOutput=argv[i++];
1105       return 2;
1106     }
1107     // -cluster-verification
1108     if (argument.CompareTo("-cluster-verification")==0) {
1109       if ((bMissingParam=(++i>=argc))) break;
1110       TString parameter=argv[i];
1111       if (parameter.IsDigit()) {
1112         fVerificationMode=parameter.Atoi();
1113         return 2;
1114       } else {
1115         HLTError("invalid parameter for argument %s, expecting number instead of %s", argument.Data(), parameter.Data());
1116         return -EPROTO;
1117       }
1118     }
1119   } while (0); // using do-while only to have break available
1120
1121   if (bMissingParam) {
1122     HLTError("missing parameter for argument %s", argument.Data());
1123     iResult=-EPROTO;
1124   }
1125
1126   return iResult;
1127 }
1128
1129 int AliHLTTPCDataCompressionComponent::InitDriftTimeTransformation()
1130 {
1131   /// calculate correction factor and offset for a linear approximation of the
1132   /// drift time transformation, separately for A and C side
1133   int iResult=0;
1134   AliHLTTPCClusterTransformation transform;
1135   if ((iResult=transform.Init( GetBz(), GetTimeStamp()))<0) {
1136     HLTError("failed to init AliHLTTPCClusterTransformation: %d", iResult);
1137     return iResult;
1138   }
1139
1140   if ((iResult=CalculateDriftTimeTransformation(transform, 0, 0, fDriftTimeFactorA, fDriftTimeOffsetA))<0) return iResult;
1141   if (fVerbosity>0) HLTInfo("drift time transformation A side: m=%f n=%f", fDriftTimeFactorA, fDriftTimeOffsetA);
1142   if ((iResult=CalculateDriftTimeTransformation(transform, 18, 0, fDriftTimeFactorC, fDriftTimeOffsetC))<0) return iResult;
1143   if (fVerbosity>0) HLTInfo("drift time transformation C side: m=%f n=%f", fDriftTimeFactorC, fDriftTimeOffsetC);
1144
1145   return 0;
1146 }
1147
1148 int AliHLTTPCDataCompressionComponent::CalculateDriftTimeTransformation(AliHLTTPCClusterTransformation& transform,
1149                                                                         int slice, int padrow,
1150                                                                         float& m, float& n) const
1151 {
1152   /// calculate correction factor and offset for a linear approximation of the
1153   /// drift time transformation by just probing the range of timebins with
1154   /// AliHLTTPCClusterTransformation
1155   const int nofSteps=100;
1156   vector<float> zvalues;
1157
1158   int nofTimebins=AliHLTTPCTransform::GetNTimeBins();
1159   int stepWidth=nofTimebins/nofSteps;
1160   int time=0;
1161   int count=0;
1162   float meanT=0.;
1163   float meanZ=0.;
1164   for (time=0; time<nofTimebins; time+=stepWidth, count++) {
1165     Float_t xyz[3];
1166     transform.Transform(slice, padrow, 0, time, xyz);
1167     zvalues.push_back(xyz[2]);
1168     meanT+=time;
1169     meanZ+=xyz[2];
1170   }
1171   if (count==0) count=1;
1172   meanT/=count;
1173   meanZ/=count;
1174   float sumTZ=.0;
1175   float sumT2=.0;
1176   time=0;
1177   for (vector<float>::const_iterator z=zvalues.begin();
1178        z!=zvalues.end(); z++, time+=stepWidth) {
1179     sumTZ+=(time-meanT)*((*z)-meanZ);
1180     sumT2+=(time-meanT)*(time-meanT);
1181   }
1182   m=sumTZ/sumT2;
1183   n=meanZ-m*meanT;
1184
1185   return 0;
1186 }