]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCClusterAccessHLTOUT.cxx
Fixing trigg.class issue
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClusterAccessHLTOUT.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE 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 "AliHLTTPCDataCompressionDecoder.h"
27 #include "AliHLTTPCDefinitions.h"
28 #include "AliHLTTPCClusterDataFormat.h"
29 #include "AliHLTTPCRawCluster.h"
30 #include "AliHLTTPCTransform.h"
31 #include "AliHLTOUT.h"
32 #include "AliHLTComponent.h"
33 #include "AliHLTErrorGuard.h"
34 #include "AliHLTDataInflater.h"
35 #include "AliLog.h"
36 #include "AliHLTSystem.h"
37 #include "AliHLTPluginBase.h"
38 #include "AliTPCclusterMI.h"
39 #include "AliTPCClustersRow.h"
40 #include "AliTPCParam.h"
41 #include "TClonesArray.h"
42 #include "TString.h"
43 #include <cstdlib>
44 #include <string>
45 #include <memory>
46 #include <iostream>
47 #include <iomanip>
48
49 /** ROOT macro for the implementation of ROOT specific class methods */
50 ClassImp(AliHLTTPCClusterAccessHLTOUT)
51
52 AliHLTTPCClusterAccessHLTOUT::AliHLTTPCClusterAccessHLTOUT()
53   : TObject()
54   , fVerbosity(0)
55   , fClusters(NULL)
56   , fCurrentSector(-1)
57   , fpDecoder(NULL)
58   , fTPCParam(NULL)
59 {
60   // see header file for class documentation
61   // or
62   // refer to README to build package
63   // or
64   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65 }
66
67 AliHLTTPCClusterAccessHLTOUT::~AliHLTTPCClusterAccessHLTOUT()
68 {
69   // destructor
70   if (fClusters) {
71     fClusters->Clear();
72     delete fClusters;
73     fClusters=NULL;
74   }
75   if (fpDecoder) {
76     fpDecoder->Clear();
77     delete fpDecoder;
78     fpDecoder=NULL;
79   }
80   if (fTPCParam) {
81     // FIXME: a copy of the TPCParam object is not possible because there is
82     // no appropriate copy constructor or assignment operator, using as
83     // external pointer
84     //delete fTPCParam;
85     fTPCParam=NULL;
86   }
87 }
88
89 void AliHLTTPCClusterAccessHLTOUT::Execute(const char *method,  const char *params, Int_t *error)
90 {
91   /// inherited from TObject: abstract command interface
92   if (strcmp(method, "read")==0) {
93     int iResult=ProcessClusters(params);
94     if (error) *error=iResult;
95     return;
96   }
97   if (strcmp(method, "verbosity")==0) {
98     int iResult=0;
99     if (params) {
100       char* dummy;
101       int value=strtol(params, &dummy, 0);
102       if (dummy==NULL) {
103         fVerbosity=value;
104       } else {
105         AliError("invalid argument for command 'verbosity', expecting string with number");
106       }
107     } else {
108       iResult=-EINVAL;
109     }
110     if (error) *error=iResult;
111     return;
112   }
113 }
114
115 TObject* AliHLTTPCClusterAccessHLTOUT::FindObject(const char *name) const
116 {
117   /// inherited from TObject: return the cluster array if name id "clusterarray"
118   if (strcmp(name, "clusterarray")==0) {
119     if (fCurrentSector<0) return NULL;
120     return fClusters->GetSectorArray(fCurrentSector);
121   }
122   return TObject::FindObject(name);
123 }
124
125 void AliHLTTPCClusterAccessHLTOUT::Copy(TObject &object) const
126 {
127   /// inherited from TObject: supports writing of data to AliTPCClustersRow
128   AliTPCClustersRow* rowcl=dynamic_cast<AliTPCClustersRow*>(&object);
129   if (rowcl) {
130     int index=rowcl->GetID();
131     if (!fTPCParam) {
132       AliFatal("TPCParam object not initialized, use 'Copy()' funtion to initialize");
133       return;
134     }
135     int sector=-1;
136     int row=-1;
137     if (!fTPCParam->AdjustSectorRow(index, sector, row)) {
138       AliFatal(Form("failed to get sector and row for index %d", index));
139       return;
140     }
141     fClusters->FillSectorArray(rowcl->GetArray(), sector, row);
142     return;
143   }
144   AliTPCParam* tpcparam=dynamic_cast<AliTPCParam*>(&object);
145   if (tpcparam) {
146     // FIXME: can nor make a copy of the TPCparam object because
147     // there is no appropriate copy constructor or assignment operator
148     const_cast<AliHLTTPCClusterAccessHLTOUT*>(this)->fTPCParam=tpcparam;
149     return;
150   }
151   return TObject::Copy(object);
152 }
153
154
155 void AliHLTTPCClusterAccessHLTOUT::Clear(Option_t * option)
156 {
157   /// inherited from TObject: cleanup
158   if (strcmp(option, "event")==0) {
159     if (fClusters) fClusters->Clear();
160     fCurrentSector=-1;
161   }
162 }
163
164 void AliHLTTPCClusterAccessHLTOUT::Print(Option_t *option) const
165 {
166   /// inherited from TObject
167   if (fClusters) fClusters->Print(option);
168 }
169
170 int AliHLTTPCClusterAccessHLTOUT::ProcessClusters(const char* params)
171 {
172   /// process the cluster data from HLTOUT and fill array
173   /// the cluster data can be in many different formats, e.g.
174   /// raw or compressed
175   int iResult=0;
176   TString strparams(params);
177   int sector=-1;
178   std::auto_ptr<TObjArray> tokens(strparams.Tokenize(" "));
179   if (!tokens.get()) return -ENOMEM;
180   for (int i=0; i< tokens->GetEntriesFast(); i++) {
181     if (!tokens->At(i)) continue;
182     TString argument=tokens->At(i)->GetName();
183     // the offline code enumerates first the 36 inner (partitions 0+1) and then 36 outer
184     // sectors (partitions 2-5)
185     if (argument.BeginsWith("sector=")) {
186       argument.ReplaceAll("sector=", "");
187       sector=argument.Atoi();
188     }
189   }
190   if (sector<0) {
191     AliError("invalid argument, please specify \"sector=sectorno\"");
192     return -EINVAL;
193   }
194   if (sector>=76) {
195     AliError(Form("invalid sector number %d", sector));
196     return -EINVAL;
197   }
198
199   if (!fClusters) {
200     fClusters=new AliRawClusterContainer;
201   }
202   if (!fClusters) return -ENOMEM;
203
204   if (fCurrentSector>=0) {
205     // cluster container already filled
206     fCurrentSector=sector;
207 //     TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
208 //     if (!pArray) {
209 //       AliError(Form("can not get cluster array for sector %d", sector));
210 //       return -ENOBUFS;
211 //     }
212 //     if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
213     return 0; //pArray->GetEntriesFast();
214   }
215
216   // fill the cluster container
217   AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
218   if (!pSystem) {
219     AliError("can not access HLT system");
220     return -ENODEV;
221   }
222   AliHLTOUT* pHLTOUT=pSystem->RequestHLTOUT();
223   if (!pHLTOUT) {
224     AliError("can not access HLTOUT");
225     return -EACCES;
226   }
227
228   if (!fpDecoder) {
229     fpDecoder=new AliHLTTPCDataCompressionDecoder;
230   }
231
232   if (!fpDecoder) {
233     AliError("failed to create decoder instance");
234     return -ENODEV;
235   }
236
237   AliHLTTPCDataCompressionDecoder& decoder=*fpDecoder;
238   decoder.Clear();
239   decoder.SetVerbosity(fVerbosity);
240
241   bool bNextBlock=false;
242   // add cluster id and mc information data blocks
243   for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
244        bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
245     AliHLTComponentBlockData desc;
246     // FIXME: extend HLTOUT to get the full descriptor
247     const AliHLTUInt8_t* buffer=NULL;
248     if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
249       continue;
250     }
251     desc.fPtr=(void*)buffer;
252     if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
253       continue;
254     }
255     if (desc.fDataType==AliHLTTPCDefinitions::DataCompressionDescriptorDataType()) {
256       // header      
257       if ((iResult=decoder.AddCompressionDescriptor(&desc))<0) {
258         return iResult;
259       }
260     }
261     if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
262       // add mc information
263       if ((iResult=decoder.AddClusterMCData(&desc))<0) {
264         return iResult;
265       }
266     }
267     if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
268         desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
269       // add cluster ids
270       if ((iResult=decoder.AddClusterIds(&desc))<0) {
271         return iResult;
272       }
273     }
274   }
275
276   bool bHavePartitionRawData=false;
277   bool bHavePartitionCompressedData=false;
278   vector<bool> bHavePartitionData(216, false);
279
280   // read data
281   iResult=-ENODATA;
282   int nExtractedClusters=0;
283   for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
284        bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
285     decoder.SetPadShift(0.0);
286     AliHLTComponentBlockData desc;
287     // FIXME: extend HLTOUT to get the full descriptor with one call
288     const AliHLTUInt8_t* buffer=NULL;
289     if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
290       continue;
291     }
292     desc.fPtr=(void*)buffer;
293     if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
294       continue;
295     }
296     if (!TestBit(kSkipPartitionClusters) &&
297         (desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType())) {
298       // This is a special handling of data blocks produced with v5-01-Release
299       // The pad shift by 0.5 was not included in the data but was applied in the
300       // unpacking in this class. Changed in r51306, the next tag containing this
301       // change in the online system is v5-01-Rev-07. There are only very few runs
302       // of Sep 2011 with recorded clusters not containing the 0.5 shift
303       // There was also a chenge in the data type of the compressed partition
304       // cluster blocks which helps to identify the blocks which need the pad shift
305       // here
306       if (desc.fSize<sizeof(AliHLTTPCRawClusterData)) continue;
307       const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(buffer);
308       if (!clusterData) continue;
309       if (clusterData->fVersion==1) {
310         // compressed clusters without the pad shift
311         // no raw clusters (version==0) have ever been recorded
312         decoder.SetPadShift(0.5);
313       }
314       AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
315       AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
316       if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
317           partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
318         AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
319                       "block specification 0x%08x", desc.fSpecification));
320       }
321       iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
322                                             reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
323                                             desc.fSize,
324                                             desc.fSpecification);
325       if (iResult>=0) nExtractedClusters+=iResult;
326       else {
327         AliFatal(Form("processing of cluster block 0x%08x failed with error code %d", desc.fSpecification, iResult));
328       }
329       unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
330       if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
331       if (bHavePartitionData[index]) {
332         AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
333                       "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
334                       "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
335                       "block specification 0x%08x", desc.fSpecification));
336       }
337       bHavePartitionData[index]=true;
338       if (bHavePartitionCompressedData) {
339         AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
340                       "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
341                       "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
342                       "block specification 0x%08x", desc.fSpecification));
343       }
344       bHavePartitionRawData=true;
345       continue;
346     } else if (!TestBit(kSkipPartitionClusters) &&
347                (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType())) {
348       AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
349       AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
350       if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
351           partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
352         AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
353                       "block specification 0x%08x", desc.fSpecification));
354       }
355       iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
356                                             reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
357                                             desc.fSize,
358                                             desc.fSpecification);
359       if (iResult>0) nExtractedClusters+=iResult;
360       unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
361       if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
362       if (bHavePartitionData[index]) {
363         AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
364                       "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
365                       "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
366                       "block specification 0x%08x", desc.fSpecification));
367       }
368       bHavePartitionData[index]=true;
369       bHavePartitionData[index]=true;
370       if (bHavePartitionRawData) {
371         AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
372                       "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
373                       "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
374                       "block specification 0x%08x", desc.fSpecification));
375       }
376       bHavePartitionCompressedData=true;
377       continue;
378     } else if (!TestBit(kSkipTrackClusters) &&
379                desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
380       iResult=decoder.ReadTrackModelClustersCompressed(fClusters->BeginTrackModelClusterBlock(0),
381                                                         reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
382                                                         desc.fSize,
383                                                         desc.fSpecification);
384       continue;
385     }
386   }
387
388   pSystem->ReleaseHLTOUT(pHLTOUT);
389
390   if (iResult<0) return iResult;
391 //   if (fVerbosity>0) {
392 //     int nConvertedClusters=0;
393 //     for (int s=0; s<72; s++) {
394 //       TObjArray* pArray=fClusters->GetSectorArray(s);
395 //       if (!pArray) continue;
396 //       nConvertedClusters+=pArray->GetEntriesFast();
397 //     }
398 //     AliInfo(Form("extracted HLT clusters: %d, converted HLT clusters: %d", nExtractedClusters, nConvertedClusters));
399 //   }
400
401   fCurrentSector=sector;
402 //   TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
403 //   if (!pArray) {
404 //     AliError(Form("can not get cluster array for sector %d", sector));
405 //     return -ENOBUFS;
406 //   }
407 //   if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
408   return 0; //pArray->GetEntriesFast();
409 }
410
411 AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::AliRawClusterContainer()
412   : fClusterMaps()
413   , fSectorArray(new TClonesArray(AliTPCclusterMI::Class()))
414   , fIterator()
415
416 {
417   /// constructor
418   for (int i=0; i<72; i++) {
419     fClusterMaps.push_back(new AliRawClusterEntryVector);
420     fClusterMaps.back()->reserve(30000);
421   }
422 }
423
424 AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::~AliRawClusterContainer()
425 {
426   /// dectructor
427   {
428     for (vector<AliRawClusterEntryVector*>::iterator i=fClusterMaps.begin(); i!=fClusterMaps.end(); i++) {
429       if (*i) {
430         delete *i;
431       }
432     }
433   }
434   if (fSectorArray) {
435     fSectorArray->Clear();
436     delete fSectorArray;
437     fSectorArray=NULL;
438   }
439 }
440
441 AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::BeginPartitionClusterBlock(int count, AliHLTUInt32_t specification)
442 {
443   /// iterator of remaining clusters block of specification
444
445   // reserve space in the array of all clusters
446   // reserve space in the map of the partition
447   unsigned index=AliHLTTPCDefinitions::GetMinSliceNr(specification);
448   AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(specification);
449   if (partition>=2) index+=36;
450   if (index<fClusterMaps.size() &&
451       fClusterMaps[index]!=NULL &&
452       fClusterMaps[index]->size()+count>fClusterMaps[index]->capacity()) {
453     fClusterMaps[index]->reserve(fClusterMaps[index]->size()+count);
454   }
455
456   fIterator=iterator(this);
457   return fIterator;
458 }
459
460 AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::BeginTrackModelClusterBlock(int /*count*/)
461 {
462   /// iterator of track model clusters
463   fIterator=iterator(this);
464   return fIterator;
465 }
466
467 AliHLTTPCClusterAccessHLTOUT::AliRawClusterEntry* AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::NextCluster(int slice, int partition)
468 {
469   /// load next cluster from array of the sepcific sector
470   unsigned sector=partition<2?slice:slice+36;
471   if (fClusterMaps.size()<=sector || 
472       fClusterMaps[sector]==NULL) {
473     AliErrorClass(Form("no cluster array available for sector %d", sector));
474     return NULL;
475   }
476   AliRawClusterEntryVector& map=*(fClusterMaps[sector]);
477   map.push_back(AliRawClusterEntry());
478   return &map.back();
479 }
480
481 void  AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::Clear(Option_t* /*option*/)
482 {
483   /// internal cleanup
484   {
485     for (vector<AliRawClusterEntryVector*>::iterator i=fClusterMaps.begin(); i!=fClusterMaps.end(); i++)
486       if (*i) (*i)->clear();
487   }
488   if (fSectorArray) fSectorArray->Clear();
489 }
490
491 TObjArray* AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::GetSectorArray(unsigned sector) const
492 {
493   /// get the cluster array for a sector
494   if (fClusterMaps.size()<=sector) return NULL;
495   if (fSectorArray &&
496       FillSectorArray(fSectorArray, sector)<0) {
497     fSectorArray->Clear();
498   }
499   return fSectorArray;
500 }
501
502 int AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::FillSectorArray(TClonesArray* pSectorArray, unsigned sector, int row) const
503 {
504   /// fill the cluster array for a sector and specific row if specified
505   if (!pSectorArray) return -EINVAL;
506   if (fClusterMaps.size()<=sector) return -ERANGE;
507   pSectorArray->Clear();
508
509   AliRawClusterEntryVector& map=*fClusterMaps[sector];
510   unsigned nFilled=0;
511   for (unsigned i=0; i<map.size(); i++) {    
512     if (row>=0 && map[i].fCluster.GetPadRow()!=row) continue;
513     AliTPCclusterMI* pCluster=new ((*pSectorArray)[nFilled]) AliTPCclusterMI;
514     if (!pCluster) break;
515     
516     pCluster->SetRow(map[i].fCluster.GetPadRow());
517     pCluster->SetPad(map[i].fCluster.GetPad());
518     pCluster->SetTimeBin(map[i].fCluster.GetTime());
519     pCluster->SetSigmaY2(map[i].fCluster.GetSigmaY2());
520     pCluster->SetSigmaZ2(map[i].fCluster.GetSigmaZ2());
521     pCluster->SetQ(map[i].fCluster.GetCharge());
522     pCluster->SetMax(map[i].fCluster.GetQMax());
523
524     for (int k=0; k<3; k++) {
525       // TODO: sort the labels according to the weight in order to assign the most likely mc label
526       // to the first component 
527       pCluster->SetLabel(map[i].fMC.fClusterID[k].fMCID, k);    
528     }
529     nFilled++;
530   }
531
532   return 0;
533 }
534
535 void AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::Print(Option_t *option) const
536 {
537   /// inherited from TObject
538   cout << "AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer" << endl;
539   ios::fmtflags coutflags=cout.flags(); // backup cout status flags
540   bool bAll=false;
541   if ((bAll=(strcmp(option, "full")==0)) ||
542       strcmp(option, "short")==0) {
543     for (unsigned iArray=0; iArray<fClusterMaps.size(); iArray++) {
544       if (fClusterMaps[iArray]) {
545         AliRawClusterEntryVector& map=*fClusterMaps[iArray];
546         cout << "  sector " << setfill(' ') << setw(2) << iArray << ": " << map.size() << endl;
547         if (bAll) {
548           for (unsigned iCluster=0; iCluster<map.size(); iCluster++) {
549             AliHLTTPCRawCluster &cluster = map[iCluster].fCluster;
550             cout << "    AliTPCclusterMI:"
551                  << "  row="    << cluster.GetPadRow() 
552                  << "  pad="    << cluster.GetPad()
553                  << "  time="   << cluster.GetTime()
554                  << "  charge=" << cluster.GetCharge()
555                  << "  maxq="   << cluster.GetQMax()
556                  << endl;
557           }
558         }
559       }
560     }
561   }
562   cout.flags(coutflags); // restore the original flags
563 }
564
565 AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliRawClusterContainer::iterator::Next(int slice, int partition)
566 {
567   // switch to next cluster
568   if (!fData) {
569     fEntry=NULL;
570     return *this;
571   }
572   if (fClusterNo>=0 && !fEntry) {
573     // end was reached before
574     return *this;
575   }
576   fEntry=fData->NextCluster(slice, partition);
577
578   // offline uses row number in physical sector, inner sector consists of
579   // partitions 0 and 1, outer sector of partition 2-5
580   fRowOffset=partition<2?0:AliHLTTPCTransform::GetFirstRow(2);
581   return *this;
582 }