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 PhysicsTools_PatUtils_SmearedJetProducerT_h
2 #define PhysicsTools_PatUtils_SmearedJetProducerT_h
3 
24 
27 
31 
35 
38 
39 #include <TFile.h>
40 #include <TFormula.h>
41 #include <TH2.h>
42 #include <TMath.h>
43 #include <TRandom3.h>
44 #include <TString.h>
45 
46 #include <iostream>
47 #include <iomanip>
48 
49 namespace SmearedJetProducer_namespace
50 {
51  template <typename T>
53  {
54  public:
55 
57  : srcGenJetsToken_(iC.consumes<reco::GenJetCollection>(cfg.getParameter<edm::InputTag>("srcGenJets"))),
59  {
60  TString dRmaxGenJetMatch_formula = cfg.getParameter<std::string>("dRmaxGenJetMatch").data();
61  dRmaxGenJetMatch_formula.ReplaceAll("genJetPt", "x");
62  dRmaxGenJetMatch_ = new TFormula("dRmaxGenJetMatch", dRmaxGenJetMatch_formula.Data());
63  }
65  {
66  delete dRmaxGenJetMatch_;
67  }
68 
69  const reco::GenJet* operator()(const T& jet, edm::Event* evt = 0) const
70  {
71  assert(evt);
72 
74  evt->getByToken(srcGenJetsToken_, genJets);
75 
76  const reco::GenJet* retVal = 0;
77 
78  double dRbestMatch = 1.e+6;
79  for ( reco::GenJetCollection::const_iterator genJet = genJets->begin();
80  genJet != genJets->end(); ++genJet ) {
81  double dRmax = dRmaxGenJetMatch_->Eval(genJet->pt());
82  //std::cout << "genJetPt = " << genJet->pt() << ": dRmax = " << dRmax << std::endl;
83  double dR = deltaR(jet.p4(), genJet->p4());
84  if ( dR < dRbestMatch && dR < dRmax ) {
85  retVal = &(*genJet);
86  dRbestMatch = dR;
87  }
88  }
89 
90  return retVal;
91  }
92 
93  private:
94 
95 //--- configuration parameter
98 
99  TFormula* dRmaxGenJetMatch_;
100  };
101 
102  template <typename T>
104  {
105  public:
106 
109 
110  double operator()(const T&) const
111  {
112  throw cms::Exception("SmearedJetProducer::produce")
113  << " Jets of type other than PF not supported yet !!\n";
114  }
115  };
116 
117  template <typename T>
118  class RawJetExtractorT // this template is neccessary to support pat::Jets
119  // (because pat::Jet->p4() returns the JES corrected, not the raw, jet momentum)
120  {
121  public:
122 
124  {
125  return jet.p4();
126  }
127  };
128 
129  template <>
130  class RawJetExtractorT<pat::Jet>
131  {
132  public:
133 
135  {
136  if ( jet.jecSetsAvailable() ) return jet.correctedP4("Uncorrected");
137  else return jet.p4();
138  }
139  };
140 }
141 
142 template <typename T, typename Textractor>
144 {
145  typedef std::vector<T> JetCollection;
146 
147  public:
148 
150  : moduleLabel_(cfg.getParameter<std::string>("@module_label")),
152  jetResolutionExtractor_(cfg.getParameter<edm::ParameterSet>("jetResolutions")),
154  {
155  //std::cout << "<SmearedJetProducer::SmearedJetProducer>:" << std::endl;
156  //std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
157 
158  src_ = cfg.getParameter<edm::InputTag>("src");
159  srcToken_ = consumes<JetCollection>(src_);
160 
162  std::string lutName = cfg.getParameter<std::string>("lutName");
163  if (inputFileName.location() == edm::FileInPath::Unknown)
164  throw cms::Exception("JetMETsmearInputProducer")
165  << " Failed to find File = " << inputFileName << " !!\n";
166 
167  inputFile_ = new TFile(inputFileName.fullPath().data());
168  lut_ = dynamic_cast<TH2*>(inputFile_->Get(lutName.data()));
169  if ( !lut_ )
170  throw cms::Exception("SmearedJetProducer")
171  << " Failed to load LUT = " << lutName.data() << " from file = " << inputFileName.fullPath().data() << " !!\n";
172 
173  jetCorrLabel_ = ( cfg.exists("jetCorrLabel") ) ?
174  cfg.getParameter<std::string>("jetCorrLabel") : "";
175  jetCorrEtaMax_ = ( cfg.exists("jetCorrEtaMax") ) ?
176  cfg.getParameter<double>("jetCorrEtaMax") : 9.9;
177 
178  sigmaMaxGenJetMatch_ = cfg.getParameter<double>("sigmaMaxGenJetMatch");
179 
180  smearBy_ = ( cfg.exists("smearBy") ) ? cfg.getParameter<double>("smearBy") : 1.0;
181  //std::cout << "smearBy = " << smearBy_ << std::endl;
182 
183  shiftBy_ = ( cfg.exists("shiftBy") ) ? cfg.getParameter<double>("shiftBy") : 0.;
184  //std::cout << "shiftBy = " << shiftBy_ << std::endl;
185 
186  if ( cfg.exists("skipJetSelection") ) {
187  std::string skipJetSelection_string = cfg.getParameter<std::string>("skipJetSelection");
188  skipJetSelection_ = new StringCutObjectSelector<T>(skipJetSelection_string);
189  }
190 
191  skipRawJetPtThreshold_ = ( cfg.exists("skipRawJetPtThreshold") ) ?
192  cfg.getParameter<double>("skipRawJetPtThreshold") : 1.e-2;
193  skipCorrJetPtThreshold_ = ( cfg.exists("skipCorrJetPtThreshold") ) ?
194  cfg.getParameter<double>("skipCorrJetPtThreshold") : 1.e-2;
195 
196  verbosity_ = ( cfg.exists("verbosity") ) ?
197  cfg.getParameter<int>("verbosity") : 0;
198 
199  produces<JetCollection>();
200  }
202  {
203  delete skipJetSelection_;
204  delete inputFile_;
205  delete lut_;
206  }
207 
208  private:
209 
210  virtual void produce(edm::Event& evt, const edm::EventSetup& es)
211  {
212  if ( verbosity_ ) {
213  std::cout << "<SmearedJetProducerT::produce>:" << std::endl;
214  std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
215  std::cout << " src = " << src_.label() << std::endl;
216  }
217 
218  std::auto_ptr<JetCollection> smearedJets(new JetCollection);
219 
221  evt.getByToken(srcToken_, jets);
222 
223  int numJets = jets->size();
224  for ( int jetIndex = 0; jetIndex < numJets; ++jetIndex ) {
225  const T& jet = jets->at(jetIndex);
226 
228  reco::Candidate::LorentzVector rawJetP4 = rawJetExtractor(jet);
229  if ( verbosity_ ) {
230  std::cout << "rawJet: Pt = " << rawJetP4.pt() << ", eta = " << rawJetP4.eta() << ", phi = " << rawJetP4.phi() << std::endl;
231  }
232 
233  reco::Candidate::LorentzVector corrJetP4 = jet.p4();
234  if ( jetCorrLabel_ != "" ) corrJetP4 = jetCorrExtractor_(jet, jetCorrLabel_, &evt, &es, jetCorrEtaMax_, &rawJetP4);
235  if ( verbosity_ ) {
236  std::cout << "corrJet: Pt = " << corrJetP4.pt() << ", eta = " << corrJetP4.eta() << ", phi = " << corrJetP4.phi() << std::endl;
237  }
238 
239  double smearFactor = 1.;
240  double x = TMath::Abs(corrJetP4.eta());
241  double y = corrJetP4.pt();
242  if ( x > lut_->GetXaxis()->GetXmin() && x < lut_->GetXaxis()->GetXmax() &&
243  y > lut_->GetYaxis()->GetXmin() && y < lut_->GetYaxis()->GetXmax() ) {
244  int binIndex = lut_->FindBin(x, y);
245 
246  if ( smearBy_ > 0. ) smearFactor += smearBy_*(lut_->GetBinContent(binIndex) - 1.);
247  double smearFactorErr = lut_->GetBinError(binIndex);
248  if ( verbosity_ ) std::cout << "smearFactor = " << smearFactor << " +/- " << smearFactorErr << std::endl;
249 
250  if ( shiftBy_ != 0. ) {
251  smearFactor += (shiftBy_*smearFactorErr);
252  if ( verbosity_ ) std::cout << "smearFactor(shifted) = " << smearFactor << std::endl;
253  }
254  }
255 
256  double smearedJetEn = jet.energy();
257  double sigmaEn = jetResolutionExtractor_(jet)*TMath::Sqrt(smearFactor*smearFactor - 1.);
258  const reco::GenJet* genJet = genJetMatcher_(jet, &evt);
259  bool isGenMatched = false;
260  if ( genJet ) {
261  if ( verbosity_ ) {
262  std::cout << "genJet: Pt = " << genJet->pt() << ", eta = " << genJet->eta() << ", phi = " << genJet->phi() << std::endl;
263  }
264  double dEn = corrJetP4.E() - genJet->energy();
265  if ( dEn < (sigmaMaxGenJetMatch_*sigmaEn) ) {
266 //--- case 1: reconstructed jet matched to generator level jet,
267 // smear difference between reconstructed and "true" jet energy
268 
269  if ( verbosity_ ) {
270  std::cout << " successfully matched to genJet" << std::endl;
271  std::cout << "corrJetEn = " << corrJetP4.E() << ", genJetEn = " << genJet->energy() << " --> dEn = " << dEn << std::endl;
272  }
273 
274  smearedJetEn = jet.energy()*(1. + (smearFactor - 1.)*dEn/TMath::Max(rawJetP4.E(), corrJetP4.E()));
275  isGenMatched = true;
276  }
277  }
278  if ( !isGenMatched ) {
279 //--- case 2: reconstructed jet **not** matched to generator level jet,
280 // smear jet energy using MC resolution functions implemented in PFMEt significance algorithm (CMS AN-10/400)
281 
282  if ( verbosity_ ) {
283  std::cout << " not matched to genJet" << std::endl;
284  std::cout << "corrJetEn = " << corrJetP4.E() << ", sigmaEn = " << sigmaEn << std::endl;
285  }
286 
287  if ( smearFactor > 1. ) {
288  // CV: MC resolution already accounted for in reconstructed jet,
289  // add additional Gaussian smearing of width = sqrt(smearFactor^2 - 1)
290  // to account for Data/MC **difference** in jet resolutions.
291  // Take maximum(rawJetEn, corrJetEn) to avoid pathological cases
292  // (e.g. corrJetEn << rawJetEn, due to L1Fastjet corrections)
293 
294  smearedJetEn = jet.energy()*(1. + rnd_.Gaus(0., sigmaEn)/TMath::Max(rawJetP4.E(), corrJetP4.E()));
295  }
296  }
297 
298  // CV: keep minimum jet energy, in order not to loose direction information
299  const double minJetEn = 1.e-2;
300  if ( smearedJetEn < minJetEn ) smearedJetEn = minJetEn;
301 
302  // CV: skip smearing in case either "raw" or "corrected" jet energy is very low
303  // or jet passes selection configurable via python
304  // (allows for protection against "pathological cases",
305  // cf. PhysicsTools/PatUtils/python/tools/metUncertaintyTools.py)
306  reco::Candidate::LorentzVector smearedJetP4 = jet.p4();
307  if ( !((skipJetSelection_ && (*skipJetSelection_)(jet)) ||
308  rawJetP4.pt() < skipRawJetPtThreshold_ ||
309  corrJetP4.pt() < skipCorrJetPtThreshold_ ) ) {
310  if ( verbosity_ ) {
311  std::cout << " smearing jetP4 by factor = " << (smearedJetEn/jet.energy()) << " --> smearedJetEn = " << smearedJetEn << std::endl;
312  }
313  smearedJetP4 *= (smearedJetEn/jet.energy());
314  }
315 
316  if ( verbosity_ ) {
317  std::cout << "smearedJet: Pt = " << smearedJetP4.pt() << ", eta = " << smearedJetP4.eta() << ", phi = " << smearedJetP4.phi() << std::endl;
318  std::cout << " dPt = " << (smearedJetP4.pt() - jet.pt())
319  << " (Px = " << (smearedJetP4.px() - jet.px()) << ", Py = " << (smearedJetP4.py() - jet.py()) << ")" << std::endl;
320  }
321 
322  T smearedJet = (jet);
323  smearedJet.setP4(smearedJetP4);
324 
325  smearedJets->push_back(smearedJet);
326  }
327 
328 //--- add collection of "smeared" jets to the event
329  evt.put(smearedJets);
330  }
331 
333 
335 
336 //--- configuration parameters
337 
338  // collection of pat::Jets (with L2L3/L2L3Residual corrections applied)
341 
342  TFile* inputFile_;
343  TH2* lut_;
344 
346  TRandom3 rnd_;
347 
348  std::string jetCorrLabel_; // e.g. 'ak5PFJetL1FastL2L3' (reco::PFJets) / '' (pat::Jets)
349  double jetCorrEtaMax_; // do not use JEC factors for |eta| above this threshold (recommended default = 4.7),
350  // in order to work around problem with CMSSW_4_2_x JEC factors at high eta,
351  // reported in
352  // https://hypernews.cern.ch/HyperNews/CMS/get/jes/270.html
353  // https://hypernews.cern.ch/HyperNews/CMS/get/JetMET/1259/1.html
354  Textractor jetCorrExtractor_;
355 
356  double sigmaMaxGenJetMatch_; // maximum difference between energy of reconstructed jet and matched generator level jet
357  // (if the difference between reconstructed and generated jet energy exceeds this threshold,
358  // the jet is considered to have substantial pile-up contributions are is considered to be unmatched)
359 
360  double smearBy_; // option to "smear" jet energy by N standard-deviations, useful for template morphing
361 
362  double shiftBy_; // option to increase/decrease within uncertainties the jet energy resolution used for smearing
363 
364  StringCutObjectSelector<T>* skipJetSelection_; // jets passing this cut are **not** smeared
365  double skipRawJetPtThreshold_; // jets with transverse momenta below this value (either on "raw" or "corrected" level)
366  double skipCorrJetPtThreshold_; // are **not** smeared
367 
368  int verbosity_; // flag to enabled/disable debug output
369 };
370 
371 #endif
virtual double energy() const GCC11_FINAL
energy
T getParameter(std::string const &) const
reco::Candidate::LorentzVector operator()(const pat::Jet &jet) const
edm::EDGetTokenT< JetCollection > srcToken_
StringCutObjectSelector< T > * skipJetSelection_
bool jecSetsAvailable() const
Definition: Jet.h:119
virtual const LorentzVector & p4() const GCC11_FINAL
four-momentum Lorentz vector
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:434
std::vector< GenJet > GenJetCollection
collection of GenJet objects
bool exists(std::string const &parameterName) const
checks if a parameter exists
const LorentzVector & correctedP4(const std::string &level, const std::string &flavor="none", const std::string &set="") const
Definition: Jet.h:146
SmearedJetProducer_namespace::GenJetMatcherT< T > genJetMatcher_
SmearedJetProducerT(const edm::ParameterSet &cfg)
virtual float phi() const GCC11_FINAL
momentum azimuthal angle
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:116
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
vector< PseudoJet > jets
Jets made from MC generator particles.
Definition: GenJet.h:24
virtual float eta() const GCC11_FINAL
momentum pseudorapidity
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
GenJetMatcherT(const edm::ParameterSet &cfg, edm::ConsumesCollector &&iC)
SmearedJetProducer_namespace::JetResolutionExtractorT< T > jetResolutionExtractor_
Analysis-level calorimeter jet class.
Definition: Jet.h:73
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:41
std::string const & label() const
Definition: InputTag.h:42
const reco::GenJet * operator()(const T &jet, edm::Event *evt=0) const
edm::EDGetTokenT< reco::GenJetCollection > srcGenJetsToken_
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
reco::Candidate::LorentzVector operator()(const T &jet) const
tuple cout
Definition: gather_cfg.py:121
Definition: DDAxes.h:10
virtual float pt() const GCC11_FINAL
transverse momentum
long double T
std::vector< T > JetCollection
virtual void produce(edm::Event &evt, const edm::EventSetup &es)