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 /* History of cvs commits:
21 * Revision 1.14 2007/01/23 10:27:37 alibrary
22 * Adding include files where needed for latest ROOT
24 * Revision 1.13 2006/09/07 18:31:08 kharlov
25 * Effective c++ corrections (T.Pocheptsov)
27 * Revision 1.12 2005/05/28 14:19:04 schutz
28 * Compilation warnings fixed by T.P.
32 //_________________________________________________________________________
33 // Class designed to convert raw data to aliroot format. We assume, that
34 // prototype is situated in the center of 3 PHOS module and convert prototype
35 // outpur to AliPHOSDigits. In addition, we fill branch of TreeE with
36 // AliPHOSBeamTestEvent, contaning description of event(triggers etc).
37 // Note, that one byte per channel in raw data is transvormed to class
38 // AliPHOSDigit, so finale zise increase ~ 100 times. So output can be split
39 // into peases of reasonable size: each file can not contain more than
40 // fMaxPerFile: if there are still events in raw file, then new directory
41 // is created and header+digits files are written to it.
44 // AliPHOSRaw2Digits * r = new AliPHOSRaw2Digits("path/input.file") ;
45 // //note, that it can be gzipped file!
46 // //Set position of the target in the given run.
47 // //Z axis along beam direction, from target to prototype (0-surface of prototype)
48 // //X axis along columns of prototype (0-center of prototype)
49 // //Y axis along raws of prototype (0-center of prototype)
50 // Double_t pos[3]={0,0,-452.} ;
51 // r->SetTargetPosition(pos) ;
52 // //Read/create connection Table:
53 // TFile f("ConTableDB.root") ;
54 // AliPHOSConTableDB * cdb = f.Get("AliPHOSConTableDB") ;
56 // r->SetConTableDB(cdb) ;
59 // As a result files galice.root and PHOS.Digits.root should be produced in
60 // current dir, and, possibly, dirs 1,2,3... each with galice.root and PHOS.Digits.root,
61 // where the rest of data are written.
63 /*-- Author: Maxim Volkov (RRC KI)
64 Dmitri Peressounko (RRC KI & SUBATECH)
65 Yuri Kharlov (IHEP & SUBATECH) */
67 //////////////////////////////////////////////////////////////////////////////
69 // --- ROOT system ---
71 #include <TClonesArray.h>
76 // --- Standard library ---
80 // --- AliRoot header files ---
81 #include "AliPHOSDigit.h"
82 #include "AliPHOSConTableDB.h"
83 #include "AliPHOSBeamTestEvent.h"
84 #include "AliPHOSRaw2Digits.h"
87 ClassImp(AliPHOSRaw2Digits)
89 //____________________________________________________________________________
90 AliPHOSRaw2Digits::AliPHOSRaw2Digits() :
102 fIsInitialized(kFALSE),
109 //As one can easily see, this is constructor.
115 //____________________________________________________________________________
116 AliPHOSRaw2Digits::AliPHOSRaw2Digits(const char * filename) :
129 fIsInitialized(kFALSE),
136 //this constructor should be normally used. Parameters: input file
137 TString outname(fInName) ;
139 outname.ReplaceAll(".fz",".root") ;
140 outname.ReplaceAll(".gz","") ;
148 //____________________________________________________________________________
149 AliPHOSRaw2Digits::AliPHOSRaw2Digits(AliPHOSRaw2Digits & r2d) :
150 TTask(r2d.GetName(), r2d.GetTitle()),
151 fDigits(r2d.fDigits),
152 fPHOSHeader(r2d.fPHOSHeader),
153 fctdb(new AliPHOSConTableDB(*r2d.fctdb)),
154 fHeaderFile(new TFile(r2d.fHeaderFile->GetName(), "new" )),
155 fDigitsFile(new TFile(r2d.fDigitsFile->GetName(), "new" )),
156 fBeamEnergy(r2d.fBeamEnergy),
157 fMaxPerFile(r2d.fMaxPerFile),
159 fStatus(r2d.fStatus),
160 fInName(r2d.fInName),
162 fIsInitialized(kFALSE),
169 // cpy ctor. wrong. because dtor can delete fDigits twice (or n times you copy AliPHOSRaw2Digits)
170 //because fHeaderFile and fDigitsFile will recreate existing files etc.
171 fTarget[0] = r2d.fTarget[0] ;
172 fTarget[1] = r2d.fTarget[1] ;
173 fTarget[2] = r2d.fTarget[2] ;
176 //____________________________________________________________________________
177 AliPHOSRaw2Digits::~AliPHOSRaw2Digits()
181 fPHOSHeader->Delete() ;
188 //____________________________________________________________________________
189 void AliPHOSRaw2Digits::Exec(const Option_t *){
190 //This is steering method performing all the conversion
192 if(!fIsInitialized) //need initialization
193 if(!Init()) //failed to initialize
199 //____________________________________________________________________________
200 Bool_t AliPHOSRaw2Digits::Init(void){
201 //Makes initialization of contaniers
206 //Make container for digits
207 fDigits = new TClonesArray("AliPHOSDigit",1000) ;
208 fPHOSHeader = new AliPHOSBeamTestEvent() ;
209 fIsInitialized = kTRUE ;
210 return StartRootFiles() ;
213 //____________________________________________________________________________
214 Bool_t AliPHOSRaw2Digits::StartRootFiles(void ) const {
215 // //Create PHOS geometry, sets magnetic field to zero,
216 // //create Generator - to store target position,
217 // //opens out file, creates TreeE
219 // //create gAlice if nececcary
221 // new AliRun("gAlice","The ALICE Off-line Simulation Framework") ;
224 // if(!gAlice->GetModule("PHOS"))
225 // new AliPHOSv1("PHOS","GPS2") ;
227 // //Set Magnetic field
228 // gAlice->SetField(0,2);
230 // //Set positin of the virtex
231 // AliGenerator * gener = gAlice->Generator() ;
233 // gener = new AliGenBox(1);
234 // Float_t ox = fTarget[1];
235 // Float_t oy = fTarget[2]+460.;
236 // Float_t oz = fTarget[0];
237 // gener->SetOrigin(ox, oy, oz);
240 // Int_t nRootFile = (fEvent+1)/fMaxPerFile ;
243 // sprintf(dname,"%d",nRootFile) ;
244 // if(gSystem->AccessPathName(dname)) //strange return: 0 if exists
245 // if(gSystem->MakeDirectory(dname)!=0)
246 // Fatal("StartRootFiles","Can not make directory %s \n",dname) ;
248 // if(!gSystem->ChangeDirectory(dname))
249 // Fatal("StartRootFiles","Can not cd to %s\n",dname) ;
252 // // Create the output file
253 // TString outname("") ;
254 // if(strstr(GetTitle(),"root")){
255 // outname=GetTitle();
258 // outname = fInName ;
259 // outname.ToLower() ;
260 // outname.ReplaceAll(".fz",".root") ;
263 // fHeaderFile = new TFile(outname,"recreate");
264 // fHeaderFile->SetCompressionLevel(2);
266 // // Create the Root Trees
268 // gime->MakeTree("E") ;
271 // Int_t splitlevel = 0 ;
272 // Int_t bufferSize = 32000 ;
273 // TBranch * headerBranch = gAlice->TreeE()->Branch("AliPHOSBeamTestEvent",
274 // "AliPHOSBeamTestEvent",
275 // &fPHOSHeader,bufferSize,splitlevel);
276 // headerBranch->SetName("AliPHOSBeamTestEvent") ;
279 // // fDigitsFile = new TFile("PHOS.Digits.root","recreate") ;
280 // // fDigitsFile->SetCompressionLevel(2) ;
284 //____________________________________________________________________________
285 Bool_t AliPHOSRaw2Digits::CloseRootFiles(void ){
286 //cleans everething to start next root file
288 printf("writing gAlice \n") ;
290 gAlice->Write(0,TObject::kOverwrite);
291 gAlice->TreeE()->Write(0,TObject::kOverwrite);
297 fHeaderFile->Close() ;
303 fDigitsFile->Close() ;
308 Int_t nRootFile = (fEvent-1)/fMaxPerFile ;
310 if(!gSystem->ChangeDirectory("../")){
311 Fatal("CloseRootFile","Can not return to initial dir \n") ;
317 //____________________________________________________________________________
318 Bool_t AliPHOSRaw2Digits::ProcessRawFile(){
320 //Method opens zebra file and reads successively bytes from it,
321 //filling corresponding fields in header and digits.
325 //First of all, open file and check if it is a zebra file
328 sprintf(command,"zcat %s",fInName.Data());
329 FILE *dataFile = popen(command, "r");
330 if (dataFile == NULL) {
331 Warning("ProcessRawFile", " Cannot open file %s\n", fInName.Data() ) ;
332 perror(fInName.Data()) ;
337 // Check if byte ordering is little-endian
338 UInt_t w = 0x12345678;
339 Int_t swapo = memcmp(&w, "\x78\x56\x34\x12", sizeof(UInt_t)) == 0;
341 Info("ProcessRawFile", "swapo=%f\n", swapo ) ;
346 // Read physical record control words
347 UInt_t nb = 8*sizeof(UInt_t);
348 Int_t n = fread(recBuf, nb, 1, dataFile);
349 if(static_cast<UInt_t>(n) != 1) {
351 perror(fInName.Data());
353 Error("ProcessRawFile", "Could not read physical record control words" ) ;
359 Info("ProcessRawFile", "recbuf[0] = %d\n", recBuf[0] );
361 // Check if it is a ZEBRA file and if the words are swapped
363 if (recBuf[0] != fMK1) {
364 Swab4(recBuf, &w, 1);
366 Error("ProcessRawFile", "Does not look like a ZEBRA file\n" ) ;
376 message = " w = %f\n" ;
377 message += " swapi = %f\n" ;
378 Info("ProcessRawFile", message.Data(), w, swapi ) ;
381 // Get number of words in physical record
384 Swab4(&recBuf[4],&nwphr,1);
387 nwphr*=2; // 1998 -- Now we have 2 records 150 words each
390 //start loop over data
391 // Read rest of record
392 nb = (nwphr-8)*sizeof(UInt_t);
393 n = fread(&recBuf[8], nb, 1, dataFile) ;
394 if (static_cast<UInt_t>(n) != 1) {
396 perror(fInName.Data());
401 nb = nwphr *sizeof(UInt_t);
403 UInt_t userVector[16] ;
406 UShort_t scanning[32] ;
409 UShort_t tdc2228[32];
411 //read untill the end of file
417 if((fEvent%fMaxPerFile == 0) && fEvent ){
421 gAlice->SetEvent(fEvent%fMaxPerFile) ;
424 fPHOSHeader->SetBeamEnergy(fBeamEnergy) ;
428 userVector[i]=*(recBuf+21+i);
430 Swab4(userVector, userVector, 16);
431 fPHOSHeader->SetUserVector(userVector) ;
434 // ZEBRA event header
436 zheader[i]=*(recBuf+47+i);
438 Swab4(zheader, zheader, 12);
439 fPHOSHeader->SetHeader(zheader) ;
443 Swab4(recBuf, recBuf, nwphr);
445 /* Physical record control words */
446 UInt_t * recptr = recBuf; //Pointer to current position
449 Error("ProcessRawFile", "Cannot handle fast blocks" ) ;
455 // Logical record control words
456 UInt_t lrtyp = recptr[1];
458 Error("ProcessRawFile", "Can not handle logical record type %d", lrtyp ) ;
464 if (recptr[0] != fCKW) {
465 Error("ProcessRawFile", "Bad check word" ) ;
470 UInt_t nwuh = recptr[9];
474 UInt_t nd = recptr[8]; /* Number of data words */
478 UInt_t evtno = recptr[2]; /* Event number */
481 Info("ProcessRawFile", "evtno= %d", evtno);
483 UInt_t nh = recptr[4]; /* Number of header words in data bank */
486 // Unswap data from VME
488 Swab4(recptr, recptr, nd-nh-3);
490 // Give buffer to monitor program
491 // UInt_t esize = nd-nh-3;
493 // Swab2(recptr, recptr, esize);
494 // Two byte data are correct after this operation.
495 //But we're in trouble if the data array contains 4 byte data!
497 // From now on deal with VME data (MSB first, or network byte order).
500 // Fill the event with data from ADCs
501 UChar_t *byteptr=(UChar_t*)recptr;
503 // Trigger bit register
504 pattern=net2host(*(UShort_t*)byteptr);
505 fPHOSHeader->SetPattern(pattern) ;
506 byteptr+=sizeof(UShort_t);
508 // Either peak ADCs, 10 modulesX8=80 channels,
509 //or Kurchatov 64+2 channel ADC
510 //(the rest of the channels padded with 0xffff)
512 Int_t peak = static_cast<Int_t>(net2host(*(UShort_t*)byteptr));
514 Int_t absID = fctdb->Raw2AbsId(i) ;
516 new((*fDigits)[i])AliPHOSDigit(-1,absID,peak,0.,i) ;
518 if(peak>(UShort_t)1000)
519 Info("ProcessRawFile", "event= %d peak[%d] = %f", fEvent, i, peak);
521 byteptr+=sizeof(UShort_t);
524 // Scanning ADCs, 4 modulesX8=32 channels
526 scanning[i]=net2host(*(UShort_t*)byteptr);
527 byteptr+=sizeof(UShort_t);
529 fPHOSHeader->SetScanning(scanning) ;
531 // Charge ADCs, 1 moduleX12=12 channels
533 charge[i]=net2host(*(UShort_t*)byteptr);
534 byteptr+=sizeof(UShort_t);
536 fPHOSHeader->SetCharge(charge) ;
538 // Scalers, 1 moduleX12=12 (4 byte) channels
540 scaler[i]=net2host(*(UInt_t*)byteptr);
541 byteptr+=sizeof(UInt_t);
543 fPHOSHeader->SetScaler(scaler) ;
545 // LeCroy TDC 2228A, 4 moduleX8=32 channels
547 tdc2228[i]=net2host(*(UShort_t*)byteptr);
548 byteptr+=sizeof(UShort_t);
550 fPHOSHeader->SetTDC(tdc2228) ;
554 Info("ProcessRawFile", "event= %d written", fEvent) ;
557 nb = nwphr *sizeof(UInt_t);
558 n = fread( recBuf, nb,1,dataFile);
564 if (static_cast<UInt_t>(n) != 1) {
567 return kTRUE ; //all read
577 //____________________________________________________________________________
578 void AliPHOSRaw2Digits::Swab4(void *from, void *to, size_t nwords)const
580 // The function swaps 4 bytes: byte#3<-->byte#0, byte#2<-->byte#1
581 register char *pf=static_cast<char*>(from) ;
582 register char *pt=static_cast<char*>(to) ;
584 while (nwords-- > 0 ) {
596 //____________________________________________________________________________
597 void AliPHOSRaw2Digits::Swab2(void *from, void *to, size_t nwords)const
599 //The function swaps 2x2 bytes: byte#0<-->byte#1, byte#2<-->byte#3
600 register char *pf=static_cast<char*>(from) ;
601 register char *pt=static_cast<char*>(to);
603 while (nwords-- > 0 ) {
615 //____________________________________________________________________________
616 void AliPHOSRaw2Digits::WriteDigits(void){
617 //In this method we create TreeD, write digits and Raw2Digits to it
618 // and write Header to TreeE. Finally we write TreeD to root file
622 fDigits->Expand(fDigits->GetEntriesFast()) ;
623 for(Int_t i=0;i<fDigits->GetEntriesFast(); i++)
624 static_cast<AliPHOSDigit*>(fDigits->At(i))->SetIndexInList(i) ;
627 sprintf(hname,"TreeD%d",fEvent%fMaxPerFile);
628 TTree * treeD = new TTree(hname,"Digits");
629 //treeD->Write(0,TObject::kOverwrite);
631 // -- create Digits branch
632 Int_t bufferSize = 32000 ;
633 TBranch * digitsBranch = treeD->Branch("PHOS",&fDigits,bufferSize);
634 digitsBranch->SetTitle("Default");
636 // -- Create Digitizer branch
637 Int_t splitlevel = 0 ;
638 const AliPHOSRaw2Digits * d = this ;
639 TBranch * digitizerBranch = treeD->Branch("AliPHOSRaw2Digits",
640 "AliPHOSRaw2Digits", &d,bufferSize,splitlevel);
641 digitizerBranch->SetTitle("Default");
645 digitsBranch->Fill() ;
646 digitizerBranch->Fill() ;
647 treeD->Write(0,TObject::kOverwrite);
653 gAlice->TreeE()->Fill();
655 //____________________________________________________________________________
656 void AliPHOSRaw2Digits::Print(const Option_t *)const{
657 //prints current configuration and status.
659 printf("----------AliPHOSRaw2Digits---------- \n") ;
660 printf("Current input File: %s\n",fInName.Data()) ;
661 printf("Current output File: %s\n", GetTitle());
662 printf("Events processes in the last file %d\n",fEvent) ;
663 printf("Input file status\n") ;
665 case 0: printf("`Have not processed yet'\n") ;
667 case 1: printf("`Processed normally'\n") ;
669 case -1: printf("`File not found'\n") ;
671 case -2: printf("`Error in reading'\n") ;
673 case -3: printf("'Interupted'\n") ;
676 printf("Connection table: " );
678 printf("%s %s \n",fctdb->GetName(), fctdb->GetTitle() ) ;
680 printf(" no DB \n" );