CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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);
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
virtual size_t numberOfMothers() const
number of mothers
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::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
virtual int status() const =0
status word
virtual double y() const final
rapidity
void addDaughter(const typename daughters::value_type &)
add a daughter via a reference
tuple d
Definition: ztail.py:151
void resetDaughters(const edm::ProductID &id)
set daughters product ID
virtual int status() const final
status word
virtual const Point & vertex() const
vertex position
virtual size_t numberOfMothers() const
number of mothers
bool isDirectHadronDecayProduct() const
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) ...
def move
Definition: eostools.py:510
virtual const LorentzVector & p4() const
four-momentum Lorentz vecto r
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
virtual const Point & vertex() const =0
vertex position
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
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 int pdgId() const =0
PDG identifier.
tuple idx
DEBUGGING if hasattr(process,&quot;trackMonIterativeTracking2012&quot;): print &quot;trackMonIterativeTracking2012 D...
virtual void setP4(const LorentzVector &p4) final
set 4-momentum
const reco::GenStatusFlags & statusFlags() const
virtual int pdgId() const final
PDG identifier.
virtual const reco::Candidate * mother(size_type) const
return mother at a given position (throws an exception)
virtual int charge() const
electric charge
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) ...
virtual double pt() const final
transverse momentum
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector