CMS 3D CMS Logo

PATGenCandsFromSimTracksProducer.cc
Go to the documentation of this file.
1 
17 
22 
25 
26 #include <ext/algorithm>
27 
28 namespace pat {
30  public:
33 
34  private:
35  virtual void produce(edm::Event&, const edm::EventSetup&) override;
36 
41  std::set<int> pdgIds_; // these are the ones we really use
42  std::vector<PdtEntry> pdts_; // these are needed before we get the EventSetup
43  std::set<int> motherPdgIds_; // these are the ones we really use
44  std::vector<PdtEntry> motherPdts_; // these are needed before we get the EventSetup
45 
47  const StrFilter filter_;
48 
53 
57 
59  struct GlobalContext {
61  const edm::SimVertexContainer &simvtxs1,
63  const edm::Handle<std::vector<int> > &genBarcodes1,
64  bool barcodesAreSorted1,
67  simtks(simtks1), simvtxs(simvtxs1),
68  gens(gens1), genBarcodes(genBarcodes1), barcodesAreSorted(barcodesAreSorted1),
69  output(output1), refprod(refprod1), simTksProcessed() {}
70  // GEANT info
73  // PYTHIA info
77  // MY OUTPUT info
80  // BOOK-KEEPING
81  std::map<unsigned int,int> simTksProcessed; // key = sim track id;
82  // val = 0: not processed;
83  // i>0: (index+1) in my output
84  // i<0: -(index+1) in pythia [NOT USED]
85  };
86 
88  const SimTrack * findGeantMother(const SimTrack &tk, const GlobalContext &g) const ;
95 
100 
101 
102 
103  struct LessById {
104  bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
105  bool operator()(const SimTrack &tk1, unsigned int id ) const { return tk1.trackId() < id; }
106  bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
107  };
108  };
109 }
110 
111 using namespace std;
112 using namespace edm;
113 using namespace reco;
115 
117  firstEvent_(true),
118  simTracksToken_(consumes<SimTrackContainer>(cfg.getParameter<InputTag>("src"))), // source sim tracks
119  simVertexToken_(consumes<SimVertexContainer>(cfg.getParameter<InputTag>("src"))), // source sim vertices
120  setStatus_(cfg.getParameter<int32_t>("setStatus")), // set status of GenParticle to this code
121  filter_( cfg.existsAs<string>("filter") ? cfg.getParameter<string>("filter") : std::string("1 == 1") ),
122  makeMotherLink_(cfg.existsAs<bool>("makeMotherLink") ? cfg.getParameter<bool>("makeMotherLink") : false),
123  writeAncestors_(cfg.existsAs<bool>("writeAncestors") ? cfg.getParameter<bool>("writeAncestors") : false),
124  genParticlesToken_(mayConsume<GenParticleCollection>(cfg.getParameter<InputTag>("genParticles"))),
125  genBarcodesToken_(mayConsume<std::vector<int> >(cfg.getParameter<InputTag>("genParticles")))
126 {
127  // Possibly allow a list of particle types
128  if (cfg.exists("particleTypes")) {
129  pdts_ = cfg.getParameter<vector<PdtEntry> >("particleTypes");
130  }
131  if (cfg.exists("motherTypes")) {
132  motherPdts_ = cfg.getParameter<vector<PdtEntry> >("motherTypes");
133  }
134 
136  edm::LogWarning("Configuration") << "PATGenCandsFromSimTracksProducer: " <<
137  "you have set 'writeAncestors' to 'true' and 'makeMotherLink' to false;" <<
138  "GEANT particles with generator level (e.g.PYHIA) mothers won't have mother links.\n";
139  }
140  produces<GenParticleCollection>();
141 }
142 
143 const SimTrack *
145  assert(tk.genpartIndex() == -1); // MUST NOT be called with a PYTHIA track
146  if (!tk.noVertex()) {
147  const SimVertex &vtx = g.simvtxs[tk.vertIndex()];
148  if (!vtx.noParent()) {
149  unsigned int idx = vtx.parentIndex();
150  SimTrackContainer::const_iterator it = std::lower_bound(g.simtks.begin(), g.simtks.end(), idx, LessById());
151  if ((it != g.simtks.end()) && (it->trackId() == idx)) {
152  return &*it;
153  }
154  }
155  }
156  return 0;
157 }
158 
162  const SimTrack * simMother = findGeantMother(tk, g);
163 
165  if (simMother != 0) motherRef = findRef(*simMother,g);
166 
167  if (writeAncestors_) {
168  // If writing ancestors, I need to serialize myself, and then to return a ref to me
169  // But first check if I've already been serialized
170  std::map<unsigned int,int>::const_iterator it = g.simTksProcessed.find(tk.trackId());
171  if (it != g.simTksProcessed.end()) {
172  // just return a ref to it
173  assert(it->second > 0);
174  return edm::Ref<reco::GenParticleCollection>(g.refprod, (it->second) - 1);
175  } else {
176  // make genParticle, save, update the map, and return ref to myself
177  reco::GenParticle p = makeGenParticle_(tk, motherRef, g);
178  g.output.push_back(p);
179  g.simTksProcessed[tk.trackId()] = g.output.size();
181  }
182  } else {
183  // Otherwise, I just return a ref to my mum
184  return motherRef;
185  }
186 }
187 
190  assert(st.genpartIndex() != -1);
191  // Note that st.genpartIndex() is the barcode, not the index within GenParticleCollection, so I have to search the particle
192  std::vector<int>::const_iterator it;
193  if (g.barcodesAreSorted) {
194  it = std::lower_bound(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
195  } else {
196  it = std::find( g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
197  }
198 
199  // Check that I found something
200  // I need to check '*it == st.genpartIndex()' because lower_bound just finds the right spot for an item in a sorted list, not the item
201  if ((it != g.genBarcodes->end()) && (*it == st.genpartIndex())) {
202  return reco::GenParticleRef(g.gens, it - g.genBarcodes->begin());
203  } else {
204  return reco::GenParticleRef();
205  }
206 }
207 
210  // Make up a GenParticleCandidate from the GEANT track info.
211  int charge = static_cast<int>(tk.charge());
213  Particle::Point vtx; // = (0,0,0) by default
214  if (!tk.noVertex()) vtx = g.simvtxs[tk.vertIndex()].position();
215  GenParticle gp(charge, p4, vtx, tk.type(), setStatus_, true);
216  if (mother.isNonnull()) gp.addMother(mother);
217  return gp;
218 }
219 
220 
222  const EventSetup& iSetup) {
223 
224  if (firstEvent_){
225  if (!pdts_.empty()) {
226  pdgIds_.clear();
227  for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
228  itp->setup(iSetup); // decode string->pdgId and vice-versa
229  pdgIds_.insert(std::abs(itp->pdgId()));
230  }
231  pdts_.clear();
232  }
233  if (!motherPdts_.empty()) {
234  motherPdgIds_.clear();
235  for (vector<PdtEntry>::iterator itp = motherPdts_.begin(), edp = motherPdts_.end(); itp != edp; ++itp) {
236  itp->setup(iSetup); // decode string->pdgId and vice-versa
237  motherPdgIds_.insert(std::abs(itp->pdgId()));
238  }
239  motherPdts_.clear();
240  }
241  firstEvent_ = false;
242  }
243 
244  // Simulated tracks (i.e. GEANT particles).
245  Handle<SimTrackContainer> simtracks;
246  event.getByToken(simTracksToken_, simtracks);
247 
248  // Need to check that SimTrackContainer is sorted; otherwise, copy and sort :-(
249  std::unique_ptr<SimTrackContainer> simtracksTmp;
250  const SimTrackContainer * simtracksSorted = &* simtracks;
252  if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
253  simtracksTmp.reset(new SimTrackContainer(*simtracks));
254  std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
255  simtracksSorted = &* simtracksTmp;
256  }
257  }
258 
259  // Get the associated vertices
260  Handle<SimVertexContainer> simvertices;
261  event.getByToken(simVertexToken_, simvertices);
262 
263  // Get the GenParticles and barcodes, if needed to set mother links
265  Handle<std::vector<int> > genBarcodes;
266  bool barcodesAreSorted = true;
267  if (makeMotherLink_) {
268  event.getByToken(genParticlesToken_, gens);
269  event.getByToken(genBarcodesToken_, genBarcodes);
270  if (gens->size() != genBarcodes->size()) throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
271  barcodesAreSorted = __gnu_cxx::is_sorted(genBarcodes->begin(), genBarcodes->end());
272  }
273 
274 
275  // make the output collection
276  auto cands = std::make_unique<GenParticleCollection>();
277  edm::RefProd<GenParticleCollection> refprod = event.getRefBeforePut<GenParticleCollection>();
278 
279  GlobalContext globals(*simtracksSorted, *simvertices, gens, genBarcodes, barcodesAreSorted, *cands, refprod);
280 
281  for (SimTrackContainer::const_iterator isimtrk = simtracks->begin();
282  isimtrk != simtracks->end(); ++isimtrk) {
283 
284  // Skip PYTHIA tracks.
285  if (isimtrk->genpartIndex() != -1) continue;
286 
287  // Maybe apply the PdgId filter
288  if (!pdgIds_.empty()) { // if we have a filter on pdg ids
289  if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end()) continue;
290  }
291 
292  GenParticle genp = makeGenParticle_(*isimtrk, Ref<GenParticleCollection>(), globals);
293 
294  // Maybe apply filter on the particle
295  if (!(filter_(genp))) continue;
296 
297 
298  if (!motherPdgIds_.empty()) {
299  const SimTrack *motherSimTk = findGeantMother(*isimtrk, globals);
300  if (motherSimTk == 0) continue;
301  if (motherPdgIds_.find(std::abs(motherSimTk->type())) == motherPdgIds_.end()) continue;
302  }
303 
305  Ref<GenParticleCollection> motherRef;
306  const SimTrack * mother = findGeantMother(*isimtrk, globals);
307  if (mother != 0) motherRef = findRef(*mother, globals);
308  if (motherRef.isNonnull()) genp.addMother(motherRef);
309  }
310 
311  cands->push_back(genp);
312  }
313 
314  // Write to the Event, and get back a handle (which can be useful for debugging)
315  edm::OrphanHandle<reco::GenParticleCollection> orphans = event.put(std::move(cands));
316 
317 #ifdef DEBUG_PATGenCandsFromSimTracksProducer
318  std::cout << "Produced a list of " << orphans->size() << " genParticles." << std::endl;
319  for (GenParticleCollection::const_iterator it = orphans->begin(), ed = orphans->end(); it != ed; ++it) {
320  std::cout << " ";
321  std::cout << "GenParticle #" << (it - orphans->begin()) << ": pdgId " << it->pdgId()
322  << ", pt = " << it->pt() << ", eta = " << it->eta() << ", phi = " << it->phi()
323  << ", rho = " << it->vertex().Rho() << ", z = " << it->vertex().Z() << std::endl;
324  edm::Ref<GenParticleCollection> mom = it->motherRef();
325  size_t depth = 2;
326  while (mom.isNonnull()) {
327  if (mom.id() == orphans.id()) {
328  // I need to re-make the ref because they are not working until this module returns.
329  mom = edm::Ref<GenParticleCollection>(orphans, mom.key());
330  }
331  for (size_t i = 0; i < depth; ++i) std::cout << " ";
332  std::cout << "GenParticleRef [" << mom.id() << "/" << mom.key() << "]: pdgId " << mom->pdgId() << ", status = " << mom->status()
333  << ", pt = " << mom->pt() << ", eta = " << mom->eta() << ", phi = " << mom->phi()
334  << ", rho = " << mom->vertex().Rho() << ", z = " << mom->vertex().Z() << std::endl;
335  if (mom.id() != orphans.id()) break;
336  if ((mom->motherRef().id() == mom.id()) && (mom->motherRef().key() == mom.key())) {
337  throw cms::Exception("Corrupt Data") << "A particle is it's own mother.\n";
338  }
339  mom = mom->motherRef();
340  depth++;
341  }
342  }
343  std::cout << std::endl;
344 #endif
345 
346 }
347 
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
const edm::Handle< reco::GenParticleCollection > & gens
const SimTrack * findGeantMother(const SimTrack &tk, const GlobalContext &g) const
Find the mother of a given GEANT track (or NULL if it can&#39;t be found).
edm::EDGetTokenT< reco::GenParticleCollection > genParticlesToken_
Collection of GenParticles I need to make refs to. It must also have its associated vector<int> of ba...
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
edm::Ref< GenParticleCollection > GenParticleRef
persistent reference to a GenParticle
edm::EDGetTokenT< std::vector< int > > genBarcodesToken_
bool exists(std::string const &parameterName) const
checks if a parameter exists
edm::Ref< reco::GenParticleCollection > findRef(const SimTrack &tk, GlobalContext &g) const
bool writeAncestors_
If true, I&#39;ll save GenParticles corresponding to the ancestors of this GEANT particle. Common ancestors are only written once.
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
float charge() const
charge
Definition: CoreSimTrack.cc:18
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 g
Definition: Activities.doc:4
GlobalContext(const edm::SimTrackContainer &simtks1, const edm::SimVertexContainer &simvtxs1, const edm::Handle< reco::GenParticleCollection > &gens1, const edm::Handle< std::vector< int > > &genBarcodes1, bool barcodesAreSorted1, reco::GenParticleCollection &output1, const edm::RefProd< reco::GenParticleCollection > &refprod1)
ProductID id() const
Accessor for product ID.
Definition: Ref.h:259
Produces reco::GenParticle from SimTracks.
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
Definition: HeavyIon.h:7
ProductID id() const
int parentIndex() const
Definition: SimVertex.h:33
double p4[4]
Definition: TauolaWrapper.h:92
int genpartIndex() const
index of the corresponding Generator particle in the Event container (-1 if no Genpart) ...
Definition: SimTrack.h:33
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool noVertex() const
Definition: SimTrack.h:30
bool makeMotherLink_
If true, I&#39;ll try to make a link from the GEANT particle to a GenParticle.
const edm::RefProd< reco::GenParticleCollection > & refprod
reco::GenParticle makeGenParticle_(const SimTrack &tk, const edm::Ref< reco::GenParticleCollection > &mother, const GlobalContext &g) const
Make a GenParticle for this SimTrack, with a given mother.
StringCutObjectSelector< reco::GenParticle > StrFilter
void addMother(const typename mothers::value_type &)
add a daughter via a reference
int vertIndex() const
index of the vertex in the Event container (-1 if no vertex)
Definition: SimTrack.h:29
unsigned int trackId() const
Definition: CoreSimTrack.h:34
bool operator()(const SimTrack &tk1, unsigned int id) const
std::vector< SimVertex > SimVertexContainer
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
edm::Ref< reco::GenParticleCollection > generatorRef_(const SimTrack &tk, const GlobalContext &g) const
Used by findRef if the track is a PYTHIA particle.
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:25
fixed size matrix
HLT enums.
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:22
bool operator()(unsigned int id, const SimTrack &tk2) const
math::XYZPoint Point
point in the space
Definition: Candidate.h:41
bool operator()(const SimTrack &tk1, const SimTrack &tk2) const
bool noParent() const
Definition: SimVertex.h:34
edm::EDGetTokenT< edm::SimVertexContainer > simVertexToken_
edm::EDGetTokenT< edm::SimTrackContainer > simTracksToken_
virtual void produce(edm::Event &, const edm::EventSetup &) override
EDGetTokenT< ProductType > mayConsume(edm::InputTag const &tag)
std::vector< SimTrack > SimTrackContainer
def move(src, dest)
Definition: eostools.py:510
Definition: event.py:1