DAS  3.0
Das Analysis System
GenericSFApplier.h
Go to the documentation of this file.
1 #pragma once
2 
5 
6 #include <correction.h>
7 #include <darwin.h>
8 
9 #include <TFile.h>
10 #include <TH1.h>
11 
12 #include <filesystem>
13 #include <map>
14 #include <utility>
15 #include <vector>
16 
17 namespace DAS {
18 
23 [[deprecated]]
24 inline std::unique_ptr<TH1> getHistSafe (std::unique_ptr<TFile>& f,
25  const std::string& name)
26 {
28  auto h = std::unique_ptr<TH1>(f->Get<TH1>(name.c_str()));
29  if (!h) {
30  std::cerr << name << std::endl;
31  BOOST_THROW_EXCEPTION( Darwin::Exceptions::BadInput("Can't find required histogram", f) );
32  }
33  h->SetDirectory(nullptr);
34  return h;
35 }
36 
76 template<class Object, class... Context>
78 {
79  std::unique_ptr<TFile> m_file;
80  bool m_correction,
82 
84  std::unique_ptr<TH1> m_nominal;
86  std::map<std::string, std::unique_ptr<TH1>> m_bin_wise_uncs;
88  std::map<std::string, std::unique_ptr<TH1>> m_global_uncs;
89 
90 public:
91  GenericHistSFApplier (const std::filesystem::path& filePath,
92  bool correction, bool uncertainties);
93  virtual ~GenericHistSFApplier () noexcept = default;
94 
95  void operator() (Object& object, const Context&... ctx) const;
96  void operator() (std::vector<Object>& objects, const Context&... ctx) const;
97  std::vector<std::string> weightNames () const;
98 
99 protected:
106  };
107 
108  void loadNominal (const std::string& histPath);
109  void loadBinWiseUnc (const std::string& name,
110  const std::string& histPath,
112  void loadGlobalUnc (const std::string& name,
113  const std::string& histPath,
115 
122  virtual bool passes (const Object& obj, const Context&... ctx) const = 0;
123 
131  virtual int binIndex (const Object& obj,
132  const Context&... ctx,
133  const std::unique_ptr<TH1>& hist) const = 0;
134 };
135 
142 template<class Object, class... Context>
144  const std::filesystem::path& filePath,
145  bool correction,
146  bool uncertainties)
147  : m_correction(correction)
148  , m_uncertainties(uncertainties)
149 {
150  namespace fs = std::filesystem;
151 
152  if (!correction)
153  return;
154 
155  // Check that the file exists
156  if (!fs::exists(filePath))
157  BOOST_THROW_EXCEPTION(
158  fs::filesystem_error("Not found",
159  filePath,
160  make_error_code(std::errc::no_such_file_or_directory)));
161 
162  m_file = std::make_unique<TFile>(filePath.c_str(), "READ");
163 }
164 
165 
169 template<class Object, class... Context>
171  Object& obj, const Context&... ctx) const
172 {
173  auto& weights = obj.weights;
174 
175  // For safety
176  if (weights.empty()) weights.emplace_back(DAS::Weight{1, 0});
177 
178  const float old = weights.front().v;
179 
180  // Apply the cut
181  if (!passes(obj, ctx...)) {
182  weights *= 0;
183  return; // Skip applying weights
184  }
185 
186  // Nominal correction
187  if (!m_correction) return;
188 
189  const int bin = binIndex(obj, ctx..., m_nominal);
190  const float sf = m_nominal->GetBinContent(bin);
191  weights *= sf;
192 
193  // Systematics
194  if (!m_uncertainties) return;
195 
196  // The order of the next two blocks must match weightNames()
197  for (const auto& [_, hist] : m_bin_wise_uncs) {
198  const float variation = hist->GetBinContent(bin);
199  weights.push_back({old * (sf + variation), bin});
200  weights.push_back({old * (sf - variation), bin});
201  }
202 
203  for (const auto& [_, hist] : m_global_uncs) {
204  const float variation = hist->GetBinContent(bin);
205  weights.push_back({old * (sf + variation), 0});
206  weights.push_back({old * (sf - variation), 0});
207  }
208 }
209 
213 template<class Object, class... Context>
215  std::vector<Object>& objects, const Context&... ctx) const
216 {
217  for (auto& obj: objects) {
218  (*this)(obj, ctx...);
219  }
220 }
221 
226 template<class Object, class... Context>
227 std::vector<std::string>
229 {
230  std::vector<std::string> names;
231  // The order of the next two blocks must match the call operator
232  for (const auto& [name, _] : m_bin_wise_uncs) {
233  names.push_back(name + SysUp);
234  names.push_back(name + SysDown);
235  }
236  for (const auto& [name, _] : m_global_uncs) {
237  names.push_back(name + SysUp);
238  names.push_back(name + SysDown);
239  }
240  return names;
241 }
242 
247 template<class Object, class... Context>
249  const std::string& histPath)
250 {
251  if (!m_correction) return;
252  m_nominal = getHistSafe(m_file, histPath);
253 }
254 
263 template<class Object, class... Context>
265  const std::string& name, const std::string& histPath, Interpretation intp)
266 {
267  if (!m_correction || !m_uncertainties) return;
268  auto hist = getHistSafe(m_file, histPath);
269  if (intp == UseBinError) // We always store variations in the bin contents
270  for (int i = 0; i <= hist->GetNcells(); ++i)
271  hist->SetBinContent(i, hist->GetBinError(i));
272  m_bin_wise_uncs[name] = std::move(hist);
273 }
274 
283 template<class Object, class... Context>
285  const std::string& name, const std::string& histPath, Interpretation intp)
286 {
287  if (!m_correction || !m_uncertainties) return;
288  auto hist = getHistSafe(m_file, histPath);
289  if (intp == UseBinError) // We always store variations in the bin contents
290  for (int i = 0; i <= hist->GetNcells(); ++i)
291  hist->SetBinContent(i, hist->GetBinError(i));
292  m_global_uncs[name] = std::move(hist);
293 }
294 
339 template<class Object, class... Context>
341 {
342 protected:
343  correction::Correction::Ref m_cref;
344 
345 private:
348 
350  std::map<std::string, correction::Variable::Type> m_bin_wise_uncs;
352  std::map<std::string, correction::Variable::Type> m_global_uncs;
353 
355  mutable std::vector<correction::Variable::Type> m_cached_inputs;
356 
357 public:
358  CorrectionlibSFApplier (const std::filesystem::path& filePath,
359  const std::string& name,
360  bool correction,
361  bool uncertainties);
362  virtual ~CorrectionlibSFApplier () noexcept = default;
363 
364  void operator() (Object& object, const Context&... ctx) const;
365  void operator() (std::vector<Object>& objects, const Context&... ctx) const;
366  std::vector<std::string> weightNames () const;
367 
368 protected:
369  void addBinWiseUnc (const std::string& name,
370  const correction::Variable::Type& input);
371  void addGlobalUnc (const std::string& name,
372  const correction::Variable::Type& input);
373 
380  virtual bool passes (const Object& obj, const Context&... ctx) const = 0;
381 
388  virtual void inputs (std::vector<correction::Variable::Type>& inputs,
389  const Object& obj,
390  const Context&... ctx) const = 0;
391 
397  virtual std::pair<double, double>
398  varied(std::vector<correction::Variable::Type>& inputs, double sf,
399  const correction::Variable::Type& uncname) const = 0;
400 
407  virtual int binIndex (const Object& obj, const Context&... ctx) const
408  { return 0; }
409 };
410 
417 template<class Object, class... Context>
419  const std::filesystem::path& filePath,
420  const std::string& name,
421  bool correction,
422  bool uncertainties)
423  : m_correction(correction)
424  , m_uncertainties(uncertainties)
425 {
426  namespace fs = std::filesystem;
427 
428  if (!correction)
429  return;
430 
431  // Check that the file exists
432  if (!fs::exists(filePath))
433  BOOST_THROW_EXCEPTION(
434  fs::filesystem_error("Not found",
435  filePath,
436  make_error_code(std::errc::no_such_file_or_directory)));
437 
438  auto cset = correction::CorrectionSet::from_file(filePath);
439  m_cref = cset->at(name);
440 }
441 
445 template<class Object, class... Context>
447  Object& obj, const Context&... ctx) const
448 {
449  auto& weights = obj.weights;
450 
451  // For safety
452  if (weights.empty()) weights.emplace_back(DAS::Weight{1, 0});
453 
454  const auto old = weights.front().v;
455 
456  // Apply the cut
457  if (!passes(obj, ctx...)) {
458  weights *= 0;
459  return; // Skip applying weights
460  }
461 
462  // Nominal correction
463  if (!m_correction) return;
464 
465  m_cached_inputs.clear();
466  inputs(m_cached_inputs, obj, ctx...);
467  const auto sf = m_cref->evaluate(m_cached_inputs);
468 
469  weights *= sf;
470 
471  // Systematics
472  if (!m_uncertainties) return;
473 
474  // The order of the next two blocks must match weightNames()
475  if (!m_bin_wise_uncs.empty()) {
476  const int bin = binIndex(obj, ctx...);
477  for (const auto& [_, uncname] : m_bin_wise_uncs) {
478  const auto& [up, down] = varied(m_cached_inputs, sf, uncname);
479  weights.push_back({old * up, bin});
480  weights.push_back({old * down, bin});
481  }
482  }
483 
484  for (const auto& [_, uncname] : m_global_uncs) {
485  const auto& [up, down] = varied(m_cached_inputs, sf, uncname);
486  weights.push_back({old * up, 0});
487  weights.push_back({old * down, 0});
488  }
489 }
490 
494 template<class Object, class... Context>
496  std::vector<Object>& objects, const Context&... ctx) const
497 {
498  for (auto& obj: objects) {
499  (*this)(obj, ctx...);
500  }
501 }
502 
507 template<class Object, class... Context>
508 std::vector<std::string>
510 {
511  std::vector<std::string> names;
512  // The order of the next two blocks must match the call operator
513  for (const auto& [name, _] : m_bin_wise_uncs) {
514  names.push_back(name + SysUp);
515  names.push_back(name + SysDown);
516  }
517  for (const auto& [name, _] : m_global_uncs) {
518  names.push_back(name + SysUp);
519  names.push_back(name + SysDown);
520  }
521  return names;
522 }
523 
532 template<class Object, class... Context>
534  const std::string& name, const correction::Variable::Type& input)
535 {
536  if (!m_correction || !m_uncertainties) return;
537  m_bin_wise_uncs[name] = std::move(input);
538 }
539 
548 template<class Object, class... Context>
550  const std::string& name, const correction::Variable::Type& input)
551 {
552  if (!m_correction || !m_uncertainties) return;
553  m_global_uncs[name] = std::move(input);
554 }
555 
556 } // namespace DAS
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
DAS::GenericHistSFApplier::m_bin_wise_uncs
std::map< std::string, std::unique_ptr< TH1 > > m_bin_wise_uncs
Histograms with uncertainties correlated bin-by-bin.
Definition: GenericSFApplier.h:86
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:105
DAS
Definition: applyBTagSF.cc:31
DAS::CorrectionlibSFApplier::weightNames
std::vector< std::string > weightNames() const
Retrieves the name of weights added by this applier. Returns an empty vector when uncertainties are d...
Definition: GenericSFApplier.h:509
DAS::CorrectionlibSFApplier::binIndex
virtual int binIndex(const Object &obj, const Context &... ctx) const
Called to retrieve the bin index to use for bin-wise uncertainties.
Definition: GenericSFApplier.h:407
DAS::CorrectionlibSFApplier
A generic base class to simplify applying scale factors.
Definition: GenericSFApplier.h:341
DAS::GenericHistSFApplier::UseBinError
@ UseBinError
The histogram errors contain the uncertainty in the scale factors.
Definition: GenericSFApplier.h:105
DAS::CorrectionlibSFApplier::m_correction
bool m_correction
Apply the scale factors?
Definition: GenericSFApplier.h:346
DAS::CorrectionlibSFApplier::addBinWiseUnc
void addBinWiseUnc(const std::string &name, const correction::Variable::Type &input)
Loads a systematic with bin-by-bin correlations.
Definition: GenericSFApplier.h:533
DAS::GenericHistSFApplier::m_correction
bool m_correction
Apply the scale factors?
Definition: GenericSFApplier.h:80
DAS::GenericHistSFApplier::loadGlobalUnc
void loadGlobalUnc(const std::string &name, const std::string &histPath, Interpretation intp=UseBinContent)
Loads a fully correlated systematic.
Definition: GenericSFApplier.h:284
DAS::SysUp
const std::string SysUp
Suffix used for "up" uncertainties. Follows the Combine convention.
Definition: Format.h:8
jercExample.cset
cset
Definition: jercExample.py:90
DAS::GenericHistSFApplier::binIndex
virtual int binIndex(const Object &obj, const Context &... ctx, const std::unique_ptr< TH1 > &hist) const =0
Called to retrieve the bin to use in the scale factor histograms.
DAS::GenericHistSFApplier::m_global_uncs
std::map< std::string, std::unique_ptr< TH1 > > m_global_uncs
Histograms with uncertainties correlated.
Definition: GenericSFApplier.h:88
Format.h
Ntupliser_cfg.f
f
Definition: Ntupliser_cfg.py:324
DAS::CorrectionlibSFApplier::~CorrectionlibSFApplier
virtual ~CorrectionlibSFApplier() noexcept=default
DAS::GenericHistSFApplier::GenericHistSFApplier
GenericHistSFApplier(const std::filesystem::path &filePath, bool correction, bool uncertainties)
Constructor.
Definition: GenericSFApplier.h:143
DAS::CorrectionlibSFApplier::m_cached_inputs
std::vector< correction::Variable::Type > m_cached_inputs
Cached inputs to reduce allocations.
Definition: GenericSFApplier.h:355
DAS::CorrectionlibSFApplier::varied
virtual std::pair< double, double > varied(std::vector< correction::Variable::Type > &inputs, double sf, const correction::Variable::Type &uncname) const =0
Called to retrieve the up and down variations of a scale factor.
DAS::CorrectionlibSFApplier::inputs
virtual void inputs(std::vector< correction::Variable::Type > &inputs, const Object &obj, const Context &... ctx) const =0
Called to retrieve the inputs for correctionlib.
DAS::GenericHistSFApplier
A generic base class to simplify applying scale factors.
Definition: GenericSFApplier.h:78
DAS::CorrectionlibSFApplier::m_cref
correction::Correction::Ref m_cref
Correction to be used.
Definition: GenericSFApplier.h:343
DAS::CorrectionlibSFApplier::CorrectionlibSFApplier
CorrectionlibSFApplier(const std::filesystem::path &filePath, const std::string &name, bool correction, bool uncertainties)
Constructor.
Definition: GenericSFApplier.h:418
DAS::CorrectionlibSFApplier::m_bin_wise_uncs
std::map< std::string, correction::Variable::Type > m_bin_wise_uncs
Inputs for uncertainties correlated bin-by-bin.
Definition: GenericSFApplier.h:350
DAS::GenericHistSFApplier::loadBinWiseUnc
void loadBinWiseUnc(const std::string &name, const std::string &histPath, Interpretation intp=UseBinContent)
Loads a systematic with bin-by-bin correlations.
Definition: GenericSFApplier.h:264
DAS::GenericHistSFApplier::operator()
void operator()(Object &object, const Context &... ctx) const
Applies the selection and scale factors to a single object.
Definition: GenericSFApplier.h:170
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.input
input
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:35
DAS::CorrectionlibSFApplier::m_global_uncs
std::map< std::string, correction::Variable::Type > m_global_uncs
Inputs for fully correlated uncertainties.
Definition: GenericSFApplier.h:352
DAS::CorrectionlibSFApplier::m_uncertainties
bool m_uncertainties
Calculate uncertainties?
Definition: GenericSFApplier.h:347
DAS::GenericHistSFApplier::passes
virtual bool passes(const Object &obj, const Context &... ctx) const =0
Called to check whether an object passes the selection.
DAS::CorrectionlibSFApplier::passes
virtual bool passes(const Object &obj, const Context &... ctx) const =0
Called to check whether an object passes the selection.
DAS::GenericHistSFApplier::weightNames
std::vector< std::string > weightNames() const
Retrieves the name of weights added by this applier. Returns an empty vector when uncertainties are d...
Definition: GenericSFApplier.h:228
DAS::getHistSafe
std::unique_ptr< TH1 > getHistSafe(std::unique_ptr< TFile > &f, const std::string &name)
Gets an histogram from a TFile.
Definition: GenericSFApplier.h:24
DAS::CorrectionlibSFApplier::operator()
void operator()(Object &object, const Context &... ctx) const
Applies the selection and scale factors to a single object.
Definition: GenericSFApplier.h:446
DAS::Weight
Definition: Weight.h:16
Weight.h
DAS::SysDown
const std::string SysDown
Suffix used for "down" uncertainties. Follows the Combine convention.
Definition: Format.h:10
DAS::GenericHistSFApplier::loadNominal
void loadNominal(const std::string &histPath)
Loads the histogram with the nominal scale factor. Has no effect when not applying the correction.
Definition: GenericSFApplier.h:248
DAS::GenericHistSFApplier::UseBinContent
@ UseBinContent
The histogram contains the uncertainty in the scale factors.
Definition: GenericSFApplier.h:103
jercExample.sf
sf
Definition: jercExample.py:112
jercExample.inputs
def inputs
Definition: jercExample.py:118
DAS::CorrectionlibSFApplier::addGlobalUnc
void addGlobalUnc(const std::string &name, const correction::Variable::Type &input)
Loads a fully correlated systematic.
Definition: GenericSFApplier.h:549
weights
DAS::Weights weights
Definition: classes.h:12
DAS::GenericHistSFApplier::m_nominal
std::unique_ptr< TH1 > m_nominal
Histogram with the nominal SFs.
Definition: GenericSFApplier.h:84
DAS::GenericHistSFApplier::m_file
std::unique_ptr< TFile > m_file
SFs are loaded from this file.
Definition: GenericSFApplier.h:79
Darwin::Exceptions::BadInput
Generic exception for ill-defined input (before the event loop).
Definition: exceptions.h:83
DAS::GenericHistSFApplier::m_uncertainties
bool m_uncertainties
Calculate uncertainties?
Definition: GenericSFApplier.h:81
DAS::GenericHistSFApplier::~GenericHistSFApplier
virtual ~GenericHistSFApplier() noexcept=default
DAS::GenericHistSFApplier< RecEvent, Trigger, vector< RecMuon > >::Interpretation
Interpretation
How loaded histograms should be interpreted.
Definition: GenericSFApplier.h:101