3 #include <fwk/CentralConfig.h>
5 #include <sdet/SDetector.h>
6 #include <sevt/SEvent.h>
7 #include <sevt/EventTrigger.h>
8 #include <sevt/StationCalibData.h>
9 #include <utl/QuadraticFitter.h>
10 #include <utl/ExponentialFitter.h>
18 namespace SdHistogramFitterOG {
21 template<
typename T1,
typename T2>
23 operator<<(ostream& os, pair<T1, T2>&
p)
25 return os <<
'[' <<
p.first <<
", " <<
p.second <<
']';
35 topB.GetChild(
"peakFitChi2Accept").GetData(fPeakFitChi2Accept);
36 topB.GetChild(
"peakOnlineToVEMFactor").GetData(fPeakOnlineToVEMFactor);
37 topB.GetChild(
"peakHistogramToVEMFactor").GetData(fPeakHistogramToVEMFactor);
38 topB.GetChild(
"peakOnlineToMIPFactor").GetData(fPeakOnlineToMIPFactor);
39 topB.GetChild(
"peakHistogramToMIPFactor").GetData(fPeakHistogramToMIPFactor);
40 topB.GetChild(
"chargeFitShoulderHeadRatio").GetData(fChargeFitShoulderHeadRatio);
41 topB.GetChild(
"chargeFitChi2Accept").GetData(fChargeFitChi2Accept);
42 topB.GetChild(
"chargeOnlineToVEMFactor").GetData(fChargeOnlineToVEMFactor);
43 topB.GetChild(
"chargeHistogramToVEMFactor").GetData(fChargeHistogramToVEMFactor);
44 topB.GetChild(
"chargeOnlineToMIPFactor").GetData(fChargeOnlineToMIPFactor);
45 topB.GetChild(
"chargeHistogramToMIPFactor").GetData(fChargeHistogramToMIPFactor);
47 auto shapeFitB = topB.GetChild(
"shapeFitRange");
48 shapeFitB.GetChild(
"beforeCalibrationVersion12").GetData(fShapeFitRangeBefore12);
49 shapeFitB.GetChild(
"sinceCalibrationVersion12").GetData(fShapeFitRangeSince12);
52 info <<
"Parameters:\n"
53 "peakFitRange: " << fPeakFitRange <<
"\n"
54 "peakFitChi2Accept: " << fPeakFitChi2Accept <<
"\n"
55 "peakOnlineToVEMFactor: " << fPeakOnlineToVEMFactor <<
"\n"
56 "peakHistogramToVEMFactor: " << fPeakHistogramToVEMFactor <<
"\n"
57 "peakOnlineToMIPFactor: " << fPeakOnlineToMIPFactor <<
"\n"
58 "peakHistogramToMIPFactor: " << fPeakHistogramToMIPFactor <<
"\n"
59 "chargeFitShoulderHeadRatio: " << fChargeFitShoulderHeadRatio <<
"\n"
60 "chargeFitChi2Accept: " << fChargeFitChi2Accept <<
"\n"
61 "chargeOnlineToVEMFactor: " << fChargeOnlineToVEMFactor <<
"\n"
62 "chargeHistogramToVEMFactor: " << fChargeHistogramToVEMFactor <<
"\n"
63 "chargeOnlineToMIPFactor: " << fChargeOnlineToMIPFactor <<
"\n"
64 "chargeHistogramToMIPFactor: " << fChargeHistogramToMIPFactor <<
"\n"
66 " beforeCalibrationVersion12: " << fShapeFitRangeBefore12 <<
"\n"
67 " sinceCalibrationVersion12: " << fShapeFitRangeSince12;
79 auto& sEvent =
event.GetSEvent();
82 fToldYaCharge =
false;
86 for (
auto& station : sEvent.StationsRange()) {
88 if (!station.HasTriggerData() ||
89 !station.HasCalibData() ||
90 !station.HasGPSData())
93 const auto& trig = station.GetTriggerData();
94 if (trig.IsRandom() ||
95 (trig.GetErrorCode() & 0xff) ||
96 station.GetCalibData().GetVersion() > 32000)
100 if (sEvent.HasTrigger()) {
101 const int trigSecond = sEvent.GetTrigger().GetTime().GetGPSSecond();
102 const int timeDiff = int(station.GetGPSData().GetSecond()) - trigSecond;
103 if (
abs(timeDiff) > 1)
107 const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
108 fIsUub = dStation.IsUUB();
110 CalculatePeakAndCharge(station);
113 if (fIsUub && station.HasSmallPMTData()) {
114 if (CopySmallPMTCalibData(station)) {
115 station.GetSmallPMTData().SetIsTubeOk();
117 station.GetSmallPMTData().SetIsTubeOk(
false);
118 station.GetSmallPMT().GetCalibData().SetIsTubeOk(
false);
120 warn <<
"Station " << station.GetId() <<
": No valid SmallPMT calibration."
121 " Setting IsTubeOk as false for SmallPMT.";
133 SdHistogramFitter::CalculatePeakAndCharge(
Station& station)
136 const auto calibVersion = stationCalib.
GetVersion();
138 const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(station);
145 const auto type = pmt.GetType();
153 if (!pmt.HasCalibData())
156 const auto& pmtCalib = pmt.GetCalibData();
158 if (!pmtCalib.IsTubeOk())
161 if (!pmt.HasRecData())
163 auto& pmtRec = pmt.GetRecData();
166 if (!pmtRec.GetVEMPeak()) {
168 const double onlineFactor =
170 double vemPeak = pmtCalib.GetOnlinePeak() * onlineFactor;
171 double vemPeakErr = 0;
172 pmtRec.SetOnlineVEMPeak(vemPeak, vemPeakErr);
175 bool vemPeakFromHisto =
false;
178 if (calibVersion > 8) {
179 const auto& peakHistoBinning = dStation.GetMuonPeakHistogramBinning<
short>(type, calibVersion);
180 const int muonPeakHistoSize = pmtCalib.GetMuonPeakHisto().size();
181 if (!muonPeakHistoSize ||
int(peakHistoBinning.size())-1 != muonPeakHistoSize) {
182 if (!(fToldYaPeak || pmt.HasSimData())) {
183 WARNING(
"According to the LS calibration version there should be a muon peak histogram... Will not tell you again!");
188 const double histoFactor =
190 const double predictedHistoPeak = vemPeak / histoFactor;
191 if (predictedHistoPeak > 0 && peakHisto.GetMaximum() > 200) {
192 const double baseEstimate = pmtCalib.GetBaseline() - pmtCalib.GetMuonPeakHistoOffset();
193 const double base = (fabs(baseEstimate) < 20) ? baseEstimate : 0;
194 const double peakLow = fPeakFitRange.first * predictedHistoPeak;
195 const double peakHigh = fPeakFitRange.second * predictedHistoPeak;
197 if (peakHigh - peakLow >= 5) {
203 peakLow + base, peakHigh + base).GetFitData(qf);
204 pmtRec.GetMuonPeakFitData() = qf;
207 if (peakLow <= fittedPeak && fittedPeak <= peakHigh &&
209 vemPeak = fittedPeak * histoFactor;
211 vemPeakFromHisto =
true;
220 pmtRec.SetVEMPeak(vemPeak, vemPeakErr);
221 pmtRec.SetIsVEMPeakFromHistogram(vemPeakFromHisto);
224 if (!pmtRec.GetVEMCharge()) {
229 const double onlineFactor =
231 double vemCharge = pmtCalib.GetOnlineCharge() * onlineFactor;
232 double vemChargeErr = 20 * onlineFactor;
233 pmtRec.SetOnlineVEMCharge(vemCharge, vemChargeErr);
234 bool vemChargeFromHisto =
false;
235 double muChargeSlope = 0;
238 if (calibVersion > 8) {
239 const auto& chargeHistoBinning = dStation.GetMuonChargeHistogramBinning<
double>(type, calibVersion);
240 const int muonChargeHistoSize = pmtCalib.GetMuonChargeHisto().size();
242 if (!muonChargeHistoSize ||
int(chargeHistoBinning.size()) - 1 != muonChargeHistoSize) {
243 if (!fToldYaCharge) {
244 WARNING(
"According to the LS calibration version there should be a muon charge histogram... Will not tell you again!");
245 fToldYaCharge =
true;
248 const CalibHistogram chargeHisto(chargeHistoBinning, pmtCalib.GetMuonChargeHisto());
250 const double baseEstimate = pmtCalib.GetBaseline() *
251 (calibVersion == 13 ? 19 : 20) - pmtCalib.GetMuonChargeHistoOffset();
252 const double base = (fabs(baseEstimate) < 20) ? baseEstimate : 0;
254 if (chargeHisto.GetMaximum() > 500) {
257 const int size = chargeHisto.GetNBins();
258 int start = (size - 1) - 5;
261 const auto small = fIsUub ? 40 : 300;
262 for ( ; start >= 2 && chargeHisto.GetBinAverage(start) < small; --start)
271 double maxValue = chargeHisto.GetBinAverage(start);
274 double value = chargeHisto.GetBinAverage(start - 1);
275 double value1 = chargeHisto.GetBinAverage(start - 2);
276 for (
int pos = start - 1; pos >= 2; --pos) {
277 if (maxValue < value) {
281 const double reducedMax = maxValue * fChargeFitShoulderHeadRatio;
284 const double value2 = chargeHisto.GetBinAverage(pos - 2);
285 if (value <= reducedMax && value1 <= reducedMax && value2 <= reducedMax) {
295 const double reducedMax = maxValue * fChargeFitShoulderHeadRatio;
296 const int size2 = size - 2;
298 int shoulderHigh = 0;
300 double value = chargeHisto.GetBinAverage(maxBin + 1);
301 double value1 = chargeHisto.GetBinAverage(maxBin + 2);
302 for (
int pos = maxBin + 1; pos < size2; ++pos) {
303 const double value2 = chargeHisto.GetBinAverage(pos+2);
304 if (value <= reducedMax && value1 <= reducedMax && value2 <= reducedMax) {
314 const double chargeLow = chargeHisto.GetBinCenter(shoulderLow);
315 const double chargeHigh = chargeHisto.GetBinCenter(shoulderHigh);
316 const double histoFactor =
318 const double predictedHistoCharge = vemCharge / histoFactor;
319 if (chargeLow <= predictedHistoCharge && predictedHistoCharge <= chargeHigh) {
324 pmtRec.GetMuonChargeFitData() = qf;
328 if (chargeLow <= fittedCharge && fittedCharge <= chargeHigh &&
330 vemCharge = fittedCharge * histoFactor;
332 pmtRec.SetHistogramVEMCharge(vemCharge, vemChargeErr);
333 vemChargeFromHisto =
true;
338 "Quadratic fit between bins " << chargeLow <<
" and " << chargeHigh
339 <<
" failed on this charge histogram:\n";
340 for (
unsigned int i = 0, n = chargeHisto.GetNBins(); i < n; ++i)
341 warn << chargeHisto.GetBinCenter(i) <<
' ' << chargeHisto.GetBinAverage(i) <<
'\n';
348 const double start = chargeHigh + 10;
349 const double stop = min(2*start, 950.);
350 if (start+10 < stop) {
352 pmtRec.GetMuonChargeSlopeFitData() = ef;
354 const double slope = vemCharge * ef.
GetSlope();
357 muChargeSlope = slope;
368 pmtRec.SetVEMCharge(vemCharge, vemChargeErr);
369 pmtRec.SetIsVEMChargeFromHistogram(vemChargeFromHisto);
370 pmtRec.SetMuonChargeSlope(muChargeSlope);
374 double muDecayTime = 0;
375 double muDecayTimeErr = 0;
376 if (calibVersion > 8) {
378 if (pmtCalib.GetMuonShapeHisto().empty()) {
380 WARNING(
"According to the LS calibration version there should be a muon shape histogram... Will not tell you again!");
384 const auto& muShapeHisto = pmtCalib.GetMuonShapeHisto();
385 const unsigned int size = muShapeHisto.size();
391 const auto& shapeHistoBinning = dStation.GetMuonShapeHistogramBinning(calibVersion);
392 const double subtract = muShapeHisto[0];
394 ShapeHistogram(shapeHistoBinning, muShapeHisto),
395 calibVersion < 12 ? fShapeFitRangeBefore12 : fShapeFitRangeSince12
396 ).GetFit(ef, subtract);
397 pmtRec.GetMuonShapeFitData() = ef;
403 const double decayTime = -1 / slope;
404 if (0 <= decayTime && decayTime < 1000*
nanosecond) {
405 muDecayTime = decayTime;
406 muDecayTimeErr = slopeErr /
Sqr(slope);
415 pmtRec.SetMuonPulseDecayTime(muDecayTime, muDecayTimeErr);
422 SdHistogramFitter::CopySmallPMTCalibData(
Station& station)
426 if (!spmt.HasCalibData())
431 if (!spmtCalib.IsTubeOk())
436 if (!pmt.HasCalibData())
441 if (!pmtCalib.IsTubeOk())
444 if (!pmt.HasRecData())
446 auto& pmtRec = pmt.GetRecData();
448 const double spmtVemCharge = 1 / (spmtCalib.GetBeta() * spmtCalib.GetCorrectionFactor());
449 const double spmtVemChargeErr =
450 spmtCalib.GetBetaError() * spmtCalib.GetCorrectionFactor() *
Sqr(spmtVemCharge);
452 if (std::isnan(spmtVemCharge) || std::isinf(spmtVemCharge) ||
453 spmtVemCharge <= 0 || spmtVemChargeErr <= 0)
456 pmtRec.SetVEMCharge(spmtVemCharge, spmtVemChargeErr);
459 double muonAreaOverPeak = 0;
460 for (
const auto& lpmt : station.PMTsRange()) {
461 if (lpmt.HasCalibData() &&
462 lpmt.GetCalibData().IsTubeOk() &&
464 lpmt.GetRecData().GetVEMPeak() > 0)
466 lpmt.GetRecData().GetVEMCharge() / lpmt.GetRecData().GetVEMPeak();
468 if (muonAreaOverPeak > 0)
469 pmtRec.SetVEMPeak(spmtVemCharge / muonAreaOverPeak, 0);
472 warn <<
"Station " << station.
GetId()
473 <<
": Cannot calculate properly SmallPMT VEMpeak. Using default value = 1/3";
475 pmtRec.SetVEMPeak(1./3, 0);
479 info <<
"SmallPMT calibration for station " << station.
GetId() <<
"\n"
480 <<
" beta = " << spmtCalib.GetBeta() <<
" +- " << spmtCalib.GetBetaError()
481 <<
" ---> VEMcharge = " << pmtRec.GetVEMCharge() <<
" +- " << pmtRec.GetVEMChargeError()
482 <<
" (VEMpeak = " << pmtRec.GetVEMPeak() <<
')';
485 pmtRec.SetIsVEMChargeFromHistogram(
false);
486 pmtRec.SetIsVEMPeakFromHistogram(
false);
488 pmtRec.SetMuonChargeSlope(0);
489 pmtRec.SetMuonPulseDecayTime(0, 0);
490 pmtRec.SetGainRatio(1);
int GetId() const
Get the station Id.
constexpr T Sqr(const T &x)
Holds result of the quadratic fit.
PMTCalibData & GetCalibData()
Get object containing PMT calibration data.
double GetExtremePositionError() const
#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.
constexpr double GetNominalVEMPeak(const bool isUub)
Exception for reporting variable out of valid range.
SmallPMTCalibData & GetCalibData()
class to hold data at Station level
ExponentialFitter< Histogram > MakeExponentialFitter(const Histogram &histogram, const T &start, const T &stop)
constexpr double nanosecond
double abs(const SVector< n, T > &v)
SmallPMTData & GetSmallPMTData()
#define WARNING(message)
Macro for logging warning messages.
QuadraticFitter< Histogram, ErrorPolicy > MakeQuadraticFitter(const Histogram &h, const ErrorPolicy)
void GetData(bool &b) const
Overloads of the GetData member template function.
sevt::StationCalibData & GetCalibData()
Get calibration data for the station.
ResultFlag
Flag returned by module methods to the RunController.
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
double GetExtremePosition() const
int GetVersion() const
version of the onboard calibration
double GetSlopeError() const
const std::string & GetMessage() const
Retrieve the message from the exception.
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)