ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / TPCLib / comp / AliHLTTPCDataCompressionMonitorComponent.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   AliHLTTPCDataCompressionMonitorComponent.cxx
19 /// @author Matthias Richter
20 /// @date   2011-09-12
21 /// @brief  TPC component for monitoring of data compression
22 ///
23
24 #include "AliHLTTPCDataCompressionMonitorComponent.h"
25 #include "AliHLTTPCDataCompressionComponent.h"
26 #include "AliHLTTPCDataCompressionDecoder.h"
27 #include "AliHLTTPCDefinitions.h"
28 #include "AliHLTTPCHWCFData.h"
29 #include "AliHLTTPCDefinitions.h"
30 #include "AliHLTTPCClusterDataFormat.h"
31 #include "AliHLTTPCRawCluster.h"
32 #include "AliHLTTPCTransform.h"
33 #include "AliHLTTPCTrackGeometry.h"
34 #include "AliHLTTPCHWCFSpacePointContainer.h"
35 #include "AliHLTErrorGuard.h"
36 #include "AliHLTComponentBenchmark.h"
37 #include "AliHLTCDHWrapper.h"
38 #include "AliTPCclusterMI.h"
39 #include "AliTPCROC.h"
40 #include "TH1I.h"
41 #include "TH1F.h"
42 #include "TH1D.h"
43 #include "TH2I.h"
44 #include "TH2F.h"
45 #include "TH2D.h"
46 #include "TH3I.h"
47 #include "TH3F.h"
48 #include "TH3D.h"
49 #include "TProfile.h"
50 #include "TFile.h"
51 #include "TObjArray.h"
52 #include "TList.h"
53 #include <memory>
54
55 ClassImp(AliHLTTPCDataCompressionMonitorComponent)
56
57 AliHLTTPCDataCompressionMonitorComponent::AliHLTTPCDataCompressionMonitorComponent()
58   : AliHLTProcessor()
59   , fpBenchmark(NULL)
60   , fpDecoder(NULL)
61   , fpHWClusterDecoder(NULL)
62   , fHistoHWCFDataSize(NULL)
63   , fHistoHWCFReductionFactor(NULL)
64   , fHistoTotalReductionFactor(NULL)
65   , fHistoNofClusters(NULL)
66   , fHistoNofClustersReductionFactor(NULL)
67   , fHistogramFile()
68   , fMonitoringContainer(NULL)
69   , fVerbosity(0)
70   , fFlags(0)
71   , fPublishingMode(kPublishSeparate)
72 {
73 }
74
75 AliHLTTPCDataCompressionMonitorComponent::~AliHLTTPCDataCompressionMonitorComponent()
76 {
77   /// destructor
78 }
79
80
81 const char* AliHLTTPCDataCompressionMonitorComponent::GetComponentID()
82 {
83   /// inherited from AliHLTComponent: id of the component
84   return "TPCDataCompressorMonitor";
85 }
86
87
88 void AliHLTTPCDataCompressionMonitorComponent::GetInputDataTypes( AliHLTComponentDataTypeList& tgtList)
89 {
90   /// inherited from AliHLTComponent: list of data types in the vector reference
91   tgtList.clear();
92   tgtList.push_back(AliHLTTPCDefinitions::fgkHWClustersDataType);
93   tgtList.push_back(kAliHLTDataTypeTrack|kAliHLTDataOriginTPC);
94   tgtList.push_back(AliHLTTPCDefinitions::fgkRawClustersDataType);
95   tgtList.push_back(AliHLTTPCDefinitions::RemainingClustersCompressedDataType());
96   tgtList.push_back(AliHLTTPCDefinitions::ClusterTracksCompressedDataType());  
97 }
98
99 AliHLTComponentDataType AliHLTTPCDataCompressionMonitorComponent::GetOutputDataType()
100 {
101   /// inherited from AliHLTComponent: output data type of the component.
102   return kAliHLTMultipleDataType;
103 }
104
105 int AliHLTTPCDataCompressionMonitorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
106 {
107   /// inherited from AliHLTComponent: multiple output data types of the component.
108   tgtList.clear();
109   tgtList.push_back(kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
110   return tgtList.size();
111 }
112
113 void AliHLTTPCDataCompressionMonitorComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
114 {
115   /// inherited from AliHLTComponent: output data size estimator
116   constBase=10000000;
117   inputMultiplier=1.0;
118 }
119
120 AliHLTComponent* AliHLTTPCDataCompressionMonitorComponent::Spawn()
121 {
122   /// inherited from AliHLTComponent: spawn function.
123   return new AliHLTTPCDataCompressionMonitorComponent;
124 }
125
126 int AliHLTTPCDataCompressionMonitorComponent::DoEvent( const AliHLTComponentEventData& /*evtData*/, 
127                                                        const AliHLTComponentBlockData* /*inputBlocks*/, 
128                                                        AliHLTComponentTriggerData& /*trigData*/,
129                                                        AliHLTUInt8_t* /*outputPtr*/,
130                                                        AliHLTUInt32_t& /*size*/,
131                                                        AliHLTComponentBlockDataList& /*outputBlocks*/ )
132 {
133   /// inherited from AliHLTProcessor: data processing
134   int iResult=0;
135
136   AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
137   if (!IsDataEvent(&eventType)) {
138     if (eventType==gkAliEventTypeEndOfRun && fPublishingMode!=kPublishOff) {
139       iResult=Publish(fPublishingMode);
140     }
141     return iResult;
142   }
143
144   if (GetBenchmarkInstance()) {
145     GetBenchmarkInstance()->StartNewEvent();
146     GetBenchmarkInstance()->Start(0);
147   }
148
149   const AliHLTComponentBlockData* pDesc=NULL;
150   unsigned rawDataSize=0;
151   unsigned rawEventSizeFromRCUtrailer=0;
152   unsigned hwclustersDataSize=0;
153   unsigned nofClusters=0;
154   unsigned compDataSize=0; 
155   
156   // check size of TPC raw data
157   for (pDesc=GetFirstInputBlock(kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC);
158        pDesc!=NULL; pDesc=GetNextInputBlock()) {
159     fFlags|=kHaveRawData;
160     rawDataSize+=pDesc->fSize;
161   }
162
163   // check size of HWCF data and add to the MonitoringContainer
164   for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::fgkHWClustersDataType);
165        pDesc!=NULL; pDesc=GetNextInputBlock()) {
166     fFlags|=kHaveHWClusters;
167     // FIXME: the decoding can now be handled via the data container
168     AliHLTCDHWrapper header(pDesc->fPtr);
169     if (pDesc->fSize<=header.GetHeaderSize()) continue;
170     if (fpHWClusterDecoder) {
171       hwclustersDataSize+=pDesc->fSize;
172       AliHLTUInt8_t* pData=reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr);
173       pData+=header.GetHeaderSize();
174       if (fpHWClusterDecoder->Init(pData, pDesc->fSize-header.GetHeaderSize())<0 ||
175           (fpHWClusterDecoder->CheckVersion()<0 && (int)(pDesc->fSize-header.GetHeaderSize())>fpHWClusterDecoder->GetRCUTrailerSize())) {
176         HLTError("data block of type %s corrupted: can not decode format",
177                  AliHLTComponent::DataType2Text(pDesc->fDataType).c_str());
178       } else {
179         nofClusters+=fpHWClusterDecoder->GetNumberOfClusters();
180         if (fpHWClusterDecoder->GetRCUTrailer()) {
181           // first word of the RCU trailer contains the payload size in 32bit words
182           const AliHLTUInt32_t*  pRCUTrailer=reinterpret_cast<const AliHLTUInt32_t*>(fpHWClusterDecoder->GetRCUTrailer());
183           AliHLTUInt32_t payloadSize=(*pRCUTrailer)&0x00ffffff;
184           rawEventSizeFromRCUtrailer+=header.GetHeaderSize()
185             + payloadSize*sizeof(AliHLTUInt32_t)
186             + fpHWClusterDecoder->GetRCUTrailerSize();
187         }
188       }
189     }
190     if (fMonitoringContainer) {
191       fMonitoringContainer->AddRawData(pDesc);
192     }
193   }
194
195   if (fMonitoringContainer && fpDecoder) {
196     if (GetBenchmarkInstance()) {
197       GetBenchmarkInstance()->Start(1);
198     }
199
200     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::RemainingClusterIdsDataType());
201          pDesc!=NULL; pDesc=GetNextInputBlock()) {
202       iResult=fMonitoringContainer->AddClusterIds(pDesc);
203     }
204
205     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::ClusterIdTracksDataType());
206          pDesc!=NULL; pDesc=GetNextInputBlock()) {
207       iResult=fMonitoringContainer->AddClusterIds(pDesc);
208     }
209
210     // read data
211     AliHLTTPCDataCompressionDecoder& decoder=*fpDecoder;
212     decoder.Clear();
213     bool bHaveRawClusters=false;
214     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::RawClustersDataType());
215          pDesc!=NULL; pDesc=GetNextInputBlock()) {
216       // Note: until r51411 and v5-01-Rev-03 the compressed cluster format was sent with data
217       // type {CLUSTRAW,TPC }, the version member indicated the actual type of data
218       // These data do not include the 0.5 shift in pad position, that's wht it has
219       // to be added in the unpacking. This is a very special case, this data type and
220       // data version==1 only occured in the early TPC data compression test runs with
221       // v5-01-Rev-01
222       if (pDesc->fSize<sizeof(AliHLTTPCRawClusterData)) continue;
223       const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pDesc->fPtr);
224       if (!clusterData) continue;
225       if (clusterData->fVersion==1) {
226         // compressed clusters without the pad shift
227         // data type {CLUSTRAW,TPC } with version==1
228         decoder.SetPadShift(0.5);
229       } else {
230         decoder.SetPadShift(0.0);
231       }
232       bHaveRawClusters=true;
233       iResult=decoder.ReadClustersPartition(fMonitoringContainer->BeginRemainingClusterBlock(0, pDesc->fSpecification),
234                                             reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr),
235                                             pDesc->fSize,
236                                             pDesc->fSpecification);
237       if (iResult<0) {
238         HLTError("reading of partition clusters failed with error %d", iResult);
239       }
240     }
241
242     decoder.SetPadShift(0.0);
243
244     if (!bHaveRawClusters) {
245     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::RemainingClustersCompressedDataType());
246          pDesc!=NULL; pDesc=GetNextInputBlock()) {
247       iResult=decoder.ReadClustersPartition(fMonitoringContainer->BeginRemainingClusterBlock(0, pDesc->fSpecification),
248                                             reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr),
249                                             pDesc->fSize,
250                                             pDesc->fSpecification);
251       compDataSize+=pDesc->fSize;
252     }
253
254     for (pDesc=GetFirstInputBlock(AliHLTTPCDefinitions::ClusterTracksCompressedDataType());
255          pDesc!=NULL; pDesc=GetNextInputBlock()) {
256       iResult=decoder.ReadTrackModelClustersCompressed(fMonitoringContainer->BeginTrackModelClusterBlock(0),
257                                                reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr),
258                                                pDesc->fSize,
259                                                pDesc->fSpecification);
260       compDataSize+=pDesc->fSize;
261     }
262     } else {
263       if (GetFirstInputBlock(AliHLTTPCDefinitions::RemainingClustersCompressedDataType()) ||
264           GetFirstInputBlock(AliHLTTPCDefinitions::ClusterTracksCompressedDataType())) {
265         ALIHLTERRORGUARD(5, "conflicting data blocks, monitoring histograms already filled from raw cluster data, ignoring blocks of compressed partition and track clusters");
266       }              
267     }
268     if (GetBenchmarkInstance()) {
269       GetBenchmarkInstance()->Stop(1);
270     }
271
272     fMonitoringContainer->Clear();
273   }
274
275   if ((fFlags&kHaveHWClusters)!=0 && (fFlags&kHaveRawData)!=0) {
276     if (rawDataSize!=rawEventSizeFromRCUtrailer && rawEventSizeFromRCUtrailer>0) {
277       HLTError("got different raw event size from raw data and rcu trailer: raw %d, rcu trailer %d", rawDataSize, rawEventSizeFromRCUtrailer);
278     }
279   }
280   if (rawDataSize==0)
281     rawDataSize=rawEventSizeFromRCUtrailer;
282
283   float hwcfratio=0;
284   float ratio=0;
285   float totalratio=0;
286   if (hwclustersDataSize) {hwcfratio=(float)rawDataSize; hwcfratio/=hwclustersDataSize;}
287   if (compDataSize) {ratio=(float)hwclustersDataSize; ratio/=compDataSize;}
288   if (compDataSize) {totalratio=(float)rawDataSize; totalratio/=compDataSize;}
289   if (fHistoHWCFDataSize)        fHistoHWCFDataSize       ->Fill(rawDataSize/1024, hwclustersDataSize/1024);
290   if (fHistoHWCFReductionFactor) fHistoHWCFReductionFactor->Fill(rawDataSize/1024, hwcfratio);
291   if (fHistoTotalReductionFactor && nofClusters>0)
292     fHistoTotalReductionFactor->Fill(rawDataSize/1024, totalratio);
293   if (fHistoNofClusters)         fHistoNofClusters        ->Fill(rawDataSize/1024, nofClusters);
294   if (fHistoNofClustersReductionFactor && nofClusters>0)
295     fHistoNofClustersReductionFactor ->Fill(nofClusters, ratio);
296   HLTInfo("raw data %d, hwcf data %d, comp data %d, ratio %f, %d clusters, total compression ratio %f\n", rawDataSize, hwclustersDataSize, compDataSize, ratio, nofClusters, totalratio);
297
298   if (iResult>=0 && fPublishingMode!=kPublishOff) {
299     iResult=Publish(fPublishingMode);
300   }
301
302   if (GetBenchmarkInstance()) {
303     GetBenchmarkInstance()->Stop(0);
304     GetBenchmarkInstance()->AddInput(compDataSize);
305     HLTBenchmark("%s", GetBenchmarkInstance()->GetStatistics());
306   }
307
308   return iResult;
309 }
310
311 int AliHLTTPCDataCompressionMonitorComponent::Publish(int mode)
312 {
313   /// publish to output
314   // additional histograms derived from the main ones to publish
315   TObjArray *derivedHistos = new TObjArray();
316   derivedHistos->SetOwner(kTRUE);
317
318   // FIXME: code needs to be optimized, maybe a bit to much new and delete for the
319   // moment, the data type might need adjustment
320   int iResult=0;
321   TObjArray* pArray=mode==kPublishArray?(new TObjArray):NULL;
322   TList* pList=mode==kPublishList?(new TList):NULL;
323   if (mode==kPublishSeparate) {
324     if (fHistoHWCFDataSize)        PushBack(fHistoHWCFDataSize       , kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
325     if (fHistoHWCFReductionFactor) PushBack(fHistoHWCFReductionFactor, kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
326     if (fHistoNofClusters)         PushBack(fHistoNofClusters        , kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
327     if (fHistoNofClustersReductionFactor) PushBack(fHistoNofClustersReductionFactor, kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
328     if (fHistoTotalReductionFactor) PushBack(fHistoTotalReductionFactor, kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
329   } else if (pList) {
330     if (fHistoHWCFDataSize)        pList->Add(fHistoHWCFDataSize->Clone());
331     if (fHistoHWCFReductionFactor) pList->Add(fHistoHWCFReductionFactor->Clone());
332     if (fHistoNofClusters)         pList->Add(fHistoNofClusters->Clone());
333     if (fHistoNofClustersReductionFactor) pList->Add(fHistoNofClustersReductionFactor->Clone());
334     if (fHistoTotalReductionFactor) pList->Add(fHistoTotalReductionFactor->Clone());
335   } else if (pArray) {
336     if (fHistoHWCFDataSize)        pArray->Add(fHistoHWCFDataSize->Clone());
337     if (fHistoHWCFReductionFactor) pArray->Add(fHistoHWCFReductionFactor->Clone());
338     if (fHistoNofClusters)         pArray->Add(fHistoNofClusters->Clone());
339     if (fHistoNofClustersReductionFactor) pArray->Add(fHistoNofClustersReductionFactor->Clone());
340     if (fHistoTotalReductionFactor) pArray->Add(fHistoTotalReductionFactor->Clone());
341   }
342
343
344   if (fMonitoringContainer) {
345     static const char* searchIds[] = {"fHistograms", "fHistograms2D", "fHistograms3D", NULL};
346     const char** searchId=searchIds;
347     while (*searchId && iResult>=0) {
348       const TObject* o=fMonitoringContainer->FindObject(*searchId);
349       if (o) {
350         const TObjArray* histograms=dynamic_cast<const TObjArray*>(o);
351         if (histograms) {
352           for (int i=0; i<histograms->GetEntriesFast() && iResult>=0; i++) {
353             if (!histograms->At(i)) continue;
354             ///
355             TString name=histograms->At(i)->GetName();
356             if( (name.CompareTo(fgkHistogramDefinitions2D[kHistogramQMaxSector].fName)==0) ||
357                 (name.CompareTo(fgkHistogramDefinitions2D[kHistogramSigmaY2Sector].fName)==0) ||
358                 (name.CompareTo(fgkHistogramDefinitions2D[kHistogramSigmaZ2Sector].fName)==0) ){
359               TH2F *h1=(TH2F*)histograms->At(i);
360               TProfile *h2 = (TProfile*)(h1->ProfileX());
361               derivedHistos->Add(h2);
362             }
363             if( name.CompareTo(fgkHistogramDefinitions3D[kHistogramPadrowPadSector].fName)==0) {
364               TH3F *h1=(TH3F*)histograms->At(i);
365               for (int j=1; j<=72; j++) {
366               h1->GetXaxis()->SetRange(j,j);
367               TString histoname = Form("zy_%d",j);
368               TH2F *h2 = (TH2F*)h1->Project3D(histoname.Data());
369               derivedHistos->Add(h2);
370               }
371             }
372             ///
373             if (mode==kPublishSeparate) {
374               iResult=PushBack(histograms->At(i), kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
375             } else if (pList) {
376               pList->Add(histograms->At(i)->Clone());
377             } else if (pArray) {
378               pArray->Add(histograms->At(i)->Clone());
379             }
380           }
381           for (int i=0; i<derivedHistos->GetEntriesFast() && iResult>=0; i++) {
382             if (mode==kPublishSeparate) {
383               iResult=PushBack(derivedHistos->At(i), kAliHLTDataTypeHistogram|kAliHLTDataOriginTPC);
384             } else if (pList) {
385               pList->Add(derivedHistos->At(i)->Clone());
386             } else if (pArray) {
387               pArray->Add(derivedHistos->At(i)->Clone());
388             }       
389           }
390         }
391       } else {
392         HLTError("failed to find object \"%s\"", *searchId);
393       }
394       searchId++;
395     }
396   }
397
398   if (pArray) {
399     iResult=PushBack(pArray, kAliHLTDataTypeTObjArray|kAliHLTDataOriginTPC);
400     pArray->SetOwner(kTRUE);
401     delete pArray;
402     pArray=NULL;
403   }
404   if (pList) {
405     iResult=PushBack(pList, kAliHLTDataTypeTObject|kAliHLTDataOriginTPC);
406     pList->SetOwner(kTRUE);
407     delete pList;
408     pList=NULL;
409   }
410   return iResult;
411 }
412
413 int AliHLTTPCDataCompressionMonitorComponent::DoInit( int argc, const char** argv )
414 {
415   /// inherited from AliHLTComponent: component initialisation and argument scan.
416   int iResult=0;
417
418   // component configuration
419   //Stage 1: default initialization.
420   //Default values.
421   fFlags=0;
422
423   //Stage 2: OCDB.
424   TString cdbPath("HLT/ConfigTPC/");
425   cdbPath += GetComponentID();
426   //
427   // iResult = ConfigureFromCDBTObjString(cdbPath);
428   // if (iResult < 0) 
429   //   return iResult;
430
431   //Stage 3: command line arguments.
432   if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
433     return iResult;
434
435   std::auto_ptr<AliHLTTPCHWCFData> hwClusterDecoder(new AliHLTTPCHWCFData);
436   std::auto_ptr<AliDataContainer> dataContainer(new AliDataContainer);
437
438   std::auto_ptr<TH2I> histoHWCFDataSize(new TH2I("HWCFDataSize",
439                                                  "HW ClusterFinder Size",
440                                                  100, 0., 80000., 100, 0., 80000.));
441   if (histoHWCFDataSize.get()) {
442     TAxis* xaxis=histoHWCFDataSize->GetXaxis();
443     if (xaxis) xaxis->SetTitle("raw data size [kB]");
444     TAxis* yaxis=histoHWCFDataSize->GetYaxis();
445     if (yaxis) yaxis->SetTitle("compressed data size [kb]");
446   }
447
448   std::auto_ptr<TH2I> histoHWCFReductionFactor(new TH2I("HWCFReductionFactor",
449                                                         "Data reduction HW ClusterFinder vs. raw data size",
450                                                         100, 0., 80000., 30, 0., 3.));
451   if (histoHWCFReductionFactor.get()) {
452     TAxis* xaxis=histoHWCFReductionFactor->GetXaxis();
453     if (xaxis) xaxis->SetTitle("raw data size [kB]");
454     TAxis* yaxis=histoHWCFReductionFactor->GetYaxis();
455     if (yaxis) yaxis->SetTitle("reduction factor");
456   }
457
458   std::auto_ptr<TH2I> histoTotalReductionFactor(new TH2I("TotalReductionFactor",
459                                                          "Total reduction Factor vs. raw data size",
460                                                          100, 0., 80000., 100, 0., 10.));
461   if (histoTotalReductionFactor.get()) {
462     TAxis* xaxis=histoTotalReductionFactor->GetXaxis();
463     if (xaxis) xaxis->SetTitle("raw data size [kB]");
464     TAxis* yaxis=histoTotalReductionFactor->GetYaxis();
465     if (yaxis) yaxis->SetTitle("reduction factor");
466   }
467
468   std::auto_ptr<TH2I> histoNofClusters(new TH2I("NofClusters",
469                                                "Number of HLT TPC clusters",
470                                                100, 0., 80000., 500, 0., 3000000.));
471   if (histoNofClusters.get()) {
472     TAxis* xaxis=histoNofClusters->GetXaxis();
473     if (xaxis) xaxis->SetTitle("raw data size [kB]");
474     TAxis* yaxis=histoNofClusters->GetYaxis();
475     if (yaxis) yaxis->SetTitle("N. of clusters");
476   }
477
478   std::auto_ptr<TH2I> histoNofClustersReductionFactor(new TH2I("ReductionFactorVsNofClusters",
479                                                                "Reduction Factor vs. Number of HLT TPC clusters",
480                                                                500, 0., 3000000., 100, 0., 10.));
481   if (histoNofClustersReductionFactor.get()) {
482     TAxis* xaxis=histoNofClustersReductionFactor->GetXaxis();
483     if (xaxis) xaxis->SetTitle("N. of clusters");
484     TAxis* yaxis=histoNofClustersReductionFactor->GetYaxis();
485     if (yaxis) yaxis->SetTitle("reduction factor");
486   }
487
488   std::auto_ptr<AliHLTComponentBenchmark> benchmark(new AliHLTComponentBenchmark);
489   if (benchmark.get()) {
490     benchmark->SetTimer(0,"total");
491     benchmark->SetTimer(1,"clusterdecoding");
492   } else {
493     return -ENOMEM;
494   }
495
496   auto_ptr<AliHLTTPCDataCompressionDecoder> decoder(new AliHLTTPCDataCompressionDecoder);
497   if (!decoder.get()) {
498     return -ENOMEM;
499   }
500
501
502   fHistoHWCFDataSize=histoHWCFDataSize.release();
503   fHistoHWCFReductionFactor=histoHWCFReductionFactor.release();
504   fHistoTotalReductionFactor=histoTotalReductionFactor.release();
505   fHistoNofClusters=histoNofClusters.release();
506   fHistoNofClustersReductionFactor=histoNofClustersReductionFactor.release();
507
508   fpHWClusterDecoder=hwClusterDecoder.release();
509   fMonitoringContainer=dataContainer.release();
510   fpBenchmark=benchmark.release();
511   fpDecoder=decoder.release();
512
513   return iResult;
514 }
515
516 int AliHLTTPCDataCompressionMonitorComponent::DoDeinit()
517 {
518   /// inherited from AliHLTComponent: component cleanup
519   int iResult=0;
520
521   if (fpBenchmark) delete fpBenchmark; fpBenchmark=NULL;
522   if (fpDecoder) delete fpDecoder;
523   fpDecoder=NULL;
524   if (fpHWClusterDecoder) delete fpHWClusterDecoder;
525   fpHWClusterDecoder=NULL;
526
527   if (!fHistogramFile.IsNull()) {
528     TFile out(fHistogramFile, "RECREATE");
529     if (!out.IsZombie()) {
530       out.cd();
531       if (fHistoHWCFDataSize) fHistoHWCFDataSize->Write();
532       if (fHistoHWCFReductionFactor) fHistoHWCFReductionFactor->Write();
533       if (fHistoTotalReductionFactor) fHistoTotalReductionFactor->Write();
534       if (fHistoNofClusters) fHistoNofClusters->Write();
535       if (fHistoNofClustersReductionFactor) fHistoNofClustersReductionFactor->Write();
536       if (fMonitoringContainer) {
537         const TObject* o1=fMonitoringContainer->FindObject("fHistograms");
538         const TObject* o2=fMonitoringContainer->FindObject("fHistograms2D");
539         const TObject* o3=fMonitoringContainer->FindObject("fHistograms3D");
540         if (o1) o1->Write();
541         if (o2) o2->Write();
542         if (o3) o3->Write();
543       }
544       out.Close();
545     }
546   }
547   if (fHistoHWCFDataSize) delete fHistoHWCFDataSize;
548   fHistoHWCFDataSize=NULL;
549   if (fHistoHWCFReductionFactor) delete fHistoHWCFReductionFactor;
550   fHistoHWCFReductionFactor=NULL;
551   if (fHistoTotalReductionFactor) delete fHistoTotalReductionFactor;
552   fHistoTotalReductionFactor=NULL;
553   if (fHistoNofClusters) delete fHistoNofClusters;
554   fHistoNofClusters=NULL;
555   if (fHistoNofClustersReductionFactor) delete fHistoNofClustersReductionFactor;
556   fHistoNofClustersReductionFactor=NULL;
557   if (fMonitoringContainer) {
558     fMonitoringContainer->Clear();
559     delete fMonitoringContainer;
560   }
561   fMonitoringContainer=NULL;
562
563
564   return iResult;
565 }
566
567 int AliHLTTPCDataCompressionMonitorComponent::ScanConfigurationArgument(int argc, const char** argv)
568 {
569   /// inherited from AliHLTComponent: argument scan
570   int iResult=0;
571   if (argc<1) return 0;
572   int bMissingParam=0;
573   int i=0;
574   TString argument=argv[i];
575
576   do {
577     // -histogram-file
578     if (argument.CompareTo("-histogram-file")==0) {
579       if ((bMissingParam=(++i>=argc))) break;
580       fHistogramFile=argv[i++];
581       return i;
582     }
583     // -publishing-mode
584     if (argument.CompareTo("-publishing-mode")==0) {
585       if ((bMissingParam=(++i>=argc))) break;
586       TString option=argv[i++];
587       if (option.CompareTo("off")==0)           fPublishingMode=kPublishOff     ;
588       else if (option.CompareTo("separate")==0) fPublishingMode=kPublishSeparate;
589       else if (option.CompareTo("list")==0)     fPublishingMode=kPublishList    ;
590       else if (option.CompareTo("array")==0)    fPublishingMode=kPublishArray   ;
591       else {
592         HLTError("invalid option \"%s\" for argument \"%s\", expecting 'off', 'separate', 'list', or 'array'", option.Data(), argument.Data());
593         return -EPROTO;
594       }
595       return i;
596     }
597   } while (0); // using do-while only to have break available
598
599   if (bMissingParam) {
600     HLTError("missing parameter for argument %s", argument.Data());
601     iResult=-EPROTO;
602   }
603
604   return iResult;
605 }
606
607 AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::AliDataContainer()
608   : fHistograms(new TObjArray)  
609   , fHistograms2D(new TObjArray)  
610   , fHistograms3D(new TObjArray)    
611   , fHistogramPointers()
612   , fHistogram2DPointers()
613   , fHistogram3DPointers()
614   , fRemainingClusterIds()
615   , fTrackModelClusterIds()
616   , fCurrentClusterIds(NULL)
617   , fRawData(NULL)
618   , fCurrentCluster()
619   , fSector(-1)
620   , fBegin()
621   , fMaxSigmaY2Scaled((0x1<<AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fBitLength)-1)
622   , fMaxSigmaZ2Scaled((0x1<<AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fBitLength)-1)
623 {
624   /// constructor
625   memset(&fCurrentCluster, 0, sizeof(AliHLTTPCRawCluster));
626   if (fHistograms) {
627     fHistograms->SetOwner(kTRUE);
628     fHistogramPointers.resize(kNumberOfHistograms, NULL);
629     for (const AliHistogramDefinition* definition=fgkHistogramDefinitions;
630          definition->fName!=NULL; definition++) {
631       fHistogramPointers[definition->fId]=new TH1D(definition->fName,
632                                                   definition->fTitle,
633                                                   definition->fBins,
634                                                   definition->fLowerBound,
635                                                   definition->fUpperBound
636                                                   );
637       if (fHistogramPointers[definition->fId]) {
638         fHistogramPointers[definition->fId]->SetOption(definition->fDrawOptions);
639       fHistograms->AddAt(fHistogramPointers[definition->fId], definition->fId);
640       }
641     }
642   }
643   ///
644   if (fHistograms2D) {
645     fHistograms2D->SetOwner(kTRUE);
646     fHistogram2DPointers.resize(kNumberOfHistograms2D, NULL);
647     for (const AliHistogramDefinition2D* definition=fgkHistogramDefinitions2D;
648          definition->fName!=NULL; definition++) {
649       fHistogram2DPointers[definition->fId]=new TH2D(definition->fName,
650                                                      definition->fTitle,
651                                                      definition->fBinsX,
652                                                      definition->fLowerBoundX,
653                                                      definition->fUpperBoundX,
654                                                      definition->fBinsY,
655                                                      definition->fLowerBoundY,
656                                                      definition->fUpperBoundY
657                                                      );
658       if (fHistogram2DPointers[definition->fId]) {
659         fHistogram2DPointers[definition->fId]->SetOption(definition->fDrawOptions);
660       fHistograms2D->AddAt(fHistogram2DPointers[definition->fId], definition->fId);
661       }
662     }
663   }
664   ///
665   if (fHistograms3D) {
666     fHistograms3D->SetOwner(kTRUE);
667     fHistogram3DPointers.resize(kNumberOfHistograms3D, NULL);
668     for (const AliHistogramDefinition3D* definition=fgkHistogramDefinitions3D;
669          definition->fName!=NULL; definition++) {
670       fHistogram3DPointers[definition->fId]=new TH3D(definition->fName,
671                                                      definition->fTitle,
672                                                      definition->fBinsX,
673                                                      definition->fLowerBoundX,
674                                                      definition->fUpperBoundX,
675                                                      definition->fBinsY,
676                                                      definition->fLowerBoundY,
677                                                      definition->fUpperBoundY,
678                                                      definition->fBinsZ,
679                                                      definition->fLowerBoundZ,
680                                                      definition->fUpperBoundZ
681                                                      );
682       if (fHistogram3DPointers[definition->fId]) {
683         fHistogram3DPointers[definition->fId]->SetOption(definition->fDrawOptions);
684       fHistograms3D->AddAt(fHistogram3DPointers[definition->fId], definition->fId);
685       }
686     }
687   }
688   
689 }
690
691 const AliHLTTPCDataCompressionMonitorComponent::AliHistogramDefinition AliHLTTPCDataCompressionMonitorComponent::fgkHistogramDefinitions[] = {
692   {kHistogramPadrow,        "padrow"   , "padrow; padrow; counts"                  ,  160,   0.,   160., ""},
693   {kHistogramHWCFPad,       "hwcfpad"  , "hwcfpad; pad; counts"                    ,  280,   0.,   140., ""},
694   {kHistogramPad,           "pad"      , "pad; pad; counts"                        ,  280,   0.,   140., ""},
695   {kHistogramTime,          "timebin"  , "timebin; time; counts"                   , 1024,   0.,  1024., ""},
696   {kHistogramSigmaY2,       "sigmaY2"  , "sigmaY2; #sigma_{Y}^{2}; counts"         ,  100,   0.,     1., ""},
697   {kHistogramSigmaZ2,       "sigmaZ2"  , "sigmaZ2; #sigma_{Z}^{2}; counts"         ,  100,   0.,     1., ""},
698   {kHistogramCharge,        "charge"   , "charge; charge; counts"                  , 1024,   0., 65536., ""},
699   {kHistogramQMax,          "qmax"     , "qmax; Q_{max}; counts"                   ,  128,   0.,  1024., ""},
700   {kHistogramDeltaPadrow,   "d_padrow" , "d_padrow; #Delta padrow; counts"         , 1000,  -1.,     1., ""},
701   {kHistogramDeltaPad,      "d_pad"    , "d_pad; #Delta pad; counts"               , 1000,  -1.,     1., ""},
702   {kHistogramDeltaTime,     "d_time"   , "d_time; #Delta time; counts"             , 1000,  -1.,     1., ""},
703   {kHistogramDeltaSigmaY2,  "d_sigmaY2", "d_sigmaY2; #Delta #sigma_{Y}^{2}; counts", 1000,  -1.,     1., ""},
704   {kHistogramDeltaSigmaZ2,  "d_sigmaZ2", "d_sigmaZ2; #Delta #sigma_{Z}^{2}; counts", 1000,  -1.,     1., ""},
705   {kHistogramDeltaCharge,   "d_charge" , "d_charge; #Delta charge"                 , 1000,  -1.,     1., ""},
706   {kHistogramDeltaQMax,     "d_qmax"   , "d_qmax; #Delta Q_{max}"                  , 1000,  -1.,     1., ""},
707   {kHistogramOutOfRange,    "ResError" , "Residual Error; padrow; counts"          ,  159,   0.,   159., ""},
708   {kNumberOfHistograms, NULL, NULL, 0,0.,0., NULL}
709 };
710
711 const AliHLTTPCDataCompressionMonitorComponent::AliHistogramDefinition2D AliHLTTPCDataCompressionMonitorComponent::fgkHistogramDefinitions2D[] = {
712   {kHistogramQMaxSector,    "qmaxsector"   , "qmaxsector; sector; Q_{max}"           ,  72,   0.,  72., 1024,   0., 1024., "colz"},
713   {kHistogramSigmaY2Sector, "sigmaY2sector", "sigmaY2sector; sector; #sigma_{Y}^{2}" ,  72,   0.,  72.,  100,   0.,    1., "colz"},
714   {kHistogramSigmaZ2Sector, "sigmaZ2sector", "sigmaZ2sector; sector; #sigma_{Z}^{2}" ,  72,   0.,  72.,  100,   0.,    1., "colz"},
715   {kHistogramXYA,            "XYA", "XY - A side; X[cm]; Y[cm]"                      , 100,-300., 300.,  100,-300.,  300., "colz"},
716   {kHistogramXYC,            "XYC", "XY - C side; X[cm]; Y[cm]"                      , 100,-300., 300.,  100,-300.,  300., "colz"},
717   {kNumberOfHistograms2D, NULL, NULL, 0,0.,0., 0,0.,0., NULL}
718 };
719
720 const AliHLTTPCDataCompressionMonitorComponent::AliHistogramDefinition3D AliHLTTPCDataCompressionMonitorComponent::fgkHistogramDefinitions3D[] = {
721   {kHistogramPadrowPadSector,"padrowpadsector","padrowpadsector; sector; pad;padrow", 72,0.,72., 140,0.,140., 159,0.,159., ""},
722   {kNumberOfHistograms3D, NULL, NULL, 0,0.,0., 0,0.,0., 0,0.,0., NULL}
723 };
724
725 AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::~AliDataContainer()
726 {
727   /// dectructor
728   if (fRawData) delete fRawData;
729   if (fHistograms) delete fHistograms;
730   if (fHistograms2D) delete fHistograms2D;
731   if (fHistograms3D) delete fHistograms3D;
732 }
733
734 AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::iterator& AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::BeginPartitionClusterBlock(int /*count*/, AliHLTUInt32_t specification)
735 {
736   /// iterator of remaining clusters block of specification
737   AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(specification);
738   AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(specification);
739   unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
740   if (index<fRemainingClusterIds.size())
741     fCurrentClusterIds=&fRemainingClusterIds[index];
742   else
743     fCurrentClusterIds=NULL;
744   fBegin=iterator(this);
745   return fBegin;
746 }
747
748 AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::iterator& AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::BeginTrackModelClusterBlock(int /*count*/)
749 {
750   /// iterator of track model clusters
751   if (fTrackModelClusterIds.fIds && fTrackModelClusterIds.fSize>0)
752     fCurrentClusterIds=&fTrackModelClusterIds;
753   else
754     fCurrentClusterIds=NULL;
755   fBegin=iterator(this);
756   return fBegin;
757 }
758
759 int AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::AddRawData(const AliHLTComponentBlockData* pDesc)
760 {
761   /// add raw data bloack
762   int iResult=0;
763   if (pDesc->fDataType==AliHLTTPCDefinitions::HWClustersDataType()) {
764     if (!fRawData) fRawData=new AliHLTTPCHWCFSpacePointContainer(AliHLTTPCHWCFSpacePointContainer::kModeCreateMap);
765     if (!fRawData) return -ENOMEM;
766     if ((iResult=fRawData->AddInputBlock(pDesc))<0) return iResult;
767     AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pSpacePointGrid=AliHLTTPCHWCFSpacePointContainer::AllocateIndexGrid();
768     if (pSpacePointGrid) {
769       fRawData->PopulateAccessGrid(pSpacePointGrid, pDesc->fSpecification);
770       fRawData->SetSpacePointPropertyGrid(pDesc->fSpecification, pSpacePointGrid);
771     }
772     return 0;
773   }
774   return -ENODATA;  
775 }
776
777 int AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::AddClusterIds(const AliHLTComponentBlockData* pDesc)
778 {
779   /// add cluster id block for remaining or track model clusters
780   if (!pDesc) return -EINVAL;
781   if (pDesc->fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
782     fTrackModelClusterIds.fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
783     fTrackModelClusterIds.fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
784     return 0;
785   }
786   if (pDesc->fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType()) {
787     AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
788     AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
789     unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
790     if (fRemainingClusterIds.size()<=index) {
791       if ((int)fRemainingClusterIds.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
792         fRemainingClusterIds.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches());
793       } else {
794         fRemainingClusterIds.resize(index+1);
795       }
796     }
797     fRemainingClusterIds[index].fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
798     fRemainingClusterIds[index].fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
799     return 0;
800   }
801   return -ENODATA;
802 }
803
804 AliHLTUInt32_t AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::GetClusterId(int clusterNo) const
805 {
806   /// get the cluster id from the current cluster id block (optional)
807   if (!fCurrentClusterIds ||
808       clusterNo<0 ||
809       (int)fCurrentClusterIds->fSize<=clusterNo)
810     return kAliHLTVoidDataSpec;
811   return fCurrentClusterIds->fIds[clusterNo];
812 }
813
814 AliHLTUInt32_t AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FindNearestCluster(int slice, int partition, const AliHLTTPCRawCluster& cluster) const
815 {
816   /// get the cluster id of the nearest original cluster
817   if (!fRawData) return kAliHLTVoidDataSpec;
818   AliHLTUInt32_t key=AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, partition, partition);
819   // FIXME: AliHLTIndexGrid::Index is not declared const
820   AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pGrid=const_cast<AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid*>(fRawData->GetSpacePointPropertyGrid(key));
821   if (!pGrid) return kAliHLTVoidDataSpec;
822   AliHLTUInt32_t clusterId=kAliHLTVoidDataSpec;
823   // search a 4x4 matrix out of the 9x9 matrix around the cell addressed by
824   // pad and time
825   float padrow=(float)cluster.GetPadRow()-AliHLTTPCTransform::GetFirstRow(partition);
826   float pad=cluster.GetPad();
827   float time=cluster.GetTime();
828   float minr2=-1.;
829   const float padpitch=AliHLTTPCTransform::GetPadPitchWidth(partition);
830   const float zwidth=AliHLTTPCTransform::GetZWidth();
831   float maxDeltaPad=AliHLTTPCDefinitions::GetMaxClusterDeltaPad();
832   float maxDeltaTime=AliHLTTPCDefinitions::GetMaxClusterDeltaTime();
833   int rowindex=pGrid->GetXIndex(padrow);
834   int padstartindex=pGrid->GetYIndex(pad);
835   int timestartindex=pGrid->GetZIndex(time);
836   int cellindex=pGrid->Index(rowindex, padstartindex, timestartindex);
837   float centerpad=pGrid->GetCenterY(cellindex);
838   float centertime=pGrid->GetCenterZ(cellindex);
839   if ((TMath::Abs(centerpad-pad)>maxDeltaPad && pad>0.) ||
840       (TMath::Abs(centertime-time)>maxDeltaTime && time>0.)) {
841     ALIHLTERRORGUARD(20, "invalid pad center calculation, please check dimensions if dimensions of index grid match the maximum possible deviation");
842   }
843
844   int paddirection=1;
845   int timedirection=1;
846   if (centerpad>pad) paddirection=-1;
847   if (centertime>time) timedirection=-1;
848   for (int padcount=0, padindex=padstartindex; padcount<2; padcount++, padindex+=paddirection) {
849     if (padindex<0) continue;
850     if (padindex>=pGrid->GetDimensionY()) break;
851     for (int timecount=0, timeindex=timestartindex; timecount<2; timecount++, timeindex+=timedirection) {
852       if (timeindex<0) continue;
853       if (timeindex>=pGrid->GetDimensionZ()) break;
854       cellindex=pGrid->Index(rowindex, padindex, timeindex);
855       float cellpad=pGrid->GetCenterY(cellindex);
856       float celltime=pGrid->GetCenterZ(cellindex);
857       for (AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid::iterator& cl=pGrid->begin((float)padrow, cellpad, celltime);
858            cl!=pGrid->end(); cl++) {
859         if (cl.Data().fTrackId>=0) continue;
860         if (fRawData->GetCharge(cl.Data().fId)!=cluster.GetCharge() ||
861             fRawData->GetQMax(cl.Data().fId)!=cluster.GetQMax()) continue;
862         if (TMath::Abs(padrow-fRawData->GetX(cl.Data().fId))>=1.) {
863           HLTError("slice %d, partition %d, cluster 0x%08x: mismatch on padrow: %f  vs. cluster %f", slice, partition, cl.Data().fId, padrow, fRawData->GetX(cl.Data().fId));
864           continue;
865         }
866         float clusterpad=fRawData->GetY(cl.Data().fId);
867         float clustertime=fRawData->GetZ(cl.Data().fId);
868         clusterpad-=pad;
869         clusterpad*=padpitch;
870         clustertime-=time;
871         clustertime*=zwidth;
872         float r2=clusterpad*clusterpad+clustertime*clustertime;
873         if (minr2<0. || r2<minr2) {
874           clusterId=cl.Data().fId;
875           cl.Data().fTrackId=1;
876           minr2=r2;
877         }
878       }
879     }
880   }
881   return clusterId;
882 }
883
884 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillPadRow(int row, int slice, AliHLTUInt32_t /*clusterId*/)
885 {
886   /// fill padrow histogram
887   unsigned index=kHistogramPadrow;
888   fCurrentCluster.SetPadRow(row);
889   // the inner sectors consist of readout partitions 0 and 1, if the row
890   // is smaller than first row of readout partition 2, its an inner sector
891   if (row<AliHLTTPCTransform::GetFirstRow(2)) {
892     fSector = slice;
893   } else {
894     fSector = slice+AliHLTTPCTransform::GetNSlice();
895   }
896   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
897     fHistogramPointers[index]->Fill(row);
898 }
899
900 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillPad(float pad, AliHLTUInt32_t /*clusterId*/)
901 {
902   /// fill pad histogram
903   fCurrentCluster.SetPad(pad);
904   int currentRow=fCurrentCluster.GetPadRow();
905   unsigned index=kHistogramPad;
906   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
907     fHistogramPointers[index]->Fill(pad);
908
909   index=kHistogramPadrowPadSector;
910   if (index<fHistogram3DPointers.size() && fHistogram3DPointers[index]!=NULL)
911     fHistogram3DPointers[index]->Fill(fSector,pad,currentRow);
912   
913   AliTPCROC *roc=AliTPCROC::Instance();
914   if (roc) {
915   Float_t pos[3]={0.,0.,0.};
916   roc->GetPositionGlobal(fSector, fSector>35?currentRow-63:currentRow, (int)pad, pos); 
917   if (fSector<=17 || (fSector>=36&&fSector<=53))
918     //Sectors 0 to 17 and 36 to 53 are on the A side, sectors 18 to 35 and 54 to 71 are on the C side. 
919     { 
920       index=kHistogramXYA;
921       if (index<fHistogram2DPointers.size() && fHistogram2DPointers[index]!=NULL)
922         fHistogram2DPointers[index]->Fill(pos[0],pos[1]);
923     } else {
924     index=kHistogramXYC;
925     if (index<fHistogram2DPointers.size() && fHistogram2DPointers[index]!=NULL)
926       fHistogram2DPointers[index]->Fill(pos[0],pos[1]);
927   }
928   }
929
930 }
931
932 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillTime(float time, AliHLTUInt32_t /*clusterId*/)
933 {
934   /// fill pad histogram
935   fCurrentCluster.SetTime(time);
936   unsigned index=kHistogramTime;
937   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
938     fHistogramPointers[index]->Fill(time);
939 }
940
941 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillSigmaY2(float sigmaY2, AliHLTUInt32_t /*clusterId*/, int partition)
942 {
943   /// fill sigmaY2 histogram
944   fCurrentCluster.SetSigmaY2(sigmaY2);
945   unsigned index=kHistogramSigmaY2;
946   /// take account for different pad widths
947   float weight=AliHLTTPCTransform::GetPadPitchWidth(partition);
948   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
949     fHistogramPointers[index]->Fill(sigmaY2*weight*weight);
950
951   index=kHistogramSigmaY2Sector;
952   if (index<fHistogram2DPointers.size() && fHistogram2DPointers[index]!=NULL)
953     fHistogram2DPointers[index]->Fill(fSector,sigmaY2*weight*weight);
954
955 }
956
957 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillSigmaZ2(float sigmaZ2, AliHLTUInt32_t /*clusterId*/)
958 {
959   /// fill sigmaZ2 histogram
960   fCurrentCluster.SetSigmaZ2(sigmaZ2);
961   unsigned index=kHistogramSigmaZ2;
962   // FIXME: this is just a fixed value, to be correct the values from the global
963   // parameter block has to be used
964   float weight=AliHLTTPCTransform::GetZWidth();
965   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
966     fHistogramPointers[index]->Fill(sigmaZ2*weight*weight);
967
968   index=kHistogramSigmaZ2Sector;
969   if (index<fHistogram2DPointers.size() && fHistogram2DPointers[index]!=NULL)
970     fHistogram2DPointers[index]->Fill(fSector,sigmaZ2*weight*weight);
971
972 }
973
974 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillCharge(unsigned charge, AliHLTUInt32_t /*clusterId*/)
975 {
976   /// fill charge histogram
977   fCurrentCluster.SetCharge(charge);
978   unsigned index=kHistogramCharge;
979   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
980     fHistogramPointers[index]->Fill(charge);
981 }
982
983 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FillQMax(unsigned qmax, AliHLTUInt32_t /*clusterId*/)
984 {
985   /// fill qmax histogram
986   fCurrentCluster.SetQMax(qmax);
987   unsigned index=kHistogramQMax;
988   if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL)
989     fHistogramPointers[index]->Fill(qmax);
990
991   index=kHistogramQMaxSector;
992   if (index<fHistogram2DPointers.size() && fHistogram2DPointers[index]!=NULL)
993     fHistogram2DPointers[index]->Fill(fSector,qmax);
994 }
995
996 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::Fill(int slice, int partition, AliHLTUInt32_t clusterId)
997 {
998   /// fill cluster histograms requiring the full cluster information
999   
1000   // TODO: the complete filling of histograms can be moved to this function
1001   // and the cluster struct be filled in the iterator
1002   // The delta histograms are filled here either by using the specified
1003   // cluster, or the nearest cluster on the padrow with identical charge
1004   // and qmax is searched for comparison.
1005   if (clusterId==kAliHLTVoidDataSpec) {
1006     clusterId=FindNearestCluster(slice, partition, fCurrentCluster);
1007   }
1008   if (clusterId==kAliHLTVoidDataSpec) return;
1009   bool bResidualError=false;
1010   int currentRow=fCurrentCluster.GetPadRow();
1011
1012     unsigned index=kHistogramDeltaPadrow;
1013     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1014       if (fRawData->Check(clusterId)) {
1015         fHistogramPointers[index]->Fill(fCurrentCluster.GetPadRow()-fRawData->GetX(clusterId));
1016       }
1017     }
1018
1019     index=kHistogramDeltaPad;
1020     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1021       if (fRawData->Check(clusterId)) {
1022         float dPad=fCurrentCluster.GetPad()-fRawData->GetY(clusterId);
1023         fHistogramPointers[index]->Fill(dPad);
1024         static const float maxdPad=0.015; // better 100um for 4 and 6mm pad width
1025         if (TMath::Abs(dPad)>maxdPad) {
1026           //HLTError("cluster 0x%08x slice %d partition %d: pad difference %f - max %f", clusterId, slice, partition, dPad, maxdPad);
1027           bResidualError=true;
1028         }
1029       }
1030     }
1031
1032     index=kHistogramDeltaTime;
1033     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1034       if (fRawData->Check(clusterId)) {
1035         float dTime=fCurrentCluster.GetTime()-fRawData->GetZ(clusterId);
1036         fHistogramPointers[index]->Fill(dTime);
1037         static const float maxdTime=0.04; // corresponds to 100um
1038         if (TMath::Abs(dTime)>maxdTime) {
1039           //HLTError("cluster 0x%08x slice %d partition %d: time difference %f - max %f", clusterId, slice, partition, dTime, maxdTime);
1040           bResidualError=true;
1041         }
1042       }
1043     }
1044
1045     index=kHistogramDeltaSigmaY2;
1046     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1047       if (fRawData->Check(clusterId)) {
1048         float factor=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale;
1049         float sigma=fRawData->GetYWidth(clusterId)*factor;
1050         if (sigma>fMaxSigmaY2Scaled) sigma=fMaxSigmaY2Scaled;
1051         sigma/=factor;
1052         fHistogramPointers[index]->Fill(fCurrentCluster.GetSigmaY2()-sigma);
1053       }
1054     }
1055
1056     index=kHistogramDeltaSigmaZ2;
1057     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1058       if (fRawData->Check(clusterId)) {
1059         float factor=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale;
1060         float sigma=fRawData->GetZWidth(clusterId)*factor;
1061         if (sigma>fMaxSigmaZ2Scaled) sigma=fMaxSigmaZ2Scaled;
1062         sigma/=factor;
1063         fHistogramPointers[index]->Fill(fCurrentCluster.GetSigmaZ2()-sigma);
1064       }
1065     }
1066
1067     index=kHistogramDeltaCharge;
1068     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1069       if (fRawData->Check(clusterId)) {
1070         fHistogramPointers[index]->Fill(fCurrentCluster.GetCharge()-fRawData->GetCharge(clusterId));
1071       }
1072     }
1073
1074     index=kHistogramDeltaQMax;
1075     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1076       if (fRawData->Check(clusterId)) {
1077         fHistogramPointers[index]->Fill(fCurrentCluster.GetQMax()-fRawData->GetQMax(clusterId));
1078       }
1079     }
1080
1081     if (bResidualError) {
1082     index=kHistogramOutOfRange;
1083     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData) {
1084       fHistogramPointers[index]->Fill(currentRow>=0?currentRow:0);
1085     }
1086     }
1087
1088     index=kHistogramHWCFPad;
1089     if (index<fHistogramPointers.size() && fHistogramPointers[index]!=NULL && fRawData)
1090       fHistogramPointers[index]->Fill(fRawData->GetY(clusterId));
1091 }
1092
1093 void AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::Clear(Option_t * option)
1094 {
1095   /// internal cleanup
1096   if (fRawData) fRawData->Clear(option);
1097 }
1098
1099 TObject* AliHLTTPCDataCompressionMonitorComponent::AliDataContainer::FindObject(const char *name) const
1100 {
1101   /// get histogram object  
1102   if (!name) return NULL;
1103   if ( strcmp(name,"fHistograms")   == 0 )
1104     return fHistograms;
1105   if ( strcmp(name,"fHistograms2D") == 0 )
1106     return fHistograms2D;
1107   if ( strcmp(name,"fHistograms3D") == 0 )
1108     return fHistograms3D;
1109
1110   return NULL;
1111 }