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