CMS 3D CMS Logo

GenPlusSimParticleProducer.cc
Go to the documentation of this file.
1 
28 
33 
37 
38 #include <ext/algorithm>
39 #include <memory>
40 
41 namespace pat {
43  public:
45 
46  private:
47  void produce(edm::Event &, const edm::EventSetup &) override;
48 
53  std::set<int> pdgIds_; // these are the ones we really use
54  std::vector<PdtEntry> pdts_; // these are needed before we get the EventSetup
55 
57  std::unique_ptr<StrFilter> filter_;
58 
62 
65 
78  void addGenParticle(const SimTrack &stMom,
79  const SimTrack &stDau,
80  unsigned int momidx,
81  const edm::SimTrackContainer &simtks,
82  const edm::SimVertexContainer &simvtxs,
83  reco::GenParticleCollection &mergedGens,
84  const reco::GenParticleRefProd ref,
85  std::vector<int> &genBarcodes,
86  bool &barcodesAreSorted) const;
87  struct LessById {
88  bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
89  bool operator()(const SimTrack &tk1, unsigned int id) const { return tk1.trackId() < id; }
90  bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
91  };
92  };
93 } // namespace pat
94 
95 using namespace std;
96 using namespace edm;
97 using namespace reco;
99 
100 GenPlusSimParticleProducer::GenPlusSimParticleProducer(const ParameterSet &cfg)
101  : firstEvent_(true),
102  simtracksToken_(consumes<SimTrackContainer>(cfg.getParameter<InputTag>("src"))), // source sim tracks & vertices
103  simverticesToken_(
104  consumes<SimVertexContainer>(cfg.getParameter<InputTag>("src"))), // source sim tracks & vertices
105  setStatus_(cfg.getParameter<int32_t>("setStatus")), // set status of GenParticle to this code
106  gensToken_(consumes<GenParticleCollection>(
107  cfg.getParameter<InputTag>("genParticles"))), // get the genParticles to add GEANT particles to
108  genBarcodesToken_(consumes<std::vector<int>>(
109  cfg.getParameter<InputTag>("genParticles"))) // get the genParticles to add GEANT particles to
110 {
111  // Possibly allow a list of particle types
112  if (cfg.exists("particleTypes")) {
113  pdts_ = cfg.getParameter<vector<PdtEntry>>("particleTypes");
114  if (!pdts_.empty()) {
116  }
117  }
118 
119  // Possibly allow a string cut
120  if (cfg.existsAs<string>("filter")) {
121  string filter = cfg.getParameter<string>("filter");
122  if (!filter.empty()) {
123  filter_ = std::make_unique<StrFilter>(filter);
124  }
125  }
126  produces<GenParticleCollection>();
127  produces<vector<int>>();
128 }
129 
131  const SimTrack &stDau,
132  unsigned int momidx,
133  const SimTrackContainer &simtracksSorted,
134  const SimVertexContainer &simvertices,
135  reco::GenParticleCollection &mergedGens,
136  const GenParticleRefProd ref,
137  std::vector<int> &genBarcodes,
138  bool &barcodesAreSorted) const {
139  // Make the genParticle for stDau and add it to the new collection and update the parent-child relationship
140  // Make up a GenParticleCandidate from the GEANT track info.
141  int charge = static_cast<int>(stDau.charge());
142  const Particle::LorentzVector &p4 = stDau.momentum();
143  Particle::Point vtx; // = (0,0,0) by default
144  if (!stDau.noVertex())
145  vtx = simvertices[stDau.vertIndex()].position();
146  GenParticle genp(charge, p4, vtx, stDau.type(), setStatus_, true);
147 
148  // Maybe apply filter on the particle
149  if (filter_.get() != nullptr) {
150  if (!(*filter_)(genp))
151  return;
152  }
153 
154  reco::GenParticleRef parentRef(ref, momidx);
155  genp.addMother(parentRef);
156  mergedGens.push_back(genp);
157  // get the index for the daughter just added
158  unsigned int dauidx = mergedGens.size() - 1;
159 
160  // update add daughter relationship
161  reco::GenParticle &cand = mergedGens[momidx];
162  cand.addDaughter(GenParticleRef(ref, dauidx));
163 
164  //look for simtrack daughters of stDau to see if we need to recur further down the chain
165 
166  for (SimTrackContainer::const_iterator isimtrk = simtracksSorted.begin(); isimtrk != simtracksSorted.end();
167  ++isimtrk) {
168  if (!isimtrk->noVertex()) {
169  // Pick the vertex (isimtrk.vertIndex() is really an index)
170  const SimVertex &vtx = simvertices[isimtrk->vertIndex()];
171 
172  // Check if the vertex has a parent track (otherwise, we're lost)
173  if (!vtx.noParent()) {
174  // Now note that vtx.parentIndex() is NOT an index, it's a track id, so I have to search for it
175  unsigned int idx = vtx.parentIndex();
176  SimTrackContainer::const_iterator it =
177  std::lower_bound(simtracksSorted.begin(), simtracksSorted.end(), idx, LessById());
178  if ((it != simtracksSorted.end()) && (it->trackId() == idx)) {
179  if (it->trackId() == stDau.trackId()) {
180  //need the genparticle index of stDau which is dauidx
182  stDau, *isimtrk, dauidx, simtracksSorted, simvertices, mergedGens, ref, genBarcodes, barcodesAreSorted);
183  }
184  }
185  }
186  }
187  }
188 }
189 
191  if (firstEvent_) {
192  if (!pdts_.empty()) {
193  auto const &pdt = iSetup.getData(tableToken_);
194  pdgIds_.clear();
195  for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
196  itp->setup(pdt); // decode string->pdgId and vice-versa
197  pdgIds_.insert(std::abs(itp->pdgId()));
198  }
199  pdts_.clear();
200  }
201  firstEvent_ = false;
202  }
203 
204  // Simulated tracks (i.e. GEANT particles).
205  Handle<SimTrackContainer> simtracks;
206  event.getByToken(simtracksToken_, simtracks);
207 
208  // Need to check that SimTrackContainer is sorted; otherwise, copy and sort :-(
209  std::unique_ptr<SimTrackContainer> simtracksTmp;
210  const SimTrackContainer *simtracksSorted = &*simtracks;
211  if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
212  simtracksTmp = std::make_unique<SimTrackContainer>(*simtracks);
213  std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
214  simtracksSorted = &*simtracksTmp;
215  }
216 
217  // Get the associated vertices
218  Handle<SimVertexContainer> simvertices;
219  event.getByToken(simverticesToken_, simvertices);
220 
221  // Get the GenParticles and barcodes, if needed to set mother and daughter links
223  Handle<std::vector<int>> genBarcodes;
224  bool barcodesAreSorted = true;
225  event.getByToken(gensToken_, gens);
226  event.getByToken(genBarcodesToken_, genBarcodes);
227  if (gens->size() != genBarcodes->size())
228  throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
229 
230  // make the output collection
231  auto candsPtr = std::make_unique<GenParticleCollection>();
232  GenParticleCollection &cands = *candsPtr;
233 
234  const GenParticleRefProd ref = event.getRefBeforePut<GenParticleCollection>();
235 
236  // add the original genParticles to the merged output list
237  for (size_t i = 0; i < gens->size(); ++i) {
238  reco::GenParticle cand((*gens)[i]);
239  cands.push_back(cand);
240  }
241 
242  // make new barcodes vector and fill it with the original list
243  auto newGenBarcodes = std::make_unique<vector<int>>();
244  for (unsigned int i = 0; i < genBarcodes->size(); ++i) {
245  newGenBarcodes->push_back((*genBarcodes)[i]);
246  }
247  barcodesAreSorted = __gnu_cxx::is_sorted(newGenBarcodes->begin(), newGenBarcodes->end());
248 
249  for (size_t i = 0; i < cands.size(); ++i) {
251  size_t nDaus = cand.numberOfDaughters();
252  GenParticleRefVector daus = cand.daughterRefVector();
253  cand.resetDaughters(ref.id());
254  for (size_t d = 0; d < nDaus; ++d) {
255  cand.addDaughter(GenParticleRef(ref, daus[d].key()));
256  }
257 
258  size_t nMoms = cand.numberOfMothers();
259  GenParticleRefVector moms = cand.motherRefVector();
260  cand.resetMothers(ref.id());
261  for (size_t m = 0; m < nMoms; ++m) {
262  cand.addMother(GenParticleRef(ref, moms[m].key()));
263  }
264  }
265 
266  for (SimTrackContainer::const_iterator isimtrk = simtracks->begin(); isimtrk != simtracks->end(); ++isimtrk) {
267  // Skip PYTHIA tracks.
268  if (isimtrk->genpartIndex() != -1)
269  continue;
270 
271  // Maybe apply the PdgId filter
272  if (!pdgIds_.empty()) { // if we have a filter on pdg ids
273  if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end())
274  continue;
275  }
276 
277  // find simtrack that has a genParticle match to its parent
278  // Look at the production vertex. If there is no vertex, I can do nothing...
279  if (!isimtrk->noVertex()) {
280  // Pick the vertex (isimtrk.vertIndex() is really an index)
281  const SimVertex &vtx = (*simvertices)[isimtrk->vertIndex()];
282 
283  // Check if the vertex has a parent track (otherwise, we're lost)
284  if (!vtx.noParent()) {
285  // Now note that vtx.parentIndex() is NOT an index, it's a track id, so I have to search for it
286  unsigned int idx = vtx.parentIndex();
287  SimTrackContainer::const_iterator it =
288  std::lower_bound(simtracksSorted->begin(), simtracksSorted->end(), idx, LessById());
289  if ((it != simtracksSorted->end()) && (it->trackId() == idx)) { //it is the parent sim track
290  if (it->genpartIndex() != -1) {
291  std::vector<int>::const_iterator itIndex;
292  if (barcodesAreSorted) {
293  itIndex = std::lower_bound(genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
294  } else {
295  itIndex = std::find(genBarcodes->begin(), genBarcodes->end(), it->genpartIndex());
296  }
297 
298  // Check that I found something
299  // I need to check '*itIndex == it->genpartIndex()' because lower_bound just finds the right spot for an item in a sorted list, not the item
300  if ((itIndex != genBarcodes->end()) && (*itIndex == it->genpartIndex())) {
301  // Ok, I'll make the genParticle for st and add it to the new collection updating the map and parent-child relationship
302  // pass the mother and daughter sim tracks and the mother genParticle to method to create the daughter genParticle and recur
303  unsigned int momidx = itIndex - genBarcodes->begin();
304  addGenParticle(*it,
305  *isimtrk,
306  momidx,
307  *simtracksSorted,
308  *simvertices,
309  *candsPtr,
310  ref,
311  *newGenBarcodes,
312  barcodesAreSorted);
313  }
314  }
315  }
316  }
317  }
318  }
319 
320  event.put(std::move(candsPtr));
321  event.put(std::move(newGenBarcodes));
322 }
323 
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
genp
produce generated paricles in acceptance #
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
edm::EDGetTokenT< edm::SimVertexContainer > simverticesToken_
edm::EDGetTokenT< std::vector< int > > genBarcodesToken_
edm::ESGetToken< HepPDT::ParticleDataTable, edm::DefaultRecord > tableToken_
std::unique_ptr< StrFilter > filter_
bool operator()(unsigned int id, const SimTrack &tk2) const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
float charge() const
charge
Definition: CoreSimTrack.cc:17
const math::XYZTLorentzVectorD & momentum() const
Definition: CoreSimTrack.h:19
Definition: HeavyIon.h:7
int type() const
particle type (HEP PDT convension)
Definition: CoreSimTrack.h:22
StringCutObjectSelector< reco::GenParticle > StrFilter
int vertIndex() const
index of the vertex in the Event container (-1 if no vertex)
Definition: SimTrack.h:33
bool operator()(const SimTrack &tk1, unsigned int id) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
GenPlusSimParticleProducer(const edm::ParameterSet &)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
Produces reco::GenParticle from SimTracks.
d
Definition: ztail.py:151
ProductID id() const
Accessor for product ID.
Definition: RefProd.h:124
bool noVertex() const
Definition: SimTrack.h:34
edm::Ref< edm::HepMCProduct, HepMC::GenParticle > GenParticleRef
edm::EDGetTokenT< reco::GenParticleCollection > gensToken_
Collection of GenParticles I need to make refs to. It must also have its associated vector<int> of ba...
std::vector< SimVertex > SimVertexContainer
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:36
void produce(edm::Event &, const edm::EventSetup &) override
bool operator()(const SimTrack &tk1, const SimTrack &tk2) const
fixed size matrix
HLT enums.
unsigned int trackId() const
Definition: CoreSimTrack.h:31
void addGenParticle(const SimTrack &stMom, const SimTrack &stDau, unsigned int momidx, const edm::SimTrackContainer &simtks, const edm::SimVertexContainer &simvtxs, reco::GenParticleCollection &mergedGens, const reco::GenParticleRefProd ref, std::vector< int > &genBarcodes, bool &barcodesAreSorted) const
Try to link the GEANT particle to the generator particle it came from.
math::XYZPoint Point
point in the space
Definition: Candidate.h:40
std::vector< SimTrack > SimTrackContainer
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1
edm::EDGetTokenT< edm::SimTrackContainer > simtracksToken_