3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
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 //**************************************************************************
19 /// @file AliHLTTPCClusterAccessHLTOUT.h
20 /// @author Matthias Richter
22 /// @brief Interface to HLT TPC clusters
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"
37 #include "AliHLTSystem.h"
38 #include "AliHLTPluginBase.h"
39 #include "AliTPCclusterMI.h"
40 #include "TClonesArray.h"
47 /** ROOT macro for the implementation of ROOT specific class methods */
48 ClassImp(AliHLTTPCClusterAccessHLTOUT)
50 AliHLTTPCClusterAccessHLTOUT::AliHLTTPCClusterAccessHLTOUT()
56 // see header file for class documentation
58 // refer to README to build package
60 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
63 AliHLTTPCClusterAccessHLTOUT::~AliHLTTPCClusterAccessHLTOUT()
73 void AliHLTTPCClusterAccessHLTOUT::Execute(const char *method, const char *params, Int_t *error)
75 /// inherited from TObject: abstract command interface
76 if (strcmp(method, "read")==0) {
77 int iResult=ProcessClusters(params);
78 if (error) *error=iResult;
81 if (strcmp(method, "verbosity")==0) {
85 int value=strtol(params, &dummy, 0);
89 AliError("invalid argument for command 'verbosity', expecting string with number");
94 if (error) *error=iResult;
99 TObject* AliHLTTPCClusterAccessHLTOUT::FindObject(const char *name) const
101 /// inherited from TObject: return the cluster array if name id "clusterarray"
102 if (strcmp(name, "clusterarray")==0) {
103 if (fCurrentSector<0) return NULL;
104 return fClusters->GetSectorArray(fCurrentSector);
106 return TObject::FindObject(name);
109 void AliHLTTPCClusterAccessHLTOUT::Clear(Option_t * option)
111 /// inherited from TObject: cleanup
112 if (strcmp(option, "event")==0) {
113 if (fClusters) fClusters->Clear();
118 void AliHLTTPCClusterAccessHLTOUT::Print(Option_t *option) const
120 /// inherited from TObject
121 if (fClusters) fClusters->Print(option);
124 int AliHLTTPCClusterAccessHLTOUT::ProcessClusters(const char* params)
126 /// process the cluster data from HLTOUT and fill array
127 /// the cluster data can be in many different formats, e.g.
128 /// raw or compressed
130 TString strparams(params);
132 std::auto_ptr<TObjArray> tokens(strparams.Tokenize(" "));
133 if (!tokens.get()) return -ENOMEM;
134 for (int i=0; i< tokens->GetEntriesFast(); i++) {
135 if (!tokens->At(i)) continue;
136 TString argument=tokens->At(i)->GetName();
137 // the offline code enumerates first the 36 inner (partitions 0+1) and then 36 outer
138 // sectors (partitions 2-5)
139 if (argument.BeginsWith("sector=")) {
140 argument.ReplaceAll("sector=", "");
141 sector=argument.Atoi();
145 AliError("invalid argument, please specify \"sector=sectorno\"");
149 AliError(Form("invalid sector number %d", sector));
154 fClusters=new AliTPCclusterMIContainer;
156 if (!fClusters) return -ENOMEM;
158 if (fCurrentSector>=0) {
159 // cluster container already filled
160 fCurrentSector=sector;
161 TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
163 AliError(Form("can not get cluster array for sector %d", sector));
166 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
167 return pArray->GetEntriesFast();
170 // fill the cluster container
171 AliHLTSystem* pSystem=AliHLTPluginBase::GetInstance();
173 AliError("can not access HLT system");
176 AliHLTOUT* pHLTOUT=pSystem->RequestHLTOUT();
178 AliError("can not access HLTOUT");
182 bool bNextBlock=false;
183 bool bHaveLabels=false;
185 // add cluster id and mc information data blocks
186 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
187 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
188 AliHLTComponentBlockData desc;
189 // FIXME: extend HLTOUT to get the full descriptor
190 const AliHLTUInt8_t* buffer=NULL;
191 if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
194 desc.fPtr=(void*)buffer;
195 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
198 if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
199 // add mc information
200 if ((iResult=fClusters->AddClusterMCData(&desc))<0) {
205 if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
206 desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
208 if ((iResult=fClusters->AddClusterIds(&desc))<0) {
215 bool bHavePartitionRawData=false;
216 bool bHavePartitionCompressedData=false;
217 vector<bool> bHavePartitionData(216, false);
221 AliHLTTPCDataCompressionDecoder decoder;
222 decoder.SetVerbosity(fVerbosity);
223 decoder.EnableClusterMerger();
224 int nExtractedClusters=0;
225 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
226 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
227 decoder.SetPadShift(0.0);
228 AliHLTComponentBlockData desc;
229 // FIXME: extend HLTOUT to get the full descriptor with one call
230 const AliHLTUInt8_t* buffer=NULL;
231 if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
234 desc.fPtr=(void*)buffer;
235 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
238 if (!TestBit(kSkipPartitionClusters) &&
239 (desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType())) {
240 // This is a special handling of data blocks produced with v5-01-Release
241 // The pad shift by 0.5 was not included in the data but was applied in the
242 // unpacking in this class. Changed in r51306, the next tag containing this
243 // change in the online system is v5-01-Rev-07. There are only very few runs
244 // of Sep 2011 with recorded clusters not containing the 0.5 shift
245 // There was also a chenge in the data type of the compressed partition
246 // cluster blocks which helps to identify the blocks which need the pad shift
248 if (desc.fSize<sizeof(AliHLTTPCRawClusterData)) continue;
249 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(buffer);
250 if (!clusterData) continue;
251 if (clusterData->fVersion==1) {
252 // compressed clusters without the pad shift
253 // no raw clusters (version==0) have ever been recorded
254 decoder.SetPadShift(0.5);
256 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
257 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
258 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
259 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
260 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
261 "block specification 0x%08x", desc.fSpecification));
263 iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
264 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
266 desc.fSpecification);
267 if (iResult>0) nExtractedClusters+=iResult;
268 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
269 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
270 if (bHavePartitionData[index]) {
271 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
272 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
273 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
274 "block specification 0x%08x", desc.fSpecification));
276 bHavePartitionData[index]=true;
277 if (bHavePartitionCompressedData) {
278 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
279 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
280 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
281 "block specification 0x%08x", desc.fSpecification));
283 bHavePartitionRawData=true;
285 } else if (!TestBit(kSkipPartitionClusters) &&
286 (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType())) {
287 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(desc.fSpecification);
288 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(desc.fSpecification);
289 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(desc.fSpecification) ||
290 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(desc.fSpecification)) {
291 AliFatal(Form("inconsistent cluster data: can not handle blocks containing multiple partitions, "
292 "block specification 0x%08x", desc.fSpecification));
294 iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
295 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
297 desc.fSpecification);
298 if (iResult>0) nExtractedClusters+=iResult;
299 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
300 if (index>=bHavePartitionData.size()) bHavePartitionData.resize(index, false);
301 if (bHavePartitionData[index]) {
302 AliFatal(Form("inconsistent cluster data: multiple data blocks of identical specification indicate a failure "
303 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
304 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
305 "block specification 0x%08x", desc.fSpecification));
307 bHavePartitionData[index]=true;
308 bHavePartitionData[index]=true;
309 if (bHavePartitionRawData) {
310 AliFatal(Form("inconsistent cluster data: both compressed and raw cluster blocks present in HLTOUT, indicates a failure "
311 "in the production of the data. Probably an HLT emulation chain is executed in the reconstruction "
312 "and produces data in addition to HLTOUT. Option 'ignore-hltout' is required in that case; "
313 "block specification 0x%08x", desc.fSpecification));
315 bHavePartitionCompressedData=true;
317 } else if (!TestBit(kSkipTrackClusters) &&
318 desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
319 iResult=decoder.ReadTrackModelClustersCompressed(fClusters->BeginTrackModelClusterBlock(0),
320 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
322 desc.fSpecification);
327 pSystem->ReleaseHLTOUT(pHLTOUT);
329 if (iResult<0) return iResult;
331 int nConvertedClusters=0;
332 for (int s=0; s<72; s++) {
333 TObjArray* pArray=fClusters->GetSectorArray(s);
334 if (!pArray) continue;
335 nConvertedClusters+=pArray->GetEntriesFast();
337 AliInfo(Form("extracted HLT clusters: %d, converted HLT clusters: %d", nExtractedClusters, nConvertedClusters));
340 fCurrentSector=sector;
341 TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
343 AliError(Form("can not get cluster array for sector %d", sector));
346 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
347 return pArray->GetEntriesFast();
350 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterMCData(AliHLTOUT* pHLTOUT, AliHLTTPCClusterMCDataList &tpcClusterLabels) const
352 // read cluster data from AliHLTTPCClusterData
354 if (!pHLTOUT) return -EINVAL;
356 const AliHLTUInt8_t* pBuffer=NULL;
357 AliHLTUInt32_t size=0;
358 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
361 if (pBuffer==NULL || size<4) {
362 AliError("invalid cluster mc data block");
365 const AliHLTTPCClusterMCData* clusterMCData = reinterpret_cast<const AliHLTTPCClusterMCData*>(pBuffer);
366 Int_t nLabels = (Int_t) clusterMCData->fCount;
367 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != size) {
368 AliError("inconsistent cluster mc data block size, skipping block");
371 // id of the cluster is
372 AliHLTComponentDataType dt=kAliHLTVoidDataType;
373 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
374 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
375 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
378 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
379 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
380 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(specification) ||
381 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(specification)) {
382 AliError(Form("can not read cluster mc data block with data of multiple partitions, skipping block %s %08x",
383 AliHLTComponent::DataType2Text(dt).c_str(), specification));
386 const AliHLTTPCClusterMCLabel *labels = clusterMCData->fLabels;
387 for (int i=0; i<nLabels; i++) {
388 AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, i);
389 if (tpcClusterLabels.find(id)==tpcClusterLabels.end()) {
391 tpcClusterLabels[id]=labels[i];
393 AliError(Form("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
394 id, i, specification));
397 } while (pHLTOUT->SelectNextDataBlock()>=0);
401 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels) const
403 // read cluster data from AliHLTTPCClusterData
405 if (!pHLTOUT || !pClusters) return -EINVAL;
407 const AliHLTUInt8_t* pBuffer=NULL;
408 AliHLTUInt32_t size=0;
409 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
412 if (pBuffer==NULL || size<4) {
413 AliError("invalid cluster data block");
416 AliHLTComponentDataType dt=kAliHLTVoidDataType;
417 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
418 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
419 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
422 const AliHLTTPCClusterData* clusterData = reinterpret_cast<const AliHLTTPCClusterData*>(pBuffer);
423 Int_t nSpacepoints = (Int_t) clusterData->fSpacePointCnt;
424 if (nSpacepoints*sizeof(AliHLTTPCSpacePointData) + sizeof(AliHLTTPCClusterData) != size) {
425 AliError("inconsistent cluster data block size, skipping block");
428 const AliHLTTPCSpacePointData *clusters = clusterData->fSpacePoints;
429 int offset=pClusters->GetEntries();
430 pClusters->ExpandCreate(offset+nSpacepoints);
431 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
432 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
433 // FIXME: get first row number of outer sectors from a common definition instead using number
434 unsigned rowOffset=partition<2?0:63;
435 for (int i=0; i<nSpacepoints; i++) {
436 if (!pClusters->At(offset+i)) continue;
437 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
439 AliError("invalid object type, expecting AliTPCclusterMI");
440 break; // this is a problem of all objects
442 if (clusters[i].fPadRow<rowOffset) {
443 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].fPadRow, rowOffset, slice, partition));
445 pCluster->SetRow(clusters[i].fPadRow-rowOffset);
447 pCluster->SetPad(clusters[i].fY);
448 pCluster->SetTimeBin(clusters[i].fZ);
449 pCluster->SetSigmaY2(clusters[i].fSigmaY2);
450 pCluster->SetSigmaZ2(clusters[i].fSigmaZ2);
451 pCluster->SetQ(clusters[i].fCharge);
452 pCluster->SetMax(clusters[i].fQMax);
453 if (tpcClusterLabels) {
454 if (tpcClusterLabels->find(clusters[i].fID)!=tpcClusterLabels->end()) {
455 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusters[i].fID)->second.fClusterID;
456 for (int k=0; k<3; k++) {
457 // TODO: sort the labels according to the weight in order to assign the most likely mc label
458 // to the first component
459 pCluster->SetLabel(mcWeights[k].fMCID, k);
462 AliError(Form("can not find mc label of cluster with id %0x08x", clusters[i].fID));
466 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nSpacepoints, AliHLTComponent::DataType2Text(dt).c_str(), specification));
467 } while (pHLTOUT->SelectNextDataBlock()>=0);
471 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
473 // read cluster data from AliHLTTPCClusterData
475 // FIXME: this is in large parts like ReadAliHLTTPCClusterData,
476 // make a common method
478 if (!pHLTOUT || !pClusters) return -EINVAL;
480 const AliHLTUInt8_t* pBuffer=NULL;
481 AliHLTUInt32_t size=0;
482 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
485 if (pBuffer==NULL || size<4) {
486 AliError("invalid cluster data block");
489 AliHLTComponentDataType dt=kAliHLTVoidDataType;
490 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
491 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
492 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
495 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
496 Int_t nCount = (Int_t) clusterData->fCount;
497 if (clusterData->fVersion!=0) {
498 // this is encoded data of different formats
499 switch (clusterData->fVersion) {
501 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
502 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
503 pClusters, tpcClusterLabels);
511 if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != size) {
512 AliError("inconsistent cluster data block size, skipping block");
515 const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
516 int offset=pClusters->GetEntries();
517 pClusters->ExpandCreate(offset+nCount);
518 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
519 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
520 // FIXME: get first row number of outer sectors from a common definition instead using number
521 int rowOffset=partition<2?0:63;
522 for (int i=0; i<nCount; i++) {
523 if (!pClusters->At(offset+i)) continue;
524 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
526 AliError("invalid object type, expecting AliTPCclusterMI");
527 break; // this is a problem of all objects
529 if (fVerbosity>1) AliInfo(Form("cluster padrow %d (slice %d partition %d)", clusters[i].GetPadRow(), slice, partition));
530 if (clusters[i].GetPadRow()<rowOffset) {
531 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].GetPadRow(), rowOffset, slice, partition));
533 pCluster->SetRow(clusters[i].GetPadRow()-rowOffset);
535 pCluster->SetPad(clusters[i].GetPad());
536 pCluster->SetTimeBin(clusters[i].GetTime());
537 pCluster->SetSigmaY2(clusters[i].GetSigmaY2());
538 pCluster->SetSigmaZ2(clusters[i].GetSigmaZ2());
539 pCluster->SetQ(clusters[i].GetCharge());
540 pCluster->SetMax(clusters[i].GetQMax());
541 if (tpcClusterLabels) {
542 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, i);
543 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
544 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
545 for (int k=0; k<3; k++) {
546 // TODO: sort the labels according to the weight in order to assign the most likely mc label
547 // to the first component
548 pCluster->SetLabel(mcWeights[k].fMCID, k);
551 AliError(Form("can not find mc label of cluster with id %0x08x", clusterID));
555 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
556 } while (pHLTOUT->SelectNextDataBlock()>=0);
560 int AliHLTTPCClusterAccessHLTOUT::ReadRemainingClustersCompressed(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
562 // read cluster data from AliHLTTPCClusterData
564 if (!pHLTOUT || !pClusters) return -EINVAL;
566 const AliHLTUInt8_t* pBuffer=NULL;
567 AliHLTUInt32_t size=0;
568 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
571 if (pBuffer==NULL || size<4) {
572 AliError("invalid cluster data block");
575 AliHLTComponentDataType dt=kAliHLTVoidDataType;
576 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
577 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
578 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
581 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
582 Int_t nCount = (Int_t) clusterData->fCount;
584 // this is encoded data of different formats
585 switch (clusterData->fVersion) {
587 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
588 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
589 pClusters, tpcClusterLabels);
592 AliError(Form("invalid cluster format version %d", clusterData->fVersion));
596 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
597 } while (pHLTOUT->SelectNextDataBlock()>=0 && iResult>=0);
602 int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterDataDeflateSimple(const AliHLTUInt8_t* pData, int dataSize,
603 int nofClusters, AliHLTUInt32_t specification,
604 TClonesArray* pClusters,
605 const AliHLTTPCClusterMCDataList *tpcClusterLabels)
607 // read cluster data from AliHLTTPCClusterData
609 // FIXME: quick implementation to read the compressed cluster data from HLTOUT
610 // the data definition below is the same as in AliHLTTPCDataCompressionComponent
611 // but needs to be moved to a common class (AliHLTTPCDefinitions?)
612 // Think about a decoder class supporting iterator objects for various types
615 if (!pData || !pClusters) return -EINVAL;
616 AliHLTDataInflater inflater;
617 if ((iResult=inflater.InitBitDataInput(pData, dataSize))<0) {
621 int offset=pClusters->GetEntries();
622 pClusters->ExpandCreate(offset+nofClusters);
623 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
624 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
625 // the compressed format stores the difference of the local row number in
626 // the partition to the row of the last cluster
627 // add the first row in the partition to get global row number
628 // offline uses row number in physical sector, inner sector consists of
629 // partitions 0 and 1, outer sector of partition 2-5
630 int rowOffset=AliHLTTPCTransform::GetFirstRow(partition)-(partition<2?0:AliHLTTPCTransform::GetFirstRow(2));
634 AliHLTUInt8_t switchBit=0;
635 AliHLTUInt64_t value=0;
636 AliTPCclusterMI* pCluster=NULL;
637 AliHLTUInt32_t lastPadRow=0;
638 while (outClusterCnt<nofClusters && inflater.InputBit(switchBit)) {
639 const AliHLTTPCDefinitions::AliClusterParameter& parameter
640 =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
641 // in mode DeflaterSimple, the optional parameter of the cluster parameter definition
642 // corresponds to the number bits of the reduced format
643 if (!inflater.InputBits(value, switchBit?parameter.fBitLength:parameter.fOptional)) {
648 if (!pClusters->At(offset+outClusterCnt)) {
649 // here we should not get anymore because of the condition outClusterCnt<nofClusters
652 pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+outClusterCnt));
654 AliError("invalid object type, expecting AliTPCclusterMI");
655 iResult=-EBADF; // this is a problem of all objects
659 switch (parameterId) {
660 case AliHLTTPCDefinitions::kPadRow:
661 {pCluster->SetRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
662 case AliHLTTPCDefinitions::kPad:
663 {float pad=value; pad/=parameter.fScale; pCluster->SetPad(pad); break;}
664 case AliHLTTPCDefinitions::kTime:
665 {float time=value; time/=parameter.fScale; pCluster->SetTimeBin(time); break;}
666 case AliHLTTPCDefinitions::kSigmaY2:
667 {float sigmaY2=value; sigmaY2/=parameter.fScale; pCluster->SetSigmaY2(sigmaY2); break;}
668 case AliHLTTPCDefinitions::kSigmaZ2:
669 {float sigmaZ2=value; sigmaZ2/=parameter.fScale; pCluster->SetSigmaZ2(sigmaZ2); break;}
670 case AliHLTTPCDefinitions::kCharge:
671 {pCluster->SetQ(value); break;}
672 case AliHLTTPCDefinitions::kQMax:
673 {pCluster->SetMax(value); break;}
675 if (parameterId>=AliHLTTPCDefinitions::kLast) {
676 // switch to next cluster
677 if (tpcClusterLabels) {
678 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, outClusterCnt);
679 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
680 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
681 for (int k=0; k<3; k++) {
682 // TODO: sort the labels according to the weight in order to assign the most likely mc label
683 // to the first component
684 pCluster->SetLabel(mcWeights[k].fMCID, k);
687 AliError(Form("can not find mc label of cluster with id 0x%08x", clusterID));
697 if (inflater.InputBit(switchBit)) {
698 AliWarning("format error of compressed clusters, there is more data than expected");
700 inflater.CloseBitDataInput();
701 if (iResult>=0 && nofClusters!=outClusterCnt) {
703 AliError(Form("error reading compressed cluster format: expected %d, read only %d cluster(s)", nofClusters, outClusterCnt));
709 AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AliTPCclusterMIContainer()
711 , fRemainingClusterIds()
712 , fTrackModelClusterIds()
713 , fCurrentClusterIds(NULL)
719 for (int i=0; i<72; i++) {
720 fClusterArrays.push_back(new TClonesArray("AliTPCclusterMI"));
724 AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::~AliTPCclusterMIContainer()
727 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++) {
735 AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginRemainingClusterBlock(int /*count*/, AliHLTUInt32_t specification)
737 /// iterator of remaining clusters block of specification
738 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(specification);
739 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(specification);
740 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
741 if (index<fRemainingClusterIds.size())
742 fCurrentClusterIds=&fRemainingClusterIds[index];
744 fCurrentClusterIds=NULL;
745 fIterator=iterator(this);
749 AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginTrackModelClusterBlock(int /*count*/)
751 /// iterator of track model clusters
752 if (fTrackModelClusterIds.fIds && fTrackModelClusterIds.fSize>0)
753 fCurrentClusterIds=&fTrackModelClusterIds;
755 fCurrentClusterIds=NULL;
756 fIterator=iterator(this);
760 int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterMCData(const AliHLTComponentBlockData* pDesc)
762 /// add cluster mc data block
763 if (!pDesc) return -EINVAL;
764 if (pDesc->fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
765 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
766 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
767 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
768 if (fClusterMCData.size()<=index) {
769 if ((int)fClusterMCData.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
770 fClusterMCData.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches(), NULL);
772 fClusterMCData.resize(index+1, NULL);
775 if (pDesc->fSize<sizeof(AliHLTTPCClusterMCData)) return -EINVAL;
776 const AliHLTTPCClusterMCData* pData=reinterpret_cast<const AliHLTTPCClusterMCData*>(pDesc->fPtr);
777 unsigned nLabels = pData->fCount;
778 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != pDesc->fSize) {
781 fClusterMCData[index]=pData;
787 int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterIds(const AliHLTComponentBlockData* pDesc)
789 /// add cluster id block for remaining or track model clusters
790 if (!pDesc) return -EINVAL;
791 if (pDesc->fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
792 fTrackModelClusterIds.fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
793 fTrackModelClusterIds.fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
796 if (pDesc->fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType()) {
797 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
798 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
799 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
800 if (fRemainingClusterIds.size()<=index) {
801 if ((int)fRemainingClusterIds.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
802 fRemainingClusterIds.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches());
804 fRemainingClusterIds.resize(index+1);
807 fRemainingClusterIds[index].fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
808 fRemainingClusterIds[index].fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
814 AliHLTUInt32_t AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetClusterId(int clusterNo) const
816 /// get the cluster id from the current cluster id block (optional)
817 if (!fCurrentClusterIds ||
818 (int)fCurrentClusterIds->fSize<=clusterNo ||
820 return kAliHLTVoidDataSpec;
821 return fCurrentClusterIds->fIds[clusterNo];
824 AliTPCclusterMI* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::NextCluster(int slice, int partition)
826 /// load next cluster from array of the sepcific sector
827 unsigned sector=partition<2?slice:slice+36;
828 if (fClusterArrays.size()<=sector ||
829 fClusterArrays[sector]==NULL) {
830 AliErrorClass(Form("no cluster array available for sector %d", sector));
833 TClonesArray& array=*(fClusterArrays[sector]);
834 int count=array.GetEntriesFast();
835 return new (array[count]) AliTPCclusterMI;
838 int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::SetMC(AliTPCclusterMI* pCluster, AliHLTUInt32_t clusterId)
840 /// set MC data for the cluster
841 if (!pCluster) return -EINVAL;
842 if (clusterId==kAliHLTVoidDataSpec) return 0;
844 unsigned slice=AliHLTTPCSpacePointData::GetSlice(clusterId);
845 unsigned partition=AliHLTTPCSpacePointData::GetPatch(clusterId);
846 unsigned number=AliHLTTPCSpacePointData::GetNumber(clusterId);
847 if ((int)slice>=AliHLTTPCTransform::GetNSlice() ||
848 (int)partition>=AliHLTTPCTransform::GetNumberOfPatches()) return -EDOM;
849 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
850 if (fClusterMCData.size()<=index ||
851 fClusterMCData[index]==NULL ||
852 fClusterMCData[index]->fCount<=number) return 0;
853 const AliHLTTPCClusterMCWeight* mcWeights=fClusterMCData[index]->fLabels[number].fClusterID;
854 for (int k=0; k<3; k++) {
855 // TODO: sort the labels according to the weight in order to assign the most likely mc label
856 // to the first component
857 pCluster->SetLabel(mcWeights[k].fMCID, k);
863 void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Clear(Option_t* /*option*/)
867 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++)
868 if (*i) (*i)->Clear();
871 for (vector<AliClusterIdBlock>::iterator i=fRemainingClusterIds.begin(); i!=fRemainingClusterIds.end(); i++)
872 {i->fIds=NULL; i->fSize=0;}
874 fTrackModelClusterIds.fIds=NULL; fTrackModelClusterIds.fSize=0;
875 fCurrentClusterIds=NULL;
877 for (vector<const AliHLTTPCClusterMCData*>::iterator i=fClusterMCData.begin(); i!=fClusterMCData.end(); i++)
882 TObjArray* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetSectorArray(unsigned sector) const
884 /// get the cluster array for a sector
885 if (fClusterArrays.size()<=sector) return NULL;
886 return fClusterArrays[sector];
889 void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Print(Option_t *option) const
891 /// inherited from TObject
892 cout << "AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer" << endl;
893 ios::fmtflags coutflags=cout.flags(); // backup cout status flags
895 if ((bAll=(strcmp(option, "full")==0)) ||
896 strcmp(option, "short")==0) {
897 for (unsigned iArray=0; iArray<fClusterArrays.size(); iArray++) {
898 if (fClusterArrays[iArray]) {
899 TClonesArray* pArray=fClusterArrays[iArray];
900 cout << " sector " << setfill(' ') << setw(2) << iArray << ": " << pArray->GetEntriesFast() << endl;
902 for (int iCluster=0; iCluster<pArray->GetEntriesFast(); iCluster++) {
903 if (!pArray->At(iCluster)) continue;
904 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pArray->At(iCluster));
905 if (!pCluster) break;
906 cout << " AliTPCclusterMI:"
907 << " row=" << pCluster->GetRow()
908 << " pad=" << pCluster->GetPad()
909 << " time=" << pCluster->GetTimeBin()
910 << " charge=" << pCluster->GetQ()
911 << " maxq=" << pCluster->GetMax()
918 cout.flags(coutflags); // restore the original flags
921 AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator::Next(int slice, int partition)
923 // switch to next cluster
926 fClusterId=kAliHLTVoidDataSpec;
929 if (fClusterNo>=0 && !fCluster) {
930 // end was reached before
933 fCluster=fData->NextCluster(slice, partition);
934 fClusterId=fData->GetClusterId(++fClusterNo);
935 if (fCluster && fClusterId!=kAliHLTVoidDataSpec) {
936 fData->SetMC(fCluster, fClusterId);
938 // offline uses row number in physical sector, inner sector consists of
939 // partitions 0 and 1, outer sector of partition 2-5
940 fRowOffset=partition<2?0:AliHLTTPCTransform::GetFirstRow(2);