CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SmearedJetProducerT.h
Go to the documentation of this file.
1 #ifndef PAT_SMEAREDJETPRODUCERT_H
2 #define PAT_SMEAREDJETPRODUCERT_H
3 
16 
25 
29 
31 
32 #include <TFile.h>
33 #include <TH1.h>
34 #include <TH1F.h>
35 
36 #include <memory>
37 #include <random>
38 
39 namespace pat {
40  class GenJetMatcher {
41  public:
43  m_genJetsToken(collector.consumes<reco::GenJetCollection>(cfg.getParameter<edm::InputTag>("genJets"))),
44  m_dR_max(cfg.getParameter<double>("dRMax")),
45  m_dPt_max_factor(cfg.getParameter<double>("dPtMaxFactor")) {
46  // Empty
47  }
48 
50  desc.add<edm::InputTag>("genJets");
51  desc.add<double>("dRMax");
52  desc.add<double>("dPtMaxFactor");
53  }
54 
55  void getTokens(const edm::Event& event) {
56  event.getByToken(m_genJetsToken, m_genJets);
57  }
58 
59  template<class T>
60  const reco::GenJet* match(const T& jet, double resolution) {
61  const reco::GenJetCollection& genJets = *m_genJets;
62 
63  // Try to find a gen jet matching
64  // dR < m_dR_max
65  // dPt < m_dPt_max_factor * resolution
66 
67  double min_dR = std::numeric_limits<double>::infinity();
68  const reco::GenJet* matched_genJet = nullptr;
69 
70  for (const auto& genJet: genJets) {
71  double dR = deltaR(genJet, jet);
72 
73  if (dR > min_dR)
74  continue;
75 
76  if (dR < m_dR_max) {
77  double dPt = std::abs(genJet.pt() - jet.pt());
78  if (dPt > m_dPt_max_factor * resolution)
79  continue;
80 
81  min_dR = dR;
82  matched_genJet = &genJet;
83  }
84  }
85 
86  return matched_genJet;
87  }
88 
89  private:
92 
93  double m_dR_max;
95  };
96 };
97 
98 template <typename T>
100 
101  using JetCollection = std::vector<T>;
102 
103  public:
105  m_enabled(cfg.getParameter<bool>("enabled")),
106  m_debug(cfg.getUntrackedParameter<bool>("debug", false)) {
107 
108  m_jets_token = consumes<JetCollection>(cfg.getParameter<edm::InputTag>("src"));
109 
110  if (m_enabled) {
111  m_rho_token = consumes<double>(cfg.getParameter<edm::InputTag>("rho"));
112 
113  m_use_txt_files = cfg.exists("resolutionFile") && cfg.exists("scaleFactorFile");
114 
115  if (m_use_txt_files) {
116  std::string resolutionFile = cfg.getParameter<edm::FileInPath>("resolutionFile").fullPath();
117  std::string scaleFactorFile = cfg.getParameter<edm::FileInPath>("scaleFactorFile").fullPath();
118 
119  m_resolution_from_file.reset(new JME::JetResolution(resolutionFile));
120  m_scale_factor_from_file.reset(new JME::JetResolutionScaleFactor(scaleFactorFile));
121  } else {
122  m_jets_algo = cfg.getParameter<std::string>("algo");
123  m_jets_algo_pt = cfg.getParameter<std::string>("algopt");
124  }
125 
126  std::uint32_t seed = cfg.getParameter<std::uint32_t>("seed");
127  m_random_generator = std::mt19937(seed);
128 
129  bool skipGenMatching = cfg.getParameter<bool>("skipGenMatching");
130  if (! skipGenMatching)
131  m_genJetMatcher = std::make_shared<pat::GenJetMatcher>(cfg, consumesCollector());
132 
133  std::int32_t variation = cfg.getParameter<std::int32_t>("variation");
134  m_nomVar=1;
135  if (variation == 0)
137  else if (variation == 1)
139  else if (variation == -1)
141  else if (variation == 101) {
143  m_nomVar=1;
144  }
145  else if (variation == -101) {
147  m_nomVar=-1;
148  }
149  else
150  throw edm::Exception(edm::errors::ConfigFileReadError, "Invalid value for 'variation' parameter. Only -1, 0, 1 or 101, -101 are supported.");
151  }
152 
153  produces<JetCollection>();
154  }
155 
158 
159  desc.add<edm::InputTag>("src");
160  desc.add<bool>("enabled");
161  desc.add<edm::InputTag>("rho");
162  desc.add<std::int32_t>("variation", 0);
163  desc.add<std::uint32_t>("seed", 37428479);
164  desc.add<bool>("skipGenMatching", false);
165  desc.addUntracked<bool>("debug", false);
166 
167  auto source =
169  (edm::ParameterDescription<edm::FileInPath>("resolutionFile", true) and edm::ParameterDescription<edm::FileInPath>("scaleFactorFile", true));
170  desc.addNode(std::move(source));
171 
173 
174  descriptions.addDefault(desc);
175  }
176 
177  virtual void produce(edm::Event& event, const edm::EventSetup& setup) override {
178 
179  edm::Handle<JetCollection> jets_collection;
180  event.getByToken(m_jets_token, jets_collection);
181 
182  // Disable the module when running on real data
183  if (m_enabled && event.isRealData()) {
184  m_enabled = false;
185  m_genJetMatcher.reset();
186  }
187 
189  if (m_enabled)
190  event.getByToken(m_rho_token, rho);
191 
193  JME::JetResolutionScaleFactor resolution_sf;
194 
195  if (m_enabled) {
196  if (m_use_txt_files) {
197  resolution = *m_resolution_from_file;
198  resolution_sf = *m_scale_factor_from_file;
199  } else {
200  resolution = JME::JetResolution::get(setup, m_jets_algo_pt);
201  resolution_sf = JME::JetResolutionScaleFactor::get(setup, m_jets_algo);
202  }
203  }
204 
205  const JetCollection& jets = *jets_collection;
206 
207  if (m_genJetMatcher)
208  m_genJetMatcher->getTokens(event);
209 
210  auto smearedJets = std::make_unique<JetCollection>();
211 
212  for (const auto& jet: jets) {
213 
214  if ((! m_enabled) || (jet.pt() == 0)) {
215  // Module disabled or invalid p4. Simply copy the input jet.
216  smearedJets->push_back(jet);
217 
218  continue;
219  }
220 
221  double jet_resolution = resolution.getResolution({{JME::Binning::JetPt, jet.pt()}, {JME::Binning::JetEta, jet.eta()}, {JME::Binning::Rho, *rho}});
222  double jer_sf = resolution_sf.getScaleFactor({{JME::Binning::JetEta, jet.eta()}}, m_systematic_variation);
223 
224  if (m_debug) {
225  std::cout << "jet: pt: " << jet.pt() << " eta: " << jet.eta() << " phi: " << jet.phi() << " e: " << jet.energy() << std::endl;
226  std::cout << "resolution: " << jet_resolution << std::endl;
227  std::cout << "resolution scale factor: " << jer_sf << std::endl;
228  }
229 
230  const reco::GenJet* genJet = nullptr;
231  if (m_genJetMatcher)
232  genJet = m_genJetMatcher->match(jet, jet.pt() * jet_resolution);
233 
234  double smearFactor = 1.;
235 
236  if (genJet) {
237  /*
238  * Case 1: we have a "good" gen jet matched to the reco jet
239  */
240 
241  if (m_debug) {
242  std::cout << "gen jet: pt: " << genJet->pt() << " eta: " << genJet->eta() << " phi: " << genJet->phi() << " e: " << genJet->energy() << std::endl;
243  }
244 
245  double dPt = jet.pt() - genJet->pt();
246  smearFactor = 1 + m_nomVar*(jer_sf - 1.) * dPt / jet.pt();
247 
248  } else if (jer_sf > 1) {
249  /*
250  * Case 2: we don't have a gen jet. Smear jet pt using a random gaussian variation
251  */
252 
253  double sigma = jet_resolution * std::sqrt(jer_sf * jer_sf - 1);
254  if (m_debug) {
255  std::cout << "gaussian width: " << sigma << std::endl;
256  }
257 
258  std::normal_distribution<> d(0, sigma);
259  smearFactor = 1. + m_nomVar*d(m_random_generator);
260  } else if (m_debug) {
261  std::cout << "Impossible to smear this jet" << std::endl;
262  }
263 
264  if (jet.energy() * smearFactor < MIN_JET_ENERGY) {
265  // Negative or too small smearFactor. We would change direction of the jet
266  // and this is not what we want.
267  // Recompute the smearing factor in order to have jet.energy() == MIN_JET_ENERGY
268  double newSmearFactor = MIN_JET_ENERGY / jet.energy();
269  if (m_debug) {
270  std::cout << "The smearing factor (" << smearFactor << ") is either negative or too small. Fixing it to " << newSmearFactor << " to avoid change of direction." << std::endl;
271  }
272  smearFactor = newSmearFactor;
273  }
274 
275  T smearedJet = jet;
276  smearedJet.scaleEnergy(smearFactor);
277 
278  if (m_debug) {
279  std::cout << "smeared jet (" << smearFactor << "): pt: " << smearedJet.pt() << " eta: " << smearedJet.eta() << " phi: " << smearedJet.phi() << " e: " << smearedJet.energy() << std::endl;
280  }
281 
282  smearedJets->push_back(smearedJet);
283  }
284 
285  // Sort jets by pt
286  std::sort(smearedJets->begin(), smearedJets->end(), jetPtComparator);
287 
288  event.put(std::move(smearedJets));
289  }
290 
291  private:
292  static constexpr const double MIN_JET_ENERGY = 1e-2;
293 
296  bool m_enabled;
300  bool m_debug;
301  std::shared_ptr<pat::GenJetMatcher> m_genJetMatcher;
302 
304  std::unique_ptr<JME::JetResolution> m_resolution_from_file;
305  std::unique_ptr<JME::JetResolutionScaleFactor> m_scale_factor_from_file;
306 
307  std::mt19937 m_random_generator;
308 
310 
311  int m_nomVar;
312 };
313 #endif
edm::EDGetTokenT< JetCollection > m_jets_token
T getParameter(std::string const &) const
float getResolution(const JetParameters &parameters) const
tuple cfg
Definition: looper.py:293
void getTokens(const edm::Event &event)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
virtual double energy() const final
energy
static const JetResolution get(const edm::EventSetup &, const std::string &)
edm::Handle< reco::GenJetCollection > m_genJets
std::vector< GenJet > GenJetCollection
collection of GenJet objects
virtual void produce(edm::Event &event, const edm::EventSetup &setup) override
GenJetMatcher(const edm::ParameterSet &cfg, edm::ConsumesCollector &&collector)
bool exists(std::string const &parameterName) const
checks if a parameter exists
SmearedJetProducerT(const edm::ParameterSet &cfg)
virtual double phi() const final
momentum azimuthal angle
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
bool isRealData() const
Definition: EventBase.h:62
#define constexpr
GreaterByPt< T > jetPtComparator
const reco::GenJet * match(const T &jet, double resolution)
std::unique_ptr< JME::JetResolution > m_resolution_from_file
tuple d
Definition: ztail.py:151
static void fillDescriptions(edm::ParameterSetDescription &desc)
void addDefault(ParameterSetDescription const &psetDescription)
std::vector< T > JetCollection
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
T sqrt(T t)
Definition: SSEVec.h:18
vector< PseudoJet > jets
def move
Definition: eostools.py:510
const double infinity
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Jets made from MC generator particles.
Definition: GenJet.h:24
ParameterDescriptionBase * add(U const &iLabel, T const &value)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
edm::EDGetTokenT< double > m_rho_token
static const double MIN_JET_ENERGY
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
std::mt19937 m_random_generator
float getScaleFactor(const JetParameters &parameters, Variation variation=Variation::NOMINAL) const
static const JetResolutionScaleFactor get(const edm::EventSetup &, const std::string &)
std::shared_ptr< pat::GenJetMatcher > m_genJetMatcher
std::unique_ptr< JME::JetResolutionScaleFactor > m_scale_factor_from_file
tuple cout
Definition: gather_cfg.py:145
edm::EDGetTokenT< reco::GenJetCollection > m_genJetsToken
virtual double eta() const final
momentum pseudorapidity
volatile std::atomic< bool > shutdown_flag false
long double T
static std::string const source
Definition: EdmProvDump.cc:43
virtual double pt() const final
transverse momentum