CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PATGenCandsFromSimTracksProducer.cc
Go to the documentation of this file.
1 
17 
22 
26 
27 #include <ext/algorithm>
28 #include <memory>
29 
30 namespace pat {
32  public:
35 
36  private:
37  void produce(edm::Event &, const edm::EventSetup &) override;
38 
43  std::set<int> pdgIds_; // these are the ones we really use
44  std::vector<PdtEntry> pdts_; // these are needed before we get the EventSetup
45  std::set<int> motherPdgIds_; // these are the ones we really use
46  std::vector<PdtEntry> motherPdts_; // these are needed before we get the EventSetup
47 
50 
55 
59 
62  struct GlobalContext {
64  const edm::SimVertexContainer &simvtxs1,
66  const edm::Handle<std::vector<int> > &genBarcodes1,
67  bool barcodesAreSorted1,
70  : simtks(simtks1),
71  simvtxs(simvtxs1),
72  gens(gens1),
73  genBarcodes(genBarcodes1),
74  barcodesAreSorted(barcodesAreSorted1),
75  output(output1),
76  refprod(refprod1),
77  simTksProcessed() {}
78  // GEANT info
81  // PYTHIA info
85  // MY OUTPUT info
88  // BOOK-KEEPING
89  std::map<unsigned int, int> simTksProcessed; // key = sim track id;
90  // val = 0: not processed;
91  // i>0: (index+1) in my output
92  // i<0: -(index+1) in pythia [NOT USED]
93  };
94 
96  const SimTrack *findGeantMother(const SimTrack &tk, const GlobalContext &g) const;
103 
109  const GlobalContext &g) const;
110 
111  struct LessById {
112  bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
113  bool operator()(const SimTrack &tk1, unsigned int id) const { return tk1.trackId() < id; }
114  bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
115  };
116  };
117 } // namespace pat
118 
119 using namespace std;
120 using namespace edm;
121 using namespace reco;
123 
124 PATGenCandsFromSimTracksProducer::PATGenCandsFromSimTracksProducer(const ParameterSet &cfg)
125  : firstEvent_(true),
126  simTracksToken_(consumes<SimTrackContainer>(cfg.getParameter<InputTag>("src"))), // source sim tracks
127  simVertexToken_(consumes<SimVertexContainer>(cfg.getParameter<InputTag>("src"))), // source sim vertices
128  setStatus_(cfg.getParameter<int32_t>("setStatus")), // set status of GenParticle to this code
129  filter_(cfg.existsAs<string>("filter") ? cfg.getParameter<string>("filter") : std::string("1 == 1")),
130  makeMotherLink_(cfg.existsAs<bool>("makeMotherLink") ? cfg.getParameter<bool>("makeMotherLink") : false),
131  writeAncestors_(cfg.existsAs<bool>("writeAncestors") ? cfg.getParameter<bool>("writeAncestors") : false),
132  genParticlesToken_(mayConsume<GenParticleCollection>(cfg.getParameter<InputTag>("genParticles"))),
133  genBarcodesToken_(mayConsume<std::vector<int> >(cfg.getParameter<InputTag>("genParticles"))),
134  tableToken_(esConsumes()) {
135  // Possibly allow a list of particle types
136  if (cfg.exists("particleTypes")) {
137  pdts_ = cfg.getParameter<vector<PdtEntry> >("particleTypes");
138  }
139  if (cfg.exists("motherTypes")) {
140  motherPdts_ = cfg.getParameter<vector<PdtEntry> >("motherTypes");
141  }
142 
144  edm::LogWarning("Configuration")
145  << "PATGenCandsFromSimTracksProducer: "
146  << "you have set 'writeAncestors' to 'true' and 'makeMotherLink' to false;"
147  << "GEANT particles with generator level (e.g.PYHIA) mothers won't have mother links.\n";
148  }
149  produces<GenParticleCollection>();
150 }
151 
153  assert(tk.genpartIndex() == -1); // MUST NOT be called with a PYTHIA track
154  if (!tk.noVertex()) {
155  const SimVertex &vtx = g.simvtxs[tk.vertIndex()];
156  if (!vtx.noParent()) {
157  unsigned int idx = vtx.parentIndex();
158  SimTrackContainer::const_iterator it = std::lower_bound(g.simtks.begin(), g.simtks.end(), idx, LessById());
159  if ((it != g.simtks.end()) && (it->trackId() == idx)) {
160  return &*it;
161  }
162  }
163  }
164  return nullptr;
165 }
166 
168  GlobalContext &g) const {
169  if (tk.genpartIndex() != -1)
171  const SimTrack *simMother = findGeantMother(tk, g);
172 
174  if (simMother != nullptr)
175  motherRef = findRef(*simMother, g);
176 
177  if (writeAncestors_) {
178  // If writing ancestors, I need to serialize myself, and then to return a ref to me
179  // But first check if I've already been serialized
180  std::map<unsigned int, int>::const_iterator it = g.simTksProcessed.find(tk.trackId());
181  if (it != g.simTksProcessed.end()) {
182  // just return a ref to it
183  assert(it->second > 0);
184  return edm::Ref<reco::GenParticleCollection>(g.refprod, (it->second) - 1);
185  } else {
186  // make genParticle, save, update the map, and return ref to myself
187  reco::GenParticle p = makeGenParticle_(tk, motherRef, g);
188  g.output.push_back(p);
189  g.simTksProcessed[tk.trackId()] = g.output.size();
190  return edm::Ref<reco::GenParticleCollection>(g.refprod, g.output.size() - 1);
191  }
192  } else {
193  // Otherwise, I just return a ref to my mum
194  return motherRef;
195  }
196 }
197 
199  const GlobalContext &g) const {
200  assert(st.genpartIndex() != -1);
201  // Note that st.genpartIndex() is the barcode, not the index within GenParticleCollection, so I have to search the particle
202  std::vector<int>::const_iterator it;
203  if (g.barcodesAreSorted) {
204  it = std::lower_bound(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
205  } else {
206  it = std::find(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
207  }
208 
209  // Check that I found something
210  // 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
211  if ((it != g.genBarcodes->end()) && (*it == st.genpartIndex())) {
212  return reco::GenParticleRef(g.gens, it - g.genBarcodes->begin());
213  } else {
214  return reco::GenParticleRef();
215  }
216 }
217 
219  const SimTrack &tk, const edm::Ref<reco::GenParticleCollection> &mother, const GlobalContext &g) const {
220  // Make up a GenParticleCandidate from the GEANT track info.
221  int charge = static_cast<int>(tk.charge());
222  const Particle::LorentzVector &p4 = tk.momentum();
223  Particle::Point vtx; // = (0,0,0) by default
224  if (!tk.noVertex())
225  vtx = g.simvtxs[tk.vertIndex()].position();
226  GenParticle gp(charge, p4, vtx, tk.type(), setStatus_, true);
227  if (mother.isNonnull())
228  gp.addMother(mother);
229  return gp;
230 }
231 
233  if (firstEvent_) {
234  auto const &pdt = iSetup.getData(tableToken_);
235  if (!pdts_.empty()) {
236  pdgIds_.clear();
237  for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
238  itp->setup(pdt); // decode string->pdgId and vice-versa
239  pdgIds_.insert(std::abs(itp->pdgId()));
240  }
241  pdts_.clear();
242  }
243  if (!motherPdts_.empty()) {
244  motherPdgIds_.clear();
245  for (vector<PdtEntry>::iterator itp = motherPdts_.begin(), edp = motherPdts_.end(); itp != edp; ++itp) {
246  itp->setup(pdt); // decode string->pdgId and vice-versa
247  motherPdgIds_.insert(std::abs(itp->pdgId()));
248  }
249  motherPdts_.clear();
250  }
251  firstEvent_ = false;
252  }
253 
254  // Simulated tracks (i.e. GEANT particles).
255  Handle<SimTrackContainer> simtracks;
256  event.getByToken(simTracksToken_, simtracks);
257 
258  // Need to check that SimTrackContainer is sorted; otherwise, copy and sort :-(
259  std::unique_ptr<SimTrackContainer> simtracksTmp;
260  const SimTrackContainer *simtracksSorted = &*simtracks;
262  if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
263  simtracksTmp = std::make_unique<SimTrackContainer>(*simtracks);
264  std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
265  simtracksSorted = &*simtracksTmp;
266  }
267  }
268 
269  // Get the associated vertices
270  Handle<SimVertexContainer> simvertices;
271  event.getByToken(simVertexToken_, simvertices);
272 
273  // Get the GenParticles and barcodes, if needed to set mother links
275  Handle<std::vector<int> > genBarcodes;
276  bool barcodesAreSorted = true;
277  if (makeMotherLink_) {
278  event.getByToken(genParticlesToken_, gens);
279  event.getByToken(genBarcodesToken_, genBarcodes);
280  if (gens->size() != genBarcodes->size())
281  throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
282  barcodesAreSorted = __gnu_cxx::is_sorted(genBarcodes->begin(), genBarcodes->end());
283  }
284 
285  // make the output collection
286  auto cands = std::make_unique<GenParticleCollection>();
287  edm::RefProd<GenParticleCollection> refprod = event.getRefBeforePut<GenParticleCollection>();
288 
289  GlobalContext globals(*simtracksSorted, *simvertices, gens, genBarcodes, barcodesAreSorted, *cands, refprod);
290 
291  for (SimTrackContainer::const_iterator isimtrk = simtracks->begin(); isimtrk != simtracks->end(); ++isimtrk) {
292  // Skip PYTHIA tracks.
293  if (isimtrk->genpartIndex() != -1)
294  continue;
295 
296  // Maybe apply the PdgId filter
297  if (!pdgIds_.empty()) { // if we have a filter on pdg ids
298  if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end())
299  continue;
300  }
301 
303 
304  // Maybe apply filter on the particle
305  if (!(filter_(genp)))
306  continue;
307 
308  if (!motherPdgIds_.empty()) {
309  const SimTrack *motherSimTk = findGeantMother(*isimtrk, globals);
310  if (motherSimTk == nullptr)
311  continue;
312  if (motherPdgIds_.find(std::abs(motherSimTk->type())) == motherPdgIds_.end())
313  continue;
314  }
315 
317  Ref<GenParticleCollection> motherRef;
318  const SimTrack *mother = findGeantMother(*isimtrk, globals);
319  if (mother != nullptr)
320  motherRef = findRef(*mother, globals);
321  if (motherRef.isNonnull())
322  genp.addMother(motherRef);
323  }
324 
325  cands->push_back(genp);
326  }
327 
328  // Write to the Event, and get back a handle (which can be useful for debugging)
330 
331 #ifdef DEBUG_PATGenCandsFromSimTracksProducer
332  std::cout << "Produced a list of " << orphans->size() << " genParticles." << std::endl;
333  for (GenParticleCollection::const_iterator it = orphans->begin(), ed = orphans->end(); it != ed; ++it) {
334  std::cout << " ";
335  std::cout << "GenParticle #" << (it - orphans->begin()) << ": pdgId " << it->pdgId() << ", pt = " << it->pt()
336  << ", eta = " << it->eta() << ", phi = " << it->phi() << ", rho = " << it->vertex().Rho()
337  << ", z = " << it->vertex().Z() << std::endl;
338  edm::Ref<GenParticleCollection> mom = it->motherRef();
339  size_t depth = 2;
340  while (mom.isNonnull()) {
341  if (mom.id() == orphans.id()) {
342  // I need to re-make the ref because they are not working until this module returns.
343  mom = edm::Ref<GenParticleCollection>(orphans, mom.key());
344  }
345  for (size_t i = 0; i < depth; ++i)
346  std::cout << " ";
347  std::cout << "GenParticleRef [" << mom.id() << "/" << mom.key() << "]: pdgId " << mom->pdgId()
348  << ", status = " << mom->status() << ", pt = " << mom->pt() << ", eta = " << mom->eta()
349  << ", phi = " << mom->phi() << ", rho = " << mom->vertex().Rho() << ", z = " << mom->vertex().Z()
350  << std::endl;
351  if (mom.id() != orphans.id())
352  break;
353  if ((mom->motherRef().id() == mom.id()) && (mom->motherRef().key() == mom.key())) {
354  throw cms::Exception("Corrupt Data") << "A particle is it's own mother.\n";
355  }
356  mom = mom->motherRef();
357  depth++;
358  }
359  }
360  std::cout << std::endl;
361 #endif
362 }
363 
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
tuple cfg
Definition: looper.py:296
const edm::Handle< reco::GenParticleCollection > & gens
uint16_t *__restrict__ id
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&lt;int&gt; of ba...
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
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:250
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
float charge() const
charge
Definition: CoreSimTrack.cc:17
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:244
Produces reco::GenParticle from SimTracks.
ProductID id() const
bool getData(T &iHolder) const
Definition: EventSetup.h:122
int parentIndex() const
Definition: SimVertex.h:29
int genpartIndex() const
index of the corresponding Generator particle in the Event container (-1 if no Genpart) ...
Definition: SimTrack.h:37
def move
Definition: eostools.py:511
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool noVertex() const
Definition: SimTrack.h:34
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.
tuple genp
produce generated paricles in acceptance #
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:33
unsigned int trackId() const
Definition: CoreSimTrack.h:31
bool operator()(const SimTrack &tk1, unsigned int id) const
std::vector< SimVertex > SimVertexContainer
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
edm::ESGetToken< HepPDT::ParticleDataTable, edm::DefaultRecord > tableToken_
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:36
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:22
__host__ __device__ constexpr RandomIt lower_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
bool operator()(unsigned int id, const SimTrack &tk2) const
math::XYZPoint Point
point in the space
Definition: Candidate.h:40
tuple cout
Definition: gather_cfg.py:144
bool operator()(const SimTrack &tk1, const SimTrack &tk2) const
bool noParent() const
Definition: SimVertex.h:30
edm::EDGetTokenT< edm::SimVertexContainer > simVertexToken_
edm::EDGetTokenT< edm::SimTrackContainer > simTracksToken_
Log< level::Warning, false > LogWarning
void produce(edm::Event &, const edm::EventSetup &) override
std::vector< SimTrack > SimTrackContainer
ESGetTokenH3DDVariant esConsumes(std::string const &Reccord, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283