5 #include "dqm_core/AlgorithmConfig.h"
6 #include "dqm_core/AlgorithmManager.h"
41 if (!
object.
IsA()->InheritsFrom(
"TH1")) {
42 throw dqm_core::BadConfig(ERS_HERE,
name,
"histogram does not inherit from TH1");
46 throw dqm_core::BadConfig(ERS_HERE,
name,
"histogram has more than one dimension");
49 if (
histogram.GetEffectiveEntries() < minstat) {
51 result->tags_[
"InsufficientEffectiveEntries"] =
histogram.GetEffectiveEntries();
55 if (sigmaRange <= 0) {
56 throw dqm_core::BadConfig(ERS_HERE,
name,
"SigmaRange must be greater than zero.");
59 ERS_DEBUG(1,
"Careful, your SigmaRange = " << sigmaRange <<
" is rather small");
64 throw dqm_core::BadConfig(ERS_HERE,
name,
"SigmaMax must be greater than zero.");
67 std::unique_ptr<TH1>
h(
static_cast<TH1 *
>(
histogram.Clone()));
69 auto f = std::make_unique<TF1> (
"f",
"gaus");
71 f->SetParLimits(2, 0, sigmaMax);
72 f->SetParameter(2, sigmaMax / 2);
73 f->SetRange(meanNominal - sigmaMax, meanNominal + sigmaMax);
76 const unsigned int maxIterations = 10;
77 const double sufficientPrecision = 0.01;
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");
86 const int fitStatus =
h->Fit(
f.get(), fitOptions.c_str());
88 ERS_DEBUG(1,
"Fit failed in iteration " <<
i <<
", status = " << fitStatus);
92 result->tags_[
"FitStatus"] = fitStatus;
96 const double mean =
f->GetParameter(1);
97 const double sigma =
f->GetParameter(2);
98 ERS_DEBUG(2,
"Iteration " <<
i <<
": mean = " <<
mean <<
", sigma = " <<
sigma);
102 ERS_DEBUG(1,
"Fit yielded sigma = 0 in iteration " <<
i);
104 result->tags_[
"Iteration"] =
i;
110 if (
sigma == sigmaMax) {
111 ERS_DEBUG(1,
"Fit result for sigma is at the limit " << sigmaMax);
113 result->tags_[
"Iteration"] =
i;
115 result->tags_[
"SigmaMax"] = sigmaMax;
119 if ((std::fabs(
sigma - sigmaOld) /
sigma) < sufficientPrecision)
break;
121 if (
i >= maxIterations) {
122 ERS_DEBUG(1,
"Sorry, this is not taking us anywhere: the iteration does not seem to converge");
124 result->tags_[
"Iteration"] =
i;
125 result->tags_[
"SigmaOld"] = sigmaOld;
132 const int ndf =
f->GetNDF();
133 const double chi2 =
f->GetChisquare();
134 const double chi2NDF = (
ndf > 0) ? (
chi2 /
ndf) : 0;
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);
151 out << m_name <<
": Applies a Gaussian fit over a limited fit range.\n"
152 " The fit range is iteratively determined in terms of Gaussian sigmas on each side of the mean.\n"
153 " The algorithm stops if sigma doesn't change anymore, or after a maximum number of iterations.\n"
154 "Mandatory parameter: SigmaRange - over plus/minus how many sigmas the fit should be applied.\n"
155 "Optional parameter: MeanNominal - the expected mean value, used for calculating MeanDeviation (default 0)\n"
156 "Optional parameter: SigmaMax - limit the maximum possible fit result for sigma (default unlimited)\n"
157 "Optional parameter: MinStat - minimum number of entries required in the histogram (default 1000).\n"
158 "Returned values: Constant, Mean, and Sigma of the fitted Gaussian including their errors, Chi2NDF and Probability.\n"
159 " MeanDeviation - the absolute difference of Mean and MeanNominal, useful for detecting shifts.\n"
160 "Thresholds can be set on any of the returned values, or a combination thereof." << std::endl;