CMS 3D CMS Logo

MuonMCClassifier.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: MuonMCClassifier
4 // Class: MuonMCClassifier
5 //
28 //
29 // Original Author: G.Petrucciani and G.Abbiendi
30 // Created: Sun Nov 16 16:14:09 CET 2008
31 // revised: 3/Aug/2017
32 //
33 
34 
35 // system include files
36 #include <memory>
37 #include <set>
38 
39 // user include files
42 
47 
49 
53 
58 
62 
64 
65 //
66 // class decleration
68  public:
69  explicit MuonMCClassifier(const edm::ParameterSet&);
70  ~MuonMCClassifier() override;
71 
72  private:
73  void produce(edm::Event&, const edm::EventSetup&) override;
76 
81 
84 
87 
91 
94 
99 
101  int flavour(int pdgId) const ;
102 
104  template<typename T>
107  const std::vector<T> & values,
108  const std::string & label) const ;
109 
111  if (tp.isNonnull() && tp->parentVertex().isNonnull() && !tp->parentVertex()->sourceTracks().empty()) {
112  return tp->parentVertex()->sourceTracks()[0];
113  } else {
114  return TrackingParticleRef();
115  }
116  }
117 
121  int convertAndPush(const TrackingParticle &tp,
123  const TrackingParticleRef &momRef,
125 };
126 
127 
129  muonsToken_(consumes<edm::View<reco::Muon> >(iConfig.getParameter<edm::InputTag>("muons"))),
130  hasMuonCut_(iConfig.existsAs<std::string>("muonPreselection")),
131  muonCut_(hasMuonCut_ ? iConfig.getParameter<std::string>("muonPreselection") : ""),
132  trackingParticlesToken_(consumes<TrackingParticleCollection>(iConfig.getParameter<edm::InputTag>("trackingParticles"))),
133  muAssocToken_(consumes<reco::MuonToTrackingParticleAssociator>(iConfig.getParameter<edm::InputTag>("associatorLabel"))),
134  decayRho_(iConfig.getParameter<double>("decayRho")),
135  decayAbsZ_(iConfig.getParameter<double>("decayAbsZ")),
136  linkToGenParticles_(iConfig.getParameter<bool>("linkToGenParticles")),
137  genParticles_(linkToGenParticles_ ? iConfig.getParameter<edm::InputTag>("genParticles") : edm::InputTag("NONE"))
138 
139 {
140  std::string trackType = iConfig.getParameter< std::string >("trackType");
141  if (trackType == "inner") trackType_ = reco::InnerTk;
142  else if (trackType == "outer") trackType_ = reco::OuterTk;
143  else if (trackType == "global") trackType_ = reco::GlobalTk;
144  else if (trackType == "segments") trackType_ = reco::Segments;
145  else if (trackType == "glb_or_trk") trackType_ = reco::GlbOrTrk;
146  else throw cms::Exception("Configuration") << "Track type '" << trackType << "' not supported.\n";
147  if (linkToGenParticles_) {
148  genParticlesToken_ = consumes<reco::GenParticleCollection>(genParticles_);
149  }
150 
151  produces<edm::ValueMap<int> >();
152  produces<edm::ValueMap<int> >("ext");
153  produces<edm::ValueMap<int> >("flav");
154  produces<edm::ValueMap<int> >("hitsPdgId");
155  produces<edm::ValueMap<int> >("G4processType"); // Geant process producing the particle
156  produces<edm::ValueMap<int> >("momPdgId");
157  produces<edm::ValueMap<int> >("momFlav");
158  produces<edm::ValueMap<int> >("momStatus");
159  produces<edm::ValueMap<int> >("gmomPdgId");
160  produces<edm::ValueMap<int> >("gmomFlav");
161  produces<edm::ValueMap<int> >("hmomFlav"); // heaviest mother flavour
162  produces<edm::ValueMap<int> >("tpId");
163  produces<edm::ValueMap<int> >("tpEv");
164  produces<edm::ValueMap<int> >("tpBx");
165  produces<edm::ValueMap<float> >("signp");
166  produces<edm::ValueMap<float> >("pt");
167  produces<edm::ValueMap<float> >("eta");
168  produces<edm::ValueMap<float> >("phi");
169  produces<edm::ValueMap<float> >("prodRho");
170  produces<edm::ValueMap<float> >("prodZ");
171  produces<edm::ValueMap<float> >("momRho");
172  produces<edm::ValueMap<float> >("momZ");
173  produces<edm::ValueMap<float> >("tpAssoQuality");
174  if (linkToGenParticles_) {
175  produces<reco::GenParticleCollection>("secondaries");
176  produces<edm::Association<reco::GenParticleCollection> >("toPrimaries");
177  produces<edm::Association<reco::GenParticleCollection> >("toSecondaries");
178  }
179 }
180 
182 {
183 }
184 
185 void
187 {
189  iEvent.getByToken(muonsToken_, muons);
190 
192  iEvent.getByToken(trackingParticlesToken_, trackingParticles);
193 
195  if (linkToGenParticles_) {
196  iEvent.getByToken(genParticlesToken_, genParticles);
197  }
198 
200  iEvent.getByToken(muAssocToken_, associatorBase);
201  const reco::MuonToTrackingParticleAssociator * assoByHits = associatorBase.product();
202 
203  reco::MuonToSimCollection recSimColl;
204  reco::SimToMuonCollection simRecColl;
205  edm::LogVerbatim("MuonMCClassifier") <<"\n ***************************************************************** ";
206  edm::LogVerbatim("MuonMCClassifier") << " RECO MUON association, type: "<< trackType_;
207  edm::LogVerbatim("MuonMCClassifier") << " ***************************************************************** \n";
208 
210  if (!hasMuonCut_) {
211  // all muons
212  for (size_t i = 0, n = muons->size(); i < n; ++i) {
213  edm::RefToBase<reco::Muon> rmu = muons->refAt(i);
214  selMuons.push_back(rmu);
215  }
216  } else {
217  // filter, fill refvectors, associate
218  // I pass through pat::Muon so that I can access muon id selectors
219  for (size_t i = 0, n = muons->size(); i < n; ++i) {
220  edm::RefToBase<reco::Muon> rmu = muons->refAt(i);
221  if (muonCut_(pat::Muon(rmu))) selMuons.push_back(rmu);
222  }
223  }
224 
226  for (size_t i = 0, n = trackingParticles->size(); i < n; ++i) {
227  allTPs.push_back(TrackingParticleRef(trackingParticles,i));
228  }
229 
230  assoByHits->associateMuons(recSimColl, simRecColl, selMuons, trackType_, allTPs);
231 
232  // for global muons without hits on muon detectors, look at the linked standalone muon
233  reco::MuonToSimCollection UpdSTA_recSimColl;
234  reco::SimToMuonCollection UpdSTA_simRecColl;
235  if (trackType_ == reco::GlobalTk) {
236  edm::LogVerbatim("MuonMCClassifier") <<"\n ***************************************************************** ";
237  edm::LogVerbatim("MuonMCClassifier") << " STANDALONE (UpdAtVtx) MUON association ";
238  edm::LogVerbatim("MuonMCClassifier") << " ***************************************************************** \n";
239  assoByHits->associateMuons(UpdSTA_recSimColl, UpdSTA_simRecColl, selMuons, reco::OuterTk,
240  allTPs);
241  }
242 
243  typedef reco::MuonToSimCollection::const_iterator r2s_it;
244  typedef reco::SimToMuonCollection::const_iterator s2r_it;
245 
246  size_t nmu = muons->size();
247  edm::LogVerbatim("MuonMCClassifier") <<"\n There are "<<nmu<<" reco::Muons.";
248 
249  std::vector<int> classif(nmu, 0), ext(nmu, 0);
250  std::vector<int> hitsPdgId(nmu, 0), G4processType(nmu, 0), momPdgId(nmu, 0), gmomPdgId(nmu, 0), momStatus(nmu, 0);
251  std::vector<int> flav(nmu, 0), momFlav(nmu, 0), gmomFlav(nmu, 0), hmomFlav(nmu, 0);
252  std::vector<int> tpId(nmu, -1), tpBx(nmu, 999), tpEv(nmu, 999);
253  std::vector<float> signp(nmu, 0.0), pt(nmu, 0.0), eta(nmu, -99.), phi(nmu, -99.);
254  std::vector<float> prodRho(nmu, 0.0), prodZ(nmu, 0.0), momRho(nmu, 0.0), momZ(nmu, 0.0);
255  std::vector<float> tpAssoQuality(nmu, -1);
256 
257  std::unique_ptr<reco::GenParticleCollection> secondaries; // output collection of secondary muons
258  std::map<TrackingParticleRef, int> tpToSecondaries; // map from tp to (index+1) in output collection
259  std::vector<int> muToPrimary(nmu, -1), muToSecondary(nmu, -1); // map from input into (index) in output, -1 for null
260  if (linkToGenParticles_) secondaries.reset(new reco::GenParticleCollection());
261 
262  // loop on reco muons
263  for(size_t i = 0; i < nmu; ++i) {
264  edm::RefToBase<reco::Muon> mu = muons->refAt(i);
265  if (hasMuonCut_ && (std::find(selMuons.begin(), selMuons.end(), mu) == selMuons.end()) ) {
266  LogTrace("MuonMCClassifier") <<"\n reco::Muon # "<<i<<"didn't pass the selection. classified as -99 and skipped";
267  classif[i] = -99; continue;
268  }
269  else edm::LogVerbatim("MuonMCClassifier") <<"\n reco::Muon # "<<i;
270 
272  edm::RefToBase<reco::Muon> muMatchBack;
273  r2s_it match = recSimColl.find(mu);
274  s2r_it matchback;
275  if (match != recSimColl.end()) {
276  // match->second is vector, front is first element, first is the ref (second would be the quality)
277  tp = match->second.front().first;
278  tpId[i] = tp.isNonnull() ? tp.key() : -1; // we check, even if null refs should not appear here at all
279  tpAssoQuality[i] = match->second.front().second;
280  s2r_it matchback = simRecColl.find(tp);
281  if (matchback != simRecColl.end()) {
282  muMatchBack = matchback->second.front().first;
283  } else {
284  edm::LogWarning("MuonMCClassifier") << "\n***WARNING: This I do NOT understand: why no match back? *** \n";
285  }
286  } else if ((trackType_ == reco::GlobalTk) &&
287  mu->isGlobalMuon()) {
288  // perform a second attempt, matching with the standalone muon
289  r2s_it matchSta = UpdSTA_recSimColl.find(mu);
290  if (matchSta != UpdSTA_recSimColl.end()) {
291  tp = matchSta->second.front().first;
292  tpId[i] = tp.isNonnull() ? tp.key() : -1; // we check, even if null refs should not appear here at all
293  tpAssoQuality[i] = matchSta->second.front().second;
294  s2r_it matchback = UpdSTA_simRecColl.find(tp);
295  if (matchback != UpdSTA_simRecColl.end()) {
296  muMatchBack = matchback->second.front().first;
297  } else {
298  edm::LogWarning("MuonMCClassifier") << "\n***WARNING: This I do NOT understand: why no match back in UpdSTA? *** \n";
299  }
300  }
301  } else {
302  edm::LogVerbatim("MuonMCClassifier") <<"\t No matching TrackingParticle is found ";
303  }
304 
305  if (tp.isNonnull()) {
306  bool isGhost = muMatchBack != mu;
307  if (isGhost) edm::LogVerbatim("MuonMCClassifier") <<"\t *** This seems a Duplicate muon ! classif[i] will be < 0 ***";
308 
309  // identify signal and pileup TP
310  tpBx[i] = tp->eventId().bunchCrossing();
311  tpEv[i] = tp->eventId().event();
312 
313  hitsPdgId[i] = tp->pdgId();
314  prodRho[i] = tp->vertex().Rho();
315  prodZ[i] = tp->vertex().Z();
316 
317  // added info on GEANT process producing the TrackingParticle
318  const std::vector<SimVertex> & G4Vs = tp->parentVertex()->g4Vertices();
319  G4processType[i] = G4Vs[0].processType();
320 
321  signp[i] = tp->charge() * tp->p();
322  pt[i] = tp->pt();
323  eta[i] = tp->eta();
324  phi[i] = tp->phi();
325 
326  // Try to extract mother and grand mother of this muon.
327  // Unfortunately, SIM and GEN histories require diffent code :-(
328  if (!tp->genParticles().empty()) { // Muon is in GEN
329  reco::GenParticleRef genp = tp->genParticles()[0];
330  reco::GenParticleRef genMom = genp->numberOfMothers() > 0 ? genp->motherRef() : reco::GenParticleRef();
331  reco::GenParticleRef mMom = genMom;
332 
333  if (genMom.isNonnull()) {
334  if (genMom->pdgId() != tp->pdgId()) {
335  momPdgId[i] = genMom->pdgId();
336  momStatus[i] = genMom->status();
337  momRho[i] = genMom->vertex().Rho();
338  momZ[i] = genMom->vz();
339  }
340  else {
341  // if mother has the same identity look backwards for the real mother (it may happen in radiative decays)
342  int jm = 0;
343  while (mMom->pdgId() == tp->pdgId()) {
344  jm++;
345 
346  if (mMom->numberOfMothers() > 0) {
347  mMom = mMom->motherRef();
348  }
349  LogTrace("MuonMCClassifier")
350  << "\t\t backtracking mother "<<jm<<", pdgId = "<<mMom->pdgId()<<", status= " <<mMom->status();
351  }
352  genMom = mMom; // redefine genMom
353  momPdgId[i] = genMom->pdgId();
354  momStatus[i] = genMom->status();
355  momRho[i] = genMom->vertex().Rho();
356  momZ[i] = genMom->vz();
357  }
358  edm::LogVerbatim("MuonMCClassifier")
359  << "\t Particle pdgId = "<<hitsPdgId[i] << ", (Event,Bx) = "<< "(" <<tpEv[i]<<","<<tpBx[i]<<")"
360  <<"\n\t q*p = "<<signp[i]<<", pT = "<<pt[i]<<", eta = "<<eta[i]<<", phi = "<<phi[i]
361  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
362  << ", (GEANT4 process = "<< G4processType[i]<<")"
363  << "\n\t has GEN mother pdgId = " << momPdgId[i] << " (status = "<<momStatus[i] << ")";
364 
365  reco::GenParticleRef genGMom = genMom->numberOfMothers() > 0 ? genMom->motherRef() : reco::GenParticleRef();
366 
367  if (genGMom.isNonnull()) {
368  gmomPdgId[i] = genGMom->pdgId();
369  edm::LogVerbatim("MuonMCClassifier") << "\t\t mother prod. vertex rho = " << momRho[i] << ", z = " << momZ[i]
370  << ", grand-mom pdgId = " << gmomPdgId[i];
371  }
372  // in this case, we might want to know the heaviest mom flavour
373  for (reco::GenParticleRef nMom = genMom;
374  nMom.isNonnull() && std::abs(nMom->pdgId()) >= 100; // stop when we're no longer looking at hadrons or mesons
375  nMom = nMom->numberOfMothers() > 0 ? nMom->motherRef() : reco::GenParticleRef()) {
376  int flav = flavour(nMom->pdgId());
377  if (hmomFlav[i] < flav) hmomFlav[i] = flav;
378  edm::LogVerbatim("MuonMCClassifier")
379  << "\t\t backtracking flavour: mom pdgId = "<<nMom->pdgId()
380  << ", flavour = " << flav << ", heaviest so far = " << hmomFlav[i];
381  }
382  } // if (genMom.isNonnull())
383 
384  else { // mother is null ??
385  edm::LogWarning("MuonMCClassifier")
386  << "\t GenParticle with pdgId = "<<hitsPdgId[i] << ", (Event,Bx) = "<< "(" <<tpEv[i]<<","<<tpBx[i]<<")"
387  <<"\n\t q*p = "<<signp[i]<<", pT = "<<pt[i]<<", eta = "<<eta[i]<<", phi = "<<phi[i]
388  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
389  << ", (GEANT4 process = "<< G4processType[i]<<")"
390  <<"\n\t has NO mother!";
391  }
392 
393  } else { // Muon is in SIM Only
394  TrackingParticleRef simMom = getTpMother(tp);
395  if (simMom.isNonnull()) {
396  momPdgId[i] = simMom->pdgId();
397  momRho[i] = simMom->vertex().Rho();
398  momZ[i] = simMom->vertex().Z();
399  edm::LogVerbatim("MuonMCClassifier")
400  << "\t Particle pdgId = "<<hitsPdgId[i] << ", (Event,Bx) = "<< "(" <<tpEv[i]<<","<<tpBx[i]<<")"
401  <<"\n\t q*p = "<<signp[i]<<", pT = "<<pt[i]<<", eta = "<<eta[i]<<", phi = "<<phi[i]
402  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
403  << ", (GEANT4 process = "<< G4processType[i]<<")"
404  <<"\n\t has SIM mother pdgId = " << momPdgId[i]
405  << " produced at rho = " << simMom->vertex().Rho() << ", z = " << simMom->vertex().Z();
406 
407  if (!simMom->genParticles().empty()) {
408  momStatus[i] = simMom->genParticles()[0]->status();
409  reco::GenParticleRef genGMom = (simMom->genParticles()[0]->numberOfMothers() > 0 ? simMom->genParticles()[0]->motherRef() : reco::GenParticleRef());
410  if (genGMom.isNonnull()) gmomPdgId[i] = genGMom->pdgId();
411  edm::LogVerbatim("MuonMCClassifier")
412  << "\t\t SIM mother is in GEN (status " << momStatus[i] << "), grand-mom id = " << gmomPdgId[i];
413  }
414  else {
415  momStatus[i] = -1;
416  TrackingParticleRef simGMom = getTpMother(simMom);
417  if (simGMom.isNonnull()) gmomPdgId[i] = simGMom->pdgId();
418  edm::LogVerbatim("MuonMCClassifier") << "\t\t SIM mother is in SIM only, grand-mom id = " << gmomPdgId[i];
419  }
420  } else {
421  edm::LogVerbatim("MuonMCClassifier")
422  << "\t Particle pdgId = "<<hitsPdgId[i] << ", (Event,Bx) = "<< "(" <<tpEv[i]<<","<<tpBx[i]<<")"
423  <<"\n\t q*p = "<<signp[i]<<", pT = "<<pt[i]<<", eta = "<<eta[i]<<", phi = "<<phi[i]
424  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
425  << ", (GEANT4 process = "<< G4processType[i]<<")"
426  <<"\n\t has NO mother!";
427  }
428  }
429  momFlav[i] = flavour(momPdgId[i]);
430  gmomFlav[i] = flavour(gmomPdgId[i]);
431 
432  // Check first IF this is a muon at all
433  if (abs(tp->pdgId()) != 13) {
434  if (abs(tp->pdgId()) == 11) {
435  classif[i] = isGhost ? -11 : 11;
436  ext[i] = isGhost ? -11 : 11;
437  edm::LogVerbatim("MuonMCClassifier") <<"\t This is electron/positron. classif[i] = " << classif[i];
438  }
439  else {
440  classif[i] = isGhost ? -1 : 1;
441  ext[i] = isGhost ? -1 : 1;
442  edm::LogVerbatim("MuonMCClassifier") <<"\t This is not a muon. Sorry. classif[i] = " << classif[i];
443  }
444 
445  continue;
446  }
447 
448  // Is this SIM muon also a GEN muon, with a mother?
449  if (!tp->genParticles().empty() && (momPdgId[i] != 0)) {
450  if (abs(momPdgId[i]) < 100 && (abs(momPdgId[i]) != 15)) {
451  classif[i] = isGhost ? -4 : 4;
452  flav[i] = 13;
453  ext[i] = 10;
454  edm::LogVerbatim("MuonMCClassifier") <<"\t This seems PRIMARY MUON ! classif[i] = " << classif[i];
455  } else if (momFlav[i] == 4 || momFlav[i] == 5 || momFlav[i] == 15) {
456  classif[i] = isGhost ? -3 : 3;
457  flav[i] = momFlav[i];
458  if (momFlav[i] == 15) ext[i] = 9; // tau->mu
459  else if (momFlav[i] == 5) ext[i] = 8; // b->mu
460  else if (hmomFlav[i] == 5) ext[i] = 7; // b->c->mu or b->tau->mu
461  else ext[i] = 6; // c->mu
462  edm::LogVerbatim("MuonMCClassifier") <<"\t This seems HEAVY FLAVOUR ! classif[i] = " << classif[i];
463  } else {
464  classif[i] = isGhost ? -2 : 2;
465  flav[i] = momFlav[i];
466  edm::LogVerbatim("MuonMCClassifier") <<"\t This seems LIGHT FLAVOUR ! classif[i] = " << classif[i];
467  }
468  } else {
469  classif[i] = isGhost ? -2 : 2;
470  flav[i] = momFlav[i];
471  edm::LogVerbatim("MuonMCClassifier") <<"\t This seems LIGHT FLAVOUR ! classif[i] = " << classif[i];
472  }
473  // extended classification
474  if (momPdgId[i] == 0) ext[i] = 2; // if it has no mom, it's not a primary particle so it won't be in ppMuX
475  else if (abs(momPdgId[i]) < 100) ext[i] = (momFlav[i] == 15 ? 9 : 10); // primary mu, or tau->mu
476  else if (momFlav[i] == 5) ext[i] = 8; // b->mu
477  else if (momFlav[i] == 4) ext[i] = (hmomFlav[i] == 5 ? 7 : 6); // b->c->mu and c->mu
478  else if (momStatus[i] != -1) { // primary light particle
479  int id = std::abs(momPdgId[i]);
480  if (id != /*pi+*/211 && id != /*K+*/321 && id != 130 /*K0L*/) ext[i] = 5; // other light particle, possibly short-lived
481  else if (prodRho[i] < decayRho_ && std::abs(prodZ[i]) < decayAbsZ_) ext[i] = 4; // decay a la ppMuX (primary pi/K within a cylinder)
482  else ext[i] = 3; // late decay that wouldn't be in ppMuX
483  } else ext[i] = 2; // decay of non-primary particle, would not be in ppMuX
484  if (isGhost) ext[i] = -ext[i];
485 
486  if (linkToGenParticles_ && std::abs(ext[i]) >= 2) {
487  // Link to the genParticle if possible, but not decays in flight (in ppMuX they're in GEN block, but they have wrong parameters)
488  if (!tp->genParticles().empty() && std::abs(ext[i]) >= 5) {
489  if (genParticles.id() != tp->genParticles().id()) {
490  throw cms::Exception("Configuration") << "Product ID mismatch between the genParticle collection (" << genParticles_ << ", id " << genParticles.id() << ") and the references in the TrackingParticles (id " << tp->genParticles().id() << ")\n";
491  }
492  muToPrimary[i] = tp->genParticles()[0].key();
493  } else {
494  // Don't put the same trackingParticle twice!
495  int &indexPlus1 = tpToSecondaries[tp]; // will create a 0 if the tp is not in the list already
496  if (indexPlus1 == 0) indexPlus1 = convertAndPush(*tp, *secondaries, getTpMother(tp), genParticles) + 1;
497  muToSecondary[i] = indexPlus1 - 1;
498  }
499  }
500  edm::LogVerbatim("MuonMCClassifier") <<"\t Extended classification code = " << ext[i];
501  } // if (tp.isNonnull())
502  } // end loop on reco muons
503 
504  writeValueMap(iEvent, muons, classif, "");
505  writeValueMap(iEvent, muons, ext, "ext");
506  writeValueMap(iEvent, muons, flav, "flav");
507  writeValueMap(iEvent, muons, tpId, "tpId");
508  writeValueMap(iEvent, muons, tpBx, "tpBx");
509  writeValueMap(iEvent, muons, tpEv, "tpEv");
510  writeValueMap(iEvent, muons, hitsPdgId, "hitsPdgId");
511  writeValueMap(iEvent, muons, G4processType, "G4processType");
512  writeValueMap(iEvent, muons, momPdgId, "momPdgId");
513  writeValueMap(iEvent, muons, momStatus, "momStatus");
514  writeValueMap(iEvent, muons, momFlav, "momFlav");
515  writeValueMap(iEvent, muons, gmomPdgId, "gmomPdgId");
516  writeValueMap(iEvent, muons, gmomFlav, "gmomFlav");
517  writeValueMap(iEvent, muons, hmomFlav, "hmomFlav");
518  writeValueMap(iEvent, muons, signp, "signp");
519  writeValueMap(iEvent, muons, pt, "pt");
520  writeValueMap(iEvent, muons, eta, "eta");
521  writeValueMap(iEvent, muons, phi, "phi");
522  writeValueMap(iEvent, muons, prodRho, "prodRho");
523  writeValueMap(iEvent, muons, prodZ, "prodZ");
524  writeValueMap(iEvent, muons, momRho, "momRho");
525  writeValueMap(iEvent, muons, momZ, "momZ");
526  writeValueMap(iEvent, muons, tpAssoQuality, "tpAssoQuality");
527 
528  if (linkToGenParticles_) {
529  edm::OrphanHandle<reco::GenParticleCollection> secHandle = iEvent.put(std::move(secondaries), "secondaries");
530  edm::RefProd<reco::GenParticleCollection> priRP(genParticles);
532  std::unique_ptr<edm::Association<reco::GenParticleCollection> > outPri(new edm::Association<reco::GenParticleCollection>(priRP));
533  std::unique_ptr<edm::Association<reco::GenParticleCollection> > outSec(new edm::Association<reco::GenParticleCollection>(secRP));
534  edm::Association<reco::GenParticleCollection>::Filler fillPri(*outPri), fillSec(*outSec);
535  fillPri.insert(muons, muToPrimary.begin(), muToPrimary.end());
536  fillSec.insert(muons, muToSecondary.begin(), muToSecondary.end());
537  fillPri.fill(); fillSec.fill();
538  iEvent.put(std::move(outPri), "toPrimaries");
539  iEvent.put(std::move(outSec), "toSecondaries");
540  }
541 
542 }
543 
544 template<typename T>
545 void
548  const std::vector<T> & values,
549  const std::string & label) const
550 {
551  using namespace edm;
552  using namespace std;
553  unique_ptr<ValueMap<T> > valMap(new ValueMap<T>());
554  typename edm::ValueMap<T>::Filler filler(*valMap);
555  filler.insert(handle, values.begin(), values.end());
556  filler.fill();
557  iEvent.put(std::move(valMap), label);
558 }
559 
560 int
562  int flav = std::abs(pdgId);
563  // for quarks, leptons and bosons except gluons, take their pdgId
564  // muons and taus have themselves as flavour
565  if (flav <= 37 && flav != 21) return flav;
566  // look for barions
567  int bflav = ((flav / 1000) % 10);
568  if (bflav != 0) return bflav;
569  // look for mesons
570  int mflav = ((flav / 100) % 10);
571  if (mflav != 0) return mflav;
572  return 0;
573 }
574 
575 // push secondary in collection.
576 // if it has a primary mother link to it.
579  const TrackingParticleRef & simMom,
581  out.push_back(reco::GenParticle(tp.charge(), tp.p4(), tp.vertex(), tp.pdgId(), tp.status(), true));
582  if (simMom.isNonnull() && !simMom->genParticles().empty()) {
583  if (genParticles.id() != simMom->genParticles().id()) {
584  throw cms::Exception("Configuration") << "Product ID mismatch between the genParticle collection (" << genParticles_ << ", id " << genParticles.id() << ") and the references in the TrackingParticles (id " << simMom->genParticles().id() << ")\n";
585  }
586  out.back().addMother(simMom->genParticles()[0]);
587  }
588  return out.size()-1;
589 }
590 
591 //define this as a plug-in
edm::InputTag genParticles_
bool linkToGenParticles_
Create a link to the generator level particles.
const LorentzVector & p4() const
Four-momentum Lorentz vector. Note this is taken from the first SimTrack only.
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
std::map< edm::RefToBase< reco::Muon >, std::vector< std::pair< TrackingParticleRef, double > >, RefToBaseSort > MuonToSimCollection
Definition: MuonTrackType.h:37
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:251
std::vector< TrackingParticle > TrackingParticleCollection
ProductID id() const
Definition: HandleBase.cc:15
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
int pdgId() const
PDG ID.
edm::Ref< GenParticleCollection > GenParticleRef
persistent reference to a GenParticle
void insert(const H &h, I begin, I end)
Definition: ValueMap.h:53
const_iterator end() const
int convertAndPush(const TrackingParticle &tp, reco::GenParticleCollection &out, const TrackingParticleRef &momRef, const edm::Handle< reco::GenParticleCollection > &genParticles) const
key_type key() const
Accessor for product key.
Definition: Ref.h:263
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
int status() const
Status word.
ProductID id() const
Accessor for product ID.
Definition: Ref.h:257
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
reco::MuonTrackType trackType_
Track to use.
std::map< TrackingParticleRef, std::vector< std::pair< edm::RefToBase< reco::Muon >, double > > > SimToMuonCollection
Definition: MuonTrackType.h:38
~MuonMCClassifier() override
char const * label
float charge() const
Electric charge. Note this is taken from the first SimTrack only.
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
Definition: Muon.py:1
bool isGlobalMuon() const override
Definition: Muon.h:291
void associateMuons(MuonToSimCollection &recoToSim, SimToMuonCollection &simToReco, const edm::RefToBaseVector< reco::Muon > &muons, MuonTrackType type, const edm::RefVector< TrackingParticleCollection > &tpColl) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
TrackingParticleRef getTpMother(TrackingParticleRef tp)
const int mu
Definition: Constants.h:22
MuonMCClassifier(const edm::ParameterSet &)
edm::InputTag associatorLabel_
The Associations.
#define LogTrace(id)
edm::EDGetTokenT< reco::GenParticleCollection > genParticlesToken_
T const * product() const
Definition: Handle.h:74
void writeValueMap(edm::Event &iEvent, const edm::Handle< edm::View< reco::Muon > > &handle, const std::vector< T > &values, const std::string &label) const
Write a ValueMap<int> in the event.
edm::EDGetTokenT< reco::MuonToTrackingParticleAssociator > muAssocToken_
const_iterator begin() const
Point vertex() const
Parent vertex position.
double decayRho_
Cylinder to use to decide if a decay is early or late.
fixed size matrix
edm::EDGetTokenT< edm::View< reco::Muon > > muonsToken_
The RECO objects.
HLT enums.
void push_back(const RefToBase< T > &)
void push_back(value_type const &ref)
Add a Ref<C, T> to the RefVector.
Definition: RefVector.h:69
Monte Carlo truth information used for tracking validation.
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
MuonTrackType
Definition: MuonTrackType.h:28
Definition: memstream.h:15
int flavour(int pdgId) const
Returns the flavour given a pdg id code.
void produce(edm::Event &, const edm::EventSetup &) override
Analysis-level muon class.
Definition: Muon.h:51
edm::Ref< TrackingParticleCollection > TrackingParticleRef
def move(src, dest)
Definition: eostools.py:511
edm::EDGetTokenT< TrackingParticleCollection > trackingParticlesToken_
The TrackingParticle objects.
StringCutObjectSelector< pat::Muon > muonCut_