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  if (pk.pdgId() == 22 and pk.statusFlags().isDirectHadronDecayProduct()) {
137  // no mother
138  if (pk.numberOfMothers() == 0) return true;
139  // miniaod mother not compatible with the status flag
140  HepPDT::ParticleID motherid(pk.mother(0)->pdgId());
141  if (not (motherid.isHadron() and pk.mother(0)->status() == 2)) return true;
142  }
143  return false;
144 }
145 
147 DEFINE_FWK_MODULE(MergedGenParticleProducer);
const reco::Candidate * mother(size_type) const override
return mother at a given position (throws an exception)
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
int pdgId() const final
PDG identifier.
const Candidate * daughter(size_type) const override
return daughter at a given position, i = 0, ... numberOfDaughters() - 1 (read only mode) ...
size_t numberOfMothers() const override
number of mothers
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:2
double pt() const final
transverse momentum
double y() const final
rapidity
Definition: config.py:1
void setVertex(const Point &vertex) override
set vertex
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
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
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
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const LorentzVector & p4() const override
four-momentum Lorentz vecto r
void addMother(const typename mothers::value_type &)
add a daughter via a reference
int pdgId() const override
PDG identifier.
int charge() const override
electric charge
size_t numberOfDaughters() const override
number of daughters
const Point & vertex() const override
vertex position
const reco::GenStatusFlags & statusFlags() const
int status() const final
status word
virtual const Point & vertex() const =0
vertex position
void resetMothers(const edm::ProductID &id)
set mother product ID
size_t numberOfMothers() const override
number of mothers
void setP4(const LorentzVector &p4) final
set 4-momentum
def move(src, dest)
Definition: eostools.py:511
const Candidate * mother(size_type=0) const override
return mother at a given position, i = 0, ... numberOfMothers() - 1 (read only mode) ...
Definition: event.py:1