]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDrawData.cxx
Inserting TMath.h where required by the new version of ROOT
[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 #include <TMath.h>
26
27 #include "AliDAQ.h"
28 #include "AliRawDataHeader.h"
29 #include "AliRawReader.h"
30 #include "AliLog.h"
31
32 #include "AliTRDrawData.h"
33 #include "AliTRDdigitsManager.h"
34 #include "AliTRDgeometry.h"
35 #include "AliTRDdataArrayI.h"
36 #include "AliTRDRawStream.h"
37 #include "AliTRDCommonParam.h"
38 #include "AliTRDcalibDB.h"
39
40 ClassImp(AliTRDrawData)
41
42 //_____________________________________________________________________________
43 AliTRDrawData::AliTRDrawData()
44   :TObject()
45   ,fRawVersion(1)
46   ,fCommonParam(0)
47   ,fCalibration(0)
48   ,fGeo(0)
49   ,fNumberOfDDLs(0)
50 {
51   //
52   // Default constructor
53   //
54
55 }
56
57 //_____________________________________________________________________________
58 AliTRDrawData::AliTRDrawData(const AliTRDrawData &r)
59   :TObject(r)
60   ,fRawVersion(1)
61   ,fCommonParam(0)
62   ,fCalibration(0)
63   ,fGeo(0)
64   ,fNumberOfDDLs(0)
65 {
66   //
67   // Copy constructor
68   //
69
70 }
71
72 //_____________________________________________________________________________
73 AliTRDrawData::~AliTRDrawData()
74 {
75   //
76   // Destructor
77   //
78
79 }
80
81 //_____________________________________________________________________________
82 Bool_t AliTRDrawData::SetRawVersion(Int_t v)
83 {
84   //
85   // Set the raw data version
86   // Currently only version 0 and 1 are available.
87   //
88
89   if ((v == 0) || 
90       (v == 1)) {
91     fRawVersion = v;
92     return kTRUE;
93   }
94
95   return kFALSE;
96
97 }
98
99 //_____________________________________________________________________________
100 Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree, TTree *tracks )
101 {
102   //
103   // Initialize necessary parameters and call one
104   // of the raw data simulator selected by SetRawVersion.
105   //
106   // Currently tracklet output is not spported yet and it
107   // will be supported in higher version simulator.
108   //
109
110   fNumberOfDDLs = AliDAQ::NumberOfDdls("TRD");
111
112   AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
113
114   if (!digitsManager->ReadDigits(digitsTree)) {
115     delete digitsManager;
116     return kFALSE;
117   }
118
119   if (tracks != NULL) {
120     delete digitsManager;
121     printf("<AliTRDrawData::Digits2Raw> Tracklet input is not supported yet.\n");
122     return kFALSE;
123   }
124
125   fGeo = new AliTRDgeometry();
126
127   fCommonParam = AliTRDCommonParam::Instance();
128   if (!fCommonParam) {
129     AliError("Could not get common params\n");
130     delete fGeo;
131     delete digitsManager;
132     return kFALSE;
133   }
134
135   fCalibration = AliTRDcalibDB::Instance();
136   if (!fCalibration) {
137     AliError("Could not get calibration object\n");
138     delete fGeo;
139     delete digitsManager;
140     return kFALSE;
141   }
142
143   Int_t retval = kTRUE;
144
145   // Call appropriate Raw Simulator
146   switch( fRawVersion ) {
147     case 0 : 
148       retval = Digits2RawV0(digitsManager); 
149       break;
150     case 1 : 
151       retval = Digits2RawV1(digitsManager); 
152       break;
153   default: 
154       retval = kFALSE;
155       AliWarning(Form("Unsupported raw version (fRawVersion=%d).\n",fRawVersion));
156     break;
157   }
158
159   // Cleanup
160   delete fGeo;
161   delete digitsManager;
162
163   return retval;
164
165 }
166
167 //_____________________________________________________________________________
168 Bool_t AliTRDrawData::Digits2RawV0(AliTRDdigitsManager* digitsManager)
169 {
170   //
171   // Bogdan's raw simulator (offline use only)
172   //
173   // Convert the digits to raw data byte stream. The output is written
174   // into the the binary files TRD_<DDL number>.ddl.
175   //
176   // The pseudo raw data format is currently defined like this:
177   //
178   //          DDL data header
179   //
180   //          Subevent (= single chamber) header (8 bytes)
181   //                  FLAG
182   //                  Detector number (2 bytes)
183   //                  Number of data bytes (2 bytes)
184   //                  Number of pads with data (2 bytes)
185   //                  1 empty byte
186   //
187   //          Data bank
188   //
189
190   const Int_t kSubeventHeaderLength = 8;
191   const Int_t kSubeventDummyFlag    = 0xBB;
192   Int_t       headerSubevent[3];
193
194   ofstream     **outputFile = new ofstream* [fNumberOfDDLs];
195   UInt_t        *bHPosition = new UInt_t    [fNumberOfDDLs];
196   Int_t         *ntotalbyte = new Int_t     [fNumberOfDDLs];
197   Int_t          nbyte = 0;
198   Int_t          npads = 0;
199   unsigned char *bytePtr;
200   unsigned char *headerPtr;
201
202   AliTRDdataArrayI *digits;
203   AliRawDataHeader  header;   // The event header
204
205   // Open the output files
206   for (Int_t iDDL = 0; iDDL < fNumberOfDDLs; iDDL++) {
207
208     char name[20];
209     sprintf(name, "TRD_%d.ddl", iDDL + AliTRDRawStream::kDDLOffset);
210 #ifndef __DECCXX
211     outputFile[iDDL] = new ofstream(name, ios::binary);
212 #else
213     outputFile[iDDL] = new ofstream(name);
214 #endif
215
216     // Write a dummy data header
217     bHPosition[iDDL] = outputFile[iDDL]->tellp();
218     outputFile[iDDL]->write((char *) (& header),sizeof(header));
219     ntotalbyte[iDDL] = 0;
220
221   }
222
223   // Loop through all detectors
224   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
225
226     Int_t cham      = fGeo->GetChamber(det);
227     Int_t plan      = fGeo->GetPlane(det);
228     Int_t sect      = fGeo->GetSector(det);
229     Int_t rowMax    = fCommonParam->GetRowMax(plan,cham,sect);
230     Int_t colMax    = fCommonParam->GetColMax(plan);
231     Int_t timeTotal = fCalibration->GetNumberOfTimeBins();
232     Int_t bufferMax = rowMax * colMax * timeTotal;
233     Int_t *buffer   = new Int_t[bufferMax];
234
235     npads   = 0;
236     nbyte   = 0;
237     bytePtr = (unsigned char *) buffer;
238
239     Int_t iDDL = sect;
240
241     // Get the digits array
242     digits = digitsManager->GetDigits(det);
243     digits->Expand();
244     // This is to take care of switched off super modules
245     if (digits->GetNtime() == 0) {
246       continue;
247     }
248
249     // Loop through the detector pixel
250     for (Int_t col = 0; col < colMax; col++) {
251       for (Int_t row = 0; row < rowMax; row++) {
252
253         // Check whether data exists for this pad
254         Bool_t dataflag = kFALSE;
255         for (Int_t time = 0; time < timeTotal; time++) {
256           Int_t data = digits->GetDataUnchecked(row,col,time);
257           if (data) {
258             dataflag = kTRUE;
259             break;
260           }
261         }
262
263         if (dataflag) {
264
265           npads++;
266
267           // The pad row number
268           *bytePtr++ = row + 1;
269           // The pad column number
270           *bytePtr++ = col + 1;
271           nbyte += 2;
272
273           Int_t nzero = 0;
274           for (Int_t time = 0; time < timeTotal; time++) {
275
276             Int_t data = digits->GetDataUnchecked(row,col,time);
277
278             if (!data) {
279               nzero++;
280               if ((nzero ==       256) || 
281                   (time  == timeTotal-1)) {
282                 *bytePtr++ = 0;
283                 *bytePtr++ = nzero-1;
284                 nbyte += 2;
285                 nzero  = 0;
286               }
287             }
288             else {
289               if (nzero) {
290                 *bytePtr++ = 0;
291                 *bytePtr++ = nzero-1;
292                 nbyte += 2;
293                 nzero  = 0;
294               }
295               // High byte (MSB always set)
296               *bytePtr++ = ((data >> 8) | 128);
297               // Low byte
298               *bytePtr++ = (data & 0xff);
299               nbyte += 2;
300             }
301
302           }
303
304         }
305
306       }
307
308     }
309
310     // Fill the end of the buffer with zeros
311     while (nbyte % 4) {  
312       *bytePtr++ = 0;
313       nbyte++;
314     }
315
316     AliDebug(1,Form("det = %d, nbyte = %d (%d)",det,nbyte,bufferMax));
317
318     // Write the subevent header
319     bytePtr    = (unsigned char *) headerSubevent;
320     headerPtr  = bytePtr;
321     *bytePtr++ = kSubeventDummyFlag;
322     *bytePtr++ = (det   & 0xff);
323     *bytePtr++ = (det   >> 8);
324     *bytePtr++ = (nbyte & 0xff);
325     *bytePtr++ = (nbyte >> 8);
326     *bytePtr++ = (nbyte >> 16);
327     *bytePtr++ = (npads & 0xff);
328     *bytePtr++ = (npads >> 8);
329     outputFile[iDDL]->write((char *) headerPtr,kSubeventHeaderLength);
330
331     // Write the buffer to the file
332     bytePtr = (unsigned char *) buffer;
333     outputFile[iDDL]->write((char *) bytePtr,nbyte);
334
335     ntotalbyte[iDDL] += nbyte + kSubeventHeaderLength;
336
337     delete buffer;
338
339   }
340
341   // Update the data headers and close the output files
342   for (Int_t iDDL = 0; iDDL < fNumberOfDDLs; iDDL++) {
343
344     header.fSize = UInt_t(outputFile[iDDL]->tellp()) - bHPosition[iDDL];
345     header.SetAttribute(0);  // valid data
346     outputFile[iDDL]->seekp(bHPosition[iDDL]);
347     outputFile[iDDL]->write((char *) (&header),sizeof(header));
348
349     outputFile[iDDL]->close();
350     delete outputFile[iDDL];
351
352   }
353
354   delete [] outputFile;
355   delete [] bHPosition;
356   delete [] ntotalbyte;
357
358   return kTRUE;
359 }
360
361 //_____________________________________________________________________________
362 Bool_t AliTRDrawData::Digits2RawV1(AliTRDdigitsManager *digitsManager)
363 {
364   //
365   // Raw data simulator version 1.
366   // This version simulate only raw data with ADC data and not with tracklet.
367   // This is close to the SM-I commissiong data format in Oct.2006.
368   //
369
370   // (timebin/3)*nADC*nMCM*nROB + header + tracklet(max 20)
371   const Int_t kMaxHcWords = (60/3)*21*16*4 + 100 + 20;
372
373   // Buffer to temporary store half chamber data
374   UInt_t     *hc_buffer   = new UInt_t[kMaxHcWords];
375
376   // sect is same as iDDL, so I use only sect here.
377   for (Int_t sect = 0; sect < fGeo->Nsect(); sect++) { 
378
379     char name[1024];
380     sprintf(name,"TRD_%d.ddl",sect + AliTRDRawStream::kDDLOffset);
381
382 #ifndef __DECCXX
383     ofstream *of = new ofstream(name, ios::binary);
384 #else
385     ofstream *of = new ofstream(name);
386 #endif
387
388     // Write a dummy data header
389     AliRawDataHeader  header;  // the event header
390     UInt_t hpos = of->tellp();
391     of->write((char *) (& header), sizeof(header));
392
393     // Reset payload byte size (payload does not include header).
394     Int_t npayloadbyte = 0;
395
396     // GTU common data header (5x4 bytes shows link mask)
397     for( Int_t cham = 0; cham < fGeo->Ncham(); cham++ ) {
398       UInt_t GtuCdh;
399       GtuCdh = 0x00000FFF;    // Assume all ORI links (12 per stack) are always up
400       of->write((char *) (& GtuCdh), sizeof(GtuCdh));
401       npayloadbyte += 4;
402     }
403
404     // Prepare chamber data
405     for( Int_t cham = 0; cham < fGeo->Ncham(); cham++) {
406       for( Int_t plan = 0; plan < fGeo->Nplan(); plan++) {
407
408         Int_t iDet = fGeo->GetDetector(plan,cham,sect);
409
410         // Get the digits array
411         AliTRDdataArrayI *digits = digitsManager->GetDigits(iDet);
412         digits->Expand();
413
414         Int_t hcwords;
415
416         // Process A side of the chamber
417         hcwords = ProduceHcDataV1(digits,0,iDet,hc_buffer,kMaxHcWords);
418         of->write((char *) hc_buffer, hcwords*4);
419         npayloadbyte += hcwords*4;
420
421         // Process B side of the chamber
422         hcwords = ProduceHcDataV1(digits,1,iDet,hc_buffer,kMaxHcWords);
423         of->write((char *) hc_buffer, hcwords*4);
424         npayloadbyte += hcwords*4;
425
426       }
427     }
428
429     // Complete header
430     header.fSize = UInt_t(of->tellp()) - hpos;
431     header.SetAttribute(0);  // Valid data
432     of->seekp(hpos);         // Rewind to header position
433     of->write((char *) (& header), sizeof(header));
434     of->close();
435     delete of;
436
437   }
438
439   delete hc_buffer;
440   return kTRUE;
441
442 }
443
444 //_____________________________________________________________________________
445 Int_t AliTRDrawData::ProduceHcDataV1(AliTRDdataArrayI *digits, Int_t side
446                                    , Int_t det, UInt_t *buf, Int_t maxSize)
447 {
448   //
449   // Produce half chamber data (= an ORI data) for the given chamber (det) and side (side)
450   // where
451   //   side=0 means A side with ROB positions 0, 2, 4, 6.
452   //   side=1 means B side with ROB positions 1, 3, 5, 7.
453   //
454   // Chamber type (C0 orC1) is determined by "det" automatically.
455   // Appropriate size of buffer (*buf) must be prepared prior to calling this function.
456   // Pointer to the buffer and its size must be given to "buf" and "maxSize".
457   // Return value is the number of valid data filled in the buffer in unit of 32 bits
458   // UInt_t words.
459   // If buffer size if too small, the data is truncated with the buffer size however
460   // the function will finish without crash (this behaviour is similar to the MCM).
461   //
462
463   Int_t          nw = 0;                       // Number of written    words
464   Int_t          of = 0;                       // Number of overflowed words
465   Int_t        plan = fGeo->GetPlane( det );   // Plane
466   Int_t        cham = fGeo->GetChamber( det ); // Chamber
467   Int_t        sect = fGeo->GetSector( det );  // Sector (=iDDL)
468   Int_t        nRow = fCommonParam->GetRowMax( plan, cham, sect );
469   Int_t        nCol = fCommonParam->GetColMax( plan );
470   const Int_t  nMcm = 16;                      // Number of MCMs per ROB (fixed)
471   const Int_t nTBin = fCalibration->GetNumberOfTimeBins();
472   Int_t         dcs = det+100;                 // DCS Serial (in simulation, it's always 
473                                                // chamber ID+1000 without any reason
474   Int_t      kCtype = 0;                       // Chamber type (0:C0, 1:C1)
475   Int_t         iEv = 0xA;                     // Event ID. Now fixed to 10, how do I get event id?
476   UInt_t          x = 0;                       // General used number
477
478   // Check the nCol and nRow.
479   if ((nCol == 144) && 
480       (nRow == 16 || nRow == 12)) {
481     kCtype = (nRow-12) / 4;
482   } 
483   else {
484     AliError(Form("This type of chamber is not supported (nRow=%d, nCol=%d).\n"
485                  ,nRow,nCol));
486     return 0;
487   }
488
489   AliDebug(1,Form("Producing raw data for sect=%d plan=%d cham=%d side=%d"
490                  ,sect,plan,cham,side));
491
492   // Tracklet should be processed here but not implemented yet
493
494   // Write end of tracklet marker
495   if (nw < maxSize) {
496     buf[nw++] = 0xAAAAAAAA;
497   } 
498   else {
499     of++;
500   }
501
502   // Half Chamber header
503   // Now it is the same version as used in SM-I commissioning.
504   // It is: (dcs << 20) | (sect << 15) | (plan << 12) | (cham << 9) | (side << 8)
505   x = (dcs << 20) | (sect << 15) | (plan << 12) | (cham << 9) | (side << 8);
506   if (nw < maxSize) {
507     buf[nw++] = x; 
508   }
509   else {
510     of++;
511   }
512
513   // Scan for ROB and MCM
514   for (Int_t iRobRow = 0; iRobRow < (kCtype + 3); iRobRow++ ) {
515     Int_t iRob = iRobRow * 2 + side;
516     for (Int_t iMcm = 0; iMcm < nMcm; iMcm++ ) {
517       Int_t padrow = iRobRow * 4 + iMcm / 4;
518
519       // MCM header
520       x = ((iRob * nMcm + iMcm) << 24) | ((iEv % 0x100000) << 4) | 0xC;
521       if (nw < maxSize) {
522         buf[nw++] = x; 
523       }
524       else {
525         of++;
526       }
527
528       // ADC data
529       for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
530         Int_t padcol = (17-(iAdc-2)) + (iMcm % 4)*18 + side*72;
531         UInt_t aa = 2;
532         UInt_t *a = new UInt_t[nTBin+2];
533         // 3 timebins are packed into one 32 bits word
534         for (Int_t iT = 0; iT < nTBin; iT+=3) { 
535           if ((padcol >=    0) && 
536               (padcol <  nCol)) {
537             if ((iT    ) < nTBin ) {
538               a[iT  ] = digits->GetDataUnchecked(padrow,padcol,iT);
539             }
540             else {
541               a[iT  ] = 0;
542             }
543             if ((iT + 1) < nTBin ) {
544               a[iT+1] = digits->GetDataUnchecked(padrow,padcol,iT + 1);
545             }
546             else {
547               a[iT+1] = 0;
548             }
549             if ((iT + 2) < nTBin ) {
550               a[iT+2] = digits->GetDataUnchecked(padrow,padcol,iT + 2); 
551             }
552             else {
553               a[iT+2] = 0;
554             }
555           } 
556           else {
557             a[iT] = a[iT+1] = a[iT+2] = 0; // This happenes at the edge of chamber
558           }
559           x = (a[iT+2] << 22) | (a[iT+1] << 12) | (a[iT] << 2) | aa;
560           if (nw < maxSize) {
561             buf[nw++] = x; 
562           }
563           else {
564             of++;
565           }
566           if (aa == 2) {
567             aa = 3; 
568           }
569           else {
570             aa = 2;  // aa alternatively changes between 10b and 11b
571           }
572         }
573         // Diagnostics
574         Float_t avg = 0;
575         Float_t rms = 0;
576         for (Int_t iT = 0; iT < nTBin; iT++) {
577           avg += (Float_t) (a[iT]);
578         }
579         avg /= (Float_t) nTBin;
580         for (Int_t iT = 0; iT < nTBin; iT++) {
581           rms += ((Float_t) (a[iT]) - avg) * ((Float_t) (a[iT]) - avg);
582         }
583         rms = TMath::Sqrt(rms / (Float_t) nTBin);
584         if (rms > 1.7) {
585           AliDebug(1,Form("Large RMS (>1.7)  (ROB,MCM,ADC)=(%02d,%02d,%02d), avg=%03.1f, rms=%03.1f\n"
586                          ,iRob,iMcm,iAdc,avg,rms));
587         }
588         delete a;
589       }
590     }
591   }
592
593   // Write end of raw data marker
594   if (nw < maxSize) {
595     buf[nw++] = 0x00000000; 
596   }
597   else {
598     of++;
599   }
600   if (of != 0) {
601     AliWarning("Buffer overflow. Data is truncated. Please increase buffer size and recompile.");
602   }
603
604   return nw;
605
606 }
607
608 //_____________________________________________________________________________
609 AliTRDdigitsManager* AliTRDrawData::Raw2Digits(AliRawReader *rawReader)
610 {
611   //
612   // Read the raw data digits and put them into the returned digits manager
613   //
614
615   AliTRDdataArrayI *digits = 0;
616   AliTRDdataArrayI *track0 = 0;
617   AliTRDdataArrayI *track1 = 0;
618   AliTRDdataArrayI *track2 = 0; 
619
620   AliTRDgeometry *geo = new AliTRDgeometry();
621
622   AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
623   if (!commonParam) {
624     AliError("Could not get common parameters\n");
625     return 0;
626   }
627     
628   AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
629   if (!calibration) {
630     AliError("Could not get calibration object\n");
631     return 0;
632   }
633
634   // Create the digits manager
635   AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
636   digitsManager->CreateArrays();
637
638   AliTRDRawStream input(rawReader);
639
640   // Loop through the digits
641   while (input.Next()) {
642
643     Int_t det    = input.GetDetector();
644     Int_t npads  = input.GetNPads();
645
646     if (input.IsNewDetector()) {
647
648       if (digits) digits->Compress(1,0);
649       if (track0) track0->Compress(1,0);
650       if (track1) track1->Compress(1,0);
651       if (track2) track2->Compress(1,0);
652
653       AliDebug(2,"Subevent header:");
654       AliDebug(2,Form("\tdet   = %d",det));
655       AliDebug(2,Form("\tnpads = %d",npads));
656
657       // Create the data buffer
658       Int_t cham      = geo->GetChamber(det);
659       Int_t plan      = geo->GetPlane(det);
660       Int_t sect      = geo->GetSector(det);
661       Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
662       Int_t colMax    = commonParam->GetColMax(plan);
663       Int_t timeTotal = calibration->GetNumberOfTimeBins();
664
665       // Add a container for the digits of this detector
666       digits = digitsManager->GetDigits(det);
667       track0 = digitsManager->GetDictionary(det,0);
668       track1 = digitsManager->GetDictionary(det,1);
669       track2 = digitsManager->GetDictionary(det,2);
670       // Allocate memory space for the digits buffer
671       if (digits->GetNtime() == 0) {
672         digits->Allocate(rowMax,colMax,timeTotal);
673         track0->Allocate(rowMax,colMax,timeTotal);
674         track1->Allocate(rowMax,colMax,timeTotal);
675         track2->Allocate(rowMax,colMax,timeTotal);
676       }
677
678     } 
679
680     digits->SetDataUnchecked(input.GetRow(),input.GetColumn(),
681                              input.GetTime(),input.GetSignal());
682     track0->SetDataUnchecked(input.GetRow(),input.GetColumn(),
683                              input.GetTime(),                0);
684     track1->SetDataUnchecked(input.GetRow(),input.GetColumn(),
685                              input.GetTime(),                0);
686     track2->SetDataUnchecked(input.GetRow(),input.GetColumn(),
687                              input.GetTime(),                0);
688
689   }
690
691   if (digits) digits->Compress(1,0);
692   if (track0) track0->Compress(1,0);
693   if (track1) track1->Compress(1,0);
694   if (track2) track2->Compress(1,0);
695
696   delete geo;
697
698   return digitsManager;
699
700 }