4 #include <evt/ShowerRecData.h>
5 #include <evt/ShowerSRecData.h>
6 #include <evt/ShowerSimData.h>
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>
16 #include <det/Detector.h>
17 #include <sdet/SDetector.h>
18 #include <sdet/Station.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>
33 #include <fwk/CentralConfig.h>
45 namespace DLECorrectionWG {
48 DLECorrection::SelectPMT(
const PMT& pmt,
const bool lgsat,
const bool hgsat,
49 const unsigned int saturationValue)
60 if (fExcludeBadTraces && !lgsat)
61 flag = flag && !FlagNegBins(pmt) && !FlagOscBaselines(pmt, hgsat, saturationValue);
64 flag = flag && !hgsat;
72 DLECorrection::FlagNegBins(
const PMT& pmt)
79 const auto& vemtrace = pmtRec.
GetVEMTrace(fComponent);
81 for (
unsigned int i = 0; i < fTraceSize; ++i)
82 if (vemtrace[i] < fNegSignalThr)
91 DLECorrection::FlagOscBaselines(
const PMT& pmt,
const bool hgsat,
92 const int saturationValue)
99 const auto& vemtrace = pmtRec.
GetVEMTrace(fComponent);
102 bool isPMTHGSat =
false;
104 for (
unsigned int i = 0; i < fTraceSize; ++i) {
105 if (hgtrace[i] >= saturationValue) {
112 const double thr = isPMTHGSat ? fOscThrLG : fOscThrHG;
118 const int stop = fTraceSize;
122 for (
int i = 0; i < stop; ++i) {
124 if (stop < i + fOscOffset)
128 int countBinsNeg = 0;
129 int countBinsPos = 0;
133 if (vemtrace[i] < -thr) {
134 for (
int j = i; j < i + fOscOffset; ++j) {
136 if (vemtrace[j] < -thr)
138 else if (vemtrace[j] > thr) {
140 sumPos += vemtrace[j];
145 if (countBinsNeg >= 3 &&
159 DLECorrection::EstimateSignalFluct(
const PMT& pmt,
const bool ishgsat,
const int pos)
163 const double vem = pmtRec.
GetVEMTrace(fComponent)[pos];
164 const double peak = pmtRec.GetVEMPeak();
165 const double peakErr = pmtRec.GetVEMPeakError();
176 baseErr = pmtCalib.GetBaselineRMS();
182 const double pmtStatErr =
sqrt(
Sqr(fadcErr/peak) +
Sqr(baseErr/peak) +
Sqr(vem/peak*peakErr));
191 DLECorrection::GetFCorr(
const int pmtId,
192 const double theta,
const double phi)
197 double phiDeg = phi/
deg;
198 double thetaDeg = theta/
deg;
202 phi0Deg = fShiftPMT1/
deg;
203 }
else if (pmtId == 2) {
204 phi0Deg = fShiftPMT2/
deg;
205 }
else if (pmtId == 3) {
206 phi0Deg = fShiftPMT3/
deg;
209 const double parA = fFormulaDLEParA->Eval(thetaDeg);
210 const double parB = fFormulaDLEParB->Eval(thetaDeg);
212 const double cosPhi = cos((phiDeg + (180 - phi0Deg)) *
deg);
213 const double cosPhi2 = cos(2*(phiDeg + (180 - phi0Deg)) * deg);
215 fCorr = parA*cosPhi + parB*cosPhi2;
222 DLECorrection::CorrectAverageDLE(
Station& station,
223 const double theta,
const double phi)
227 det::Detector::GetInstance().GetSDetector().GetStation(station);
229 std::ostringstream info;
235 for (
auto& pmt : station.PMTsRange()) {
238 const bool flagPMTSel =
243 auto& pmtRec = pmt.GetRecData();
244 if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
247 auto& vemtrace = pmtRec.GetVEMTrace(fCleaned);
250 const int pmtId = pmt.GetId();
251 const double corr = 1 / (1. + GetFCorr(pmtId, theta, phi));
253 for (
unsigned int i = 0; i < fTraceSize; ++i) {
263 DLECorrection::CorrectIndividualDLE(
Station& station)
266 const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
267 const int saturationValue = dStation.GetSaturationValue();
273 vector<unsigned int> workingPMTsIds;
274 for (
const auto& pmt : station.PMTsRange()) {
277 const bool flagPMTSel =
282 const auto& pmtRec = pmt.GetRecData();
284 if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
287 workingPMTsIds.push_back(pmt.GetId());
290 const int nPMTs = workingPMTsIds.size();
294 for (
unsigned int jTr = 0; jTr < fTraceSize; ++jTr) {
297 double signalOutlier = -100;
298 double sigmaSignal = 0;
303 for (
int iPMT = 0; iPMT < nPMTs; ++iPMT) {
305 if (vem[jTr] > signalOutlier) {
307 signalOutlier = vem[jTr];
312 int countSignalTh = 0;
315 for (
int iPMT = 0; iPMT < nPMTs; ++iPMT) {
317 const auto& currPMT = station.
GetPMT(workingPMTsIds[iPMT]);
320 bool isPMTHGSat =
false;
322 for (
unsigned int i = 0; i < fTraceSize; ++i) {
324 if (fadc >= saturationValue) {
331 const double vem = currPMT.GetRecData().GetVEMTrace(fComponent)[jTr];
332 meanAll += vem / double(nPMTs);
335 const double pmtSFluct = EstimateSignalFluct(currPMT, isPMTHGSat, jTr);
337 countSignalTh += (vem > fDLESignalThreshold);
339 if (iPMT != outlierid) {
340 meanRed += vem / (nPMTs - 1);
341 sigmaSignal +=
Sqr(pmtSFluct / (nPMTs - 1));
342 }
else if (iPMT == outlierid) {
344 sigmaSignal +=
Sqr(pmtSFluct);
349 sigmaSignal =
sqrt(sigmaSignal);
350 const double filterValue = (signalOutlier - meanRed) / sigmaSignal;
353 if (filterValue >= fDLEFilterThreshold && countSignalTh > 0) {
355 double signalRepl = 0;
358 signalRepl = meanAll;
360 signalRepl = (meanAll*nPMTs - signalOutlier) / (nPMTs - 1);
370 workingPMTsIds.clear();
377 const unsigned int startIntegration,
378 const unsigned int endIntegration,
379 const double traceIntegral)
382 if (traceIntegral <= 0)
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;
395 double runningSum = 0;
400 for (
unsigned int i = startIntegration; i < endIntegration; ++i) {
402 const double binValue = trace[i];
403 runningSum += binValue;
405 if (!riseStartBin && runningSum > riseStartSentry)
406 riseStartBin = i - (runningSum - riseStartSentry) / (runningSum - oldSum);
408 if (!riseEndBin && runningSum > riseEndSentry)
409 riseEndBin = i - (runningSum - riseEndSentry) / (runningSum - oldSum);
411 if (!fallStartBin && runningSum > fallStartSentry)
412 fallStartBin = i - (runningSum - fallStartSentry) / (runningSum - oldSum);
414 if (!fallEndBin && runningSum > fallEndSentry)
415 fallEndBin = i - (runningSum - fallEndSentry) / (runningSum - oldSum);
424 if (fOverwriteVEMTrace) {
425 pmtRec.
SetRiseTime(binTiming * (riseEndBin-riseStartBin), 0);
426 pmtRec.
SetFallTime(binTiming * (fallEndBin-fallStartBin), 0);
434 auto& cc = *CentralConfig::GetInstance();
439 topBranch.
GetChild(
"calcCorrSignalRiseFall").
GetData(fCalcCorrSignalRiseFall);
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]");
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");
455 std::ostringstream info;
456 if (fCalcCorrSignalRiseFall) {
458 "\tRisetime fractions: " << fRiseTimeFractions.first
459 <<
' ' << fRiseTimeFractions.second
460 <<
"\tFalltime fractions: " << fFallTimeFractions.first
461 <<
' ' << fFallTimeFractions.second <<
'\n';
467 fCleaned = fOverwriteVEMTrace ?
470 topBranch.
GetChild(
"doCorrectionIndividual").
GetData(fDoCorrectionIndividual);
471 topBranch.
GetChild(
"doCorrectionAverage").
GetData(fDoCorrectionAverage);
483 fFormulaDLEParA =
new TFormula(
"fDLEFormulaParA", fAsymmParA.c_str());
484 fFormulaDLEParB =
new TFormula(
"fDLEFormulaParB", fAsymmParB.c_str());
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';
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';
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";
507 fFormulaDLEParA->Delete();
508 fFormulaDLEParA =
nullptr;
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";
518 fFormulaDLEParB->Delete();
519 fFormulaDLEParB =
nullptr;
525 topBranch.
GetChild(
"excludeBadTracesCalc").
GetData(fExcludeBadTracesCalc);
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");
554 return eContinueLoop;
556 auto& sevent =
event.GetSEvent();
559 bool flagHasRecShower =
false;
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);
571 for (
auto& station : sevent.StationsRange()) {
573 if (!station.HasRecData())
576 const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
578 const unsigned int saturationValue = dStation.GetSaturationValue();
579 fTraceSize = dStation.GetFADCTraceLength();
580 fBinSize = dStation.GetFADCBinSize();
582 auto& sRec = station.GetRecData();
583 const unsigned int startIntegration = sRec.GetSignalStartSlot();
584 const unsigned int endIntegration = sRec.GetSignalEndSlot();
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());
596 for (
auto& pmt : station.PMTsRange()) {
598 if (!pmt.HasRecData())
601 auto& pmtRec = pmt.GetRecData();
602 if (!pmtRec.HasVEMTrace(fComponent))
605 pmtRec.SetRiseTimeCleaned(pmtRec.GetRiseTime(),
606 pmtRec.GetRiseTimeRMS());
607 pmtRec.SetFallTimeCleaned(pmtRec.GetFallTime(),
608 pmtRec.GetFallTimeRMS());
613 if (!station.IsCandidate())
618 for (
auto& pmt : station.PMTsRange()) {
620 if (!pmt.HasRecData())
623 auto& pmtRec = pmt.GetRecData();
624 if (!pmtRec.HasVEMTrace(fComponent))
627 const auto& vemtraceComp = pmtRec.GetVEMTrace(fComponent);
629 if (!pmtRec.HasVEMTrace(fCleaned))
630 pmtRec.MakeVEMTrace(fCleaned);
632 auto& vemtraceClean = pmtRec.GetVEMTrace(fCleaned);
633 for (
unsigned int i = 0; i < fTraceSize; ++i)
634 vemtraceClean[i] = vemtraceComp[i];
637 bool flagPMTSel = SelectPMT(pmt,
638 station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
646 bool flagStationCorr =
true;
647 for (
unsigned int iSt = 0; iSt < fExcludeStations.size(); ++iSt) {
648 if (station.GetId() == fExcludeStations[iSt])
649 flagStationCorr =
false;
652 if (flagStationCorr) {
654 if (fDoCorrectionIndividual && nPMTs >= fDLEMinNPMTs)
655 CorrectIndividualDLE(station);
658 if (fDoCorrectionAverage && flagHasRecShower)
659 CorrectAverageDLE(station, theta, phi);
662 double totalCharge = 0;
663 Accumulator::SampleStandardDeviationN riseStat;
664 Accumulator::SampleStandardDeviationN fallStat;
668 for (
auto& pmt : station.PMTsRange()) {
670 if (!pmt.HasRecData())
673 auto& pmtRec = pmt.GetRecData();
674 if (!pmtRec.HasVEMTrace(fComponent) || !pmtRec.HasVEMTrace(fCleaned))
678 const bool flagPMTSel = SelectPMT(pmt,
679 station.IsLowGainSaturation(), station.IsHighGainSaturation(), saturationValue);
684 const double vemCharge = pmtRec.GetVEMCharge();
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;
693 ComputeCleanedRiseFall(pmtRec, startIntegration, endIntegration+1, pmtIntegral);
695 riseStat(pmtRec.GetRiseTimeCleaned());
696 fallStat(pmtRec.GetFallTimeCleaned());
701 const int n = nTraces;
703 if (!n || !totalCharge)
707 sRec.SetTotalSignalCleaned(totalCharge, sRec.GetTotalSignalError());
709 if (fOverwriteVEMTrace)
710 sRec.SetTotalSignal(totalCharge, sRec.GetTotalSignalError());
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));
724 sRec.SetRiseTimeCleaned(riseStat.GetAverage(n), 0);
725 sRec.SetFallTimeCleaned(fallStat.GetAverage(n), 0);
727 if (fOverwriteVEMTrace) {
728 sRec.SetRiseTime(riseStat.GetAverage(n), 0);
729 sRec.SetFallTime(fallStat.GetAverage(n), 0);
739 DLECorrection::Finish()
741 delete fFormulaDLEParA;
742 fFormulaDLEParA =
nullptr;
743 delete fFormulaDLEParB;
744 fFormulaDLEParB =
nullptr;
Branch GetTopBranch() const
utl::TraceD & GetVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal)
Traces calibrated in VEM Peak.
bool HasRecData() const
Check for existenc of PMT reconstructed data object.
void SetRiseTimeCleaned(const double riseTime, const double rms)
constexpr T Sqr(const T &x)
class to hold data at PMT level
Detector description interface for Station-related data.
total (shower and background)
PMTCalibData & GetCalibData()
Get object containing PMT calibration data.
bool HasRecShower() const
PMTRecData & GetRecData()
Get object containing PMT reconstructed data.
bool HasCalibData() const
Check for existence of PMT calibration data object.
std::map< std::string, std::string > AttributeMap
void SetFallTime(const double fallTime, const double rms)
#define INFO(message)
Macro for logging informational messages.
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
bool IsHighGainSaturation() const
Class representing a document branch.
class to hold data at Station level
class to hold reconstructed data at PMT level
unsigned int GetSaturationValue() const
void SetFallTimeCleaned(const double fallTime, const double rms)
signal after subtracting direct light (includes all particle sources).
void GetData(bool &b) const
Overloads of the GetData member template function.
utl::TraceI & GetFADCTrace(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain, const StationConstants::SignalComponent source=StationConstants::eTotal)
bool IsLowGainSaturation() const
Check which gains are saturated.
ResultFlag
Flag returned by module methods to the RunController.
PMT & GetPMT(const unsigned int pmtId)
Retrive a PMT by Id.
void SetRiseTime(const double riseTime, const double rms)
#define ERROR(message)
Macro for logging error messages.
double GetGainRatio() const