CMS 3D CMS Logo

PFJetDQMPostProcessor.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Validation/RecoParticleFlow
4 // Class: PFJetDQMPostProcessor.cc
5 //
6 // Main Developer: "Juska Pekkanen"
7 // Original Author: "Kenichi Hatakeyama"
8 //
9 
16 
19 
20 #include "TCanvas.h"
21 
22 //
23 // class declaration
24 //
25 
27 public:
29  ~PFJetDQMPostProcessor() override;
30 
31 private:
33  void fitResponse(TH1F* hreso,
34  TH1F* h_genjet_pt,
35  int ptbinlow,
36  int ietahigh,
37  double recoptcut,
38  double& resp,
39  double& resp_err,
40  double& reso,
41  double& reso_err);
42  double getRespUnc(double width, double width_err, double mean, double mean_err);
43 
44  std::vector<std::string> jetResponseDir;
46  std::vector<double> ptBins;
47  std::vector<double> etaBins;
48 
49  double recoptcut;
50 
51  bool debug = false;
52 
53  std::string seta(double eta) {
54  std::string seta = std::to_string(int(eta * 10.));
55  if (seta.length() < 2)
56  seta = "0" + seta;
57  return seta;
58  }
59 
60  std::string spt(double ptmin, double ptmax) {
62  return spt;
63  }
64 };
65 
66 // Some switches
67 //
68 // constuctors and destructor
69 //
71  jetResponseDir = iConfig.getParameter<std::vector<std::string>>("jetResponseDir");
72  genjetDir = iConfig.getParameter<std::string>("genjetDir");
73  ptBins = iConfig.getParameter<std::vector<double>>("ptBins");
74  etaBins = iConfig.getParameter<std::vector<double>>("etaBins");
75  recoptcut = iConfig.getParameter<double>("recoPtCut");
76 }
77 
79 
80 // ------------ method called right after a run ends ------------
82  for (unsigned int idir = 0; idir < jetResponseDir.size(); idir++) {
84  std::vector<std::string> sME_genjets = iget_.getMEs();
85  std::for_each(sME_genjets.begin(), sME_genjets.end(), [&](auto& s) { s.insert(0, genjetDir); });
86  //for (unsigned int i=0; i<sME_genjets.size(); i++) std::cout << sME_genjets[i] << std::endl;
87 
88  iget_.setCurrentFolder(jetResponseDir[idir]);
89  std::vector<std::string> sME_response = iget_.getMEs();
90  std::for_each(sME_response.begin(), sME_response.end(), [&](auto& s) { s.insert(0, jetResponseDir[idir]); });
91  //for (unsigned int i=0; i<sME_response.size(); i++) std::cout << sME_response[i] << std::endl;
92 
93  iget_.setCurrentFolder(jetResponseDir[idir]);
94 
95  double ptBinsArray[ptBins.size()];
96  unsigned int nPtBins = ptBins.size() - 1;
97  std::copy(ptBins.begin(), ptBins.end(), ptBinsArray);
98  //for(unsigned int ipt = 0; ipt < ptBins.size(); ++ipt) std::cout << ptBins[ipt] << std::endl;
99 
100  std::string stitle;
101  char ctitle[50];
102  std::vector<MonitorElement*> vME_presponse;
103  std::vector<MonitorElement*> vME_preso;
104  std::vector<MonitorElement*> vME_preso_rms;
105 
107  TH1F* h_resp;
108  TH1F* h_genjet_pt;
109 
110  //
111  // Response distributions
112  //
113  for (unsigned int ieta = 1; ieta < etaBins.size(); ++ieta) {
114  stitle = genjetDir + "genjet_pt" + "_eta" + seta(etaBins[ieta]);
115  //std::cout << ieta << " " << stitle << std::endl;
116 
117  std::vector<std::string>::const_iterator it = std::find(sME_genjets.begin(), sME_genjets.end(), stitle);
118  if (it == sME_genjets.end())
119  continue;
120  me = iget_.get(stitle);
121  h_genjet_pt = (TH1F*)me->getTH1F();
122 
123  stitle = "presponse_eta" + seta(etaBins[ieta]);
124  // adding "Raw" to the title of raw jet response histograms
125  if (jetResponseDir[idir].find("noJEC") != std::string::npos) {
126  sprintf(ctitle, "Raw Jet pT response, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
127  } else {
128  sprintf(ctitle, "Jet pT response, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
129  }
130  TH1F* h_presponse = new TH1F(stitle.c_str(), ctitle, nPtBins, ptBinsArray);
131 
132  stitle = "preso_eta" + seta(etaBins[ieta]);
133  if (jetResponseDir[idir].find("noJEC") != std::string::npos) {
134  sprintf(ctitle, "Raw Jet pT resolution, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
135  } else {
136  sprintf(ctitle, "Jet pT resolution, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
137  }
138  TH1F* h_preso = new TH1F(stitle.c_str(), ctitle, nPtBins, ptBinsArray);
139 
140  stitle = "preso_eta" + seta(etaBins[ieta]) + "_rms";
141  if (jetResponseDir[idir].find("noJEC") != std::string::npos) {
142  sprintf(ctitle, "Raw Jet pT resolution using RMS, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
143  } else {
144  sprintf(ctitle, "Jet pT resolution using RMS, %4.1f<|#eta|<%4.1f", etaBins[ieta - 1], etaBins[ieta]);
145  }
146  TH1F* h_preso_rms = new TH1F(stitle.c_str(), ctitle, nPtBins, ptBinsArray);
147 
148  for (unsigned int ipt = 0; ipt < ptBins.size() - 1; ++ipt) {
149  stitle = jetResponseDir[idir] + "reso_dist_" + spt(ptBins[ipt], ptBins[ipt + 1]) + "_eta" + seta(etaBins[ieta]);
150  std::vector<std::string>::const_iterator it = std::find(sME_response.begin(), sME_response.end(), stitle);
151  if (it == sME_response.end())
152  continue;
153  me = iget_.get(stitle);
154  h_resp = (TH1F*)me->getTH1F();
155 
156  // Fit-based
157  double resp = 1.0, resp_err = 0.0, reso = 0.0, reso_err = 0.0;
158  fitResponse(h_resp, h_genjet_pt, ipt, ieta, recoptcut, resp, resp_err, reso, reso_err);
159 
160  h_presponse->SetBinContent(ipt + 1, resp);
161  h_presponse->SetBinError(ipt + 1, resp_err);
162  h_preso->SetBinContent(ipt + 1, reso);
163  h_preso->SetBinError(ipt + 1, reso_err);
164 
165  // RMS-based
166  double std = h_resp->GetStdDev();
167  double std_error = h_resp->GetStdDevError();
168 
169  // Scale each bin with mean response
170  double mean = 1.0;
171  double mean_error = 0.0;
172  double err = 0.0;
173  if (h_resp->GetMean() > 0) {
174  mean = h_resp->GetMean();
175  mean_error = h_resp->GetMeanError();
176 
177  // Scale resolution by response.
178  std /= mean;
179  std_error /= mean;
180 
181  err = getRespUnc(std, std_error, mean, mean_error);
182  }
183 
184  h_preso_rms->SetBinContent(ipt + 1, std);
185  h_preso_rms->SetBinError(ipt + 1, err);
186 
187  } // ipt
188 
189  stitle = "presponse_eta" + seta(etaBins[ieta]);
190  me = ibook_.book1D(stitle.c_str(), h_presponse);
191  vME_presponse.push_back(me);
192 
193  stitle = "preso_eta" + seta(etaBins[ieta]);
194  me = ibook_.book1D(stitle.c_str(), h_preso);
195  vME_preso.push_back(me);
196 
197  stitle = "preso_eta" + seta(etaBins[ieta]) + "_rms";
198  me = ibook_.book1D(stitle.c_str(), h_preso_rms);
199  vME_preso_rms.push_back(me);
200 
201  } // ieta
202 
203  //
204  // Checks
205  //
206  if (debug) {
207  for (std::vector<MonitorElement*>::const_iterator i = vME_presponse.begin(); i != vME_presponse.end(); ++i)
208  (*i)->getTH1F()->Print();
209  for (std::vector<MonitorElement*>::const_iterator i = vME_preso.begin(); i != vME_preso.end(); ++i)
210  (*i)->getTH1F()->Print();
211  for (std::vector<MonitorElement*>::const_iterator i = vME_preso_rms.begin(); i != vME_preso_rms.end(); ++i)
212  (*i)->getTH1F()->Print();
213  }
214  }
215 }
216 
218  TH1F* h_genjet_pt,
219  int ptbinlow,
220  int ietahigh,
221  double recoptcut,
222  double& resp,
223  double& resp_err,
224  double& reso,
225  double& reso_err) {
226  // This 'smartfitter' is converted from the original Python smart_fit() -function
227  // implemented in test/helperFunctions.py. See that file for more commentary.
228  // Juska 23 May 2019
229 
230  // Only do plots if needed for debugging
231  // NOTE a directory called 'debug' must exist in the working directory
232  //
233  bool doPlots = false;
234 
235  double ptlow = ptBins[ptbinlow];
236  double pthigh = ptBins[ptbinlow + 1];
237 
238  // Take range by Mikko's advice: -1.5 and + 1.5 * RMS width
239 
240  double rmswidth = hreso->GetStdDev();
241  double rmsmean = hreso->GetMean();
242  double fitlow = rmsmean - 1.5 * rmswidth;
243  fitlow = TMath::Max(recoptcut / ptlow, fitlow);
244  double fithigh = rmsmean + 1.5 * rmswidth;
245 
246  TF1* fg = new TF1("mygaus", "gaus", fitlow, fithigh);
247  TF1* fg2 = new TF1("fg2", "TMath::Gaus(x,[0],[1],true)*[2]", fitlow, fithigh);
248 
249  hreso->Fit("mygaus", "RQN");
250 
251  fg2->SetParameter(0, fg->GetParameter(1));
252  fg2->SetParameter(1, fg->GetParameter(2));
253 
254  // Extract ngenjet in the current pT bin from the genjet histo
255  float ngenjet = h_genjet_pt->GetBinContent(ptbinlow + 1);
256 
257  // Here the fit is forced to take the area of ngenjets.
258  // The area is further normalized for the response histogram x-axis length
259  // (3) and number of bins (100)
260  fg2->FixParameter(2, ngenjet * 3. / 100.);
261 
262  hreso->Fit("fg2", "RQN");
263 
264  fitlow = fg2->GetParameter(0) - 1.5 * fg2->GetParameter(1);
265  fitlow = TMath::Max(15. / ptlow, fitlow);
266  fithigh = fg2->GetParameter(0) + 1.5 * fg2->GetParameter(1);
267 
268  fg2->SetRange(fitlow, fithigh);
269 
270  hreso->Fit("fg2", "RQ");
271 
272  fg->SetRange(0, 3);
273  fg2->SetRange(0, 3);
274  fg->SetLineWidth(2);
275  fg2->SetLineColor(kGreen + 2);
276 
277  hreso->GetXaxis()->SetRangeUser(0, 2);
278 
279  // Save plots to a subdirectory if asked (debug-directory must exist!)
280  if (doPlots & (hreso->GetEntries() > 0)) {
281  TCanvas* cfit = new TCanvas(Form("respofit_%i", int(ptlow)), "respofit", 600, 600);
282  hreso->Draw("ehist");
283  fg->Draw("same");
284  fg2->Draw("same");
285  cfit->SaveAs(
286  Form("debug/respo_smartfit_%04d_%i_eta%s.pdf", (int)ptlow, (int)pthigh, seta(etaBins[ietahigh]).c_str()));
287  }
288 
289  resp = fg2->GetParameter(0);
290  resp_err = fg2->GetParError(0);
291 
292  // Scale resolution by response. Avoid division by zero.
293  if (0 == resp)
294  reso = 0;
295  else
296  reso = fg2->GetParameter(1) / resp;
297  reso_err = fg2->GetParError(1) / resp;
298 
299  reso_err = getRespUnc(reso, reso_err, resp, resp_err);
300 }
301 
302 // Calculate resolution uncertainty
303 double PFJetDQMPostProcessor::getRespUnc(double width, double width_err, double mean, double mean_err) {
304  if (0 == width || 0 == mean)
305  return 0;
306  return TMath::Sqrt(pow(width_err, 2) / pow(width, 2) + pow(mean_err, 2) / pow(mean, 2)) * width;
307 }
308 
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
PFJetDQMPostProcessor(const edm::ParameterSet &)
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
std::vector< std::string > jetResponseDir
virtual std::vector< std::string > getMEs() const
Definition: DQMStore.cc:759
constexpr int pow(int x)
Definition: conifer.h:24
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
static std::string to_string(const XMLCh *ch)
std::string spt(double ptmin, double ptmax)
std::vector< double > etaBins
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
virtual TH1F * getTH1F() const
void fitResponse(TH1F *hreso, TH1F *h_genjet_pt, int ptbinlow, int ietahigh, double recoptcut, double &resp, double &resp_err, double &reso, double &reso_err)
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:712
double ptmin
Definition: HydjetWrapper.h:86
std::vector< double > ptBins
std::string seta(double eta)
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
double getRespUnc(double width, double width_err, double mean, double mean_err)