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 // system include files
35 #include <memory>
36 #include <set>
37 
38 // user include files
41 
46 
48 
52 
57 
61 
63 
64 //
65 // class decleration
67 public:
68  explicit MuonMCClassifier(const edm::ParameterSet &);
69  ~MuonMCClassifier() override;
70 
71 private:
72  void produce(edm::Event &, const edm::EventSetup &) override;
75 
80 
83 
86 
90 
93 
98 
100  int flavour(int pdgId) const;
101 
103  template <typename T>
106  const std::vector<T> &values,
107  const std::string &label) const;
108 
110  if (tp.isNonnull() && tp->parentVertex().isNonnull() && !tp->parentVertex()->sourceTracks().empty()) {
111  return tp->parentVertex()->sourceTracks()[0];
112  } else {
113  return TrackingParticleRef();
114  }
115  }
116 
120  int convertAndPush(const TrackingParticle &tp,
122  const TrackingParticleRef &momRef,
124 };
125 
127  : muonsToken_(consumes<edm::View<reco::Muon> >(iConfig.getParameter<edm::InputTag>("muons"))),
128  hasMuonCut_(iConfig.existsAs<std::string>("muonPreselection")),
129  muonCut_(hasMuonCut_ ? iConfig.getParameter<std::string>("muonPreselection") : ""),
131  consumes<TrackingParticleCollection>(iConfig.getParameter<edm::InputTag>("trackingParticles"))),
133  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")
143  else if (trackType == "outer")
145  else if (trackType == "global")
147  else if (trackType == "segments")
149  else if (trackType == "glb_or_trk")
151  else
152  throw cms::Exception("Configuration") << "Track type '" << trackType << "' not supported.\n";
153  if (linkToGenParticles_) {
154  genParticlesToken_ = consumes<reco::GenParticleCollection>(genParticles_);
155  }
156 
157  produces<edm::ValueMap<int> >();
158  produces<edm::ValueMap<int> >("ext");
159  produces<edm::ValueMap<int> >("flav");
160  produces<edm::ValueMap<int> >("hitsPdgId");
161  produces<edm::ValueMap<int> >("G4processType"); // Geant process producing the particle
162  produces<edm::ValueMap<int> >("momPdgId");
163  produces<edm::ValueMap<int> >("momFlav");
164  produces<edm::ValueMap<int> >("momStatus");
165  produces<edm::ValueMap<int> >("gmomPdgId");
166  produces<edm::ValueMap<int> >("gmomFlav");
167  produces<edm::ValueMap<int> >("hmomFlav"); // heaviest mother flavour
168  produces<edm::ValueMap<int> >("tpId");
169  produces<edm::ValueMap<int> >("tpEv");
170  produces<edm::ValueMap<int> >("tpBx");
171  produces<edm::ValueMap<float> >("signp");
172  produces<edm::ValueMap<float> >("pt");
173  produces<edm::ValueMap<float> >("eta");
174  produces<edm::ValueMap<float> >("phi");
175  produces<edm::ValueMap<float> >("prodRho");
176  produces<edm::ValueMap<float> >("prodZ");
177  produces<edm::ValueMap<float> >("momRho");
178  produces<edm::ValueMap<float> >("momZ");
179  produces<edm::ValueMap<float> >("tpAssoQuality");
180  if (linkToGenParticles_) {
181  produces<reco::GenParticleCollection>("secondaries");
182  produces<edm::Association<reco::GenParticleCollection> >("toPrimaries");
183  produces<edm::Association<reco::GenParticleCollection> >("toSecondaries");
184  }
185 }
186 
188 
191  iEvent.getByToken(muonsToken_, muons);
192 
194  iEvent.getByToken(trackingParticlesToken_, trackingParticles);
195 
197  if (linkToGenParticles_) {
198  iEvent.getByToken(genParticlesToken_, genParticles);
199  }
200 
202  iEvent.getByToken(muAssocToken_, associatorBase);
203  const reco::MuonToTrackingParticleAssociator *assoByHits = associatorBase.product();
204 
205  reco::MuonToSimCollection recSimColl;
206  reco::SimToMuonCollection simRecColl;
207  edm::LogVerbatim("MuonMCClassifier") << "\n ***************************************************************** ";
208  edm::LogVerbatim("MuonMCClassifier") << " RECO MUON association, type: " << trackType_;
209  edm::LogVerbatim("MuonMCClassifier") << " ***************************************************************** \n";
210 
212  if (!hasMuonCut_) {
213  // all muons
214  for (size_t i = 0, n = muons->size(); i < n; ++i) {
215  edm::RefToBase<reco::Muon> rmu = muons->refAt(i);
216  selMuons.push_back(rmu);
217  }
218  } else {
219  // filter, fill refvectors, associate
220  // I pass through pat::Muon so that I can access muon id selectors
221  for (size_t i = 0, n = muons->size(); i < n; ++i) {
222  edm::RefToBase<reco::Muon> rmu = muons->refAt(i);
223  if (muonCut_(pat::Muon(rmu)))
224  selMuons.push_back(rmu);
225  }
226  }
227 
229  for (size_t i = 0, n = trackingParticles->size(); i < n; ++i) {
230  allTPs.push_back(TrackingParticleRef(trackingParticles, i));
231  }
232 
233  assoByHits->associateMuons(recSimColl, simRecColl, selMuons, trackType_, allTPs);
234 
235  // for global muons without hits on muon detectors, look at the linked standalone muon
236  reco::MuonToSimCollection UpdSTA_recSimColl;
237  reco::SimToMuonCollection UpdSTA_simRecColl;
238  if (trackType_ == reco::GlobalTk) {
239  edm::LogVerbatim("MuonMCClassifier") << "\n ***************************************************************** ";
240  edm::LogVerbatim("MuonMCClassifier") << " STANDALONE (UpdAtVtx) MUON association ";
241  edm::LogVerbatim("MuonMCClassifier") << " ***************************************************************** \n";
242  assoByHits->associateMuons(UpdSTA_recSimColl, UpdSTA_simRecColl, selMuons, reco::OuterTk, allTPs);
243  }
244 
245  typedef reco::MuonToSimCollection::const_iterator r2s_it;
246  typedef reco::SimToMuonCollection::const_iterator s2r_it;
247 
248  size_t nmu = muons->size();
249  edm::LogVerbatim("MuonMCClassifier") << "\n There are " << nmu << " reco::Muons.";
250 
251  std::vector<int> classif(nmu, 0), ext(nmu, 0);
252  std::vector<int> hitsPdgId(nmu, 0), G4processType(nmu, 0), momPdgId(nmu, 0), gmomPdgId(nmu, 0), momStatus(nmu, 0);
253  std::vector<int> flav(nmu, 0), momFlav(nmu, 0), gmomFlav(nmu, 0), hmomFlav(nmu, 0);
254  std::vector<int> tpId(nmu, -1), tpBx(nmu, 999), tpEv(nmu, 999);
255  std::vector<float> signp(nmu, 0.0), pt(nmu, 0.0), eta(nmu, -99.), phi(nmu, -99.);
256  std::vector<float> prodRho(nmu, 0.0), prodZ(nmu, 0.0), momRho(nmu, 0.0), momZ(nmu, 0.0);
257  std::vector<float> tpAssoQuality(nmu, -1);
258 
259  std::unique_ptr<reco::GenParticleCollection> secondaries; // output collection of secondary muons
260  std::map<TrackingParticleRef, int> tpToSecondaries; // map from tp to (index+1) in output collection
261  std::vector<int> muToPrimary(nmu, -1), muToSecondary(nmu, -1); // map from input into (index) in output, -1 for null
263  secondaries.reset(new reco::GenParticleCollection());
264 
265  // loop on reco muons
266  for (size_t i = 0; i < nmu; ++i) {
267  edm::RefToBase<reco::Muon> mu = muons->refAt(i);
268  if (hasMuonCut_ && (std::find(selMuons.begin(), selMuons.end(), mu) == selMuons.end())) {
269  LogTrace("MuonMCClassifier") << "\n reco::Muon # " << i
270  << "didn't pass the selection. classified as -99 and skipped";
271  classif[i] = -99;
272  continue;
273  } else
274  edm::LogVerbatim("MuonMCClassifier") << "\n reco::Muon # " << i;
275 
277  edm::RefToBase<reco::Muon> muMatchBack;
278  r2s_it match = recSimColl.find(mu);
279  s2r_it matchback;
280  if (match != recSimColl.end()) {
281  // match->second is vector, front is first element, first is the ref (second would be the quality)
282  tp = match->second.front().first;
283  tpId[i] = tp.isNonnull() ? tp.key() : -1; // we check, even if null refs should not appear here at all
284  tpAssoQuality[i] = match->second.front().second;
285  s2r_it matchback = simRecColl.find(tp);
286  if (matchback != simRecColl.end()) {
287  muMatchBack = matchback->second.front().first;
288  } else {
289  edm::LogWarning("MuonMCClassifier") << "\n***WARNING: This I do NOT understand: why no match back? *** \n";
290  }
291  } else if ((trackType_ == reco::GlobalTk) && mu->isGlobalMuon()) {
292  // perform a second attempt, matching with the standalone muon
293  r2s_it matchSta = UpdSTA_recSimColl.find(mu);
294  if (matchSta != UpdSTA_recSimColl.end()) {
295  tp = matchSta->second.front().first;
296  tpId[i] = tp.isNonnull() ? tp.key() : -1; // we check, even if null refs should not appear here at all
297  tpAssoQuality[i] = matchSta->second.front().second;
298  s2r_it matchback = UpdSTA_simRecColl.find(tp);
299  if (matchback != UpdSTA_simRecColl.end()) {
300  muMatchBack = matchback->second.front().first;
301  } else {
302  edm::LogWarning("MuonMCClassifier")
303  << "\n***WARNING: This I do NOT understand: why no match back in UpdSTA? *** \n";
304  }
305  }
306  } else {
307  edm::LogVerbatim("MuonMCClassifier") << "\t No matching TrackingParticle is found ";
308  }
309 
310  if (tp.isNonnull()) {
311  bool isGhost = muMatchBack != mu;
312  if (isGhost)
313  edm::LogVerbatim("MuonMCClassifier") << "\t *** This seems a Duplicate muon ! classif[i] will be < 0 ***";
314 
315  // identify signal and pileup TP
316  tpBx[i] = tp->eventId().bunchCrossing();
317  tpEv[i] = tp->eventId().event();
318 
319  hitsPdgId[i] = tp->pdgId();
320  prodRho[i] = tp->vertex().Rho();
321  prodZ[i] = tp->vertex().Z();
322 
323  // added info on GEANT process producing the TrackingParticle
324  const std::vector<SimVertex> &G4Vs = tp->parentVertex()->g4Vertices();
325  G4processType[i] = G4Vs[0].processType();
326 
327  signp[i] = tp->charge() * tp->p();
328  pt[i] = tp->pt();
329  eta[i] = tp->eta();
330  phi[i] = tp->phi();
331 
332  // Try to extract mother and grand mother of this muon.
333  // Unfortunately, SIM and GEN histories require diffent code :-(
334  if (!tp->genParticles().empty()) { // Muon is in GEN
335  reco::GenParticleRef genp = tp->genParticles()[0];
336  reco::GenParticleRef genMom = genp->numberOfMothers() > 0 ? genp->motherRef() : reco::GenParticleRef();
337  reco::GenParticleRef mMom = genMom;
338 
339  if (genMom.isNonnull()) {
340  if (genMom->pdgId() != tp->pdgId()) {
341  momPdgId[i] = genMom->pdgId();
342  momStatus[i] = genMom->status();
343  momRho[i] = genMom->vertex().Rho();
344  momZ[i] = genMom->vz();
345  } else {
346  // if mother has the same identity look backwards for the real mother (it may happen in radiative decays)
347  int jm = 0;
348  while (mMom->pdgId() == tp->pdgId()) {
349  jm++;
350 
351  if (mMom->numberOfMothers() > 0) {
352  mMom = mMom->motherRef();
353  }
354  LogTrace("MuonMCClassifier") << "\t\t backtracking mother " << jm << ", pdgId = " << mMom->pdgId()
355  << ", status= " << mMom->status();
356  }
357  genMom = mMom; // redefine genMom
358  momPdgId[i] = genMom->pdgId();
359  momStatus[i] = genMom->status();
360  momRho[i] = genMom->vertex().Rho();
361  momZ[i] = genMom->vz();
362  }
363  edm::LogVerbatim("MuonMCClassifier")
364  << "\t Particle pdgId = " << hitsPdgId[i] << ", (Event,Bx) = "
365  << "(" << tpEv[i] << "," << tpBx[i] << ")"
366  << "\n\t q*p = " << signp[i] << ", pT = " << pt[i] << ", eta = " << eta[i] << ", phi = " << phi[i]
367  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
368  << ", (GEANT4 process = " << G4processType[i] << ")"
369  << "\n\t has GEN mother pdgId = " << momPdgId[i] << " (status = " << momStatus[i] << ")";
370 
371  reco::GenParticleRef genGMom = genMom->numberOfMothers() > 0 ? genMom->motherRef() : reco::GenParticleRef();
372 
373  if (genGMom.isNonnull()) {
374  gmomPdgId[i] = genGMom->pdgId();
375  edm::LogVerbatim("MuonMCClassifier") << "\t\t mother prod. vertex rho = " << momRho[i]
376  << ", z = " << momZ[i] << ", grand-mom pdgId = " << gmomPdgId[i];
377  }
378  // in this case, we might want to know the heaviest mom flavour
379  for (reco::GenParticleRef nMom = genMom;
380  nMom.isNonnull() &&
381  std::abs(nMom->pdgId()) >= 100; // stop when we're no longer looking at hadrons or mesons
382  nMom = nMom->numberOfMothers() > 0 ? nMom->motherRef() : reco::GenParticleRef()) {
383  int flav = flavour(nMom->pdgId());
384  if (hmomFlav[i] < flav)
385  hmomFlav[i] = flav;
386  edm::LogVerbatim("MuonMCClassifier") << "\t\t backtracking flavour: mom pdgId = " << nMom->pdgId()
387  << ", flavour = " << flav << ", heaviest so far = " << hmomFlav[i];
388  }
389  } // if (genMom.isNonnull())
390 
391  else { // mother is null ??
392  edm::LogWarning("MuonMCClassifier")
393  << "\t GenParticle with pdgId = " << hitsPdgId[i] << ", (Event,Bx) = "
394  << "(" << tpEv[i] << "," << tpBx[i] << ")"
395  << "\n\t q*p = " << signp[i] << ", pT = " << pt[i] << ", eta = " << eta[i] << ", phi = " << phi[i]
396  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
397  << ", (GEANT4 process = " << G4processType[i] << ")"
398  << "\n\t has NO mother!";
399  }
400 
401  } else { // Muon is in SIM Only
402  TrackingParticleRef simMom = getTpMother(tp);
403  if (simMom.isNonnull()) {
404  momPdgId[i] = simMom->pdgId();
405  momRho[i] = simMom->vertex().Rho();
406  momZ[i] = simMom->vertex().Z();
407  edm::LogVerbatim("MuonMCClassifier")
408  << "\t Particle pdgId = " << hitsPdgId[i] << ", (Event,Bx) = "
409  << "(" << tpEv[i] << "," << tpBx[i] << ")"
410  << "\n\t q*p = " << signp[i] << ", pT = " << pt[i] << ", eta = " << eta[i] << ", phi = " << phi[i]
411  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
412  << ", (GEANT4 process = " << G4processType[i] << ")"
413  << "\n\t has SIM mother pdgId = " << momPdgId[i] << " produced at rho = " << simMom->vertex().Rho()
414  << ", z = " << simMom->vertex().Z();
415 
416  if (!simMom->genParticles().empty()) {
417  momStatus[i] = simMom->genParticles()[0]->status();
418  reco::GenParticleRef genGMom =
419  (simMom->genParticles()[0]->numberOfMothers() > 0 ? simMom->genParticles()[0]->motherRef()
421  if (genGMom.isNonnull())
422  gmomPdgId[i] = genGMom->pdgId();
423  edm::LogVerbatim("MuonMCClassifier")
424  << "\t\t SIM mother is in GEN (status " << momStatus[i] << "), grand-mom id = " << gmomPdgId[i];
425  } else {
426  momStatus[i] = -1;
427  TrackingParticleRef simGMom = getTpMother(simMom);
428  if (simGMom.isNonnull())
429  gmomPdgId[i] = simGMom->pdgId();
430  edm::LogVerbatim("MuonMCClassifier") << "\t\t SIM mother is in SIM only, grand-mom id = " << gmomPdgId[i];
431  }
432  } else {
433  edm::LogVerbatim("MuonMCClassifier")
434  << "\t Particle pdgId = " << hitsPdgId[i] << ", (Event,Bx) = "
435  << "(" << tpEv[i] << "," << tpBx[i] << ")"
436  << "\n\t q*p = " << signp[i] << ", pT = " << pt[i] << ", eta = " << eta[i] << ", phi = " << phi[i]
437  << "\n\t produced at vertex rho = " << prodRho[i] << ", z = " << prodZ[i]
438  << ", (GEANT4 process = " << G4processType[i] << ")"
439  << "\n\t has NO mother!";
440  }
441  }
442  momFlav[i] = flavour(momPdgId[i]);
443  gmomFlav[i] = flavour(gmomPdgId[i]);
444 
445  // Check first IF this is a muon at all
446  if (abs(tp->pdgId()) != 13) {
447  if (abs(tp->pdgId()) == 11) {
448  classif[i] = isGhost ? -11 : 11;
449  ext[i] = isGhost ? -11 : 11;
450  edm::LogVerbatim("MuonMCClassifier") << "\t This is electron/positron. classif[i] = " << classif[i];
451  } else {
452  classif[i] = isGhost ? -1 : 1;
453  ext[i] = isGhost ? -1 : 1;
454  edm::LogVerbatim("MuonMCClassifier") << "\t This is not a muon. Sorry. classif[i] = " << classif[i];
455  }
456 
457  continue;
458  }
459 
460  // Is this SIM muon also a GEN muon, with a mother?
461  if (!tp->genParticles().empty() && (momPdgId[i] != 0)) {
462  if (abs(momPdgId[i]) < 100 && (abs(momPdgId[i]) != 15)) {
463  classif[i] = isGhost ? -4 : 4;
464  flav[i] = 13;
465  ext[i] = 10;
466  edm::LogVerbatim("MuonMCClassifier") << "\t This seems PRIMARY MUON ! classif[i] = " << classif[i];
467  } else if (momFlav[i] == 4 || momFlav[i] == 5 || momFlav[i] == 15) {
468  classif[i] = isGhost ? -3 : 3;
469  flav[i] = momFlav[i];
470  if (momFlav[i] == 15)
471  ext[i] = 9; // tau->mu
472  else if (momFlav[i] == 5)
473  ext[i] = 8; // b->mu
474  else if (hmomFlav[i] == 5)
475  ext[i] = 7; // b->c->mu or b->tau->mu
476  else
477  ext[i] = 6; // c->mu
478  edm::LogVerbatim("MuonMCClassifier") << "\t This seems HEAVY FLAVOUR ! classif[i] = " << classif[i];
479  } else {
480  classif[i] = isGhost ? -2 : 2;
481  flav[i] = momFlav[i];
482  edm::LogVerbatim("MuonMCClassifier") << "\t This seems LIGHT FLAVOUR ! classif[i] = " << classif[i];
483  }
484  } else {
485  classif[i] = isGhost ? -2 : 2;
486  flav[i] = momFlav[i];
487  edm::LogVerbatim("MuonMCClassifier") << "\t This seems LIGHT FLAVOUR ! classif[i] = " << classif[i];
488  }
489  // extended classification
490  if (momPdgId[i] == 0)
491  ext[i] = 2; // if it has no mom, it's not a primary particle so it won't be in ppMuX
492  else if (abs(momPdgId[i]) < 100)
493  ext[i] = (momFlav[i] == 15 ? 9 : 10); // primary mu, or tau->mu
494  else if (momFlav[i] == 5)
495  ext[i] = 8; // b->mu
496  else if (momFlav[i] == 4)
497  ext[i] = (hmomFlav[i] == 5 ? 7 : 6); // b->c->mu and c->mu
498  else if (momStatus[i] != -1) { // primary light particle
499  int id = std::abs(momPdgId[i]);
500  if (id != /*pi+*/ 211 && id != /*K+*/ 321 && id != 130 /*K0L*/)
501  ext[i] = 5; // other light particle, possibly short-lived
502  else if (prodRho[i] < decayRho_ && std::abs(prodZ[i]) < decayAbsZ_)
503  ext[i] = 4; // decay a la ppMuX (primary pi/K within a cylinder)
504  else
505  ext[i] = 3; // late decay that wouldn't be in ppMuX
506  } else
507  ext[i] = 2; // decay of non-primary particle, would not be in ppMuX
508  if (isGhost)
509  ext[i] = -ext[i];
510 
511  if (linkToGenParticles_ && std::abs(ext[i]) >= 2) {
512  // Link to the genParticle if possible, but not decays in flight (in ppMuX they're in GEN block, but they have wrong parameters)
513  if (!tp->genParticles().empty() && std::abs(ext[i]) >= 5) {
514  if (genParticles.id() != tp->genParticles().id()) {
515  throw cms::Exception("Configuration")
516  << "Product ID mismatch between the genParticle collection (" << genParticles_ << ", id "
517  << genParticles.id() << ") and the references in the TrackingParticles (id " << tp->genParticles().id()
518  << ")\n";
519  }
520  muToPrimary[i] = tp->genParticles()[0].key();
521  } else {
522  // Don't put the same trackingParticle twice!
523  int &indexPlus1 = tpToSecondaries[tp]; // will create a 0 if the tp is not in the list already
524  if (indexPlus1 == 0)
525  indexPlus1 = convertAndPush(*tp, *secondaries, getTpMother(tp), genParticles) + 1;
526  muToSecondary[i] = indexPlus1 - 1;
527  }
528  }
529  edm::LogVerbatim("MuonMCClassifier") << "\t Extended classification code = " << ext[i];
530  } // if (tp.isNonnull())
531  } // end loop on reco muons
532 
533  writeValueMap(iEvent, muons, classif, "");
534  writeValueMap(iEvent, muons, ext, "ext");
535  writeValueMap(iEvent, muons, flav, "flav");
536  writeValueMap(iEvent, muons, tpId, "tpId");
537  writeValueMap(iEvent, muons, tpBx, "tpBx");
538  writeValueMap(iEvent, muons, tpEv, "tpEv");
539  writeValueMap(iEvent, muons, hitsPdgId, "hitsPdgId");
540  writeValueMap(iEvent, muons, G4processType, "G4processType");
541  writeValueMap(iEvent, muons, momPdgId, "momPdgId");
542  writeValueMap(iEvent, muons, momStatus, "momStatus");
543  writeValueMap(iEvent, muons, momFlav, "momFlav");
544  writeValueMap(iEvent, muons, gmomPdgId, "gmomPdgId");
545  writeValueMap(iEvent, muons, gmomFlav, "gmomFlav");
546  writeValueMap(iEvent, muons, hmomFlav, "hmomFlav");
547  writeValueMap(iEvent, muons, signp, "signp");
548  writeValueMap(iEvent, muons, pt, "pt");
549  writeValueMap(iEvent, muons, eta, "eta");
550  writeValueMap(iEvent, muons, phi, "phi");
551  writeValueMap(iEvent, muons, prodRho, "prodRho");
552  writeValueMap(iEvent, muons, prodZ, "prodZ");
553  writeValueMap(iEvent, muons, momRho, "momRho");
554  writeValueMap(iEvent, muons, momZ, "momZ");
555  writeValueMap(iEvent, muons, tpAssoQuality, "tpAssoQuality");
556 
557  if (linkToGenParticles_) {
558  edm::OrphanHandle<reco::GenParticleCollection> secHandle = iEvent.put(std::move(secondaries), "secondaries");
559  edm::RefProd<reco::GenParticleCollection> priRP(genParticles);
561  std::unique_ptr<edm::Association<reco::GenParticleCollection> > outPri(
563  std::unique_ptr<edm::Association<reco::GenParticleCollection> > outSec(
565  edm::Association<reco::GenParticleCollection>::Filler fillPri(*outPri), fillSec(*outSec);
566  fillPri.insert(muons, muToPrimary.begin(), muToPrimary.end());
567  fillSec.insert(muons, muToSecondary.begin(), muToSecondary.end());
568  fillPri.fill();
569  fillSec.fill();
570  iEvent.put(std::move(outPri), "toPrimaries");
571  iEvent.put(std::move(outSec), "toSecondaries");
572  }
573 }
574 
575 template <typename T>
578  const std::vector<T> &values,
579  const std::string &label) const {
580  using namespace edm;
581  using namespace std;
582  unique_ptr<ValueMap<T> > valMap(new ValueMap<T>());
583  typename edm::ValueMap<T>::Filler filler(*valMap);
584  filler.insert(handle, values.begin(), values.end());
585  filler.fill();
586  iEvent.put(std::move(valMap), label);
587 }
588 
590  int flav = std::abs(pdgId);
591  // for quarks, leptons and bosons except gluons, take their pdgId
592  // muons and taus have themselves as flavour
593  if (flav <= 37 && flav != 21)
594  return flav;
595  // look for barions
596  int bflav = ((flav / 1000) % 10);
597  if (bflav != 0)
598  return bflav;
599  // look for mesons
600  int mflav = ((flav / 100) % 10);
601  if (mflav != 0)
602  return mflav;
603  return 0;
604 }
605 
606 // push secondary in collection.
607 // if it has a primary mother link to it.
610  const TrackingParticleRef &simMom,
612  out.push_back(reco::GenParticle(tp.charge(), tp.p4(), tp.vertex(), tp.pdgId(), tp.status(), true));
613  if (simMom.isNonnull() && !simMom->genParticles().empty()) {
614  if (genParticles.id() != simMom->genParticles().id()) {
615  throw cms::Exception("Configuration")
616  << "Product ID mismatch between the genParticle collection (" << genParticles_ << ", id " << genParticles.id()
617  << ") and the references in the TrackingParticles (id " << simMom->genParticles().id() << ")\n";
618  }
619  out.back().addMother(simMom->genParticles()[0]);
620  }
621  return out.size() - 1;
622 }
623 
624 //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:131
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
genp
produce generated paricles in acceptance #
std::vector< TrackingParticle > TrackingParticleCollection
ProductID id() const
Definition: HandleBase.cc:13
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:525
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:250
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
int status() const
Status word.
ProductID id() const
Accessor for product ID.
Definition: Ref.h:244
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:298
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)
MuonMCClassifier(const edm::ParameterSet &)
edm::InputTag associatorLabel_
The Associations.
#define LogTrace(id)
edm::EDGetTokenT< reco::GenParticleCollection > genParticlesToken_
T const * product() const
Definition: Handle.h:69
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:67
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_