ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCHWCFData.cxx
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   AliHLTTPCHWCFData.cxx
20 /// @author Matthias Richter
21 /// @date   2011-08-04
22 /// @brief  Decoder methods for the HWCF format
23 ///
24 #include "AliHLTTPCHWCFData.h"
25 #include "AliHLTErrorGuard.h"
26 #include "AliHLTTPCHWCFEmulator.h"
27 #include "AliHLTTPCTransform.h"
28 #include "AliHLTCDHWrapper.h"
29 #include "TFile.h"
30 #include <memory>
31 #include <ostream>
32
33 ClassImp(AliHLTTPCHWCFData) //ROOT macro for the implementation of ROOT specific class methods
34
35 AliHLTTPCHWCFData::AliHLTTPCHWCFData(int forceVersion)
36  : fpBuffer(NULL)
37  , fBufferSize(0)
38  , fVersion(-1)
39  , fForcedVersion(forceVersion)
40  , fRCUTrailerSize(0)
41  , fpFileBuffer(NULL)
42  , fIterator()
43  , fIteratorEnd()
44 {
45   // constructor
46 }
47
48 const unsigned AliHLTTPCHWCFData::fgkAliHLTTPCHWClusterSize=sizeof(AliHLTTPCHWCFData::AliHLTTPCHWClusterV1)/sizeof(AliHLTUInt32_t);
49
50 AliHLTTPCHWCFData::~AliHLTTPCHWCFData()
51 {
52   // destructor
53   if (fpFileBuffer) delete fpFileBuffer;
54 }
55
56 int AliHLTTPCHWCFData::Init(const AliHLTUInt8_t* pBuffer, int bufferSize)
57 {
58   // init the internal pointer
59   Reset();
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);
63     return -EINVAL;
64   }
65   const AliHLTUInt32_t* rcuTrailer=reinterpret_cast<const AliHLTUInt32_t*>(pBuffer);
66   rcuTrailer+=bufferSize/sizeof(AliHLTUInt32_t)-1;
67
68   if ((*rcuTrailer >> 30) != 3) {
69     // The HWCFEmulator does not write the RCU trailer at the moment
70     // skip this error
71     // HLTError("can not read last rcu trailer word");
72     // return -ENODATA;
73   } else {
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);
78       return -ENODATA;
79     }
80
81     if (nofRCUTrailerWords*4>bufferSize) {
82       HLTError("inconsistent RCU trailer size, exceeds buffer size");
83       return -ENODATA;
84     }
85
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);
90       return -ENODATA;
91     }
92
93     fRCUTrailerSize = nofRCUTrailerWords*4;
94   }
95
96   fpBuffer=pBuffer;
97   fBufferSize=bufferSize;
98
99   return 0;
100 }
101
102 int AliHLTTPCHWCFData::Reset()
103 {
104   // reset
105   fpBuffer=NULL;
106   fBufferSize=0;
107   fRCUTrailerSize=0;
108   return 0;
109 }
110
111 int AliHLTTPCHWCFData::CheckVersion()
112 {
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;
119   }
120   return fVersion;
121 }
122
123 bool AliHLTTPCHWCFData::CheckAssumption(int format, const AliHLTUInt8_t* pData, int size) const
124 {
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;
137   }
138   return true;
139 }
140
141 Int_t AliHLTTPCHWCFData::GetNumberOfClusters() const
142 {
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;
149 }
150
151 Int_t    AliHLTTPCHWCFData::GetPadRow(int i)  const
152 {
153   // get raw coordinate
154   if (fVersion>=0 && CheckBounds(i)) {
155     switch (fVersion) {
156     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetPadRow();
157     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetPadRow();
158     default:
159       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
160     }
161   }
162   return -1;
163 }
164
165 Float_t  AliHLTTPCHWCFData::GetPad(int i)     const
166 {
167   // get pad coordinate
168   if (fVersion>=0 && CheckBounds(i)) {
169     switch (fVersion) {
170     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetPad();
171     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetPad();
172     default:
173       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
174     }
175   }
176   return -10000.;
177 }
178
179 Float_t  AliHLTTPCHWCFData::GetTime(int i)    const
180 {
181   // get time coordinate
182   if (fVersion>=0 && CheckBounds(i)) {
183     switch (fVersion) {
184     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetTime();
185     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetTime();
186     default:
187       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
188     }
189   }
190   return -10000.;
191 }
192
193 Float_t  AliHLTTPCHWCFData::GetSigmaY2(int i) const
194 {
195   // get sigmaY2 coordinate
196   if (fVersion>=0 && CheckBounds(i)) {
197     switch (fVersion) {
198     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetSigmaY2();
199     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetSigmaY2();
200     default:
201       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
202     }
203   }
204   return -10000.;
205 }
206
207 Float_t  AliHLTTPCHWCFData::GetSigmaZ2(int i) const
208 {
209   // get sigmaZ2 coordinate
210   if (fVersion>=0 && CheckBounds(i)) {
211     switch (fVersion) {
212     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetSigmaZ2();
213     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetSigmaZ2();
214     default:
215       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
216     }
217   }
218   return -10000.;
219 }
220
221 Int_t    AliHLTTPCHWCFData::GetCharge(int i)  const
222 {
223   // get charge coordinate
224   if (fVersion>=0 && CheckBounds(i)) {
225     switch (fVersion) {
226     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetCharge();
227     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetCharge();
228     default:
229       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
230     }
231   }
232   return -1;
233 }
234
235 Int_t    AliHLTTPCHWCFData::GetQMax(int i)    const
236 {
237   // get qmax coordinate
238   if (fVersion>=0 && CheckBounds(i)) {
239     switch (fVersion) {
240     case 0: return reinterpret_cast<const AliHLTTPCHWClusterV0*>(Get(i))->GetQMax();
241     case 1: return reinterpret_cast<const AliHLTTPCHWClusterV1*>(Get(i))->GetQMax();
242     default:
243       ALIHLTERRORGUARD(1, "invalid format version %d", fVersion);
244     }
245   }
246   return -1;
247 }
248
249 void AliHLTTPCHWCFData::Print(const char* option)
250 {
251   // print info
252   cout << "HWCF format version " << fVersion << endl;
253   if (fVersion<0) return;
254
255   cout << "    " << GetNumberOfClusters() << " cluster(s)" << endl;
256   if (GetRCUTrailerSize()>0) {
257     cout << "    RCU trailer: " << GetRCUTrailerSize() << " word(s)" << endl;
258   }
259
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);
270       cout << endl;
271     }
272   }
273 }
274
275 void AliHLTTPCHWCFData::ErrorMsg( const char *str ) const
276 {
277   ALIHLTERRORGUARD(1, str);
278 }
279
280 int AliHLTTPCHWCFData::Open(const char* filename)
281 {
282   // open block from file and add to collection
283   if (!filename) return -EINVAL;
284   
285   TString input=filename;
286   input+="?filetype=raw";
287   std::auto_ptr<TFile> pFile(new TFile(input));
288   if (!pFile.get()) return -ENOMEM;
289   if (pFile->IsZombie()) return -ENOENT;
290
291   int iResult=0;
292   if (pFile->GetSize()<(int)sizeof(AliRawDataHeader)) {
293     HLTError("file %s to small", filename);
294     return -ENODATA;
295   }
296
297   pFile->Seek(0);
298   std::auto_ptr<TArrayC> buffer(new TArrayC);
299   if (!buffer.get()) return -ENOMEM;
300
301   buffer->Set(pFile->GetSize());
302   if (pFile->ReadBuffer(buffer->GetArray(), buffer->GetSize())==0) {
303   } else {
304     HLTError("failed reading %d byte(s) from file %s", pFile->GetSize(), filename);
305     iResult=-ENODATA;
306   }
307
308   AliHLTCDHWrapper header(buffer->GetArray());
309   AliHLTUInt8_t* pBuffer=reinterpret_cast<AliHLTUInt8_t*>(buffer->GetArray()+header.GetHeaderSize());
310   unsigned bufferSize=buffer->GetSize()-header.GetHeaderSize();
311   if ((iResult=Init(pBuffer, bufferSize))<0 ||
312       (iResult=CheckVersion())<0) {
313     Reset();
314     return iResult;
315   }
316
317   fpFileBuffer=buffer.release();
318   return GetNumberOfClusters();
319 }
320
321 Int_t    AliHLTTPCHWCFData::AliHLTTPCHWClusterV0::GetPadRow()  const
322 {
323   // bit 24 to 29
324   AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
325   if ((header>>30) != 3) return -EBADMSG;
326   return (header >> 24) & 0x3f;
327 }
328
329 Int_t    AliHLTTPCHWCFData::AliHLTTPCHWClusterV0::GetCharge()  const
330 {
331   // 24 bit fixed point number with 6 bits after the point
332   AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
333   return (header & 0xFFFFFF )>>6;
334 }
335
336 Int_t    AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetPadRow()  const
337 {
338   // bit 24 to 29
339   AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
340   if ((header>>30) != 3) return -EBADMSG;
341   return (header >> 24) & 0x3f;
342 }
343
344 Int_t    AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetCharge()  const
345 {
346   // 32 bit fixed point number with 12 bits after the point
347   return AliHLTTPCHWCFEmulator::ReadBigEndian(fCharge)>>12;
348 }
349
350 Int_t    AliHLTTPCHWCFData::AliHLTTPCHWClusterV1::GetQMax()    const
351 {
352   // 24 bit fixed point number with 12 bits after the point
353   AliHLTUInt32_t header=AliHLTTPCHWCFEmulator::ReadBigEndian(fHeader);
354   return (header & 0xFFFFFF )>>12;
355 }