]>
Commit | Line | Data |
---|---|---|
ee299369 | 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$ */ | |
ee299369 | 17 | |
e5bbbc4e | 18 | //_________________________________________________________________________ |
19 | // Utility Class for handling Raw data | |
20 | // Does all transitions from Digits to Raw and vice versa, | |
21 | // for simu and reconstruction | |
22 | // | |
23 | // Note: the current version is still simplified. Only | |
24 | // one raw signal per digit is generated; either high-gain or low-gain | |
25 | // Need to add concurrent high and low-gain info in the future | |
26 | // No pedestal is added to the raw signal. | |
ee299369 | 27 | //*-- Author: Marco van Leeuwen (LBL) |
e5bbbc4e | 28 | |
ee299369 | 29 | #include "AliEMCALRawUtils.h" |
21cad85c | 30 | |
ee299369 | 31 | #include "TF1.h" |
32 | #include "TGraph.h" | |
e5bbbc4e | 33 | class TSystem; |
21cad85c | 34 | |
e5bbbc4e | 35 | class AliLog; |
72c58de0 | 36 | #include "AliRun.h" |
ee299369 | 37 | #include "AliRunLoader.h" |
e5bbbc4e | 38 | class AliCaloAltroMapping; |
ee299369 | 39 | #include "AliAltroBuffer.h" |
40 | #include "AliRawReader.h" | |
32cd4c24 | 41 | #include "AliCaloRawStreamV3.h" |
ee299369 | 42 | #include "AliDAQ.h" |
21cad85c | 43 | |
feedcab9 | 44 | #include "AliEMCALRecParam.h" |
ee299369 | 45 | #include "AliEMCALLoader.h" |
46 | #include "AliEMCALGeometry.h" | |
e5bbbc4e | 47 | class AliEMCALDigitizer; |
ee299369 | 48 | #include "AliEMCALDigit.h" |
20b636fc | 49 | #include "AliEMCAL.h" |
5e3106bc | 50 | #include "AliCaloCalibPedestal.h" |
9f467289 | 51 | #include "AliCaloFastAltroFitv0.h" |
52 | ||
ee299369 | 53 | ClassImp(AliEMCALRawUtils) |
21cad85c | 54 | |
ee299369 | 55 | // Signal shape parameters |
89d338a6 | 56 | Int_t AliEMCALRawUtils::fgTimeBins = 256; // number of sampling bins of the raw RO signal (we typically use 15-50; theoretical max is 1k+) |
e5bbbc4e | 57 | Double_t AliEMCALRawUtils::fgTimeBinWidth = 100E-9 ; // each sample is 100 ns |
09974781 | 58 | Double_t AliEMCALRawUtils::fgTimeTrigger = 1.5E-6 ; // 15 time bins ~ 1.5 musec |
ee299369 | 59 | |
60 | // some digitization constants | |
61 | Int_t AliEMCALRawUtils::fgThreshold = 1; | |
62 | Int_t AliEMCALRawUtils::fgDDLPerSuperModule = 2; // 2 ddls per SuperModule | |
e5bbbc4e | 63 | Int_t AliEMCALRawUtils::fgPedestalValue = 32; // pedestal value for digits2raw |
64 | Double_t AliEMCALRawUtils::fgFEENoise = 3.; // 3 ADC channels of noise (sampled) | |
ee299369 | 65 | |
8cb998bd | 66 | AliEMCALRawUtils::AliEMCALRawUtils() |
b4133f05 | 67 | : fHighLowGainFactor(0.), fOrder(0), fTau(0.), fNoiseThreshold(0), |
9f467289 | 68 | fNPedSamples(0), fGeom(0), fOption(""), |
69 | fRemoveBadChannels(kTRUE),fFittingAlgorithm(0) | |
8cb998bd | 70 | { |
b4133f05 | 71 | |
72 | //These are default parameters. | |
73 | //Can be re-set from without with setter functions | |
9f467289 | 74 | //Already set in the OCDB and passed via setter in the AliEMCALReconstructor |
ee299369 | 75 | fHighLowGainFactor = 16. ; // adjusted for a low gain range of 82 GeV (10 bits) |
b4133f05 | 76 | fOrder = 2; // order of gamma fn |
77 | fTau = 2.35; // in units of timebin, from CERN 2007 testbeam | |
7643e728 | 78 | fNoiseThreshold = 3; // 3 ADC counts is approx. noise level |
79 | fNPedSamples = 4; // less than this value => likely pedestal samples | |
9f467289 | 80 | fRemoveBadChannels = kTRUE; //Remove bad channels before fitting |
81 | fFittingAlgorithm = kFastFit;//kStandard; // Use default minuit fitter | |
82 | ||
65bdc82f | 83 | //Get Mapping RCU files from the AliEMCALRecParam |
84 | const TObjArray* maps = AliEMCALRecParam::GetMappings(); | |
85 | if(!maps) AliFatal("Cannot retrieve ALTRO mappings!!"); | |
86 | ||
21cad85c | 87 | for(Int_t i = 0; i < 4; i++) { |
65bdc82f | 88 | fMapping[i] = (AliAltroMapping*)maps->At(i); |
89 | } | |
90 | ||
72c58de0 | 91 | //To make sure we match with the geometry in a simulation file, |
92 | //let's try to get it first. If not, take the default geometry | |
33c3c91a | 93 | AliRunLoader *rl = AliRunLoader::Instance(); |
c61fe3b4 | 94 | if(!rl) AliError("Cannot find RunLoader!"); |
72c58de0 | 95 | if (rl->GetAliRun() && rl->GetAliRun()->GetDetector("EMCAL")) { |
96 | fGeom = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"))->GetGeometry(); | |
97 | } else { | |
98 | AliInfo(Form("Using default geometry in raw reco")); | |
937d0661 | 99 | fGeom = AliEMCALGeometry::GetInstance(AliEMCALGeometry::GetDefaultGeometryName()); |
65bdc82f | 100 | } |
101 | ||
72c58de0 | 102 | if(!fGeom) AliFatal(Form("Could not get geometry!")); |
103 | ||
65bdc82f | 104 | } |
105 | ||
106 | //____________________________________________________________________________ | |
5544799a | 107 | AliEMCALRawUtils::AliEMCALRawUtils(AliEMCALGeometry *pGeometry) |
108 | : fHighLowGainFactor(0.), fOrder(0), fTau(0.), fNoiseThreshold(0), | |
9f467289 | 109 | fNPedSamples(0), fGeom(pGeometry), fOption(""), |
110 | fRemoveBadChannels(kTRUE),fFittingAlgorithm(0) | |
5544799a | 111 | { |
112 | // | |
113 | // Initialize with the given geometry - constructor required by HLT | |
114 | // HLT does not use/support AliRunLoader(s) instances | |
115 | // This is a minimum intervention solution | |
116 | // Comment by MPloskon@lbl.gov | |
117 | // | |
118 | ||
119 | //These are default parameters. | |
120 | //Can be re-set from without with setter functions | |
9f467289 | 121 | //Already set in the OCDB and passed via setter in the AliEMCALReconstructor |
5544799a | 122 | fHighLowGainFactor = 16. ; // adjusted for a low gain range of 82 GeV (10 bits) |
123 | fOrder = 2; // order of gamma fn | |
124 | fTau = 2.35; // in units of timebin, from CERN 2007 testbeam | |
7643e728 | 125 | fNoiseThreshold = 3; // 3 ADC counts is approx. noise level |
126 | fNPedSamples = 4; // less than this value => likely pedestal samples | |
9f467289 | 127 | fRemoveBadChannels = kTRUE; //Remove bad channels before fitting |
128 | fFittingAlgorithm = kStandard; // Use default minuit fitter | |
129 | ||
5544799a | 130 | //Get Mapping RCU files from the AliEMCALRecParam |
131 | const TObjArray* maps = AliEMCALRecParam::GetMappings(); | |
132 | if(!maps) AliFatal("Cannot retrieve ALTRO mappings!!"); | |
133 | ||
21cad85c | 134 | for(Int_t i = 0; i < 4; i++) { |
5544799a | 135 | fMapping[i] = (AliAltroMapping*)maps->At(i); |
136 | } | |
137 | ||
138 | if(!fGeom) AliFatal(Form("Could not get geometry!")); | |
139 | ||
140 | } | |
141 | ||
142 | //____________________________________________________________________________ | |
65bdc82f | 143 | AliEMCALRawUtils::AliEMCALRawUtils(const AliEMCALRawUtils& rawU) |
144 | : TObject(), | |
145 | fHighLowGainFactor(rawU.fHighLowGainFactor), | |
b4133f05 | 146 | fOrder(rawU.fOrder), |
147 | fTau(rawU.fTau), | |
148 | fNoiseThreshold(rawU.fNoiseThreshold), | |
149 | fNPedSamples(rawU.fNPedSamples), | |
65bdc82f | 150 | fGeom(rawU.fGeom), |
9f467289 | 151 | fOption(rawU.fOption), |
152 | fRemoveBadChannels(rawU.fRemoveBadChannels), | |
153 | fFittingAlgorithm(rawU.fFittingAlgorithm) | |
65bdc82f | 154 | { |
155 | //copy ctor | |
156 | fMapping[0] = rawU.fMapping[0]; | |
157 | fMapping[1] = rawU.fMapping[1]; | |
21cad85c | 158 | fMapping[2] = rawU.fMapping[2]; |
159 | fMapping[3] = rawU.fMapping[3]; | |
65bdc82f | 160 | } |
161 | ||
162 | //____________________________________________________________________________ | |
163 | AliEMCALRawUtils& AliEMCALRawUtils::operator =(const AliEMCALRawUtils &rawU) | |
164 | { | |
165 | //assignment operator | |
166 | ||
167 | if(this != &rawU) { | |
168 | fHighLowGainFactor = rawU.fHighLowGainFactor; | |
b4133f05 | 169 | fOrder = rawU.fOrder; |
170 | fTau = rawU.fTau; | |
171 | fNoiseThreshold = rawU.fNoiseThreshold; | |
172 | fNPedSamples = rawU.fNPedSamples; | |
65bdc82f | 173 | fGeom = rawU.fGeom; |
174 | fOption = rawU.fOption; | |
9f467289 | 175 | fRemoveBadChannels = rawU.fRemoveBadChannels; |
176 | fFittingAlgorithm = rawU.fFittingAlgorithm; | |
65bdc82f | 177 | fMapping[0] = rawU.fMapping[0]; |
178 | fMapping[1] = rawU.fMapping[1]; | |
21cad85c | 179 | fMapping[2] = rawU.fMapping[2]; |
180 | fMapping[3] = rawU.fMapping[3]; | |
65bdc82f | 181 | } |
182 | ||
183 | return *this; | |
184 | ||
ee299369 | 185 | } |
65bdc82f | 186 | |
ee299369 | 187 | //____________________________________________________________________________ |
188 | AliEMCALRawUtils::~AliEMCALRawUtils() { | |
e5bbbc4e | 189 | //dtor |
65bdc82f | 190 | |
ee299369 | 191 | } |
65bdc82f | 192 | |
ee299369 | 193 | //____________________________________________________________________________ |
65bdc82f | 194 | void AliEMCALRawUtils::Digits2Raw() |
ee299369 | 195 | { |
196 | // convert digits of the current event to raw data | |
197 | ||
33c3c91a | 198 | AliRunLoader *rl = AliRunLoader::Instance(); |
ee299369 | 199 | AliEMCALLoader *loader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL")); |
200 | ||
201 | // get the digits | |
202 | loader->LoadDigits("EMCAL"); | |
203 | loader->GetEvent(); | |
204 | TClonesArray* digits = loader->Digits() ; | |
205 | ||
206 | if (!digits) { | |
207 | Warning("Digits2Raw", "no digits found !"); | |
208 | return; | |
209 | } | |
65bdc82f | 210 | |
ee299369 | 211 | static const Int_t nDDL = 12*2; // 12 SM hardcoded for now. Buffers allocated dynamically, when needed, so just need an upper limit here |
212 | AliAltroBuffer* buffers[nDDL]; | |
213 | for (Int_t i=0; i < nDDL; i++) | |
214 | buffers[i] = 0; | |
215 | ||
e2c2134b | 216 | TArrayI adcValuesLow(fgTimeBins); |
217 | TArrayI adcValuesHigh(fgTimeBins); | |
ee299369 | 218 | |
ee299369 | 219 | // loop over digits (assume ordered digits) |
220 | for (Int_t iDigit = 0; iDigit < digits->GetEntries(); iDigit++) { | |
221 | AliEMCALDigit* digit = dynamic_cast<AliEMCALDigit *>(digits->At(iDigit)) ; | |
222 | if (digit->GetAmp() < fgThreshold) | |
223 | continue; | |
224 | ||
225 | //get cell indices | |
226 | Int_t nSM = 0; | |
227 | Int_t nIphi = 0; | |
228 | Int_t nIeta = 0; | |
229 | Int_t iphi = 0; | |
230 | Int_t ieta = 0; | |
231 | Int_t nModule = 0; | |
65bdc82f | 232 | fGeom->GetCellIndex(digit->GetId(), nSM, nModule, nIphi, nIeta); |
233 | fGeom->GetCellPhiEtaIndexInSModule(nSM, nModule, nIphi, nIeta,iphi, ieta) ; | |
ee299369 | 234 | |
21cad85c | 235 | //Check which is the RCU, 0 or 1, of the cell. |
ee299369 | 236 | Int_t iRCU = -111; |
237 | //RCU0 | |
238 | if (0<=iphi&&iphi<8) iRCU=0; // first cable row | |
239 | else if (8<=iphi&&iphi<16 && 0<=ieta&&ieta<24) iRCU=0; // first half; | |
240 | //second cable row | |
241 | //RCU1 | |
242 | else if(8<=iphi&&iphi<16 && 24<=ieta&&ieta<48) iRCU=1; // second half; | |
243 | //second cable row | |
244 | else if(16<=iphi&&iphi<24) iRCU=1; // third cable row | |
21cad85c | 245 | |
246 | if (nSM%2==1) iRCU = 1 - iRCU; // swap for odd=C side, to allow us to cable both sides the same | |
247 | ||
e36e3bcf | 248 | if (iRCU<0) |
249 | Fatal("Digits2Raw()","Non-existent RCU number: %d", iRCU); | |
ee299369 | 250 | |
251 | //Which DDL? | |
252 | Int_t iDDL = fgDDLPerSuperModule* nSM + iRCU; | |
253 | if (iDDL >= nDDL) | |
254 | Fatal("Digits2Raw()","Non-existent DDL board number: %d", iDDL); | |
255 | ||
256 | if (buffers[iDDL] == 0) { | |
257 | // open new file and write dummy header | |
258 | TString fileName = AliDAQ::DdlFileName("EMCAL",iDDL); | |
21cad85c | 259 | //Select mapping file RCU0A, RCU0C, RCU1A, RCU1C |
260 | Int_t iRCUside=iRCU+(nSM%2)*2; | |
261 | //iRCU=0 and even (0) SM -> RCU0A.data 0 | |
262 | //iRCU=1 and even (0) SM -> RCU1A.data 1 | |
263 | //iRCU=0 and odd (1) SM -> RCU0C.data 2 | |
264 | //iRCU=1 and odd (1) SM -> RCU1C.data 3 | |
265 | //cout<<" nSM "<<nSM<<"; iRCU "<<iRCU<<"; iRCUside "<<iRCUside<<endl; | |
266 | buffers[iDDL] = new AliAltroBuffer(fileName.Data(),fMapping[iRCUside]); | |
ee299369 | 267 | buffers[iDDL]->WriteDataHeader(kTRUE, kFALSE); //Dummy; |
268 | } | |
269 | ||
270 | // out of time range signal (?) | |
271 | if (digit->GetTimeR() > GetRawFormatTimeMax() ) { | |
272 | AliInfo("Signal is out of time range.\n"); | |
273 | buffers[iDDL]->FillBuffer((Int_t)digit->GetAmp()); | |
274 | buffers[iDDL]->FillBuffer(GetRawFormatTimeBins() ); // time bin | |
275 | buffers[iDDL]->FillBuffer(3); // bunch length | |
276 | buffers[iDDL]->WriteTrailer(3, ieta, iphi, nSM); // trailer | |
277 | // calculate the time response function | |
278 | } else { | |
e2c2134b | 279 | Bool_t lowgain = RawSampledResponse(digit->GetTimeR(), digit->GetAmp(), adcValuesHigh.GetArray(), adcValuesLow.GetArray()) ; |
ee299369 | 280 | if (lowgain) |
e2c2134b | 281 | buffers[iDDL]->WriteChannel(ieta, iphi, 0, GetRawFormatTimeBins(), adcValuesLow.GetArray(), fgThreshold); |
ee299369 | 282 | else |
e2c2134b | 283 | buffers[iDDL]->WriteChannel(ieta,iphi, 1, GetRawFormatTimeBins(), adcValuesHigh.GetArray(), fgThreshold); |
ee299369 | 284 | } |
285 | } | |
286 | ||
287 | // write headers and close files | |
288 | for (Int_t i=0; i < nDDL; i++) { | |
289 | if (buffers[i]) { | |
290 | buffers[i]->Flush(); | |
291 | buffers[i]->WriteDataHeader(kFALSE, kFALSE); | |
292 | delete buffers[i]; | |
293 | } | |
294 | } | |
65bdc82f | 295 | |
ee299369 | 296 | loader->UnloadDigits(); |
297 | } | |
298 | ||
299 | //____________________________________________________________________________ | |
5e3106bc | 300 | void AliEMCALRawUtils::Raw2Digits(AliRawReader* reader,TClonesArray *digitsArr, AliCaloCalibPedestal* pedbadmap) |
ee299369 | 301 | { |
65bdc82f | 302 | // convert raw data of the current event to digits |
ee299369 | 303 | |
c47157cd | 304 | digitsArr->Clear(); |
ee299369 | 305 | |
c47157cd | 306 | if (!digitsArr) { |
ee299369 | 307 | Error("Raw2Digits", "no digits found !"); |
308 | return; | |
309 | } | |
310 | if (!reader) { | |
311 | Error("Raw2Digits", "no raw reader found !"); | |
312 | return; | |
313 | } | |
314 | ||
32cd4c24 | 315 | AliCaloRawStreamV3 in(reader,"EMCAL",fMapping); |
ee299369 | 316 | // Select EMCAL DDL's; |
7643e728 | 317 | reader->Select("EMCAL",0,43); // 43 = AliEMCALGeoParams::fgkLastAltroDDL |
feedcab9 | 318 | |
8cb998bd | 319 | //Updated fitting routine from 2007 beam test takes into account |
320 | //possibility of two peaks in data and selects first one for fitting | |
321 | //Also sets some of the starting parameters based on the shape of the | |
322 | //given raw signal being fit | |
323 | ||
324 | TF1 * signalF = new TF1("signal", RawResponseFunction, 0, GetRawFormatTimeBins(), 5); | |
7643e728 | 325 | signalF->SetParameters(10.,5.,fTau,fOrder,0.); //set all defaults once, just to be safe |
8cb998bd | 326 | signalF->SetParNames("amp","t0","tau","N","ped"); |
7643e728 | 327 | signalF->FixParameter(2,fTau); // tau in units of time bin |
328 | signalF->FixParameter(3,fOrder); // order | |
48a56166 | 329 | |
ee299369 | 330 | Int_t id = -1; |
82cbdfca | 331 | Float_t time = 0. ; |
332 | Float_t amp = 0. ; | |
7643e728 | 333 | Float_t ped = 0. ; |
334 | Float_t ampEstimate = 0; | |
335 | Float_t timeEstimate = 0; | |
336 | Float_t pedEstimate = 0; | |
32cd4c24 | 337 | Int_t i = 0; |
338 | Int_t startBin = 0; | |
ee299369 | 339 | |
8cb998bd | 340 | //Graph to hold data we will fit (should be converted to an array |
341 | //later to speed up processing | |
342 | TGraph * gSig = new TGraph(GetRawFormatTimeBins()); | |
ee299369 | 343 | |
ee299369 | 344 | Int_t lowGain = 0; |
e5bbbc4e | 345 | Int_t caloFlag = 0; // low, high gain, or TRU, or LED ref. |
ee299369 | 346 | |
32cd4c24 | 347 | // start loop over input stream |
348 | while (in.NextDDL()) { | |
349 | while (in.NextChannel()) { | |
7643e728 | 350 | |
351 | //Check if the signal is high or low gain and then do the fit, | |
352 | //if it is from TRU do not fit | |
353 | caloFlag = in.GetCaloFlag(); | |
354 | if (caloFlag != 0 && caloFlag != 1) continue; | |
355 | ||
5e3106bc | 356 | //Do not fit bad channels |
9f467289 | 357 | if(fRemoveBadChannels && pedbadmap->IsBadChannel(in.GetModule(),in.GetColumn(),in.GetRow())) { |
5e3106bc | 358 | //printf("Tower from SM %d, column %d, row %d is BAD!!! Skip \n", in.GetModule(),in.GetColumn(),in.GetRow()); |
359 | continue; | |
360 | } | |
361 | ||
32cd4c24 | 362 | // There can be zero-suppression in the raw data, |
363 | // so set up the TGraph in advance | |
364 | for (i=0; i < GetRawFormatTimeBins(); i++) { | |
7643e728 | 365 | gSig->SetPoint(i, i , -1); // init to out-of-range values |
32cd4c24 | 366 | } |
7643e728 | 367 | |
368 | Int_t maxTimeBin = 0; | |
369 | Int_t min = 0x3ff; // init to 10-bit max | |
370 | Int_t max = 0; // init to 10-bit min | |
32cd4c24 | 371 | while (in.NextBunch()) { |
7643e728 | 372 | |
32cd4c24 | 373 | const UShort_t *sig = in.GetSignals(); |
374 | startBin = in.GetStartTimeBin(); | |
7643e728 | 375 | if (maxTimeBin < startBin) { |
376 | maxTimeBin = startBin; // timebins come in reverse order | |
377 | } | |
378 | if (maxTimeBin < 0 || maxTimeBin >= GetRawFormatTimeBins()) { | |
379 | AliWarning(Form("Invalid time bin %d",maxTimeBin)); | |
380 | maxTimeBin = GetRawFormatTimeBins(); | |
32cd4c24 | 381 | } |
7643e728 | 382 | |
32cd4c24 | 383 | for (i = 0; i < in.GetBunchLength(); i++) { |
384 | time = startBin--; | |
7643e728 | 385 | gSig->SetPoint((Int_t)time, time, (Double_t) sig[i]) ; |
386 | if (max < sig[i]) max = sig[i]; | |
03a3ed3f | 387 | if (min > sig[i]) min = sig[i]; |
7643e728 | 388 | |
32cd4c24 | 389 | } |
390 | } // loop over bunches | |
56613d93 | 391 | |
7643e728 | 392 | gSig->Set(maxTimeBin+1); // set actual max size of TGraph |
393 | ||
394 | //Initialize the variables, do not keep previous values. | |
395 | // not really necessary to reset all of them (only amp and time at the moment), but better safe than sorry | |
396 | amp = -1 ; | |
397 | time = -1 ; | |
398 | ped = -1; | |
399 | ampEstimate = -1 ; | |
400 | timeEstimate = -1 ; | |
401 | pedEstimate = -1; | |
9f467289 | 402 | |
403 | if ( (max - min) > fNoiseThreshold) { | |
73eed584 | 404 | FitRaw(gSig, signalF, maxTimeBin, amp, time, ped, |
405 | ampEstimate, timeEstimate, pedEstimate); | |
406 | // switch(fFittingAlgorithm) | |
407 | // { | |
408 | // case kStandard: | |
409 | // { | |
410 | // //printf("Standard fitter \n"); | |
411 | // FitRaw(gSig, signalF, maxTimeBin, amp, time, ped, | |
412 | // ampEstimate, timeEstimate, pedEstimate); | |
413 | // break; | |
414 | // } | |
415 | // case kFastFit: | |
416 | // { | |
417 | // //printf("FastFitter \n"); | |
418 | // Double_t eSignal = 0; | |
419 | // Double_t dAmp = amp; | |
420 | // Double_t dTimeEstimate = timeEstimate; | |
421 | // Double_t eTimeEstimate = 0; | |
422 | // Double_t eAmp = 0; | |
423 | // Double_t chi2 = 0; | |
424 | // | |
425 | // AliCaloFastAltroFitv0::FastFit(gSig->GetX(), gSig->GetY(), gSig->GetN(), | |
426 | // eSignal, fTau, | |
427 | // dAmp, eAmp, dTimeEstimate, eTimeEstimate, chi2); | |
428 | // amp=dAmp; | |
429 | // timeEstimate = dTimeEstimate; | |
430 | // //printf("FastFitter: Amp %f, time %f, eAmp %f, eTimeEstimate %f, chi2 %f\n",amp, timeEstimate,eAmp,eTimeEstimate,chi2); | |
431 | // | |
432 | // break; | |
433 | // } | |
434 | // } | |
9f467289 | 435 | } |
7643e728 | 436 | |
437 | if ( amp>0 && amp<2000 && time>0 && time<(maxTimeBin*GetRawFormatTimeBinWidth()) ) { //check both high and low end of amplitude result, and time | |
438 | //2000 is somewhat arbitrary - not nice with magic numbers in the code.. | |
439 | id = fGeom->GetAbsCellIdFromCellIndexes(in.GetModule(), in.GetRow(), in.GetColumn()) ; | |
440 | lowGain = in.IsLowGain(); | |
441 | ||
442 | // check fit results: should be consistent with initial estimates | |
443 | // more magic numbers, but very loose cuts, for now.. | |
444 | // We have checked that amp an time values are positive so division for assymmetry | |
445 | // calculation should be OK/safe | |
446 | Float_t ampAsymm = (amp - ampEstimate)/(amp + ampEstimate); | |
447 | if ( (TMath::Abs(ampAsymm) > 0.1) || | |
448 | (TMath::Abs(time - timeEstimate) > 2*GetRawFormatTimeBinWidth()) ) { | |
5e3106bc | 449 | AliDebug(2,Form("Fit results ped %f amp %f time %f not consistent with expectations ped %f max-ped %f time %d", |
7643e728 | 450 | ped, amp, time, pedEstimate, ampEstimate, timeEstimate)); |
5e3106bc | 451 | |
7643e728 | 452 | // what should do we do then? skip this channel or assign the simple estimate? |
453 | // for now just overwrite the fit results with the simple estimate | |
454 | amp = ampEstimate; | |
455 | time = timeEstimate; | |
32cd4c24 | 456 | } |
7643e728 | 457 | |
458 | AliDebug(2,Form("id %d lowGain %d amp %g", id, lowGain, amp)); | |
459 | // printf("Added tower: SM %d, row %d, column %d, amp %3.2f\n",in.GetModule(), in.GetRow(), in.GetColumn(),amp); | |
460 | // round off amplitude value to nearest integer | |
461 | AddDigit(digitsArr, id, lowGain, TMath::Nint(amp), time); | |
462 | } | |
463 | ||
32cd4c24 | 464 | // Reset graph |
465 | for (Int_t index = 0; index < gSig->GetN(); index++) { | |
7643e728 | 466 | gSig->SetPoint(index, index, -1) ; |
32cd4c24 | 467 | } |
468 | // Reset starting parameters for fit function | |
7643e728 | 469 | signalF->SetParameters(10.,5.,fTau,fOrder,0.); //reset all defaults just to be safe |
48a56166 | 470 | |
32cd4c24 | 471 | } // end while over channel |
472 | } //end while over DDL's, of input stream | |
ee299369 | 473 | |
474 | delete signalF ; | |
475 | delete gSig; | |
476 | ||
477 | return ; | |
478 | } | |
479 | ||
480 | //____________________________________________________________________________ | |
82cbdfca | 481 | void AliEMCALRawUtils::AddDigit(TClonesArray *digitsArr, Int_t id, Int_t lowGain, Int_t amp, Float_t time) { |
482 | // | |
483 | // Add a new digit. | |
484 | // This routine checks whether a digit exists already for this tower | |
485 | // and then decides whether to use the high or low gain info | |
486 | // | |
487 | // Called by Raw2Digits | |
488 | ||
489 | AliEMCALDigit *digit = 0, *tmpdigit = 0; | |
82cbdfca | 490 | TIter nextdigit(digitsArr); |
491 | while (digit == 0 && (tmpdigit = (AliEMCALDigit*) nextdigit())) { | |
492 | if (tmpdigit->GetId() == id) | |
493 | digit = tmpdigit; | |
494 | } | |
495 | ||
496 | if (!digit) { // no digit existed for this tower; create one | |
a7ec7165 | 497 | if (lowGain && amp > fgkOverflowCut) |
82cbdfca | 498 | amp = Int_t(fHighLowGainFactor * amp); |
499 | Int_t idigit = digitsArr->GetEntries(); | |
500 | new((*digitsArr)[idigit]) AliEMCALDigit( -1, -1, id, amp, time, idigit) ; | |
501 | } | |
502 | else { // a digit already exists, check range | |
b4133f05 | 503 | // (use high gain if signal < cut value, otherwise low gain) |
82cbdfca | 504 | if (lowGain) { // new digit is low gain |
b4133f05 | 505 | if (digit->GetAmp() > fgkOverflowCut) { // use if stored digit is out of range |
82cbdfca | 506 | digit->SetAmp(Int_t(fHighLowGainFactor * amp)); |
507 | digit->SetTime(time); | |
508 | } | |
509 | } | |
b4133f05 | 510 | else if (amp < fgkOverflowCut) { // new digit is high gain; use if not out of range |
82cbdfca | 511 | digit->SetAmp(amp); |
512 | digit->SetTime(time); | |
513 | } | |
514 | } | |
515 | } | |
516 | ||
517 | //____________________________________________________________________________ | |
7643e728 | 518 | void AliEMCALRawUtils::FitRaw(TGraph * gSig, TF1* signalF, const Int_t lastTimeBin, Float_t & amp, Float_t & time, Float_t & ped, Float_t & ampEstimate, Float_t & timeEstimate, Float_t & pedEstimate, const Float_t cut) const |
ee299369 | 519 | { |
520 | // Fits the raw signal time distribution; from AliEMCALGetter | |
7643e728 | 521 | // last argument: Float_t cut = 0.0; // indicating how much of amplitude w.r.t. max value fit should be above noise and pedestal |
522 | ||
523 | // initialize return values | |
524 | amp = 0; | |
525 | time = 0; | |
526 | ped = 0; | |
527 | ampEstimate = 0; | |
528 | timeEstimate = 0; | |
529 | pedEstimate = 0; | |
530 | ||
531 | // 0th step: remove plateau / overflow candidates | |
532 | // before trying to estimate amplitude, search for maxima etc. | |
533 | // | |
534 | Int_t nOrig = gSig->GetN(); // number of samples before we remove any overflows | |
535 | // Values for readback from input graph | |
536 | Double_t ttime = 0; | |
537 | Double_t signal = 0; | |
538 | ||
539 | /* | |
540 | // start: tmp dump of all values | |
541 | for (Int_t i=0; i<gSig->GetN(); i++) { | |
542 | gSig->GetPoint(i, ttime, signal) ; // get values | |
543 | printf("orig: i %d, time %f, signal %f\n",i, ttime, signal); | |
544 | } | |
545 | // end: tmp dump of all values | |
546 | */ | |
547 | ||
548 | // start from back of TGraph since RemovePoint will downshift indices | |
549 | for (Int_t i=nOrig-1; i>=0; i--) { | |
550 | gSig->GetPoint(i, ttime, signal) ; // get values | |
551 | if (signal >= (pedEstimate + fgkOverflowCut) ) { | |
552 | gSig->RemovePoint(i); | |
553 | } | |
554 | } | |
ee299369 | 555 | |
7643e728 | 556 | // 1st step: we try to estimate the pedestal value |
557 | Int_t nPed = 0; | |
558 | for (Int_t index = 0; index < gSig->GetN(); index++) { | |
82cbdfca | 559 | gSig->GetPoint(index, ttime, signal) ; |
7643e728 | 560 | // ttime < fNPedsamples used for pedestal estimate; |
561 | // ttime >= fNPedSamples used for signal checks | |
562 | if (signal >= 0 && ttime<fNPedSamples) { // valid value | |
563 | pedEstimate += signal; | |
82cbdfca | 564 | nPed++; |
ee299369 | 565 | } |
566 | } | |
e9dbb64a | 567 | |
82cbdfca | 568 | if (nPed > 0) |
7643e728 | 569 | pedEstimate /= nPed; |
e9dbb64a | 570 | else { |
7643e728 | 571 | //AliWarning("Could not determine pedestal"); |
572 | AliDebug(1,"Could not determine pedestal"); | |
573 | pedEstimate = 0; // good estimate for ZeroSupp data (non ZS data should have no problem with pedestal estimate) | |
e9dbb64a | 574 | } |
82cbdfca | 575 | |
7643e728 | 576 | // 2nd step: we look through the rest of the time-bins/ADC values and |
577 | // see if we have something that looks like a signal. | |
578 | // We look for a first local maxima, as well as for a global maxima | |
579 | Int_t locMaxFound = 0; | |
580 | Int_t locMaxId = 0; // time-bin index at first local max | |
581 | Float_t locMaxSig = -1; // actual local max value | |
582 | Int_t globMaxId = 0; // time-bin index at global max | |
583 | Float_t globMaxSig = -1; // actual global max value | |
584 | // We will also look for any values that look like they are in overflow region | |
585 | for (Int_t i=0; i<gSig->GetN(); i++) { | |
586 | gSig->GetPoint(i, ttime, signal) ; // get values | |
587 | ||
588 | // ttime < fNPedsamples used for pedestal estimate; | |
589 | // ttime >= fNPedSamples used for signal checks | |
590 | if (ttime >= fNPedSamples) { | |
591 | ||
592 | // look for first local maximum signal=ADC value | |
593 | if (!locMaxFound && signal > locMaxSig) { | |
594 | locMaxId = i; | |
595 | locMaxSig = signal; | |
e9dbb64a | 596 | } |
7643e728 | 597 | else if ( locMaxSig > (pedEstimate + fNoiseThreshold) ) { |
598 | // we enter this condition after signal<=max, but previous | |
599 | // max value was large enough. I.e. at least a significant local | |
600 | // maxima has been found (just before) | |
601 | locMaxFound = 1; | |
e9dbb64a | 602 | } |
7643e728 | 603 | |
604 | // also check for global maximum.. | |
605 | if (signal > globMaxSig) { | |
606 | globMaxId = i; | |
607 | globMaxSig = signal; | |
c61fe3b4 | 608 | } |
7643e728 | 609 | } // ttime check |
610 | } // end for-loop over samples after pedestal | |
611 | ||
612 | // OK, we have looked through the signal spectra, let's see if we should try to make the fit | |
613 | ampEstimate = locMaxSig - pedEstimate; // estimate using first local maxima | |
614 | if ( ampEstimate > fNoiseThreshold ) { // else it's just noise | |
615 | ||
616 | //Check that the local maximum we will use is not at the end or beginning of time sample range | |
617 | Double_t timeMax = -1; | |
618 | Int_t iMax = locMaxId; | |
619 | gSig->GetPoint(locMaxId, timeMax, signal) ; | |
620 | if (timeMax < 2 || timeMax > lastTimeBin-1) { // lastTimeBin is the lowest kept time-sample; current (Dec 2009) case | |
621 | // if (timeMax < 2 || timeMax > lastTimeBin-2) { // for when lastTimeBin is the lowest read-out time-sample, future (2010) case | |
622 | AliDebug(1,Form("Skip fit, maximum of the sample close to the edges : timeMax %3.2f, ampEstimate %3.2f",timeMax, ampEstimate)); | |
623 | return; | |
624 | } | |
625 | ||
626 | // Check if the local and global maximum disagree | |
627 | if (locMaxId != globMaxId) { | |
628 | AliDebug(1,Form("Warning, local first maximum %d does not agree with global maximum %d\n", locMaxId, globMaxId)); | |
629 | return; | |
630 | } | |
631 | ||
632 | // Get the maximum and find the lowest timebin (tailmin) where the ADC value is not | |
633 | // significantly different from the pedestal | |
634 | // first lower times edge a.k.a. tailmin | |
635 | Int_t tailMin = 0; | |
636 | Double_t tmptime = 0; | |
637 | for (Int_t i=iMax-1; i > 0; i--) { | |
638 | gSig->GetPoint(i, tmptime, signal) ; | |
639 | if((signal-pedEstimate) < fNoiseThreshold){ | |
640 | tailMin = i; | |
641 | break; | |
e9dbb64a | 642 | } |
5a056daa | 643 | } |
7643e728 | 644 | // then same exercise for the higher times edge a.k.a. tailmax |
645 | Int_t tailMax = lastTimeBin; | |
646 | for (Int_t i=iMax+1; i < gSig->GetN(); i++) { | |
647 | gSig->GetPoint(i, tmptime, signal) ; | |
648 | if ((signal-pedEstimate) <= (ampEstimate*cut + fNoiseThreshold)) { // stop fit at cut-fraction of amplitude above noise-threshold (cut>0 would mean avoid the pulse shape falling edge) | |
649 | tailMax = i; | |
650 | break; | |
651 | } | |
fb070798 | 652 | } |
fb070798 | 653 | |
7643e728 | 654 | // remove all points which are not in the distribution around maximum |
655 | // i.e. up to tailmin, and from tailmax | |
656 | if ( tailMax != (gSig->GetN()-1) ){ // else nothing to remove | |
657 | nOrig = gSig->GetN(); // can't use GetN call in for loop below since gSig size changes.. | |
658 | for(int j = tailMax; j < nOrig; j++) gSig->RemovePoint(tailMax); | |
fb070798 | 659 | } |
7643e728 | 660 | for(int j = 0; j<=tailMin; j++) gSig->RemovePoint(0); |
5a056daa | 661 | |
7643e728 | 662 | if(gSig->GetN() < 3) { |
663 | AliDebug(2,Form("Skip fit, number of entries in sample smaller than number of fitting parameters: in sample %d, fitting param 3", | |
664 | gSig->GetN() )); | |
665 | return; | |
666 | } | |
8cb998bd | 667 | |
7643e728 | 668 | timeEstimate = timeMax * GetRawFormatTimeBinWidth(); |
73eed584 | 669 | |
670 | //-------------------------------------------------- | |
671 | //Do the fit, different fitting algorithms available | |
672 | //-------------------------------------------------- | |
673 | ||
674 | switch(fFittingAlgorithm) { | |
675 | case kStandard: | |
676 | { | |
677 | //printf("Standard fitter \n"); | |
678 | ||
679 | // determine what the valid fit range is | |
680 | Double_t minFit = 9999; | |
681 | Double_t maxFit = 0; | |
682 | for (Int_t i=0; i < gSig->GetN(); i++) { | |
683 | gSig->GetPoint(i, ttime, signal); | |
684 | if (minFit > ttime) minFit=ttime; | |
685 | if (maxFit < ttime) maxFit=ttime; | |
686 | //debug: printf("no tail: i %d, time %f, signal %f\n",i, ttime, signal); | |
687 | } | |
688 | signalF->SetRange(minFit, maxFit); | |
689 | ||
690 | signalF->FixParameter(4, pedEstimate) ; | |
691 | signalF->SetParameter(1, timeMax); | |
692 | signalF->SetParameter(0, ampEstimate); | |
693 | ||
694 | gSig->Fit(signalF, "QROW"); // Note option 'W': equal errors on all points | |
695 | ||
696 | // assign fit results | |
697 | amp = signalF->GetParameter(0); | |
698 | time = signalF->GetParameter(1) * GetRawFormatTimeBinWidth(); // skip subtraction of fgTimeTrigger? | |
699 | ped = signalF->GetParameter(4); | |
700 | //printf("Std : Amp %f, time %g\n",amp, time); | |
701 | ||
702 | //BEG YS alternative methods to calculate the amplitude | |
703 | Double_t * ymx = gSig->GetX() ; | |
704 | Double_t * ymy = gSig->GetY() ; | |
705 | const Int_t kN = 3 ; | |
706 | Double_t ymMaxX[kN] = {0., 0., 0.} ; | |
707 | Double_t ymMaxY[kN] = {0., 0., 0.} ; | |
708 | Double_t ymax = 0. ; | |
709 | // find the maximum amplitude | |
710 | Int_t ymiMax = 0 ; | |
711 | for (Int_t ymi = 0; ymi < gSig->GetN(); ymi++) { | |
712 | if (ymy[ymi] > ymMaxY[0] ) { | |
713 | ymMaxY[0] = ymy[ymi] ; //<========== This is the maximum amplitude | |
714 | ymMaxX[0] = ymx[ymi] ; | |
715 | ymiMax = ymi ; | |
716 | } | |
717 | } | |
718 | // find the maximum by fitting a parabola through the max and the two adjacent samples | |
719 | if ( ymiMax < gSig->GetN()-1 && ymiMax > 0) { | |
720 | ymMaxY[1] = ymy[ymiMax+1] ; | |
721 | ymMaxY[2] = ymy[ymiMax-1] ; | |
722 | ymMaxX[1] = ymx[ymiMax+1] ; | |
723 | ymMaxX[2] = ymx[ymiMax-1] ; | |
724 | if (ymMaxY[0]*ymMaxY[1]*ymMaxY[2] > 0) { | |
725 | //fit a parabola through the 3 points y= a+bx+x*x*x | |
726 | Double_t sy = 0 ; | |
727 | Double_t sx = 0 ; | |
728 | Double_t sx2 = 0 ; | |
729 | Double_t sx3 = 0 ; | |
730 | Double_t sx4 = 0 ; | |
731 | Double_t sxy = 0 ; | |
732 | Double_t sx2y = 0 ; | |
733 | for (Int_t i = 0; i < kN ; i++) { | |
734 | sy += ymMaxY[i] ; | |
735 | sx += ymMaxX[i] ; | |
736 | sx2 += ymMaxX[i]*ymMaxX[i] ; | |
737 | sx3 += ymMaxX[i]*ymMaxX[i]*ymMaxX[i] ; | |
738 | sx4 += ymMaxX[i]*ymMaxX[i]*ymMaxX[i]*ymMaxX[i] ; | |
739 | sxy += ymMaxX[i]*ymMaxY[i] ; | |
740 | sx2y += ymMaxX[i]*ymMaxX[i]*ymMaxY[i] ; | |
741 | } | |
742 | Double_t cN = (sx2y*kN-sy*sx2)*(sx3*sx-sx2*sx2)-(sx2y*sx-sxy*sx2)*(sx3*kN-sx*sx2); | |
743 | Double_t cD = (sx4*kN-sx2*sx2)*(sx3*sx-sx2*sx2)-(sx4*sx-sx3*sx2)*(sx3*kN-sx*sx2) ; | |
744 | Double_t c = cN / cD ; | |
745 | Double_t b = ((sx2y*kN-sy*sx2)-c*(sx4*kN-sx2*sx2))/(sx3*kN-sx*sx2) ; | |
746 | Double_t a = (sy-b*sx-c*sx2)/kN ; | |
747 | Double_t xmax = -b/(2*c) ; | |
748 | ymax = a + b*xmax + c*xmax*xmax ;//<========== This is the maximum amplitude | |
749 | } | |
750 | } | |
751 | ||
752 | Double_t diff = TMath::Abs(1-ymMaxY[0]/amp) ; | |
753 | if (diff > 0.1) | |
754 | amp = ymMaxY[0] ; | |
755 | //printf("Yves : Amp %f, time %g\n",amp, time); | |
756 | //END YS | |
757 | break; | |
758 | }//kStandard Fitter | |
759 | //---------------------------- | |
760 | case kFastFit: | |
761 | { | |
762 | //printf("FastFitter \n"); | |
763 | Double_t eSignal = 0; | |
764 | Double_t dAmp = amp; | |
765 | Double_t eAmp = 0; | |
766 | Double_t dTime = time; | |
767 | Double_t eTime = 0; | |
768 | Double_t chi2 = 0; | |
769 | ||
770 | AliCaloFastAltroFitv0::FastFit(gSig->GetX(), gSig->GetY(), gSig->GetN(), | |
771 | eSignal, fTau, | |
772 | dAmp, eAmp, dTime, eTime, chi2); | |
773 | amp = dAmp; | |
774 | time = dTime * GetRawFormatTimeBinWidth(); | |
775 | //printf("FastFitter: Amp %f, time %g, eAmp %f, eTimeEstimate %g, chi2 %f\n",amp, time,eAmp,eTime,chi2); | |
776 | break; | |
777 | } //kFastFit | |
778 | //---------------------------- | |
779 | }//switch fitting algorithms | |
7643e728 | 780 | } // ampEstimate > fNoiseThreshold |
ee299369 | 781 | return; |
782 | } | |
783 | //__________________________________________________________________ | |
784 | Double_t AliEMCALRawUtils::RawResponseFunction(Double_t *x, Double_t *par) | |
785 | { | |
8cb998bd | 786 | // Matches version used in 2007 beam test |
787 | // | |
ee299369 | 788 | // Shape of the electronics raw reponse: |
789 | // It is a semi-gaussian, 2nd order Gamma function of the general form | |
790 | // | |
7643e728 | 791 | // xx = (t - t0 + tau) / tau [xx is just a convenient help variable] |
792 | // F = A * (xx**N * exp( N * ( 1 - xx) ) for xx >= 0 | |
793 | // F = 0 for xx < 0 | |
ee299369 | 794 | // |
795 | // parameters: | |
8cb998bd | 796 | // A: par[0] // Amplitude = peak value |
797 | // t0: par[1] | |
798 | // tau: par[2] | |
799 | // N: par[3] | |
800 | // ped: par[4] | |
ee299369 | 801 | // |
802 | Double_t signal ; | |
8cb998bd | 803 | Double_t tau =par[2]; |
e5bbbc4e | 804 | Double_t n =par[3]; |
8cb998bd | 805 | Double_t ped = par[4]; |
806 | Double_t xx = ( x[0] - par[1] + tau ) / tau ; | |
ee299369 | 807 | |
5a056daa | 808 | if (xx <= 0) |
8cb998bd | 809 | signal = ped ; |
ee299369 | 810 | else { |
e5bbbc4e | 811 | signal = ped + par[0] * TMath::Power(xx , n) * TMath::Exp(n * (1 - xx )) ; |
ee299369 | 812 | } |
813 | return signal ; | |
814 | } | |
815 | ||
816 | //__________________________________________________________________ | |
817 | Bool_t AliEMCALRawUtils::RawSampledResponse( | |
818 | const Double_t dtime, const Double_t damp, Int_t * adcH, Int_t * adcL) const | |
819 | { | |
820 | // for a start time dtime and an amplitude damp given by digit, | |
821 | // calculates the raw sampled response AliEMCAL::RawResponseFunction | |
822 | ||
ee299369 | 823 | Bool_t lowGain = kFALSE ; |
824 | ||
48a56166 | 825 | // A: par[0] // Amplitude = peak value |
826 | // t0: par[1] | |
827 | // tau: par[2] | |
828 | // N: par[3] | |
829 | // ped: par[4] | |
830 | ||
56e13066 | 831 | TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeBins(), 5); |
48a56166 | 832 | signalF.SetParameter(0, damp) ; |
56e13066 | 833 | signalF.SetParameter(1, (dtime + fgTimeTrigger)/fgTimeBinWidth) ; |
b4133f05 | 834 | signalF.SetParameter(2, fTau) ; |
835 | signalF.SetParameter(3, fOrder); | |
fe93d365 | 836 | signalF.SetParameter(4, fgPedestalValue); |
ee299369 | 837 | |
838 | for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) { | |
56e13066 | 839 | Double_t signal = signalF.Eval(iTime) ; |
fe93d365 | 840 | |
7643e728 | 841 | // Next lines commeted for the moment but in principle it is not necessary to add |
ff10f540 | 842 | // extra noise since noise already added at the digits level. |
7643e728 | 843 | |
fe93d365 | 844 | //According to Terry Awes, 13-Apr-2008 |
845 | //add gaussian noise in quadrature to each sample | |
09974781 | 846 | //Double_t noise = gRandom->Gaus(0.,fgFEENoise); |
fe93d365 | 847 | //signal = sqrt(signal*signal + noise*noise); |
848 | ||
e2c2134b | 849 | // March 17,09 for fast fit simulations by Alexei Pavlinov. |
850 | // Get from PHOS analysis. In some sense it is open questions. | |
ff10f540 | 851 | //Double_t noise = gRandom->Gaus(0.,fgFEENoise); |
852 | //signal += noise; | |
7643e728 | 853 | |
ee299369 | 854 | adcH[iTime] = static_cast<Int_t>(signal + 0.5) ; |
b4133f05 | 855 | if ( adcH[iTime] > fgkRawSignalOverflow ){ // larger than 10 bits |
856 | adcH[iTime] = fgkRawSignalOverflow ; | |
ee299369 | 857 | lowGain = kTRUE ; |
858 | } | |
859 | ||
860 | signal /= fHighLowGainFactor; | |
861 | ||
862 | adcL[iTime] = static_cast<Int_t>(signal + 0.5) ; | |
b4133f05 | 863 | if ( adcL[iTime] > fgkRawSignalOverflow) // larger than 10 bits |
864 | adcL[iTime] = fgkRawSignalOverflow ; | |
ee299369 | 865 | } |
866 | return lowGain ; | |
867 | } |