DLECorrectionWG/DLECorrection.cc
Go to the documentation of this file.
1 #include "DLECorrection.h"
2 
3 #include <evt/Event.h>
4 #include <evt/ShowerRecData.h>
5 #include <evt/ShowerSRecData.h>
6 #include <evt/ShowerSimData.h>
7 
8 #include <sevt/Header.h>
9 #include <sevt/SEvent.h>
10 #include <sevt/PMTCalibData.h>
11 #include <sevt/PMTRecData.h>
12 #include <sevt/Station.h>
13 #include <sevt/StationRecData.h>
14 #include <sevt/StationConstants.h>
15 
16 #include <det/Detector.h>
17 #include <sdet/SDetector.h>
18 #include <sdet/Station.h>
19 
20 #include <utl/Accumulator.h>
21 #include <utl/AugerUnits.h>
22 #include <utl/AxialVector.h>
23 #include <utl/CoordinateSystemPtr.h>
24 #include <utl/ErrorLogger.h>
25 #include <utl/MathConstants.h>
26 #include <utl/PhysicalConstants.h>
27 #include <utl/Point.h>
28 #include <utl/Trace.h>
29 #include <utl/TraceAlgorithm.h>
30 #include <utl/Vector.h>
31 
32 // Offline headers
33 #include <fwk/CentralConfig.h>
34 
35 // ROOT headers
36 #include <TFormula.h>
37 
38 using namespace sevt;
39 using namespace evt;
40 using namespace std;
41 using namespace utl;
42 using namespace fwk;
43 
44 
45 namespace DLECorrectionWG {
46 
47  bool
48  DLECorrection::SelectPMT(const PMT& pmt, const bool lgsat, const bool hgsat,
49  const unsigned int saturationValue)
50  const
51  {
52  bool flag =
53  !lgsat &&
54  pmt.HasRecData() &&
55  pmt.HasCalibData() &&
56  pmt.GetCalibData().IsTubeOk() &&
57  !(hgsat && pmt.HasCalibData() && !(pmt.GetCalibData().IsLowGainOk()));
58  // remove bad traces
59  // not for low gain saturated!
60  if (fExcludeBadTraces && !lgsat)
61  flag = flag && !FlagNegBins(pmt) && !FlagOscBaselines(pmt, hgsat, saturationValue);
62 
63  if (!fCorrectHGSat)
64  flag = flag && !hgsat;
65 
66  return flag;
67  }
68 
69 
70  // Flag traces with huge negative signal bins
71  bool
72  DLECorrection::FlagNegBins(const PMT& pmt)
73  const
74  {
75  if (!pmt.GetCalibData().IsTubeOk() || !pmt.HasRecData())
76  return false;
77 
78  const auto& pmtRec = pmt.GetRecData();
79  const auto& vemtrace = pmtRec.GetVEMTrace(fComponent);
80 
81  for (unsigned int i = 0; i < fTraceSize; ++i)
82  if (vemtrace[i] < fNegSignalThr)
83  return true;
84 
85  return false;
86  }
87 
88 
89  // Flag traces with oscillating baselines
90  bool
91  DLECorrection::FlagOscBaselines(const PMT& pmt, const bool hgsat,
92  const int saturationValue)
93  const
94  {
95  if (!pmt.HasCalibData() || !pmt.GetCalibData().IsTubeOk() || !pmt.HasRecData())
96  return false;
97 
98  const auto& pmtRec = pmt.GetRecData();
99  const auto& vemtrace = pmtRec.GetVEMTrace(fComponent);
100  const auto& hgtrace = pmt.GetFADCTrace(sdet::PMTConstants::eHighGain, fComponent);
101 
102  bool isPMTHGSat = false;
103  if (hgsat) {
104  for (unsigned int i = 0; i < fTraceSize; ++i) {
105  if (hgtrace[i] >= saturationValue) {
106  isPMTHGSat = true;
107  break;
108  }
109  }
110  }
111 
112  const double thr = isPMTHGSat ? fOscThrLG : fOscThrHG;
113 
114  bool flag = false;
115 
116  // check if pmt high gain saturated
117  // int iPrev = 0;
118  const int stop = fTraceSize;
119 
120  // Find oscillating pattern within moving window
121  // of 15 bins (a bit clumsy to read)
122  for (int i = 0; i < stop; ++i) {
123 
124  if (stop < i + fOscOffset)
125  break;
126 
127  flag = false;
128  int countBinsNeg = 0;
129  int countBinsPos = 0;
130  double sum = 0;
131  double sumPos = 0;
132 
133  if (vemtrace[i] < -thr) {
134  for (int j = i; j < i + fOscOffset; ++j) {
135  sum += vemtrace[j];
136  if (vemtrace[j] < -thr)
137  ++countBinsNeg;
138  else if (vemtrace[j] > thr) {
139  ++countBinsPos;
140  sumPos += vemtrace[j];
141  }
142  }
143  }
144 
145  if (countBinsNeg >= 3 &&
146  countBinsPos >= 3 &&
147  sum < 0.5*sumPos) {
148  flag = true;
149  break;
150  }
151  }
152 
153  return flag;
154  }
155 
156 
157  // Estimate statistical fluctuations of signal
158  double
159  DLECorrection::EstimateSignalFluct(const PMT& pmt, const bool ishgsat, const int pos)
160  const
161  {
162  const auto& pmtRec = pmt.GetRecData();
163  const double vem = pmtRec.GetVEMTrace(fComponent)[pos];
164  const double peak = pmtRec.GetVEMPeak();
165  const double peakErr = pmtRec.GetVEMPeakError();
166  double fadcErr = 0;
167  double baseErr = 0;
168 
169  const auto& pmtCalib = pmt.GetCalibData();
170  if (ishgsat) {
171  const double daratio = pmtRec.GetGainRatio();
172  baseErr = pmtCalib.GetBaselineRMS(sdet::PMTConstants::eLowGain) * daratio;
173  const auto fadc = pmt.GetFADCTrace(sdet::PMTConstants::eLowGain, fComponent)[pos];
174  fadcErr = std::sqrt(fadc * daratio);
175  } else {
176  baseErr = pmtCalib.GetBaselineRMS();
177  const auto fadc = pmt.GetFADCTrace(sdet::PMTConstants::eHighGain, fComponent)[pos];
178  fadcErr = std::sqrt(fadc);
179  }
180 
181  // contributions to fluctuations of a single pmt: fadc counts, baseline, peak value
182  const double pmtStatErr = sqrt(Sqr(fadcErr/peak) + Sqr(baseErr/peak) + Sqr(vem/peak*peakErr));
183 
184  return pmtStatErr;
185  }
186 
187 
188  // Average correction of direct light
189  // (zenithal & azimuthal dependence)
190  double
191  DLECorrection::GetFCorr(const int pmtId,
192  const double theta, const double phi)
193  const
194  {
195  double fCorr = 0;
196 
197  double phiDeg = phi/deg;
198  double thetaDeg = theta/deg;
199 
200  double phi0Deg = 0;
201  if (pmtId == 1) {
202  phi0Deg = fShiftPMT1/deg;
203  } else if (pmtId == 2) {
204  phi0Deg = fShiftPMT2/deg;
205  } else if (pmtId == 3) {
206  phi0Deg = fShiftPMT3/deg;
207  }
208 
209  const double parA = fFormulaDLEParA->Eval(thetaDeg);
210  const double parB = fFormulaDLEParB->Eval(thetaDeg);
211 
212  const double cosPhi = cos((phiDeg + (180 - phi0Deg)) * deg);
213  const double cosPhi2 = cos(2*(phiDeg + (180 - phi0Deg)) * deg);
214 
215  fCorr = parA*cosPhi + parB*cosPhi2;
216 
217  return fCorr;
218  }
219 
220 
221  void
222  DLECorrection::CorrectAverageDLE(Station& station,
223  const double theta, const double phi)
224  const
225  {
226  const sdet::Station& dStation =
227  det::Detector::GetInstance().GetSDetector().GetStation(station);
228  const unsigned int saturationValue = dStation.GetSaturationValue();
229  std::ostringstream info;
230 
231  //StationRecData& sRec = station.GetRecData();
232  //const unsigned int startIntegration = sRec.GetSignalStartSlot();
233  //const unsigned int endIntegration = sRec.GetSignalEndSlot();
234 
235  for (auto& pmt : station.PMTsRange()) {
236 
237  // pmt selection
238  const bool flagPMTSel =
239  SelectPMT(pmt, station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
240  if (!flagPMTSel)
241  continue;
242 
243  auto& pmtRec = pmt.GetRecData();
244  if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
245  continue;
246 
247  auto& vemtrace = pmtRec.GetVEMTrace(fCleaned);
248 
249  // phase shift of individual pmt
250  const int pmtId = pmt.GetId();
251  const double corr = 1 / (1. + GetFCorr(pmtId, theta, phi));
252 
253  for (unsigned int i = 0; i < fTraceSize; ++i) {
254  vemtrace[i] *= corr;
255  }
256 
257  }
258  }
259 
260 
261  // Correction of individual direct light instances
262  void
263  DLECorrection::CorrectIndividualDLE(Station& station)
264  const
265  {
266  const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
267  const int saturationValue = dStation.GetSaturationValue();
268 
269  //auto& sRec = station.GetRecData();
270  //const unsigned int startIntegration = sRec.GetSignalStartSlot();
271  //const unsigned int endIntegration = sRec.GetSignalEndSlot();
272 
273  vector<unsigned int> workingPMTsIds;
274  for (const auto& pmt : station.PMTsRange()) {
275 
276  // pmt selection
277  const bool flagPMTSel =
278  SelectPMT(pmt, station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
279  if (!flagPMTSel)
280  continue;
281 
282  const auto& pmtRec = pmt.GetRecData();
283 
284  if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
285  continue;
286 
287  workingPMTsIds.push_back(pmt.GetId());
288  }
289 
290  const int nPMTs = workingPMTsIds.size();
291  const bool ishgsat = station.IsHighGainSaturation();
292 
293  // trace loop
294  for (unsigned int jTr = 0; jTr < fTraceSize; ++jTr) {
295 
296  int outlierid = 0;
297  double signalOutlier = -100;
298  double sigmaSignal = 0;
299  double meanRed = 0;
300  double meanAll = 0;
301 
303  for (int iPMT = 0; iPMT < nPMTs; ++iPMT) {
304  const auto& vem = station.GetPMT(workingPMTsIds[iPMT]).GetRecData().GetVEMTrace(fComponent);
305  if (vem[jTr] > signalOutlier) {
306  outlierid = iPMT;
307  signalOutlier = vem[jTr];
308  }
309  }
310 
311  // Cut on minimum signal in time bin
312  int countSignalTh = 0;
313 
315  for (int iPMT = 0; iPMT < nPMTs; ++iPMT) {
316 
317  const auto& currPMT = station.GetPMT(workingPMTsIds[iPMT]);
318 
319  // check if high gain is saturated
320  bool isPMTHGSat = false;
321  if (ishgsat) {
322  for (unsigned int i = 0; i < fTraceSize; ++i) {
323  const int fadc = currPMT.GetFADCTrace(sdet::PMTConstants::eHighGain, fComponent)[i];
324  if (fadc >= saturationValue) {
325  isPMTHGSat = true;
326  break;
327  }
328  }
329  }
330 
331  const double vem = currPMT.GetRecData().GetVEMTrace(fComponent)[jTr];
332  meanAll += vem / double(nPMTs);
333 
334  // fluctuations of a single pmt
335  const double pmtSFluct = EstimateSignalFluct(currPMT, isPMTHGSat, jTr);
336 
337  countSignalTh += (vem > fDLESignalThreshold);
338 
339  if (iPMT != outlierid) { // pmts except for the outlier
340  meanRed += vem / (nPMTs - 1);
341  sigmaSignal += Sqr(pmtSFluct / (nPMTs - 1));
342  } else if (iPMT == outlierid) { // pmt outlier
343  signalOutlier = vem;
344  sigmaSignal += Sqr(pmtSFluct);
345  }
346 
347  } // end of pmt loop
348 
349  sigmaSignal = sqrt(sigmaSignal);
350  const double filterValue = (signalOutlier - meanRed) / sigmaSignal;
351 
353  if (filterValue >= fDLEFilterThreshold && countSignalTh > 0) {
354 
355  double signalRepl = 0;
356 
357  if (nPMTs == 2)
358  signalRepl = meanAll;
359  else if (nPMTs == 3)
360  signalRepl = (meanAll*nPMTs - signalOutlier) / (nPMTs - 1);
361  else
362  signalRepl = station.GetPMT(workingPMTsIds[outlierid]).GetRecData().GetVEMTrace(fCleaned)[jTr];
363  // replace signal bin
364  station.GetPMT(workingPMTsIds[outlierid]).GetRecData().GetVEMTrace(fCleaned)[jTr] = signalRepl;
365 
366  }
367 
368  }
369 
370  workingPMTsIds.clear();
371  }
372 
373 
374  // Compute station rise- and falltime
375  void
376  DLECorrection::ComputeCleanedRiseFall(PMTRecData& pmtRec,
377  const unsigned int startIntegration,
378  const unsigned int endIntegration,
379  const double traceIntegral)
380  const
381  {
382  if (traceIntegral <= 0)
383  return;
384 
385  const double riseStartSentry = fRiseTimeFractions.first * traceIntegral;
386  const double riseEndSentry = fRiseTimeFractions.second * traceIntegral;
387  const double fallStartSentry = fFallTimeFractions.first * traceIntegral;
388  const double fallEndSentry = fFallTimeFractions.second * traceIntegral;
389  const double binTiming = fBinSize;
390  double riseStartBin = 0;
391  double riseEndBin = 0;
392  double fallStartBin = 0;
393  double fallEndBin = 0;
394 
395  double runningSum = 0;
396  double oldSum = 0;
397 
398  const TraceD& trace = pmtRec.GetVEMTrace(fCleaned);
399 
400  for (unsigned int i = startIntegration; i < endIntegration; ++i) {
401 
402  const double binValue = trace[i];
403  runningSum += binValue;
404 
405  if (!riseStartBin && runningSum > riseStartSentry)
406  riseStartBin = i - (runningSum - riseStartSentry) / (runningSum - oldSum);
407 
408  if (!riseEndBin && runningSum > riseEndSentry)
409  riseEndBin = i - (runningSum - riseEndSentry) / (runningSum - oldSum);
410 
411  if (!fallStartBin && runningSum > fallStartSentry)
412  fallStartBin = i - (runningSum - fallStartSentry) / (runningSum - oldSum);
413 
414  if (!fallEndBin && runningSum > fallEndSentry)
415  fallEndBin = i - (runningSum - fallEndSentry) / (runningSum - oldSum);
416 
417  oldSum = runningSum;
418 
419  }
420 
421  pmtRec.SetRiseTimeCleaned(binTiming * (riseEndBin-riseStartBin), 0);
422  pmtRec.SetFallTimeCleaned(binTiming * (fallEndBin-fallStartBin), 0);
423 
424  if (fOverwriteVEMTrace) {
425  pmtRec.SetRiseTime(binTiming * (riseEndBin-riseStartBin), 0);
426  pmtRec.SetFallTime(binTiming * (fallEndBin-fallStartBin), 0);
427  }
428  }
429 
430 
433  {
434  auto& cc = *CentralConfig::GetInstance();
435 
436  AttributeMap Attributes;
437  Branch topBranch = cc.GetTopBranch("DLECorrection");
438 
439  topBranch.GetChild("calcCorrSignalRiseFall").GetData(fCalcCorrSignalRiseFall);
440  topBranch.GetChild("riseTimeFractions").GetData(fRiseTimeFractions);
441  topBranch.GetChild("fallTimeFractions").GetData(fFallTimeFractions);
442 
443  if (fRiseTimeFractions.first < 0 || fRiseTimeFractions.first > 1 ||
444  fRiseTimeFractions.second < 0 || fRiseTimeFractions.second > 1) {
445  ERROR("Rise-/falltime fractions must be within [0, 1]");
446  return eFailure;
447  }
448  if (fRiseTimeFractions.first >= fRiseTimeFractions.second ||
449  fFallTimeFractions.first >= fFallTimeFractions.second ||
450  fRiseTimeFractions.first >= fFallTimeFractions.second) {
451  ERROR("Rise-/falltime definition is not in the ascending order");
452  return eFailure;
453  }
454 
455  std::ostringstream info;
456  if (fCalcCorrSignalRiseFall) {
457  info << "General\n"
458  "\tRisetime fractions: " << fRiseTimeFractions.first
459  << ' ' << fRiseTimeFractions.second
460  << "\tFalltime fractions: " << fFallTimeFractions.first
461  << ' ' << fFallTimeFractions.second << '\n';
462  }
463 
464  topBranch.GetChild("overwriteVEMTrace").GetData(fOverwriteVEMTrace);
465 
466  fComponent = sevt::StationConstants::eTotal;
467  fCleaned = fOverwriteVEMTrace ?
469 
470  topBranch.GetChild("doCorrectionIndividual").GetData(fDoCorrectionIndividual);
471  topBranch.GetChild("doCorrectionAverage").GetData(fDoCorrectionAverage);
472  topBranch.GetChild("correctHGSaturated").GetData(fCorrectHGSat);
473 
474  topBranch.GetChild("DLESignalThreshold").GetData(fDLESignalThreshold);
475  topBranch.GetChild("DLEFilterThreshold").GetData(fDLEFilterThreshold);
476  topBranch.GetChild("DLEMinNPMTs").GetData(fDLEMinNPMTs);
477 
478  topBranch.GetChild("ShiftPMT1").GetData(fShiftPMT1);
479  topBranch.GetChild("ShiftPMT2").GetData(fShiftPMT2);
480  topBranch.GetChild("ShiftPMT3").GetData(fShiftPMT3);
481  topBranch.GetChild("AsymmParA").GetData(fAsymmParA);
482  topBranch.GetChild("AsymmParB").GetData(fAsymmParB);
483  fFormulaDLEParA = new TFormula("fDLEFormulaParA", fAsymmParA.c_str());
484  fFormulaDLEParB = new TFormula("fDLEFormulaParB", fAsymmParB.c_str());
485 
486  if (fDoCorrectionIndividual) {
487  info << "Individual DLE correction\n"
488  "\tDLE signal threshold [VEM peak]: " << fDLESignalThreshold << "\n"
489  "\tDLE filter threshold: " << fDLEFilterThreshold << "\n"
490  "\tMinimum number of PMTs: " << fDLEMinNPMTs << '\n';
491  }
492  if (fDoCorrectionAverage) {
493  info << "Average DLE correction\n"
494  "\tPMT1 phase/deg: " << fShiftPMT1/deg << "\n"
495  "\tPMT2 phase/deg: " << fShiftPMT2/deg << "\n"
496  "\tPMT3 phase/deg: " << fShiftPMT3/deg << "\n"
497  "\tParametrization of parA: " << fAsymmParA.c_str() << "\n"
498  "\tParametrization of parB: " << fAsymmParB.c_str() << '\n';
499  }
500 
501  if (fFormulaDLEParA->IsZombie()) {
502  std::ostringstream error;
503  error << "Formula for parameter A defined in DLECorrection.xml contains an error!\n"
504  "Current formula is: parA = " << fAsymmParA.c_str() << "\n"
505  "This formula is not conform to the ROOT formula class guidelines.\n";
506  ERROR(error);
507  fFormulaDLEParA->Delete();
508  fFormulaDLEParA = nullptr;
509  return eFailure;
510  }
511 
512  if (fFormulaDLEParB->IsZombie()) {
513  std::ostringstream error;
514  error << "Formula for parameter B defined in DLECorrection.xml contains an error!\n"
515  "Current formula is: parB = " << fAsymmParB.c_str() << "\n"
516  "This formula is not conform to the ROOT formula class guidelines.\n";
517  ERROR(error);
518  fFormulaDLEParB->Delete();
519  fFormulaDLEParB = nullptr;
520  return eFailure;
521  }
522 
523  topBranch.GetChild("excludeStations").GetData(fExcludeStations); // tank selection
524  topBranch.GetChild("excludeBadTraces").GetData(fExcludeBadTraces);
525  topBranch.GetChild("excludeBadTracesCalc").GetData(fExcludeBadTracesCalc);
526  topBranch.GetChild("OscThrHG").GetData(fOscThrHG);
527  topBranch.GetChild("OscThrLG").GetData(fOscThrLG);
528  topBranch.GetChild("OscOffset").GetData(fOscOffset);
529  topBranch.GetChild("NegSignalThr").GetData(fNegSignalThr);
530 
531  if (fExcludeBadTraces) {
532  info << "Exclusion\n"
533  "\tDLECorrection::FlagOscBaselines(): Careful! "
534  "For offline version older than v2r9p3 don't apply this on "
535  "high- or low-gain-saturated station!\n";
536  if (fExcludeBadTracesCalc)
537  info << "\tBad traces excl. from calculation of cleaned signal and risetime\n";
538  } else if (!fExcludeBadTraces && fExcludeBadTracesCalc) {
539  ERROR("Exclusion of bad traces from calculation of cleaned signal and "
540  "risetime only if ExcludeBadTraces true");
541  return eFailure;
542  }
543 
544  INFO(info);
545 
546  return eSuccess;
547  }
548 
549 
551  DLECorrection::Run(evt::Event& event)
552  {
553  if (!event.HasSEvent())
554  return eContinueLoop;
555 
556  auto& sevent = event.GetSEvent();
557  double theta = 0;
558  double phi = 0;
559  bool flagHasRecShower = false;
560 
561  if (event.HasRecShower() && event.GetRecShower().HasSRecShower()) {
562  flagHasRecShower = true;
563  const auto& detector = det::Detector::GetInstance();
564  const auto& siteCS = detector.GetSiteCoordinateSystem();
565  auto& showersrec = event.GetRecShower().GetSRecShower();
566  const auto& axis = showersrec.GetAxis();
567  theta = axis.GetTheta(siteCS);
568  phi = axis.GetPhi(siteCS);
569  }
570 
571  for (auto& station : sevent.StationsRange()) {
572 
573  if (!station.HasRecData())
574  continue;
575 
576  const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
577 
578  const unsigned int saturationValue = dStation.GetSaturationValue();
579  fTraceSize = dStation.GetFADCTraceLength();
580  fBinSize = dStation.GetFADCBinSize();
581 
582  auto& sRec = station.GetRecData();
583  const unsigned int startIntegration = sRec.GetSignalStartSlot();
584  const unsigned int endIntegration = sRec.GetSignalEndSlot();
585 
586  // initialize station/pmt to uncleaned values (before further selection)
587  if (fCalcCorrSignalRiseFall) {
588  sRec.SetRiseTimeCleaned(sRec.GetRiseTime(),
589  sRec.GetRiseTimeRMS());
590  sRec.SetFallTimeCleaned(sRec.GetFallTime(),
591  sRec.GetFallTimeRMS());
592  sRec.SetTotalSignalCleaned(sRec.GetTotalSignal(),
593  sRec.GetTotalSignalError());
594  }
595 
596  for (auto& pmt : station.PMTsRange()) {
597 
598  if (!pmt.HasRecData())
599  continue;
600 
601  auto& pmtRec = pmt.GetRecData();
602  if (!pmtRec.HasVEMTrace(fComponent))
603  continue;
604 
605  pmtRec.SetRiseTimeCleaned(pmtRec.GetRiseTime(),
606  pmtRec.GetRiseTimeRMS());
607  pmtRec.SetFallTimeCleaned(pmtRec.GetFallTime(),
608  pmtRec.GetFallTimeRMS());
609 
610  }
611 
612  // select candidates
613  if (!station.IsCandidate())
614  continue;
615 
616  int nPMTs = 0;
617  // build cleaned traces
618  for (auto& pmt : station.PMTsRange()) {
619 
620  if (!pmt.HasRecData())
621  continue;
622 
623  auto& pmtRec = pmt.GetRecData();
624  if (!pmtRec.HasVEMTrace(fComponent))
625  continue;
626 
627  const auto& vemtraceComp = pmtRec.GetVEMTrace(fComponent);
628 
629  if (!pmtRec.HasVEMTrace(fCleaned))
630  pmtRec.MakeVEMTrace(fCleaned);
631 
632  auto& vemtraceClean = pmtRec.GetVEMTrace(fCleaned);
633  for (unsigned int i = 0; i < fTraceSize; ++i)
634  vemtraceClean[i] = vemtraceComp[i];
635 
636  // count good pmts for DLE correction
637  bool flagPMTSel = SelectPMT(pmt,
638  station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
639 
640  if (flagPMTSel)
641  ++nPMTs;
642 
643  }
644 
645  // flag for excluding miscabled stations
646  bool flagStationCorr = true;
647  for (unsigned int iSt = 0; iSt < fExcludeStations.size(); ++iSt) {
648  if (station.GetId() == fExcludeStations[iSt])
649  flagStationCorr = false;
650  }
651 
652  if (flagStationCorr) {
653  // Correction of individual direct light instances
654  if (fDoCorrectionIndividual && nPMTs >= fDLEMinNPMTs)
655  CorrectIndividualDLE(station);
656 
657  // Average correction of direct light (azimuthal and zenithal dependence)
658  if (fDoCorrectionAverage && flagHasRecShower)
659  CorrectAverageDLE(station, theta, phi);
660  }
661 
662  double totalCharge = 0;
663  Accumulator::SampleStandardDeviationN riseStat;
664  Accumulator::SampleStandardDeviationN fallStat;
665  int nTraces = 0;
666 
667  // Write cleaned observables
668  for (auto& pmt : station.PMTsRange()) {
669 
670  if (!pmt.HasRecData())
671  continue;
672 
673  auto& pmtRec = pmt.GetRecData();
674  if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
675  continue;
676 
677  // pmt selection
678  const bool flagPMTSel = SelectPMT(pmt,
679  station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
680  if (!flagPMTSel)
681  continue;
682 
683  // calculate cleaned signal and rise/falltime
684  const double vemCharge = pmtRec.GetVEMCharge();
685  if (vemCharge > 0) {
686  const auto& vemtraceClean = pmtRec.GetVEMTrace(fCleaned);
687  const double pmtIntegral =
688  accumulate(&vemtraceClean[startIntegration], &vemtraceClean[endIntegration+1], 0.);
689  const double pmtCharge = pmtIntegral * pmtRec.GetVEMPeak() / vemCharge;
690  totalCharge += pmtCharge;
691  ++nTraces;
692 
693  ComputeCleanedRiseFall(pmtRec, startIntegration, endIntegration+1, pmtIntegral);
694 
695  riseStat(pmtRec.GetRiseTimeCleaned());
696  fallStat(pmtRec.GetFallTimeCleaned());
697  }
698 
699  }
700 
701  const int n = nTraces;
702 
703  if (!n || !totalCharge)
704  continue;
705 
706  totalCharge /= n;
707  sRec.SetTotalSignalCleaned(totalCharge, sRec.GetTotalSignalError());
708 
709  if (fOverwriteVEMTrace)
710  sRec.SetTotalSignal(totalCharge, sRec.GetTotalSignalError());
711 
712  if (n > 1) {
713  sRec.SetRiseTimeCleaned(riseStat.GetAverage(n),
714  riseStat.GetStandardDeviation(n));
715  sRec.SetFallTimeCleaned(fallStat.GetAverage(n),
716  fallStat.GetStandardDeviation(n));
717  if (fOverwriteVEMTrace) {
718  sRec.SetRiseTime(riseStat.GetAverage(n),
719  riseStat.GetStandardDeviation(n));
720  sRec.SetFallTime(fallStat.GetAverage(n),
721  fallStat.GetStandardDeviation(n));
722  }
723  } else {
724  sRec.SetRiseTimeCleaned(riseStat.GetAverage(n), 0);
725  sRec.SetFallTimeCleaned(fallStat.GetAverage(n), 0);
726 
727  if (fOverwriteVEMTrace) {
728  sRec.SetRiseTime(riseStat.GetAverage(n), 0);
729  sRec.SetFallTime(fallStat.GetAverage(n), 0);
730  }
731  }
732  }
733 
734  return eSuccess;
735  }
736 
737 
739  DLECorrection::Finish()
740  {
741  delete fFormulaDLEParA;
742  fFormulaDLEParA = nullptr;
743  delete fFormulaDLEParB;
744  fFormulaDLEParB = nullptr;
745 
746  return eSuccess;
747  }
748 
749 }
Branch GetTopBranch() const
Definition: Branch.cc:63
utl::TraceD & GetVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal)
Traces calibrated in VEM Peak.
Definition: PMTRecData.h:46
bool HasRecData() const
Check for existenc of PMT reconstructed data object.
Definition: SEvent/PMT.h:53
void SetRiseTimeCleaned(const double riseTime, const double rms)
Definition: PMTRecData.h:174
constexpr T Sqr(const T &x)
class to hold data at PMT level
Definition: SEvent/PMT.h:28
Detector description interface for Station-related data.
total (shower and background)
bool IsTubeOk() const
Definition: PMTCalibData.h:29
PMTCalibData & GetCalibData()
Get object containing PMT calibration data.
Definition: SEvent/PMT.h:56
bool HasRecShower() const
PMTRecData & GetRecData()
Get object containing PMT reconstructed data.
Definition: SEvent/PMT.h:48
bool HasCalibData() const
Check for existence of PMT calibration data object.
Definition: SEvent/PMT.h:61
std::map< std::string, std::string > AttributeMap
Definition: Branch.h:24
void SetFallTime(const double fallTime, const double rms)
Definition: PMTRecData.h:177
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
bool IsHighGainSaturation() const
constexpr double deg
Definition: AugerUnits.h:140
Class representing a document branch.
Definition: Branch.h:107
class to hold data at Station level
class to hold reconstructed data at PMT level
Definition: PMTRecData.h:38
unsigned int GetSaturationValue() const
void SetFallTimeCleaned(const double fallTime, const double rms)
Definition: PMTRecData.h:179
signal after subtracting direct light (includes all particle sources).
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
utl::TraceI & GetFADCTrace(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain, const StationConstants::SignalComponent source=StationConstants::eTotal)
Definition: SEvent/PMT.h:72
bool IsLowGainOk() const
Definition: PMTCalibData.h:31
bool IsLowGainSaturation() const
Check which gains are saturated.
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
PMT & GetPMT(const unsigned int pmtId)
Retrive a PMT by Id.
void SetRiseTime(const double riseTime, const double rms)
Definition: PMTRecData.h:172
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
bool HasSEvent() const
double GetGainRatio() const
Definition: PMTCalibData.h:47

, generated on Tue Sep 26 2023.