]>
Commit | Line | Data |
---|---|---|
04fa961a | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
bea6b2a4 | 16 | /* $Id$ */ |
17 | ||
04fa961a | 18 | /////////////////////////////////////////////////////////////////////////////// |
bea6b2a4 | 19 | /// |
20 | /// This is a class for reading raw data from a root file. | |
21 | /// | |
22 | /// The root file is expected to contain a tree of name "RAW" with | |
23 | /// a branch of name "rawevent" which contains objects of type | |
24 | /// AliRawEvent. | |
25 | /// | |
26 | /// The file name and the event number are arguments of the constructor | |
27 | /// of AliRawReaderRoot. | |
28 | /// | |
04fa961a | 29 | /////////////////////////////////////////////////////////////////////////////// |
30 | ||
a197a4ce | 31 | #include <TFile.h> |
32 | #include <TTree.h> | |
04fa961a | 33 | #include "AliRawReaderRoot.h" |
42d20574 | 34 | #include "AliRawEvent.h" |
a197a4ce | 35 | #include "AliRawEventHeader.h" |
36 | #include "AliRawEquipmentHeader.h" | |
37 | #include "AliRawData.h" | |
04fa961a | 38 | |
39 | ||
40 | ClassImp(AliRawReaderRoot) | |
41 | ||
42 | ||
43 | AliRawReaderRoot::AliRawReaderRoot(const char* fileName, Int_t eventNumber) | |
44 | { | |
45 | // create an object to read digits from the given input file for the | |
46 | // event with the given number | |
47 | ||
be50fca2 | 48 | fEvent = NULL; |
03c6d9a3 | 49 | TDirectory* dir = gDirectory; |
04fa961a | 50 | fFile = TFile::Open(fileName); |
03c6d9a3 | 51 | dir->cd(); |
04fa961a | 52 | if (!fFile || !fFile->IsOpen()) { |
53 | Error("AliRawReaderRoot", "could not open file %s", fileName); | |
54 | return; | |
55 | } | |
56 | TTree* tree = (TTree*) fFile->Get("RAW"); | |
57 | if (!tree) { | |
58 | Error("AliRawReaderRoot", "no raw data tree found"); | |
59 | return; | |
60 | } | |
61 | TBranch* branch = tree->GetBranch("rawevent"); | |
62 | if (!branch) { | |
63 | Error("AliRawReaderRoot", "no raw data branch found"); | |
64 | return; | |
65 | } | |
66 | ||
67 | fEvent = new AliRawEvent; | |
68 | branch->SetAddress(&fEvent); | |
69 | if (branch->GetEntry(eventNumber) <= 0) { | |
70 | Error("AliRawReaderRoot", "no event with number %d found", eventNumber); | |
71 | return; | |
72 | } | |
73 | ||
74 | fSubEventIndex = 0; | |
75 | fSubEvent = NULL; | |
76 | fRawData = NULL; | |
39f9963f | 77 | fHeader = NULL; |
04fa961a | 78 | |
79 | fCount = 0; | |
80 | fPosition = fEnd = NULL; | |
81 | } | |
82 | ||
83 | AliRawReaderRoot::AliRawReaderRoot(AliRawEvent* event) | |
84 | { | |
85 | // create an object to read digits from the given raw event | |
86 | ||
87 | fFile = NULL; | |
88 | fEvent = event; | |
89 | ||
90 | fSubEventIndex = 0; | |
91 | fSubEvent = NULL; | |
92 | fRawData = NULL; | |
39f9963f | 93 | fHeader = NULL; |
04fa961a | 94 | |
95 | fCount = 0; | |
96 | fPosition = fEnd = NULL; | |
97 | } | |
98 | ||
42d20574 | 99 | AliRawReaderRoot::AliRawReaderRoot(const AliRawReaderRoot& rawReader) : |
100 | AliRawReader(rawReader) | |
101 | { | |
102 | // copy constructor | |
103 | ||
104 | fFile = NULL; | |
105 | fEvent = rawReader.fEvent; | |
106 | ||
107 | fSubEventIndex = rawReader.fSubEventIndex; | |
108 | fSubEvent = rawReader.fSubEvent; | |
109 | fRawData = rawReader.fRawData; | |
39f9963f | 110 | fHeader = rawReader.fHeader; |
42d20574 | 111 | |
112 | fCount = rawReader.fCount; | |
113 | fPosition = rawReader.fPosition; | |
114 | fEnd = rawReader.fEnd; | |
115 | } | |
116 | ||
117 | AliRawReaderRoot& AliRawReaderRoot::operator = (const AliRawReaderRoot& | |
118 | rawReader) | |
119 | { | |
120 | // assignment operator | |
121 | ||
122 | this->~AliRawReaderRoot(); | |
123 | new(this) AliRawReaderRoot(rawReader); | |
124 | return *this; | |
125 | } | |
126 | ||
04fa961a | 127 | AliRawReaderRoot::~AliRawReaderRoot() |
128 | { | |
129 | // delete objects and close root file | |
130 | ||
131 | if (fFile) { | |
132 | if (fEvent) delete fEvent; | |
133 | fFile->Close(); | |
134 | delete fFile; | |
135 | } | |
136 | } | |
137 | ||
138 | ||
42d20574 | 139 | UInt_t AliRawReaderRoot::GetType() const |
04fa961a | 140 | { |
141 | // get the type from the event header | |
142 | ||
143 | if (!fEvent) return 0; | |
144 | return fEvent->GetHeader()->GetType(); | |
145 | } | |
146 | ||
42d20574 | 147 | UInt_t AliRawReaderRoot::GetRunNumber() const |
04fa961a | 148 | { |
149 | // get the run number from the event header | |
150 | ||
151 | if (!fEvent) return 0; | |
152 | return fEvent->GetHeader()->GetRunNumber(); | |
153 | } | |
154 | ||
42d20574 | 155 | const UInt_t* AliRawReaderRoot::GetEventId() const |
04fa961a | 156 | { |
157 | // get the event id from the event header | |
158 | ||
159 | if (!fEvent) return NULL; | |
160 | return fEvent->GetHeader()->GetId(); | |
161 | } | |
162 | ||
42d20574 | 163 | const UInt_t* AliRawReaderRoot::GetTriggerPattern() const |
04fa961a | 164 | { |
165 | // get the trigger pattern from the event header | |
166 | ||
167 | if (!fEvent) return NULL; | |
168 | return fEvent->GetHeader()->GetTriggerPattern(); | |
169 | } | |
170 | ||
42d20574 | 171 | const UInt_t* AliRawReaderRoot::GetDetectorPattern() const |
04fa961a | 172 | { |
173 | // get the detector pattern from the event header | |
174 | ||
175 | if (!fEvent) return NULL; | |
176 | return fEvent->GetHeader()->GetDetectorPattern(); | |
177 | } | |
178 | ||
42d20574 | 179 | const UInt_t* AliRawReaderRoot::GetAttributes() const |
04fa961a | 180 | { |
181 | // get the type attributes from the event header | |
182 | ||
183 | if (!fEvent) return NULL; | |
184 | return fEvent->GetHeader()->GetTypeAttribute(); | |
185 | } | |
186 | ||
c946ab02 | 187 | UInt_t AliRawReaderRoot::GetLDCId() const |
188 | { | |
189 | // get the LDC Id from the event header | |
190 | ||
191 | if (!fEvent || !fEvent->GetSubEvent(fSubEventIndex)) return 0; | |
192 | return fEvent->GetSubEvent(fSubEventIndex)->GetHeader()->GetLDCId(); | |
193 | } | |
194 | ||
42d20574 | 195 | UInt_t AliRawReaderRoot::GetGDCId() const |
04fa961a | 196 | { |
197 | // get the GDC Id from the event header | |
198 | ||
199 | if (!fEvent) return 0; | |
200 | return fEvent->GetHeader()->GetGDCId(); | |
201 | } | |
202 | ||
203 | ||
c946ab02 | 204 | Int_t AliRawReaderRoot::GetEquipmentSize() const |
205 | { | |
206 | // get the size of the equipment | |
207 | ||
208 | if (!fEvent || !fEvent->GetEquipmentHeader()) return 0; | |
209 | return fEvent->GetEquipmentHeader()->GetEquipmentSize(); | |
210 | } | |
211 | ||
212 | Int_t AliRawReaderRoot::GetEquipmentType() const | |
213 | { | |
214 | // get the type from the equipment header | |
215 | ||
216 | if (!fEvent || !fEvent->GetEquipmentHeader()) return -1; | |
217 | return fEvent->GetEquipmentHeader()->GetEquipmentType(); | |
218 | } | |
219 | ||
220 | Int_t AliRawReaderRoot::GetEquipmentId() const | |
221 | { | |
222 | // get the ID from the equipment header | |
223 | ||
224 | if (!fEvent || !fEvent->GetEquipmentHeader()) return -1; | |
225 | return fEvent->GetEquipmentHeader()->GetId(); | |
226 | } | |
227 | ||
228 | const UInt_t* AliRawReaderRoot::GetEquipmentAttributes() const | |
229 | { | |
230 | // get the attributes from the equipment header | |
231 | ||
232 | if (!fEvent || !fEvent->GetEquipmentHeader()) return NULL; | |
233 | return fEvent->GetEquipmentHeader()->GetTypeAttribute(); | |
234 | } | |
235 | ||
236 | Int_t AliRawReaderRoot::GetEquipmentElementSize() const | |
237 | { | |
238 | // get the basic element size from the equipment header | |
239 | ||
240 | if (!fEvent || !fEvent->GetEquipmentHeader()) return 0; | |
241 | return fEvent->GetEquipmentHeader()->GetBasicSizeType(); | |
242 | } | |
243 | ||
244 | ||
245 | Bool_t AliRawReaderRoot::ReadHeader() | |
04fa961a | 246 | { |
39f9963f | 247 | // read a data header at the current position |
248 | // returns kFALSE if the data header could not be read | |
04fa961a | 249 | |
b4857df7 | 250 | fErrorCode = 0; |
04fa961a | 251 | if (!fEvent) return kFALSE; |
b4857df7 | 252 | |
04fa961a | 253 | do { |
b4857df7 | 254 | // skip payload (if event was not selected) |
255 | if (fCount > 0) fPosition += fCount; | |
256 | ||
257 | // get the first or the next sub event if at the end of a sub event | |
258 | if (!fSubEvent || (fPosition >= fEnd)) { | |
259 | ||
260 | // check for end of event data | |
04fa961a | 261 | if (fSubEventIndex >= fEvent->GetNSubEvents()) return kFALSE; |
262 | fSubEvent = fEvent->GetSubEvent(fSubEventIndex++); | |
b4857df7 | 263 | |
264 | // check the magic word of the sub event | |
265 | if (!fSubEvent->GetHeader()->IsValid()) { | |
c946ab02 | 266 | Error("ReadHeader", "wrong magic number in sub event!"); |
b4857df7 | 267 | fSubEvent->GetHeader()->Dump(); |
268 | fErrorCode = kErrMagic; | |
269 | return kFALSE; | |
270 | } | |
271 | ||
04fa961a | 272 | fRawData = fSubEvent->GetRawData(); |
273 | fCount = 0; | |
274 | fPosition = (UChar_t*) fRawData->GetBuffer(); | |
275 | fEnd = ((UChar_t*) fRawData->GetBuffer()) + fRawData->GetSize(); | |
276 | } | |
b4857df7 | 277 | |
278 | // continue with the next sub event if no data left in the payload | |
279 | if (fPosition >= fEnd) continue; | |
280 | ||
39f9963f | 281 | // check that there are enough bytes left for the data header |
282 | if (fPosition + sizeof(AliRawDataHeader) > fEnd) { | |
283 | Error("ReadHeader", "could not read data header!"); | |
c946ab02 | 284 | Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition); |
b4857df7 | 285 | fSubEvent->GetHeader()->Dump(); |
286 | fCount = 0; | |
287 | fPosition = fEnd; | |
39f9963f | 288 | fErrorCode = kErrNoDataHeader; |
b4857df7 | 289 | continue; |
04fa961a | 290 | } |
b4857df7 | 291 | |
39f9963f | 292 | // "read" the data header |
293 | fHeader = (AliRawDataHeader*) fPosition; | |
294 | fPosition += sizeof(AliRawDataHeader); | |
295 | if (fHeader->fSize != 0xFFFFFFFF) { | |
296 | fCount = fHeader->fSize - sizeof(AliRawDataHeader); | |
297 | } else { | |
298 | fCount = fEnd - fPosition; | |
72dd1d4f | 299 | } |
b4857df7 | 300 | |
39f9963f | 301 | // check consistency of data size in the header and in the sub event |
b4857df7 | 302 | if (fPosition + fCount > fEnd) { |
39f9963f | 303 | Error("ReadHeader", "size in data header exceeds event size!"); |
c946ab02 | 304 | Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition); |
03c6d9a3 | 305 | fSubEvent->GetHeader()->Dump(); |
306 | fCount = 0; | |
307 | fPosition = fEnd; | |
b4857df7 | 308 | fErrorCode = kErrSize; |
03c6d9a3 | 309 | continue; |
04fa961a | 310 | } |
b4857df7 | 311 | |
04fa961a | 312 | } while (!IsSelected()); |
b4857df7 | 313 | |
04fa961a | 314 | return kTRUE; |
315 | } | |
316 | ||
317 | Bool_t AliRawReaderRoot::ReadNextData(UChar_t*& data) | |
318 | { | |
319 | // reads the next payload at the current position | |
320 | // returns kFALSE if the data could not be read | |
321 | ||
b4857df7 | 322 | fErrorCode = 0; |
04fa961a | 323 | while (fCount == 0) { |
c946ab02 | 324 | if (!ReadHeader()) return kFALSE; |
04fa961a | 325 | } |
326 | data = fPosition; | |
327 | fPosition += fCount; | |
328 | fCount = 0; | |
329 | return kTRUE; | |
330 | } | |
331 | ||
332 | Bool_t AliRawReaderRoot::ReadNext(UChar_t* data, Int_t size) | |
333 | { | |
334 | // reads the next block of data at the current position | |
335 | // returns kFALSE if the data could not be read | |
336 | ||
b4857df7 | 337 | fErrorCode = 0; |
04fa961a | 338 | if (fPosition + size > fEnd) { |
339 | Error("ReadNext", "could not read data!"); | |
b4857df7 | 340 | fErrorCode = kErrOutOfBounds; |
04fa961a | 341 | return kFALSE; |
342 | } | |
343 | memcpy(data, fPosition, size); | |
344 | fPosition += size; | |
345 | fCount -= size; | |
346 | return kTRUE; | |
347 | } | |
348 | ||
349 | ||
350 | Bool_t AliRawReaderRoot::Reset() | |
351 | { | |
352 | // reset the current position to the beginning of the event | |
353 | ||
354 | fSubEventIndex = 0; | |
355 | fSubEvent = NULL; | |
356 | fRawData = NULL; | |
39f9963f | 357 | fHeader = NULL; |
04fa961a | 358 | |
359 | fCount = 0; | |
360 | fPosition = fEnd = NULL; | |
361 | return kTRUE; | |
362 | } | |
363 | ||
b4857df7 | 364 | |
365 | Int_t AliRawReaderRoot::CheckData() const | |
366 | { | |
367 | // check the consistency of the data | |
368 | ||
369 | if (!fEvent) return 0; | |
370 | ||
371 | AliRawEvent* subEvent = NULL; | |
372 | Int_t subEventIndex = 0; | |
373 | UChar_t* position = 0; | |
374 | UChar_t* end = 0; | |
be50fca2 | 375 | Int_t result = 0; |
b4857df7 | 376 | |
377 | while (kTRUE) { | |
378 | // get the first or the next sub event if at the end of a sub event | |
379 | if (!subEvent || (position >= end)) { | |
380 | ||
381 | // check for end of event data | |
be50fca2 | 382 | if (subEventIndex >= fEvent->GetNSubEvents()) return result; |
b4857df7 | 383 | subEvent = fEvent->GetSubEvent(subEventIndex++); |
384 | ||
385 | // check the magic word of the sub event | |
be50fca2 | 386 | if (!fSubEvent->GetHeader()->IsValid()) { |
387 | result |= kErrMagic; | |
388 | return result; | |
389 | } | |
b4857df7 | 390 | |
391 | AliRawData* rawData = subEvent->GetRawData(); | |
392 | position = (UChar_t*) rawData->GetBuffer(); | |
393 | end = ((UChar_t*) rawData->GetBuffer()) + rawData->GetSize(); | |
394 | } | |
395 | ||
396 | // continue with the next sub event if no data left in the payload | |
397 | if (position >= end) continue; | |
398 | ||
39f9963f | 399 | // check that there are enough bytes left for the data header |
400 | if (position + sizeof(AliRawDataHeader) > end) { | |
401 | result |= kErrNoDataHeader; | |
be50fca2 | 402 | position = end; |
403 | continue; | |
404 | } | |
b4857df7 | 405 | |
39f9963f | 406 | // check consistency of data size in the header and in the sub event |
407 | AliRawDataHeader* header = (AliRawDataHeader*) position; | |
408 | if (fHeader->fSize != 0xFFFFFFFF) { | |
409 | if (position + header->fSize > end) { | |
410 | result |= kErrSize; | |
411 | position = end; | |
412 | } else { | |
413 | position += header->fSize; | |
414 | } | |
415 | } else { | |
be50fca2 | 416 | position = end; |
be50fca2 | 417 | } |
b4857df7 | 418 | }; |
fd0de2e2 | 419 | |
420 | return result; | |
b4857df7 | 421 | } |