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 AliHLTTPCHWCFData.cxx
20 /// @author Matthias Richter
22 /// @brief Decoder methods for the HWCF format
24 #include "AliHLTTPCHWCFData.h"
25 #include "AliHLTErrorGuard.h"
26 #include "AliHLTTPCHWCFEmulator.h"
27 #include "AliHLTTPCTransform.h"
28 #include "AliRawDataHeader.h"
33 ClassImp(AliHLTTPCHWCFData) //ROOT macro for the implementation of ROOT specific class methods
35 AliHLTTPCHWCFData::AliHLTTPCHWCFData(int forceVersion)
39 , fForcedVersion(forceVersion)
48 const unsigned AliHLTTPCHWCFData::fgkAliHLTTPCHWClusterSize=sizeof(AliHLTTPCHWCFData::AliHLTTPCHWClusterV1)/sizeof(AliHLTUInt32_t);
50 AliHLTTPCHWCFData::~AliHLTTPCHWCFData()
53 if (fpFileBuffer) delete fpFileBuffer;
56 int AliHLTTPCHWCFData::Init(const AliHLTUInt8_t* pBuffer, int bufferSize)
58 // init the internal pointer
60 if (!pBuffer || (unsigned)bufferSize<sizeof(AliHLTUInt32_t)) return -EINVAL;
61 if (bufferSize%sizeof(AliHLTUInt32_t)) {
62 HLTError("invalid buffer size %d, expecting multiple of 4", bufferSize);
65 const AliHLTUInt32_t* rcuTrailer=reinterpret_cast<const AliHLTUInt32_t*>(pBuffer);
66 rcuTrailer+=bufferSize/sizeof(AliHLTUInt32_t)-1;
68 if ((*rcuTrailer >> 30) != 3) {
69 // The HWCFEmulator does not write the RCU trailer at the moment
71 // HLTError("can not read last rcu trailer word");
74 // number of 32 bit RCU trailer words can be found in the last word
75 int nofRCUTrailerWords = (*rcuTrailer & 0x7F);
76 if (nofRCUTrailerWords < 2) {
77 HLTError("Invalid trailer size found (%d bytes)", nofRCUTrailerWords*4);
81 if (nofRCUTrailerWords*4>bufferSize) {
82 HLTError("inconsistent RCU trailer size, exceeds buffer size");
86 // check if the first RCU trailer word starts with pattern '10'
87 rcuTrailer-=nofRCUTrailerWords-1;
88 if ((*rcuTrailer >> 30) != 2) {
89 HLTError("inconsistent first RCU trailer word: can not find indicator pattern '10' in bit 31 and 30 (0x%08x): trailer size %d word(s), buffer size %d byte", *rcuTrailer, nofRCUTrailerWords, bufferSize);
93 fRCUTrailerSize = nofRCUTrailerWords*4;
97 fBufferSize=bufferSize;
102 int AliHLTTPCHWCFData::Reset()
111 int AliHLTTPCHWCFData::CheckVersion()
113 // check the data buffer for format version
114 if (fVersion>=0) return fVersion;
115 if (CheckAssumption(kHWCFDataV1, fpBuffer, fBufferSize-fRCUTrailerSize)) {
116 fVersion=kHWCFDataV1;
117 } else if (CheckAssumption(kHWCFDataV0, fpBuffer, fBufferSize-fRCUTrailerSize)) {
118 fVersion=kHWCFDataV0;
123 bool AliHLTTPCHWCFData::CheckAssumption(int format, const AliHLTUInt8_t* pData, int size) const
125 // check the format assumption for data buffer
126 int elementsize=GetElementSize(format);
127 // size has to be known
128 if (elementsize<0) return false;
129 // buffer must be multiple of element size
130 if (size<elementsize || (size%elementsize)!=0) return false;
131 for (int trial=0; trial<10 && (trial+1)*elementsize<=size; trial++) {
132 AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(*reinterpret_cast<const AliHLTUInt32_t*>(pData+trial*elementsize));
133 // cluster header starts with 11 in bit 30 and 31
134 if ((header&0xc0000000)!=0xc0000000) return false;
135 // check that the padrow is within bounds
136 if (((header >> 24) & 0x3f)>(unsigned)AliHLTTPCTransform::GetNRows(-1)) return false;
141 Int_t AliHLTTPCHWCFData::GetNumberOfClusters() const
143 // get number of clusters
144 if (fVersion<0) return 0;
145 int elementsize=GetElementSize(fVersion);
146 if (elementsize<0) return 0;
147 if (!fpBuffer || fBufferSize==0 || fBufferSize<fRCUTrailerSize) return 0;
148 return (fBufferSize-fRCUTrailerSize)/elementsize;
151 Int_t AliHLTTPCHWCFData::GetPadRow(int i) const
153 // get raw coordinate
154 if (fVersion>=0 && CheckBounds(i)) {
156 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetPadRow();
157 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetPadRow();
159 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
165 Float_t AliHLTTPCHWCFData::GetPad(int i) const
167 // get pad coordinate
168 if (fVersion>=0 && CheckBounds(i)) {
170 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetPad();
171 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetPad();
173 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
179 Float_t AliHLTTPCHWCFData::GetTime(int i) const
181 // get time coordinate
182 if (fVersion>=0 && CheckBounds(i)) {
184 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetTime();
185 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetTime();
187 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
193 Float_t AliHLTTPCHWCFData::GetSigmaY2(int i) const
195 // get sigmaY2 coordinate
196 if (fVersion>=0 && CheckBounds(i)) {
198 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetSigmaY2();
199 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetSigmaY2();
201 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
207 Float_t AliHLTTPCHWCFData::GetSigmaZ2(int i) const
209 // get sigmaZ2 coordinate
210 if (fVersion>=0 && CheckBounds(i)) {
212 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetSigmaZ2();
213 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetSigmaZ2();
215 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
221 Int_t AliHLTTPCHWCFData::GetCharge(int i) const
223 // get charge coordinate
224 if (fVersion>=0 && CheckBounds(i)) {
226 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetCharge();
227 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetCharge();
229 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
235 Int_t AliHLTTPCHWCFData::GetQMax(int i) const
237 // get qmax coordinate
238 if (fVersion>=0 && CheckBounds(i)) {
240 case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetQMax();
241 case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetQMax();
243 ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
249 void AliHLTTPCHWCFData::Print(const char* option)
252 cout << "HWCF format version " << fVersion << endl;
253 if (fVersion<0) return;
255 cout << " " << GetNumberOfClusters() << " cluster(s)" << endl;
256 if (GetRCUTrailerSize()>0) {
257 cout << " RCU trailer: " << GetRCUTrailerSize() << " word(s)" << endl;
260 if (strcmp(option, "all")==0) {
261 for (unsigned i=0; (int)i<GetNumberOfClusters(); i++) {
262 cout << /* setw(5) <<*/ i << ":";
263 cout << /* setw(8) <<*/ " " << GetPadRow(i);
264 cout << /* setw(8) <<*/ " " << GetPad(i);
265 cout << /* setw(8) <<*/ " " << GetTime(i);
266 cout << /* setw(8) <<*/ " " << GetSigmaY2(i);
267 cout << /* setw(8) <<*/ " " << GetSigmaZ2(i);
268 cout << /* setw(8) <<*/ " " << GetCharge(i);
269 cout << /* setw(8) <<*/ " " << GetQMax(i);
275 int AliHLTTPCHWCFData::Open(const char* filename)
277 // open block from file and add to collection
278 if (!filename) return -EINVAL;
280 TString input=filename;
281 input+="?filetype=raw";
282 std::auto_ptr<TFile> pFile(new TFile(input));
283 if (!pFile.get()) return -ENOMEM;
284 if (pFile->IsZombie()) return -ENOENT;
287 if (pFile->GetSize()<(int)sizeof(AliRawDataHeader)) {
288 HLTError("file %s to small", filename);
293 std::auto_ptr<TArrayC> buffer(new TArrayC);
294 if (!buffer.get()) return -ENOMEM;
296 buffer->Set(pFile->GetSize());
297 if (pFile->ReadBuffer(buffer->GetArray(), buffer->GetSize())==0) {
299 HLTError("failed reading %d byte(s) from file %s", pFile->GetSize(), filename);
303 AliHLTUInt8_t* pBuffer=reinterpret_cast<AliHLTUInt8_t*>(buffer->GetArray()+sizeof(AliRawDataHeader));
304 unsigned bufferSize=buffer->GetSize()-sizeof(AliRawDataHeader);
305 if ((iResult=Init(pBuffer, bufferSize))<0 ||
306 (iResult=CheckVersion())<0) {
311 fpFileBuffer=buffer.release();
312 return GetNumberOfClusters();
315 Int_t AliHLTTPCHWCFData::AliHLTTPCHWClusterV0::GetPadRow() const
318 AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
319 if ((header>>30) != 3) return -EBADMSG;
320 return (header >> 24) & 0x3f;
323 Int_t AliHLTTPCHWCFData::AliHLTTPCHWClusterV0::GetCharge() const
325 // 24 bit fixed point number with 6 bits after the point
326 AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
327 return (header & 0xFFFFFF )>>6;
330 Int_t AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetPadRow() const
333 AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
334 if ((header>>30) != 3) return -EBADMSG;
335 return (header >> 24) & 0x3f;
338 Int_t AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetCharge() const
340 // 32 bit fixed point number with 12 bits after the point
341 return AliHLTTPCHWCFEmulator::ReadBigEndian(fCharge)>>12;
344 Int_t AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetQMax() const
346 // 24 bit fixed point number with 12 bits after the point
347 AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
348 return (header & 0xFFFFFF )>>12;