minor bugfix in argument scanning
[u/mrichter/AliRoot.git] / RAW / AliRawReader.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 the base class for reading raw data.
21 ///
22 /// The derived classes, which operate on concrete raw data formats,
23 /// should implement
24 /// - ReadHeader to read the next (data/equipment) header
25 /// - ReadNextData to read the next raw data block (=1 DDL)
26 /// - ReadNext to read a given number of bytes
27 /// - several getters like GetType
28 ///
29 /// Sequential access to the raw data is provided by the methods
30 /// ReadHeader, ReadNextData, ReadNextInt, ReadNextShort, ReadNextChar
31 ///
32 /// If only data from a specific detector (and a given range of DDL numbers)
33 /// should be read, this can be achieved by the Select method.
34 /// Several getters provide information about the current event and the
35 /// current type of raw data.
36 ///
37 ///////////////////////////////////////////////////////////////////////////////
38
39 #include <Riostream.h>
40 #include "AliRawReader.h"
41 #include "AliDAQ.h"
42 #include "AliLog.h"
43
44 ClassImp(AliRawReader)
45
46
47 AliRawReader::AliRawReader() :
48   fEquipmentIdsIn(NULL),
49   fEquipmentIdsOut(NULL),
50   fRequireHeader(kTRUE),
51   fHeader(NULL),
52   fCount(0),
53   fSelectEquipmentType(-1),
54   fSelectMinEquipmentId(-1),
55   fSelectMaxEquipmentId(-1),
56   fSkipInvalid(kFALSE),
57   fSelectEventType(-1),
58   fErrorCode(0),
59   fEventNumber(-1),
60   fErrorLogs("AliRawDataErrorLog",100),
61   fHeaderSwapped(NULL)
62 {
63 // default constructor: initialize data members
64 // Allocate the swapped header in case of Mac
65 #ifndef R__BYTESWAP
66   fHeaderSwapped=new AliRawDataHeader();
67 #endif
68 }
69
70 Bool_t AliRawReader::LoadEquipmentIdsMap(const char *fileName)
71 {
72   // Open the mapping file
73   // and load the mapping data
74   ifstream input(fileName);
75   if (input.is_open()) {
76     Warning("AliRawReader","Equipment ID mapping file is found !");
77     const Int_t kMaxDDL = 256;
78     fEquipmentIdsIn = new TArrayI(kMaxDDL);
79     fEquipmentIdsOut = new TArrayI(kMaxDDL);
80     Int_t equipIn, equipOut;
81     Int_t nIds = 0;
82     while (input >> equipIn >> equipOut) {
83       if (nIds >= kMaxDDL) {
84         Error("AliRawReader","Too many equipment Id mappings found ! Truncating the list !");
85         break;
86       }
87       fEquipmentIdsIn->AddAt(equipIn,nIds); 
88       fEquipmentIdsOut->AddAt(equipOut,nIds);
89       nIds++;
90     }
91     fEquipmentIdsIn->Set(nIds);
92     fEquipmentIdsOut->Set(nIds);
93     input.close();
94     return kTRUE;
95   }
96   else {
97     Error("AliRawReader","equipment id map file is not found ! Skipping the mapping !");
98     return kFALSE;
99   }
100 }
101
102 AliRawReader::AliRawReader(const AliRawReader& rawReader) :
103   TObject(rawReader),
104   fEquipmentIdsIn(rawReader.fEquipmentIdsIn),
105   fEquipmentIdsOut(rawReader.fEquipmentIdsOut),
106   fRequireHeader(rawReader.fRequireHeader),
107   fHeader(rawReader.fHeader),
108   fCount(rawReader.fCount),
109   fSelectEquipmentType(rawReader.fSelectEquipmentType),
110   fSelectMinEquipmentId(rawReader.fSelectMinEquipmentId),
111   fSelectMaxEquipmentId(rawReader.fSelectMaxEquipmentId),
112   fSkipInvalid(rawReader.fSkipInvalid),
113   fSelectEventType(rawReader.fSelectEventType),
114   fErrorCode(0),
115   fEventNumber(-1),
116   fErrorLogs("AliRawDataErrorLog",100),
117   fHeaderSwapped(NULL)
118 {
119 // copy constructor
120 // Allocate the swapped header in case of Mac
121 #ifndef R__BYTESWAP
122   fHeaderSwapped=new AliRawDataHeader(*rawReader.fHeaderSwapped);
123 #endif
124 }
125
126 AliRawReader& AliRawReader::operator = (const AliRawReader& rawReader)
127 {
128 // assignment operator
129   fEquipmentIdsIn = rawReader.fEquipmentIdsIn;
130   fEquipmentIdsOut = rawReader.fEquipmentIdsOut;
131
132   fHeader = rawReader.fHeader;
133   fCount = rawReader.fCount;
134
135   fSelectEquipmentType = rawReader.fSelectEquipmentType;
136   fSelectMinEquipmentId = rawReader.fSelectMinEquipmentId;
137   fSelectMaxEquipmentId = rawReader.fSelectMaxEquipmentId;
138   fSkipInvalid = rawReader.fSkipInvalid;
139   fSelectEventType = rawReader.fSelectEventType;
140
141   fErrorCode = rawReader.fErrorCode;
142
143   fEventNumber = rawReader.fEventNumber;
144   fErrorLogs = *((TClonesArray*)rawReader.fErrorLogs.Clone());
145
146   return *this;
147 }
148
149 AliRawReader::~AliRawReader()
150 {
151   // destructor
152   // delete the mapping arrays if
153   // initialized
154   if (fEquipmentIdsIn) delete fEquipmentIdsIn;
155   if (fEquipmentIdsOut) delete fEquipmentIdsOut;
156   fErrorLogs.Delete();
157   if (fHeaderSwapped) delete fHeaderSwapped;
158 }
159
160 Int_t AliRawReader::GetMappedEquipmentId() const
161 {
162   if (!fEquipmentIdsIn || !fEquipmentIdsOut) {
163     Error("AliRawReader","equipment Ids mapping is not initialized !");
164     return GetEquipmentId();
165   }
166   Int_t equipmentId = GetEquipmentId();
167   for(Int_t iId = 0; iId < fEquipmentIdsIn->GetSize(); iId++) {
168     if (equipmentId == fEquipmentIdsIn->At(iId)) {
169       equipmentId = fEquipmentIdsOut->At(iId);
170       break;
171     }
172   }
173   return equipmentId;
174 }
175
176 Int_t AliRawReader::GetDetectorID() const
177 {
178   // Get the detector ID
179   // The list of detector IDs
180   // can be found in AliDAQ.h
181   Int_t equipmentId;
182   if (fEquipmentIdsIn && fEquipmentIdsIn)
183     equipmentId = GetMappedEquipmentId();
184   else
185     equipmentId = GetEquipmentId();
186
187   if (equipmentId >= 0) {
188     Int_t ddlIndex;
189     return AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex);
190   }
191   else
192     return -1;
193 }
194
195 Int_t AliRawReader::GetDDLID() const
196 {
197   // Get the DDL ID (within one sub-detector)
198   // The list of detector IDs
199   // can be found in AliDAQ.h
200   Int_t equipmentId;
201   if (fEquipmentIdsIn && fEquipmentIdsIn)
202     equipmentId = GetMappedEquipmentId();
203   else
204     equipmentId = GetEquipmentId();
205
206   if (equipmentId >= 0) {
207     Int_t ddlIndex;
208     AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex);
209     return ddlIndex;
210   }
211   else
212     return -1;
213 }
214
215 void AliRawReader::Select(const char *detectorName, Int_t minDDLID, Int_t maxDDLID)
216 {
217 // read only data of the detector with the given name and in the given
218 // range of DDLs (minDDLID <= DDLID <= maxDDLID).
219 // no selection is applied if a value < 0 is used.
220   Int_t detectorID = AliDAQ::DetectorID(detectorName);
221   if(detectorID >= 0)
222     Select(detectorID,minDDLID,maxDDLID);
223 }
224
225 void AliRawReader::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID)
226 {
227 // read only data of the detector with the given ID and in the given
228 // range of DDLs (minDDLID <= DDLID <= maxDDLID).
229 // no selection is applied if a value < 0 is used.
230
231   fSelectEquipmentType = -1;
232
233   if (minDDLID < 0)
234     fSelectMinEquipmentId = AliDAQ::DdlIDOffset(detectorID);
235   else
236     fSelectMinEquipmentId = AliDAQ::DdlID(detectorID,minDDLID);
237
238   if (maxDDLID < 0)
239     fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,AliDAQ::NumberOfDdls(detectorID)-1);
240   else
241     fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,maxDDLID);
242 }
243
244 void AliRawReader::SelectEquipment(Int_t equipmentType, 
245                                    Int_t minEquipmentId, Int_t maxEquipmentId)
246 {
247 // read only data of the equipment with the given type and in the given
248 // range of IDs (minEquipmentId <= EquipmentId <= maxEquipmentId).
249 // no selection is applied if a value < 0 is used.
250
251   fSelectEquipmentType = equipmentType;
252   fSelectMinEquipmentId = minEquipmentId;
253   fSelectMaxEquipmentId = maxEquipmentId;
254 }
255
256 void AliRawReader::SelectEvents(Int_t type)
257 {
258 // read only events with the given type.
259 // no selection is applied if a value < 0 is used.
260
261   fSelectEventType = type;
262 }
263
264 Bool_t AliRawReader::IsSelected() const
265 {
266 // apply the selection (if any)
267
268   if (fSkipInvalid && !IsValid()) return kFALSE;
269
270   if (fSelectEquipmentType >= 0)
271     if (GetEquipmentType() != fSelectEquipmentType) return kFALSE;
272
273   Int_t equipmentId;
274   if (fEquipmentIdsIn && fEquipmentIdsIn)
275     equipmentId = GetMappedEquipmentId();
276   else
277     equipmentId = GetEquipmentId();
278
279   if ((fSelectMinEquipmentId >= 0) && 
280       (equipmentId < fSelectMinEquipmentId))
281     return kFALSE;
282   if ((fSelectMaxEquipmentId >= 0) && 
283       (equipmentId > fSelectMaxEquipmentId))
284     return kFALSE;
285
286   return kTRUE;
287 }
288
289 Bool_t AliRawReader::IsEventSelected() const
290 {
291 // apply the event selection (if any)
292
293   if (fSelectEventType >= 0) {
294     if (GetType() != (UInt_t) fSelectEventType) return kFALSE;
295   }
296
297   return kTRUE;
298 }
299
300 UInt_t AliRawReader::SwapWord(UInt_t x) const
301 {
302    // Swap the endianess of the integer value 'x'
303
304    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
305            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
306 }
307
308 UShort_t AliRawReader::SwapShort(UShort_t x) const
309 {
310    // Swap the endianess of the short value 'x'
311
312    return (((x & 0x00ffU) <<  8) | ((x & 0xff00U) >>  8)) ;
313 }
314
315 Bool_t AliRawReader::ReadNextInt(UInt_t& data)
316 {
317 // reads the next 4 bytes at the current position
318 // returns kFALSE if the data could not be read
319
320   while (fCount == 0) {
321     if (!ReadHeader()) return kFALSE;
322   }
323   if (fCount < (Int_t) sizeof(data)) {
324     Error("ReadNextInt", 
325           "too few data left (%d bytes) to read an UInt_t!", fCount);
326     return kFALSE;
327   }
328   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
329     Error("ReadNextInt", "could not read data!");
330     return kFALSE;
331   }
332 #ifndef R__BYTESWAP
333   data=SwapWord(data);
334 #endif
335   return kTRUE;
336 }
337
338 Bool_t AliRawReader::ReadNextShort(UShort_t& data)
339 {
340 // reads the next 2 bytes at the current position
341 // returns kFALSE if the data could not be read
342
343   while (fCount == 0) {
344     if (!ReadHeader()) return kFALSE;
345   }
346   if (fCount < (Int_t) sizeof(data)) {
347     Error("ReadNextShort", 
348           "too few data left (%d bytes) to read an UShort_t!", fCount);
349     return kFALSE;
350   }
351   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
352     Error("ReadNextShort", "could not read data!");
353     return kFALSE;
354   }
355 #ifndef R__BYTESWAP
356   data=SwapShort(data);
357 #endif
358   return kTRUE;
359 }
360
361 Bool_t AliRawReader::ReadNextChar(UChar_t& data)
362 {
363 // reads the next 1 byte at the current stream position
364 // returns kFALSE if the data could not be read
365
366   while (fCount == 0) {
367     if (!ReadHeader()) return kFALSE;
368   }
369   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
370     Error("ReadNextChar", "could not read data!");
371     return kFALSE;
372   }
373   return kTRUE;
374 }
375
376
377 Int_t AliRawReader::CheckData() const
378 {
379 // check the consistency of the data
380 // derived classes should overwrite the default method which returns 0 (no err)
381
382   return 0;
383 }
384
385
386 void AliRawReader::DumpData(Int_t limit)
387 {
388 // print the raw data
389 // if limit is not negative, only the first and last "limit" lines of raw data
390 // are printed
391
392   Reset();
393   if (!ReadHeader()) {
394     Error("DumpData", "no header");
395     return;
396   }
397   printf("header:\n"
398          " type = %d  run = %d  ", GetType(), GetRunNumber());
399   if (GetEventId()) {
400     printf("event = %8.8x %8.8x\n", GetEventId()[1], GetEventId()[0]);
401   } else {
402     printf("event = -------- --------\n");
403   }
404   if (GetTriggerPattern()) {
405     printf(" trigger = %8.8x %8.8x  ",
406            GetTriggerPattern()[1], GetTriggerPattern()[0]);
407   } else {
408     printf(" trigger = -------- --------  ");
409   }
410   if (GetDetectorPattern()) {
411     printf("detector = %8.8x\n", GetDetectorPattern()[0]);
412   } else {
413     printf("detector = --------\n");
414   }
415   if (GetAttributes()) {
416     printf(" attributes = %8.8x %8.8x %8.8x  ",
417            GetAttributes()[2], GetAttributes()[1], GetAttributes()[0]);
418   } else {
419     printf(" attributes = -------- -------- --------  ");
420   }
421   printf("GDC = %d\n", GetGDCId());
422   printf("\n");
423
424   do {
425     printf("-------------------------------------------------------------------------------\n");
426     printf("LDC = %d\n", GetLDCId());
427
428     printf("equipment:\n"
429            " size = %d  type = %d  id = %d\n",
430            GetEquipmentSize(), GetEquipmentType(), GetEquipmentId());
431     if (GetEquipmentAttributes()) {
432       printf(" attributes = %8.8x %8.8x %8.8x  ", GetEquipmentAttributes()[2],
433              GetEquipmentAttributes()[1], GetEquipmentAttributes()[0]);
434     } else {
435       printf(" attributes = -------- -------- --------  ");
436     }
437     printf("element size = %d\n", GetEquipmentElementSize());
438
439     printf("data header:\n"
440            " size = %d  version = %d  valid = %d  compression = %d\n",
441            GetDataSize(), GetVersion(), IsValid(), IsCompressed());
442
443     printf("\n");
444     if (limit == 0) continue;
445
446     Int_t size = GetDataSize();
447     char line[70];
448     for (Int_t i = 0; i < 70; i++) line[i] = ' ';
449     line[69] = '\0';
450     Int_t pos = 0;
451     Int_t max = 16;
452     UChar_t byte;
453
454     for (Int_t n = 0; n < size; n++) {
455       if (!ReadNextChar(byte)) {
456         Error("DumpData", "couldn't read byte number %d\n", n);
457         break;
458       }
459       if (pos >= max) {
460         printf("%8.8x  %s\n", n-pos, line);
461         for (Int_t i = 0; i < 70; i++) line[i] = ' ';
462         line[69] = '\0';
463         pos = 0;
464         if ((limit > 0) && (n/max == limit)) {
465           Int_t nContinue = ((size-1)/max+1-limit) * max;
466           if (nContinue > n) {
467             printf(" [skipping %d bytes]\n", nContinue-n);
468             n = nContinue-1;
469             continue;
470           }
471         }
472       }
473       Int_t offset = pos/4;
474       if ((byte > 0x20) && (byte < 0x7f)) {
475         line[pos+offset] = byte;
476       } else {
477         line[pos+offset] = '.';
478       }
479       char hex[3];
480       sprintf(hex, "%2.2x", byte);
481       line[max+max/4+3+2*pos+offset] = hex[0];
482       line[max+max/4+4+2*pos+offset] = hex[1];
483       pos++;
484     }
485
486     if (pos > 0) printf("%8.8x  %s\n", size-pos, line);
487     printf("\n");
488            
489   } while (ReadHeader());
490 }
491
492 void AliRawReader::AddErrorLog(AliRawDataErrorLog::ERawDataErrorLevel level,
493                                Int_t code,
494                                const char *message)
495 {
496   // Add a raw data error message to the list
497   // of raw-data decoding errors
498   if (fEventNumber < 0) {
499     AliError("No events have read so far! Impossible to add a raw data error log!");
500     return;
501   }
502   Int_t ddlId = GetEquipmentId();
503   if (ddlId < 0) {
504     AliError("No ddl raw data have been read so far! Impossible to add a raw data error log!");
505     return;
506   }
507
508   Int_t prevEventNumber = -1;
509   Int_t prevDdlId = -1;
510   Int_t prevErrorCode = -1;
511   AliRawDataErrorLog *prevLog = (AliRawDataErrorLog *)fErrorLogs.Last();
512   if (prevLog) {
513     prevEventNumber = prevLog->GetEventNumber();
514     prevDdlId       = prevLog->GetDdlID();
515     prevErrorCode   = prevLog->GetErrorCode();
516   }
517
518   if ((prevEventNumber != fEventNumber) ||
519       (prevDdlId != ddlId) ||
520       (prevErrorCode != code)) {
521     new (fErrorLogs[fErrorLogs.GetEntriesFast()])
522       AliRawDataErrorLog(fEventNumber,
523                          ddlId,
524                          level,
525                          code,
526                          message);
527   }
528   else
529     if (prevLog) prevLog->AddCount();
530
531 }