4 #include <utl/Histogram.h>
6 #include <sdet/Station.h>
7 #include <sevt/Station.h>
9 #include <sevt/PMTCalibData.h>
10 #include <utl/QuadraticFitData.h>
11 #include <utl/ExponentialFitData.h>
16 #include <TGraphErrors.h>
17 #include <TPaveText.h>
26 using namespace SdCalibPlotterOG;
35 os <<
"MuPeak PMT " << pmtId;
37 auto& peak = Add(
new TH1D(os.str().c_str(), os.str().c_str(), peakBinning.size()-1, &peakBinning[0]));
39 SetContent(peak, peakBinning, pmtCalib.GetMuonPeakHisto(),
"peak");
40 peak.SetLineColor(kRed);
44 const double lsValue = pmtCalib.GetOnlinePeak() + pmtCalib.GetBaseline() - offset;
48 DrawQuadraticFit(peak, lsValue);
49 const double peakMax = peak.GetMaximum();
50 DrawBaseline(pmtCalib, peakMax);
51 DrawOffset(offset, peakMax);
62 os <<
"MuCharge PMT" << pmtId;
65 auto& charge = Add(
new TH1D(os.str().c_str(), os.str().c_str(), chargeBinning.size()-1, &chargeBinning[0]));
66 SetContent(charge, chargeBinning, pmtCalib.GetMuonChargeHisto(),
"charge");
67 charge.SetLineColor(kRed);
68 charge.SetStats(
false);
70 const int offset = pmtCalib.GetMuonChargeHistoOffset();
71 const int baseFact = pmtCalib.GetMuonShapeHisto().size();
72 const double lsValue = pmtCalib.GetOnlineCharge()*1.045 + pmtCalib.GetBaseline() * baseFact - offset;
78 DrawQuadraticFit(charge, lsValue);
79 const double chargeMax = charge.GetMaximum();
80 DrawBaseline(pmtCalib, chargeMax);
81 DrawOffset(
double(offset) / baseFact, chargeMax);
87 MuonShapeView::Draw(
const sdet::Station& dStation,
const PMT& pmt,
const int pmtId,
const int calibVersion)
93 os <<
"MuShape PMT" << pmtId;
95 auto& shape = Add(
new TH1D(os.str().c_str(), os.str().c_str(), shapeBinning.size()-1, &shapeBinning[0]));
97 SetContent(shape, shapeBinning, pmtCalib.GetMuonShapeHisto(),
"shape", 0);
98 shape.SetLineColor(kRed);
99 shape.SetStats(
false);
103 DrawExponentialFit(shape, pmtRec.GetMuonShapeFitData());
104 DrawDecay(pmtRec.GetMuonPulseDecayTime());
117 os <<
"MuBase PMT" << pmtId;
118 const auto& baseBinning = dStation.GetBaselineHistogramBinning<
double>();
119 auto& base = Add(
new TH1D(os.str().c_str(), os.str().c_str(), baseBinning.size()-1, &baseBinning[0]));
121 SetContent(base, baseBinning, pmtCalib.GetMuonBaseHisto(),
"base");
122 base.SetLineColor(kRed);
123 base.SetStats(
false);
131 HistoView::DividePage(TCanvas&
c,
const double xmargin,
const double ymargin)
133 const auto savePad = (TPad*)gPad;
135 const string name = c.GetName();
139 for (
int row = 0; row < nRows; ++row) {
140 const double y1 = 1 - (row+1)*(1 - ymargin)/nRows;
141 const double y2 = 1 - ymargin - row*(1 - ymargin)/nRows;
142 const int nColumns = (row ? (row < 4 ? 2 : 3) : 1);
143 for (
int column = 0; column < nColumns; ++column) {
144 const double x1 = xmargin + column*(1 - xmargin)/nColumns;
145 const double x2 = (column+1)*(1 - xmargin)/nColumns;
146 os.str(
""); os << name <<
'_' << row+1 << column+1;
147 const auto pad =
new TPad(os.str().c_str(), os.str().c_str(), x1, y1, x2, y2, 0);
157 HistoView::HasNoCalib(
const PMT& pmt)
160 auto& pt = Add(
new TPaveText(0.3,0.4,0.7,0.6,
"ndc"));
162 pt.SetFillColor(kRed);
164 pt.AddText(
"No Calibration Data");
173 HistoView::IsNotOK(
const PMT& pmt)
176 auto& pt = Add(
new TPaveText(0.5,0.43,0.8,0.57,
"ndc"));
178 pt.SetFillColor(kRed);
180 pt.AddText(
"Tube not OK");
189 HistoView::SetContent(TH1D& rh,
190 const vector<double>& bins,
const vector<int>& hist,
192 const int subtractBin)
195 if (bins.size()-1 != hist.size()) {
197 warn <<
"Mismatch in PMT " << what <<
" histogram: " << bins.size()-1 <<
" bin intervals "
198 "but " << hist.size() <<
" values!";
204 const double sub = (subtractBin >= 0 ? h.
GetBinAverage(subtractBin) : 0);
206 for (
int i = 0; i < n; ++i) {
208 rh.SetBinContent(i+1, (val > 0 ? val : 0));
215 const double lsValue)
217 const string parabolaName = string(hist.GetName()) +
"_parabola";
218 auto& par = Add(
new TF1(parabolaName.c_str(),
219 [&qf](
double* x,
double*) {
return qf(*x); }, qf.
GetStart(), qf.
GetStop(), 0));
221 par.SetLineColor(kBlue);
224 const double yext = qf(x);
225 const double y = 1.15 * yext;
228 auto& gfit = Add(
new TGraphErrors(1, &x, &y, &dx, 0));
229 gfit.SetLineColor(kBlue);
230 gfit.SetMarkerStyle(kFullCircle);
231 gfit.SetMarkerColor(kBlue);
232 gfit.SetMarkerSize(0.5);
234 const double yy = 1.1 * y;
235 const double histMax = hist.GetMaximum();
238 DrawQuadraticFit(hist, lsValue, y);
243 HistoView::DrawQuadraticFit(TH1D& hist,
const double lsValue,
const double fitValue)
245 const double hMax = hist.GetMaximum();
246 const double hValue = hist.GetBinContent(hist.FindBin(lsValue));
247 const bool up = (hValue > 0.5*hMax);
248 const double y2 = up ? 0.82*hValue :
max(hValue + 0.15*hMax, 1.15*fitValue);
249 const double y1 = up ? 0.5*y2 : y2 + 0.5*(hMax-y2);
251 auto& als = Add(
new TArrow(lsValue, y1, lsValue, y2, 0.01));
261 const string exponentialName = string(hist.GetName()) +
"_exponential";
262 auto& ex = Add(
new TF1(exponentialName.c_str(),
263 [&ef](
double* x,
double*) {
return ef(*x); }, ef.
GetStart(), ef.
GetStop(), 0));
267 ex.SetLineColor(kBlue);
276 const double y = 0.19*
max;
278 auto&
g = Add(
new TGraphErrors(1, &x, &y, &dx, 0));
280 g.SetMarkerColor(46);
286 HistoView::DrawOffset(
const double x,
const double max)
288 const double y = 0.15*
max;
289 auto&
a = Add(
new TArrow(x, y, x, 0, 0.01));
291 a.SetLineColor(kBlack);
297 HistoView::DrawAverage(TH1D& h)
299 const double x = h.GetMean();
300 const double dx =
sqrt(
Sqr(h.GetMeanError()) +
Sqr(h.GetBinWidth(1))/12);
301 const double y = 0.01*h.GetMaximum();
302 auto&
g = Add(
new TGraphErrors(1, &x, &y, &dx, &y));
303 g.SetLineColor(kBlack);
304 g.SetMarkerColor(kBlack);
306 const double y2 = 0.1*y;
307 const double dx2 = h.GetRMS();
308 auto& g2 = Add(
new TGraphErrors(1, &x, &y2, &dx2, 0));
309 g2.SetLineColor(kBlack);
310 g2.SetMarkerColor(kBlack);
316 HistoView::DrawDecay(
const double time)
319 os <<
"#tau = " << setprecision(4) << time/
nanosecond <<
" ns";
320 auto& pt = Add(
new TPaveText(0.58,0.77,0.87,0.85,
"ndc"));
322 pt.SetFillColor(kWhite);
324 pt.AddText(os.str().c_str());
bool HasRecData() const
Check for existenc of PMT reconstructed data object.
constexpr T Sqr(const T &x)
Holds result of the quadratic fit.
class to hold data at PMT level
double GetBaselineRMS(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain) const
Detector description interface for Station-related data.
PMTCalibData & GetCalibData()
Get object containing PMT calibration data.
sdet::PMTConstants::PMTType GetType() const
double GetExtremePositionError() const
int GetMuonPeakHistoOffset() const
x-axis offset of the muon peak histogram
PMTRecData & GetRecData()
Get object containing PMT reconstructed data.
bool HasCalibData() const
Check for existence of PMT calibration data object.
utl::ExponentialFitData & GetMuonChargeSlopeFitData()
double GetBinAverage(const size_t i) const
double GetAmplitude() const
class to hold data at Station level
utl::QuadraticFitData & GetMuonChargeFitData()
utl::QuadraticFitData & GetMuonPeakFitData()
constexpr double nanosecond
const std::vector< double > & GetMuonShapeHistogramBinning(const int calibrationVersion) const
#define WARNING(message)
Macro for logging warning messages.
sevt::StationCalibData & GetCalibData()
Get calibration data for the station.
double GetBaseline(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain) const
double GetExtremePosition() const
int GetVersion() const
version of the onboard calibration