functionality of raw readers extended to read more than one event
[u/mrichter/AliRoot.git] / RAW / AliRawReaderRoot.cxx
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
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
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 ///
29 ///////////////////////////////////////////////////////////////////////////////
30
31 #include <TFile.h>
32 #include <TTree.h>
33 #include "AliRawReaderRoot.h"
34 #include "AliRawEvent.h"
35 #include "AliRawEventHeader.h"
36 #include "AliRawEquipmentHeader.h"
37 #include "AliRawData.h"
38
39
40 ClassImp(AliRawReaderRoot)
41
42
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)
53 {
54 // create an object to read digits from the given input file for the
55 // event with the given number
56
57   TDirectory* dir = gDirectory;
58   fFile = TFile::Open(fileName);
59   dir->cd();
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   }
69   fBranch = tree->GetBranch("rawevent");
70   if (!fBranch) {
71     Error("AliRawReaderRoot", "no raw data branch found");
72     return;
73   }
74
75   fEvent = new AliRawEvent;
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     }
82   }
83 }
84
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)
95 {
96 // create an object to read digits from the given raw event
97
98 }
99
100 AliRawReaderRoot::AliRawReaderRoot(const AliRawReaderRoot& rawReader) :
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)
111 {
112 // copy constructor
113
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   }
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
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
182 UInt_t AliRawReaderRoot::GetType() const
183 {
184 // get the type from the event header
185
186   if (!fEvent) return 0;
187   return fEvent->GetHeader()->GetType();
188 }
189
190 UInt_t AliRawReaderRoot::GetRunNumber() const
191 {
192 // get the run number from the event header
193
194   if (!fEvent) return 0;
195   return fEvent->GetHeader()->GetRunNumber();
196 }
197
198 const UInt_t* AliRawReaderRoot::GetEventId() const
199 {
200 // get the event id from the event header
201
202   if (!fEvent) return NULL;
203   return fEvent->GetHeader()->GetId();
204 }
205
206 const UInt_t* AliRawReaderRoot::GetTriggerPattern() const
207 {
208 // get the trigger pattern from the event header
209
210   if (!fEvent) return NULL;
211   return fEvent->GetHeader()->GetTriggerPattern();
212 }
213
214 const UInt_t* AliRawReaderRoot::GetDetectorPattern() const
215 {
216 // get the detector pattern from the event header
217
218   if (!fEvent) return NULL;
219   return fEvent->GetHeader()->GetDetectorPattern();
220 }
221
222 const UInt_t* AliRawReaderRoot::GetAttributes() const
223 {
224 // get the type attributes from the event header
225
226   if (!fEvent) return NULL;
227   return fEvent->GetHeader()->GetTypeAttribute();
228 }
229
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
238 UInt_t AliRawReaderRoot::GetGDCId() const
239 {
240 // get the GDC Id from the event header
241
242   if (!fEvent) return 0;
243   return fEvent->GetHeader()->GetGDCId();
244 }
245
246
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()
289 {
290 // read a data header at the current position
291 // returns kFALSE if the data header could not be read
292
293   fErrorCode = 0;
294   if (!fEvent) return kFALSE;
295
296   do {
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
304       if (fSubEventIndex >= fEvent->GetNSubEvents()) return kFALSE;
305       fSubEvent = fEvent->GetSubEvent(fSubEventIndex++);
306
307       // check the magic word of the sub event
308       if (!fSubEvent->GetHeader()->IsValid()) {
309         Error("ReadHeader", "wrong magic number in sub event!");
310         fSubEvent->GetHeader()->Dump();
311         fErrorCode = kErrMagic;
312         return kFALSE;
313       }
314
315       fRawData = fSubEvent->GetRawData();
316       fCount = 0;
317       fPosition = (UChar_t*) fRawData->GetBuffer();
318       fEnd = ((UChar_t*) fRawData->GetBuffer()) + fRawData->GetSize();
319     }
320
321     // continue with the next sub event if no data left in the payload
322     if (fPosition >= fEnd) continue;
323
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!");
327       Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition);
328       fSubEvent->GetHeader()->Dump();
329       fCount = 0;
330       fPosition = fEnd;
331       fErrorCode = kErrNoDataHeader;
332       continue;
333     }
334
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;
342     }
343
344     // check consistency of data size in the header and in the sub event
345     if (fPosition + fCount > fEnd) {  
346       Error("ReadHeader", "size in data header exceeds event size!");
347       Warning("ReadHeader", "skipping %d bytes", fEnd - fPosition);
348       fSubEvent->GetHeader()->Dump();
349       fCount = 0;
350       fPosition = fEnd;
351       fErrorCode = kErrSize;
352       continue;
353     }
354
355   } while (!IsSelected());
356
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
365   fErrorCode = 0;
366   while (fCount == 0) {
367     if (!ReadHeader()) return kFALSE;
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
380   fErrorCode = 0;
381   if (fPosition + size > fEnd) {
382     Error("ReadNext", "could not read data!");
383     fErrorCode = kErrOutOfBounds;
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;
400   fHeader = NULL;
401
402   fCount = 0;
403   fPosition = fEnd = NULL;
404   return kTRUE;
405 }
406
407
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
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;
450   Int_t result = 0;
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
457       if (subEventIndex >= fEvent->GetNSubEvents()) return result;
458       subEvent = fEvent->GetSubEvent(subEventIndex++);
459
460       // check the magic word of the sub event
461       if (!fSubEvent->GetHeader()->IsValid()) {
462         result |= kErrMagic;
463         return result;
464       }
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
474     // check that there are enough bytes left for the data header
475     if (position + sizeof(AliRawDataHeader) > end) {
476       result |= kErrNoDataHeader;
477       position = end;
478       continue;
479     }
480
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 {
491       position = end;
492     }
493   };
494
495   return result;
496 }