40{
41 if (!
object.
IsA()->InheritsFrom(
"TH1")) {
42 throw dqm_core::BadConfig(ERS_HERE, name, "histogram does not inherit from TH1");
43 }
46 throw dqm_core::BadConfig(ERS_HERE, name, "histogram has more than one dimension");
47 }
49 if (
histogram.GetEffectiveEntries() < minstat) {
50 dqm_core::Result *
result =
new dqm_core::Result(dqm_core::Result::Undefined);
51 result->tags_[
"InsufficientEffectiveEntries"] =
histogram.GetEffectiveEntries();
53 }
55 if (sigmaRange <= 0) {
56 throw dqm_core::BadConfig(ERS_HERE, name, "SigmaRange must be greater than zero.");
57 }
58 if (sigmaRange < 1) {
59 ERS_DEBUG(1, "Careful, your SigmaRange = " << sigmaRange << " is rather small");
60 }
63 if (sigmaMax < 0) {
64 throw dqm_core::BadConfig(ERS_HERE, name, "SigmaMax must be greater than zero.");
65 }
66
67 std::unique_ptr<TH1>
h(
static_cast<TH1 *
>(
histogram.Clone()));
68
69 auto f = std::make_unique<TF1> (
"f",
"gaus");
70 if (sigmaMax) {
71 f->SetParLimits(2, 0, sigmaMax);
72 f->SetParameter(2, sigmaMax / 2);
73 f->SetRange(meanNominal - sigmaMax, meanNominal + sigmaMax);
74 }
75
76 const unsigned int maxIterations = 10;
77 const double sufficientPrecision = 0.01;
78
80 while (true) {
81 const double sigmaOld = (
i == 0) ? 0 :
f->GetParameter(2);
82 std::string fitOptions("INQ");
83 if (i > 0 || sigmaMax) fitOptions.append("R");
84 if (sigmaMax) fitOptions.append("B");
85
86 const int fitStatus =
h->Fit(
f.get(), fitOptions.c_str());
87 if (fitStatus) {
88 ERS_DEBUG(1, "Fit failed in iteration " << i << ", status = " << fitStatus);
89 dqm_core::Result *
result =
new dqm_core::Result(dqm_core::Result::Red);
90 if (fitStatus < 0)
result->status_ = dqm_core::Result::Undefined;
92 result->tags_[
"FitStatus"] = fitStatus;
94 }
95
96 const double mean =
f->GetParameter(1);
97 const double sigma =
f->GetParameter(2);
98 ERS_DEBUG(2,
"Iteration " << i <<
": mean = " <<
mean <<
", sigma = " << sigma);
99 f->SetRange(
mean - sigmaRange * sigma,
mean + sigmaRange * sigma);
100
101 if (sigma == 0) {
102 ERS_DEBUG(1, "Fit yielded sigma = 0 in iteration " << i);
103 dqm_core::Result *
result =
new dqm_core::Result(dqm_core::Result::Red);
104 result->tags_[
"Iteration"] =
i;
108 }
109
110 if (sigma == sigmaMax) {
111 ERS_DEBUG(1, "Fit result for sigma is at the limit " << sigmaMax);
112 dqm_core::Result *
result =
new dqm_core::Result(dqm_core::Result::Red);
113 result->tags_[
"Iteration"] =
i;
115 result->tags_[
"SigmaMax"] = sigmaMax;
117 }
118
119 if ((std::fabs(sigma - sigmaOld) / sigma) < sufficientPrecision) break;
120
121 if (i >= maxIterations) {
122 ERS_DEBUG(1, "Sorry, this is not taking us anywhere: the iteration does not seem to converge");
123 dqm_core::Result *
result =
new dqm_core::Result(dqm_core::Result::Undefined);
124 result->tags_[
"Iteration"] =
i;
125 result->tags_[
"SigmaOld"] = sigmaOld;
128 }
130 }
131
132 const int ndf =
f->GetNDF();
133 const double chi2 =
f->GetChisquare();
134 const double chi2NDF = (
ndf > 0) ? (
chi2 / ndf) : 0;
135
136 std::map<std::string, double> resultValues;
137 resultValues[
"Constant"] =
f->GetParameter(0);
138 resultValues[
"ConstantError"] =
f->GetParError(0);
139 resultValues[
"Mean"] =
f->GetParameter(1);
140 resultValues[
"MeanError"] =
f->GetParError(1);
141 resultValues[
"Sigma"] =
f->GetParameter(2);
142 resultValues[
"SigmaError"] =
f->GetParError(2);
143 resultValues["Chi2NDF"] = chi2NDF;
144 resultValues[
"Probability"] =
f->GetProb();
145 resultValues[
"MeanDeviation"] = std::fabs(
f->GetParameter(1) - meanNominal);
147}
double chi2(TH1 *h0, TH1 *h1)
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
#define IsA
Declare the TObject style functions.