]> git.uio.no Git - u/mrichter/AliRoot.git/blame - EMCAL/AliEMCALCalibTimeDep.cxx
split parts of CalibAbs off into new class CalibReference
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALCalibTimeDep.cxx
CommitLineData
a42992b7 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: AliEMCALCalibTimeDep.cxx $ */
17
18//_________________________________________________________________________
19///*-- Author:
20///////////////////////////////////////////////////////////////////////////////
21// //
22// class for EMCAL time-dep calibration //
23// //
24///////////////////////////////////////////////////////////////////////////////
25
26#include <iostream>
27#include <TGraphSmooth.h>
28#include "AliLog.h"
29#include "AliCDBEntry.h"
30#include "AliCDBManager.h"
31#include "AliEMCALSensorTempArray.h"
d81e6423 32#include "AliCaloCalibSignal.h"
33#include "AliEMCALBiasAPD.h"
34#include "AliEMCALCalibMapAPD.h"
82d90a2f 35#include "AliEMCALCalibReference.h"
d81e6423 36#include "AliEMCALCalibTimeDepCorrection.h"
a42992b7 37#include "AliEMCALCalibTimeDep.h"
38
39/* first a bunch of constants.. */
40const double fkSecToHour = 1.0/3600.0; // conversion factor from seconds to hours
41
d81e6423 42// some global variables for APD handling; values from Catania studies, best fit
43// TempCoeff = p0+p1*M (M=gain), where p0 and and p1 are functions of the dark current
44const double fkTempCoeffP0Const = -0.903; //
45const double fkTempCoeffP0Factor = -1.381e7; //
46const double fkTempCoeffP1Const = -0.023; //
47const double fkTempCoeffP1Factor = -4.966e5; //
48
621ff010 49const double fkErrorCode = -999; // to indicate that something went wrong
50
a42992b7 51using namespace std;
52
53ClassImp(AliEMCALCalibTimeDep)
54
55//________________________________________________________________
56AliEMCALCalibTimeDep::AliEMCALCalibTimeDep() :
57 fRun(0),
58 fStartTime(0),
59 fEndTime(0),
60 fMinTemp(0),
61 fMaxTemp(0),
62 fMinTime(0),
63 fMaxTime(0),
d81e6423 64 fTemperatureResolution(0.1), // 0.1 deg C is default
65 fTimeBinsPerHour(2), // 2 30-min bins per hour is default
82d90a2f 66 fHighLowGainFactor(16), // factor ~16 between High gain and low gain
d81e6423 67 fTempArray(NULL),
68 fCalibSignal(NULL),
69 fBiasAPD(NULL),
70 fCalibMapAPD(NULL),
82d90a2f 71 fCalibReference(NULL),
d81e6423 72 fCalibTimeDepCorrection(NULL)
a42992b7 73{
74 // Constructor
75}
76
77//________________________________________________________________
78AliEMCALCalibTimeDep::AliEMCALCalibTimeDep(const AliEMCALCalibTimeDep& calibt) :
621ff010 79 TObject(calibt),
a42992b7 80 fRun(calibt.GetRunNumber()),
81 fStartTime(calibt.GetStartTime()),
82 fEndTime(calibt.GetEndTime()),
83 fMinTemp(calibt.GetMinTemp()),
84 fMaxTemp(calibt.GetMaxTemp()),
85 fMinTime(calibt.GetMinTime()),
86 fMaxTime(calibt.GetMaxTime()),
d81e6423 87 fTemperatureResolution(calibt.GetTemperatureResolution()),
88 fTimeBinsPerHour(calibt.GetTimeBinsPerHour()),
82d90a2f 89 fHighLowGainFactor(calibt.GetHighLowGainFactor()),
d81e6423 90 fTempArray(calibt.GetTempArray()),
91 fCalibSignal(calibt.GetCalibSignal()),
92 fBiasAPD(calibt.GetBiasAPD()),
93 fCalibMapAPD(calibt.GetCalibMapAPD()),
82d90a2f 94 fCalibReference(calibt.GetCalibReference()),
d81e6423 95 fCalibTimeDepCorrection(calibt.GetCalibTimeDepCorrection())
a42992b7 96{
97 // copy constructor
98}
99
100
101//________________________________________________________________
102AliEMCALCalibTimeDep &AliEMCALCalibTimeDep::operator =(const AliEMCALCalibTimeDep& calibt)
103{
104 // assignment operator; use copy ctor
105 if (&calibt == this) return *this;
106
107 new (this) AliEMCALCalibTimeDep(calibt);
108 return *this;
109}
110
111//________________________________________________________________
112AliEMCALCalibTimeDep::~AliEMCALCalibTimeDep()
113{
114 // Destructor
115}
116
117//________________________________________________________________
118void AliEMCALCalibTimeDep::Reset()
119{
120 // clear variables to default
121 fRun = 0;
122 fStartTime = 0;
123 fEndTime = 0;
124 fMinTemp = 0;
125 fMaxTemp = 0;
126 fMinTime = 0;
127 fMaxTime = 0;
d81e6423 128 fTemperatureResolution = 0.1; // 0.1 deg C is default
129 fTimeBinsPerHour = 2; // 2 30-min bins per hour is default
a42992b7 130 fTempArray = NULL;
d81e6423 131 fCalibSignal = NULL;
132 fBiasAPD = NULL;
133 fCalibMapAPD = NULL;
82d90a2f 134 fCalibReference = NULL;
d81e6423 135 fCalibTimeDepCorrection = NULL;
a42992b7 136 return;
137}
138
139//________________________________________________________________
621ff010 140void AliEMCALCalibTimeDep::PrintInfo() const
a42992b7 141{
142 // print some info
d81e6423 143 cout << endl << " AliEMCALCalibTimeDep::PrintInfo() " << endl;
a42992b7 144 // basic variables, all 'publicly available' also
145 cout << " VARIABLE DUMP: " << endl
146 << " GetStartTime() " << GetStartTime() << endl
147 << " GetEndTime() " << GetEndTime() << endl
148 << " GetMinTemp() " << GetMinTemp() << endl
d81e6423 149 << " GetMaxTemp() " << GetMaxTemp() << endl;
a42992b7 150 // run ranges
151 cout << " RUN INFO: " << endl
152 << " length (in hours) " << GetLengthOfRunInHours() << endl
153 << " range of temperature measurements (in hours) " << GetRangeOfTempMeasureInHours()
154 << " (in deg. C) " << GetRangeOfTempMeasureInDegrees()
155 << endl;
a42992b7 156
157 return;
158}
d81e6423 159
a42992b7 160//________________________________________________________________
d81e6423 161Double_t AliEMCALCalibTimeDep::GetLengthOfRunInHours() const
a42992b7 162{
163 return (fEndTime - fStartTime)*fkSecToHour;
164}
d81e6423 165
166//________________________________________________________________
167Double_t AliEMCALCalibTimeDep::GetLengthOfRunInBins() const
168{
169 return (fEndTime - fStartTime)*fkSecToHour*fTimeBinsPerHour;
170}
171
a42992b7 172//________________________________________________________________
d81e6423 173Double_t AliEMCALCalibTimeDep::GetRangeOfTempMeasureInHours() const
a42992b7 174{
175 return (fMaxTime - fMinTime)*fkSecToHour;
176}
d81e6423 177
a42992b7 178//________________________________________________________________
d81e6423 179Double_t AliEMCALCalibTimeDep::GetRangeOfTempMeasureInDegrees() const
a42992b7 180{
181 return (fMaxTemp - fMinTemp);
182}
183
184//________________________________________________________________
185void AliEMCALCalibTimeDep::Initialize(Int_t run,
186 UInt_t startTime, UInt_t endTime)
187{
188 Reset(); // start fresh
189
190 fRun = run;
191 fStartTime = startTime;
192 fEndTime = endTime;
193
194 // collect the needed information
195 GetTemperatureInfo(); // temperature readings during the run
d81e6423 196 ScanTemperatureInfo(); // see what the boundaries are (Min/Max Time/Temp)
a42992b7 197
198 return;
199}
200
201//________________________________________________________________
d81e6423 202Double_t AliEMCALCalibTimeDep::GetTemperature(UInt_t timeStamp) const
a42992b7 203{// return estimate for all SuperModules and sensors, that had data
204
205 // first convert from seconds to hours..
d81e6423 206 Double_t timeHour = (timeStamp - fStartTime) * fkSecToHour;
621ff010 207
d81e6423 208 Double_t average = 0;
621ff010 209 int n = 0;
210
211 for (int i=0; i<fTempArray->NumSensors(); i++) {
212
213 AliEMCALSensorTemp *st = fTempArray->GetSensor(i);
214
215 // check if we had valid data for the time that is being asked for
216 if ( timeStamp>=st->GetStartTime() && timeStamp<=st->GetEndTime() ) {
217 AliSplineFit *f = st->GetFit();
218 if (f) { // ok, looks like we have valid data/info
219 // let's check what the expected value at the time appears to be
d81e6423 220 Double_t val = f->Eval(timeHour);
621ff010 221 average += val;
222 n++;
223 }
224 } // time
225 } // loop over fTempArray
226
227 if (n>0) { // some valid data was found
228 average /= n;
229 return average;
230 }
231 else { // no good data
232 return fkErrorCode;
233 }
a42992b7 234
a42992b7 235}
236
237//________________________________________________________________
d81e6423 238Double_t AliEMCALCalibTimeDep::GetTemperatureSM(int imod, UInt_t timeStamp) const
a42992b7 239{// return estimate for this one SuperModule, if it had data
240
241 // first convert from seconds to hours..
d81e6423 242 Double_t timeHour = (timeStamp - fStartTime) * fkSecToHour;
621ff010 243
d81e6423 244 Double_t average = 0;
621ff010 245 int n = 0;
246
247 for (int i=0; i<fTempArray->NumSensors(); i++) {
248
249 AliEMCALSensorTemp *st = fTempArray->GetSensor(i);
250 int module = st->GetSector()*2 + st->GetSide();
251 if ( module == imod ) { // right module
252 // check if we had valid data for the time that is being asked for
253 if ( timeStamp>=st->GetStartTime() && timeStamp<=st->GetEndTime() ) {
254 AliSplineFit *f = st->GetFit();
255 if (f) { // ok, looks like we have valid data/info
256 // let's check what the expected value at the time appears to be
d81e6423 257 Double_t val = f->Eval(timeHour);
621ff010 258 cout << " i " << i << " val " << val << endl;
259 average += val;
260 n++;
261 }
262 } // time
263 }
264
265 } // loop over fTempArray
266
267 if (n>0) { // some valid data was found
268 average /= n;
269 return average;
270 }
271 else { // no good data
272 return fkErrorCode;
273 }
a42992b7 274
a42992b7 275}
276
277//________________________________________________________________
d81e6423 278Double_t AliEMCALCalibTimeDep::GetTemperatureSMSensor(int imod, int isens, UInt_t timeStamp) const
a42992b7 279{// return estimate for this one SuperModule and sensor, if it had data
621ff010 280
a42992b7 281 // first convert from seconds to hours..
d81e6423 282 Double_t timeHour = (timeStamp - fStartTime) * fkSecToHour;
621ff010 283
284 for (int i=0; i<fTempArray->NumSensors(); i++) {
285
286 AliEMCALSensorTemp *st = fTempArray->GetSensor(i);
287 int module = st->GetSector()*2 + st->GetSide();
288 if ( module == imod && st->GetNum()==isens ) { // right module, and sensor
289 // check if we had valid data for the time that is being asked for
290 if ( timeStamp>=st->GetStartTime() && timeStamp<=st->GetEndTime() ) {
291 AliSplineFit *f = st->GetFit();
292 if (f) { // ok, looks like we have valid data/info
293 // let's check what the expected value at the time appears to be
d81e6423 294 Double_t val = f->Eval(timeHour);
621ff010 295
296 return val; // no point to move further in for loop, we have found the sensor we were looking for
297 }
298 } // time
299 }
300
301 } // loop over fTempArray
a42992b7 302
621ff010 303 // if we made it all here, it means that we didn't find the sensor we were looking for
304 // i.e. no good data
305 return fkErrorCode;
306
a42992b7 307}
308
309//________________________________________________________________
d81e6423 310Int_t AliEMCALCalibTimeDep::CalcCorrection()
311{ // OK, this is where the real action takes place - the heart of this class..
312 /* The philosophy is as follows:
313 0. Init corrections to 1.0 values
314 1: if we have LED info for the tower, use it
315 2. if not 1, we rely on LED info averaged over strip
316 3. if not 2 either, we try to use temperature info + APD bias and calibration info
317 */
318
319 // 0: Init
320 // how many SuperModules do we have?
82d90a2f 321 Int_t nSM = fCalibReference->GetNSuperModule();
d81e6423 322 // how many time-bins should we have for this run?
323 Int_t nBins = (Int_t) GetLengthOfRunInBins(); // round-down (from double to int)
220ed45a 324 Int_t binSize = (Int_t) (3600/fTimeBinsPerHour); // in seconds
d81e6423 325 // set up a reasonable default (correction = 1.0)
326 fCalibTimeDepCorrection->InitCorrection(nSM, nBins, 1.0);
220ed45a 327 fCalibTimeDepCorrection->SetStartTime(fStartTime);
328 fCalibTimeDepCorrection->SetNTimeBins(nBins);
329 fCalibTimeDepCorrection->SetTimeBinSize(binSize);
d81e6423 330
331 // 1+2: try with LED corrections
332 Int_t nRemaining = CalcLEDCorrection(nSM, nBins);
333
334 // 3: try with Temperature, if needed
335 if (nRemaining>0) {
336 nRemaining = CalcTemperatureCorrection(nSM, nBins);
337 }
338
339 return nRemaining;
a42992b7 340}
341
d81e6423 342
343//________________________________________________________________
344Double_t AliEMCALCalibTimeDep::GetTempCoeff(Double_t IDark, Double_t M) const
345{ // estimate the Temperature Coefficient, based on the dark current (IDark)
346 // and the gain (M), based on Catania parameterizations
347
348 Double_t P0 = fkTempCoeffP0Const + fkTempCoeffP0Factor * IDark;
349 Double_t P1 = fkTempCoeffP1Const + fkTempCoeffP1Factor * IDark;
350
351 Double_t TC = P0 + P1*M;
352
353 return TC;
354}
355
356/* Next come the methods that do the work in picking up all the needed info..*/
a42992b7 357//________________________________________________________________
358void AliEMCALCalibTimeDep::GetTemperatureInfo()
359{
360 // pick up Preprocessor output, based on fRun (most recent version)
361 AliCDBEntry* entry = AliCDBManager::Instance()->Get("EMCAL/Calib/Temperature", fRun);
362 if (entry) {
363 fTempArray = (AliEMCALSensorTempArray *) entry->GetObject();
364 }
365
621ff010 366 if (fTempArray) {
a42992b7 367 AliInfo( Form("NumSensors %d - IdDCS: first %d last %d",
368 fTempArray->NumSensors(),
369 fTempArray->GetFirstIdDCS(), fTempArray->GetLastIdDCS() ) );
621ff010 370 }
371 else {
372 AliWarning( Form("AliEMCALSensorTempArray not found!") );
a42992b7 373 }
374
375 return;
376}
d81e6423 377
378//________________________________________________________________
379Int_t AliEMCALCalibTimeDep::ScanTemperatureInfo()
380{// assign max/min time and temperature values
381
382 fMinTemp = 999; // init to some large value (999 deg C)
383 fMaxTemp = 0;
384 fMinTime = 2147483647; // init to a large value in the far future (0x7fffffff), year 2038 times..
385 fMaxTime = 0;
386
387 Int_t n = 0; // number of valid readings
388
389 for (int i=0; i<fTempArray->NumSensors(); i++) {
390
391 AliEMCALSensorTemp *st = fTempArray->GetSensor(i);
392
393 // check time ranges
394 if (fMinTime > st->GetStartTime()) { fMinTime = st->GetStartTime(); }
395 if (fMaxTime < st->GetEndTime()) { fMaxTime = st->GetEndTime(); }
396
397 // check temperature ranges
398 TGraph *g = st->GetGraph();
399 if (g) { // ok, looks like we have valid data/info
400 // let's check what the expected value at the time appears to be
401 if (fMinTemp > g->GetMinimum()) { fMinTemp = g->GetMinimum(); }
402 if (fMaxTemp < g->GetMaximum()) { fMaxTemp = g->GetMaximum(); }
403 n++;
404 }
405 } // loop over fTempArray
406
407 if (n>0) { // some valid data was found
408 return n;
409 }
410 else { // no good data
411 return (Int_t) fkErrorCode;
412 }
413
414}
415
416//________________________________________________________________
417void AliEMCALCalibTimeDep::GetCalibSignalInfo()
418{
419 // pick up Preprocessor output, based on fRun (most recent version)
420 AliCDBEntry* entry = AliCDBManager::Instance()->Get("EMCAL/Calib/LED", fRun);
421 if (entry) {
422 fCalibSignal = (AliCaloCalibSignal *) entry->GetObject();
423 }
424
425 if (fCalibSignal) {
426 AliInfo( Form("CalibSignal: NEvents %d NAcceptedEvents %d Entries %d AvgEntries LEDRefEntries %d LEDRefAvgEntries %d",
427 fCalibSignal->GetNEvents(), fCalibSignal->GetNAcceptedEvents(),
428 fCalibSignal->GetTreeAmpVsTime()->GetEntries(),
429 fCalibSignal->GetTreeAvgAmpVsTime()->GetEntries(),
430 fCalibSignal->GetTreeLEDAmpVsTime()->GetEntries(),
431 fCalibSignal->GetTreeLEDAvgAmpVsTime()->GetEntries() ) );
432 }
433 else {
434 AliWarning( Form("AliCaloCalibSignal not found!") );
435 }
436
437 return;
438}
439
440//________________________________________________________________
441void AliEMCALCalibTimeDep::GetBiasAPDInfo()
442{
443 // pick up Preprocessor output, based on fRun (most recent version)
444 AliCDBEntry* entry = AliCDBManager::Instance()->Get("EMCAL/Calib/BiasAPD", fRun);
445 if (entry) {
2f17a269 446 fBiasAPD = (AliEMCALBiasAPD *) entry->GetObject();
d81e6423 447 }
448
449 if (fBiasAPD) {
450 AliInfo( Form("BiasAPD: NSuperModule %d ", fBiasAPD->GetNSuperModule() ) );
451 }
452 else {
453 AliWarning( Form("AliEMCALBiasAPD not found!") );
454 }
455
456 return;
457}
458
459//________________________________________________________________
460void AliEMCALCalibTimeDep::GetCalibMapAPDInfo()
461{
462 // pick up Preprocessor output, based on fRun (most recent version)
463 AliCDBEntry* entry = AliCDBManager::Instance()->Get("EMCAL/Calib/MapAPD", fRun);
61917ab3 464 // stored object should be a TTree; read the info
d81e6423 465 if (entry) {
2f17a269 466 fCalibMapAPD = (AliEMCALCalibMapAPD *) entry->GetObject();
d81e6423 467 }
468
469 if (fCalibMapAPD) {
470 AliInfo( Form("CalibMapAPD: NSuperModule %d ", fCalibMapAPD->GetNSuperModule() ) );
471 }
472 else {
473 AliWarning( Form("AliEMCALCalibMapAPD not found!") );
474 }
475
476 return;
477}
478
479//________________________________________________________________
82d90a2f 480void AliEMCALCalibTimeDep::GetCalibReferenceInfo()
d81e6423 481{
482 // pick up Preprocessor output, based on fRun (most recent version)
483 AliCDBEntry* entry = AliCDBManager::Instance()->Get("EMCAL/Calib/MapAPD", fRun);
484 if (entry) {
82d90a2f 485 fCalibReference = (AliEMCALCalibReference *) entry->GetObject();
d81e6423 486 }
487
82d90a2f 488 if (fCalibReference) {
489 AliInfo( Form("CalibReference: NSuperModule %d ", fCalibReference->GetNSuperModule() ) );
d81e6423 490 }
491 else {
82d90a2f 492 AliWarning( Form("AliEMCALCalibReference not found!") );
d81e6423 493 }
494
495 return;
496}
497
498//________________________________________________________________
499Int_t AliEMCALCalibTimeDep::CalcLEDCorrection(Int_t nSM, Int_t nBins)
500{// Construct normalized ratios R(t)=LED(t)/LEDRef(t), for current time T and calibration time t0
501 // The correction factor we keep is c(T) = R(t0)/R(T)
82d90a2f 502 // T info from fCalibSignal, t0 info from fCalibReference
d81e6423 503
82d90a2f 504 // NOTE: for now we don't use the RMS info either from fCalibSignal or fCalibReference
d81e6423 505 // but one could upgrade this in the future
506 Int_t nRemaining = 0; // we count the towers for which we could not get valid data
507
508 // sanity check; same SuperModule indices for corrections as for regular calibrations
d81e6423 509 for (int i = 0; i < nSM; i++) {
82d90a2f 510 AliEMCALSuperModuleCalibReference * CalibReferenceData = fCalibReference->GetSuperModuleCalibReferenceNum(i);
2f17a269 511 AliEMCALSuperModuleCalibTimeDepCorrection * CalibTimeDepCorrectionData = fCalibTimeDepCorrection->GetSuperModuleCalibTimeDepCorrectionNum(i);
512
82d90a2f 513 int iSMRef = CalibReferenceData->GetSuperModuleNum();
2f17a269 514 int iSMCorr = CalibTimeDepCorrectionData->GetSuperModuleNum();
82d90a2f 515 if (iSMRef != iSMCorr) {
516 AliWarning( Form("AliEMCALCalibTimeDep - SuperModule index mismatch: %d != %d", iSMRef, iSMCorr) );
d81e6423 517 nRemaining = nSM * AliEMCALGeoParams::fgkEMCALCols * AliEMCALGeoParams::fgkEMCALRows * nBins;
518 return nRemaining;
519 }
520 }
521
522 int iSM = 0;
523 int iCol = 0;
524 int iRow = 0;
525 int iStrip = 0;
526 int iGain = 0;
527
528 // The fCalibSignal info is stored in TTrees
529 // Note that the time-bins for the TTree's may not exactly match with our correction time bins
530 int timeDiff = fCalibSignal->GetStartTime() - fStartTime; // in seconds
531 // fCalibSignal time info in seconds: Hour/fkSecToHour
532 // corrected for startTime difference: Hour/fkSecToHour + timeDiff
533 // converted into a time-bin we use: (Hour + timeDiff*fkSecToHour) * fTimeBinsPerHour
534
535 // values for R(T), size of TArray = nBins
536 // the [2] dimension below is for the low or high gain
537 TArrayF ampT[AliEMCALGeoParams::fgkEMCALModules][AliEMCALGeoParams::fgkEMCALCols][AliEMCALGeoParams::fgkEMCALRows][2];
538 TArrayF nT[AliEMCALGeoParams::fgkEMCALModules][AliEMCALGeoParams::fgkEMCALCols][AliEMCALGeoParams::fgkEMCALRows][2];
539 TArrayF ampLEDRefT[AliEMCALGeoParams::fgkEMCALModules][AliEMCALGeoParams::fgkEMCALLEDRefs][2];
540 TArrayF nLEDRefT[AliEMCALGeoParams::fgkEMCALModules][AliEMCALGeoParams::fgkEMCALLEDRefs][2];
541
542 // set up TArray's first
543 for (iSM = 0; iSM < AliEMCALGeoParams::fgkEMCALModules; iSM++) {
544 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
545 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
546 for (iGain = 0; iGain < 2; iGain++) {
547 // length of arrays
548 ampT[iSM][iCol][iRow][iGain].Set(nBins);
549 nT[iSM][iCol][iRow][iGain].Set(nBins);
550 // content of arrys
551 for (int j = 0; j < nBins; j++) {
552 ampT[iSM][iCol][iRow][iGain].AddAt(0, j);
553 nT[iSM][iCol][iRow][iGain].AddAt(0, j);
554 }
555 }
556 }
557 }//iCol
558 for (iStrip = 0; iStrip < AliEMCALGeoParams::fgkEMCALLEDRefs; iStrip++) {
559 for (iGain = 0; iGain < 2; iGain++) {
560 // length of arrays
561 ampLEDRefT[iSM][iStrip][iGain].Set(nBins);
562 nLEDRefT[iSM][iStrip][iGain].Set(nBins);
563 // content of arrys
564 for (int j = 0; j < nBins; j++) {
565 ampLEDRefT[iSM][iStrip][iGain].AddAt(0, j);
566 nLEDRefT[iSM][iStrip][iGain].AddAt(0, j);
567 }
568 }
569 }//iStrip
570 }
571
572 // OK, now loop over the TTrees and fill the arrays needed for R(T)
573 TTree *TAvg = fCalibSignal->GetTreeAvgAmpVsTime();
574 TTree *TLEDRefAvg = fCalibSignal->GetTreeAvgAmpVsTime();
575
576 int ChannelNum; // for regular towers
577 int RefNum; // for LED
578 double Hour;
579 double AvgAmp;
580
581 TAvg->SetBranchAddress("fChannelNum", &ChannelNum);
582 TAvg->SetBranchAddress("fHour", &Hour);
583 TAvg->SetBranchAddress("fAvgAmp",&AvgAmp);
584
585 int iBin = 0;
586 // counters for how many values were seen per SuperModule
587 int nCount[AliEMCALGeoParams::fgkEMCALModules] = {0};
588 int nCountLEDRef[AliEMCALGeoParams::fgkEMCALModules] = {0};
589
590 for (int ient=0; ient<TAvg->GetEntries(); ient++) {
591 TAvg->GetEntry(ient);
592 // figure out where this info comes from
593 fCalibSignal->DecodeChannelNum(ChannelNum, &iSM, &iCol, &iRow, &iGain);
594 iBin = (int) ( (Hour + timeDiff*fkSecToHour) * fTimeBinsPerHour ); // CHECK!!!
595 // add value in the arrays
596 ampT[iSM][iCol][iRow][iGain].AddAt( ampT[iSM][iCol][iRow][iGain].At(iBin)+AvgAmp, iBin );
597 nT[iSM][iCol][iRow][iGain].AddAt( nT[iSM][iCol][iRow][iGain].At(iBin)+1, iBin );
598 nCount[iSM]++;
599 }
600
601 TLEDRefAvg->SetBranchAddress("fRefNum", &RefNum);
602 TLEDRefAvg->SetBranchAddress("fHour", &Hour);
603 TLEDRefAvg->SetBranchAddress("fAvgAmp",&AvgAmp);
604
605 for (int ient=0; ient<TLEDRefAvg->GetEntries(); ient++) {
606 TLEDRefAvg->GetEntry(ient);
607 // figure out where this info comes from
608 fCalibSignal->DecodeRefNum(RefNum, &iSM, &iStrip, &iGain);
609 iBin = (int) ( (Hour + timeDiff*fkSecToHour) * fTimeBinsPerHour ); // CHECK!!!
610 // add value in the arrays
611 ampLEDRefT[iSM][iStrip][iGain].AddAt( ampLEDRefT[iSM][iStrip][iGain].At(iBin)+AvgAmp, iBin );
612 nLEDRefT[iSM][iStrip][iGain].AddAt( nLEDRefT[iSM][iStrip][iGain].At(iBin)+1, iBin );
613 nCountLEDRef[iSM]++;
614 }
615
616 // Normalize TArray values, and calculate average also
617 Float_t norm = 0; // extra var, for readability
618
619 for (iSM = 0; iSM < AliEMCALGeoParams::fgkEMCALModules; iSM++) {
620 if (nCount[iSM]>0 && nCountLEDRef[iSM]>0) { // avoid SuperModules with no data..
621 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
622 // iStrip = AliEMCALGeoParams::GetStripModule(iSM, iCol);
623 iStrip = (iSM%2==0) ? iCol/2 : AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - iCol/2; //TMP, FIXME
624 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
625 for (iGain = 0; iGain < 2; iGain++) {
626 // content of arrys
627 for (int j = 0; j < nBins; j++) {
628 if (nT[iSM][iCol][iRow][iGain].At(j) > 0) {
629 norm = ampT[iSM][iCol][iRow][iGain].At(j) / nT[iSM][iCol][iRow][iGain].At(j);
630 ampT[iSM][iCol][iRow][iGain].AddAt(norm, j); // AddAt = SetAt
631 }
632 }
633 }
634 }
635 }//iCol
636 for (iStrip = 0; iStrip < AliEMCALGeoParams::fgkEMCALLEDRefs; iStrip++) {
637 for (iGain = 0; iGain < 2; iGain++) {
638 for (int j = 0; j < nBins; j++) {
639 if (nLEDRefT[iSM][iStrip][iGain].At(j) > 0) {
640 norm = ampLEDRefT[iSM][iStrip][iGain].At(j) / nLEDRefT[iSM][iStrip][iGain].At(j);
641 ampLEDRefT[iSM][iStrip][iGain].AddAt(norm, j); // AddAt = SetAt
642 }
643 }
644 }
645 }//iStrip
646 }
647 } // iSM
648
649
650 // Calculate correction values, and store them
651 // set fkErrorCode values for those that could not be set
652
653 Float_t Rt0 = 0;
654 Float_t RT = 0;
655 Float_t correction = 0; // c(T) = R(t0)/R(T)
656 Int_t refGain = 0; // typically use low gain for LED reference amplitude (high gain typically well beyond saturation)
657
658 for (int i = 0; i < nSM; i++) {
82d90a2f 659 AliEMCALSuperModuleCalibReference * CalibReferenceData = fCalibReference->GetSuperModuleCalibReferenceNum(i);
2f17a269 660 AliEMCALSuperModuleCalibTimeDepCorrection * CalibTimeDepCorrectionData = fCalibTimeDepCorrection->GetSuperModuleCalibTimeDepCorrectionNum(i);
82d90a2f 661 iSM = CalibReferenceData->GetSuperModuleNum();
2f17a269 662
d81e6423 663 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
664 // iStrip = AliEMCALGeoParams::GetStripModule(iSM, iCol);
665 iStrip = (iSM%2==0) ? iCol/2 : AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - iCol/2; //TMP, FIXME
82d90a2f 666 refGain = CalibReferenceData->GetLEDRefHighLow(iStrip); // LED reference gain value used for reference calibration
667
d81e6423 668 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
669
670 // Calc. R(t0):
82d90a2f 671 AliEMCALCalibReferenceVal * refVal = CalibReferenceData->GetAPDVal(iCol, iRow);
672 iGain = refVal->GetHighLow(); // gain value used for reference calibration
d81e6423 673 // valid amplitude values should be larger than 0
82d90a2f 674 if (refVal->GetLEDAmp()>0 && CalibReferenceData->GetLEDRefAmp(iStrip)>0) {
675 Rt0 = refVal->GetLEDAmp() / CalibReferenceData->GetLEDRefAmp(iStrip);
d81e6423 676 }
677 else {
678 Rt0 = fkErrorCode;
679 }
680
82d90a2f 681 // Calc. R(T)
d81e6423 682 for (int j = 0; j < nBins; j++) {
683
684 // calculate R(T) also; first try with individual tower:
82d90a2f 685 // same gain as for reference calibration is the default
d81e6423 686 if (ampT[iSM][iCol][iRow][iGain].At(j)>0 && ampLEDRefT[iSM][iStrip][refGain].At(j)>0) {
687 // looks like valid data with the right gain combination
688 RT = ampT[iSM][iCol][iRow][iGain].At(j) / ampLEDRefT[iSM][iStrip][refGain].At(j);
689
690 // if data appears to be saturated, and we are in high gain, then try with low gain instead
82d90a2f 691 int newGain = iGain;
692 int newRefGain = refGain;
693 if ( ampT[iSM][iCol][iRow][iGain].At(j)>AliEMCALGeoParams::fgkOverflowCut && iGain==1 ) {
694 newGain = 0;
695 }
696 if ( ampLEDRefT[iSM][iStrip][refGain].At(j)>AliEMCALGeoParams::fgkOverflowCut && refGain==1 ) {
697 newRefGain = 0;
698 }
699
700 if (newGain!=iGain || newRefGain!=refGain) {
701 // compensate for using different gain than in the reference calibration
702 // we may need to have a custom H/L ratio value for each tower
703 // later, but for now just use a common value, as the rest of the code does..
704 RT = ampT[iSM][iCol][iRow][newGain].At(j) / ampLEDRefT[iSM][iStrip][newRefGain].At(j);
705
706 if (newGain<iGain) {
707 RT *= fHighLowGainFactor;
708 }
709 else if (newRefGain<refGain) {
710 RT /= fHighLowGainFactor;
711 }
d81e6423 712 }
713 }
714 else {
715 RT = fkErrorCode;
716 }
717
718 // Calc. correction factor
719 if (Rt0>0 && RT>0) {
720 correction = Rt0/RT;
721 }
722 else {
723 correction = fkErrorCode;
724 nRemaining++;
725 }
726
727 // Store the value
2f17a269 728 CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->AddAt(correction, j);
d81e6423 729 /* Check that
730 fTimeDepCorrection->SetCorrection(i, iCol, iRow, j, correction);
731 also works OK */
732 } // nBins
733 }
734 }
735 }
736
737 nRemaining = CalcLEDCorrectionStripBasis(nSM, nBins);
738 return nRemaining;
739}
740
741//________________________________________________________________
742Int_t AliEMCALCalibTimeDep::CalcLEDCorrectionStripBasis(Int_t nSM, Int_t nBins)
743{ // use averages for each strip if no good values exist for some single tower
744
745 // go over fTimeDepCorrection info
746 Int_t nRemaining = 0; // we count the towers for which we could not get valid data
747
d81e6423 748 // for calculating StripAverage info
749 int nValidTower = 0;
750 Float_t StripAverage = 0;
751 Float_t val = 0;
752
753 int iSM = 0;
754 int iCol = 0;
755 int iRow = 0;
756 int iStrip = 0;
757 int firstCol = 0;
758 int lastCol = 0;
759
760 for (int i = 0; i < nSM; i++) {
2f17a269 761 AliEMCALSuperModuleCalibTimeDepCorrection * CalibTimeDepCorrectionData = fCalibTimeDepCorrection->GetSuperModuleCalibTimeDepCorrectionNum(i);
762 iSM = CalibTimeDepCorrectionData->GetSuperModuleNum();
763
d81e6423 764 for (int j = 0; j < nBins; j++) {
765
766 nValidTower = 0;
767 StripAverage = 0;
768
769 for (iStrip = 0; iStrip < AliEMCALGeoParams::fgkEMCALLEDRefs; iStrip++) {
770 firstCol = iStrip*2;
771 if ((iSM%2)==1) { // C side
772 firstCol = (AliEMCALGeoParams::fgkEMCALLEDRefs-1 - iStrip)*2;
773 }
774 lastCol = firstCol+1;
775
776 for (iCol = firstCol; iCol <= lastCol; iCol++) {
777 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
2f17a269 778 val = CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->At(j);
d81e6423 779 if (val>0) { // valid value; error code is negative
780 StripAverage += val;
781 nValidTower++;
782 }
783 }
784 }
785
786 // calc average over strip
787 if (nValidTower>0) {
788 StripAverage /= nValidTower;
789 for (iCol = firstCol; iCol <= lastCol; iCol++) {
790 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
2f17a269 791 val = CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->At(j);
d81e6423 792 if (val<0) { // invalid value; error code is negative
2f17a269 793 CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->AddAt(val, j);
d81e6423 794 }
795 }
796 }
797 }
798 else { // could not fill in unvalid entries
799 nRemaining += 2*AliEMCALGeoParams::fgkEMCALRows;
800 }
801
802 } // iStrip
803 } // j, bins
804 } // iSM
805
806 return nRemaining;
807}
808
809//________________________________________________________________
810Int_t AliEMCALCalibTimeDep::CalcTemperatureCorrection(Int_t nSM, Int_t nBins)
811{ // OK, so we didn't have valid LED data that allowed us to do the correction only
812 // with that info.
813 // So, instead we'll rely on the temperature info and try to do the correction
814 // based on that instead.
815 // For this, we'll need the info from 3 classes (+temperature array), and output the values in a 4th class
816 Int_t nRemaining = 0;
817
d81e6423 818 int iSM = 0;
819 int iCol = 0;
820 int iRow = 0;
821
822 Double_t TempCoeff[AliEMCALGeoParams::fgkEMCALCols][AliEMCALGeoParams::fgkEMCALRows];
823 memset(TempCoeff, 0, sizeof(TempCoeff));
824 Float_t MGain = 0;
825 Double_t correction = 0;
220ed45a 826 Double_t secondsPerBin = (3600/fTimeBinsPerHour);
d81e6423 827
828 for (int i = 0; i < nSM; i++) {
2f17a269 829 AliEMCALSuperModuleCalibTimeDepCorrection * CalibTimeDepCorrectionData = fCalibTimeDepCorrection->GetSuperModuleCalibTimeDepCorrectionNum(iSM);
830 iSM = CalibTimeDepCorrectionData->GetSuperModuleNum();
831
82d90a2f 832 AliEMCALSuperModuleCalibReference * CalibReferenceData = fCalibReference->GetSuperModuleCalibReferenceNum(iSM);
2f17a269 833 AliEMCALSuperModuleCalibMapAPD * CalibMapAPDData = fCalibMapAPD->GetSuperModuleCalibMapAPDNum(iSM);
834 AliEMCALSuperModuleBiasAPD * BiasAPDData = fBiasAPD->GetSuperModuleBiasAPDNum(iSM);
d81e6423 835
836 // first calculate the M=Gain values, and TemperatureCoeff, for all towers in this SuperModule, from BiasAPD and CalibMapAPD info
837 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
838 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
2f17a269 839 AliEMCALCalibMapAPDVal * mapAPD = CalibMapAPDData->GetAPDVal(iCol, iRow);
840 MGain = fCalibMapAPD->GetGain(mapAPD->GetPar(0), mapAPD->GetPar(1), mapAPD->GetPar(2),
841 BiasAPDData->GetVoltage(iCol, iRow));
842 TempCoeff[iCol][iRow] = GetTempCoeff(mapAPD->GetDarkCurrent(), MGain);
d81e6423 843 }
844 }
845
82d90a2f 846 // figure out what the reference temperature is, from fCalibReference
d81e6423 847 Double_t ReferenceTemperature = 0;
848 int nVal = 0;
849 for (int iSensor = 0; iSensor<AliEMCALGeoParams::fgkEMCALTempSensors ; iSensor++) {
82d90a2f 850 if (CalibReferenceData->GetTemperature(iSensor)>0) { // hopefully OK value
851 ReferenceTemperature += CalibReferenceData->GetTemperature(iSensor);
d81e6423 852 nVal++;
853 }
854 }
855
856 if (nVal>0) {
857 ReferenceTemperature /= nVal; // valid values exist, we can look into corrections
858
859 for (int j = 0; j < nBins; j++) {
860
861 // what is the timestamp in the middle of this bin? (0.5 is for middle of bin)
862 UInt_t timeStamp = fStartTime + (UInt_t)((j+0.5)*secondsPerBin);
863 // get the temperature at this time; use average over whole SM for now (TO BE CHECKED LATER - if we can do better with finer grained info)
864 Double_t SMTemperature = GetTemperatureSM(iSM, timeStamp);
865
866 Double_t TemperatureDiff = ReferenceTemperature - SMTemperature; // old vs new
867 // if the new temperature is higher than the old/reference one, then the gain has gone down
868 if (fabs(TemperatureDiff)>fTemperatureResolution) {
869 // significant enough difference that we need to consider it
870
871 // loop over all towers; effect of temperature change will depend on gain for this tower
872 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
873 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
874
875 correction = TemperatureDiff * TempCoeff[iCol][iRow];
2f17a269 876 CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->AddAt(correction, j);
d81e6423 877 }
878 }
879
880 } // if noteworthy temperature change
881 else { // just set correction values to 1.0
882 correction = 1;
883 for (iCol = 0; iCol < AliEMCALGeoParams::fgkEMCALCols; iCol++) {
884 for (iRow = 0; iRow < AliEMCALGeoParams::fgkEMCALRows; iRow++) {
2f17a269 885 CalibTimeDepCorrectionData->GetCorrection(iCol,iRow)->AddAt(correction, j);
d81e6423 886 }
887 }
888 } // else
889 } // j, Bins
890
891 } // if reference temperature exist
892 else { // could not do the needed check.. signal that in the return code
893 nRemaining += AliEMCALGeoParams::fgkEMCALCols * AliEMCALGeoParams::fgkEMCALRows * nBins;
894 }
895 } // iSM
896
897 return nRemaining;
898}
899