CMS 3D CMS Logo

ElectronMVANtuplizer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: RecoEgamma/ElectronIdentification
4 // Class: ElectronMVANtuplizer
5 //
13 //
14 // Original Author: Jonas REMBSER
15 // Created: Thu, 22 Mar 2018 14:54:24 GMT
16 //
17 //
18 
19 
20 // user include files
23 
25 
28 
32 
35 
37 
41 
42 #include <TTree.h>
43 #include <TFile.h>
44 #include <Math/VectorUtil.h>
45 
46 //
47 // class declaration
48 //
49 
50 // If the analyzer does not use TFileService, please remove
51 // the template argument to the base class so the class inherits
52 // from edm::one::EDAnalyzer<>
53 // This will improve performance in multithreaded jobs.
54 //
55 
56 class ElectronMVANtuplizer : public edm::one::EDAnalyzer<edm::one::SharedResources> {
57  public:
58  explicit ElectronMVANtuplizer(const edm::ParameterSet&);
59  ~ElectronMVANtuplizer() override;
60 
61  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
62 
63 
64  private:
65  void beginJob() override;
66  void analyze(const edm::Event&, const edm::EventSetup&) override;
67  void endJob() override;
68 
69  void findFirstNonElectronMother2(const reco::Candidate *particle, int &ancestorPID, int &ancestorStatus);
70 
71  template<class T, class V>
72  int matchToTruth(const T &el, const V &genParticles, int &genIdx);
73 
74  // ----------member data ---------------------------
75 
76  // for AOD case
81 
82  // for miniAOD case
87 
88  // other
89  TTree* tree_;
90 
92  std::vector<float> vars_;
93  int nVars_;
94 
95  //global variables
97  int genNpu_;
98  int vtxN_;
99 
100  // electron variables
101  float eleQ_;
102  int ele3Q_;
105 
106 
107  // gap variables
108  bool eleIsEB_;
109  bool eleIsEE_;
115 
116  // to hold ID decisions and categories
117  std::vector<int> mvaPasses_;
118  std::vector<float> mvaValues_;
119  std::vector<int> mvaCats_;
120 
121  // config
122  const bool isMC_;
123  const double deltaR_;
124  const double ptThreshold_;
125 
126  // ID decisions objects
127  const std::vector< std::string > eleMapTags_;
128  std::vector< edm::EDGetTokenT< edm::ValueMap<bool> > > eleMapTokens_;
129  const std::vector< std::string > eleMapBranchNames_;
130  const size_t nEleMaps_;
131 
132  // MVA values and categories (optional)
133  const std::vector< std::string > valMapTags_;
134  std::vector< edm::EDGetTokenT<edm::ValueMap<float> > > valMapTokens_;
135  const std::vector< std::string > valMapBranchNames_;
136  const size_t nValMaps_;
137 
138  const std::vector< std::string > mvaCatTags_;
139  std::vector< edm::EDGetTokenT<edm::ValueMap<int> > > mvaCatTokens_;
140  const std::vector< std::string > mvaCatBranchNames_;
141  const size_t nCats_;
142 };
143 
144 //
145 // constants, enums and typedefs
146 //
147 
153  }; // The last does not include tau parents
154 
155 //
156 // static data member definitions
157 //
158 
159 //
160 // constructors and destructor
161 //
163  :
164  src_ (consumes<edm::View<reco::GsfElectron> >(iConfig.getParameter<edm::InputTag>("src"))),
165  vertices_ (consumes<std::vector<reco::Vertex> >(iConfig.getParameter<edm::InputTag>("vertices"))),
166  pileup_ (consumes<std::vector< PileupSummaryInfo > >(iConfig.getParameter<edm::InputTag>("pileup"))),
167  genParticles_ (consumes<edm::View<reco::GenParticle> >(iConfig.getParameter<edm::InputTag>("genParticles"))),
168  srcMiniAOD_ (consumes<edm::View<reco::GsfElectron> >(iConfig.getParameter<edm::InputTag>("srcMiniAOD"))),
169  verticesMiniAOD_ (consumes<std::vector<reco::Vertex> >(iConfig.getParameter<edm::InputTag>("verticesMiniAOD"))),
170  pileupMiniAOD_ (consumes<std::vector< PileupSummaryInfo > >(iConfig.getParameter<edm::InputTag>("pileupMiniAOD"))),
171  genParticlesMiniAOD_ (consumes<edm::View<reco::GenParticle> >(iConfig.getParameter<edm::InputTag>("genParticlesMiniAOD"))),
172  mvaVarMngr_ (iConfig.getParameter<std::string>("variableDefinition")),
173  isMC_ (iConfig.getParameter<bool>("isMC")),
174  deltaR_ (iConfig.getParameter<double>("deltaR")),
175  ptThreshold_ (iConfig.getParameter<double>("ptThreshold")),
176  eleMapTags_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVAs")),
177  eleMapBranchNames_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVALabels")),
179  valMapTags_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVAValMaps")),
180  valMapBranchNames_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVAValMapLabels")),
182  mvaCatTags_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVACats")),
183  mvaCatBranchNames_ (iConfig.getUntrackedParameter<std::vector<std::string>>("eleMVACatLabels")),
185 {
186  // eleMaps
187  for (size_t k = 0; k < nEleMaps_; ++k) {
188 
190 
191  // Initialize vectors for holding ID decisions
192  mvaPasses_.push_back(0);
193  }
194 
195  // valMaps
196  for (size_t k = 0; k < nValMaps_; ++k) {
198 
199  // Initialize vectors for holding MVA values
200  mvaValues_.push_back(0.0);
201  }
202 
203  // categories
204  for (size_t k = 0; k < nCats_; ++k) {
206 
207  // Initialize vectors for holding MVA values
208  mvaCats_.push_back(0);
209  }
210 
211  // Book tree
212  usesResource(TFileService::kSharedResource);
214  tree_ = fs->make<TTree>("tree","tree");
215 
217 
218  tree_->Branch("nEvent", &nEvent_);
219  tree_->Branch("nRun", &nRun_);
220  tree_->Branch("nLumi", &nLumi_);
221  if (isMC_) tree_->Branch("genNpu", &genNpu_);
222  tree_->Branch("vtxN", &vtxN_);
223 
224  tree_->Branch("ele_q",&eleQ_);
225  tree_->Branch("ele_3q",&ele3Q_);
226 
227  if (isMC_) {
228  tree_->Branch("matchedToGenEle", &matchedToGenEle_);
229  }
230 
231  // Has to be in two different loops
232  for (int i = 0; i < nVars_; ++i) {
233  vars_.push_back(0.0);
234  }
235  for (int i = 0; i < nVars_; ++i) {
236  tree_->Branch(mvaVarMngr_.getName(i).c_str(), &vars_[i]);
237  }
238 
239  tree_->Branch("ele_isEB",&eleIsEB_);
240  tree_->Branch("ele_isEE",&eleIsEE_);
241  tree_->Branch("ele_isEBEtaGap",&eleIsEBEtaGap_);
242  tree_->Branch("ele_isEBPhiGap",&eleIsEBPhiGap_);
243  tree_->Branch("ele_isEBEEGap", &eleIsEBEEGap_);
244  tree_->Branch("ele_isEEDeeGap",&eleIsEEDeeGap_);
245  tree_->Branch("ele_isEERingGap",&eleIsEERingGap_);
246 
247  // IDs
248  for (size_t k = 0; k < nValMaps_; ++k) {
249  tree_->Branch(valMapBranchNames_[k].c_str() , &mvaValues_[k]);
250  }
251 
252  for (size_t k = 0; k < nEleMaps_; ++k) {
253  tree_->Branch(eleMapBranchNames_[k].c_str() , &mvaPasses_[k]);
254  }
255 
256  for (size_t k = 0; k < nCats_; ++k) {
257  tree_->Branch(mvaCatBranchNames_[k].c_str() , &mvaCats_[k]);
258  }
259 
260  // All tokens for event content needed by this MVA
261  // Tags from the variable helper
262  for (auto &tag : mvaVarMngr_.getHelperInputTags()) {
263  consumes<edm::ValueMap<float>>(tag);
264  }
265  for (auto &tag : mvaVarMngr_.getGlobalInputTags()) {
266  consumes<double>(tag);
267  }
268 }
269 
270 
272 {
273 
274  // do anything here that needs to be done at desctruction time
275  // (e.g. close files, deallocate resources etc.)
276 
277 }
278 
279 
280 //
281 // member functions
282 //
283 
284 // ------------ method called for each event ------------
285 void
287 {
288  // Fill global event info
289  nEvent_ = iEvent.id().event();
290  nRun_ = iEvent.id().run();
291  nLumi_ = iEvent.luminosityBlock();
292 
293 
294  // Retrieve Vertecies
296  iEvent.getByToken(vertices_, vertices);
297  if( !vertices.isValid() ){
298  iEvent.getByToken(verticesMiniAOD_,vertices);
299  if( !vertices.isValid() )
300  throw cms::Exception(" Collection not found: ")
301  << " failed to find a standard AOD or miniAOD vertex collection " << std::endl;
302  }
303 
304  vtxN_ = vertices->size();
305 
306  // Retrieve Pileup Info
307  if(isMC_) {
309  iEvent.getByToken(pileup_, pileup);
310  if( !pileup.isValid() ){
311  iEvent.getByToken(pileupMiniAOD_,pileup);
312  if( !pileup.isValid() )
313  throw cms::Exception(" Collection not found: ")
314  << " failed to find a standard AOD or miniAOD pileup collection " << std::endl;
315  }
316 
317  // Fill with true number of pileup
318  for(const auto& pu : *pileup)
319  {
320  int bx = pu.getBunchCrossing();
321  if(bx == 0)
322  {
323  genNpu_ = pu.getPU_NumInteractions();
324  break;
325  }
326  }
327  }
328 
329  // Retrieve genParticles
331  if(isMC_) {
332  iEvent.getByToken(genParticles_, genParticles);
333  if( !genParticles.isValid() ){
334  iEvent.getByToken(genParticlesMiniAOD_, genParticles);
335  if( !genParticles.isValid() )
336  throw cms::Exception(" Collection not found: ")
337  << " failed to find a standard AOD or miniAOD genParticle collection " << std::endl;
338  }
339  }
340 
341 
343 
344  // Retrieve the collection of particles from the event.
345  // If we fail to retrieve the collection with the standard AOD
346  // name, we next look for the one with the stndard miniAOD name.
347  iEvent.getByToken(src_, src);
348  if( !src.isValid() ){
349  iEvent.getByToken(srcMiniAOD_,src);
350  if( !src.isValid() )
351  throw cms::Exception(" Collection not found: ")
352  << " failed to find a standard AOD or miniAOD particle collection " << std::endl;
353  }
354 
355  // Get MVA decisions
357  for (size_t k = 0; k < nEleMaps_; ++k) {
358  iEvent.getByToken(eleMapTokens_[k],decisions[k]);
359  }
360 
361  // Get MVA values
363  for (size_t k = 0; k < nValMaps_; ++k) {
364  iEvent.getByToken(valMapTokens_[k],values[k]);
365  }
366 
367  // Get MVA categories
369  for (size_t k = 0; k < nCats_; ++k) {
370  iEvent.getByToken(mvaCatTokens_[k],mvaCats[k]);
371  }
372 
373  int nEle = src->size();
374 
375  for(int iEle = 0; iEle < nEle; ++iEle) {
376 
377  const auto ele = src->ptrAt(iEle);
378 
379  eleQ_ = ele->charge();
380  ele3Q_ = ele->chargeInfo().isGsfCtfScPixConsistent;
381 
382  if (ele->pt() < ptThreshold_) {
383  continue;
384  }
385 
386  for (int iVar = 0; iVar < nVars_; ++iVar) {
387  vars_[iVar] = mvaVarMngr_.getValue(iVar, ele, iEvent);
388  }
389 
390  if (isMC_) {
391  matchedToGenEle_ = matchToTruth( ele, genParticles, matchedGenIdx_);
392  }
393 
394  // gap variables
395  eleIsEB_ = ele->isEB();
396  eleIsEE_ = ele->isEE();
397  eleIsEBEEGap_ = ele->isEBEEGap();
398  eleIsEBEtaGap_ = ele->isEBEtaGap();
399  eleIsEBPhiGap_ = ele->isEBPhiGap();
400  eleIsEEDeeGap_ = ele->isEEDeeGap();
401  eleIsEERingGap_ = ele->isEERingGap();
402 
403  //
404  // Look up and save the ID decisions
405  //
406  for (size_t k = 0; k < nEleMaps_; ++k) {
407  mvaPasses_[k] = (int)(*decisions[k])[ele];
408  }
409 
410  for (size_t k = 0; k < nValMaps_; ++k) {
411  mvaValues_[k] = (*values[k])[ele];
412  }
413 
414  for (size_t k = 0; k < nCats_; ++k) {
415  mvaCats_[k] = (*mvaCats[k])[ele];
416  }
417 
418 
419  tree_->Fill();
420  }
421 
422 }
423 
425  int &ancestorPID, int &ancestorStatus){
426 
427  if( particle == nullptr ){
428  edm::LogError ("ElectronNtuplizer") << "ElectronNtuplizer: ERROR! null candidate pointer, this should never happen";
429  return;
430  }
431 
432  // Is this the first non-electron parent? If yes, return, otherwise
433  // go deeper into recursion
434  if( abs(particle->pdgId()) == 11 ){
435  findFirstNonElectronMother2(particle->mother(0), ancestorPID, ancestorStatus);
436  }else{
437  ancestorPID = particle->pdgId();
438  ancestorStatus = particle->status();
439  }
440 
441  return;
442 }
443 
444 template<class T, class V>
445 int ElectronMVANtuplizer::matchToTruth(const T &el, const V &prunedGenParticles, int &genIdx){
446 
447  //
448  // Explicit loop and geometric matching method (advised by Josh Bendavid)
449  //
450 
451  // Find the closest status 1 gen electron to the reco electron
452  double dR = 999;
453  const reco::Candidate *closestElectron = nullptr;
454  for(size_t i=0; i<prunedGenParticles->size();i++){
455  const reco::Candidate *particle = &(*prunedGenParticles)[i];
456  // Drop everything that is not electron or not status 1
457  if( abs(particle->pdgId()) != 11 || particle->status() != 1 )
458  continue;
459  //
460  double dRtmp = ROOT::Math::VectorUtil::DeltaR( el->p4(), particle->p4() );
461  if( dRtmp < dR ){
462  dR = dRtmp;
463  closestElectron = particle;
464  genIdx = i;
465  }
466  }
467  // See if the closest electron (if it exists) is close enough.
468  // If not, no match found.
469  if( !(closestElectron != nullptr && dR < deltaR_) ) {
470  return UNMATCHED;
471  }
472 
473  //
474  int ancestorPID = -999;
475  int ancestorStatus = -999;
476  findFirstNonElectronMother2(closestElectron, ancestorPID, ancestorStatus);
477 
478  if( ancestorPID == -999 && ancestorStatus == -999 ){
479  // No non-electron parent??? This should never happen.
480  // Complain.
481  edm::LogError ("ElectronNtuplizer") << "ElectronNtuplizer: ERROR! null candidate pointer, this should never happen";
482  return UNMATCHED;
483  }
484 
485  if( abs(ancestorPID) > 50 && ancestorStatus == 2 )
487 
488  if( abs(ancestorPID) == 15 && ancestorStatus == 2 )
489  return TRUE_ELECTRON_FROM_TAU;
490 
491  // What remains is true prompt electrons
492  return TRUE_PROMPT_ELECTRON;
493 }
494 
495 // ------------ method called once each job just before starting event loop ------------
496 void
498 {
499 }
500 
501 // ------------ method called once each job just after ending the event loop ------------
502 void
504 {
505 }
506 
507 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
508 void
510 
512  desc.add<edm::InputTag>("src");
513  desc.add<edm::InputTag>("vertices");
514  desc.add<edm::InputTag>("pileup");
515  desc.add<edm::InputTag>("genParticles");
516  desc.add<edm::InputTag>("srcMiniAOD");
517  desc.add<edm::InputTag>("verticesMiniAOD");
518  desc.add<edm::InputTag>("pileupMiniAOD");
519  desc.add<edm::InputTag>("genParticlesMiniAOD");
520  desc.add<std::string>("variableDefinition");
521  desc.add<bool>("isMC");
522  desc.add<double>("deltaR", 0.1);
523  desc.add<double>("ptThreshold", 5.0);
524  desc.addUntracked<std::vector<std::string>>("eleMVAs");
525  desc.addUntracked<std::vector<std::string>>("eleMVALabels");
526  desc.addUntracked<std::vector<std::string>>("eleMVAValMaps");
527  desc.addUntracked<std::vector<std::string>>("eleMVAValMapLabels");
528  desc.addUntracked<std::vector<std::string>>("eleMVACats");
529  desc.addUntracked<std::vector<std::string>>("eleMVACatLabels");
530  descriptions.addDefault(desc);
531 
532 }
533 
534 //define this as a plug-in
RunNumber_t run() const
Definition: EventID.h:39
size
Write out results.
static const std::string kSharedResource
Definition: TFileService.h:76
const std::string getName(int index) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
EventNumber_t event() const
Definition: EventID.h:41
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
const edm::EDGetToken srcMiniAOD_
const edm::EDGetToken verticesMiniAOD_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
std::vector< edm::InputTag > getHelperInputTags() const
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:63
virtual const Candidate * mother(size_type i=0) const =0
return pointer to mother
T * make(const Args &...args) const
make new ROOT object
Definition: TFileService.h:64
std::vector< edm::EDGetTokenT< edm::ValueMap< int > > > mvaCatTokens_
std::vector< float > mvaValues_
const edm::EDGetToken vertices_
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
virtual int status() const =0
status word
int iEvent
Definition: GenABIO.cc:230
void addDefault(ParameterSetDescription const &psetDescription)
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
virtual int pdgId() const =0
PDG identifier.
std::vector< int > mvaPasses_
const std::vector< std::string > valMapBranchNames_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< int > mvaCats_
ElectronMVANtuplizer(const edm::ParameterSet &)
int matchToTruth(const T &el, const V &genParticles, int &genIdx)
const int getNVars() const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool isValid() const
Definition: HandleBase.h:74
int k[5][pyjets_maxn]
const edm::EDGetToken genParticlesMiniAOD_
const std::vector< std::string > eleMapBranchNames_
std::vector< float > vars_
MVAVariableManager< reco::GsfElectron > mvaVarMngr_
float getValue(int index, const edm::Ptr< ParticleType > &ptclPtr, const edm::EventBase &iEvent) const
std::vector< edm::EDGetTokenT< edm::ValueMap< float > > > valMapTokens_
void analyze(const edm::Event &, const edm::EventSetup &) override
const edm::EDGetToken pileupMiniAOD_
void findFirstNonElectronMother2(const reco::Candidate *particle, int &ancestorPID, int &ancestorStatus)
edm::EventID id() const
Definition: EventBase.h:60
fixed size matrix
HLT enums.
const std::vector< std::string > mvaCatTags_
std::vector< edm::EDGetTokenT< edm::ValueMap< bool > > > eleMapTokens_
const edm::EDGetToken pileup_
const edm::EDGetToken src_
long double T
const edm::EDGetToken genParticles_
const std::vector< std::string > mvaCatBranchNames_
std::vector< edm::InputTag > getGlobalInputTags() const
const std::vector< std::string > eleMapTags_
const std::vector< std::string > valMapTags_