ATLAS Offline Software
Loading...
Searching...
No Matches
LastBinThreshold.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9#include "dqm_core/AlgorithmConfig.h"
10#include "dqm_core/AlgorithmManager.h"
13#include "ers/ers.h"
14
15#include "TClass.h"
16#include "TObject.h"
17#include "TH1.h"
18#include "TProfile.h"
19
20#include <iostream>
21#include <cmath>
22
23namespace { // anonymous
24dqm_algorithms::LastBinThreshold instance("LastBinThreshold"); // global instance to have this algorithm registered with the manager
25}
26
31 , m_greaterThan(false)
32 , m_valueThresholds(false)
33 , m_getEntries(0)
34 , m_grn(0.)
35 , m_red(0.)
36 , m_name(name)
37{
38 dqm_core::AlgorithmManager::instance().registerAlgorithm(m_name, this);
39}
40
45
47{
48 return new LastBinThreshold(m_name); // somebody else must delete this
49}
50
51dqm_core::Result *dqm_algorithms::LastBinThreshold::execute(const std::string &name, const TObject &object, const dqm_core::AlgorithmConfig &config)
52{
53 if (!object.IsA()->InheritsFrom("TH1")) { // this could also be TH2 or TH3
54 throw dqm_core::BadConfig(ERS_HERE, name, "does not inherit from TH1");
55 }
56 const TH1 &histogram = dynamic_cast<const TH1 &>(object); // should be possible after the previous check (otherwise we'd get a std::bad_cast)
57 if (histogram.GetDimension() > 1) { // only one-dimensional histograms have a last bin, but feel free to generalise this for D > 1 if you like
58 throw dqm_core::BadConfig(ERS_HERE, name, "has more than one dimension");
59 }
60 bool is_tProfile = false;
61 if (object.IsA()->InheritsFrom("TProfile")) { // BinMinEntries is used only when the histogram is TProfile
62 is_tProfile = true;
63 }
64
65 getParameters(name, config);
66 getThresholds(name, config);
67
68 dqm_core::Result *result = new dqm_core::Result(); // somebody else must delete this
69 int grnExceeded = 0; // how many of the checked bins exceeded the green threshold
70 int redExceeded = 0; // how many of the checked bins exceeded the red threshold
71
72 int currentBin = histogram.GetNbinsX(); // this is the last proper bin (we don't want the overflow bin)
73 if (m_getEntries == 0) { // skip trailing bins with zero content
74 while ((histogram.GetBinContent(currentBin) == 0) && (currentBin > 0)) --currentBin;
75 } else if (m_getEntries == 1) { // assume that this value corresponds to the bin number of the last bin
76 currentBin = histogram.GetEntries();
77 } else if (m_getEntries == 2) { /* noop */ } // just start checking from the rightmost bin
78
79 result->tags_["LastBinNumber"] = currentBin; // report where we began the checks (mostly for debugging)
80 result->tags_["LastBinCenter"] = histogram.GetBinCenter(currentBin); // report where that is on the x-axis
81 // if the histogram is completely empty then currentBin is now zero, and we shouldn't check anything,
82 // therefore the break statement is at the front (!) of the following loop
83
84 for (int i = 0; i < m_nBinsToWatch; ++i) { // step through the final NBinsToWatch bins
85 if (currentBin == 0) break; // we hit the left end (and we don't want the underflow bin)
86 double content = histogram.GetBinContent(currentBin);
88 if (m_greaterThan) content = histogram.GetXaxis()->GetBinUpEdge(currentBin);
89 else content = histogram.GetXaxis()->GetBinLowEdge(currentBin);
90 }
91 if (is_tProfile) { // if the histogram is TProfile, the bin entries are checked
92 const TProfile &profile = dynamic_cast<const TProfile &>(object);
93 if (profile.GetBinEntries(currentBin) < m_binMinEntries) { // if the bin entries is less than MinBinEntries, the count is skipped
94 --currentBin;
95 continue;
96 }
97 }
98 if (exceeds(content, m_grn)) ++grnExceeded; // can be less-than or greater-than relation
99 if (exceeds(content, m_red)) ++redExceeded; // can be less-than or greater-than relation
100 --currentBin;
101 }
102
103 result->tags_["GreenExceeded"] = grnExceeded;
104 result->tags_["RedExceeded"] = redExceeded;
105 if (grnExceeded < redExceeded) // sanity check, this should never happen because getThresholds() makes sure the thresholds have the right order
106 throw dqm_core::BadConfig(ERS_HERE, name, "more bins exceeded the red threshold than the green threshold, this shouldn't happen");
107
108 if (grnExceeded < m_nBinsToExceed) result->status_ = dqm_core::Result::Green;
109 else if (redExceeded < m_nBinsToExceed) result->status_ = dqm_core::Result::Yellow;
110 else result->status_ = dqm_core::Result::Red;
111 return result;
112}
113
115{
116 out << m_name << ": Checks whether the last bin(s) of a histogram exceed the given thresholds.\n"
117 "Mandatory green/red thresholds: Threshold - the thresholds against which the bin contents are compared.\n"
118 "Optional parameter: NBinsToWatch - number of final bins that will be checked. (NBinsToWatch >= 1, default = 1)\n"
119 " The result of the algorithm is the worst-case result of all checked bins.\n"
120 "Optional parameter: NBinsToExceed - minimal number of checked bins that have to exceed the given thresholds\n"
121 " before the corresponding result is returned. (1 <= NBinsToExceed <= NBinsToWatch, default = 1)\n"
122 "Optional parameter: BinMinEntries: Minimum number of entries in a TProfile (1D only) for a bin to be checked against thresolds\n"
123 " If a bin does not have a sufficient number of entries it also will not be printed (default = 0)\n"
124 "Optional parameter: GreaterThan - how the values will be compared. (GreaterThan = {0, 1}, default = 1)\n"
125 " GreaterThan == 0: the given thresholds are lower thresholds. (requires green >= red)\n"
126 " GreaterThan == 1: the given thresholds are upper thresholds. (requires green <= red)\n"
127 "Optional parameter: ValueThresholds - which values will be compared. (ValueThresholds = {0, 1}, default = 0)\n"
128 " ValueThresholds == 0: the thresholds correspond to the bin content.\n"
129 " ValueThresholds == 1: the thresholds correspond to the bin x-axis value.\n"
130 "Optional parameter: GetEntries - how to determine which bin is the last. (GetEntries = {0, 1, 2}, default = 0)\n"
131 " GetEntries == 0: find the rightmost non-zero bin, ignore trailing zero bins.\n"
132 " GetEntries == 1: take the return value of TH1::GetEntries() as the number of the last bin.\n"
133 " GetEntries == 2: take the rightmost bin as the last bin, regardless of the bin content.\n"
134 "Returned value: LastBinNumber - the bin number of the last checked (i. e. non-zero) bin.\n"
135 "Returned value: LastBinCenter - the centre of that bin on the horizontal axis.\n"
136 "Returned value: GreenExceeded - how many bins exceeded the green threshold.\n"
137 "Returned value: RedExceeded - how many bins exceeded the red threshold." << std::endl;
138}
139
140void dqm_algorithms::LastBinThreshold::getParameters(const std::string &name, const dqm_core::AlgorithmConfig &config)
141{
142 // The following intermediate variables do not yet have the correct type,
143 // since dqm_core::AlgorithmConfig::getParameters can only return values of type double.
144 // We cannot cast them immediately because we still need to perform some manual range checks.
145 //
146 const double par0 = dqm_algorithms::tools::GetFirstFromMap("NBinsToWatch", config.getParameters(), 1); // default = 1
147 const double par1 = dqm_algorithms::tools::GetFirstFromMap("NBinsToExceed", config.getParameters(), 1); // default = 1
148 const double par2 = dqm_algorithms::tools::GetFirstFromMap("GreaterThan", config.getParameters(), 1); // default = true
149 const double par3 = dqm_algorithms::tools::GetFirstFromMap("ValueThresholds", config.getParameters(), 0); // default = false
150 const double par4 = dqm_algorithms::tools::GetFirstFromMap("GetEntries", config.getParameters(), 0); // default = 0
151 const double par5 = dqm_algorithms::tools::GetFirstFromMap("BinMinEntries", config.getParameters(), 0); // default = 0
152
153 if (par0 < 1)
154 throw dqm_core::BadConfig(ERS_HERE, name, "NBinsToWatch must be 1 or greater");
155 if (par1 < 1)
156 throw dqm_core::BadConfig(ERS_HERE, name, "NBinsToExceed must be 1 or greater");
157 if (par1 > par0)
158 throw dqm_core::BadConfig(ERS_HERE, name, "NBinsToExceed must not be greater than NBinsToWatch");
159 if ((par2 != 0) && (par2 != 1))
160 throw dqm_core::BadConfig(ERS_HERE, name, "GreaterThan must be 0 or 1");
161 if ((par3 != 0) && (par3 != 1))
162 throw dqm_core::BadConfig(ERS_HERE, name, "ValueThresholds must be 0 or 1");
163 if ((par4 != 0) && (par4 != 1) && (par4 != 2))
164 throw dqm_core::BadConfig(ERS_HERE, name, "GetEntries must be 0, 1 or 2");
165
166 m_nBinsToWatch = static_cast<int>(par0);
167 m_nBinsToExceed = static_cast<int>(par1);
168 m_greaterThan = static_cast<bool>(par2);
169 m_valueThresholds = static_cast<bool>(par3);
170 m_getEntries = static_cast<int>(par4);
171 m_binMinEntries = static_cast<int>(par5);
172}
173
174void dqm_algorithms::LastBinThreshold::getThresholds(const std::string &name, const dqm_core::AlgorithmConfig &config)
175{
176 m_grn = dqm_algorithms::tools::GetFromMap("Threshold", config.getGreenThresholds());
177 m_red = dqm_algorithms::tools::GetFromMap("Threshold", config.getRedThresholds());
178
179 if (m_greaterThan && (m_red < m_grn))
180 throw dqm_core::BadConfig(ERS_HERE, name, "using greater-than comparison, but red threshold is less than green threshold");
181 else if (!m_greaterThan && (m_red > m_grn))
182 throw dqm_core::BadConfig(ERS_HERE, name, "using less-than comparison, but red threshold is greater than green threshold");
183}
184
185inline bool dqm_algorithms::LastBinThreshold::exceeds(double value, double threshold) const
186{
187 if (m_greaterThan)
188 return value > threshold;
189 else
190 return value < threshold;
191 // We could derive that behaviour from testing whether (m_grn < m_red) or (m_grn > m_red), but then we
192 // weren't able to find a reasonable behaviour if (m_grn == m_red), i. e. for people who never want yellow.
193}
std::map< std::string, double > instance
std::string histogram
Definition chains.cxx:52
void getThresholds(const std::string &name, const dqm_core::AlgorithmConfig &config)
bool exceeds(double value, double threshold) const
virtual void printDescription(std::ostream &out)
virtual dqm_core::Result * execute(const std::string &name, const TObject &object, const dqm_core::AlgorithmConfig &config)
virtual LastBinThreshold * clone()
LastBinThreshold(const std::string &name)
void getParameters(const std::string &name, const dqm_core::AlgorithmConfig &config)
double GetFirstFromMap(const std::string &paramName, const std::map< std::string, double > &params)
const T & GetFromMap(const std::string &pname, const std::map< std::string, T > &params)
#define IsA
Declare the TObject style functions.