Add conversion class to produce fake raw data
[u/mrichter/AliRoot.git] / TRD / AliTRDrawData.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 /*
17 $Log$
18 */
19
20 ///////////////////////////////////////////////////////////////////////////////
21 //                                                                           //
22 //  TRD raw data conversion class                                            //
23 //                                                                           //
24 ///////////////////////////////////////////////////////////////////////////////
25
26 #include <fstream.h>
27
28 #include "AliTRDrawData.h"
29 #include "AliTRDdigitsManager.h"
30 #include "AliTRDgeometryFull.h"
31 #include "AliTRDparameter.h"
32 #include "AliTRDdataArrayI.h"
33 #include "AliTRDarrayI.h"
34
35 ClassImp(AliTRDrawData)
36
37 //_____________________________________________________________________________
38 AliTRDrawData::AliTRDrawData():TObject()
39 {
40
41   fDebug         = 0;
42   fDigitsManager = NULL;
43
44 }
45
46 //_____________________________________________________________________________
47 AliTRDrawData::AliTRDrawData(const AliTRDrawData &r)
48 {
49   //
50   // AliTRDrawData copy constructor
51   //
52
53   ((AliTRDrawData &) r).Copy(*this);
54
55 }
56
57 //_____________________________________________________________________________
58 AliTRDrawData::~AliTRDrawData()
59 {
60   //
61   // Destructor
62   //
63
64   if (fDigitsManager) {
65     delete fDigitsManager;
66     fDigitsManager = NULL;
67   }
68
69 }
70
71 //_____________________________________________________________________________
72 AliTRDrawData &AliTRDrawData::operator=(const AliTRDrawData &r)
73 {
74   //
75   // Assignment operator
76   //
77
78   if (this != &r) ((AliTRDrawData &) r).Copy(*this);
79   return *this;
80
81 }
82
83 //_____________________________________________________________________________
84 void AliTRDrawData::Copy(TObject &r)
85 {
86   //
87   // Copy function
88   //
89
90   ((AliTRDrawData &) r).fDebug         = fDebug;
91   ((AliTRDrawData &) r).fDigitsManager = NULL;
92
93 }
94
95 //_____________________________________________________________________________
96 Bool_t AliTRDrawData::OpenInput(const Char_t *name)
97 {
98   //
99   // Opens a ROOT-file with the TRD digits 
100   //
101
102   // Create the digits manager
103   if (fDigitsManager) {
104     delete fDigitsManager;
105   }
106   fDigitsManager = new AliTRDdigitsManager();
107   fDigitsManager->SetDebug(fDebug);
108
109   // Open the input file
110   return fDigitsManager->Open(name);
111
112 }
113
114 //_____________________________________________________________________________
115 Bool_t AliTRDrawData::Digit2Raw(const Char_t *name1, const Char_t *name2)
116 {
117   //
118   // Convert the digits to raw data byte stream. The output is written
119   // into the the binary files <name1> and <name2>.
120   //
121   // The pseudo raw data format is currently defined like this:
122   //
123   //          LDC header (8 bytes)
124   //                  FLAG
125   //                  LDC no.
126   //                  Number of detectors with data (not yet implemented)
127   //                  5 empty bytes
128   //
129   //          Subevent (= single chamber) header (8 bytes)
130   //                  FLAG
131   //                  Detector number (2 bytes)
132   //                  Number of data bytes (2 bytes)
133   //                  Number of pads with data (2 bytes)
134   //                  1 empty byte
135   //
136   //          Data bank
137   //
138
139   const Int_t kLDCHeaderLength      = 8;
140   const Int_t kSubeventHeaderLength = 8;
141
142   const Int_t kLDCDummyFlag         = 0xAA;
143   const Int_t kSubeventDummyFlag    = 0xBB;
144
145   int headerLDC[2];
146   int headerSubevent[2];
147
148   Int_t          ntotalbyte[2] = { 0 };
149   Int_t          nbyte = 0;
150   Int_t          npads = 0;
151   unsigned char *byte_p;
152   unsigned char *header_p;
153
154   AliTRDgeometryFull *geo = new AliTRDgeometryFull();
155   AliTRDparameter    *par = new AliTRDparameter("TRDparameter"
156                                                ,"TRD parameter class");
157   AliTRDdataArrayI   *digits;
158
159   if (fDebug) {
160     Info("Digit2Raw","Open the LDC output files %s, %s"
161         ,name1,name2);
162   }
163   ofstream *outputFile1 = new ofstream(name1, ios::out | ios::binary);
164   ofstream *outputFile2 = new ofstream(name2, ios::out | ios::binary);
165   ofstream *outputFile;
166
167   if (!fDigitsManager) {
168     Error("Digit2Raw","No input file open\n");
169     return kFALSE;
170   }
171
172   // Read in the digit arrays
173   if (!fDigitsManager->ReadDigits()) {
174     return kFALSE;
175   }
176
177   // Count the number of chambers with data
178   Int_t ndetLDC0 = 0;
179   Int_t ndetLDC1 = 0;
180
181   if (fDebug > 1) {
182     Info("Digit2Raw","Write the LDC headers");
183   }
184
185   // Write the LDC header 1
186   byte_p    = (unsigned char *) headerLDC;
187   header_p  = byte_p;
188   *byte_p++ = kLDCDummyFlag;
189   *byte_p++ = 1;
190   *byte_p++ = ndetLDC0;
191   *byte_p++ = 0;
192   *byte_p++ = 0;
193   *byte_p++ = 0;
194   *byte_p++ = 0;
195   *byte_p++ = 0;
196   outputFile1->write(header_p,kLDCHeaderLength);
197   ntotalbyte[0] += kLDCHeaderLength;
198
199   if (fDebug > 1) {
200     Info("Digit2Raw","LDC header 0 = %d, %d",headerLDC[0],headerLDC[1]);
201   }
202
203   // Write the LDC header 1
204   byte_p    = (unsigned char *) headerLDC;
205   header_p  = byte_p;
206   *byte_p++ = kLDCDummyFlag;
207   *byte_p++ = 2;
208   *byte_p++ = ndetLDC1;
209   *byte_p++ = 0;
210   *byte_p++ = 0;
211   *byte_p++ = 0;
212   *byte_p++ = 0;
213   *byte_p++ = 0;
214   outputFile2->write(header_p,kLDCHeaderLength);
215   ntotalbyte[1] += kLDCHeaderLength;
216
217   if (fDebug > 1) {
218     Info("Digit2Raw","LDC header 1 = %d, %d",headerLDC[0],headerLDC[1]);
219   }
220
221   // Loop through all detectors
222   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
223
224     Int_t cham      = geo->GetChamber(det);
225     Int_t plan      = geo->GetPlane(det);
226     Int_t sect      = geo->GetSector(det);
227     Int_t rowMax    = par->GetRowMax(plan,cham,sect);
228     Int_t colMax    = par->GetColMax(plan);
229     Int_t timeMax   = par->GetTimeMax();
230     Int_t bufferMax = rowMax*colMax*timeMax;
231     int  *buffer    = new int[bufferMax];
232
233     npads  = 0;
234     nbyte  = 0;
235     byte_p = (unsigned char *) buffer;
236
237     // Determine the LDC (resp. output file)
238     Int_t ldc;
239     if (sect < 9) {
240       outputFile = outputFile1;
241       ldc = 0;
242     }
243     else {
244       outputFile = outputFile2;
245       ldc = 1;
246     }
247
248     // Get the digits array
249     digits = fDigitsManager->GetDigits(det);
250     digits->Expand();
251
252     // Loop through the detector pixel
253     for (Int_t col = 0; col < colMax; col++) {
254       for (Int_t row = 0; row < rowMax; row++) {
255
256         // Check whether data exists for this pad
257         Bool_t dataflag = kFALSE;
258         for (Int_t time = 0; time < timeMax; time++) {
259           Int_t data = digits->GetDataUnchecked(row,col,time);
260           if (data) {
261             dataflag = kTRUE;
262             break;
263           }
264         }
265
266         if (dataflag) {
267
268           npads++;
269
270           // The pad row number
271           *byte_p++ = row + 1;
272           // The pad column number
273           *byte_p++ = col + 1;
274           nbyte += 2;
275
276           Int_t nzero = 0;
277           for (Int_t time = 0; time < timeMax; time++) {
278
279             Int_t data = digits->GetDataUnchecked(row,col,time);
280
281             if (!data) {
282               nzero++;
283               if ((nzero ==       256) || 
284                   (time  == timeMax-1)) {
285                 *byte_p++ = 0;
286                 *byte_p++ = nzero-1;
287                 nbyte += 2;
288                 nzero  = 0;
289               }
290             }
291             else {
292               if (nzero) {
293                 *byte_p++ = 0;
294                 *byte_p++ = nzero-1;
295                 nbyte += 2;
296                 nzero  = 0;
297               }
298               // High byte (MSB always set)
299               *byte_p++ = ((data >> 8) | 128);
300               // Low byte
301               *byte_p++ = (data & 0xff);
302               nbyte += 2;
303             }
304
305           }
306
307         }
308
309       }
310
311     }
312
313     // Fill the end of the buffer with zeros
314     while (nbyte % 4) {  
315       *byte_p++ = 0;
316       nbyte++;
317     }
318
319     if (fDebug > 1) {
320       Info("Digit2Raw","LDC = %d, det = %d, nbyte = %d (%d)",ldc,det,nbyte,bufferMax);
321     }
322
323     // Write the subevent header
324     byte_p    = (unsigned char *) headerSubevent;
325     header_p  = byte_p;
326     *byte_p++ = kSubeventDummyFlag;
327     *byte_p++ = (det   & 0xff);
328     *byte_p++ = (det   >> 8);
329     *byte_p++ = (nbyte & 0xff);
330     *byte_p++ = (nbyte >> 8);
331     *byte_p++ = (npads & 0xff);
332     *byte_p++ = (npads >> 8);
333     *byte_p++ = 0;
334     outputFile->write(header_p,kSubeventHeaderLength);
335
336     // Write the buffer to the file
337     byte_p = (unsigned char *) buffer;
338     outputFile->write(byte_p,nbyte);
339
340     ntotalbyte[ldc] += nbyte + kSubeventHeaderLength;
341
342     delete buffer;
343
344   }
345
346   if (fDebug) {
347     Info("Digit2Raw","Total size: LDC0 = %d, LDC1 = %d",ntotalbyte[0],ntotalbyte[1]);
348   }
349
350   outputFile1->close();
351   outputFile2->close();
352
353   delete geo;
354   delete par;
355   delete outputFile1;
356   delete outputFile2;
357
358   return kTRUE;
359
360 }
361
362 //_____________________________________________________________________________
363 Bool_t AliTRDrawData::Raw2Digit(const Char_t *name1, const Char_t *name2)
364 {
365
366   const Int_t  kLDCHeaderLength      = 8;
367   const Int_t  kSubeventHeaderLength = 8;
368
369   const Int_t  kNldc = 2;
370   const Char_t *name = 0;
371
372   int headerLDC[2];
373   int headerSubevent[2];
374
375   Int_t             npads     = 0;
376   Int_t             nbyte     = 0;
377   unsigned char    *byte_p;
378   ifstream         *inputFile = 0;
379   AliTRDdataArrayI *digits    = 0;
380
381   AliTRDgeometryFull *geo = new AliTRDgeometryFull();
382   AliTRDparameter    *par = new AliTRDparameter("TRDparameter"
383                                                ,"TRD parameter class");
384
385   // Create the digits manager
386   if (fDigitsManager) {
387     delete fDigitsManager;
388   }
389   fDigitsManager = new AliTRDdigitsManager();
390   fDigitsManager->SetDebug(fDebug);
391   fDigitsManager->CreateArrays();
392
393   for (Int_t ldc = 0; ldc < kNldc; ldc++) {
394
395     if      (ldc == 0) {
396       name = name1;
397     }
398     else if (ldc == 1) {
399       name = name2;
400     }
401     if (fDebug) {
402       Info("Raw2Digit","Open the LDC input file %s",name);
403     }
404     inputFile = new ifstream(name, ios::in | ios::binary);
405
406     // Read the LDC header
407     byte_p = (unsigned char *) headerLDC;
408     inputFile->read(byte_p,kLDCHeaderLength);
409
410     if (fDebug > 1) {
411       Info("Raw2Digit","LDC header no. %d:",ldc);
412       Info("Raw2Digit","\tflag   = %d",*byte_p++);
413       Info("Raw2Digit","\tldc no = %d",*byte_p++);
414       Info("Raw2Digit","\tndet   = %d",*byte_p++);
415       Info("Raw2Digit","\tempty  = %d",*byte_p++);
416       Info("Raw2Digit","\tempty  = %d",*byte_p++);
417       Info("Raw2Digit","\tempty  = %d",*byte_p++);
418       Info("Raw2Digit","\tempty  = %d",*byte_p++);
419       Info("Raw2Digit","\tempty  = %d",*byte_p++);
420     }
421
422     // Loop through the subevents
423     byte_p = (unsigned char *) headerSubevent;
424     while (inputFile->read(byte_p,kSubeventHeaderLength)) {
425
426       Int_t flag   = *byte_p++;
427       Int_t detl   = *byte_p++;
428       Int_t deth   = *byte_p++;
429       Int_t det    = detl   + (deth   << 8);
430       Int_t nbytel = *byte_p++;
431       Int_t nbyteh = *byte_p++;
432             nbyte  = nbytel + (nbyteh << 8);
433       Int_t npadsl = *byte_p++;
434       Int_t npadsh = *byte_p++;
435             npads  = npadsl + (npadsh << 8);
436       if (fDebug > 2) {
437         Info("Raw2Digit","Subevent header:");
438         Info("Raw2Digit","\tflag  = %d",flag);
439         Info("Raw2Digit","\tdet   = %d",det);
440         Info("Raw2Digit","\tnbyte = %d",nbyte);
441         Info("Raw2Digit","\tnpads = %d",npads);
442         Info("Raw2Digit","\tempty = %d",*byte_p++);
443       }      
444
445       // Create the data buffer
446       Int_t cham      = geo->GetChamber(det);
447       Int_t plan      = geo->GetPlane(det);
448       Int_t sect      = geo->GetSector(det);
449       Int_t rowMax    = par->GetRowMax(plan,cham,sect);
450       Int_t colMax    = par->GetColMax(plan);
451       Int_t timeMax   = par->GetTimeMax();
452       Int_t bufferMax = rowMax*colMax*timeMax;
453       int   *buffer   = new int[bufferMax];
454       byte_p          = (unsigned char *) buffer;      
455       memset(buffer,0,bufferMax*sizeof(int));
456
457       // Add a container for the digits of this detector
458       digits = fDigitsManager->GetDigits(det);
459       // Allocate memory space for the digits buffer
460       if (digits->GetNtime() == 0) {
461         digits->Allocate(rowMax,colMax,timeMax);
462       }
463
464       // Read the data   
465       inputFile->read(byte_p,nbyte);
466
467       Int_t time;
468       Int_t nzero;
469       Int_t data;
470       Int_t low;
471       Int_t high;
472       Int_t signal;
473
474       // Decompress the data
475       while (nbyte > 0) {
476
477         // The pad row number
478         Int_t row = (*byte_p++) - 1;
479         // The pad column number
480         Int_t col = (*byte_p++) - 1;
481         nbyte -= 2;
482
483         time = nzero = 0;
484
485         while ((time  < timeMax) &&
486                (nbyte >       0)) {
487
488           data = *byte_p++;
489           nbyte--;
490
491           if (data) {
492             if (!nzero) {
493               // signal for given timebim
494               low    = *byte_p++;
495               high   = data & 127;
496               signal = low + (high << 8);
497               if ((row <       0) || (col <       0) || (time <        0) ||
498                   (row >= rowMax) || (col >= colMax) || (time >= timeMax)) {
499                 Error("Raw2Digit"
500                      ,"row=%d(%d) col=%d(%d) time=%d(%d)"
501                      ,row,rowMax,col,colMax,time,timeMax);
502               }
503               else {
504                 digits->SetDataUnchecked(row,col,time,signal);
505               }
506               nbyte--;
507               time++;
508             }
509             else {
510               time += data + 1;
511               nzero = 0;
512             }
513           }
514           else {
515             if (!nzero) {
516               nzero = 1;
517             }
518             else {
519               time++;
520               nzero = 0;
521             }
522           }
523
524         }
525
526       }
527
528       digits->Compress(1,0);
529
530       delete buffer;
531
532       byte_p = (unsigned char *) headerSubevent;
533
534     } 
535
536     inputFile->close();
537     delete inputFile;
538     inputFile = 0;
539
540   }
541
542   delete geo;
543   delete par;
544
545   return kTRUE;
546
547 }