CMS 3D CMS Logo

EmDQMPostProcessor.cc
Go to the documentation of this file.
2 
6 
7 #include <cmath>
8 #include <cstring>
9 #include <fstream>
10 #include <iomanip>
11 #include <iostream>
12 
13 #include <TEfficiency.h>
14 
15 //----------------------------------------------------------------------
16 
18  subDir_ = pset.getUntrackedParameter<std::string>("subDir");
19 
20  dataSet_ = pset.getUntrackedParameter<std::string>("dataSet", "unknown");
21 
22  noPhiPlots = pset.getUntrackedParameter<bool>("noPhiPlots", true);
23 
24  normalizeToReco = pset.getUntrackedParameter<bool>("normalizeToReco", false);
25 
26  ignoreEmpty = pset.getUntrackedParameter<bool>("ignoreEmpty", true);
27 }
28 
29 //----------------------------------------------------------------------
30 
32  // go to the directory to be processed
33  if (igetter.dirExists(subDir_))
34  ibooker.cd(subDir_);
35  else {
36  edm::LogWarning("EmDQMPostProcessor") << "cannot find directory: " << subDir_ << " , skipping";
37  return;
38  }
39 
40  //--------------------
41  // with respect to what are (some) efficiencies calculated ?
42  std::string shortReferenceName;
43  if (normalizeToReco)
44  shortReferenceName = "RECO";
45  else
46  shortReferenceName = "gen";
47  //--------------------
48 
50  // loop over all triggers/samples//
52 
53  // store dataset name (if defined) in output file
54  // DQMStore:bookString seems to put a key in the file which is
55  // of the form <dataSet>s=....</dataSet> which is not very convenient
56  // (it points to a null pointer, one would have to loop over
57  // all keys of the corresponding directory in the ROOT file
58  // and check whether it is of the desired form and then parse
59  // it from this string...).
60  //
61  // So we store the name of the dataset as the title of a histogram,
62  // which is much easier to access...
63  // TH1D *dataSetNameHisto =
64  ibooker.book1D("DataSetNameHistogram", dataSet_, 1, 0, 1);
65 
66  std::vector<std::string> subdirectories = igetter.getSubdirs();
68  // Do everything twice: once for mc-matched histos, //
69  // once for unmatched histos //
71 
72  std::vector<std::string> postfixes;
73  postfixes.push_back(""); // unmatched histograms
74  postfixes.push_back("_RECO_matched"); // for data
75  // we put this on the list even when we're running on
76  // data (where there is no generator information).
77  // The first test in the loop will then fail and
78  // the iteration is skipped.
79  postfixes.push_back("_MC_matched");
80 
81  std::vector<TProfile *> allElePaths;
82  int nEle = 0;
83  int nPhoton = 0;
84 
85  // find the number of electron and photon paths
86  for (std::vector<std::string>::iterator dir = subdirectories.begin(); dir != subdirectories.end(); ++dir) {
87  if (dir->find("Ele") != std::string::npos || dir->find("_SC") != std::string::npos)
88  ++nEle;
89  else if (dir->find("Photon") != std::string::npos)
90  ++nPhoton;
91  }
92 
93  std::vector<TProfile *> allPhotonPaths;
94  for (std::vector<std::string>::iterator postfix = postfixes.begin(); postfix != postfixes.end(); postfix++) {
95  bool pop = false;
96  int elePos = 1;
97  int photonPos = 1;
98 
100  // computer per-event efficiencies //
102 
103  std::string histoName = "efficiency_by_step" + *postfix;
104  std::string baseName = "total_eff" + *postfix;
105 
106  std::string allEleHistoName = "EfficiencyByPath_Ele" + *postfix;
107  std::string allEleHistoLabel = "Efficiency_for_each_validated_electron_path" + *postfix;
108  allElePaths.push_back(
109  new TProfile(allEleHistoName.c_str(), allEleHistoLabel.c_str(), nEle, 0., (double)nEle, 0., 1.2));
110  std::string allPhotonHistoName = "EfficiencyByPath_Photon" + *postfix;
111  std::string allPhotonHistoLabel = "Efficiency_for_each_validated_photon_path" + *postfix;
112  allPhotonPaths.push_back(
113  new TProfile(allPhotonHistoName.c_str(), allPhotonHistoLabel.c_str(), nPhoton, 0., (double)nPhoton, 0., 1.2));
114 
115  for (std::vector<std::string>::iterator dir = subdirectories.begin(); dir != subdirectories.end(); dir++) {
116  ibooker.cd(*dir);
117 
118  // get the current trigger name
119  std::string trigName = dir->substr(dir->rfind("/") + 1);
120  trigName = trigName.replace(trigName.rfind("_DQM"), 4, "");
121 
122  // Get the gen-level (or reco, for data) plots
123  std::string genName;
124 
125  // only generate efficiency plots if there are generated/recoed events
126  // selected but label the bin in the overview plot, even if the bin is
127  // empty
128  if (ignoreEmpty) {
129  if (normalizeToReco)
130  genName = ibooker.pwd() + "/reco_et";
131  else
132  genName = ibooker.pwd() + "/gen_et";
133  TH1F *genHist = getHistogram(ibooker, igetter, genName);
134  if (genHist->GetEntries() == 0) {
135  edm::LogInfo("EmDQMPostProcessor")
136  << "Zero events were selected for path '" << trigName << "'. No efficiency plots will be generated.";
137  if (trigName.find("Ele") != std::string::npos || trigName.find("_SC") != std::string::npos) {
138  allElePaths.back()->GetXaxis()->SetBinLabel(elePos, trigName.c_str());
139  ++elePos;
140  } else if (trigName.find("Photon") != std::string::npos) {
141  allPhotonPaths.back()->GetXaxis()->SetBinLabel(photonPos, trigName.c_str());
142  ++photonPos;
143  }
144  ibooker.goUp();
145  continue;
146  }
147  }
148 
149  TH1F *basehist = getHistogram(ibooker, igetter, ibooker.pwd() + "/" + baseName);
150  if (basehist == nullptr) {
151  // edm::LogWarning("EmDQMPostProcessor") << "histogram " <<
152  // (ibooker.pwd() + "/" + baseName) << " does not exist, skipping
153  // postfix
154  // '" << *postfix << "'";
155  pop = true;
156  ibooker.goUp();
157  continue;
158  }
159  // at least one histogram with postfix was found
160  pop = false;
161 
162  ibooker.goUp();
163  MonitorElement *meTotal = ibooker.bookProfile(trigName + "__" + histoName,
164  trigName + "__" + histoName,
165  basehist->GetXaxis()->GetNbins(),
166  basehist->GetXaxis()->GetXmin(),
167  basehist->GetXaxis()->GetXmax(),
168  0.,
169  1.2);
170  meTotal->setEfficiencyFlag();
171  TProfile *total = meTotal->getTProfile();
172  ibooker.cd(*dir);
173  total->GetXaxis()->SetBinLabel(1, basehist->GetXaxis()->GetBinLabel(1));
174 
175  // std::vector<std::string> mes = igetter.getMEs();
176  // for(std::vector<std::string>::iterator me = mes.begin() ;me!=
177  // mes.end(); me++ )
178  // std::cout <<*me <<std::endl;
179  // std::cout <<std::endl;
180 
181  double value = 0;
182  double errorh = 0, errorl = 0, error = 0;
183  // compute stepwise total efficiencies
184  for (int bin = total->GetNbinsX() - 2; bin > 1; bin--) {
185  value = 0;
186  errorl = 0;
187  errorh = 0;
188  error = 0;
189  if (basehist->GetBinContent(bin - 1) != 0) {
190  Efficiency(
191  (int)basehist->GetBinContent(bin), (int)basehist->GetBinContent(bin - 1), 0.683, value, errorl, errorh);
192  error = value - errorl > errorh - value ? value - errorl : errorh - value;
193  }
194  total->SetBinContent(bin, value);
195  total->SetBinEntries(bin, 1);
196  total->SetBinError(bin, sqrt(value * value + error * error));
197  total->GetXaxis()->SetBinLabel(bin, basehist->GetXaxis()->GetBinLabel(bin));
198  }
199 
200  // set first bin to L1 efficiency
201  if (basehist->GetBinContent(basehist->GetNbinsX()) != 0) {
202  Efficiency((int)basehist->GetBinContent(1),
203  (int)basehist->GetBinContent(basehist->GetNbinsX()),
204  0.683,
205  value,
206  errorl,
207  errorh);
208  error = value - errorl > errorh - value ? value - errorl : errorh - value;
209  } else {
210  value = 0;
211  error = 0;
212  }
213  total->SetBinContent(1, value);
214  total->SetBinEntries(1, 1);
215  total->SetBinError(1, sqrt(value * value + error * error));
216 
217  // total efficiency relative to gen or reco
218  if (basehist->GetBinContent(basehist->GetNbinsX()) != 0) {
219  Efficiency((int)basehist->GetBinContent(basehist->GetNbinsX() - 2),
220  (int)basehist->GetBinContent(basehist->GetNbinsX()),
221  0.683,
222  value,
223  errorl,
224  errorh);
225  error = value - errorl > errorh - value ? value - errorl : errorh - value;
226  } else {
227  value = 0;
228  error = 0;
229  }
230  total->SetBinContent(total->GetNbinsX(), value);
231  total->SetBinEntries(total->GetNbinsX(), 1);
232  total->SetBinError(total->GetNbinsX(), sqrt(value * value + error * error));
233  total->GetXaxis()->SetBinLabel(total->GetNbinsX(), ("total efficiency rel. " + shortReferenceName).c_str());
234 
235  // total efficiency relative to L1
236  if (basehist->GetBinContent(1) != 0) {
237  Efficiency((int)basehist->GetBinContent(basehist->GetNbinsX() - 2),
238  (int)basehist->GetBinContent(1),
239  0.683,
240  value,
241  errorl,
242  errorh);
243  error = value - errorl > errorh - value ? value - errorl : errorh - value;
244  } else {
245  value = 0;
246  error = 0;
247  }
248  total->SetBinContent(total->GetNbinsX() - 1, value);
249  total->SetBinError(total->GetNbinsX() - 1, sqrt(value * value + error * error));
250  total->SetBinEntries(total->GetNbinsX() - 1, 1);
251  total->GetXaxis()->SetBinLabel(total->GetNbinsX() - 1, "total efficiency rel. L1");
252 
253  //----------------------------------------
254 
256  // compute per-object efficiencies //
258  // MonitorElement *eff, *num, *denom, *genPlot, *effVsGen, *effL1VsGen;
259  std::vector<std::string> varNames;
260  varNames.push_back("et");
261  varNames.push_back("eta");
262 
263  if (!noPhiPlots) {
264  varNames.push_back("phi");
265  }
266  varNames.push_back("etaphi");
267 
269  std::string filterName2;
270  std::string denomName;
271  std::string numName;
272 
273  // Get the L1 over gen filter first
274  filterName2 = total->GetXaxis()->GetBinLabel(1);
275  // loop over variables (eta/phi/et)
276  for (std::vector<std::string>::iterator var = varNames.begin(); var != varNames.end(); var++) {
277  numName = ibooker.pwd() + "/" + filterName2 + *var + *postfix;
278 
279  if (normalizeToReco)
280  genName = ibooker.pwd() + "/reco_" + *var;
281  else
282  genName = ibooker.pwd() + "/gen_" + *var;
283 
284  if ((*var).find("etaphi") != std::string::npos) {
285  if (!dividehistos2D(ibooker,
286  igetter,
287  numName,
288  genName,
289  "efficiency_" + filterName2 + "_vs_" + *var + *postfix,
290  *var,
291  "eff. of" + filterName2 + " vs " + *var + *postfix))
292  break;
293  } else if (!dividehistos(ibooker,
294  igetter,
295  numName,
296  genName,
297  "efficiency_" + filterName2 + "_vs_" + *var + *postfix,
298  *var,
299  "eff. of" + filterName2 + " vs " + *var + *postfix))
300  break;
301  } // loop over variables
302 
303  // get the filter names from the bin-labels of the master-histogram
304  for (int filter = 1; filter < total->GetNbinsX() - 2; filter++) {
305  filterName = total->GetXaxis()->GetBinLabel(filter);
306  filterName2 = total->GetXaxis()->GetBinLabel(filter + 1);
307 
308  // loop over variables (eta/et/phi)
309  for (std::vector<std::string>::iterator var = varNames.begin(); var != varNames.end(); var++) {
310  numName = ibooker.pwd() + "/" + filterName2 + *var + *postfix;
311  denomName = ibooker.pwd() + "/" + filterName + *var + *postfix;
312 
313  // Is this the last filter? Book efficiency vs gen (or reco, for data)
314  // level
315  std::string temp = *postfix;
316  if (filter == total->GetNbinsX() - 3 && temp.find("matched") != std::string::npos) {
317  if (normalizeToReco)
318  genName = ibooker.pwd() + "/reco_" + *var;
319  else
320  genName = ibooker.pwd() + "/gen_" + *var;
321 
322  if ((*var).find("etaphi") != std::string::npos) {
323  if (!dividehistos2D(ibooker,
324  igetter,
325  numName,
326  genName,
327  "final_eff_vs_" + *var,
328  *var,
329  "Efficiency Compared to " + shortReferenceName + " vs " + *var))
330  break;
331  } else if (!dividehistos(ibooker,
332  igetter,
333  numName,
334  genName,
335  "final_eff_vs_" + *var,
336  *var,
337  "Efficiency Compared to " + shortReferenceName + " vs " + *var))
338  break;
339  }
340 
341  if ((*var).find("etaphi") != std::string::npos) {
342  if (!dividehistos2D(ibooker,
343  igetter,
344  numName,
345  denomName,
346  "efficiency_" + filterName2 + "_vs_" + *var + *postfix,
347  *var,
348  "efficiency_" + filterName2 + "_vs_" + *var + *postfix))
349  break;
350  } else if (!dividehistos(ibooker,
351  igetter,
352  numName,
353  denomName,
354  "efficiency_" + filterName2 + "_vs_" + *var + *postfix,
355  *var,
356  "efficiency_" + filterName2 + "_vs_" + *var + *postfix))
357  break;
358 
359  } // loop over variables
360  } // loop over monitoring modules within path
361 
362  ibooker.goUp();
363 
364  // fill overall efficiency histograms
365  double totCont = total->GetBinContent(total->GetNbinsX());
366  double totErr = total->GetBinError(total->GetNbinsX());
367  if (trigName.find("Ele") != std::string::npos || trigName.find("_SC") != std::string::npos) {
368  allElePaths.back()->SetBinContent(elePos, totCont);
369  allElePaths.back()->SetBinEntries(elePos, 1);
370  allElePaths.back()->SetBinError(elePos, sqrt(totCont * totCont + totErr * totErr));
371  allElePaths.back()->GetXaxis()->SetBinLabel(elePos, trigName.c_str());
372  ++elePos;
373  } else if (trigName.find("Photon") != std::string::npos) {
374  allPhotonPaths.back()->SetBinContent(photonPos, totCont);
375  allPhotonPaths.back()->SetBinEntries(photonPos, 1);
376  allPhotonPaths.back()->SetBinError(photonPos, sqrt(totCont * totCont + totErr * totErr));
377  allPhotonPaths.back()->GetXaxis()->SetBinLabel(photonPos, trigName.c_str());
378  ++photonPos;
379  }
380 
381  } // loop over dirs
382  if (pop) {
383  allElePaths.pop_back();
384  allPhotonPaths.pop_back();
385  } else {
386  allElePaths.back()->GetXaxis()->SetLabelSize(0.03);
387  allPhotonPaths.back()->GetXaxis()->SetLabelSize(0.03);
388  ibooker.bookProfile(allEleHistoName, allElePaths.back())->setEfficiencyFlag();
389  ibooker.bookProfile(allPhotonHistoName, allPhotonPaths.back())->setEfficiencyFlag();
390  }
391  } // loop over postfixes
392 }
393 
394 //----------------------------------------------------------------------
395 
397  DQMStore::IGetter &igetter,
398  const std::string &numName,
399  const std::string &denomName,
400  const std::string &outName,
401  const std::string &label,
402  const std::string &titel) {
403  // std::cout << numName <<std::endl;
404 
405  TH1F *num = getHistogram(ibooker, igetter, numName);
406 
407  // std::cout << denomName << std::endl;
408  TH1F *denom = getHistogram(ibooker, igetter, denomName);
409 
410  if (num == nullptr)
411  edm::LogWarning("EmDQMPostProcessor") << "numerator histogram " << numName << " does not exist";
412 
413  if (denom == nullptr)
414  edm::LogWarning("EmDQMPostProcessor") << "denominator histogram " << denomName << " does not exist";
415 
416  // Check if histograms actually exist
417 
418  if (num == nullptr || denom == nullptr)
419  return nullptr;
420 
421  MonitorElement *meOut = ibooker.bookProfile(
422  outName, titel, num->GetXaxis()->GetNbins(), num->GetXaxis()->GetXmin(), num->GetXaxis()->GetXmax(), 0., 1.2);
423  meOut->setEfficiencyFlag();
424  TProfile *out = meOut->getTProfile();
425  out->GetXaxis()->SetTitle(label.c_str());
426  out->SetYTitle("Efficiency");
427  out->SetOption("PE");
428  out->SetLineColor(2);
429  out->SetLineWidth(2);
430  out->SetMarkerStyle(20);
431  out->SetMarkerSize(0.8);
432  out->SetStats(kFALSE);
433  for (int i = 1; i <= num->GetNbinsX(); i++) {
434  double e, low, high;
435  Efficiency((int)num->GetBinContent(i), (int)denom->GetBinContent(i), 0.683, e, low, high);
436  double err = e - low > high - e ? e - low : high - e;
437  // here is the trick to store info in TProfile:
438  out->SetBinContent(i, e);
439  out->SetBinEntries(i, 1);
440  out->SetBinError(i, sqrt(e * e + err * err));
441  }
442 
443  return out;
444 }
445 //----------------------------------------------------------------------
447  DQMStore::IGetter &igetter,
448  const std::string &numName,
449  const std::string &denomName,
450  const std::string &outName,
451  const std::string &label,
452  const std::string &titel) {
453  // std::cout << numName <<std::endl;
454  TH2F *num = get2DHistogram(ibooker, igetter, numName);
455  // std::cout << denomName << std::endl;
456  TH2F *denom = get2DHistogram(ibooker, igetter, denomName);
457  if (num == nullptr)
458  edm::LogWarning("EmDQMPostProcessor") << "2D numerator histogram " << numName << " does not exist";
459 
460  if (denom == nullptr)
461  edm::LogWarning("EmDQMPostProcessor") << "2D denominator histogram " << denomName << " does not exist";
462 
463  // Check if histograms actually exist
464  if (num == nullptr || denom == nullptr)
465  return nullptr;
466 
467  MonitorElement *meOut = ibooker.book2D(outName,
468  titel,
469  num->GetXaxis()->GetNbins(),
470  num->GetXaxis()->GetXmin(),
471  num->GetXaxis()->GetXmax(),
472  num->GetYaxis()->GetNbins(),
473  num->GetYaxis()->GetXmin(),
474  num->GetYaxis()->GetXmax());
475  TH2F *out = meOut->getTH2F();
476  out->Add(num);
477  out->Divide(denom);
478  out->GetXaxis()->SetTitle(label.c_str());
479  out->SetYTitle("#phi");
480  out->SetXTitle("#eta");
481  out->SetOption("COLZ");
482  out->SetStats(kFALSE);
483 
484  return out;
485 }
486 //--------------------
488  DQMStore::IGetter &igetter,
489  const std::string &histoPath) {
490  MonitorElement *monElement = igetter.get(histoPath);
491  if (monElement != nullptr)
492  return monElement->getTH1F();
493  else
494  return nullptr;
495 }
496 //----------------------------------------------------------------------
498  DQMStore::IGetter &igetter,
499  const std::string &histoPath) {
500  MonitorElement *monElement = igetter.get(histoPath);
501  if (monElement != nullptr)
502  return monElement->getTH2F();
503  else
504  return nullptr;
505 }
506 
507 //----------------------------------------------------------------------
508 
510  int passing, int total, double level, double &mode, double &lowerBound, double &upperBound) {
511  // protection (see also TGraphAsymmErrors::Efficiency(..), mimick the old
512  // behaviour )
513  if (total == 0) {
514  mode = 0.5;
515  lowerBound = 0;
516  upperBound = 1;
517  return;
518  }
519 
520  mode = passing / ((double)total);
521 
522  // note that the order of the two first arguments ('total' and 'passed') is
523  // the opposited with respect to the earlier TGraphAsymmErrors::Efficiency(..)
524  // method
525  //
526  // see http://root.cern.ch/root/html/TEfficiency.html#compare for
527  // an illustration of the coverage of the different methods provided by
528  // TEfficiency
529 
530  lowerBound = TEfficiency::Wilson(total, passing, level, false);
531  upperBound = TEfficiency::Wilson(total, passing, level, true);
532 }
533 
534 //----------------------------------------------------------------------
535 
537 
538 //----------------------------------------------------------------------
TH2F * get2DHistogram(DQMStore::IBooker &ibooker, DQMStore::IGetter &igetter, const std::string &histoPath)
virtual TProfile * getTProfile() const
TH1F * getHistogram(DQMStore::IBooker &ibooker, DQMStore::IGetter &igetter, const std::string &histoPath)
virtual std::string pwd()
Definition: DQMStore.cc:20
virtual bool dirExists(std::string const &path) const
Definition: DQMStore.cc:754
constexpr char const * varNames[]
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
virtual TH2F * getTH2F() const
char const * label
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:399
T sqrt(T t)
Definition: SSEVec.h:19
TProfile * dividehistos(DQMStore::IBooker &ibooker, DQMStore::IGetter &igetter, const std::string &num, const std::string &denom, const std::string &out, const std::string &label, const std::string &titel="")
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
TH2F * dividehistos2D(DQMStore::IBooker &ibooker, DQMStore::IGetter &igetter, const std::string &num, const std::string &denom, const std::string &out, const std::string &label, const std::string &titel="")
Definition: value.py:1
EmDQMPostProcessor(const edm::ParameterSet &pset)
Log< level::Info, false > LogInfo
virtual TH1F * getTH1F() const
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:212
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:697
Log< level::Warning, false > LogWarning
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
static void Efficiency(int passing, int total, double level, double &mode, double &lowerBound, double &upperBound)
virtual DQM_DEPRECATED std::vector< std::string > getSubdirs() const
Definition: DQMStore.cc:724