ATLAS Offline Software
Loading...
Searching...
No Matches
TileLaserTimingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Athena includes
7#include "CoralBase/Blob.h"
8#include "CoralBase/AttributeListSpecification.h"
12
13// Tile includes
14#include "TileLaserTimingTool.h"
20
21#include "TFile.h"
22#include "TTree.h"
23#include "TF1.h"
24#include "TObjArray.h"
25#include <TROOT.h>
26
27#include <cmath>
28
29//const unsigned NPmts = 48;
30
31template<class _T> inline _T sqr(const _T &data) { return data * data; }
32
33inline int imax(int i, int j) { return i < j ? j : i; }
34
36 : TimeDiffHisto(("pmt_dtime"+id).c_str(),("pmt_dtime"+id).c_str(),1200,-60,60)
37 , TimeDiffNoCFCorrHisto(("dtimeNoCorr"+id).c_str(),("dtimeNoCorr"+id).c_str(),1200,-60,60)
38
40 , timeHisto(("time" + id).c_str(), ("time" + id).c_str(), 200, -100, 100)
41 , eneHisto(("energy" + id).c_str(), ("energy" + id).c_str(), 300, 0., 300.)
42 , gainHisto(("gain" + id).c_str(), ("gain" + id).c_str(), 2, 0, 2)
43#endif
44
45#ifdef TileLaserTimingPMT0Mon
46 , TimeDiffHistoHigh(("dtime" + id + "hi").c_str(), ("dtime" + id + "hi").c_str(), 200, -40, 40)
47 , TimeDiffHistoLow(("dtime" + id + "lo").c_str(), ("dtime" + id + "lo").c_str(), 200, -60, 60)
48#endif
49
50#ifdef TileLaserTimingMonPulse
51 , pulseShapeHigh(("pulseShape_" + id + "hi").c_str(), ("pulseShape_" + id + "hi").c_str(), 400, -200., 300., 0, 100000.)
52 , pulseShapeLow(("pulseShape_" + id + "lo").c_str(), ("pulseShape_" + id + "lo").c_str(), 400, -200., 300., 0, 100000.)
53#endif
54
55 , TimeDiffResHis(("dtimeRes"+id).c_str(),("dtimeRes"+id).c_str(),1000,-40.,40.)
56 , time(0.0)
57
58#ifdef TileLaserTimingPMT0
59 , dtime(0.0)
60 , dtimeNoCFCorr(0.0)
61#endif
62
63 , energy(0.0)
64{
65}
66
74
79
81 m_mean_time = 0;
82 m_mean_rms = 0;
83
84 for (int i = 0; i < m_N_active; ++i) m_mean_time += m_ch_time[i];
85
87
88 for (int i = 0; i < m_N_active; ++i) m_mean_rms += sqr(m_ch_time[i] - m_mean_time);
89
90 m_mean_rms = m_mean_rms / ((float) m_N_active);
91 m_mean_rms = sqrt(m_mean_rms);
92}
93
95 : Digi0TimeDiffHisto(("TimeDiff" + id).c_str(), ("TimeDiff" + id).c_str(), 2000, -100., 100.)
96 , Digi0Time(("Digi0Time" + id).c_str(), ("Digi0Time" + id).c_str(), 2000, -100., 100.)
98{
99
100 for (int i = 0; i < 48; ++i) {
101 std::ostringstream sout;
102 sout << id << '_' << i;
103 pmtd[i] = new PMTData(sout.str());
104 }
105}
106
107
108// LBA | LBC
109// EBA | EBC
110float const TileLaserTimingTool::s_fiberLength[2][48] = {{167.1,167.1,178.7,178.7,190.3,190.3,201.9,201.9,213.5,213.5,
111 225.1,225.1,236.7,236.7,248.3,248.3,259.9,259.9,271.5,271.5,
112 283.1,283.1,294.7,294.7,201.9,201.9,213.5,213.5,225.1,225.1,
113 236.7,236.7,248.3,248.3,259.9,259.9,271.5,271.5,283.1,283.1,
114 294.7,294.7,306.3,306.3,317.9,317.9,329.6,329.6},
115
116 { 51.1, 51.1, 62.7, 62.7, 74.3, 74.3, 85.9, 85.9, 97.5, 97.5,
117 109.1,109.1,120.7,120.7,132.3,132.3,143.9,143.9,143.9,143.9,
118 167.1,167.1,178.1,178.1,178.1,178.1,178.1,178.1,213.5,213.5,
119 213.5,213.5,236.7,236.7,236.7,236.7,259.9,259.9,259.9,259.9,
120 283.1,283.1,294.7,294.7,294.7,294.7,294.7,294.7}};
121
122TileLaserTimingTool::TileLaserTimingTool(const std::string& type, const std::string& name, const IInterface* pParent)
123 : AthAlgTool(type, name, pParent)
124 , m_tileHWID(nullptr)
125 , m_cabling(nullptr)
126 , m_nevts(0)
127 , m_gaussf(nullptr)
128{
129
130 declareInterface<ITileCalibTool>( this );
131
132 declareProperty("NtupleID", m_ntupleID = "h3000");
133 declareProperty("FiberLightSpeed", m_fiberLightSpeed);
134 declareProperty("NSamples", m_nSamples = 9);
135 declareProperty("EneLowLimitPulseShape", m_eneLowLimitPulseShape = 0.000001);
136 declareProperty("ReferenceDrawer", m_refDrawer = 39);
137
138 declareProperty("UseMeanChannelOffset", m_useMeanChannelOffset = true);
139 declareProperty("MaxTimeDiff", m_maxTimeDiff = 10000.);
140 declareProperty("UsePMT0AsDskewRef", m_usePMT0AsDskewRef = true);
141
142#ifdef TileLaserTimingMonPulse
143 // create mon histos
144 m_h1_time_check = new TH1F("h1_time_check", "Time(Tfit based) - Time(cispar based)", 1000, -200., 200.);
145 m_h2_time_check = new TH2F("h2_time_check", "Time(Tfit based) vs Time(cispar based)", 1000, -200., 200., 1000, -200., 200.);
146
147 m_PulseShapeHigh = new TProfile("pulse_shape_HG", "pulse shape HG", 400, -200., 300., 0, 100000.);
148 m_PulseShapeLow = new TProfile("pulse_shape_LG", "pulse shape LG", 400, -200., 300., 0, 100000.);
149#endif
150
151 // creating multi-dim arrays on the heap and initialize all elements to zeros
153
154 m_DrawerOffset = new float[NROS][NDRAWERS]();
155 m_DrawerOffsetError = new float[NROS][NDRAWERS]();
156
157 m_ChannelOffset = new float[NROS][NDRAWERS][NCHANNELS]();
159
160 m_ADCAmplitude = new float[NROS][NDRAWERS][NCHANNELS]();
161
162 m_PedestalMean = new float[NROS][NDRAWERS][NCHANNELS]();
163 m_PedestalSigma = new float[NROS][NDRAWERS][NCHANNELS]();
164
165 m_TimeDiffMean = new float[NROS][NDRAWERS][NCHANNELS]();
167 m_TimeDiffSigma = new float[NROS][NDRAWERS][NCHANNELS]();
168
169 m_MeanOddPmtTdiffPMT0 = new float[NROS][NDRAWERS]();
170 m_OddPmtCounterPMT0 = new int[NROS][NDRAWERS]();
171 m_MeanEvenPmtTdiffPMT0 = new float[NROS][NDRAWERS]();
172 m_EvenPmtCounterPMT0 = new int[NROS][NDRAWERS]();
173 m_EvenOddTimeDiffPMT0 = new float[NROS][NDRAWERS]();
174
175#ifdef TileLaserTimingPMT0Mon
176 m_TimeDiffHighMean = new float[NROS][NDRAWERS][NCHANNELS]();
177 m_TimeDiffHighMeanError = new float[NROS][NDRAWERS][NCHANNELS]();
178 m_TimeDiffHighSigma = new float[NROS][NDRAWERS][NCHANNELS]();
179
180 m_TimeDiffLowMean = new float[NROS][NDRAWERS][NCHANNELS]();
181 m_TimeDiffLowMeanError = new float[NROS][NDRAWERS][NCHANNELS]();
182 m_TimeDiffLowSigma = new float[NROS][NDRAWERS][NCHANNELS]();
183
184 m_TimeDiffNoCFCorrMean = new float[NROS][NDRAWERS][NCHANNELS]();
185 m_TimeDiffNoCFCorrMeanError = new float[NROS][NDRAWERS][NCHANNELS]();
186 m_TimeDiffNoCFCorrSigma = new float[NROS][NDRAWERS][NCHANNELS]();
187#endif
188
189 m_FiberLength = new float[NROS][NDRAWERS][NCHANNELS]();
190
191#ifdef TileLaserTimingMon
192 m_TimeDiffPMTDigi0 = new float[NROS][NDRAWERS][NCHANNELS]();
193 m_FiberCorrection = new float[NROS][NDRAWERS][NCHANNELS]();
194 m_IsConnected = new int[NROS][NDRAWERS][NCHANNELS]();
195
196 m_MeanOddPmtTdiff = new float[NROS][NDRAWERS]();
197 m_OddPmtCounter = new int[NROS][NDRAWERS]();
198 m_MeanEvenPmtTdiff = new float[NROS][NDRAWERS]();
199 m_EvenPmtCounter = new int[NROS][NDRAWERS]();
200
201 m_EvenOddTimeDiff = new float[NROS][NDRAWERS]();
202#endif
203
204 m_DSkewSet = new float[NROS][NDRAWERS][NDIGI]();
205 m_DigiMean = new float[NROS][NDRAWERS][NDIGI]();
206}
207
209
210 delete[] m_drawerData;
211 delete[] m_DrawerOffset;
212 delete[] m_DrawerOffsetError;
213 delete[] m_ChannelOffset;
214 delete[] m_ChannelOffsetError;
215 delete[] m_ADCAmplitude;
216 delete[] m_PedestalMean;
217 delete[] m_PedestalSigma;
218 delete[] m_TimeDiffMean;
219 delete[] m_TimeDiffMeanError;
220 delete[] m_TimeDiffSigma;
221 delete[] m_MeanOddPmtTdiffPMT0;
222 delete[] m_OddPmtCounterPMT0;
223 delete[] m_MeanEvenPmtTdiffPMT0;
224 delete[] m_EvenPmtCounterPMT0;
225 delete[] m_EvenOddTimeDiffPMT0;
226#ifdef TileLaserTimingPMT0Mon
227 delete[] m_TimeDiffHighMean;
228 delete[] m_TimeDiffHighMeanError;
229 delete[] m_TimeDiffHighSigma;
230 delete[] m_TimeDiffLowMean;
231 delete[] m_TimeDiffLowMeanError;
232 delete[] m_TimeDiffLowSigma;
233 delete[] m_TimeDiffNoCFCorrMean;
234 delete[] m_TimeDiffNoCFCorrMeanError;
235 delete[] m_TimeDiffNoCFCorrSigma;
236#endif
237
238 delete[] m_FiberLength;
239
240#ifdef TileLaserTimingMon
241 delete[] m_TimeDiffPMTDigi0;
242 delete[] m_FiberCorrection;
243 delete[] m_IsConnected;
244 delete[] m_MeanOddPmtTdiff;
245 delete[] m_OddPmtCounter;
246 delete[] m_MeanEvenPmtTdiff;
247 delete[] m_EvenPmtCounter;
248 delete[] m_EvenOddTimeDiff;
249#endif
250 delete[] m_DSkewSet;
251 delete[] m_DigiMean;
252}
253
254
255
257
258 ATH_MSG_INFO( "initialize()" );
259
260 // get TileHWID helper
261 CHECK( detStore()->retrieve(m_tileHWID) );
262
263 // get the timing tool
264 CHECK( m_tileToolTiming.retrieve() );
265
266 // get TileCabling Service
268
269 m_nevts = 0;
270
271 ATH_CHECK( m_eventInfoKey.initialize() );
272 ATH_CHECK( m_rawChannelContainerKey.initialize() );
273 ATH_CHECK( m_digitsContainerKey.initialize() );
274
275 // gauss fit function
276 m_gaussf = new TF1("GainGauss", "[0]*exp(- (x-[1])*(x-[1])/(2*[2]*[2]))", -60, 60);
277
278 ATH_MSG_DEBUG( "initialize() ready " );
279
290
291 return StatusCode::SUCCESS;
292}
293
294StatusCode TileLaserTimingTool::initNtuple(int runNumber, int runType, TFile * rootFile) {
295
296 ATH_MSG_INFO( "initNtuple(" << runNumber << "," << runType << "," << rootFile << ")" );
297
298 return StatusCode::SUCCESS;
299}
300
301// conv factor from low gain to high gain
302//const float LG2HG = 64.;
303
308
309 ATH_MSG_DEBUG( "execute()" );
310
311 gROOT->cd();
312
313 // Get event's CIS parameters
314 // QQQ: const uint32_t *cispar = m_beamInfo->cispar();
315 // QQQ: const uint32_t dac = cispar[6];
316 // QQQ: const uint32_t phase = cispar[5];
317 // QQQ: const uint32_t cap = cispar[7];
318
319 // Get EventInfo
321 ATH_CHECK( eventInfo.isValid() );
322
323
324 // QQQ: const unsigned runNumber = eventInfo->runNumber();
325 // QQQ: const unsigned eventNumber = eventInfo->eventNumber();
326
327 // Check if event should be used in calibration
328 bool pass = true;
329
330 // Get TileRawChannelContainer
332 ATH_CHECK( container.isValid() );
333
334 // Get TileDigitsContainer
336 ATH_CHECK( digitsCnt.isValid() );
337
338 // Create iterator over RawChannelContainer
339 TileRawChannelContainer::const_iterator itColl = (*container).begin();
340 TileRawChannelContainer::const_iterator itCollEnd = (*container).end();
342
343 // tmp vars
344 const TileDigitsCollection *digiColl = nullptr;
345 const TileDigits* digits;
346 const TileRawChannel *rawch = nullptr;
347 float dtime, dtimeNoCFCorr;
348
349#ifdef TileLaserTimingMonPulse
350 float f_SampleTime, f_phase1, f_phase2, f_time, f_tfittime;
351#endif
352
353 size_t colls;
354 int Nconnected;
355 float ChannelOffset;
356
357 DrawerData *ddata = nullptr;
358
359 unsigned frag;
360 if (pass) {
361 m_nevts++;
362
363 // Go through all TileRawChannelCollections
364 for (; itColl != itCollEnd; ++itColl) {
365 // Get the digits collection for the drawer corresponding to the raw channel
366 frag = (*itColl)->identify();
367 const auto *digiCollIt = digitsCnt->indexFindPtr(digitsCnt->hashFunc()(frag));
368 if (digiCollIt == nullptr) {
369 ATH_MSG_ERROR( " unable to get TileDigitsCollection for drawer:" << drawerIdStr(frag) );
370
371 } else {
372 digiColl = digiCollIt;
373 colls = (*itColl)->size();
374 ATH_MSG_VERBOSE( "execute() colls:" << colls
375 << " digiColl->size:" << digiColl->size()
376 << " drawer:" << drawerIdStr((*itColl)->identify()) );
377
378 if (digiColl->size() != colls) {
379 ATH_MSG_ERROR( " size of TileDigitsCollection and TileRawChannelCollection differ for drawer:" << drawerIdStr((*itColl)->identify()) );
380
381 } else {
382 // ZZZ: Assume the first RawChannel in the collection corresponds to PMT 0
383 // ZZZ: if this is not the case (for some reason) there will be a nasty segflt
384
385 // get drawer HWID
386 HWIdentifier dhwid = drawerId((*itColl)->identify());
387 // LBA=1 LBC=2 EBA=3 EBC=4
388 int ros = m_tileHWID->ros(dhwid);
389 // 0 to 63
390 int drawer = m_tileHWID->drawer(dhwid);
391 // get and create DrawerData if needed, cannot be null
392 ddata = drawerData(ros, drawer);
393 // store ref to first PMT
394 PMTData &pmt0data = *ddata->pmtd[0];
395
396 for (size_t i = 0; i < colls; ++i) {
397 digits = digiColl->at(i);
398 rawch = (*itColl)->at(i);
399
400 // require both digits and raw channels with equal ids
401 if (!digits || !rawch || (digits->identify() != rawch->identify())) {
402 if (!digits) {
403 ATH_MSG_ERROR( " no TileDigits for drawer:" << drawerIdStr((*itColl)->identify()) );
404 }
405
406 if (!rawch) {
407 ATH_MSG_ERROR( " no TileRawChannel for drawer:" << drawerIdStr((*itColl)->identify()) );
408 }
409
410 if (rawch && digits) {
411 ATH_MSG_ERROR( " no id mismatch for drawer:" << drawerIdStr((*itColl)->identify()) );
412 }
413
414 } else {
415 // get hardware id to identify adc
416 HWIdentifier hwid = rawch->adc_HWID();
417 // int ros = m_tileHWID->ros(hwid); // LBA=1 LBC=2 EBA=3 EBC=4
418 // int drawer = m_tileHWID->drawer(hwid); // 0 to 63
419 const int chan = m_tileHWID->channel(hwid); // 0 to 47 channel not PMT
420 const int gain = m_tileHWID->adc(hwid); // low=0 high=1
421 const int ipmt = channel2PMT(ros, chan);
422
423 // store Fit data
424 PMTData &pmtdata = *ddata->pmtd[ipmt];
425 pmtdata.time = rawch->time();
426 pmtdata.energy = rawch->amplitude();
427 pmtdata.pedestal.add(rawch->pedestal());
428
429 // in case of the first PMT (i.e. 0) this will be 0 as per definition
430 dtimeNoCFCorr = pmtdata.time - pmt0data.time;
431 dtime = dtimeNoCFCorr - fiberCorrection(ros, ipmt);
432 pmtdata.TimeDiffHisto.Fill(dtime);
433
434#ifdef TileLaserTimingPMT0
435 pmtdata.TimeDiffNoCFCorrHisto.Fill(dtimeNoCFCorr);
436
437 if(gain == 0) pmtdata.TimeDiffHistoLow.Fill(dtime);
438 else pmtdata.TimeDiffHistoHigh.Fill(dtime);
439#endif
440
441#ifdef TileLaserTimingMon
442 pmtdata.timeHisto.Fill(pmtdata.time);
443 pmtdata.eneHisto.Fill(pmtdata.energy);
444 pmtdata.gainHisto.Fill(gain);
445#endif
446
447 // pulse data-->
448#ifdef TileLaserTimingMonPulse
449 if(isConnectedChan(ros, chan)) {
450 std::vector<float> sample = digits->samples();
451 if(sample.size() != m_nSamples) {
452 ATH_MSG_ERROR( " sample size mismatch for drawer:" << drawerIdStr(frag)
453 <<" in:" << sample.size() << " expected:" << m_nSamples );
454 } else {
455 for (unsigned jsample = 0; jsample < m_nSamples; ++jsample) {
456 f_SampleTime = ((float) jsample) * 25.;
457 f_phase1 = (25. * ((float) phase)) / (30. * 8);
458 f_phase2 = -pmtdata.time;
459 f_time = f_SampleTime + f_phase1 - 100;
460 f_tfittime = f_SampleTime + f_phase2 - 100;
461 if (phase >= 160) {
462 f_time -= 25;
463 f_phase1 -= 25;
464 }
465
466 if (phase < 140 || phase > 160) {
467 // if Low gain convert to the HG scale
468 if (gain == 0) {
469 m_h1_time_check->Fill(f_phase1 - f_phase2);
470 m_h2_time_check->Fill(f_phase1, f_phase2);
471
472 if (fabs(pmtdata.energy) > m_eneLowLimitPulseShape) {
473 pmtdata.pulseShapeLow.Fill(f_tfittime, (LG2HG * (sample[jsample] - rawch->pedestal())));
474 }
475 }
476 //HG
477 else if (fabs(pmtdata.energy) > m_eneLowLimitPulseShape) {
478 pmtdata.pulseShapeHigh.Fill(f_tfittime, (sample[jsample] - rawch->pedestal()));
479 }
480 } // if Cispar not in 140->160 (range with time jitter,
481 //difficult to handle for smooth pulse shape
482 }
483 } // end loop over jsample
484 } // end if PMT is connected
485#endif
486 // <--pulse data
487
488 } // else: ok digits and raw channels
489 } // end collection loop
490
491 //=====================================================================================
492 //=== Compute mean Tfit (corrected for laser fiber length) over the first digitizer ===
493 //=====================================================================================
494 Nconnected = 0;
495 ddata->FarDigitizerMeanTime = 0.;
496 for (int ipmt = 0; ipmt < 6; ++ipmt) {
497 if (isConnectedPMT(ros, ipmt)) {
498 ddata->FarDigitizerMeanTime += (ddata->pmtd[ipmt]->time - fiberCorrection(ros, ipmt));
499 Nconnected++;
500 }
501 }
502 if (Nconnected)
503 ddata->FarDigitizerMeanTime /= (float) Nconnected;
504
505#ifdef TileLaserTimingMon
506 ddata->Digi0Time.Fill(ddata->FarDigitizerMeanTime);
507#endif
508
509 if (msgLvl(MSG::VERBOSE) && (ros == 1) && (drawer == 1)) {
510 ATH_MSG_VERBOSE( " ddata->FarDigitizerMeanTime:" << ddata->FarDigitizerMeanTime );
511 }
512
513 //============================================================================
514 //=== Calculate residuals. Fill histos with time diff b/w PMT i and digi 1 ===
515 //============================================================================
516 for (int ipmt = 0; ipmt < NCHANNELS; ipmt++) {
517 if (isConnectedPMT(ros, ipmt)) {
518 ChannelOffset = -(ddata->pmtd[ipmt]->time - fiberCorrection(ros, ipmt) - ddata->FarDigitizerMeanTime);
519 ddata->pmtd[ipmt]->TimeDiffResHis.Fill(ChannelOffset);
520 if (msgLvl(MSG::VERBOSE) && (ros == 1) && (drawer == 1)) {
521 ATH_MSG_VERBOSE( " ipmt:" << ipmt << " ChannelOffset:" << ChannelOffset );
522 }
523 }
524 }
525
526 } // else: matching digits and raw channel collections
527 }
528 } // end container loop
529
530 //=====================================================================================
531 //=== this histogram contains the difference between first digitizer of drawer 1 and drawer 2: drawer offset
532 //=====================================================================================
533 for (unsigned int ros = 1; ros < TileCalibUtils::MAX_ROS; ++ros) {
534 if (drawerData(ros, m_refDrawer)) {
535 DrawerData &drawer0data = *drawerData(ros, m_refDrawer);
536 for (unsigned int drawer = 0; drawer < TileCalibUtils::MAX_DRAWER; ++drawer) {
537 if ((drawer != m_refDrawer) && drawerData(ros, drawer)) {
538 DrawerData &ddata = *drawerData(ros, drawer);
539 ddata.Digi0TimeDiffHisto.Fill( ddata.FarDigitizerMeanTime - drawer0data.FarDigitizerMeanTime);
540
541 if (msgLvl(MSG::VERBOSE) && (ros == 1) && (drawer == 1)) {
542 ATH_MSG_VERBOSE( " drawerdiff:" << ddata.FarDigitizerMeanTime - drawer0data.FarDigitizerMeanTime );
543 }
544 }
545 }
546 }
547 }
548 }
549
550 return StatusCode::SUCCESS;
551}
552
554
555 ATH_MSG_INFO( "finalizeCalculations()" );
556
557 gROOT->cd();
558
559 float fmean, fdummy, fchi2, fmeanerr;
560
561 for (unsigned int ros = 1; ros < TileCalibUtils::MAX_ROS; ++ros) {
562 for (unsigned int drawer = 0; drawer < TileCalibUtils::MAX_DRAWER; ++drawer) {
563 DrawerData &drawerd = *drawerData(ros, drawer);
564
565 for (int ipmt = 0; ipmt < NCHANNELS; ++ipmt) {
566 PMTData &pmtd = *drawerd.pmtd[ipmt];
567 // to simplify the root analysis, store the fiber length, not really neccessary
568 m_FiberLength[ros][drawer][ipmt] = fiberLength(ros, ipmt);
569#ifdef TileLaserTimingMon
570 m_FiberCorrection[ros][drawer][ipmt] = fiberCorrection(ros, ipmt);
571 m_IsConnected[ros][drawer][ipmt] = isConnectedPMT(ros, ipmt);
572#endif
573 //==========================================================================================
574 //==== Pulse shapes ====
575
576 // use the number of entries in the histos as the number of passed events for high/low
577
578#ifdef TileLaserTimingMonPulse
579 if(pmtd.TimeDiffHistoLow.GetEntries() > 0.99 * m_nevts) {
580 m_PulseShapeLow->Add(&pmtd.pulseShapeLow);
581 }
582
583 if(pmtd.TimeDiffHistoHigh.GetEntries() > 0.99 * m_nevts) {
584 m_PulseShapeHigh->Add(&pmtd.pulseShapeHigh);
585 }
586#endif
587
588 if (ipmt > 0) {
589 //==================================================================
590 // Fit time difference regardless of gain, to derive standard Dskews
591 //==================================================================
592 if (isConnectedPMT(ros, ipmt)) {
593 fitGauss(pmtd.TimeDiffHisto, m_TimeDiffMean[ros][drawer][ipmt], m_TimeDiffSigma[ros][drawer][ipmt], m_TimeDiffMeanError[ros][drawer][ipmt]);
594 }
595
596#ifdef TileLaserTimingPMT0
597 //===========================================================
598 //=== Fit time difference without clear fiber corrections ===
599 //===========================================================
600 if(isConnectedPMT(ros, ipmt)) {
601 fitGauss(pmtd.TimeDiffNoCFCorrHisto, m_TimeDiffNoCFCorrMean[ros][drawer][ipmt], m_TimeDiffNoCFCorrSigma[ros][drawer][ipmt], m_TimeDiffNoCFCorrMeanError[ros][drawer][ipmt]);
602 }
603
604 //================================================================================
605 //==== Fit gauss to time differences in all gains/ low gain/ high gain in all PMTs
606 //================================================================================
607
608 fitGauss(pmtd.TimeDiffHistoLow, m_TimeDiffLowMean[ros][drawer][ipmt], m_TimeDiffLowSigma[ros][drawer][ipmt], m_TimeDiffLowMeanError[ros][drawer][ipmt]);
609
610 //------------------------------------- For high gain --------------------------------------
611
612 fitGauss(pmtd.TimeDiffHistoHigh, m_TimeDiffHighMean[ros][drawer][ipmt], m_TimeDiffHighSigma[ros][drawer][ipmt], m_TimeDiffHighMeanError[ros][drawer][ipmt]);
613#endif
614 }
615
616 //==================================================================================
617 //=== Fit mean value of time difference b/w drawer_i(pmt_j) and drawer_i(digi_1) ===
618 //==================================================================================
619
620 // TODO: previous values on error
621 if (isConnectedPMT(ros, ipmt)) {
623 m_TimeDiffPMTDigi0[ros][drawer][ipmt] = m_ChannelOffset[ros][drawer][ipmt] = pmtd.TimeDiffResHis.GetMean();
624 m_ChannelOffsetError[ros][drawer][ipmt] = pmtd.TimeDiffResHis.GetMeanError();
625 } else {
626 fitGauss2(pmtd.TimeDiffResHis, fmean, fdummy, fchi2, fmeanerr, 1.0, 3.0);
627
628 if (fchi2 > 500) {
629 ATH_MSG_WARNING( "pmt # " << ipmt + 1
630 << " has chi2 value " << fchi2
631 << " force timing residual same as PMT-1 " );
632
633 // FittedMean=PreviousFittedMean;
634 fchi2 = -fchi2; // just to make Coverity happt
635 fmean = -4711;
636 fmeanerr = 0.0;
637 }
638 if (fabs(fmean) > 100) {
639 ATH_MSG_WARNING( " pmt # " << ipmt + 1
640 << " has ChannelOffset " << fmean
641 << " force timing residual same as PMT-1" );
642
643 // FittedMean=PreviousFittedMean;
644 fmean = -4711;
645 fmeanerr = 0.0;
646 }
647 m_ChannelOffset[ros][drawer][ipmt] = fmean;
648 m_ChannelOffsetError[ros][drawer][ipmt] = fmeanerr;
649 }
650 } else {
651 m_ChannelOffset[ros][drawer][ipmt] = 0.0;
652 m_ChannelOffsetError[ros][drawer][ipmt] = 0.0;
653 }
654
655#ifdef TileLaserTimingMonPulse
656 //===========================================================
657 //=== Pedestal and ADC Amplitudes ===
658 //===========================================================
659 pmtd.pedestal.getStat(m_PedestalMean[ros][drawer][ipmt], m_PedestalSigma[ros][drawer][ipmt]);
660 if (isConnectedPMT(ros, ipmt))
661 m_ADCAmplitude[ros][drawer][ipmt] = fmax(pmtd.pulseShapeHigh.GetMaximum(), pmtd.pulseShapeLow.GetMaximum());
662 else
663 m_ADCAmplitude[ros][drawer][ipmt] = 0.;
664
665 if (msgLvl(MSG::VERBOSE) && (ros == 1) && (drawer == 1)) {
666 msg(MSG::VERBOSE) << "ipmt: " << ipmt
667 << " TimeDiffLow: " << m_TimeDiffLowMean[ros][drawer][ipmt] << "(" << m_TimeDiffLowSigma[ros][drawer][ipmt] << ") +-" << m_TimeDiffLowMeanError[ros][drawer][ipmt]
668 << " TimeDiffHigh:" << m_TimeDiffHighMean[ros][drawer][ipmt] << "(" << m_TimeDiffHighSigma[ros][drawer][ipmt] << ") +-" << m_TimeDiffHighMeanError[ros][drawer][ipmt] << endmsg;
669
670 msg(MSG::VERBOSE) << " TimeDiff:" << m_TimeDiffMean[ros][drawer][ipmt] << "(" << m_TimeDiffSigma[ros][drawer][ipmt] << ") +-" << m_TimeDiffMeanError[ros][drawer][ipmt]
671 << " TomeDiffNoCF:" << m_TimeDiffNoCFCorrMean[ros][drawer][ipmt] << "(" << m_TimeDiffNoCFCorrSigma[ros][drawer][ipmt] << ") +-" << m_TimeDiffNoCFCorrMeanError[ros][drawer][ipmt] << endmsg;
672
673 msg(MSG::VERBOSE) << " ped:" << m_PedestalMean[ros][drawer][ipmt] << "(" << m_PedestalSigma[ros][drawer][ipmt]
674 << ") amp:" << m_ADCAmplitude[ros][drawer][ipmt] << endmsg;
675 }
676#endif
677
678 } // end PMT loop
679
680 //============================================
681 //========= Fit mean DrawerOffset ============
682 //============================================
683
684 fitGauss2(drawerd.Digi0TimeDiffHisto, m_DrawerOffset[ros][drawer], fdummy, fdummy, m_DrawerOffsetError[ros][drawer], 0.5, 1.0);
685
686 ATH_MSG_DEBUG( "finalizeCalculations()"
687 << " ros: " << ros
688 << " drawer:" << drawer
689 << " DrawerOffset:" << m_DrawerOffset[ros][drawer] << "("
690 << m_DrawerOffsetError[ros][drawer] << ")" );
691
692 //==============================================================
693 //=== correct for overall offset between odd and even fibers ===
694 //
695 // Better would be to meassure the laser fiber lengths and
696 // implement this as a correction. Meanwhile, use this as
697 // a compromise.
698 //==============================================================
699 // CCC: MeanEvenPmtTdiff= 0;
700 // CCC: MeanOddPmtTdiff = 0;
701 // CCC: DeltaParity = 0;
702 // CCC: OddPmtCounter =0;
703 // CCC: EvenPmtCounter =0;
704
706
708
710
711 //==================================================================
712 //=== Calculate Dskews ===
713 //==================================================================
714 for (int ipmt = 0; ipmt < NCHANNELS; ++ipmt) {
715 // LBA and LBC
716 if (isBarrel(ros)) {
717 if (isConnectedPMT(ros, ipmt) && (timeDiffs[ros][drawer][ipmt] < 300)) {
718 drawerd.digid[ipmt / 6].Add(timeDiffs[ros][drawer][ipmt]);
719 }
720 if (ipmt % 6 == 5) {
721 drawerd.digid[ipmt / 6].Freeze();
722 }
723 } // end isBarrel
724 // EBA and EBC%
725 else if (isExtBarrel(ros)) {
726 if (isConnectedPMT(ros, ipmt) && (timeDiffs[ros][drawer][ipmt] < 300)) {
727 if (ipmt < 6) drawerd.digid[0].Add(timeDiffs[ros][drawer][ipmt]);
728 else if (ipmt > 5 && ipmt < 12) drawerd.digid[1].Add(timeDiffs[ros][drawer][ipmt]);
729 else if (ipmt > 11 && ipmt < 18) drawerd.digid[2].Add(timeDiffs[ros][drawer][ipmt]);
730 else if (ipmt > 17 && ipmt < 24) drawerd.digid[3].Add(timeDiffs[ros][drawer][ipmt]);
731 else if (ipmt > 27 && ipmt < 34) {
732 drawerd.digid[4].Add(timeDiffs[ros][drawer][ipmt]);
733 drawerd.digid[5].Add(timeDiffs[ros][drawer][ipmt]);
734 } else if (ipmt > 35) {
735 drawerd.digid[6].Add(timeDiffs[ros][drawer][ipmt]);
736 drawerd.digid[7].Add(timeDiffs[ros][drawer][ipmt]);
737 }
738 }
739
740 if (ipmt == 5) drawerd.digid[0].Freeze();
741 else if (ipmt == 11) drawerd.digid[1].Freeze();
742 else if (ipmt == 17) drawerd.digid[2].Freeze();
743 else if (ipmt == 23) drawerd.digid[3].Freeze();
744 else if (ipmt == 33) {
745 drawerd.digid[4].Freeze();
746 drawerd.digid[5].Freeze();
747 } else if (ipmt == 47) {
748 drawerd.digid[6].Freeze();
749 drawerd.digid[7].Freeze();
750 }
751 } // end isExtBarrel
752 } // end PMT loop
753
754 for (int digi = 0; digi < NDIGI; ++digi) {
755 m_DigiMean[ros][drawer][digi] = drawerd.digid[digi].GetDigiTime();
756 m_DSkewSet[ros][drawer][digi] = (m_DigiMean[ros][drawer][digi] - m_DigiMean[ros][drawer][0]) * 240. / 25.;
757
758 ATH_MSG_DEBUG( "finalizeCalculations()"
759 << " ros: " << ros
760 << " drawer: " << drawer
761 << " digi: " << digi
762 << " digi_time: " << drawerd.digid[digi].GetDigiTime()
763 << " #active: " << drawerd.digid[digi].GetTotActive()
764 << " DSkewSet: " << m_DSkewSet[ros][drawer][digi] );
765
766 }
767 } // end drawer loop
768 } // end ros loop
769
770 return StatusCode::SUCCESS;
771}
772
773StatusCode TileLaserTimingTool::writeNtuple(int runNumber, int runType, TFile* rootFile) {
774
775 ATH_MSG_INFO( "writeNtuple(" << runNumber << "," << runType << "," << rootFile << ")" );
776
777 // Write a tree with all arrays
778 TTree *t = new TTree(m_ntupleID.c_str(), "TileLaserTimingNtuple");
779 t->Branch("DrawerOffset", m_DrawerOffset, "DrawerOffset[5][64]/F"); // float m_DrawerOffset[s_NRos][64];
780 t->Branch("DrawerOffsetError", m_DrawerOffsetError, "DrawerOffsetError[5][64]/F"); // float m_DrawerOffsetError[NROS][64];
781
782 t->Branch("ChannelOffset", m_ChannelOffset, "ChannelOffset[5][64][48]/F"); // float m_ChannelOffset[NROS][64][48];
783 t->Branch("ChannelOffsetError", m_ChannelOffsetError, "ChannelOffsetError[5][64][48]/F"); // float m_ChannelOffsetError[NROS][64][48];
784
785 t->Branch("ADCAmplitude", m_ADCAmplitude, "ADCAmplitude[5][64][48]/F"); // float m_ADCAmplitude[NROS][64][48];
786
787 t->Branch("PedestalMean", m_PedestalMean, "PedestalMean[5][64][48]/F"); // float m_PedestalMean[NROS][64][48];
788 t->Branch("PedestalSigma", m_PedestalSigma, "PedestalSigma[5][64][48]/F"); // float m_PedestalSigma[NROS][64][48];
789
790 t->Branch("TimeDiffMean", m_TimeDiffMean, "TimeDiffMean[5][64][48]/F"); // float m_TimeDiffMean[NROS][64][48];
791 t->Branch("TimeDiffMeanError", m_TimeDiffMeanError, "TimeDiffMeanError[5][64][48]/F"); // float m_TimeDiffMeanError[NROS][64][48];
792 t->Branch("TimeDiffSigma", m_TimeDiffSigma, "TimeDiffSigma[5][64][48]/F"); // float m_TimeDiffSigma[NROS][64][48];
793
794#ifdef TileLaserTimingPMT0Mon
795 t->Branch("TimeDiffHighMean", m_TimeDiffHighMean, "TimeDiffHighMean[5][64][48]/F"); // float m_TimeDiffHighMean[NROS][64][48];
796 t->Branch("TimeDiffHighMeanError", m_TimeDiffHighMeanError, "TimeDiffHighMeanError[5][64][48]/F"); // float m_TimeDiffHighMeanError[NROS][64][48];
797 t->Branch("TimeDiffHighSigma", m_TimeDiffHighSigma, "TimeDiffHighSigma[5][64][48]/F"); // float m_TimeDiffHighSigma[NROS][64][48];
798 t->Branch("TimeDiffLowMean", m_TimeDiffLowMean, "TimeDiffLowMean[5][64][48]/F"); // float m_TimeDiffLowMean[NROS][64][48];
799 t->Branch("TimeDiffLowMeanError", m_TimeDiffLowMeanError, "TimeDiffLowMeanError[5][64][48]/F"); // float m_TimeDiffLowMeanError[NROS][64][48];
800 t->Branch("TimeDiffLowSigma", m_TimeDiffLowSigma, "TimeDiffLowSigma[5][64][48]/F"); // float m_TimeDiffLowSigma[NROS][64][48];
801 t->Branch("TimeDiffNoCFCorrMean", m_TimeDiffNoCFCorrMean, "TimeDiffNoCFCorrMean[5][64][48]/F"); // float m_TimeDiffNoCFCorrMean[NROS][64][48];
802 t->Branch("TimeDiffNoCFCorrMeanError", m_TimeDiffNoCFCorrMeanError, "TimeDiffNoCFCorrMeanError[5][64][48]/F"); // float m_TimeDiffNoCFCorrMeanError[NROS][64][48];
803 t->Branch("TimeDiffNoCFCorrSigma", m_TimeDiffNoCFCorrSigma, "TimeDiffNoCFCorrSigma[5][64][48]/F"); // float m_TimeDiffNoCFCorrSigma[NROS][64][48];
804#endif
805 t->Branch("FiberLength", m_FiberLength, "FiberLength[5][64][48]/F"); // float m_FiberLength[NROS][64][48];
806
807#ifdef TileLaserTimingMon
808 t->Branch("EvenOddTimeDiff", m_EvenOddTimeDiff, "EvenOddTimeDiff[5][64]/F"); // float m_EvenOddTimeDiff[NROS][64];
809
810 t->Branch("FiberCorrection", m_FiberCorrection, "FiberCorrection[5][64][48]/F"); // float m_FiberCorrection[NROS][64][48];
811 t->Branch("IsConnected", m_IsConnected, "IsConnected[5][64][48]/F"); // float m_FiberCorrection[NROS][64][48];
812
813 t->Branch("MeanOddPmtTdiff", m_MeanOddPmtTdiff, "MeanOddPmtTdiff[5][64]/F");
814 t->Branch("OddPmtCounter", m_OddPmtCounter, "OddPmtCounter[5][64]/I");
815 t->Branch("MeanEvenPmtTdiff", m_MeanEvenPmtTdiff, "MeanEvenPmtTdiff[5][64]/F");
816 t->Branch("EvenPmtCounter", m_EvenPmtCounter, "EvenPmtCounter[5][64]/I");
817
818 t->Branch("TimeDiffPMTDigi0", m_TimeDiffPMTDigi0, "TimeDiffPMTDigi0[5][64][48]/F");
819#endif
820
821 // mon pmt0-->
822 t->Branch("EvenOddTimeDiffPMT0", m_EvenOddTimeDiffPMT0, "EvenOddTimeDiffPMT0[5][64]/F");
823 t->Branch("MeanOddPmtTdiffPMT0", m_MeanOddPmtTdiffPMT0, "MeanOddPmtTdiffPMT0[5][64]/F");
824 t->Branch("OddPmtCounterPMT0", m_OddPmtCounterPMT0, "OddPmtCounterPMT0[5][64]/I");
825 t->Branch("MeanEvenPmtTdiffPMT0", m_MeanEvenPmtTdiffPMT0, "MeanEvenPmtTdiffPMT0[5][64]/F");
826 t->Branch("EvenPmtCounterPMT0", m_EvenPmtCounterPMT0, "EvenPmtCounterPMT0[5][64]/I");
827 // <-- mon pmt0
828
829 t->Branch("DSkewSet", m_DSkewSet, "DSkewSet[5][64][8]/F"); // float m_DSkewSet[NROS][64][8];
830 t->Branch("DigiMean", m_DigiMean, "DigiMean[5][64][8]/F"); // float m_DigiMean[NROS][64][8];
831 t->Fill();
832 rootFile->cd();
833 t->Write();
834
835 ATH_MSG_INFO( "writeNtuple(" << runNumber << "," << runType << "," << rootFile << ") data written" );
836
837 rootFile->ls();
838
839 // store histos
840 for (unsigned int ros = 1; ros < TileCalibUtils::MAX_ROS; ++ros) {
841 for (unsigned int drawer = 0; drawer < TileCalibUtils::MAX_DRAWER; ++drawer) {
842 ATH_MSG_VERBOSE( "writeNtuple() ros:" << ros << " drawer:" << drawer );
843
844 DrawerData* dd = drawerData(ros, drawer);
845 if (dd) {
846 dd->Digi0TimeDiffHisto.Write();
847#ifdef TileLaserTimingMon
848 dd->Digi0Time.Write();
849#endif
850 for (int ipmt = 0; ipmt < NCHANNELS; ++ipmt) {
851 if (isConnectedPMT(ros, ipmt)) {
852 /*dd->pmtd[ipmt]->TimeDiffHisto.Write();
853 dd->pmtd[ipmt]->TimeDiffNoCFCorrHisto.Write();*/
854#ifdef TileLaserTimingMon
855 dd->pmtd[ipmt]->timeHisto.Write();
856 dd->pmtd[ipmt]->eneHisto.Write();
857 dd->pmtd[ipmt]->gainHisto.Write();
858#endif
859 /*dd->pmtd[ipmt]->TimeDiffHistoHigh.Write();
860 dd->pmtd[ipmt]->pulseShapeHigh.Write();
861 dd->pmtd[ipmt]->TimeDiffHistoLow.Write();
862 dd->pmtd[ipmt]->pulseShapeLow.Write();*/
863 dd->pmtd[ipmt]->TimeDiffResHis.Write();
864 }
865 }
866 }
867 }
868 }
869
870 return StatusCode::SUCCESS;
871}
872
874
875 ATH_MSG_INFO( "finalize()" );
876
877 return StatusCode::SUCCESS;
878}
879
880
881
882bool TileLaserTimingTool::isConnectedPMT(int ros, int ipmt) {
883 if (isBarrel(ros)) {
884 return !(ipmt == 31 || ipmt == 32 || ipmt == 43);
885 } else if (isExtBarrel(ros)) {
886 return !( ipmt == 18 || ipmt == 19 || ipmt == 24 || ipmt == 25
887 || ipmt == 26 || ipmt == 27 || ipmt == 30 || ipmt == 31
888 || ipmt == 34 || ipmt == 35 || ipmt == 38 || ipmt == 39
889 || ipmt == 44 || ipmt == 45 || ipmt == 46 || ipmt == 47);
890 }
891
892 return false;
893}
894
895
896void TileLaserTimingTool::fitGauss(TH1F &hi, float &p1, float &p2, float &p1_err) {
897
898 if (hi.GetEntries() == 0) {
899 p1 = p2 = p1_err = 0.0;
900 return;
901 }
902 double MaxAmplitude = hi.GetMaximum();
903 double MeanTimeDiff = hi.GetMean();
904 double RMSTimeDiff = hi.GetRMS();
905 m_gaussf->SetParameter(0, MaxAmplitude);
906 m_gaussf->SetParameter(1, MeanTimeDiff);
907 m_gaussf->SetParameter(2, RMSTimeDiff);
908 m_gaussf->SetRange(MeanTimeDiff - 2.0 * RMSTimeDiff, MeanTimeDiff + 2.0 * RMSTimeDiff);
909
910 hi.Fit(m_gaussf, "QR");
911
912 p1 = m_gaussf->GetParameter(1);
913 p1_err = m_gaussf->GetParError(1);
914 p2 = m_gaussf->GetParameter(2);
915}
916
917void TileLaserTimingTool::fitGauss2(TH1F &hi, float &p1, float &p2, float &chi2, float &p1_err, float w1, float w2) {
918
919 if (hi.GetEntries() == 0) {
920 p1 = p2 = chi2 = p1_err = w1 = w2 = 0.0;
921 return;
922 }
923
924 double MaxAmplitude = hi.GetMaximum();
925 double MeanTimeDiff = hi.GetMean();
926 double RMSTimeDiff = hi.GetRMS();
927
928 m_gaussf->SetParameter(0, MaxAmplitude);
929 m_gaussf->SetParameter(1, MeanTimeDiff);
930 m_gaussf->SetParameter(2, RMSTimeDiff);
931 m_gaussf->SetRange(MeanTimeDiff - w1 * RMSTimeDiff, MeanTimeDiff + w1 * RMSTimeDiff);
932
933 hi.Fit(m_gaussf, "QR");
934 double FittedAmplitude = m_gaussf->GetParameter(0);
935 double FittedMean = m_gaussf->GetParameter(1);
936 double FittedSigma = m_gaussf->GetParameter(2);
937
938 //=== Iterate once ===
939
940 m_gaussf->SetParameter(0, FittedAmplitude);
941 m_gaussf->SetParameter(1, FittedMean);
942 m_gaussf->SetParameter(2, FittedSigma);
943 m_gaussf->SetRange(FittedMean - w2 * FittedSigma, FittedMean + w2 * FittedSigma);
944
945 hi.Fit(m_gaussf, "QR");
946 p1 = m_gaussf->GetParameter(1);
947 p2 = m_gaussf->GetParameter(2);
948 p1_err = m_gaussf->GetParError(1);
949 chi2 = m_gaussf->GetChisquare();
950}
951
952void TileLaserTimingTool::correctEvenOddPMT(int ros, int drawer, TPMTArray& ChannelOffset
953 , TDrawerArrayF& MeanOddPmtTdiff, TDrawerArrayI& OddPmtCounter
954 , TDrawerArrayF& MeanEvenPmtTdiff, TDrawerArrayI& EvenPmtCounter
955 , TDrawerArrayF& EvenOddTimeDiff) {
956
957
958 float DeltaParity = 0;
959
960 //=== determine overall shift between odd and even fibers ===
961 //=== for this take only into account channels with connected PMT
962 //=== don't take into the mean the value of tdiff when it is too far from zero
963 for (int ipmt = 0; ipmt < NCHANNELS; ++ipmt) {
964 if (isConnectedPMT(ros, ipmt)) {
965 if (ipmt % 2 == 1) {
966 // odd PMTs
967 if (fabs(ChannelOffset[ros][drawer][ipmt]) < m_maxTimeDiff) {
968 MeanOddPmtTdiff[ros][drawer] += ChannelOffset[ros][drawer][ipmt];
969 ++OddPmtCounter[ros][drawer];
970 } else {
971 ATH_MSG_WARNING( "correctEvenOddPMT()"
972 << " time overflow (" << ChannelOffset[ros][drawer][ipmt]
973 << ") ros:" << ros
974 << " dr:" << drawer
975 << " pmt:" << ipmt );
976
977 }
978 } else if (ipmt % 2 == 0) {
979 // even PMTs
980 if (fabs(ChannelOffset[ros][drawer][ipmt]) < m_maxTimeDiff) {
981 MeanEvenPmtTdiff[ros][drawer] += ChannelOffset[ros][drawer][ipmt];
982 ++EvenPmtCounter[ros][drawer];
983 } else {
984 ATH_MSG_WARNING( "correctEvenOddPMT()"
985 << " time overflow (" << ChannelOffset[ros][drawer][ipmt]
986 << ") ros:" << ros
987 << " dr:" << drawer
988 << " pmt:" << ipmt );
989 }
990 }
991 }
992 }
993
994 // Save Time difference b/w odd/even pmt's
995 MeanOddPmtTdiff[ros][drawer] /= (float) OddPmtCounter[ros][drawer];
996 MeanEvenPmtTdiff[ros][drawer] /= (float) EvenPmtCounter[ros][drawer];
997 DeltaParity = 0.5 * (MeanOddPmtTdiff[ros][drawer] - MeanEvenPmtTdiff[ros][drawer]);
998
999 EvenOddTimeDiff[ros][drawer] = 2 * DeltaParity;
1000
1001 ATH_MSG_DEBUG( "correctEvenOddPMT()"
1002 << " ros: " << ros
1003 << " drawer:" << drawer
1004 << " EvenOddTimeDiff:" << EvenOddTimeDiff[ros][drawer]
1005 << " | MeanOddPmtTdiff:" << MeanOddPmtTdiff[ros][drawer]
1006 << " MeanEvenPmtTdiff:" << MeanEvenPmtTdiff[ros][drawer]
1007 << " DeltaParity:" << DeltaParity );
1008
1009 //==================================================================
1010 //=== Correct for overall shift b/w odd and even fibers ===
1011 //==================================================================
1012 for (int ipmt = 0; ipmt < NCHANNELS; ++ipmt) {
1013 if (isConnectedPMT(ros, ipmt)) {
1014 if (ipmt % 2 == 1)
1015 ChannelOffset[ros][drawer][ipmt] -= DeltaParity;
1016 else if (ipmt % 2 == 0) ChannelOffset[ros][drawer][ipmt] += DeltaParity;
1017 }
1018 } // end pmt loop
1019}
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
#define sqr(t)
Handle class for reading from StoreGate.
int imax(int i, int j)
#define NDIGI
#define NCHANNELS
#define NPARTITIONS
#define NDRAWERS
#define TileLaserTimingMon
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
DataModel_detail::const_iterator< DataVector > const_iterator
Standard const_iterator.
Definition DataVector.h:838
const T * at(size_type n) const
Access an element, as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
static const TileCablingService * getInstance()
get pointer to service instance
static const unsigned int MAX_ROS
Number of ROSs.
static const unsigned int MAX_DRAWER
Number of drawers in ROS 1-4.
const std::vector< float > & samples() const
Definition TileDigits.h:58
float(* m_FiberCorrection)[NDRAWERS][NCHANNELS]
float(* m_ChannelOffset)[NDRAWERS][NCHANNELS]
float(* m_TimeDiffMean)[NDRAWERS][NCHANNELS]
ToolHandle< TileCondToolTiming > m_tileToolTiming
float(* m_EvenOddTimeDiff)[NDRAWERS]
HWIdentifier drawerId(int frag)
float(* TDrawerArrayF)[NDRAWERS]
int(* m_IsConnected)[NDRAWERS][NCHANNELS]
void fitGauss(TH1F &hi, float &p1, float &p2, float &p1_err)
Fit a Gaussian function (m_gaussf) to the given histogram, store mean, rms and mean error.
int(* m_OddPmtCounterPMT0)[NDRAWERS]
virtual StatusCode execute() override
TODO: determine event type, select laser?
const TileHWID * m_tileHWID
static bool isConnectedPMT(int ros, int chan)
virtual StatusCode finalize() override
float(* m_TimeDiffPMTDigi0)[NDRAWERS][NCHANNELS]
int(* m_EvenPmtCounterPMT0)[NDRAWERS]
int(* m_OddPmtCounter)[NDRAWERS]
float(* m_ADCAmplitude)[NDRAWERS][NCHANNELS]
virtual StatusCode initNtuple(int runNumber, int runType, TFile *rootfile) override
static bool isExtBarrel(int ros)
float(* m_DrawerOffset)[NDRAWERS]
float(* m_TimeDiffMeanError)[NDRAWERS][NCHANNELS]
virtual StatusCode finalizeCalculations() override
DrawerData *(* m_drawerData)[NDRAWERS]
int(* m_EvenPmtCounter)[NDRAWERS]
static bool isBarrel(int ros)
float(* m_MeanOddPmtTdiffPMT0)[NDRAWERS]
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
SG::ReadHandleKey< TileDigitsContainer > m_digitsContainerKey
const TileCablingService * m_cabling
float(* m_PedestalMean)[NDRAWERS][NCHANNELS]
bool isConnectedChan(int ros, int chan)
int m_nevts
number of laser events
std::string drawerIdStr(int frag)
float(* m_MeanOddPmtTdiff)[NDRAWERS]
DrawerData * drawerData(int ros, int drawer)
static float fiberLength(int ros, int pmt)
void correctEvenOddPMT(int ros, int drawer, TPMTArray &ChannelOffset, TDrawerArrayF &MeanOddPmtTdiff, TDrawerArrayI &OddPmtCounter, TDrawerArrayF &MeanEvenPmtTdiff, TDrawerArrayI &EvenPmtCounter, TDrawerArrayF &EvenOddTimeDiff)
Correct for differences between even and odd PMTs.
float(* m_TimeDiffSigma)[NDRAWERS][NCHANNELS]
float(* m_MeanEvenPmtTdiff)[NDRAWERS]
float(* TPMTArray)[NDRAWERS][NCHANNELS]
int channel2PMT(int ros, int chan)
SG::ReadHandleKey< TileRawChannelContainer > m_rawChannelContainerKey
float(* m_ChannelOffsetError)[NDRAWERS][NCHANNELS]
float(* m_FiberLength)[NDRAWERS][NCHANNELS]
virtual StatusCode initialize() override
float(* m_DigiMean)[NDRAWERS][NDIGI]
float(* m_PedestalSigma)[NDRAWERS][NCHANNELS]
double fiberCorrection(int ros, int pmt)
static const float s_fiberLength[2][48]
virtual StatusCode writeNtuple(int runNumber, int runType, TFile *rootfile) override
float(* m_DrawerOffsetError)[NDRAWERS]
float(* m_DSkewSet)[NDRAWERS][NDIGI]
float(* m_MeanEvenPmtTdiffPMT0)[NDRAWERS]
int(* TDrawerArrayI)[NDRAWERS]
void fitGauss2(TH1F &hi, float &p1, float &p2, float &chi2, float &p1_err, float w1, float w2)
Fit a Gaussian function with two iterations mean range = hi.mean +- w1|w2 * hi.rms.
TileLaserTimingTool(const std::string &type, const std::string &name, const IInterface *pParent)
float(* m_EvenOddTimeDiffPMT0)[NDRAWERS]
float pedestal(void) const
float time(int ind=0) const
float amplitude(int ind=0) const
Identifier identify(void) const
Definition TileRawData.h:52
HWIdentifier adc_HWID(void) const
Definition TileRawData.h:53
void getStat(double &mean, double &sigma)
void add(double val)
double chi2(TH1 *h0, TH1 *h1)