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