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