First round of effc++ changes
[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 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  TRD raw data conversion class                                            //
21 //                                                                           //
22 ///////////////////////////////////////////////////////////////////////////////
23
24 #include <Riostream.h>
25
26 #include "AliDAQ.h"
27 #include "AliRawDataHeader.h"
28 #include "AliRawReader.h"
29 #include "AliLog.h"
30
31 #include "AliTRDrawData.h"
32 #include "AliTRDdigitsManager.h"
33 #include "AliTRDgeometry.h"
34 #include "AliTRDdataArrayI.h"
35 #include "AliTRDRawStream.h"
36 #include "AliTRDCommonParam.h"
37 #include "AliTRDcalibDB.h"
38
39 ClassImp(AliTRDrawData)
40
41 //_____________________________________________________________________________
42 AliTRDrawData::AliTRDrawData():TObject()
43 {
44   //
45   // Default constructor
46   //
47
48 }
49
50 //_____________________________________________________________________________
51 AliTRDrawData::~AliTRDrawData()
52 {
53   //
54   // Destructor
55   //
56
57 }
58
59 //_____________________________________________________________________________
60 Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree)
61 {
62   //
63   // Convert the digits to raw data byte stream. The output is written
64   // into the the binary files TRD_<DDL number>.ddl.
65   //
66   // The pseudo raw data format is currently defined like this:
67   //
68   //          DDL data header
69   //
70   //          Subevent (= single chamber) header (8 bytes)
71   //                  FLAG
72   //                  Detector number (2 bytes)
73   //                  Number of data bytes (2 bytes)
74   //                  Number of pads with data (2 bytes)
75   //                  1 empty byte
76   //
77   //          Data bank
78   //
79
80   const Int_t kNumberOfDDLs         = AliDAQ::NumberOfDdls("TRD");
81   const Int_t kSubeventHeaderLength = 8;
82   const Int_t kSubeventDummyFlag    = 0xBB;
83   Int_t       headerSubevent[3];
84
85   ofstream     **outputFile = new ofstream* [kNumberOfDDLs];
86   UInt_t        *bHPosition = new UInt_t    [kNumberOfDDLs];
87   Int_t         *ntotalbyte = new Int_t     [kNumberOfDDLs];
88   Int_t          nbyte = 0;
89   Int_t          npads = 0;
90   unsigned char *bytePtr;
91   unsigned char *headerPtr;
92
93   AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
94
95   // Read in the digit arrays
96   if (!digitsManager->ReadDigits(digitsTree)) {
97     delete digitsManager;
98     return kFALSE;
99   }
100
101   AliTRDgeometry   *geo = new AliTRDgeometry();
102   AliTRDdataArrayI *digits;
103
104   AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
105   if (!commonParam) {
106     AliError("Could not get common parameters\n");
107     return 0;
108   }
109   
110   AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
111   if (!calibration)
112   {
113     AliError("Could not get calibration object\n");
114     return kFALSE;
115   }
116     
117   // the event header
118   AliRawDataHeader header;
119
120   // Open the output files
121   for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
122     char name[20];
123     strcpy(name,AliDAQ::DdlFileName("TRD",iDDL));
124 #ifndef __DECCXX
125     outputFile[iDDL] = new ofstream(name, ios::binary);
126 #else
127     outputFile[iDDL] = new ofstream(name);
128 #endif
129
130     // Write a dummy data header
131     bHPosition[iDDL] = outputFile[iDDL]->tellp();
132     outputFile[iDDL]->write((char*)(&header),sizeof(header));
133     ntotalbyte[iDDL] = 0;
134   }
135
136   // Loop through all detectors
137   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
138
139     Int_t cham      = geo->GetChamber(det);
140     Int_t plan      = geo->GetPlane(det);
141     Int_t sect      = geo->GetSector(det);
142     Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
143     Int_t colMax    = commonParam->GetColMax(plan);
144     Int_t timeTotal = calibration->GetNumberOfTimeBins();
145     Int_t bufferMax = rowMax*colMax*timeTotal;
146     Int_t *buffer   = new Int_t[bufferMax];
147
148     npads   = 0;
149     nbyte   = 0;
150     bytePtr = (unsigned char *) buffer;
151
152     Int_t iDDL = sect;
153
154     // Get the digits array
155     digits = digitsManager->GetDigits(det);
156     digits->Expand();
157
158     // Loop through the detector pixel
159     for (Int_t col = 0; col < colMax; col++) {
160       for (Int_t row = 0; row < rowMax; row++) {
161
162         // Check whether data exists for this pad
163         Bool_t dataflag = kFALSE;
164         for (Int_t time = 0; time < timeTotal; time++) {
165           Int_t data = digits->GetDataUnchecked(row,col,time);
166           if (data) {
167             dataflag = kTRUE;
168             break;
169           }
170         }
171
172         if (dataflag) {
173
174           npads++;
175
176           // The pad row number
177           *bytePtr++ = row + 1;
178           // The pad column number
179           *bytePtr++ = col + 1;
180           nbyte += 2;
181
182           Int_t nzero = 0;
183           for (Int_t time = 0; time < timeTotal; time++) {
184
185             Int_t data = digits->GetDataUnchecked(row,col,time);
186
187             if (!data) {
188               nzero++;
189               if ((nzero ==       256) || 
190                   (time  == timeTotal-1)) {
191                 *bytePtr++ = 0;
192                 *bytePtr++ = nzero-1;
193                 nbyte += 2;
194                 nzero  = 0;
195               }
196             }
197             else {
198               if (nzero) {
199                 *bytePtr++ = 0;
200                 *bytePtr++ = nzero-1;
201                 nbyte += 2;
202                 nzero  = 0;
203               }
204               // High byte (MSB always set)
205               *bytePtr++ = ((data >> 8) | 128);
206               // Low byte
207               *bytePtr++ = (data & 0xff);
208               nbyte += 2;
209             }
210
211           }
212
213         }
214
215       }
216
217     }
218
219     // Fill the end of the buffer with zeros
220     while (nbyte % 4) {  
221       *bytePtr++ = 0;
222       nbyte++;
223     }
224
225     AliDebug(1,Form("det = %d, nbyte = %d (%d)",det,nbyte,bufferMax));
226
227     // Write the subevent header
228     bytePtr    = (unsigned char *) headerSubevent;
229     headerPtr  = bytePtr;
230     *bytePtr++ = kSubeventDummyFlag;
231     *bytePtr++ = (det   & 0xff);
232     *bytePtr++ = (det   >> 8);
233     *bytePtr++ = (nbyte & 0xff);
234     *bytePtr++ = (nbyte >> 8);
235     *bytePtr++ = (nbyte >> 16);
236     *bytePtr++ = (npads & 0xff);
237     *bytePtr++ = (npads >> 8);
238     outputFile[iDDL]->write((char*)headerPtr,kSubeventHeaderLength);
239
240     // Write the buffer to the file
241     bytePtr = (unsigned char *) buffer;
242     outputFile[iDDL]->write((char*)bytePtr,nbyte);
243
244     ntotalbyte[iDDL] += nbyte + kSubeventHeaderLength;
245
246     delete buffer;
247
248   }
249
250   // Update the data headers and close the output files
251   for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
252
253     header.fSize = UInt_t(outputFile[iDDL]->tellp()) - bHPosition[iDDL];
254     header.SetAttribute(0);  // valid data
255     outputFile[iDDL]->seekp(bHPosition[iDDL]);
256     outputFile[iDDL]->write((char*)(&header),sizeof(header));
257
258     outputFile[iDDL]->close();
259     delete outputFile[iDDL];
260
261   }
262
263   delete geo;
264   delete digitsManager;
265
266   delete [] outputFile;
267   delete [] bHPosition;
268   delete [] ntotalbyte;
269
270   return kTRUE;
271
272 }
273
274 //_____________________________________________________________________________
275 AliTRDdigitsManager* AliTRDrawData::Raw2Digits(AliRawReader* rawReader)
276 {
277   //
278   // Read the raw data digits and put them into the returned digits manager
279   //
280
281   AliTRDdataArrayI *digits    = 0;
282   AliTRDdataArrayI *track0    = 0;
283   AliTRDdataArrayI *track1    = 0;
284   AliTRDdataArrayI *track2    = 0; 
285
286   AliTRDgeometry *geo = new AliTRDgeometry();
287
288   AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
289   if (!commonParam) {
290     AliError("Could not get common parameters\n");
291     return 0;
292   }
293     
294   AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
295   if (!calibration) {
296     AliError("Could not get calibration object\n");
297     return 0;
298   }
299
300   // Create the digits manager
301   AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
302   digitsManager->CreateArrays();
303
304   AliTRDRawStream input(rawReader);
305
306   // Loop through the digits
307   while (input.Next()) {
308
309     Int_t det    = input.GetDetector();
310     Int_t npads  = input.GetNPads();
311
312     if (input.IsNewDetector()) {
313
314       if (digits) digits->Compress(1,0);
315       if (track0) track0->Compress(1,0);
316       if (track1) track1->Compress(1,0);
317       if (track2) track2->Compress(1,0);
318
319       AliDebug(2,"Subevent header:");
320       AliDebug(2,Form("\tdet   = %d",det));
321       AliDebug(2,Form("\tnpads = %d",npads));
322
323       // Create the data buffer
324       Int_t cham      = geo->GetChamber(det);
325       Int_t plan      = geo->GetPlane(det);
326       Int_t sect      = geo->GetSector(det);
327       Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
328       Int_t colMax    = commonParam->GetColMax(plan);
329       Int_t timeTotal = calibration->GetNumberOfTimeBins();
330
331       // Add a container for the digits of this detector
332       digits = digitsManager->GetDigits(det);
333       track0 = digitsManager->GetDictionary(det,0);
334       track1 = digitsManager->GetDictionary(det,1);
335       track2 = digitsManager->GetDictionary(det,2);
336       // Allocate memory space for the digits buffer
337       if (digits->GetNtime() == 0) {
338         digits->Allocate(rowMax,colMax,timeTotal);
339         track0->Allocate(rowMax,colMax,timeTotal);
340         track1->Allocate(rowMax,colMax,timeTotal);
341         track2->Allocate(rowMax,colMax,timeTotal);
342       }
343
344     } 
345
346     digits->SetDataUnchecked(input.GetRow(),input.GetColumn(),
347                              input.GetTime(),input.GetSignal());
348     track0->SetDataUnchecked(input.GetRow(),input.GetColumn(),
349                              input.GetTime(),               -1);
350     track1->SetDataUnchecked(input.GetRow(),input.GetColumn(),
351                              input.GetTime(),               -1);
352     track2->SetDataUnchecked(input.GetRow(),input.GetColumn(),
353                              input.GetTime(),               -1);
354   }
355
356   if (digits) digits->Compress(1,0);
357   if (track0) track0->Compress(1,0);
358   if (track1) track1->Compress(1,0);
359   if (track2) track2->Compress(1,0);
360
361   delete geo;
362
363   return digitsManager;
364
365 }