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 // user include files
37 
38 #include <TTree.h>
39 #include <TFile.h>
40 #include <Math/VectorUtil.h>
41 
42 //
43 // class declaration
44 //
45 
46 class ElectronMVANtuplizer : public edm::one::EDAnalyzer<edm::one::SharedResources> {
47 public:
48  explicit ElectronMVANtuplizer(const edm::ParameterSet&);
49 
50  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
51 
52 private:
53  void analyze(const edm::Event&, const edm::EventSetup&) override;
54 
55  // method called once each job just before starting event loop
56  void beginJob() override{};
57  // method called once each job just after ending the event loop
58  void endJob() override{};
59 
61 
62  // ----------member data ---------------------------
63 
64  //global variables
65  int nEvent_;
66  int nRun_;
67  int nLumi_;
68  int genNpu_;
69  int vtxN_;
70 
71  // electron variables
72  float eleQ_;
73  int ele3Q_;
75 
76  std::vector<float> energyMatrix_;
77 
78  // gap variables
79  bool eleIsEB_;
80  bool eleIsEE_;
86 
87  // config
88  const bool isMC_;
89  const double deltaR_;
90  const double ptThreshold_;
91 
92  // ID decisions objects
93  const std::vector<std::string> eleMapTags_;
94  std::vector<edm::EDGetTokenT<edm::ValueMap<bool>>> eleMapTokens_;
95  const std::vector<std::string> eleMapBranchNames_;
96  const size_t nEleMaps_;
97 
98  // MVA values and categories (optional)
99  const std::vector<std::string> valMapTags_;
100  std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> valMapTokens_;
101  const std::vector<std::string> valMapBranchNames_;
102  const size_t nValMaps_;
103 
104  const std::vector<std::string> mvaCatTags_;
105  std::vector<edm::EDGetTokenT<edm::ValueMap<int>>> mvaCatTokens_;
106  const std::vector<std::string> mvaCatBranchNames_;
107  const size_t nCats_;
108 
109  // Tokens
116 
118 
119  // to hold ID decisions and categories
120  std::vector<int> mvaPasses_;
121  std::vector<float> mvaValues_;
122  std::vector<int> mvaCats_;
123 
124  // To get the auxiliary MVA variables
126 
127  // other
128  TTree* tree_;
129 
131  const int nVars_;
132  std::vector<float> vars_;
133 
134  const bool doEnergyMatrix_;
135  const int energyMatrixSize_;
136 };
137 
138 //
139 // constants, enums and typedefs
140 //
141 
147 }; // The last does not include tau parents
148 
149 //
150 // constructors and destructor
151 //
153  : isMC_(iConfig.getParameter<bool>("isMC")),
154  deltaR_(iConfig.getParameter<double>("deltaR")),
155  ptThreshold_(iConfig.getParameter<double>("ptThreshold")),
156  eleMapTags_(iConfig.getParameter<std::vector<std::string>>("eleMVAs")),
157  eleMapBranchNames_(iConfig.getParameter<std::vector<std::string>>("eleMVALabels")),
158  nEleMaps_(eleMapBranchNames_.size()),
159  valMapTags_(iConfig.getParameter<std::vector<std::string>>("eleMVAValMaps")),
160  valMapBranchNames_(iConfig.getParameter<std::vector<std::string>>("eleMVAValMapLabels")),
161  nValMaps_(valMapBranchNames_.size()),
162  mvaCatTags_(iConfig.getParameter<std::vector<std::string>>("eleMVACats")),
163  mvaCatBranchNames_(iConfig.getParameter<std::vector<std::string>>("eleMVACatLabels")),
164  nCats_(mvaCatBranchNames_.size()),
165  src_(consumes<edm::View<reco::GsfElectron>>(iConfig.getParameter<edm::InputTag>("src"))),
166  vertices_(consumes<std::vector<reco::Vertex>>(iConfig.getParameter<edm::InputTag>("vertices"))),
167  pileup_(consumes<std::vector<PileupSummaryInfo>>(iConfig.getParameter<edm::InputTag>("pileup"))),
168  genParticles_(consumes<edm::View<reco::GenParticle>>(iConfig.getParameter<edm::InputTag>("genParticles"))),
169  ebRecHits_(consumes<EcalRecHitCollection>(iConfig.getParameter<edm::InputTag>("ebReducedRecHitCollection"))),
170  eeRecHits_(consumes<EcalRecHitCollection>(iConfig.getParameter<edm::InputTag>("eeReducedRecHitCollection"))),
171  ecalClusterToolsESGetTokens_{consumesCollector()},
172  mvaPasses_(nEleMaps_),
173  mvaValues_(nValMaps_),
174  mvaCats_(nCats_),
175  variableHelper_(consumesCollector()),
176  mvaVarMngr_(iConfig.getParameter<std::string>("variableDefinition"), MVAVariableHelper::indexMap()),
177  nVars_(mvaVarMngr_.getNVars()),
178  vars_(nVars_),
179  doEnergyMatrix_(iConfig.getParameter<bool>("doEnergyMatrix")),
180  energyMatrixSize_(iConfig.getParameter<int>("energyMatrixSize")) {
181  // eleMaps
182  for (auto const& tag : eleMapTags_) {
183  eleMapTokens_.push_back(consumes<edm::ValueMap<bool>>(edm::InputTag(tag)));
184  }
185  // valMaps
186  for (auto const& tag : valMapTags_) {
187  valMapTokens_.push_back(consumes<edm::ValueMap<float>>(edm::InputTag(tag)));
188  }
189  // categories
190  for (auto const& tag : mvaCatTags_) {
191  mvaCatTokens_.push_back(consumes<edm::ValueMap<int>>(edm::InputTag(tag)));
192  }
193 
194  // Book tree
195  usesResource(TFileService::kSharedResource);
197  tree_ = fs->make<TTree>("tree", "tree");
198 
199  tree_->Branch("nEvent", &nEvent_);
200  tree_->Branch("nRun", &nRun_);
201  tree_->Branch("nLumi", &nLumi_);
202  if (isMC_)
203  tree_->Branch("genNpu", &genNpu_);
204  tree_->Branch("vtxN", &vtxN_);
205 
206  tree_->Branch("ele_q", &eleQ_);
207  tree_->Branch("ele_3q", &ele3Q_);
208 
209  if (doEnergyMatrix_)
210  tree_->Branch("energyMatrix", &energyMatrix_);
211 
212  if (isMC_)
213  tree_->Branch("matchedToGenEle", &matchedToGenEle_);
214 
215  for (int i = 0; i < nVars_; ++i)
216  tree_->Branch(mvaVarMngr_.getName(i).c_str(), &vars_[i]);
217 
218  tree_->Branch("ele_isEB", &eleIsEB_);
219  tree_->Branch("ele_isEE", &eleIsEE_);
220  tree_->Branch("ele_isEBEtaGap", &eleIsEBEtaGap_);
221  tree_->Branch("ele_isEBPhiGap", &eleIsEBPhiGap_);
222  tree_->Branch("ele_isEBEEGap", &eleIsEBEEGap_);
223  tree_->Branch("ele_isEEDeeGap", &eleIsEEDeeGap_);
224  tree_->Branch("ele_isEERingGap", &eleIsEERingGap_);
225 
226  // IDs
227  for (size_t k = 0; k < nValMaps_; ++k) {
228  tree_->Branch(valMapBranchNames_[k].c_str(), &mvaValues_[k]);
229  }
230 
231  for (size_t k = 0; k < nEleMaps_; ++k) {
232  tree_->Branch(eleMapBranchNames_[k].c_str(), &mvaPasses_[k]);
233  }
234 
235  for (size_t k = 0; k < nCats_; ++k) {
236  tree_->Branch(mvaCatBranchNames_[k].c_str(), &mvaCats_[k]);
237  }
238 }
239 
240 // ------------ method called for each event ------------
242  // Fill global event info
243  nEvent_ = iEvent.id().event();
244  nRun_ = iEvent.id().run();
245  nLumi_ = iEvent.luminosityBlock();
246 
247  // Get Handles
248  auto src = iEvent.getHandle(src_);
249  auto vertices = iEvent.getHandle(vertices_);
250 
251  // initialize cluster tools
252  std::unique_ptr<noZS::EcalClusterLazyTools> lazyTools;
253  if (doEnergyMatrix_) {
254  // Configure Lazy Tools, which will compute 5x5 quantities
255  lazyTools = std::make_unique<noZS::EcalClusterLazyTools>(
257  }
258 
259  // Get MC only Handles, which are allowed to be non-valid
260  auto genParticles = iEvent.getHandle(genParticles_);
261  auto pileup = iEvent.getHandle(pileup_);
262 
263  vtxN_ = vertices->size();
264 
265  // Fill with true number of pileup
266  if (isMC_) {
267  for (const auto& pu : *pileup) {
268  int bx = pu.getBunchCrossing();
269  if (bx == 0) {
270  genNpu_ = pu.getPU_NumInteractions();
271  break;
272  }
273  }
274  }
275 
276  // Get MVA decisions
278  for (size_t k = 0; k < nEleMaps_; ++k) {
279  iEvent.getByToken(eleMapTokens_[k], decisions[k]);
280  }
281 
282  // Get MVA values
284  for (size_t k = 0; k < nValMaps_; ++k) {
285  iEvent.getByToken(valMapTokens_[k], values[k]);
286  }
287 
288  // Get MVA categories
290  for (size_t k = 0; k < nCats_; ++k) {
291  iEvent.getByToken(mvaCatTokens_[k], mvaCats[k]);
292  }
293 
294  std::vector<float> extraVariables = variableHelper_.getAuxVariables(iEvent);
295 
296  for (auto const& ele : src->ptrs()) {
297  if (ele->pt() < ptThreshold_)
298  continue;
299 
300  // Fill the energy matrix around the seed
301  if (doEnergyMatrix_) {
302  const auto& seed = *(ele->superCluster()->seed());
303  energyMatrix_ = lazyTools->energyMatrix(seed, energyMatrixSize_);
304  }
305 
306  // Fill various tree variable
307  eleQ_ = ele->charge();
308  ele3Q_ = ele->chargeInfo().isGsfCtfScPixConsistent;
309 
310  for (int iVar = 0; iVar < nVars_; ++iVar) {
311  vars_[iVar] = mvaVarMngr_.getValue(iVar, *ele, extraVariables);
312  }
313 
314  if (isMC_) {
316  }
317 
318  // gap variables
319  eleIsEB_ = ele->isEB();
320  eleIsEE_ = ele->isEE();
321  eleIsEBEEGap_ = ele->isEBEEGap();
322  eleIsEBEtaGap_ = ele->isEBEtaGap();
323  eleIsEBPhiGap_ = ele->isEBPhiGap();
324  eleIsEEDeeGap_ = ele->isEEDeeGap();
325  eleIsEERingGap_ = ele->isEERingGap();
326 
327  //
328  // Look up and save the ID decisions
329  //
330  for (size_t k = 0; k < nEleMaps_; ++k)
331  mvaPasses_[k] = static_cast<int>((*decisions[k])[ele]);
332  for (size_t k = 0; k < nValMaps_; ++k)
333  mvaValues_[k] = (*values[k])[ele];
334  for (size_t k = 0; k < nCats_; ++k)
335  mvaCats_[k] = (*mvaCats[k])[ele];
336 
337  tree_->Fill();
338  }
339 }
340 
343  //
344  // Explicit loop and geometric matching method (advised by Josh Bendavid)
345  //
346 
347  // Find the closest status 1 gen electron to the reco electron
348  double dR = 999;
349  reco::GenParticle const* closestElectron = nullptr;
350  for (auto const& particle : genParticles) {
351  // Drop everything that is not electron or not status 1
352  if (std::abs(particle.pdgId()) != 11 || particle.status() != 1)
353  continue;
354  //
355  double dRtmp = ROOT::Math::VectorUtil::DeltaR(electron.p4(), particle.p4());
356  if (dRtmp < dR) {
357  dR = dRtmp;
358  closestElectron = &particle;
359  }
360  }
361  // See if the closest electron is close enough. If not, no match found.
362  if (closestElectron == nullptr || dR >= deltaR_)
363  return UNMATCHED;
364 
365  if (closestElectron->fromHardProcessFinalState())
366  return TRUE_PROMPT_ELECTRON;
367 
368  if (closestElectron->isDirectHardProcessTauDecayProductFinalState())
369  return TRUE_ELECTRON_FROM_TAU;
370 
371  // What remains is true non-prompt electrons
373 }
374 
375 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
378  desc.add<edm::InputTag>("src", edm::InputTag("slimmedElectrons"));
379  desc.add<edm::InputTag>("vertices", edm::InputTag("offlineSlimmedPrimaryVertices"));
380  desc.add<edm::InputTag>("pileup", edm::InputTag("slimmedAddPileupInfo"));
381  desc.add<edm::InputTag>("genParticles", edm::InputTag("prunedGenParticles"));
382  desc.add<edm::InputTag>("ebReducedRecHitCollection", edm::InputTag("reducedEgamma", "reducedEBRecHits"));
383  desc.add<edm::InputTag>("eeReducedRecHitCollection", edm::InputTag("reducedEgamma", "reducedEERecHits"));
384  desc.add<std::string>("variableDefinition");
385  desc.add<bool>("doEnergyMatrix", false);
386  desc.add<int>("energyMatrixSize", 2)->setComment("extension of crystals in each direction away from the seed");
387  desc.add<bool>("isMC", true);
388  desc.add<double>("deltaR", 0.1);
389  desc.add<double>("ptThreshold", 5.0);
390  desc.add<std::vector<std::string>>("eleMVAs", {});
391  desc.add<std::vector<std::string>>("eleMVALabels", {});
392  desc.add<std::vector<std::string>>("eleMVAValMaps", {});
393  desc.add<std::vector<std::string>>("eleMVAValMapLabels", {});
394  desc.add<std::vector<std::string>>("eleMVACats", {});
395  desc.add<std::vector<std::string>>("eleMVACatLabels", {});
396  descriptions.addDefault(desc);
397 }
398 
399 //define this as a plug-in
size
Write out results.
static const std::string kSharedResource
Definition: TFileService.h:76
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< edm::EDGetTokenT< edm::ValueMap< bool > > > eleMapTokens_
const edm::EDGetTokenT< std::vector< PileupSummaryInfo > > pileup_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const edm::EDGetTokenT< EcalRecHitCollection > ebRecHits_
std::vector< edm::EDGetTokenT< edm::ValueMap< int > > > mvaCatTokens_
const std::vector< std::string > mvaCatBranchNames_
std::vector< float > mvaValues_
std::vector< edm::EDGetTokenT< edm::ValueMap< float > > > valMapTokens_
const EcalClusterLazyTools::ESGetTokens ecalClusterToolsESGetTokens_
static std::unordered_map< std::string, int > indexMap()
bool isDirectHardProcessTauDecayProductFinalState() const
Definition: GenParticle.h:85
const std::vector< std::string > eleMapBranchNames_
ESData get(edm::EventSetup const &eventSetup) const
const std::vector< std::string > valMapTags_
int iEvent
Definition: GenABIO.cc:224
const std::vector< std::string > mvaCatTags_
void addDefault(ParameterSetDescription const &psetDescription)
const edm::EDGetTokenT< std::vector< reco::Vertex > > vertices_
const std::vector< std::string > valMapBranchNames_
std::vector< float > energyMatrix_
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
std::vector< int > mvaPasses_
const MVAVariableHelper variableHelper_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< int > mvaCats_
ElectronMVANtuplizer(const edm::ParameterSet &)
const edm::EDGetTokenT< edm::View< reco::GsfElectron > > src_
const edm::EDGetTokenT< edm::View< reco::GenParticle > > genParticles_
int matchToTruth(reco::GsfElectron const &electron, edm::View< reco::GenParticle > const &genParticles) const
const std::vector< std::string > eleMapTags_
float getValue(int index, const ParticleType &particle, const std::vector< float > &auxVariables) const
std::vector< float > vars_
MVAVariableManager< reco::GsfElectron > mvaVarMngr_
void analyze(const edm::Event &, const edm::EventSetup &) override
fixed size matrix
HLT enums.
constexpr int nVars_
const edm::EDGetTokenT< EcalRecHitCollection > eeRecHits_
const std::vector< float > getAuxVariables(const edm::Event &iEvent) const
bool fromHardProcessFinalState() const
Definition: GenParticle.h:75