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