1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 // TRD raw data conversion class //
22 ///////////////////////////////////////////////////////////////////////////////
24 #include <Riostream.h>
28 #include "AliRawDataHeader.h"
29 #include "AliRawReader.h"
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"
40 ClassImp(AliTRDrawData)
42 //_____________________________________________________________________________
43 AliTRDrawData::AliTRDrawData()
52 // Default constructor
57 //_____________________________________________________________________________
58 AliTRDrawData::AliTRDrawData(const AliTRDrawData &r)
72 //_____________________________________________________________________________
73 AliTRDrawData::~AliTRDrawData()
81 //_____________________________________________________________________________
82 Bool_t AliTRDrawData::SetRawVersion(Int_t v)
85 // Set the raw data version
86 // Currently only version 0 and 1 are available.
99 //_____________________________________________________________________________
100 Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree, TTree *tracks )
103 // Initialize necessary parameters and call one
104 // of the raw data simulator selected by SetRawVersion.
106 // Currently tracklet output is not spported yet and it
107 // will be supported in higher version simulator.
110 fNumberOfDDLs = AliDAQ::NumberOfDdls("TRD");
112 AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
114 if (!digitsManager->ReadDigits(digitsTree)) {
115 delete digitsManager;
119 if (tracks != NULL) {
120 delete digitsManager;
121 printf("<AliTRDrawData::Digits2Raw> Tracklet input is not supported yet.\n");
125 fGeo = new AliTRDgeometry();
127 fCommonParam = AliTRDCommonParam::Instance();
129 AliError("Could not get common params\n");
131 delete digitsManager;
135 fCalibration = AliTRDcalibDB::Instance();
137 AliError("Could not get calibration object\n");
139 delete digitsManager;
143 Int_t retval = kTRUE;
145 // Call appropriate Raw Simulator
146 switch( fRawVersion ) {
148 retval = Digits2RawV0(digitsManager);
151 retval = Digits2RawV1(digitsManager);
155 AliWarning(Form("Unsupported raw version (fRawVersion=%d).\n",fRawVersion));
161 delete digitsManager;
167 //_____________________________________________________________________________
168 Bool_t AliTRDrawData::Digits2RawV0(AliTRDdigitsManager* digitsManager)
171 // Bogdan's raw simulator (offline use only)
173 // Convert the digits to raw data byte stream. The output is written
174 // into the the binary files TRD_<DDL number>.ddl.
176 // The pseudo raw data format is currently defined like this:
180 // Subevent (= single chamber) header (8 bytes)
182 // Detector number (2 bytes)
183 // Number of data bytes (2 bytes)
184 // Number of pads with data (2 bytes)
190 const Int_t kSubeventHeaderLength = 8;
191 const Int_t kSubeventDummyFlag = 0xBB;
192 Int_t headerSubevent[3];
194 ofstream **outputFile = new ofstream* [fNumberOfDDLs];
195 UInt_t *bHPosition = new UInt_t [fNumberOfDDLs];
196 Int_t *ntotalbyte = new Int_t [fNumberOfDDLs];
199 unsigned char *bytePtr;
200 unsigned char *headerPtr;
202 AliTRDdataArrayI *digits;
203 AliRawDataHeader header; // The event header
205 // Open the output files
206 for (Int_t iDDL = 0; iDDL < fNumberOfDDLs; iDDL++) {
209 sprintf(name, "TRD_%d.ddl", iDDL + AliTRDRawStream::kDDLOffset);
211 outputFile[iDDL] = new ofstream(name, ios::binary);
213 outputFile[iDDL] = new ofstream(name);
216 // Write a dummy data header
217 bHPosition[iDDL] = outputFile[iDDL]->tellp();
218 outputFile[iDDL]->write((char *) (& header),sizeof(header));
219 ntotalbyte[iDDL] = 0;
223 // Loop through all detectors
224 for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
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];
237 bytePtr = (unsigned char *) buffer;
241 // Get the digits array
242 digits = digitsManager->GetDigits(det);
244 // This is to take care of switched off super modules
245 if (digits->GetNtime() == 0) {
249 // Loop through the detector pixel
250 for (Int_t col = 0; col < colMax; col++) {
251 for (Int_t row = 0; row < rowMax; row++) {
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);
267 // The pad row number
268 *bytePtr++ = row + 1;
269 // The pad column number
270 *bytePtr++ = col + 1;
274 for (Int_t time = 0; time < timeTotal; time++) {
276 Int_t data = digits->GetDataUnchecked(row,col,time);
280 if ((nzero == 256) ||
281 (time == timeTotal-1)) {
283 *bytePtr++ = nzero-1;
291 *bytePtr++ = nzero-1;
295 // High byte (MSB always set)
296 *bytePtr++ = ((data >> 8) | 128);
298 *bytePtr++ = (data & 0xff);
310 // Fill the end of the buffer with zeros
316 AliDebug(1,Form("det = %d, nbyte = %d (%d)",det,nbyte,bufferMax));
318 // Write the subevent header
319 bytePtr = (unsigned char *) headerSubevent;
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);
331 // Write the buffer to the file
332 bytePtr = (unsigned char *) buffer;
333 outputFile[iDDL]->write((char *) bytePtr,nbyte);
335 ntotalbyte[iDDL] += nbyte + kSubeventHeaderLength;
341 // Update the data headers and close the output files
342 for (Int_t iDDL = 0; iDDL < fNumberOfDDLs; iDDL++) {
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));
349 outputFile[iDDL]->close();
350 delete outputFile[iDDL];
354 delete [] outputFile;
355 delete [] bHPosition;
356 delete [] ntotalbyte;
361 //_____________________________________________________________________________
362 Bool_t AliTRDrawData::Digits2RawV1(AliTRDdigitsManager *digitsManager)
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.
370 // (timebin/3)*nADC*nMCM*nROB + header + tracklet(max 20)
371 const Int_t kMaxHcWords = (60/3)*21*16*4 + 100 + 20;
373 // Buffer to temporary store half chamber data
374 UInt_t *hc_buffer = new UInt_t[kMaxHcWords];
376 // sect is same as iDDL, so I use only sect here.
377 for (Int_t sect = 0; sect < fGeo->Nsect(); sect++) {
380 sprintf(name,"TRD_%d.ddl",sect + AliTRDRawStream::kDDLOffset);
383 ofstream *of = new ofstream(name, ios::binary);
385 ofstream *of = new ofstream(name);
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));
393 // Reset payload byte size (payload does not include header).
394 Int_t npayloadbyte = 0;
396 // GTU common data header (5x4 bytes shows link mask)
397 for( Int_t cham = 0; cham < fGeo->Ncham(); cham++ ) {
399 GtuCdh = 0x00000FFF; // Assume all ORI links (12 per stack) are always up
400 of->write((char *) (& GtuCdh), sizeof(GtuCdh));
404 // Prepare chamber data
405 for( Int_t cham = 0; cham < fGeo->Ncham(); cham++) {
406 for( Int_t plan = 0; plan < fGeo->Nplan(); plan++) {
408 Int_t iDet = fGeo->GetDetector(plan,cham,sect);
410 // Get the digits array
411 AliTRDdataArrayI *digits = digitsManager->GetDigits(iDet);
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;
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;
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));
444 //_____________________________________________________________________________
445 Int_t AliTRDrawData::ProduceHcDataV1(AliTRDdataArrayI *digits, Int_t side
446 , Int_t det, UInt_t *buf, Int_t maxSize)
449 // Produce half chamber data (= an ORI data) for the given chamber (det) and side (side)
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.
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
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).
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
478 // Check the nCol and nRow.
480 (nRow == 16 || nRow == 12)) {
481 kCtype = (nRow-12) / 4;
484 AliError(Form("This type of chamber is not supported (nRow=%d, nCol=%d).\n"
489 AliDebug(1,Form("Producing raw data for sect=%d plan=%d cham=%d side=%d"
490 ,sect,plan,cham,side));
492 // Tracklet should be processed here but not implemented yet
494 // Write end of tracklet marker
496 buf[nw++] = 0xAAAAAAAA;
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);
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;
520 x = ((iRob * nMcm + iMcm) << 24) | ((iEv % 0x100000) << 4) | 0xC;
529 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
530 Int_t padcol = (17-(iAdc-2)) + (iMcm % 4)*18 + side*72;
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) {
537 if ((iT ) < nTBin ) {
538 a[iT ] = digits->GetDataUnchecked(padrow,padcol,iT);
543 if ((iT + 1) < nTBin ) {
544 a[iT+1] = digits->GetDataUnchecked(padrow,padcol,iT + 1);
549 if ((iT + 2) < nTBin ) {
550 a[iT+2] = digits->GetDataUnchecked(padrow,padcol,iT + 2);
557 a[iT] = a[iT+1] = a[iT+2] = 0; // This happenes at the edge of chamber
559 x = (a[iT+2] << 22) | (a[iT+1] << 12) | (a[iT] << 2) | aa;
570 aa = 2; // aa alternatively changes between 10b and 11b
576 for (Int_t iT = 0; iT < nTBin; iT++) {
577 avg += (Float_t) (a[iT]);
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);
583 rms = TMath::Sqrt(rms / (Float_t) nTBin);
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));
593 // Write end of raw data marker
595 buf[nw++] = 0x00000000;
601 AliWarning("Buffer overflow. Data is truncated. Please increase buffer size and recompile.");
608 //_____________________________________________________________________________
609 AliTRDdigitsManager* AliTRDrawData::Raw2Digits(AliRawReader *rawReader)
612 // Read the raw data digits and put them into the returned digits manager
615 AliTRDdataArrayI *digits = 0;
616 AliTRDdataArrayI *track0 = 0;
617 AliTRDdataArrayI *track1 = 0;
618 AliTRDdataArrayI *track2 = 0;
620 AliTRDgeometry *geo = new AliTRDgeometry();
622 AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
624 AliError("Could not get common parameters\n");
628 AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
630 AliError("Could not get calibration object\n");
634 // Create the digits manager
635 AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
636 digitsManager->CreateArrays();
638 AliTRDRawStream input(rawReader);
640 // Loop through the digits
641 while (input.Next()) {
643 Int_t det = input.GetDetector();
644 Int_t npads = input.GetNPads();
646 if (input.IsNewDetector()) {
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);
653 AliDebug(2,"Subevent header:");
654 AliDebug(2,Form("\tdet = %d",det));
655 AliDebug(2,Form("\tnpads = %d",npads));
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();
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);
680 digits->SetDataUnchecked(input.GetRow(),input.GetColumn(),
681 input.GetTime(),input.GetSignal());
682 track0->SetDataUnchecked(input.GetRow(),input.GetColumn(),
684 track1->SetDataUnchecked(input.GetRow(),input.GetColumn(),
686 track2->SetDataUnchecked(input.GetRow(),input.GetColumn(),
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);
698 return digitsManager;