CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GEMEfficiencyHarvester.cc
Go to the documentation of this file.
2 
5 
6 #include "TEfficiency.h"
7 
9  folder_ = pset.getUntrackedParameter<std::string>("folder");
10  log_category_ = "GEMEfficiencyHarvester";
11 }
12 
14 
17  desc.addUntracked<std::string>("folder", "GEM/Efficiency/type0");
18  descriptions.add("gemEfficiencyHarvesterDefault", desc);
19 }
20 
22  const TH1F* passed, const TH1F* total, const char* name, const char* title, const double confidence_level) {
23  if (not TEfficiency::CheckConsistency(*passed, *total)) {
24  edm::LogError(log_category_) << "failed to pass TEfficiency::CheckConsistency. " << name << std::endl;
25  return nullptr;
26  }
27 
28  const TAxis* total_x = total->GetXaxis();
29 
30  TProfile* eff_profile = new TProfile(name, title, total_x->GetNbins(), total_x->GetXmin(), total_x->GetXmax());
31  eff_profile->GetXaxis()->SetTitle(total_x->GetTitle());
32  eff_profile->GetYaxis()->SetTitle("Efficiency");
33 
34  for (int bin = 1; bin <= total->GetNbinsX(); bin++) {
35  double num_passed = passed->GetBinContent(bin);
36  double num_total = total->GetBinContent(bin);
37 
38  if (num_total < 1) {
39  eff_profile->SetBinEntries(bin, 0);
40  continue;
41  }
42 
43  double efficiency = num_passed / num_total;
44 
45  double lower_bound = TEfficiency::ClopperPearson(num_total, num_passed, confidence_level, false);
46  double upper_bound = TEfficiency::ClopperPearson(num_total, num_passed, confidence_level, true);
47 
48  double width = std::max(efficiency - lower_bound, upper_bound - efficiency);
49  double error = std::hypot(efficiency, width);
50 
51  eff_profile->SetBinContent(bin, efficiency);
52  eff_profile->SetBinError(bin, error);
53  eff_profile->SetBinEntries(bin, 1);
54  }
55 
56  return eff_profile;
57 }
58 
60  const TH2F* total,
61  const char* name,
62  const char* title) {
63  if (not TEfficiency::CheckConsistency(*passed, *total)) {
64  edm::LogError(log_category_) << "failed to pass TEfficiency::CheckConsistency. " << name << std::endl;
65  return nullptr;
66  }
67 
68  TEfficiency eff(*passed, *total);
69  TH2F* eff_hist = dynamic_cast<TH2F*>(eff.CreateHistogram());
70  eff_hist->SetName(name);
71  eff_hist->SetTitle(title);
72 
73  const TAxis* total_x = total->GetXaxis();
74  TAxis* eff_hist_x = eff_hist->GetXaxis();
75  eff_hist_x->SetTitle(total_x->GetTitle());
76  for (int bin = 1; bin <= total->GetNbinsX(); bin++) {
77  const char* label = total_x->GetBinLabel(bin);
78  eff_hist_x->SetBinLabel(bin, label);
79  }
80 
81  const TAxis* total_y = total->GetYaxis();
82  TAxis* eff_hist_y = eff_hist->GetYaxis();
83  eff_hist_y->SetTitle(total_y->GetTitle());
84  for (int bin = 1; bin <= total->GetNbinsY(); bin++) {
85  const char* label = total_y->GetBinLabel(bin);
86  eff_hist_y->SetBinLabel(bin, label);
87  }
88 
89  return eff_hist;
90 }
91 
93  const std::string efficiency_folder = folder_ + "/Efficiency/";
94  ibooker.setCurrentFolder(efficiency_folder);
95  igetter.setCurrentFolder(efficiency_folder);
96 
97  std::map<std::string, std::pair<const MonitorElement*, const MonitorElement*> > me_pairs;
98 
99  const std::string matched = "_matched";
100 
101  for (const std::string& name : igetter.getMEs()) {
102  const std::string fullpath = efficiency_folder + name;
103  const MonitorElement* me = igetter.get(fullpath);
104  if (me == nullptr) {
105  edm::LogError(log_category_) << "failed to get " << fullpath << std::endl;
106  continue;
107  }
108 
109  const bool is_matched = name.find(matched) != std::string::npos;
110 
111  std::string key = name;
112  if (is_matched)
113  key.erase(key.find(matched), matched.length());
114 
115  if (me_pairs.find(key) == me_pairs.end()) {
116  me_pairs[key] = {nullptr, nullptr};
117  }
118 
119  if (is_matched)
120  me_pairs[key].first = me;
121  else
122  me_pairs[key].second = me;
123  }
124 
125  for (auto&& [key, value] : me_pairs) {
126  const auto& [me_passed, me_total] = value;
127  if (me_passed == nullptr) {
128  edm::LogError(log_category_) << "numerator is missing. " << key << std::endl;
129  continue;
130  }
131 
132  if (me_total == nullptr) {
133  edm::LogError(log_category_) << "denominator is missing. " << key << std::endl;
134  continue;
135  }
136 
137  if (me_passed->kind() != me_total->kind()) {
138  edm::LogError(log_category_) << "inconsistency between kinds of passed and total" << key << std::endl;
139  continue;
140  }
141 
142  const std::string name = "eff_" + me_total->getName();
143  const std::string title = me_passed->getTitle();
144 
145  if (me_passed->kind() == MonitorElement::Kind::TH1F) {
146  TH1F* h_passed = me_passed->getTH1F();
147  if (h_passed == nullptr) {
148  edm::LogError(log_category_) << "failed to get TH1F from passed " << key << std::endl;
149  continue;
150  }
151  h_passed->Sumw2();
152 
153  TH1F* h_total = me_total->getTH1F();
154  if (h_total == nullptr) {
155  edm::LogError(log_category_) << "failed to get TH1F from total" << key << std::endl;
156  continue;
157  }
158  h_total->Sumw2();
159 
160  TProfile* eff = computeEfficiency(h_passed, h_total, name.c_str(), title.c_str());
161  if (eff == nullptr) {
162  edm::LogError(log_category_) << "failed to compute the efficiency " << key << std::endl;
163  continue;
164  }
165 
166  ibooker.bookProfile(name, eff);
167 
168  } else if (me_passed->kind() == MonitorElement::Kind::TH2F) {
169  TH2F* h_passed = me_passed->getTH2F();
170  if (h_passed == nullptr) {
171  edm::LogError(log_category_) << "failed to get TH1F from passed " << key << std::endl;
172  continue;
173  }
174  h_passed->Sumw2();
175 
176  TH2F* h_total = me_total->getTH2F();
177  if (h_total == nullptr) {
178  edm::LogError(log_category_) << "failed to get TH1F from total" << key << std::endl;
179  continue;
180  }
181  h_total->Sumw2();
182 
183  TH2F* eff = computeEfficiency(h_passed, h_total, name.c_str(), title.c_str());
184  if (eff == nullptr) {
185  edm::LogError(log_category_) << "failed to compute the efficiency " << key << std::endl;
186  continue;
187  }
188 
189  ibooker.book2D(name, eff);
190 
191  } else {
192  edm::LogError(log_category_) << "not implemented" << std::endl;
193  continue;
194  }
195  } // me_pairs
196 }
197 
198 std::vector<std::string> GEMEfficiencyHarvester::splitString(std::string name, const std::string delimiter) {
199  std::vector<std::string> tokens;
200  size_t delimiter_pos;
201  size_t delimiter_len = delimiter.length();
202  while ((delimiter_pos = name.find('_')) != std::string::npos) {
203  tokens.push_back(name.substr(0, delimiter_pos));
204  name.erase(0, delimiter_pos + delimiter_len);
205  }
206  tokens.push_back(name);
207  return tokens;
208 }
209 
210 std::tuple<std::string, int, int> GEMEfficiencyHarvester::parseResidualName(const std::string org_name,
211  const std::string prefix) {
212  std::string name = org_name;
213 
214  // e.g. residual_rdphi_GE-11_R4 -> _GE-11_R4
215  name.erase(name.find(prefix), prefix.length());
216 
217  // _GE-11_R4 -> -11_R4
218  name.erase(name.find("_GE"), 3);
219 
220  // -11_R4 -> (-11, R4)
221  const std::vector<std::string>&& tokens = splitString(name, "_");
222  const size_t num_tokens = tokens.size();
223 
224  if (num_tokens != 2) {
225  return std::make_tuple("", -1, -1);
226  }
227 
228  // '-'11
229  std::string region_sign = tokens.front().substr(0, 1);
230  // -'1'1
231  TString station_str = tokens.front().substr(1, 1);
232 
233  // R'4' or R'16'
234  TString ieta_str = tokens.back().substr(1);
235 
236  const int station = station_str.IsDigit() ? station_str.Atoi() : -1;
237  const int ieta = ieta_str.IsDigit() ? ieta_str.Atoi() : -1;
238 
239  return std::make_tuple(region_sign, station, ieta);
240 }
241 
243  DQMStore::IGetter& igetter,
244  const std::string prefix) {
245  const std::string resolution_folder = folder_ + "/Resolution/";
246 
247  igetter.setCurrentFolder(resolution_folder);
248  ibooker.setCurrentFolder(resolution_folder);
249 
250  // (histogram, (region_sign, station), ieta)
251  std::vector<std::tuple<const TH1F*, std::pair<std::string, int>, int> > hist_vector;
252  // (region_sign, station)
253  std::vector<std::pair<std::string, int> > re_st_vec;
254  // ieta
255  std::vector<int> ieta_vec;
256 
257  for (const std::string& name : igetter.getMEs()) {
258  if (name.find(prefix) == std::string::npos)
259  continue;
260 
261  const std::string fullpath = resolution_folder + name;
262  const MonitorElement* me = igetter.get(fullpath);
263  if (me == nullptr) {
264  edm::LogError(log_category_) << "failed to get " << fullpath << std::endl;
265  continue;
266  }
267 
268  const TH1F* hist = me->getTH1F();
269  if (hist == nullptr) {
270  edm::LogError(log_category_) << "failed to get TH1F" << std::endl;
271  continue;
272  }
273 
274  auto&& [region_sign, station, ieta] = parseResidualName(name, prefix);
275  if (region_sign.empty() or station < 0 or ieta < 0) {
276  edm::LogError(log_category_) << "failed to parse the name of the residual histogram: " << name << std::endl;
277  continue;
278  }
279  std::pair<std::string, int> region_station(region_sign, station);
280 
281  hist_vector.emplace_back(hist, region_station, ieta);
282  if (std::find(re_st_vec.begin(), re_st_vec.end(), region_station) == re_st_vec.end())
283  re_st_vec.push_back(region_station);
284  if (std::find(ieta_vec.begin(), ieta_vec.end(), ieta) == ieta_vec.end())
285  ieta_vec.push_back(ieta);
286  } // MonitorElement
287 
288  if (hist_vector.empty()) {
289  edm::LogError(log_category_) << "failed to find " << prefix << std::endl;
290  return;
291  }
292 
293  // NOTE
294  // GE-2/1, GE-1/1, GE-0/1, GE+0/1, GE+1/1, GE+2/1
295  auto f_sort = [](const std::pair<std::string, int>& lhs, const std::pair<std::string, int>& rhs) -> bool {
296  if (lhs.first == rhs.first) {
297  if (lhs.first == "-")
298  return lhs.second > rhs.second;
299  else
300  return lhs.second < rhs.second;
301 
302  } else {
303  return (lhs.first == "-");
304  }
305  };
306 
307  std::sort(re_st_vec.begin(), re_st_vec.end(), f_sort);
308  std::sort(ieta_vec.begin(), ieta_vec.end());
309 
310  const int num_st = re_st_vec.size();
311  const int num_ieta = ieta_vec.size();
312 
313  // NOTE
314  TString tmp_title{std::get<0>(hist_vector.front())->GetTitle()};
315 
316  const TObjArray* tokens = tmp_title.Tokenize(":");
317  const TString title_prefix = dynamic_cast<TObjString*>(tokens->At(0))->GetString();
318 
319  const TString h_mean_name = prefix + "_mean";
320  const TString h_stddev_name = prefix + "_stddev";
321  const TString h_skewness_name = prefix + "_skewness";
322 
323  const TString h_mean_title = title_prefix + " : Mean";
324  const TString h_stddev_title = title_prefix + " : Standard Deviation";
325  const TString h_skewness_title = title_prefix + " : Skewness";
326 
327  TH2F* h_mean = new TH2F(h_mean_name, h_mean_title, num_ieta, 0.5, num_ieta + 0.5, num_st, 0.5, num_st + 0.5);
328  // x-axis
329  h_mean->GetXaxis()->SetTitle("i#eta");
330  for (unsigned int idx = 0; idx < ieta_vec.size(); idx++) {
331  const int xbin = idx + 1;
332  const char* label = Form("%d", ieta_vec[idx]);
333  h_mean->GetXaxis()->SetBinLabel(xbin, label);
334  }
335  // y-axis
336  for (unsigned int idx = 0; idx < re_st_vec.size(); idx++) {
337  auto [region_sign, station] = re_st_vec[idx];
338  const char* label = Form("GE%s%d/1", region_sign.c_str(), station);
339  const int ybin = idx + 1;
340  h_mean->GetYaxis()->SetBinLabel(ybin, label);
341  }
342 
343  TH2F* h_stddev = dynamic_cast<TH2F*>(h_mean->Clone(h_stddev_name));
344  TH2F* h_skewness = dynamic_cast<TH2F*>(h_mean->Clone(h_skewness_name));
345 
346  h_stddev->SetTitle(h_stddev_title);
347  h_skewness->SetTitle(h_skewness_title);
348 
349  // NOTE
350  for (auto [hist, region_station, ieta] : hist_vector) {
351  const int xbin = findResolutionBin(ieta, ieta_vec);
352  if (xbin < 0) {
353  edm::LogError(log_category_) << "found a wrong x bin = " << xbin << std::endl;
354  continue;
355  }
356 
357  const int ybin = findResolutionBin(region_station, re_st_vec);
358  if (ybin < 0) {
359  edm::LogError(log_category_) << "found a wrong y bin = " << ybin << std::endl;
360  continue;
361  }
362 
363  h_mean->SetBinContent(xbin, ybin, hist->GetMean());
364  h_stddev->SetBinContent(xbin, ybin, hist->GetStdDev());
365 
366  // FIXME
367  // `GetSkewness` seems to returns nan when its histogram has no entry..
368  const double skewness = hist->GetSkewness();
369  if (edm::isFinite(skewness))
370  h_skewness->SetBinContent(xbin, ybin, skewness);
371 
372  h_mean->SetBinError(xbin, ybin, hist->GetMeanError());
373  h_stddev->SetBinError(xbin, ybin, hist->GetStdDevError());
374  h_skewness->SetBinError(xbin, ybin, hist->GetSkewness(11));
375  }
376 
377  for (auto&& each : {h_mean, h_stddev, h_skewness}) {
378  ibooker.book2D(each->GetName(), each);
379  }
380 }
381 
383  doEfficiency(ibooker, igetter);
384  doResolution(ibooker, igetter, "residual_rphi");
385 }
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
T getUntrackedParameter(std::string const &, T const &) const
GEMEfficiencyHarvester(const edm::ParameterSet &)
virtual TH2F * getTH2F() const
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
virtual TH1F * getTH1F() const
std::tuple< std::string, int, int > parseResidualName(std::string, const std::string)
__host__ __device__ constexpr RandomIt upper_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
static void fillDescriptions(edm::ConfigurationDescriptions &)
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
constexpr bool isFinite(T x)
def fullpath
Definition: das_client.py:267
char const * label
std::vector< std::string > splitString(std::string, const std::string)
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:322
void doResolution(DQMStore::IBooker &, DQMStore::IGetter &, const std::string)
void doEfficiency(DQMStore::IBooker &, DQMStore::IGetter &)
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:673
tuple key
prepare the HTCondor submission files and eventually submit them
__shared__ Hist hist
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:177
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TProfile * computeEfficiency(const TH1F *, const TH1F *, const char *, const char *, const double confidence_level=0.683)
virtual std::vector< std::string > getMEs() const
Definition: DQMStore.cc:720
__host__ __device__ constexpr RandomIt lower_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
int findResolutionBin(const T &, const std::vector< T > &)