]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/TPCLib/AliHLTTPCClusterAccessHLTOUT.cxx
fatal error in case of HLT TPC cluster decoding problems
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClusterAccessHLTOUT.cxx
CommitLineData
c54aa300 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"
b60d3f6a 26#include "AliHLTTPCDataCompressionDecoder.h"
c54aa300 27#include "AliHLTTPCDefinitions.h"
28#include "AliHLTTPCClusterDataFormat.h"
5e75f4e0 29#include "AliHLTTPCRawCluster.h"
61e66346 30#include "AliHLTTPCTransform.h"
c54aa300 31#include "AliHLTOUT.h"
81e7f739 32#include "AliHLTComponent.h"
73db5fa6 33#include "AliHLTErrorGuard.h"
61e66346 34#include "AliHLTDataInflater.h"
35#include "AliHLTTPCDefinitions.h"
c54aa300 36#include "AliLog.h"
37#include "AliHLTSystem.h"
38#include "AliHLTPluginBase.h"
39#include "AliTPCclusterMI.h"
40#include "TClonesArray.h"
81e7f739 41#include <cstdlib>
42#include <string>
43#include <memory>
b60d3f6a 44#include <iostream>
45#include <iomanip>
c54aa300 46
47/** ROOT macro for the implementation of ROOT specific class methods */
48ClassImp(AliHLTTPCClusterAccessHLTOUT)
49
50AliHLTTPCClusterAccessHLTOUT::AliHLTTPCClusterAccessHLTOUT()
51 : TObject()
81e7f739 52 , fVerbosity(0)
c54aa300 53 , fClusters(NULL)
b60d3f6a 54 , fCurrentSector(-1)
768dad20 55 , fpDecoder(NULL)
c54aa300 56{
57 // see header file for class documentation
58 // or
59 // refer to README to build package
60 // or
61 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
62}
63
64AliHLTTPCClusterAccessHLTOUT::~AliHLTTPCClusterAccessHLTOUT()
65{
66 // destructor
67 if (fClusters) {
68 fClusters->Clear();
69 delete fClusters;
70 fClusters=NULL;
71 }
768dad20 72 if (fpDecoder) {
73 fpDecoder->Clear();
74 delete fpDecoder;
75 fpDecoder=NULL;
76 }
c54aa300 77}
78
81e7f739 79void AliHLTTPCClusterAccessHLTOUT::Execute(const char *method, const char *params, Int_t *error)
c54aa300 80{
81 /// inherited from TObject: abstract command interface
82 if (strcmp(method, "read")==0) {
81e7f739 83 int iResult=ProcessClusters(params);
84 if (error) *error=iResult;
85 return;
86 }
87 if (strcmp(method, "verbosity")==0) {
88 int iResult=0;
89 if (params) {
90 char* dummy;
91 int value=strtol(params, &dummy, 0);
92 if (dummy==NULL) {
93 fVerbosity=value;
94 } else {
95 AliError("invalid argument for command 'verbosity', expecting string with number");
96 }
97 } else {
98 iResult=-EINVAL;
99 }
c54aa300 100 if (error) *error=iResult;
101 return;
102 }
103}
104
105TObject* AliHLTTPCClusterAccessHLTOUT::FindObject(const char *name) const
106{
107 /// inherited from TObject: return the cluster array if name id "clusterarray"
b60d3f6a 108 if (strcmp(name, "clusterarray")==0) {
109 if (fCurrentSector<0) return NULL;
110 return fClusters->GetSectorArray(fCurrentSector);
111 }
c54aa300 112 return TObject::FindObject(name);
113}
114
b60d3f6a 115void AliHLTTPCClusterAccessHLTOUT::Clear(Option_t * option)
c54aa300 116{
117 /// inherited from TObject: cleanup
b60d3f6a 118 if (strcmp(option, "event")==0) {
119 if (fClusters) fClusters->Clear();
120 fCurrentSector=-1;
121 }
c54aa300 122}
123
b60d3f6a 124void AliHLTTPCClusterAccessHLTOUT::Print(Option_t *option) const
c54aa300 125{
126 /// inherited from TObject
b60d3f6a 127 if (fClusters) fClusters->Print(option);
c54aa300 128}
129
81e7f739 130int AliHLTTPCClusterAccessHLTOUT::ProcessClusters(const char* params)
c54aa300 131{
132 /// process the cluster data from HLTOUT and fill array
133 /// the cluster data can be in many different formats, e.g.
134 /// raw or compressed
135 int iResult=0;
81e7f739 136 TString strparams(params);
b60d3f6a 137 int sector=-1;
81e7f739 138 std::auto_ptr<TObjArray> tokens(strparams.Tokenize(" "));
139 if (!tokens.get()) return -ENOMEM;
140 for (int i=0; i< tokens->GetEntriesFast(); i++) {
141 if (!tokens->At(i)) continue;
142 TString argument=tokens->At(i)->GetName();
b60d3f6a 143 // the offline code enumerates first the 36 inner (partitions 0+1) and then 36 outer
144 // sectors (partitions 2-5)
81e7f739 145 if (argument.BeginsWith("sector=")) {
146 argument.ReplaceAll("sector=", "");
b60d3f6a 147 sector=argument.Atoi();
81e7f739 148 }
149 }
b60d3f6a 150 if (sector<0) {
151 AliError("invalid argument, please specify \"sector=sectorno\"");
152 return -EINVAL;
153 }
154 if (sector>=76) {
155 AliError(Form("invalid sector number %d", sector));
156 return -EINVAL;
157 }
81e7f739 158
c54aa300 159 if (!fClusters) {
b60d3f6a 160 fClusters=new AliTPCclusterMIContainer;
c54aa300 161 }
162 if (!fClusters) return -ENOMEM;
163
b60d3f6a 164 if (fCurrentSector>=0) {
165 // cluster container already filled
166 fCurrentSector=sector;
167 TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
168 if (!pArray) {
169 AliError(Form("can not get cluster array for sector %d", sector));
170 return -ENOBUFS;
171 }
af9e48d7 172 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
b60d3f6a 173 return pArray->GetEntriesFast();
174 }
175
176 // fill the cluster container
c54aa300 177 AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
178 if (!pSystem) {
179 AliError("can not access HLT system");
180 return -ENODEV;
181 }
182 AliHLTOUT* pHLTOUT=pSystem->RequestHLTOUT();
183 if (!pHLTOUT) {
184 AliError("can not access HLTOUT");
b60d3f6a 185 return -EACCES;
c54aa300 186 }
187
768dad20 188 if (!fpDecoder) {
189 fpDecoder=new AliHLTTPCDataCompressionDecoder;
190 }
191
192 if (!fpDecoder) {
193 AliError("failed to create decoder instance");
194 return -ENODEV;
195 }
196
197 AliHLTTPCDataCompressionDecoder& decoder=*fpDecoder;
198 decoder.Clear();
efa1bd1b 199 decoder.SetVerbosity(fVerbosity);
200 decoder.EnableClusterMerger();
201
b60d3f6a 202 bool bNextBlock=false;
b60d3f6a 203 // add cluster id and mc information data blocks
204 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
205 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
206 AliHLTComponentBlockData desc;
207 // FIXME: extend HLTOUT to get the full descriptor
208 const AliHLTUInt8_t* buffer=NULL;
209 if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
210 continue;
211 }
212 desc.fPtr=(void*)buffer;
213 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
214 continue;
215 }
216 if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
217 // add mc information
efa1bd1b 218 if ((iResult=decoder.AddClusterMCData(&desc))<0) {
b60d3f6a 219 return iResult;
81e7f739 220 }
b60d3f6a 221 }
222 if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
223 desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
224 // add cluster ids
efa1bd1b 225 if ((iResult=decoder.AddClusterIds(&desc))<0) {
b60d3f6a 226 return iResult;
81e7f739 227 }
b60d3f6a 228 }
229 }
230
14f37d68 231 bool bHavePartitionRawData=false;
232 bool bHavePartitionCompressedData=false;
233 vector<bool> bHavePartitionData(216, false);
234
b60d3f6a 235 // read data
236 iResult=-ENODATA;
af9e48d7 237 int nExtractedClusters=0;
b60d3f6a 238 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
239 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
14f37d68 240 decoder.SetPadShift(0.0);
b60d3f6a 241 AliHLTComponentBlockData desc;
242 // FIXME: extend HLTOUT to get the full descriptor with one call
243 const AliHLTUInt8_t* buffer=NULL;
244 if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
245 continue;
246 }
247 desc.fPtr=(void*)buffer;
248 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
249 continue;
250 }
251 if (!TestBit(kSkipPartitionClusters) &&
14f37d68 252 (desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType())) {
253 // This is a special handling of data blocks produced with v5-01-Release
254 // The pad shift by 0.5 was not included in the data but was applied in the
255 // unpacking in this class. Changed in r51306, the next tag containing this
256 // change in the online system is v5-01-Rev-07. There are only very few runs
257 // of Sep 2011 with recorded clusters not containing the 0.5 shift
258 // There was also a chenge in the data type of the compressed partition
259 // cluster blocks which helps to identify the blocks which need the pad shift
260 // here
261 if (desc.fSize<sizeof(AliHLTTPCRawClusterData)) continue;
262 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(buffer);
263 if (!clusterData) continue;
264 if (clusterData->fVersion==1) {
265 // compressed clusters without the pad shift
266 // no raw clusters (version==0) have ever been recorded
267 decoder.SetPadShift(0.5);
268 }
269 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
270 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
271 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
272 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
273 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
274 "block specification 0x%08x", desc.fSpecification));
275 }
276 iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
277 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
278 desc.fSize,
279 desc.fSpecification);
be2dd46a 280 if (iResult>=0) nExtractedClusters+=iResult;
281 else {
282 AliFatal(Form("processing of cluster block 0x%08x failed with error code %d", desc.fSpecification, iResult));
283 }
14f37d68 284 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
285 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
286 if (bHavePartitionData[index]) {
287 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
288 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
289 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
290 "block specification 0x%08x", desc.fSpecification));
291 }
292 bHavePartitionData[index]=true;
293 if (bHavePartitionCompressedData) {
294 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
295 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
296 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
297 "block specification 0x%08x", desc.fSpecification));
298 }
299 bHavePartitionRawData=true;
300 continue;
301 } else if (!TestBit(kSkipPartitionClusters) &&
302 (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType())) {
303 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
304 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
305 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
306 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
307 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
308 "block specification 0x%08x", desc.fSpecification));
309 }
b60d3f6a 310 iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
311 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
312 desc.fSize,
313 desc.fSpecification);
af9e48d7 314 if (iResult>0) nExtractedClusters+=iResult;
14f37d68 315 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
316 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
317 if (bHavePartitionData[index]) {
318 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
319 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
320 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
321 "block specification 0x%08x", desc.fSpecification));
322 }
323 bHavePartitionData[index]=true;
324 bHavePartitionData[index]=true;
325 if (bHavePartitionRawData) {
326 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
327 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
328 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
329 "block specification 0x%08x", desc.fSpecification));
330 }
331 bHavePartitionCompressedData=true;
b60d3f6a 332 continue;
333 } else if (!TestBit(kSkipTrackClusters) &&
334 desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
335 iResult=decoder.ReadTrackModelClustersCompressed(fClusters->BeginTrackModelClusterBlock(0),
336 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
337 desc.fSize,
338 desc.fSpecification);
339 continue;
81e7f739 340 }
c54aa300 341 }
342
343 pSystem->ReleaseHLTOUT(pHLTOUT);
b60d3f6a 344
345 if (iResult<0) return iResult;
af9e48d7 346 if (fVerbosity>0) {
347 int nConvertedClusters=0;
348 for (int s=0; s<72; s++) {
349 TObjArray* pArray=fClusters->GetSectorArray(s);
350 if (!pArray) continue;
351 nConvertedClusters+=pArray->GetEntriesFast();
352 }
353 AliInfo(Form("extracted HLT clusters: %d, converted HLT clusters: %d", nExtractedClusters, nConvertedClusters));
354 }
355
b60d3f6a 356 fCurrentSector=sector;
357 TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
358 if (!pArray) {
359 AliError(Form("can not get cluster array for sector %d", sector));
360 return -ENOBUFS;
361 }
af9e48d7 362 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
b60d3f6a 363 return pArray->GetEntriesFast();
c54aa300 364}
365
81e7f739 366int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterMCData(AliHLTOUT* pHLTOUT, AliHLTTPCClusterMCDataList &tpcClusterLabels) const
367{
368 // read cluster data from AliHLTTPCClusterData
369 int iResult=0;
370 if (!pHLTOUT) return -EINVAL;
371 do {
372 const AliHLTUInt8_t* pBuffer=NULL;
373 AliHLTUInt32_t size=0;
374 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
375 continue;
376 }
377 if (pBuffer==NULL || size<4) {
378 AliError("invalid cluster mc data block");
379 continue;
380 }
381 const AliHLTTPCClusterMCData* clusterMCData = reinterpret_cast<const AliHLTTPCClusterMCData*>(pBuffer);
382 Int_t nLabels = (Int_t) clusterMCData->fCount;
383 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != size) {
384 AliError("inconsistent cluster mc data block size, skipping block");
385 continue;
386 }
387 // id of the cluster is
388 AliHLTComponentDataType dt=kAliHLTVoidDataType;
389 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
390 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
391 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
392 continue;
393 }
394 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
395 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
396 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(specification) ||
397 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(specification)) {
398 AliError(Form("can not read cluster mc data block with data of multiple partitions, skipping block %s %08x",
399 AliHLTComponent::DataType2Text(dt).c_str(), specification));
400 continue;
401 }
402 const AliHLTTPCClusterMCLabel *labels = clusterMCData->fLabels;
403 for (int i=0; i<nLabels; i++) {
404 AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, i);
405 if (tpcClusterLabels.find(id)==tpcClusterLabels.end()) {
406 // new cluster
407 tpcClusterLabels[id]=labels[i];
408 } else {
409 AliError(Form("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
410 id, i, specification));
411 }
412 }
413 } while (pHLTOUT->SelectNextDataBlock()>=0);
414 return iResult;
415}
416
417int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels) const
c54aa300 418{
419 // read cluster data from AliHLTTPCClusterData
420 int iResult=0;
421 if (!pHLTOUT || !pClusters) return -EINVAL;
422 do {
423 const AliHLTUInt8_t* pBuffer=NULL;
424 AliHLTUInt32_t size=0;
425 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
426 continue;
427 }
428 if (pBuffer==NULL || size<4) {
429 AliError("invalid cluster data block");
430 continue;
431 }
81e7f739 432 AliHLTComponentDataType dt=kAliHLTVoidDataType;
433 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
434 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
435 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
436 continue;
437 }
c54aa300 438 const AliHLTTPCClusterData* clusterData = reinterpret_cast<const AliHLTTPCClusterData*>(pBuffer);
439 Int_t nSpacepoints = (Int_t) clusterData->fSpacePointCnt;
440 if (nSpacepoints*sizeof(AliHLTTPCSpacePointData) + sizeof(AliHLTTPCClusterData) != size) {
441 AliError("inconsistent cluster data block size, skipping block");
442 continue;
443 }
444 const AliHLTTPCSpacePointData *clusters = clusterData->fSpacePoints;
81e7f739 445 int offset=pClusters->GetEntries();
446 pClusters->ExpandCreate(offset+nSpacepoints);
0e63cf4a 447 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
448 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
449 // FIXME: get first row number of outer sectors from a common definition instead using number
80874dc5 450 unsigned rowOffset=partition<2?0:63;
c54aa300 451 for (int i=0; i<nSpacepoints; i++) {
81e7f739 452 if (!pClusters->At(offset+i)) continue;
453 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
c54aa300 454 if (!pCluster) {
455 AliError("invalid object type, expecting AliTPCclusterMI");
456 break; // this is a problem of all objects
457 }
0e63cf4a 458 if (clusters[i].fPadRow<rowOffset) {
459 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].fPadRow, rowOffset, slice, partition));
460 } else {
461 pCluster->SetRow(clusters[i].fPadRow-rowOffset);
462 }
81e7f739 463 pCluster->SetPad(clusters[i].fY);
5e75f4e0 464 pCluster->SetTimeBin(clusters[i].fZ);
81e7f739 465 pCluster->SetSigmaY2(clusters[i].fSigmaY2);
466 pCluster->SetSigmaZ2(clusters[i].fSigmaZ2);
c54aa300 467 pCluster->SetQ(clusters[i].fCharge);
468 pCluster->SetMax(clusters[i].fQMax);
81e7f739 469 if (tpcClusterLabels) {
470 if (tpcClusterLabels->find(clusters[i].fID)!=tpcClusterLabels->end()) {
471 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusters[i].fID)->second.fClusterID;
472 for (int k=0; k<3; k++) {
473 // TODO: sort the labels according to the weight in order to assign the most likely mc label
474 // to the first component
475 pCluster->SetLabel(mcWeights[k].fMCID, k);
476 }
477 } else {
478 AliError(Form("can not find mc label of cluster with id %0x08x", clusters[i].fID));
479 }
480 }
c54aa300 481 }
1214ab89 482 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nSpacepoints, AliHLTComponent::DataType2Text(dt).c_str(), specification));
c54aa300 483 } while (pHLTOUT->SelectNextDataBlock()>=0);
484 return iResult;
485}
5e75f4e0 486
487int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
488{
489 // read cluster data from AliHLTTPCClusterData
490
491 // FIXME: this is in large parts like ReadAliHLTTPCClusterData,
492 // make a common method
493 int iResult=0;
494 if (!pHLTOUT || !pClusters) return -EINVAL;
495 do {
496 const AliHLTUInt8_t* pBuffer=NULL;
497 AliHLTUInt32_t size=0;
498 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
499 continue;
500 }
501 if (pBuffer==NULL || size<4) {
502 AliError("invalid cluster data block");
503 continue;
504 }
505 AliHLTComponentDataType dt=kAliHLTVoidDataType;
506 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
507 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
508 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
509 continue;
510 }
511 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
512 Int_t nCount = (Int_t) clusterData->fCount;
61e66346 513 if (clusterData->fVersion!=0) {
514 // this is encoded data of different formats
515 switch (clusterData->fVersion) {
516 case 1:
517 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
518 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
519 pClusters, tpcClusterLabels);
520 break;
521 default:
522 iResult=-EPROTO;
523 }
524 return iResult;
525 }
526
5e75f4e0 527 if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != size) {
528 AliError("inconsistent cluster data block size, skipping block");
529 continue;
530 }
531 const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
532 int offset=pClusters->GetEntries();
533 pClusters->ExpandCreate(offset+nCount);
0e63cf4a 534 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
535 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
536 // FIXME: get first row number of outer sectors from a common definition instead using number
80874dc5 537 int rowOffset=partition<2?0:63;
5e75f4e0 538 for (int i=0; i<nCount; i++) {
539 if (!pClusters->At(offset+i)) continue;
540 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
541 if (!pCluster) {
542 AliError("invalid object type, expecting AliTPCclusterMI");
543 break; // this is a problem of all objects
544 }
1214ab89 545 if (fVerbosity>1) AliInfo(Form("cluster padrow %d (slice %d partition %d)", clusters[i].GetPadRow(), slice, partition));
0e63cf4a 546 if (clusters[i].GetPadRow()<rowOffset) {
547 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].GetPadRow(), rowOffset, slice, partition));
548 } else {
549 pCluster->SetRow(clusters[i].GetPadRow()-rowOffset);
550 }
1b9cc91a 551 pCluster->SetPad(clusters[i].GetPad());
5e75f4e0 552 pCluster->SetTimeBin(clusters[i].GetTime());
553 pCluster->SetSigmaY2(clusters[i].GetSigmaY2());
554 pCluster->SetSigmaZ2(clusters[i].GetSigmaZ2());
555 pCluster->SetQ(clusters[i].GetCharge());
556 pCluster->SetMax(clusters[i].GetQMax());
557 if (tpcClusterLabels) {
5e75f4e0 558 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, i);
559 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
560 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
561 for (int k=0; k<3; k++) {
562 // TODO: sort the labels according to the weight in order to assign the most likely mc label
563 // to the first component
564 pCluster->SetLabel(mcWeights[k].fMCID, k);
565 }
566 } else {
567 AliError(Form("can not find mc label of cluster with id %0x08x", clusterID));
568 }
569 }
570 }
571 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
572 } while (pHLTOUT->SelectNextDataBlock()>=0);
573 return iResult;
574}
61e66346 575
2827cd62 576int AliHLTTPCClusterAccessHLTOUT::ReadRemainingClustersCompressed(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
577{
578 // read cluster data from AliHLTTPCClusterData
579 int iResult=0;
580 if (!pHLTOUT || !pClusters) return -EINVAL;
581 do {
582 const AliHLTUInt8_t* pBuffer=NULL;
583 AliHLTUInt32_t size=0;
584 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
585 continue;
586 }
587 if (pBuffer==NULL || size<4) {
588 AliError("invalid cluster data block");
589 continue;
590 }
591 AliHLTComponentDataType dt=kAliHLTVoidDataType;
592 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
593 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
594 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
595 continue;
596 }
597 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
598 Int_t nCount = (Int_t) clusterData->fCount;
599
600 // this is encoded data of different formats
601 switch (clusterData->fVersion) {
602 case 1:
603 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
604 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
605 pClusters, tpcClusterLabels);
606 break;
607 default:
608 AliError(Form("invalid cluster format version %d", clusterData->fVersion));
609 iResult=-EPROTO;
610 }
611
612 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
613 } while (pHLTOUT->SelectNextDataBlock()>=0 && iResult>=0);
614
615 return iResult;
616}
617
61e66346 618int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterDataDeflateSimple(const AliHLTUInt8_t* pData, int dataSize,
619 int nofClusters, AliHLTUInt32_t specification,
620 TClonesArray* pClusters,
621 const AliHLTTPCClusterMCDataList *tpcClusterLabels)
622{
623 // read cluster data from AliHLTTPCClusterData
624
625 // FIXME: quick implementation to read the compressed cluster data from HLTOUT
626 // the data definition below is the same as in AliHLTTPCDataCompressionComponent
627 // but needs to be moved to a common class (AliHLTTPCDefinitions?)
628 // Think about a decoder class supporting iterator objects for various types
629 // of cluster data
630 int iResult=0;
631 if (!pData || !pClusters) return -EINVAL;
632 AliHLTDataInflater inflater;
633 if ((iResult=inflater.InitBitDataInput(pData, dataSize))<0) {
634 return iResult;
635 }
636
637 int offset=pClusters->GetEntries();
638 pClusters->ExpandCreate(offset+nofClusters);
639 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
640 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
641 // the compressed format stores the difference of the local row number in
642 // the partition to the row of the last cluster
643 // add the first row in the partition to get global row number
644 // offline uses row number in physical sector, inner sector consists of
645 // partitions 0 and 1, outer sector of partition 2-5
646 int rowOffset=AliHLTTPCTransform::GetFirstRow(partition)-(partition<2?0:AliHLTTPCTransform::GetFirstRow(2));
647
648 int parameterId=0;
649 int outClusterCnt=0;
650 AliHLTUInt8_t switchBit=0;
651 AliHLTUInt64_t value=0;
652 AliTPCclusterMI* pCluster=NULL;
653 AliHLTUInt32_t lastPadRow=0;
654 while (outClusterCnt<nofClusters && inflater.InputBit(switchBit)) {
655 const AliHLTTPCDefinitions::AliClusterParameter& parameter
656 =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
657 // in mode DeflaterSimple, the optional parameter of the cluster parameter definition
658 // corresponds to the number bits of the reduced format
659 if (!inflater.InputBits(value, switchBit?parameter.fBitLength:parameter.fOptional)) {
660 break;
661 }
662
663 if (!pCluster) {
664 if (!pClusters->At(offset+outClusterCnt)) {
665 // here we should not get anymore because of the condition outClusterCnt<nofClusters
666 return -ENOSPC;
667 }
668 pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+outClusterCnt));
669 if (!pCluster) {
670 AliError("invalid object type, expecting AliTPCclusterMI");
671 iResult=-EBADF; // this is a problem of all objects
672 break;
673 }
674 }
675 switch (parameterId) {
676 case AliHLTTPCDefinitions::kPadRow:
677 {pCluster->SetRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
678 case AliHLTTPCDefinitions::kPad:
679 {float pad=value; pad/=parameter.fScale; pCluster->SetPad(pad); break;}
680 case AliHLTTPCDefinitions::kTime:
681 {float time=value; time/=parameter.fScale; pCluster->SetTimeBin(time); break;}
682 case AliHLTTPCDefinitions::kSigmaY2:
683 {float sigmaY2=value; sigmaY2/=parameter.fScale; pCluster->SetSigmaY2(sigmaY2); break;}
684 case AliHLTTPCDefinitions::kSigmaZ2:
685 {float sigmaZ2=value; sigmaZ2/=parameter.fScale; pCluster->SetSigmaZ2(sigmaZ2); break;}
686 case AliHLTTPCDefinitions::kCharge:
687 {pCluster->SetQ(value); break;}
688 case AliHLTTPCDefinitions::kQMax:
689 {pCluster->SetMax(value); break;}
690 }
691 if (parameterId>=AliHLTTPCDefinitions::kLast) {
692 // switch to next cluster
693 if (tpcClusterLabels) {
694 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, outClusterCnt);
695 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
696 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
697 for (int k=0; k<3; k++) {
698 // TODO: sort the labels according to the weight in order to assign the most likely mc label
699 // to the first component
700 pCluster->SetLabel(mcWeights[k].fMCID, k);
701 }
702 } else {
2827cd62 703 AliError(Form("can not find mc label of cluster with id 0x%08x", clusterID));
61e66346 704 }
705 }
706 outClusterCnt++;
707 pCluster=NULL;
708 parameterId=-1;
709 }
710 parameterId++;
711 }
712 inflater.Pad8Bits();
713 if (inflater.InputBit(switchBit)) {
714 AliWarning("format error of compressed clusters, there is more data than expected");
715 }
716 inflater.CloseBitDataInput();
717 if (iResult>=0 && nofClusters!=outClusterCnt) {
718 // is this a Fatal?
719 AliError(Form("error reading compressed cluster format: expected %d, read only %d cluster(s)", nofClusters, outClusterCnt));
720 return -EPROTO;
721 }
722 return iResult;
723}
b60d3f6a 724
725AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AliTPCclusterMIContainer()
726 : fClusterArrays()
727 , fRemainingClusterIds()
728 , fTrackModelClusterIds()
729 , fCurrentClusterIds(NULL)
730 , fClusterMCData()
731 , fIterator()
732
733{
734 /// constructor
735 for (int i=0; i<72; i++) {
736 fClusterArrays.push_back(new TClonesArray("AliTPCclusterMI"));
737 }
738}
739
740AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::~AliTPCclusterMIContainer()
741{
742 /// dectructor
743 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++) {
744 if (*i) {
745 (*i)->Clear();
746 delete *i;
747 }
748 }
749}
750
751AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginRemainingClusterBlock(int /*count*/, AliHLTUInt32_t specification)
752{
753 /// iterator of remaining clusters block of specification
754 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(specification);
755 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(specification);
756 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
757 if (index<fRemainingClusterIds.size())
758 fCurrentClusterIds=&fRemainingClusterIds[index];
759 else
760 fCurrentClusterIds=NULL;
761 fIterator=iterator(this);
762 return fIterator;
763}
764
765AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginTrackModelClusterBlock(int /*count*/)
766{
767 /// iterator of track model clusters
768 if (fTrackModelClusterIds.fIds && fTrackModelClusterIds.fSize>0)
769 fCurrentClusterIds=&fTrackModelClusterIds;
770 else
771 fCurrentClusterIds=NULL;
772 fIterator=iterator(this);
773 return fIterator;
774}
775
776int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterMCData(const AliHLTComponentBlockData* pDesc)
777{
778 /// add cluster mc data block
779 if (!pDesc) return -EINVAL;
780 if (pDesc->fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
781 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
782 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
783 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
784 if (fClusterMCData.size()<=index) {
785 if ((int)fClusterMCData.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
786 fClusterMCData.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches(), NULL);
787 } else {
788 fClusterMCData.resize(index+1, NULL);
789 }
790 }
791 if (pDesc->fSize<sizeof(AliHLTTPCClusterMCData)) return -EINVAL;
792 const AliHLTTPCClusterMCData* pData=reinterpret_cast<const AliHLTTPCClusterMCData*>(pDesc->fPtr);
793 unsigned nLabels = pData->fCount;
794 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != pDesc->fSize) {
795 return -EINVAL;
796 }
797 fClusterMCData[index]=pData;
798 return 0;
799 }
800 return -ENODATA;
801}
802
803int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterIds(const AliHLTComponentBlockData* pDesc)
804{
805 /// add cluster id block for remaining or track model clusters
806 if (!pDesc) return -EINVAL;
807 if (pDesc->fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
808 fTrackModelClusterIds.fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
809 fTrackModelClusterIds.fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
810 return 0;
811 }
812 if (pDesc->fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType()) {
813 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
814 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
815 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
816 if (fRemainingClusterIds.size()<=index) {
817 if ((int)fRemainingClusterIds.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
818 fRemainingClusterIds.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches());
819 } else {
820 fRemainingClusterIds.resize(index+1);
821 }
822 }
823 fRemainingClusterIds[index].fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
824 fRemainingClusterIds[index].fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
825 return 0;
826 }
827 return -ENODATA;
828}
829
830AliHLTUInt32_t AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetClusterId(int clusterNo) const
831{
832 /// get the cluster id from the current cluster id block (optional)
833 if (!fCurrentClusterIds ||
ebba640a 834 (int)fCurrentClusterIds->fSize<=clusterNo ||
835 clusterNo<0)
b60d3f6a 836 return kAliHLTVoidDataSpec;
837 return fCurrentClusterIds->fIds[clusterNo];
838}
839
840AliTPCclusterMI* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::NextCluster(int slice, int partition)
841{
842 /// load next cluster from array of the sepcific sector
843 unsigned sector=partition<2?slice:slice+36;
844 if (fClusterArrays.size()<=sector ||
845 fClusterArrays[sector]==NULL) {
846 AliErrorClass(Form("no cluster array available for sector %d", sector));
847 return NULL;
848 }
849 TClonesArray& array=*(fClusterArrays[sector]);
850 int count=array.GetEntriesFast();
851 return new (array[count]) AliTPCclusterMI;
852}
853
854int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::SetMC(AliTPCclusterMI* pCluster, AliHLTUInt32_t clusterId)
855{
856 /// set MC data for the cluster
857 if (!pCluster) return -EINVAL;
858 if (clusterId==kAliHLTVoidDataSpec) return 0;
859
860 unsigned slice=AliHLTTPCSpacePointData::GetSlice(clusterId);
861 unsigned partition=AliHLTTPCSpacePointData::GetPatch(clusterId);
862 unsigned number=AliHLTTPCSpacePointData::GetNumber(clusterId);
863 if ((int)slice>=AliHLTTPCTransform::GetNSlice() ||
864 (int)partition>=AliHLTTPCTransform::GetNumberOfPatches()) return -EDOM;
865 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
866 if (fClusterMCData.size()<=index ||
867 fClusterMCData[index]==NULL ||
868 fClusterMCData[index]->fCount<=number) return 0;
869 const AliHLTTPCClusterMCWeight* mcWeights=fClusterMCData[index]->fLabels[number].fClusterID;
870 for (int k=0; k<3; k++) {
871 // TODO: sort the labels according to the weight in order to assign the most likely mc label
872 // to the first component
873 pCluster->SetLabel(mcWeights[k].fMCID, k);
874 }
875
876 return 0;
877}
878
879void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Clear(Option_t* /*option*/)
880{
881 /// internal cleanup
882 {
883 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++)
884 if (*i) (*i)->Clear();
885 }
886 {
887 for (vector<AliClusterIdBlock>::iterator i=fRemainingClusterIds.begin(); i!=fRemainingClusterIds.end(); i++)
888 {i->fIds=NULL; i->fSize=0;}
889 }
890 fTrackModelClusterIds.fIds=NULL; fTrackModelClusterIds.fSize=0;
891 fCurrentClusterIds=NULL;
892 {
893 for (vector<const AliHLTTPCClusterMCData*>::iterator i=fClusterMCData.begin(); i!=fClusterMCData.end(); i++)
894 *i=NULL;
895 }
896}
897
898TObjArray* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetSectorArray(unsigned sector) const
899{
900 /// get the cluster array for a sector
901 if (fClusterArrays.size()<=sector) return NULL;
902 return fClusterArrays[sector];
903}
904
905void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Print(Option_t *option) const
906{
907 /// inherited from TObject
908 cout << "AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer" << endl;
909 ios::fmtflags coutflags=cout.flags(); // backup cout status flags
910 bool bAll=false;
911 if ((bAll=(strcmp(option, "full")==0)) ||
912 strcmp(option, "short")==0) {
913 for (unsigned iArray=0; iArray<fClusterArrays.size(); iArray++) {
914 if (fClusterArrays[iArray]) {
915 TClonesArray* pArray=fClusterArrays[iArray];
916 cout << " sector " << setfill(' ') << setw(2) << iArray << ": " << pArray->GetEntriesFast() << endl;
917 if (bAll) {
918 for (int iCluster=0; iCluster<pArray->GetEntriesFast(); iCluster++) {
919 if (!pArray->At(iCluster)) continue;
920 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pArray->At(iCluster));
921 if (!pCluster) break;
922 cout << " AliTPCclusterMI:"
923 << " row=" << pCluster->GetRow()
924 << " pad=" << pCluster->GetPad()
925 << " time=" << pCluster->GetTimeBin()
926 << " charge=" << pCluster->GetQ()
927 << " maxq=" << pCluster->GetMax()
928 << endl;
929 }
930 }
931 }
932 }
933 }
934 cout.flags(coutflags); // restore the original flags
935}
936
937AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator::Next(int slice, int partition)
938{
939 // switch to next cluster
940 if (!fData) {
941 fCluster=NULL;
942 fClusterId=kAliHLTVoidDataSpec;
943 return *this;
944 }
945 if (fClusterNo>=0 && !fCluster) {
946 // end was reached before
947 return *this;
948 }
949 fCluster=fData->NextCluster(slice, partition);
950 fClusterId=fData->GetClusterId(++fClusterNo);
951 if (fCluster && fClusterId!=kAliHLTVoidDataSpec) {
952 fData->SetMC(fCluster, fClusterId);
953 }
954 // offline uses row number in physical sector, inner sector consists of
955 // partitions 0 and 1, outer sector of partition 2-5
956 fRowOffset=partition<2?0:AliHLTTPCTransform::GetFirstRow(2);
957 return *this;
958}