Add AliEMCALRecoUtils pointer to remove bad or exotic clusters for cluster histograms...
[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
b60d3f6a 182 bool bNextBlock=false;
183 bool bHaveLabels=false;
184 bool bHaveIds=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) {
192 continue;
193 }
194 desc.fPtr=(void*)buffer;
195 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
196 continue;
197 }
198 if (desc.fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
199 // add mc information
200 if ((iResult=fClusters->AddClusterMCData(&desc))<0) {
201 return iResult;
81e7f739 202 }
b60d3f6a 203 bHaveLabels=true;
204 }
205 if (desc.fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
206 desc.fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
207 // add cluster ids
208 if ((iResult=fClusters->AddClusterIds(&desc))<0) {
209 return iResult;
81e7f739 210 }
b60d3f6a 211 bHaveIds=true;
212 }
213 }
214
215 // read data
216 iResult=-ENODATA;
217 AliHLTTPCDataCompressionDecoder decoder;
af9e48d7 218 decoder.SetVerbosity(fVerbosity);
219 int nExtractedClusters=0;
b60d3f6a 220 for (bNextBlock=(pHLTOUT->SelectFirstDataBlock()>=0);
221 bNextBlock; bNextBlock=(pHLTOUT->SelectNextDataBlock()>=0)) {
222 AliHLTComponentBlockData desc;
223 // FIXME: extend HLTOUT to get the full descriptor with one call
224 const AliHLTUInt8_t* buffer=NULL;
225 if ((iResult=pHLTOUT->GetDataBuffer(buffer, desc.fSize))<0) {
226 continue;
227 }
228 desc.fPtr=(void*)buffer;
229 if (pHLTOUT->GetDataBlockDescription(desc.fDataType, desc.fSpecification)<0) {
230 continue;
231 }
232 if (!TestBit(kSkipPartitionClusters) &&
233 (desc.fDataType==AliHLTTPCDefinitions::RemainingClustersCompressedDataType() ||
234 desc.fDataType==AliHLTTPCDefinitions::RawClustersDataType())) {
235 iResult=decoder.ReadClustersPartition(fClusters->BeginRemainingClusterBlock(0, desc.fSpecification),
236 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
237 desc.fSize,
238 desc.fSpecification);
af9e48d7 239 if (iResult>0) nExtractedClusters+=iResult;
b60d3f6a 240 continue;
241 } else if (!TestBit(kSkipTrackClusters) &&
242 desc.fDataType==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
243 iResult=decoder.ReadTrackModelClustersCompressed(fClusters->BeginTrackModelClusterBlock(0),
244 reinterpret_cast<AliHLTUInt8_t*>(desc.fPtr),
245 desc.fSize,
246 desc.fSpecification);
247 continue;
81e7f739 248 }
c54aa300 249 }
250
251 pSystem->ReleaseHLTOUT(pHLTOUT);
b60d3f6a 252
253 if (iResult<0) return iResult;
af9e48d7 254 if (fVerbosity>0) {
255 int nConvertedClusters=0;
256 for (int s=0; s<72; s++) {
257 TObjArray* pArray=fClusters->GetSectorArray(s);
258 if (!pArray) continue;
259 nConvertedClusters+=pArray->GetEntriesFast();
260 }
261 AliInfo(Form("extracted HLT clusters: %d, converted HLT clusters: %d", nExtractedClusters, nConvertedClusters));
262 }
263
b60d3f6a 264 fCurrentSector=sector;
265 TObjArray* pArray=fClusters->GetSectorArray(fCurrentSector);
266 if (!pArray) {
267 AliError(Form("can not get cluster array for sector %d", sector));
268 return -ENOBUFS;
269 }
af9e48d7 270 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) for sector %d", pArray->GetEntriesFast() ,sector));
b60d3f6a 271 return pArray->GetEntriesFast();
c54aa300 272}
273
81e7f739 274int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterMCData(AliHLTOUT* pHLTOUT, AliHLTTPCClusterMCDataList &tpcClusterLabels) const
275{
276 // read cluster data from AliHLTTPCClusterData
277 int iResult=0;
278 if (!pHLTOUT) return -EINVAL;
279 do {
280 const AliHLTUInt8_t* pBuffer=NULL;
281 AliHLTUInt32_t size=0;
282 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
283 continue;
284 }
285 if (pBuffer==NULL || size<4) {
286 AliError("invalid cluster mc data block");
287 continue;
288 }
289 const AliHLTTPCClusterMCData* clusterMCData = reinterpret_cast<const AliHLTTPCClusterMCData*>(pBuffer);
290 Int_t nLabels = (Int_t) clusterMCData->fCount;
291 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != size) {
292 AliError("inconsistent cluster mc data block size, skipping block");
293 continue;
294 }
295 // id of the cluster is
296 AliHLTComponentDataType dt=kAliHLTVoidDataType;
297 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
298 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
299 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
300 continue;
301 }
302 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
303 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
304 if (slice!=AliHLTTPCDefinitions::GetMaxSliceNr(specification) ||
305 partition!=AliHLTTPCDefinitions::GetMaxPatchNr(specification)) {
306 AliError(Form("can not read cluster mc data block with data of multiple partitions, skipping block %s %08x",
307 AliHLTComponent::DataType2Text(dt).c_str(), specification));
308 continue;
309 }
310 const AliHLTTPCClusterMCLabel *labels = clusterMCData->fLabels;
311 for (int i=0; i<nLabels; i++) {
312 AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, i);
313 if (tpcClusterLabels.find(id)==tpcClusterLabels.end()) {
314 // new cluster
315 tpcClusterLabels[id]=labels[i];
316 } else {
317 AliError(Form("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
318 id, i, specification));
319 }
320 }
321 } while (pHLTOUT->SelectNextDataBlock()>=0);
322 return iResult;
323}
324
325int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels) const
c54aa300 326{
327 // read cluster data from AliHLTTPCClusterData
328 int iResult=0;
329 if (!pHLTOUT || !pClusters) return -EINVAL;
330 do {
331 const AliHLTUInt8_t* pBuffer=NULL;
332 AliHLTUInt32_t size=0;
333 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
334 continue;
335 }
336 if (pBuffer==NULL || size<4) {
337 AliError("invalid cluster data block");
338 continue;
339 }
81e7f739 340 AliHLTComponentDataType dt=kAliHLTVoidDataType;
341 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
342 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
343 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
344 continue;
345 }
c54aa300 346 const AliHLTTPCClusterData* clusterData = reinterpret_cast<const AliHLTTPCClusterData*>(pBuffer);
347 Int_t nSpacepoints = (Int_t) clusterData->fSpacePointCnt;
348 if (nSpacepoints*sizeof(AliHLTTPCSpacePointData) + sizeof(AliHLTTPCClusterData) != size) {
349 AliError("inconsistent cluster data block size, skipping block");
350 continue;
351 }
352 const AliHLTTPCSpacePointData *clusters = clusterData->fSpacePoints;
81e7f739 353 int offset=pClusters->GetEntries();
354 pClusters->ExpandCreate(offset+nSpacepoints);
0e63cf4a 355 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
356 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
357 // FIXME: get first row number of outer sectors from a common definition instead using number
80874dc5 358 unsigned rowOffset=partition<2?0:63;
c54aa300 359 for (int i=0; i<nSpacepoints; i++) {
81e7f739 360 if (!pClusters->At(offset+i)) continue;
361 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
c54aa300 362 if (!pCluster) {
363 AliError("invalid object type, expecting AliTPCclusterMI");
364 break; // this is a problem of all objects
365 }
0e63cf4a 366 if (clusters[i].fPadRow<rowOffset) {
367 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].fPadRow, rowOffset, slice, partition));
368 } else {
369 pCluster->SetRow(clusters[i].fPadRow-rowOffset);
370 }
81e7f739 371 pCluster->SetPad(clusters[i].fY);
5e75f4e0 372 pCluster->SetTimeBin(clusters[i].fZ);
81e7f739 373 pCluster->SetSigmaY2(clusters[i].fSigmaY2);
374 pCluster->SetSigmaZ2(clusters[i].fSigmaZ2);
c54aa300 375 pCluster->SetQ(clusters[i].fCharge);
376 pCluster->SetMax(clusters[i].fQMax);
81e7f739 377 if (tpcClusterLabels) {
378 if (tpcClusterLabels->find(clusters[i].fID)!=tpcClusterLabels->end()) {
379 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusters[i].fID)->second.fClusterID;
380 for (int k=0; k<3; k++) {
381 // TODO: sort the labels according to the weight in order to assign the most likely mc label
382 // to the first component
383 pCluster->SetLabel(mcWeights[k].fMCID, k);
384 }
385 } else {
386 AliError(Form("can not find mc label of cluster with id %0x08x", clusters[i].fID));
387 }
388 }
c54aa300 389 }
1214ab89 390 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nSpacepoints, AliHLTComponent::DataType2Text(dt).c_str(), specification));
c54aa300 391 } while (pHLTOUT->SelectNextDataBlock()>=0);
392 return iResult;
393}
5e75f4e0 394
395int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterData(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
396{
397 // read cluster data from AliHLTTPCClusterData
398
399 // FIXME: this is in large parts like ReadAliHLTTPCClusterData,
400 // make a common method
401 int iResult=0;
402 if (!pHLTOUT || !pClusters) return -EINVAL;
403 do {
404 const AliHLTUInt8_t* pBuffer=NULL;
405 AliHLTUInt32_t size=0;
406 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
407 continue;
408 }
409 if (pBuffer==NULL || size<4) {
410 AliError("invalid cluster data block");
411 continue;
412 }
413 AliHLTComponentDataType dt=kAliHLTVoidDataType;
414 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
415 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
416 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
417 continue;
418 }
419 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
420 Int_t nCount = (Int_t) clusterData->fCount;
61e66346 421 if (clusterData->fVersion!=0) {
422 // this is encoded data of different formats
423 switch (clusterData->fVersion) {
424 case 1:
425 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
426 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
427 pClusters, tpcClusterLabels);
428 break;
429 default:
430 iResult=-EPROTO;
431 }
432 return iResult;
433 }
434
5e75f4e0 435 if (nCount*sizeof(AliHLTTPCRawCluster) + sizeof(AliHLTTPCRawClusterData) != size) {
436 AliError("inconsistent cluster data block size, skipping block");
437 continue;
438 }
439 const AliHLTTPCRawCluster *clusters = clusterData->fClusters;
440 int offset=pClusters->GetEntries();
441 pClusters->ExpandCreate(offset+nCount);
0e63cf4a 442 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
443 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
444 // FIXME: get first row number of outer sectors from a common definition instead using number
80874dc5 445 int rowOffset=partition<2?0:63;
5e75f4e0 446 for (int i=0; i<nCount; i++) {
447 if (!pClusters->At(offset+i)) continue;
448 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+i));
449 if (!pCluster) {
450 AliError("invalid object type, expecting AliTPCclusterMI");
451 break; // this is a problem of all objects
452 }
1214ab89 453 if (fVerbosity>1) AliInfo(Form("cluster padrow %d (slice %d partition %d)", clusters[i].GetPadRow(), slice, partition));
0e63cf4a 454 if (clusters[i].GetPadRow()<rowOffset) {
455 AliError(Form("invalid row number %d, expecting minimum row number %d for slice %d partition %d", clusters[i].GetPadRow(), rowOffset, slice, partition));
456 } else {
457 pCluster->SetRow(clusters[i].GetPadRow()-rowOffset);
458 }
1b9cc91a 459 pCluster->SetPad(clusters[i].GetPad());
5e75f4e0 460 pCluster->SetTimeBin(clusters[i].GetTime());
461 pCluster->SetSigmaY2(clusters[i].GetSigmaY2());
462 pCluster->SetSigmaZ2(clusters[i].GetSigmaZ2());
463 pCluster->SetQ(clusters[i].GetCharge());
464 pCluster->SetMax(clusters[i].GetQMax());
465 if (tpcClusterLabels) {
5e75f4e0 466 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, i);
467 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
468 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
469 for (int k=0; k<3; k++) {
470 // TODO: sort the labels according to the weight in order to assign the most likely mc label
471 // to the first component
472 pCluster->SetLabel(mcWeights[k].fMCID, k);
473 }
474 } else {
475 AliError(Form("can not find mc label of cluster with id %0x08x", clusterID));
476 }
477 }
478 }
479 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
480 } while (pHLTOUT->SelectNextDataBlock()>=0);
481 return iResult;
482}
61e66346 483
2827cd62 484int AliHLTTPCClusterAccessHLTOUT::ReadRemainingClustersCompressed(AliHLTOUT* pHLTOUT, TClonesArray* pClusters, const AliHLTTPCClusterMCDataList *tpcClusterLabels)
485{
486 // read cluster data from AliHLTTPCClusterData
487 int iResult=0;
488 if (!pHLTOUT || !pClusters) return -EINVAL;
489 do {
490 const AliHLTUInt8_t* pBuffer=NULL;
491 AliHLTUInt32_t size=0;
492 if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, size))<0) {
493 continue;
494 }
495 if (pBuffer==NULL || size<4) {
496 AliError("invalid cluster data block");
497 continue;
498 }
499 AliHLTComponentDataType dt=kAliHLTVoidDataType;
500 AliHLTUInt32_t specification=kAliHLTVoidDataSpec;
501 if (pHLTOUT->GetDataBlockDescription(dt, specification)<0) {
502 AliError("failed to retrieve data block description, skipping mc cluster data block ...");
503 continue;
504 }
505 const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
506 Int_t nCount = (Int_t) clusterData->fCount;
507
508 // this is encoded data of different formats
509 switch (clusterData->fVersion) {
510 case 1:
511 iResult=ReadAliHLTTPCRawClusterDataDeflateSimple(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
512 size-sizeof(AliHLTTPCRawClusterData), nCount, specification,
513 pClusters, tpcClusterLabels);
514 break;
515 default:
516 AliError(Form("invalid cluster format version %d", clusterData->fVersion));
517 iResult=-EPROTO;
518 }
519
520 if (fVerbosity>0) AliInfo(Form("converted %d cluster(s) from block %s 0x%08x", nCount, AliHLTComponent::DataType2Text(dt).c_str(), specification));
521 } while (pHLTOUT->SelectNextDataBlock()>=0 && iResult>=0);
522
523 return iResult;
524}
525
61e66346 526int AliHLTTPCClusterAccessHLTOUT::ReadAliHLTTPCRawClusterDataDeflateSimple(const AliHLTUInt8_t* pData, int dataSize,
527 int nofClusters, AliHLTUInt32_t specification,
528 TClonesArray* pClusters,
529 const AliHLTTPCClusterMCDataList *tpcClusterLabels)
530{
531 // read cluster data from AliHLTTPCClusterData
532
533 // FIXME: quick implementation to read the compressed cluster data from HLTOUT
534 // the data definition below is the same as in AliHLTTPCDataCompressionComponent
535 // but needs to be moved to a common class (AliHLTTPCDefinitions?)
536 // Think about a decoder class supporting iterator objects for various types
537 // of cluster data
538 int iResult=0;
539 if (!pData || !pClusters) return -EINVAL;
540 AliHLTDataInflater inflater;
541 if ((iResult=inflater.InitBitDataInput(pData, dataSize))<0) {
542 return iResult;
543 }
544
545 int offset=pClusters->GetEntries();
546 pClusters->ExpandCreate(offset+nofClusters);
547 AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(specification);
548 AliHLTUInt8_t partition = AliHLTTPCDefinitions::GetMinPatchNr(specification);
549 // the compressed format stores the difference of the local row number in
550 // the partition to the row of the last cluster
551 // add the first row in the partition to get global row number
552 // offline uses row number in physical sector, inner sector consists of
553 // partitions 0 and 1, outer sector of partition 2-5
554 int rowOffset=AliHLTTPCTransform::GetFirstRow(partition)-(partition<2?0:AliHLTTPCTransform::GetFirstRow(2));
555
556 int parameterId=0;
557 int outClusterCnt=0;
558 AliHLTUInt8_t switchBit=0;
559 AliHLTUInt64_t value=0;
560 AliTPCclusterMI* pCluster=NULL;
561 AliHLTUInt32_t lastPadRow=0;
562 while (outClusterCnt<nofClusters && inflater.InputBit(switchBit)) {
563 const AliHLTTPCDefinitions::AliClusterParameter& parameter
564 =AliHLTTPCDefinitions::fgkClusterParameterDefinitions[parameterId];
565 // in mode DeflaterSimple, the optional parameter of the cluster parameter definition
566 // corresponds to the number bits of the reduced format
567 if (!inflater.InputBits(value, switchBit?parameter.fBitLength:parameter.fOptional)) {
568 break;
569 }
570
571 if (!pCluster) {
572 if (!pClusters->At(offset+outClusterCnt)) {
573 // here we should not get anymore because of the condition outClusterCnt<nofClusters
574 return -ENOSPC;
575 }
576 pCluster=dynamic_cast<AliTPCclusterMI*>(pClusters->At(offset+outClusterCnt));
577 if (!pCluster) {
578 AliError("invalid object type, expecting AliTPCclusterMI");
579 iResult=-EBADF; // this is a problem of all objects
580 break;
581 }
582 }
583 switch (parameterId) {
584 case AliHLTTPCDefinitions::kPadRow:
585 {pCluster->SetRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
586 case AliHLTTPCDefinitions::kPad:
587 {float pad=value; pad/=parameter.fScale; pCluster->SetPad(pad); break;}
588 case AliHLTTPCDefinitions::kTime:
589 {float time=value; time/=parameter.fScale; pCluster->SetTimeBin(time); break;}
590 case AliHLTTPCDefinitions::kSigmaY2:
591 {float sigmaY2=value; sigmaY2/=parameter.fScale; pCluster->SetSigmaY2(sigmaY2); break;}
592 case AliHLTTPCDefinitions::kSigmaZ2:
593 {float sigmaZ2=value; sigmaZ2/=parameter.fScale; pCluster->SetSigmaZ2(sigmaZ2); break;}
594 case AliHLTTPCDefinitions::kCharge:
595 {pCluster->SetQ(value); break;}
596 case AliHLTTPCDefinitions::kQMax:
597 {pCluster->SetMax(value); break;}
598 }
599 if (parameterId>=AliHLTTPCDefinitions::kLast) {
600 // switch to next cluster
601 if (tpcClusterLabels) {
602 UInt_t clusterID=AliHLTTPCSpacePointData::GetID(slice, partition, outClusterCnt);
603 if (tpcClusterLabels->find(clusterID)!=tpcClusterLabels->end()) {
604 const AliHLTTPCClusterMCWeight* mcWeights=tpcClusterLabels->find(clusterID)->second.fClusterID;
605 for (int k=0; k<3; k++) {
606 // TODO: sort the labels according to the weight in order to assign the most likely mc label
607 // to the first component
608 pCluster->SetLabel(mcWeights[k].fMCID, k);
609 }
610 } else {
2827cd62 611 AliError(Form("can not find mc label of cluster with id 0x%08x", clusterID));
61e66346 612 }
613 }
614 outClusterCnt++;
615 pCluster=NULL;
616 parameterId=-1;
617 }
618 parameterId++;
619 }
620 inflater.Pad8Bits();
621 if (inflater.InputBit(switchBit)) {
622 AliWarning("format error of compressed clusters, there is more data than expected");
623 }
624 inflater.CloseBitDataInput();
625 if (iResult>=0 && nofClusters!=outClusterCnt) {
626 // is this a Fatal?
627 AliError(Form("error reading compressed cluster format: expected %d, read only %d cluster(s)", nofClusters, outClusterCnt));
628 return -EPROTO;
629 }
630 return iResult;
631}
b60d3f6a 632
633AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AliTPCclusterMIContainer()
634 : fClusterArrays()
635 , fRemainingClusterIds()
636 , fTrackModelClusterIds()
637 , fCurrentClusterIds(NULL)
638 , fClusterMCData()
639 , fIterator()
640
641{
642 /// constructor
643 for (int i=0; i<72; i++) {
644 fClusterArrays.push_back(new TClonesArray("AliTPCclusterMI"));
645 }
646}
647
648AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::~AliTPCclusterMIContainer()
649{
650 /// dectructor
651 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++) {
652 if (*i) {
653 (*i)->Clear();
654 delete *i;
655 }
656 }
657}
658
659AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginRemainingClusterBlock(int /*count*/, AliHLTUInt32_t specification)
660{
661 /// iterator of remaining clusters block of specification
662 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(specification);
663 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(specification);
664 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
665 if (index<fRemainingClusterIds.size())
666 fCurrentClusterIds=&fRemainingClusterIds[index];
667 else
668 fCurrentClusterIds=NULL;
669 fIterator=iterator(this);
670 return fIterator;
671}
672
673AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::BeginTrackModelClusterBlock(int /*count*/)
674{
675 /// iterator of track model clusters
676 if (fTrackModelClusterIds.fIds && fTrackModelClusterIds.fSize>0)
677 fCurrentClusterIds=&fTrackModelClusterIds;
678 else
679 fCurrentClusterIds=NULL;
680 fIterator=iterator(this);
681 return fIterator;
682}
683
684int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterMCData(const AliHLTComponentBlockData* pDesc)
685{
686 /// add cluster mc data block
687 if (!pDesc) return -EINVAL;
688 if (pDesc->fDataType==AliHLTTPCDefinitions::AliHLTDataTypeClusterMCInfo()) {
689 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
690 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
691 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
692 if (fClusterMCData.size()<=index) {
693 if ((int)fClusterMCData.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
694 fClusterMCData.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches(), NULL);
695 } else {
696 fClusterMCData.resize(index+1, NULL);
697 }
698 }
699 if (pDesc->fSize<sizeof(AliHLTTPCClusterMCData)) return -EINVAL;
700 const AliHLTTPCClusterMCData* pData=reinterpret_cast<const AliHLTTPCClusterMCData*>(pDesc->fPtr);
701 unsigned nLabels = pData->fCount;
702 if (nLabels*sizeof(AliHLTTPCClusterMCLabel) + sizeof(AliHLTTPCClusterMCData) != pDesc->fSize) {
703 return -EINVAL;
704 }
705 fClusterMCData[index]=pData;
706 return 0;
707 }
708 return -ENODATA;
709}
710
711int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::AddClusterIds(const AliHLTComponentBlockData* pDesc)
712{
713 /// add cluster id block for remaining or track model clusters
714 if (!pDesc) return -EINVAL;
715 if (pDesc->fDataType==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
716 fTrackModelClusterIds.fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
717 fTrackModelClusterIds.fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
718 return 0;
719 }
720 if (pDesc->fDataType==AliHLTTPCDefinitions::RemainingClusterIdsDataType()) {
721 AliHLTUInt8_t slice=AliHLTTPCDefinitions::GetMinSliceNr(pDesc->fSpecification);
722 AliHLTUInt8_t partition=AliHLTTPCDefinitions::GetMinPatchNr(pDesc->fSpecification);
723 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
724 if (fRemainingClusterIds.size()<=index) {
725 if ((int)fRemainingClusterIds.size()<AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches()) {
726 fRemainingClusterIds.resize(AliHLTTPCTransform::GetNSlice()*AliHLTTPCTransform::GetNumberOfPatches());
727 } else {
728 fRemainingClusterIds.resize(index+1);
729 }
730 }
731 fRemainingClusterIds[index].fIds=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
732 fRemainingClusterIds[index].fSize=pDesc->fSize/sizeof(AliHLTUInt32_t);
733 return 0;
734 }
735 return -ENODATA;
736}
737
738AliHLTUInt32_t AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetClusterId(int clusterNo) const
739{
740 /// get the cluster id from the current cluster id block (optional)
741 if (!fCurrentClusterIds ||
ebba640a 742 (int)fCurrentClusterIds->fSize<=clusterNo ||
743 clusterNo<0)
b60d3f6a 744 return kAliHLTVoidDataSpec;
745 return fCurrentClusterIds->fIds[clusterNo];
746}
747
748AliTPCclusterMI* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::NextCluster(int slice, int partition)
749{
750 /// load next cluster from array of the sepcific sector
751 unsigned sector=partition<2?slice:slice+36;
752 if (fClusterArrays.size()<=sector ||
753 fClusterArrays[sector]==NULL) {
754 AliErrorClass(Form("no cluster array available for sector %d", sector));
755 return NULL;
756 }
757 TClonesArray& array=*(fClusterArrays[sector]);
758 int count=array.GetEntriesFast();
759 return new (array[count]) AliTPCclusterMI;
760}
761
762int AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::SetMC(AliTPCclusterMI* pCluster, AliHLTUInt32_t clusterId)
763{
764 /// set MC data for the cluster
765 if (!pCluster) return -EINVAL;
766 if (clusterId==kAliHLTVoidDataSpec) return 0;
767
768 unsigned slice=AliHLTTPCSpacePointData::GetSlice(clusterId);
769 unsigned partition=AliHLTTPCSpacePointData::GetPatch(clusterId);
770 unsigned number=AliHLTTPCSpacePointData::GetNumber(clusterId);
771 if ((int)slice>=AliHLTTPCTransform::GetNSlice() ||
772 (int)partition>=AliHLTTPCTransform::GetNumberOfPatches()) return -EDOM;
773 unsigned index=slice*AliHLTTPCTransform::GetNumberOfPatches()+partition;
774 if (fClusterMCData.size()<=index ||
775 fClusterMCData[index]==NULL ||
776 fClusterMCData[index]->fCount<=number) return 0;
777 const AliHLTTPCClusterMCWeight* mcWeights=fClusterMCData[index]->fLabels[number].fClusterID;
778 for (int k=0; k<3; k++) {
779 // TODO: sort the labels according to the weight in order to assign the most likely mc label
780 // to the first component
781 pCluster->SetLabel(mcWeights[k].fMCID, k);
782 }
783
784 return 0;
785}
786
787void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Clear(Option_t* /*option*/)
788{
789 /// internal cleanup
790 {
791 for (vector<TClonesArray*>::iterator i=fClusterArrays.begin(); i!=fClusterArrays.end(); i++)
792 if (*i) (*i)->Clear();
793 }
794 {
795 for (vector<AliClusterIdBlock>::iterator i=fRemainingClusterIds.begin(); i!=fRemainingClusterIds.end(); i++)
796 {i->fIds=NULL; i->fSize=0;}
797 }
798 fTrackModelClusterIds.fIds=NULL; fTrackModelClusterIds.fSize=0;
799 fCurrentClusterIds=NULL;
800 {
801 for (vector<const AliHLTTPCClusterMCData*>::iterator i=fClusterMCData.begin(); i!=fClusterMCData.end(); i++)
802 *i=NULL;
803 }
804}
805
806TObjArray* AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::GetSectorArray(unsigned sector) const
807{
808 /// get the cluster array for a sector
809 if (fClusterArrays.size()<=sector) return NULL;
810 return fClusterArrays[sector];
811}
812
813void AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::Print(Option_t *option) const
814{
815 /// inherited from TObject
816 cout << "AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer" << endl;
817 ios::fmtflags coutflags=cout.flags(); // backup cout status flags
818 bool bAll=false;
819 if ((bAll=(strcmp(option, "full")==0)) ||
820 strcmp(option, "short")==0) {
821 for (unsigned iArray=0; iArray<fClusterArrays.size(); iArray++) {
822 if (fClusterArrays[iArray]) {
823 TClonesArray* pArray=fClusterArrays[iArray];
824 cout << " sector " << setfill(' ') << setw(2) << iArray << ": " << pArray->GetEntriesFast() << endl;
825 if (bAll) {
826 for (int iCluster=0; iCluster<pArray->GetEntriesFast(); iCluster++) {
827 if (!pArray->At(iCluster)) continue;
828 AliTPCclusterMI* pCluster=dynamic_cast<AliTPCclusterMI*>(pArray->At(iCluster));
829 if (!pCluster) break;
830 cout << " AliTPCclusterMI:"
831 << " row=" << pCluster->GetRow()
832 << " pad=" << pCluster->GetPad()
833 << " time=" << pCluster->GetTimeBin()
834 << " charge=" << pCluster->GetQ()
835 << " maxq=" << pCluster->GetMax()
836 << endl;
837 }
838 }
839 }
840 }
841 }
842 cout.flags(coutflags); // restore the original flags
843}
844
845AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator& AliHLTTPCClusterAccessHLTOUT::AliTPCclusterMIContainer::iterator::Next(int slice, int partition)
846{
847 // switch to next cluster
848 if (!fData) {
849 fCluster=NULL;
850 fClusterId=kAliHLTVoidDataSpec;
851 return *this;
852 }
853 if (fClusterNo>=0 && !fCluster) {
854 // end was reached before
855 return *this;
856 }
857 fCluster=fData->NextCluster(slice, partition);
858 fClusterId=fData->GetClusterId(++fClusterNo);
859 if (fCluster && fClusterId!=kAliHLTVoidDataSpec) {
860 fData->SetMC(fCluster, fClusterId);
861 }
862 // offline uses row number in physical sector, inner sector consists of
863 // partitions 0 and 1, outer sector of partition 2-5
864 fRowOffset=partition<2?0:AliHLTTPCTransform::GetFirstRow(2);
865 return *this;
866}