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