CMS 3D CMS Logo

MergedGenParticleProducer.cc
Go to the documentation of this file.
1 #include "MergedGenParticleProducer.hh"
2 
4 
8 
9 #include "HepPDT/ParticleID.hh"
10 
11 MergedGenParticleProducer::MergedGenParticleProducer(const edm::ParameterSet& config)
12 {
13  input_pruned_ = consumes<edm::View<reco::GenParticle>>(config.getParameter<edm::InputTag>("inputPruned"));
14  input_packed_ = consumes<edm::View<pat::PackedGenParticle>>(config.getParameter<edm::InputTag>("inputPacked"));
15 
16  produces<reco::GenParticleCollection>();
17 }
18 
19 void MergedGenParticleProducer::produce(edm::Event& event, const edm::EventSetup& setup)
20 {
21  // Need a ref to the product now for creating the mother/daughter refs
22  auto ref = event.getRefBeforePut<reco::GenParticleCollection>();
23 
24  // Get the input collections
26  event.getByToken(input_pruned_, pruned_handle);
27 
29  event.getByToken(input_packed_, packed_handle);
30 
31  // First determine which packed particles are also still in the pruned collection
32  // so that we can skip them later
33  std::map<pat::PackedGenParticle const*, reco::GenParticle const*> st1_dup_map;
34 
35  // Also map pointers in the original pruned collection to their index in the vector.
36  // This index will be the same in the merged collection.
37  std::map<reco::Candidate const*, std::size_t> pruned_idx_map;
38 
39  for (unsigned int i = 0; i < pruned_handle->size(); ++i) {
40  reco::GenParticle const& src = pruned_handle->at(i);
41  pruned_idx_map[&src] = i;
42  if (src.status() != 1) continue;
43 
44  // Convert the pruned GenParticle into a PackedGenParticle then do an exact
45  // floating point comparison of the pt, eta and phi
46  // This of course relies on the PackedGenParticle constructor being identical
47  // between the CMSSW version this sample was produced with and the one we're
48  // analysing with
50  unsigned found_matches = 0;
51  for (unsigned j = 0; j < packed_handle->size(); ++j) {
52  pat::PackedGenParticle const& pk = packed_handle->at(j);
53  if ( pks.pdgId() != pk.pdgId() or pks.p4() != pk.p4() ) continue;
54  ++found_matches;
55  st1_dup_map[&pk] = &src;
56  }
57  if (found_matches > 1) {
58  edm::LogWarning("MergedGenParticleProducer") << "Found multiple packed matches for: " << i << "\t" << src.pdgId() << "\t" << src.pt() << "\t" << src.y() << "\n";
59  }
60  else if (found_matches == 0 && std::abs(src.y()) < 6.0) {
61  edm::LogWarning("MergedGenParticleProducer") << "unmatched status 1: " << i << "\t" << src.pdgId() << "\t" << src.pt() << "\t" << src.y() << "\n";
62  }
63  }
64 
65  // Fix by Markus
66  // check for photons from pruned (light) hadrons
67  unsigned int nPhotonsFromPrunedHadron = 0;
68  for (unsigned int j = 0; j < packed_handle->size(); ++j) {
69  pat::PackedGenParticle const& pk = packed_handle->at(j);
70  if (isPhotonFromPrunedHadron(pk)) ++nPhotonsFromPrunedHadron;
71  }
72 
73  // At this point we know what the size of the merged GenParticle will be so we can create it
74  const unsigned int n = pruned_handle->size() + (packed_handle->size() - st1_dup_map.size()) + nPhotonsFromPrunedHadron;
75  auto cands = std::unique_ptr<reco::GenParticleCollection>(new reco::GenParticleCollection(n));
76 
77  // First copy in all the pruned candidates
78  for (unsigned i = 0; i < pruned_handle->size(); ++i) {
79  reco::GenParticle const& old_cand = pruned_handle->at(i);
80  reco::GenParticle & new_cand = cands->at(i);
81  new_cand = reco::GenParticle(pruned_handle->at(i));
82  // Update the mother and daughter refs to this new merged collection
83  new_cand.resetMothers(ref.id());
84  new_cand.resetDaughters(ref.id());
85  for (unsigned m = 0; m < old_cand.numberOfMothers(); ++m) {
86  new_cand.addMother(reco::GenParticleRef(ref, pruned_idx_map.at(old_cand.mother(m))));
87  }
88  for (unsigned d = 0; d < old_cand.numberOfDaughters(); ++d) {
89  new_cand.addDaughter(reco::GenParticleRef(ref, pruned_idx_map.at(old_cand.daughter(d))));
90  }
91  }
92 
93  // Now copy in the packed candidates that are not already in the pruned
94  for (unsigned i = 0, idx = pruned_handle->size(); i < packed_handle->size(); ++i) {
95  pat::PackedGenParticle const& pk = packed_handle->at(i);
96  if (st1_dup_map.count(&pk)) continue;
97  reco::GenParticle & new_cand = cands->at(idx);
98  new_cand = reco::GenParticle(pk.charge(), pk.p4(), pk.vertex(), pk.pdgId(), 1, true);
99 
100  // Insert dummy pi0 mothers for orphaned photons
101  if (isPhotonFromPrunedHadron(pk)) {
102  ++idx;
103  reco::GenParticle & dummy_mother = cands->at(idx);
104  dummy_mother = reco::GenParticle(0, pk.p4(), pk.vertex(), 111, 2, true);
105  for (unsigned m = 0; m < pk.numberOfMothers(); ++m) {
106  new_cand.addMother(reco::GenParticleRef(ref, idx));
107  // Since the packed candidates drop the vertex position we'll take this from the mother
108  if (m == 0) {
109  dummy_mother.setP4(pk.mother(m)->p4());
110  dummy_mother.setVertex(pk.mother(m)->vertex());
111  new_cand.setVertex(pk.mother(m)->vertex());
112  }
113  // Should then add the GenParticle as a daughter of its dummy mother
114  dummy_mother.addDaughter(reco::GenParticleRef(ref, idx-1));
115  }
116  }
117  // Connect to mother from pruned particles
118  reco::GenParticle & daughter = cands->at(idx);
119  for (unsigned m = 0; m < pk.numberOfMothers(); ++m) {
120  daughter.addMother(reco::GenParticleRef(ref, pruned_idx_map.at(pk.mother(m))));
121  // Since the packed candidates drop the vertex position we'll take this from the mother
122  if (m == 0) {
123  daughter.setVertex(pk.mother(m)->vertex());
124  }
125  // Should then add this GenParticle as a daughter of its mother
126  cands->at(pruned_idx_map.at(pk.mother(m))).addDaughter(reco::GenParticleRef(ref, idx));
127  }
128  ++idx;
129  }
130 
131  event.put(std::move(cands));
132 }
133 
134 bool MergedGenParticleProducer::isPhotonFromPrunedHadron(const pat::PackedGenParticle& pk) const
135 {
136  HepPDT::ParticleID motherid(pk.mother(0)->pdgId());
137  return
138  ( pk.pdgId() == 22 // We care about photons for lepton dressing here
139  and pk.statusFlags().isDirectHadronDecayProduct() // Gen status flag seems correct
140  // Catch cases where miniaod mother is not compatible with the status flag
141  and not (motherid.isHadron() and pk.mother(0)->status() == 2)
142  );
143 }
144 
146 DEFINE_FWK_MODULE(MergedGenParticleProducer);
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
virtual double pt() const final
transverse momentum
virtual size_t numberOfMothers() const
number of mothers
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
virtual int status() const final
status word
Definition: config.py:1
void addDaughter(const typename daughters::value_type &)
add a daughter via a reference
void resetDaughters(const edm::ProductID &id)
set daughters product ID
virtual int status() const =0
status word
virtual const Point & vertex() const
vertex position
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
virtual size_t numberOfMothers() const
number of mothers
virtual int pdgId() const =0
PDG identifier.
bool isDirectHadronDecayProduct() const
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
virtual size_t numberOfDaughters() const
number of daughters
virtual const Candidate * daughter(size_type) const
return daughter at a given position, i = 0, ... numberOfDaughters() - 1 (read only mode) ...
virtual int pdgId() const final
PDG identifier.
virtual const LorentzVector & p4() const
four-momentum Lorentz vecto r
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
virtual void setVertex(const Point &vertex)
set vertex
void addMother(const typename mothers::value_type &)
add a daughter via a reference
virtual int pdgId() const
PDG identifier.
virtual double y() const final
rapidity
virtual void setP4(const LorentzVector &p4) final
set 4-momentum
const reco::GenStatusFlags & statusFlags() const
virtual const reco::Candidate * mother(size_type) const
return mother at a given position (throws an exception)
virtual int charge() const
electric charge
virtual const Point & vertex() const =0
vertex position
void resetMothers(const edm::ProductID &id)
set mother product ID
virtual const Candidate * mother(size_type=0) const
return mother at a given position, i = 0, ... numberOfMothers() - 1 (read only mode) ...
def move(src, dest)
Definition: eostools.py:510
Definition: event.py:1