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 | |
dd9a70fe |
43 | AliRawReaderRoot::AliRawReaderRoot(const char* fileName, Int_t eventNumber) : |
44 | fFile(NULL), |
45 | fBranch(NULL), |
46 | fEventIndex(eventNumber), |
47 | fEvent(NULL), |
48 | fSubEventIndex(0), |
49 | fSubEvent(NULL), |
50 | fRawData(NULL), |
51 | fPosition(NULL), |
52 | fEnd(NULL) |
04fa961a |
53 | { |
54 | // create an object to read digits from the given input file for the |
55 | // event with the given number |
56 | |
03c6d9a3 |
57 | TDirectory* dir = gDirectory; |
04fa961a |
58 | fFile = TFile::Open(fileName); |
03c6d9a3 |
59 | dir->cd(); |
04fa961a |
60 | if (!fFile || !fFile->IsOpen()) { |
61 | Error("AliRawReaderRoot", "could not open file %s", fileName); |
62 | return; |
63 | } |
64 | TTree* tree = (TTree*) fFile->Get("RAW"); |
65 | if (!tree) { |
66 | Error("AliRawReaderRoot", "no raw data tree found"); |
67 | return; |
68 | } |
dd9a70fe |
69 | fBranch = tree->GetBranch("rawevent"); |
70 | if (!fBranch) { |
04fa961a |
71 | Error("AliRawReaderRoot", "no raw data branch found"); |
72 | return; |
73 | } |
74 | |
75 | fEvent = new AliRawEvent; |
dd9a70fe |
76 | fBranch->SetAddress(&fEvent); |
77 | if (fEventIndex >= 0) { |
78 | if (fBranch->GetEntry(fEventIndex) <= 0) { |
79 | Error("AliRawReaderRoot", "no event with number %d found", fEventIndex); |
80 | return; |
81 | } |
04fa961a |
82 | } |
04fa961a |
83 | } |
84 | |
dd9a70fe |
85 | AliRawReaderRoot::AliRawReaderRoot(AliRawEvent* event) : |
86 | fFile(NULL), |
87 | fBranch(NULL), |
88 | fEventIndex(-1), |
89 | fEvent(event), |
90 | fSubEventIndex(0), |
91 | fSubEvent(NULL), |
92 | fRawData(NULL), |
93 | fPosition(NULL), |
94 | fEnd(NULL) |
04fa961a |
95 | { |
96 | // create an object to read digits from the given raw event |
97 | |
04fa961a |
98 | } |
99 | |
42d20574 |
100 | AliRawReaderRoot::AliRawReaderRoot(const AliRawReaderRoot& rawReader) : |
dd9a70fe |
101 | AliRawReader(rawReader), |
102 | fFile(NULL), |
103 | fBranch(NULL), |
104 | fEventIndex(rawReader.fEventIndex), |
105 | fEvent(NULL), |
106 | fSubEventIndex(rawReader.fSubEventIndex), |
107 | fSubEvent(NULL), |
108 | fRawData(NULL), |
109 | fPosition(NULL), |
110 | fEnd(NULL) |
42d20574 |
111 | { |
112 | // copy constructor |
113 | |
dd9a70fe |
114 | if (rawReader.fFile) { |
115 | TDirectory* dir = gDirectory; |
116 | fFile = TFile::Open(rawReader.fFile->GetName()); |
117 | dir->cd(); |
118 | if (!fFile || !fFile->IsOpen()) { |
119 | Error("AliRawReaderRoot", "could not open file %s", |
120 | rawReader.fFile->GetName()); |
121 | return; |
122 | } |
123 | TTree* tree = (TTree*) fFile->Get("RAW"); |
124 | if (!tree) { |
125 | Error("AliRawReaderRoot", "no raw data tree found"); |
126 | return; |
127 | } |
128 | fBranch = tree->GetBranch("rawevent"); |
129 | if (!fBranch) { |
130 | Error("AliRawReaderRoot", "no raw data branch found"); |
131 | return; |
132 | } |
133 | |
134 | fEvent = new AliRawEvent; |
135 | fBranch->SetAddress(&fEvent); |
136 | if (fEventIndex >= 0) { |
137 | if (fBranch->GetEntry(fEventIndex) <= 0) { |
138 | Error("AliRawReaderRoot", "no event with number %d found", |
139 | fEventIndex); |
140 | return; |
141 | } |
142 | } |
143 | } else { |
144 | fEvent = rawReader.fEvent; |
145 | } |
146 | |
147 | if (fSubEventIndex > 0) { |
148 | fSubEvent = fEvent->GetSubEvent(fSubEventIndex-1); |
149 | fRawData = fSubEvent->GetRawData(); |
150 | fCount = 0; |
151 | fHeader = (AliRawDataHeader*) ((UChar_t*) fRawData->GetBuffer() + |
152 | ((UChar_t*) rawReader.fHeader - |
153 | (UChar_t*) rawReader.fRawData->GetBuffer())); |
154 | fPosition = (UChar_t*) fRawData->GetBuffer() + |
155 | (rawReader.fPosition - (UChar_t*) rawReader.fRawData->GetBuffer()); |
156 | fEnd = ((UChar_t*) fRawData->GetBuffer()) + fRawData->GetSize(); |
157 | } |
42d20574 |
158 | } |
159 | |
160 | AliRawReaderRoot& AliRawReaderRoot::operator = (const AliRawReaderRoot& |
161 | rawReader) |
162 | { |
163 | // assignment operator |
164 | |
165 | this->~AliRawReaderRoot(); |
166 | new(this) AliRawReaderRoot(rawReader); |
167 | return *this; |
168 | } |
169 | |
04fa961a |
170 | AliRawReaderRoot::~AliRawReaderRoot() |
171 | { |
172 | // delete objects and close root file |
173 | |
174 | if (fFile) { |
175 | if (fEvent) delete fEvent; |
176 | fFile->Close(); |
177 | delete fFile; |
178 | } |
179 | } |
180 | |
181 | |
42d20574 |
182 | UInt_t AliRawReaderRoot::GetType() const |
04fa961a |
183 | { |
184 | // get the type from the event header |
185 | |
186 | if (!fEvent) return 0; |
187 | return fEvent->GetHeader()->GetType(); |
188 | } |
189 | |
42d20574 |
190 | UInt_t AliRawReaderRoot::GetRunNumber() const |
04fa961a |
191 | { |
192 | // get the run number from the event header |
193 | |
194 | if (!fEvent) return 0; |
195 | return fEvent->GetHeader()->GetRunNumber(); |
196 | } |
197 | |
42d20574 |
198 | const UInt_t* AliRawReaderRoot::GetEventId() const |
04fa961a |
199 | { |
200 | // get the event id from the event header |
201 | |
202 | if (!fEvent) return NULL; |
203 | return fEvent->GetHeader()->GetId(); |
204 | } |
205 | |
42d20574 |
206 | const UInt_t* AliRawReaderRoot::GetTriggerPattern() const |
04fa961a |
207 | { |
208 | // get the trigger pattern from the event header |
209 | |
210 | if (!fEvent) return NULL; |
211 | return fEvent->GetHeader()->GetTriggerPattern(); |
212 | } |
213 | |
42d20574 |
214 | const UInt_t* AliRawReaderRoot::GetDetectorPattern() const |
04fa961a |
215 | { |
216 | // get the detector pattern from the event header |
217 | |
218 | if (!fEvent) return NULL; |
219 | return fEvent->GetHeader()->GetDetectorPattern(); |
220 | } |
221 | |
42d20574 |
222 | const UInt_t* AliRawReaderRoot::GetAttributes() const |
04fa961a |
223 | { |
224 | // get the type attributes from the event header |
225 | |
226 | if (!fEvent) return NULL; |
227 | return fEvent->GetHeader()->GetTypeAttribute(); |
228 | } |
229 | |
c946ab02 |
230 | UInt_t AliRawReaderRoot::GetLDCId() const |
231 | { |
232 | // get the LDC Id from the event header |
233 | |
234 | if (!fEvent || !fEvent->GetSubEvent(fSubEventIndex)) return 0; |
235 | return fEvent->GetSubEvent(fSubEventIndex)->GetHeader()->GetLDCId(); |
236 | } |
237 | |
42d20574 |
238 | UInt_t AliRawReaderRoot::GetGDCId() const |
04fa961a |
239 | { |
240 | // get the GDC Id from the event header |
241 | |
242 | if (!fEvent) return 0; |
243 | return fEvent->GetHeader()->GetGDCId(); |
244 | } |
245 | |
246 | |
c946ab02 |
247 | Int_t AliRawReaderRoot::GetEquipmentSize() const |
248 | { |
249 | // get the size of the equipment |
250 | |
251 | if (!fEvent || !fEvent->GetEquipmentHeader()) return 0; |
252 | return fEvent->GetEquipmentHeader()->GetEquipmentSize(); |
253 | } |
254 | |
255 | Int_t AliRawReaderRoot::GetEquipmentType() const |
256 | { |
257 | // get the type from the equipment header |
258 | |
259 | if (!fEvent || !fEvent->GetEquipmentHeader()) return -1; |
260 | return fEvent->GetEquipmentHeader()->GetEquipmentType(); |
261 | } |
262 | |
263 | Int_t AliRawReaderRoot::GetEquipmentId() const |
264 | { |
265 | // get the ID from the equipment header |
266 | |
267 | if (!fEvent || !fEvent->GetEquipmentHeader()) return -1; |
268 | return fEvent->GetEquipmentHeader()->GetId(); |
269 | } |
270 | |
271 | const UInt_t* AliRawReaderRoot::GetEquipmentAttributes() const |
272 | { |
273 | // get the attributes from the equipment header |
274 | |
275 | if (!fEvent || !fEvent->GetEquipmentHeader()) return NULL; |
276 | return fEvent->GetEquipmentHeader()->GetTypeAttribute(); |
277 | } |
278 | |
279 | Int_t AliRawReaderRoot::GetEquipmentElementSize() const |
280 | { |
281 | // get the basic element size from the equipment header |
282 | |
283 | if (!fEvent || !fEvent->GetEquipmentHeader()) return 0; |
284 | return fEvent->GetEquipmentHeader()->GetBasicSizeType(); |
285 | } |
286 | |
287 | |
288 | Bool_t AliRawReaderRoot::ReadHeader() |
04fa961a |
289 | { |
39f9963f |
290 | // read a data header at the current position |
291 | // returns kFALSE if the data header could not be read |
04fa961a |
292 | |
b4857df7 |
293 | fErrorCode = 0; |
04fa961a |
294 | if (!fEvent) return kFALSE; |
b4857df7 |
295 | |
04fa961a |
296 | do { |
b4857df7 |
297 | // skip payload (if event was not selected) |
298 | if (fCount > 0) fPosition += fCount; |
299 | |
300 | // get the first or the next sub event if at the end of a sub event |
301 | if (!fSubEvent || (fPosition >= fEnd)) { |
302 | |
303 | // check for end of event data |
04fa961a |
304 | if (fSubEventIndex >= fEvent->GetNSubEvents()) return kFALSE; |
305 | fSubEvent = fEvent->GetSubEvent(fSubEventIndex++); |
b4857df7 |
306 | |
307 | // check the magic word of the sub event |
308 | if (!fSubEvent->GetHeader()->IsValid()) { |
c946ab02 |
309 | Error("ReadHeader", "wrong magic number in sub event!"); |
b4857df7 |
310 | fSubEvent->GetHeader()->Dump(); |
311 | fErrorCode = kErrMagic; |
312 | return kFALSE; |
313 | } |
314 | |
04fa961a |
315 | fRawData = fSubEvent->GetRawData(); |
316 | fCount = 0; |
317 | fPosition = (UChar_t*) fRawData->GetBuffer(); |
318 | fEnd = ((UChar_t*) fRawData->GetBuffer()) + fRawData->GetSize(); |
319 | } |
b4857df7 |
320 | |
321 | // continue with the next sub event if no data left in the payload |
322 | if (fPosition >= fEnd) continue; |
323 | |
39f9963f |
324 | // check that there are enough bytes left for the data header |
325 | if (fPosition + sizeof(AliRawDataHeader) > fEnd) { |
326 | Error("ReadHeader", "could not read data header!"); |
c946ab02 |
327 | Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition); |
b4857df7 |
328 | fSubEvent->GetHeader()->Dump(); |
329 | fCount = 0; |
330 | fPosition = fEnd; |
39f9963f |
331 | fErrorCode = kErrNoDataHeader; |
b4857df7 |
332 | continue; |
04fa961a |
333 | } |
b4857df7 |
334 | |
39f9963f |
335 | // "read" the data header |
336 | fHeader = (AliRawDataHeader*) fPosition; |
337 | fPosition += sizeof(AliRawDataHeader); |
338 | if (fHeader->fSize != 0xFFFFFFFF) { |
339 | fCount = fHeader->fSize - sizeof(AliRawDataHeader); |
340 | } else { |
341 | fCount = fEnd - fPosition; |
72dd1d4f |
342 | } |
b4857df7 |
343 | |
39f9963f |
344 | // check consistency of data size in the header and in the sub event |
b4857df7 |
345 | if (fPosition + fCount > fEnd) { |
39f9963f |
346 | Error("ReadHeader", "size in data header exceeds event size!"); |
c946ab02 |
347 | Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition); |
03c6d9a3 |
348 | fSubEvent->GetHeader()->Dump(); |
349 | fCount = 0; |
350 | fPosition = fEnd; |
b4857df7 |
351 | fErrorCode = kErrSize; |
03c6d9a3 |
352 | continue; |
04fa961a |
353 | } |
b4857df7 |
354 | |
04fa961a |
355 | } while (!IsSelected()); |
b4857df7 |
356 | |
04fa961a |
357 | return kTRUE; |
358 | } |
359 | |
360 | Bool_t AliRawReaderRoot::ReadNextData(UChar_t*& data) |
361 | { |
362 | // reads the next payload at the current position |
363 | // returns kFALSE if the data could not be read |
364 | |
b4857df7 |
365 | fErrorCode = 0; |
04fa961a |
366 | while (fCount == 0) { |
c946ab02 |
367 | if (!ReadHeader()) return kFALSE; |
04fa961a |
368 | } |
369 | data = fPosition; |
370 | fPosition += fCount; |
371 | fCount = 0; |
372 | return kTRUE; |
373 | } |
374 | |
375 | Bool_t AliRawReaderRoot::ReadNext(UChar_t* data, Int_t size) |
376 | { |
377 | // reads the next block of data at the current position |
378 | // returns kFALSE if the data could not be read |
379 | |
b4857df7 |
380 | fErrorCode = 0; |
04fa961a |
381 | if (fPosition + size > fEnd) { |
382 | Error("ReadNext", "could not read data!"); |
b4857df7 |
383 | fErrorCode = kErrOutOfBounds; |
04fa961a |
384 | return kFALSE; |
385 | } |
386 | memcpy(data, fPosition, size); |
387 | fPosition += size; |
388 | fCount -= size; |
389 | return kTRUE; |
390 | } |
391 | |
392 | |
393 | Bool_t AliRawReaderRoot::Reset() |
394 | { |
395 | // reset the current position to the beginning of the event |
396 | |
397 | fSubEventIndex = 0; |
398 | fSubEvent = NULL; |
399 | fRawData = NULL; |
39f9963f |
400 | fHeader = NULL; |
04fa961a |
401 | |
402 | fCount = 0; |
403 | fPosition = fEnd = NULL; |
404 | return kTRUE; |
405 | } |
406 | |
b4857df7 |
407 | |
dd9a70fe |
408 | Bool_t AliRawReaderRoot::NextEvent() |
409 | { |
410 | // go to the next event in the root file |
411 | |
412 | if (!fFile) return kFALSE; |
413 | |
414 | do { |
415 | if (fBranch->GetEntry(fEventIndex+1) <= 0) { |
416 | delete fEvent; |
417 | fEvent = new AliRawEvent; |
418 | fBranch->SetAddress(&fEvent); |
419 | return kFALSE; |
420 | } |
421 | fEventIndex++; |
422 | } while (!IsEventSelected()); |
423 | return Reset(); |
424 | } |
425 | |
426 | Bool_t AliRawReaderRoot::RewindEvents() |
427 | { |
428 | // go back to the beginning of the root file |
429 | |
430 | if (!fFile) return kFALSE; |
431 | |
432 | fEventIndex = -1; |
433 | delete fEvent; |
434 | fEvent = new AliRawEvent; |
435 | fBranch->SetAddress(&fEvent); |
436 | return Reset(); |
437 | } |
438 | |
439 | |
b4857df7 |
440 | Int_t AliRawReaderRoot::CheckData() const |
441 | { |
442 | // check the consistency of the data |
443 | |
444 | if (!fEvent) return 0; |
445 | |
446 | AliRawEvent* subEvent = NULL; |
447 | Int_t subEventIndex = 0; |
448 | UChar_t* position = 0; |
449 | UChar_t* end = 0; |
be50fca2 |
450 | Int_t result = 0; |
b4857df7 |
451 | |
452 | while (kTRUE) { |
453 | // get the first or the next sub event if at the end of a sub event |
454 | if (!subEvent || (position >= end)) { |
455 | |
456 | // check for end of event data |
be50fca2 |
457 | if (subEventIndex >= fEvent->GetNSubEvents()) return result; |
b4857df7 |
458 | subEvent = fEvent->GetSubEvent(subEventIndex++); |
459 | |
460 | // check the magic word of the sub event |
be50fca2 |
461 | if (!fSubEvent->GetHeader()->IsValid()) { |
462 | result |= kErrMagic; |
463 | return result; |
464 | } |
b4857df7 |
465 | |
466 | AliRawData* rawData = subEvent->GetRawData(); |
467 | position = (UChar_t*) rawData->GetBuffer(); |
468 | end = ((UChar_t*) rawData->GetBuffer()) + rawData->GetSize(); |
469 | } |
470 | |
471 | // continue with the next sub event if no data left in the payload |
472 | if (position >= end) continue; |
473 | |
39f9963f |
474 | // check that there are enough bytes left for the data header |
475 | if (position + sizeof(AliRawDataHeader) > end) { |
476 | result |= kErrNoDataHeader; |
be50fca2 |
477 | position = end; |
478 | continue; |
479 | } |
b4857df7 |
480 | |
39f9963f |
481 | // check consistency of data size in the header and in the sub event |
482 | AliRawDataHeader* header = (AliRawDataHeader*) position; |
483 | if (fHeader->fSize != 0xFFFFFFFF) { |
484 | if (position + header->fSize > end) { |
485 | result |= kErrSize; |
486 | position = end; |
487 | } else { |
488 | position += header->fSize; |
489 | } |
490 | } else { |
be50fca2 |
491 | position = end; |
be50fca2 |
492 | } |
b4857df7 |
493 | }; |
fd0de2e2 |
494 | |
495 | return result; |
b4857df7 |
496 | } |