]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALRawUtils.cxx
change order of bookkeeping events
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALRawUtils.cxx
1 // -*- mode: c++ -*-
2 /**************************************************************************
3  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4  *                                                                        *
5  * Author: The ALICE Off-line Project.                                    *
6  * Contributors are mentioned in the code where appropriate.              *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19
20 //_________________________________________________________________________
21 //  Utility Class for handling Raw data
22 //  Does all transitions from Digits to Raw and vice versa, 
23 //  for simu and reconstruction
24 //
25 //  Note: the current version is still simplified. Only 
26 //    one raw signal per digit is generated; either high-gain or low-gain
27 //    Need to add concurrent high and low-gain info in the future
28 //    No pedestal is added to the raw signal.
29 //*-- Author: Marco van Leeuwen (LBL)
30 //*-- Major refactoring by Per Thomas Hille
31
32 //#include "AliCDBManager.h"
33 #include "AliEMCALRawUtils.h"
34 #include "AliRun.h"
35 #include "AliRunLoader.h"
36 #include "AliAltroBuffer.h"
37 #include "AliRawReader.h"
38 #include "AliCaloRawStreamV3.h"
39 #include "AliDAQ.h"
40 #include "AliEMCALRecParam.h"
41 #include "AliEMCALLoader.h"
42 #include "AliEMCALGeometry.h"
43 #include "AliEMCALDigit.h"
44 #include "AliEMCALRawDigit.h"
45 #include "AliEMCAL.h"
46 #include "AliCaloCalibPedestal.h"  
47 #include "AliCaloBunchInfo.h"
48 #include "AliCaloFitResults.h"
49 #include "AliEMCALTriggerRawDigitMaker.h"
50 #include "AliEMCALTriggerSTURawStream.h"
51 #include "AliEMCALTriggerData.h"
52 #include "AliCaloConstants.h"
53 #include "AliCaloRawAnalyzer.h"
54 #include "AliCaloRawAnalyzerFactory.h"
55 #include "AliEMCALRawResponse.h"
56
57 using namespace CALO;
58 using namespace EMCAL;
59
60 using std::vector;
61 ClassImp(AliEMCALRawUtils)
62
63
64 AliEMCALRawUtils::AliEMCALRawUtils( Algo::fitAlgorithm fitAlgo) : fNoiseThreshold(3),
65                                                                   fNPedSamples(4), 
66                                                                   fGeom(0), 
67                                                                   fOption(""),
68                                                                   fRemoveBadChannels(kFALSE),
69                                                                   fFittingAlgorithm(fitAlgo),  
70                                                                   fTimeMin(-1.),
71                                                                   fTimeMax(1.),
72                                                                   fUseFALTRO(kTRUE),
73                                                                   fRawAnalyzer(0),
74                                                                   fTriggerRawDigitMaker(0x0)
75 { // ctor; set up fit algo etc
76   SetFittingAlgorithm(fitAlgo);
77   const TObjArray* maps = AliEMCALRecParam::GetMappings();
78   if(!maps) AliFatal("Cannot retrieve ALTRO mappings!!");
79   for(Int_t i = 0; i < 4; i++) 
80     {
81       fMapping[i] = (AliAltroMapping*)maps->At(i);
82     }
83   
84   AliRunLoader *rl = AliRunLoader::Instance();
85   if (rl && rl->GetAliRun()) 
86     {
87     AliEMCAL * emcal = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"));
88     if(emcal)
89       {
90         fGeom = emcal->GetGeometry();
91       }
92     else 
93       {
94         AliDebug(1, Form("Using default geometry in raw reco"));
95         fGeom =  AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName());
96       }
97     } 
98   else 
99     {
100       AliDebug(1, Form("Using default geometry in raw reco"));
101       fGeom =  AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName());
102     }
103   
104   if(!fGeom) AliFatal(Form("Could not get geometry!"));
105   fTriggerRawDigitMaker = new AliEMCALTriggerRawDigitMaker();
106 }
107
108
109 AliEMCALRawUtils::~AliEMCALRawUtils() 
110 {
111   //dtor
112   delete fRawAnalyzer;
113   delete fTriggerRawDigitMaker;
114 }
115
116
117 void AliEMCALRawUtils::Digits2Raw()
118 {
119   // convert digits of the current event to raw data
120   AliRunLoader *rl = AliRunLoader::Instance();
121   AliEMCALLoader *loader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
122   loader->LoadDigits("EMCAL");
123   loader->GetEvent();
124   TClonesArray* digits = loader->Digits() ;
125   
126   if (!digits) {
127     Warning("Digits2Raw", "no digits found !");
128     return;
129   }
130   
131   static const Int_t nDDL = 20*2; // 20 SM for EMCal + DCal hardcoded for now. Buffers allocated dynamically, when needed, so just need an upper limit here  
132   AliAltroBuffer* buffers[nDDL];
133   for (Int_t i=0; i < nDDL; i++)
134     buffers[i] = 0;
135   
136   TArrayI adcValuesLow( TIMEBINS );
137   TArrayI adcValuesHigh( TIMEBINS );
138   
139   // loop over digits (assume ordered digits)
140   for (Int_t iDigit = 0; iDigit < digits->GetEntries(); iDigit++) {
141     AliEMCALDigit* digit = dynamic_cast<AliEMCALDigit *>(digits->At(iDigit)) ;
142     if(!digit) {
143       AliFatal("NULL Digit");
144     } else {
145       if (digit->GetAmplitude() <  AliEMCALRawResponse::GetRawFormatThreshold() ) {
146         continue;
147       }
148       //get cell indices
149       Int_t nSM = 0;
150       Int_t nIphi = 0;
151       Int_t nIeta = 0;
152       Int_t iphi = 0;
153       Int_t ieta = 0;
154       Int_t nModule = 0;
155       fGeom->GetCellIndex(digit->GetId(), nSM, nModule, nIphi, nIeta);
156       fGeom->GetCellPhiEtaIndexInSModule(nSM, nModule, nIphi, nIeta,iphi, ieta) ;
157     
158       //Check which is the RCU, 0 or 1, of the cell.
159       Int_t iRCU = -111;
160       if (0<=iphi&&iphi<8) iRCU=0; // first cable row
161       else if (8<=iphi&&iphi<16 && 0<=ieta&&ieta<24) iRCU=0; // first half; 
162       else if(8<=iphi&&iphi<16 && 24<=ieta&&ieta<48) iRCU=1; // second half; 
163       //second cable row
164       else if(16<=iphi&&iphi<24) iRCU=1; // third cable row
165       
166       if (nSM%2==1) iRCU = 1 - iRCU; // swap for odd=C side, to allow us to cable both sides the same
167       
168       if (iRCU<0) 
169         Fatal("Digits2Raw()","Non-existent RCU number: %d", iRCU);
170     
171       //Which DDL?
172       Int_t iDDL = NRCUSPERMODULE*nSM + iRCU;
173       if (iDDL < 0 || iDDL >= nDDL){
174         Fatal("Digits2Raw()","Non-existent DDL board number: %d", iDDL);
175       } else {
176         if (buffers[iDDL] == 0) {      
177           // open new file and write dummy header
178           TString fileName = AliDAQ::DdlFileName("EMCAL",iDDL);
179           //Select mapping file RCU0A, RCU0C, RCU1A, RCU1C
180           Int_t iRCUside=iRCU+(nSM%2)*2;
181           //iRCU=0 and even (0) SM -> RCU0A.data   0
182           //iRCU=1 and even (0) SM -> RCU1A.data   1
183           //iRCU=0 and odd  (1) SM -> RCU0C.data   2
184           //iRCU=1 and odd  (1) SM -> RCU1C.data   3
185           buffers[iDDL] = new AliAltroBuffer(fileName.Data(),fMapping[iRCUside]);
186           buffers[iDDL]->WriteDataHeader(kTRUE, kFALSE);  //Dummy;
187         }
188         
189         // out of time range signal (?)
190         if (digit->GetTimeR() >  TIMEBINMAX  ) {
191           AliInfo("Signal is out of time range.\n");
192           buffers[iDDL]->FillBuffer((Int_t)digit->GetAmplitude());
193           buffers[iDDL]->FillBuffer( TIMEBINS );  // time bin
194           buffers[iDDL]->FillBuffer(3);          // bunch length      
195           buffers[iDDL]->WriteTrailer(3, ieta, iphi, nSM);  // trailer
196           // calculate the time response function
197         } else {
198           Bool_t lowgain = AliEMCALRawResponse::RawSampledResponse(digit->GetTimeR(), digit->GetAmplitude(),
199                                                                    adcValuesHigh.GetArray(), adcValuesLow.GetArray()) ; 
200       
201           if (lowgain) 
202             buffers[iDDL]->WriteChannel(ieta, iphi, 0, TIMEBINS, adcValuesLow.GetArray(),  AliEMCALRawResponse::GetRawFormatThreshold()  );
203           else 
204             buffers[iDDL]->WriteChannel(ieta,iphi, 1, TIMEBINS, adcValuesHigh.GetArray(),  AliEMCALRawResponse::GetRawFormatThreshold()  );
205         }
206       }// iDDL under the limits
207     }//digit exists
208   }//Digit loop
209   
210   // write headers and close files
211   for (Int_t i=0; i < nDDL; i++) {
212     if (buffers[i]) {
213       buffers[i]->Flush();
214       buffers[i]->WriteDataHeader(kFALSE, kFALSE);
215       delete buffers[i];
216     }
217   }
218   
219   loader->UnloadDigits();
220 }
221
222
223
224 void AliEMCALRawUtils::AddDigit(TClonesArray *digitsArr, Int_t id, Int_t lowGain, Float_t amp, Float_t time, Float_t chi2, Int_t ndf) 
225 {
226   // comment
227   AliEMCALDigit *digit = 0, *tmpdigit = 0;
228   TIter nextdigit(digitsArr);
229  
230   while (digit == 0 && (tmpdigit = (AliEMCALDigit*) nextdigit())) 
231     {
232       if (tmpdigit->GetId() == id) digit = tmpdigit;
233     }
234   
235   if (!digit) { // no digit existed for this tower; create one
236     Int_t type = AliEMCALDigit::kHG; // use enum in AliEMCALDigit
237     if (lowGain) 
238       { 
239         amp *= HGLGFACTOR;
240         type = AliEMCALDigit::kLGnoHG;
241       } 
242     
243     Int_t idigit = digitsArr->GetEntries();
244     new((*digitsArr)[idigit]) AliEMCALDigit( -1, -1, id, amp, time, type, idigit, chi2, ndf); 
245     AliDebug(2,Form("Add digit Id %d for the first time, type %d", id, type));
246   }//digit added first time
247   else 
248     { // a digit already exists, check range 
249                 // (use high gain if signal < cut value, otherwise low gain)
250       if (lowGain) 
251         { // new digit is low gain
252           if (digit->GetAmplitude() >  OVERFLOWCUT ) 
253             {  // use if previously stored (HG) digit is out of range
254               digit->SetAmplitude( HGLGFACTOR * amp);
255               digit->SetTime(time);
256               digit->SetType(AliEMCALDigit::kLG);
257               AliDebug(2,Form("Add LG digit ID %d for the second time, type %d", digit->GetId(), digit->GetType()));
258             }
259         }//new low gain digit
260       else { // new digit is high gain 
261         
262         if (amp <  OVERFLOWCUT  ) 
263           { // new digit is high gain; use if not out of range
264             digit->SetAmplitude(amp);
265             digit->SetTime(time);
266             digit->SetType(AliEMCALDigit::kHG);
267             AliDebug(2,Form("Add HG digit ID %d for the second time, type %d", digit->GetId(), digit->GetType()));
268           }
269         else 
270           { // HG out of range, just change flag value to show that HG did exist
271             digit->SetType(AliEMCALDigit::kLG);
272             AliDebug(2,Form("Change LG digit to HG, ID %d, type %d", digit->GetId(), digit->GetType()));
273           }
274       }//new high gain digit
275     }//digit existed replace it
276 }
277
278
279 void AliEMCALRawUtils::Raw2Digits(AliRawReader* reader,TClonesArray *digitsArr, const AliCaloCalibPedestal* pedbadmap, TClonesArray *digitsTRG, AliEMCALTriggerData* trgData)
280 {
281   //conversion of raw data to digits
282   if(digitsArr) digitsArr->Clear("C"); 
283   if (!digitsArr) { Error("Raw2Digits", "no digits found !");return;}
284   if (!reader) {Error("Raw2Digits", "no raw reader found !");return;}
285   AliEMCALTriggerSTURawStream inSTU(reader);
286   AliCaloRawStreamV3 in(reader,"EMCAL",fMapping);       
287   reader->Select("EMCAL",0,39); // 39 = AliEMCALGeoParams::fgkLastAltroDDL
288   fTriggerRawDigitMaker->Reset();       
289   fTriggerRawDigitMaker->SetIO(reader, in, inSTU, digitsTRG, trgData);
290   fRawAnalyzer->SetIsZeroSuppressed(true); // TMP - should use stream->IsZeroSuppressed(), or altro cfg registers later
291     
292   Int_t lowGain  = 0;
293   Int_t caloFlag = 0; // low, high gain, or TRU, or LED ref.
294   
295   Float_t bcTimePhaseCorr = 0; // for BC-based L1 phase correction
296   Int_t bcMod4 = (reader->GetBCID() % 4); // LHC uses 40 MHz, EMCal uses 10 MHz clock
297         
298   //AliCDBManager* man = AliCDBManager::Instance();
299   //Int_t runNumber = man->GetRun();
300         
301  Int_t runNumber = reader->GetRunNumber();
302
303   if ((runNumber >130850 ) && (bcMod4==0 || bcMod4==1)) 
304     bcTimePhaseCorr = -1e-7; // subtract 100 ns for certain BC values
305
306   while (in.NextDDL()) 
307     {
308       while (in.NextChannel()) 
309         {
310           caloFlag = in.GetCaloFlag();
311           if (caloFlag > 2) continue; // Work with ALTRO and FALTRO 
312           if(caloFlag < 2 && fRemoveBadChannels && pedbadmap->IsBadChannel(in.GetModule(),in.GetColumn(),in.GetRow()))
313             {
314               continue;
315             }  
316           vector<AliCaloBunchInfo> bunchlist; 
317           while (in.NextBunch()) 
318             {
319               bunchlist.push_back( AliCaloBunchInfo(in.GetStartTimeBin(), in.GetBunchLength(), in.GetSignals() ) );
320             } 
321           if (bunchlist.size() == 0) continue;
322           if ( caloFlag < 2 )
323             { // ALTRO
324               Int_t id = fGeom->GetAbsCellIdFromCellIndexes(in.GetModule(), in.GetRow(), in.GetColumn()) ;
325               lowGain  = in.IsLowGain();
326               fRawAnalyzer->SetL1Phase( in.GetL1Phase() );
327               AliCaloFitResults res =  fRawAnalyzer->Evaluate( bunchlist, in.GetAltroCFG1(), in.GetAltroCFG2());  
328               if(res.GetAmp() >= fNoiseThreshold )
329                 {
330                   AddDigit(digitsArr, id, lowGain, res.GetAmp(),  res.GetTime()+bcTimePhaseCorr, res.GetChi2(),  res.GetNdf() ); 
331                 }
332             }//ALTRO
333           else if(fUseFALTRO)
334             {// Fake ALTRO
335               fTriggerRawDigitMaker->Add( bunchlist );
336             }//Fake ALTRO
337         } // end while over channel   
338     } //end while over DDL's, of input stream 
339   fTriggerRawDigitMaker->PostProcess(); 
340   TrimDigits(digitsArr);
341 }
342
343
344 void AliEMCALRawUtils::TrimDigits(TClonesArray *digitsArr) 
345 { // rm entries with LGnoHG (unphysical), out of time window, and too bad chi2
346   AliEMCALDigit *digit = 0;
347   Int_t n = 0;
348   Int_t nDigits = digitsArr->GetEntriesFast();
349   TIter nextdigit(digitsArr);
350   while ((digit = (AliEMCALDigit*) nextdigit())) {
351     if (digit->GetType() == AliEMCALDigit::kLGnoHG) {
352       AliDebug(1,Form("Remove digit with id %d, LGnoHG",digit->GetId()));
353       digitsArr->Remove(digit);
354     }
355     else if(fTimeMin > digit->GetTime() || fTimeMax < digit->GetTime()) {
356       digitsArr->Remove(digit);
357       AliDebug(1,Form("Remove digit with id %d, Bad Time %e",digit->GetId(), digit->GetTime()));
358     }
359     else if (0 > digit->GetChi2()) {
360       digitsArr->Remove(digit);
361       AliDebug(1,Form("Remove digit with id %d, Bad Chi2 %e",digit->GetId(), digit->GetChi2()));
362     }
363     else {
364       digit->SetIndexInList(n); 
365       n++;
366     }    
367   }//while
368   
369   digitsArr->Compress();
370   AliDebug(1,Form("N Digits before trimming : %d; after array compression %d",nDigits,digitsArr->GetEntriesFast()));
371 }
372
373
374 void AliEMCALRawUtils::SetFittingAlgorithm(Int_t fitAlgo)              
375 { // select which fitting algo should be used
376   delete fRawAnalyzer; // delete doesn't do anything if the pointer is 0x0
377   fRawAnalyzer = AliCaloRawAnalyzerFactory::CreateAnalyzer( fitAlgo );
378   fRawAnalyzer->SetNsampleCut(5); // requirement for fits to be done, for the new methods
379   fRawAnalyzer->SetOverflowCut ( OVERFLOWCUT );
380   fRawAnalyzer->SetAmpCut(fNoiseThreshold);
381   fRawAnalyzer->SetFitArrayCut(fNoiseThreshold);
382 }
383
384
385