]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCClusterAccessHLTOUT.cxx
Be sure to load mapping when needed
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClusterAccessHLTOUT.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /// @file   AliHLTTPCClusterAccessHLTOUT.h
20 /// @author Matthias Richter
21 /// @date   2011-06-06
22 /// @brief  Interface to HLT TPC clusters
23 ///
24
25 #include "AliHLTTPCClusterAccessHLTOUT.h"
26 #include "AliHLTTPCDefinitions.h"
27 #include "AliHLTTPCClusterDataFormat.h"
28 #include "AliHLTTPCRawCluster.h"
29 #include "AliHLTTPCTransform.h"
30 #include "AliHLTOUT.h"
31 #include "AliHLTComponent.h"
32 #include "AliHLTErrorGuard.h"
33 #include "AliHLTDataInflater.h"
34 #include "AliHLTTPCDefinitions.h"
35 #include "AliLog.h"
36 #include "AliHLTSystem.h"
37 #include "AliHLTPluginBase.h"
38 #include "AliTPCclusterMI.h"
39 #include "TClonesArray.h"
40 #include <cstdlib>
41 #include <string>
42 #include <memory>
43
44 /** ROOT macro for the implementation of ROOT specific class methods */
45 ClassImp(AliHLTTPCClusterAccessHLTOUT)
46
47 AliHLTTPCClusterAccessHLTOUT::AliHLTTPCClusterAccessHLTOUT()
48   : TObject()
49   , fVerbosity(0)
50   , fClusters(NULL)
51 {
52   // see header file for class documentation
53   // or
54   // refer to README to build package
55   // or
56   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
57 }
58
59 AliHLTTPCClusterAccessHLTOUT::~AliHLTTPCClusterAccessHLTOUT()
60 {
61   // destructor
62   if (fClusters) {
63     fClusters->Clear();
64     delete fClusters;
65     fClusters=NULL;
66   }
67 }
68
69 void AliHLTTPCClusterAccessHLTOUT::Execute(const char *method,  const char *params, Int_t *error)
70 {
71   /// inherited from TObject: abstract command interface
72   if (strcmp(method, "read")==0) {
73     int iResult=ProcessClusters(params);
74     if (error) *error=iResult;
75     return;
76   }
77   if (strcmp(method, "verbosity")==0) {
78     int iResult=0;
79     if (params) {
80       char* dummy;
81       int value=strtol(params, &dummy, 0);
82       if (dummy==NULL) {
83         fVerbosity=value;
84       } else {
85         AliError("invalid argument for command 'verbosity', expecting string with number");
86       }
87     } else {
88       iResult=-EINVAL;
89     }
90     if (error) *error=iResult;
91     return;
92   }
93 }
94
95 TObject* AliHLTTPCClusterAccessHLTOUT::FindObject(const char *name) const
96 {
97   /// inherited from TObject: return the cluster array if name id "clusterarray"
98   if (strcmp(name, "clusterarray")==0) return fClusters;
99   return TObject::FindObject(name);
100 }
101
102 void AliHLTTPCClusterAccessHLTOUT::Clear(Option_t * /*option*/)
103 {
104   /// inherited from TObject: cleanup
105   if (fClusters) fClusters->Clear();
106 }
107
108 void AliHLTTPCClusterAccessHLTOUT::Print(Option_t */*option*/) const
109 {
110   /// inherited from TObject
111   if (!fClusters) return;
112   for (int i=0; i<fClusters->GetEntriesFast(); i++) {
113     if (!fClusters->At(i)) continue;
114     AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(fClusters->At(i));
115     if (!pCluster) break;
116     cout << "AliTPCclusterMI:"
117          << "  row="    << pCluster->GetRow() 
118          << "  pad="    << pCluster->GetPad()
119          << "  time="   << pCluster->GetTimeBin()
120          << "  charge=" << pCluster->GetQ()
121          << "  maxq="   << pCluster->GetMax()
122          << endl;
123   }
124 }
125
126 int AliHLTTPCClusterAccessHLTOUT::ProcessClusters(const char* params)
127 {
128   /// process the cluster data from HLTOUT and fill array
129   /// the cluster data can be in many different formats, e.g.
130   /// raw or compressed
131   int iResult=0;
132   TString strparams(params);
133   int minSlice=0, maxSlice=35, minPart=0, maxPart=5;
134   std::auto_ptr<TObjArray> tokens(strparams.Tokenize(" "));
135   if (!tokens.get()) return -ENOMEM;
136   for (int i=0; i< tokens->GetEntriesFast(); i++) {
137     if (!tokens->At(i)) continue;
138     TString argument=tokens->At(i)->GetName();
139     if (argument.BeginsWith("sector=")) {
140       argument.ReplaceAll("sector=", "");
141       int sector=argument.Atoi();
142       // the offline code enumerates first the 36 inner (partitions 0+1) and then 36 outer
143       // sectors (partitions 2-5)
144       if (fVerbosity>0) AliInfo(Form("processing HLT clusters for sector %d", sector));
145       if (sector<36) { // inner sectors
146         minSlice=maxSlice=sector;
147         minPart=0; maxPart=1;
148       } else { // outer sectors
149         minSlice=maxSlice=sector-36;
150         minPart=2; maxPart=5;
151       }
152     }
153   }
154
155   if (!fClusters) {
156     fClusters=new TClonesArray("AliTPCclusterMI");
157   }
158   if (!fClusters) return -ENOMEM;
159
160   AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
161   if (!pSystem) {
162     AliError("can not access HLT system");
163     return -ENODEV;
164   }
165   AliHLTOUT* pHLTOUT=pSystem->RequestHLTOUT();
166   if (!pHLTOUT) {
167     AliError("can not access HLTOUT");
168     return -ENODEV;
169   }
170
171   for (int slice=minSlice; slice<=maxSlice; slice++) {
172     for (int part=minPart; part<=maxPart; part++) {
173       if (fVerbosity>0) AliInfo(Form("processing HLT clusters for slice %d partitions %d", slice, part));
174       AliHLTUInt32_t spec=slice<<24 | slice<<16 | part<<8 | part;
175       AliHLTTPCClusterMCDataList tpcClusterLabels;
176       bool bHaveLabels=false;
177       if (pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo, spec)>=0) {
178         iResult=ReadAliHLTTPCClusterMCData(pHLTOUT, tpcClusterLabels);
179         bHaveLabels=true;
180       }
181
182       if (pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::RemainingClustersCompressedDataType(), spec)>=0) {
183         iResult=ReadRemainingClustersCompressed(pHLTOUT, fClusters, bHaveLabels?&tpcClusterLabels:NULL);
184       } else if (pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::fgkRawClustersDataType, spec)>=0) {
185         iResult=ReadAliHLTTPCRawClusterData(pHLTOUT, fClusters, bHaveLabels?&tpcClusterLabels:NULL);
186       } else if (pHLTOUT->SelectFirstDataBlock(AliHLTTPCDefinitions::fgkClustersDataType, spec)>=0) {
187         ALIHLTERRORGUARD(1, "HLTOUT data contains tarnsformed TPC clusters instead of raw TPC clusters, can not create clusters for reconstruction");
188       }
189     }
190   }
191
192   pSystem->ReleaseHLTOUT(pHLTOUT);
193   return iResult;
194 }
195
196 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterMCData(AliHLTOUT* pHLTOUT, AliHLTTPCClusterMCDataList &tpcClusterLabels) const
197 {
198   // read cluster data from AliHLTTPCClusterData
199   int iResult=0;
200   if (!pHLTOUT) return -EINVAL;
201   do {
202     const AliHLTUInt8_t* pBuffer=NULL;
203     AliHLTUInt32_t size=0;
204     if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
205       continue;
206     }
207     if (pBuffer==NULL || size<4) {
208       AliError("invalid cluster mc data block");
209       continue;
210     }
211     const AliHLTTPCClusterMCData* clusterMCData = reinterpret_cast<const AliHLTTPCClusterMCData*>(pBuffer);
212     Int_t nLabels = (Int_t) clusterMCData->fCount;
213     if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != size) {
214       AliError("inconsistent cluster mc data block size, skipping block");
215       continue;
216     }
217     // id of the cluster is 
218     AliHLTComponentDataType dt=kAliHLTVoidDataType;
219     AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
220     if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
221       AliError("failed to retrieve data block description, skipping mc cluster data block ...");
222       continue;
223     }
224     AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
225     AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
226     if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(specification) ||
227         partition!=AliHLTTPCDefinitions::GetMaxPatchNr(specification)) {
228       AliError(Form("can not read cluster mc data block with data of multiple partitions, skipping block %s %08x",
229                     AliHLTComponent::DataType2Text(dt).c_str(), specification));
230       continue;
231     }
232     const AliHLTTPCClusterMCLabel *labels = clusterMCData->fLabels;
233     for (int i=0; i<nLabels; i++) {
234       AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, i);
235       if (tpcClusterLabels.find(id)==tpcClusterLabels.end()) {
236         // new cluster
237         tpcClusterLabels[id]=labels[i];
238       } else {
239         AliError(Form("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
240                       id, i, specification));
241       }
242     }
243   } while (pHLTOUT->SelectNextDataBlock()>=0);
244   return iResult;
245 }
246
247 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels) const
248 {
249   // read cluster data from AliHLTTPCClusterData
250   int iResult=0;
251   if (!pHLTOUT || !pClusters) return -EINVAL;
252   do {
253     const AliHLTUInt8_t* pBuffer=NULL;
254     AliHLTUInt32_t size=0;
255     if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
256       continue;
257     }
258     if (pBuffer==NULL || size<4) {
259       AliError("invalid cluster data block");
260       continue;
261     }
262     AliHLTComponentDataType dt=kAliHLTVoidDataType;
263     AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
264     if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
265       AliError("failed to retrieve data block description, skipping mc cluster data block ...");
266       continue;
267     }
268     const AliHLTTPCClusterData* clusterData = reinterpret_cast<const AliHLTTPCClusterData*>(pBuffer);
269     Int_t nSpacepoints = (Int_t) clusterData->fSpacePointCnt;
270     if (nSpacepoints*sizeof(AliHLTTPCSpacePointData) + sizeof(AliHLTTPCClusterData) != size) {
271       AliError("inconsistent cluster data block size, skipping block");
272       continue;
273     }
274     const AliHLTTPCSpacePointData *clusters = clusterData->fSpacePoints;
275     int offset=pClusters->GetEntries();
276     pClusters->ExpandCreate(offset+nSpacepoints);
277     AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
278     AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
279     // FIXME: get first row number of outer sectors from a common definition instead using number
280     unsigned rowOffset=partition<2?0:63;
281     for (int i=0; i<nSpacepoints; i++) {
282       if (!pClusters->At(offset+i)) continue;
283       AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
284       if (!pCluster) {
285         AliError("invalid object type, expecting AliTPCclusterMI");
286         break; // this is a problem of all objects
287       }
288       if (clusters[i].fPadRow<rowOffset) {
289         AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].fPadRow, rowOffset, slice, partition));
290       } else {
291       pCluster->SetRow(clusters[i].fPadRow-rowOffset);
292       }
293       pCluster->SetPad(clusters[i].fY);
294       pCluster->SetTimeBin(clusters[i].fZ);
295       pCluster->SetSigmaY2(clusters[i].fSigmaY2);
296       pCluster->SetSigmaZ2(clusters[i].fSigmaZ2);
297       pCluster->SetQ(clusters[i].fCharge);
298       pCluster->SetMax(clusters[i].fQMax);
299       if (tpcClusterLabels) {
300         if (tpcClusterLabels->find(clusters[i].fID)!=tpcClusterLabels->end()) {
301           const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusters[i].fID)->second.fClusterID;
302           for (int k=0; k<3; k++) {
303             // TODO: sort the labels according to the weight in order to assign the most likely mc label
304             // to the first component 
305             pCluster->SetLabel(mcWeights[k].fMCID, k);
306           }
307         } else {
308           AliError(Form("can not find mc label of cluster with id %0x08x", clusters[i].fID));
309         }
310       }
311     }
312     if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nSpacepoints, AliHLTComponent::DataType2Text(dt).c_str(), specification));
313   } while (pHLTOUT->SelectNextDataBlock()>=0);
314   return iResult;
315 }
316
317 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
318 {
319   // read cluster data from AliHLTTPCClusterData
320
321   // FIXME: this is in large parts like ReadAliHLTTPCClusterData,
322   // make a common method
323   int iResult=0;
324   if (!pHLTOUT || !pClusters) return -EINVAL;
325   do {
326     const AliHLTUInt8_t* pBuffer=NULL;
327     AliHLTUInt32_t size=0;
328     if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
329       continue;
330     }
331     if (pBuffer==NULL || size<4) {
332       AliError("invalid cluster data block");
333       continue;
334     }
335     AliHLTComponentDataType dt=kAliHLTVoidDataType;
336     AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
337     if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
338       AliError("failed to retrieve data block description, skipping mc cluster data block ...");
339       continue;
340     }
341     const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
342     Int_t nCount = (Int_t) clusterData->fCount;
343     if (clusterData->fVersion!=0) {
344       // this is encoded data of different formats
345       switch (clusterData->fVersion) {
346       case 1: 
347         iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
348                                                          size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
349                                                          pClusters, tpcClusterLabels);
350         break;
351       default:
352         iResult=-EPROTO;
353       }
354       return iResult;
355     }
356
357     if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != size) {
358       AliError("inconsistent cluster data block size, skipping block");
359       continue;
360     }
361     const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
362     int offset=pClusters->GetEntries();
363     pClusters->ExpandCreate(offset+nCount);
364     AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
365     AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
366     // FIXME: get first row number of outer sectors from a common definition instead using number
367     int rowOffset=partition<2?0:63;
368     for (int i=0; i<nCount; i++) {
369       if (!pClusters->At(offset+i)) continue;
370       AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
371       if (!pCluster) {
372         AliError("invalid object type, expecting AliTPCclusterMI");
373         break; // this is a problem of all objects
374       }
375       if (fVerbosity>1) AliInfo(Form("cluster padrow %d (slice %d partition %d)", clusters[i].GetPadRow(), slice, partition));
376       if (clusters[i].GetPadRow()<rowOffset) {
377         AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].GetPadRow(), rowOffset, slice, partition));
378       } else {
379       pCluster->SetRow(clusters[i].GetPadRow()-rowOffset);
380       }
381       pCluster->SetPad(clusters[i].GetPad());
382       pCluster->SetTimeBin(clusters[i].GetTime());
383       pCluster->SetSigmaY2(clusters[i].GetSigmaY2());
384       pCluster->SetSigmaZ2(clusters[i].GetSigmaZ2());
385       pCluster->SetQ(clusters[i].GetCharge());
386       pCluster->SetMax(clusters[i].GetQMax());
387       if (tpcClusterLabels) {
388         UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, i);
389         if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
390           const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
391           for (int k=0; k<3; k++) {
392             // TODO: sort the labels according to the weight in order to assign the most likely mc label
393             // to the first component 
394             pCluster->SetLabel(mcWeights[k].fMCID, k);
395           }
396         } else {
397           AliError(Form("can not find mc label of cluster with id %0x08x", clusterID));
398         }
399       }
400     }
401     if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
402   } while (pHLTOUT->SelectNextDataBlock()>=0);
403   return iResult;
404 }
405
406 int AliHLTTPCClusterAccessHLTOUT::ReadRemainingClustersCompressed(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
407 {
408   // read cluster data from AliHLTTPCClusterData
409   int iResult=0;
410   if (!pHLTOUT || !pClusters) return -EINVAL;
411   do {
412     const AliHLTUInt8_t* pBuffer=NULL;
413     AliHLTUInt32_t size=0;
414     if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
415       continue;
416     }
417     if (pBuffer==NULL || size<4) {
418       AliError("invalid cluster data block");
419       continue;
420     }
421     AliHLTComponentDataType dt=kAliHLTVoidDataType;
422     AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
423     if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
424       AliError("failed to retrieve data block description, skipping mc cluster data block ...");
425       continue;
426     }
427     const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
428     Int_t nCount = (Int_t) clusterData->fCount;
429
430     // this is encoded data of different formats
431     switch (clusterData->fVersion) {
432     case 1: 
433       iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
434                                                        size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
435                                                        pClusters, tpcClusterLabels);
436       break;
437     default:
438       AliError(Form("invalid cluster format version %d", clusterData->fVersion));
439       iResult=-EPROTO;
440     }
441
442     if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
443   } while (pHLTOUT->SelectNextDataBlock()>=0 && iResult>=0);
444
445   return iResult;
446 }
447
448 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterDataDeflateSimple(const AliHLTUInt8_t* pData, int dataSize,
449                                                                            int nofClusters, AliHLTUInt32_t specification,
450                                                                            TClonesArray* pClusters,
451                                                                            const AliHLTTPCClusterMCDataList *tpcClusterLabels)
452 {
453   // read cluster data from AliHLTTPCClusterData
454
455   // FIXME: quick implementation to read the compressed cluster data from HLTOUT
456   // the data definition below is the same as in AliHLTTPCDataCompressionComponent
457   // but needs to be moved to a common class (AliHLTTPCDefinitions?)
458   // Think about a decoder class supporting iterator objects for various types
459   // of cluster data
460   int iResult=0;
461   if (!pData || !pClusters) return -EINVAL;
462   AliHLTDataInflater inflater;
463   if ((iResult=inflater.InitBitDataInput(pData, dataSize))<0) {
464     return iResult;
465   }
466
467   int offset=pClusters->GetEntries();
468   pClusters->ExpandCreate(offset+nofClusters);
469   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
470   AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
471   // the compressed format stores the difference of the local row number in
472   // the partition to the row of the last cluster
473   // add the first row in the partition to get global row number
474   // offline uses row number in physical sector, inner sector consists of
475   // partitions 0 and 1, outer sector of partition 2-5
476   int rowOffset=AliHLTTPCTransform::GetFirstRow(partition)-(partition<2?0:AliHLTTPCTransform::GetFirstRow(2));
477
478   int parameterId=0;
479   int outClusterCnt=0;
480   AliHLTUInt8_t switchBit=0;
481   AliHLTUInt64_t value=0;
482   AliTPCclusterMI* pCluster=NULL;
483   AliHLTUInt32_t lastPadRow=0;
484   while (outClusterCnt<nofClusters && inflater.InputBit(switchBit)) {
485     const AliHLTTPCDefinitions::AliClusterParameter& parameter
486       =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
487     // in mode DeflaterSimple, the optional parameter of the cluster parameter definition
488     // corresponds to the number bits of the reduced format
489     if (!inflater.InputBits(value, switchBit?parameter.fBitLength:parameter.fOptional)) {
490       break;
491     }
492
493     if (!pCluster) {
494       if (!pClusters->At(offset+outClusterCnt)) {
495         // here we should not get anymore because of the condition outClusterCnt<nofClusters
496         return -ENOSPC;
497       }
498       pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+outClusterCnt));
499       if (!pCluster) {
500         AliError("invalid object type, expecting AliTPCclusterMI");
501         iResult=-EBADF; // this is a problem of all objects
502         break;
503       }
504     }
505     switch (parameterId) {
506     case AliHLTTPCDefinitions::kPadRow:
507       {pCluster->SetRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
508     case AliHLTTPCDefinitions::kPad:
509       {float pad=value; pad/=parameter.fScale; pCluster->SetPad(pad); break;}
510     case AliHLTTPCDefinitions::kTime:
511       {float time=value; time/=parameter.fScale; pCluster->SetTimeBin(time); break;}
512     case AliHLTTPCDefinitions::kSigmaY2:
513       {float sigmaY2=value; sigmaY2/=parameter.fScale; pCluster->SetSigmaY2(sigmaY2); break;}
514     case AliHLTTPCDefinitions::kSigmaZ2:
515       {float sigmaZ2=value; sigmaZ2/=parameter.fScale; pCluster->SetSigmaZ2(sigmaZ2); break;}
516     case AliHLTTPCDefinitions::kCharge:
517       {pCluster->SetQ(value); break;}
518     case AliHLTTPCDefinitions::kQMax:
519       {pCluster->SetMax(value); break;}
520     }
521     if (parameterId>=AliHLTTPCDefinitions::kLast) {
522       // switch to next cluster
523       if (tpcClusterLabels) {
524         UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, outClusterCnt);
525         if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
526           const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
527           for (int k=0; k<3; k++) {
528             // TODO: sort the labels according to the weight in order to assign the most likely mc label
529             // to the first component 
530             pCluster->SetLabel(mcWeights[k].fMCID, k);
531           }
532         } else {
533           AliError(Form("can not find mc label of cluster with id 0x%08x", clusterID));
534         }
535       }
536       outClusterCnt++;
537       pCluster=NULL;
538       parameterId=-1;
539     }
540     parameterId++;
541   }
542   inflater.Pad8Bits();
543   if (inflater.InputBit(switchBit)) {
544     AliWarning("format error of compressed clusters, there is more data than expected");
545   }
546   inflater.CloseBitDataInput();
547   if (iResult>=0 && nofClusters!=outClusterCnt) {
548     // is this a Fatal?
549     AliError(Form("error reading compressed cluster format: expected %d, read only %d cluster(s)", nofClusters, outClusterCnt));
550     return -EPROTO;
551   }
552   return iResult;
553 }