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