CMS 3D CMS Logo

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