CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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&);
36  virtual void endJob() {}
37 
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  std::auto_ptr<StrFilter> filter_;
48 
53 
56 
58  struct GlobalContext {
60  const edm::SimVertexContainer &simvtxs1,
62  const edm::Handle<std::vector<int> > &genBarcodes1,
63  bool barcodesAreSorted1,
66  simtks(simtks1), simvtxs(simvtxs1),
67  gens(gens1), genBarcodes(genBarcodes1), barcodesAreSorted(barcodesAreSorted1),
68  output(output1), refprod(refprod1), simTksProcessed() {}
69  // GEANT info
72  // PYTHIA info
76  // MY OUTPUT info
79  // BOOK-KEEPING
80  std::map<unsigned int,int> simTksProcessed; // key = sim track id;
81  // val = 0: not processed;
82  // i>0: (index+1) in my output
83  // i<0: -(index+1) in pythia [NOT USED]
84  };
85 
87  const SimTrack * findGeantMother(const SimTrack &tk, const GlobalContext &g) const ;
94 
99 
100 
101 
102  struct LessById {
103  bool operator()(const SimTrack &tk1, const SimTrack &tk2) const { return tk1.trackId() < tk2.trackId(); }
104  bool operator()(const SimTrack &tk1, unsigned int id ) const { return tk1.trackId() < id; }
105  bool operator()(unsigned int id, const SimTrack &tk2) const { return id < tk2.trackId(); }
106  };
107 
108 };
109 }
110 
111 using namespace std;
112 using namespace edm;
113 using namespace reco;
115 
116 PATGenCandsFromSimTracksProducer::PATGenCandsFromSimTracksProducer(const ParameterSet& cfg) :
117  firstEvent_(true),
118  src_(cfg.getParameter<InputTag>("src")), // source sim tracks & vertices
119  setStatus_(cfg.getParameter<int32_t>("setStatus")), // set status of GenParticle to this code
120  makeMotherLink_(cfg.existsAs<bool>("makeMotherLink") ? cfg.getParameter<bool>("makeMotherLink") : false),
121  writeAncestors_(cfg.existsAs<bool>("writeAncestors") ? cfg.getParameter<bool>("writeAncestors") : false),
122  genParticles_(makeMotherLink_ ? cfg.getParameter<InputTag>("genParticles") : edm::InputTag())
123 {
124  // Possibly allow a list of particle types
125  if (cfg.exists("particleTypes")) {
126  pdts_ = cfg.getParameter<vector<PdtEntry> >("particleTypes");
127  }
128  if (cfg.exists("motherTypes")) {
129  motherPdts_ = cfg.getParameter<vector<PdtEntry> >("motherTypes");
130  }
131 
132  // Possibly allow a string cut
133  if (cfg.existsAs<string>("filter")) {
134  string filter = cfg.getParameter<string>("filter");
135  if (!filter.empty()) {
136  filter_ = auto_ptr<StrFilter>(new StrFilter(filter));
137  }
138  }
139 
141  edm::LogWarning("Configuration") << "PATGenCandsFromSimTracksProducer: " <<
142  "you have set 'writeAncestors' to 'true' and 'makeMotherLink' to false;" <<
143  "GEANT particles with generator level (e.g.PYHIA) mothers won't have mother links.\n";
144  }
145  produces<GenParticleCollection>();
146 }
147 
148 const SimTrack *
150  assert(tk.genpartIndex() == -1); // MUST NOT be called with a PYTHIA track
151  if (!tk.noVertex()) {
152  const SimVertex &vtx = g.simvtxs[tk.vertIndex()];
153  if (!vtx.noParent()) {
154  unsigned int idx = vtx.parentIndex();
155  SimTrackContainer::const_iterator it = std::lower_bound(g.simtks.begin(), g.simtks.end(), idx, LessById());
156  if ((it != g.simtks.end()) && (it->trackId() == idx)) {
157  return &*it;
158  }
159  }
160  }
161  return 0;
162 }
163 
167  const SimTrack * simMother = findGeantMother(tk, g);
168 
170  if (simMother != 0) motherRef = findRef(*simMother,g);
171 
172  if (writeAncestors_) {
173  // If writing ancestors, I need to serialize myself, and then to return a ref to me
174  // But first check if I've already been serialized
175  std::map<unsigned int,int>::const_iterator it = g.simTksProcessed.find(tk.trackId());
176  if (it != g.simTksProcessed.end()) {
177  // just return a ref to it
178  assert(it->second > 0);
179  return edm::Ref<reco::GenParticleCollection>(g.refprod, (it->second) - 1);
180  } else {
181  // make genParticle, save, update the map, and return ref to myself
182  reco::GenParticle p = makeGenParticle_(tk, motherRef, g);
183  g.output.push_back(p);
184  g.simTksProcessed[tk.trackId()] = g.output.size();
186  }
187  } else {
188  // Otherwise, I just return a ref to my mum
189  return motherRef;
190  }
191 }
192 
195  assert(st.genpartIndex() != -1);
196  // Note that st.genpartIndex() is the barcode, not the index within GenParticleCollection, so I have to search the particle
197  std::vector<int>::const_iterator it;
198  if (g.barcodesAreSorted) {
199  it = std::lower_bound(g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
200  } else {
201  it = std::find( g.genBarcodes->begin(), g.genBarcodes->end(), st.genpartIndex());
202  }
203 
204  // Check that I found something
205  // 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
206  if ((it != g.genBarcodes->end()) && (*it == st.genpartIndex())) {
207  return reco::GenParticleRef(g.gens, it - g.genBarcodes->begin());
208  } else {
209  return reco::GenParticleRef();
210  }
211 }
212 
215  // Make up a GenParticleCandidate from the GEANT track info.
216  int charge = static_cast<int>(tk.charge());
218  Particle::Point vtx; // = (0,0,0) by default
219  if (!tk.noVertex()) vtx = g.simvtxs[tk.vertIndex()].position();
220  GenParticle gp(charge, p4, vtx, tk.type(), setStatus_, true);
221  if (mother.isNonnull()) gp.addMother(mother);
222  return gp;
223 }
224 
225 
227  const EventSetup& iSetup) {
228 
229  if (firstEvent_){
230  if (!pdts_.empty()) {
231  pdgIds_.clear();
232  for (vector<PdtEntry>::iterator itp = pdts_.begin(), edp = pdts_.end(); itp != edp; ++itp) {
233  itp->setup(iSetup); // decode string->pdgId and vice-versa
234  pdgIds_.insert(std::abs(itp->pdgId()));
235  }
236  pdts_.clear();
237  }
238  if (!motherPdts_.empty()) {
239  motherPdgIds_.clear();
240  for (vector<PdtEntry>::iterator itp = motherPdts_.begin(), edp = motherPdts_.end(); itp != edp; ++itp) {
241  itp->setup(iSetup); // decode string->pdgId and vice-versa
242  motherPdgIds_.insert(std::abs(itp->pdgId()));
243  }
244  motherPdts_.clear();
245  }
246  firstEvent_ = false;
247  }
248 
249  // Simulated tracks (i.e. GEANT particles).
250  Handle<SimTrackContainer> simtracks;
251  event.getByLabel(src_, simtracks);
252 
253  // Need to check that SimTrackContainer is sorted; otherwise, copy and sort :-(
254  std::auto_ptr<SimTrackContainer> simtracksTmp;
255  const SimTrackContainer * simtracksSorted = &* simtracks;
257  if (!__gnu_cxx::is_sorted(simtracks->begin(), simtracks->end(), LessById())) {
258  simtracksTmp.reset(new SimTrackContainer(*simtracks));
259  std::sort(simtracksTmp->begin(), simtracksTmp->end(), LessById());
260  simtracksSorted = &* simtracksTmp;
261  }
262  }
263 
264  // Get the associated vertices
265  Handle<SimVertexContainer> simvertices;
266  event.getByLabel(src_, simvertices);
267 
268  // Get the GenParticles and barcodes, if needed to set mother links
270  Handle<std::vector<int> > genBarcodes;
271  bool barcodesAreSorted = true;
272  if (makeMotherLink_) {
273  event.getByLabel(genParticles_, gens);
274  event.getByLabel(genParticles_, genBarcodes);
275  if (gens->size() != genBarcodes->size()) throw cms::Exception("Corrupt data") << "Barcodes not of the same size as GenParticles!\n";
276  barcodesAreSorted = __gnu_cxx::is_sorted(genBarcodes->begin(), genBarcodes->end());
277  }
278 
279 
280  // make the output collection
281  auto_ptr<GenParticleCollection> cands(new GenParticleCollection);
282  edm::RefProd<GenParticleCollection> refprod = event.getRefBeforePut<GenParticleCollection>();
283 
284  GlobalContext globals(*simtracksSorted, *simvertices, gens, genBarcodes, barcodesAreSorted, *cands, refprod);
285 
286  for (SimTrackContainer::const_iterator isimtrk = simtracks->begin();
287  isimtrk != simtracks->end(); ++isimtrk) {
288 
289  // Skip PYTHIA tracks.
290  if (isimtrk->genpartIndex() != -1) continue;
291 
292  // Maybe apply the PdgId filter
293  if (!pdgIds_.empty()) { // if we have a filter on pdg ids
294  if (pdgIds_.find(std::abs(isimtrk->type())) == pdgIds_.end()) continue;
295  }
296 
298 
299  // Maybe apply filter on the particle
300  if (filter_.get() != 0) {
301  if (!(*filter_)(genp)) continue;
302  }
303 
304  if (!motherPdgIds_.empty()) {
305  const SimTrack *motherSimTk = findGeantMother(*isimtrk, globals);
306  if (motherSimTk == 0) continue;
307  if (motherPdgIds_.find(std::abs(motherSimTk->type())) == motherPdgIds_.end()) continue;
308  }
309 
311  Ref<GenParticleCollection> motherRef;
312  const SimTrack * mother = findGeantMother(*isimtrk, globals);
313  if (mother != 0) motherRef = findRef(*mother, globals);
314  if (motherRef.isNonnull()) genp.addMother(motherRef);
315  }
316 
317  cands->push_back(genp);
318  }
319 
320  // Write to the Event, and get back a handle (which can be useful for debugging)
321  edm::OrphanHandle<reco::GenParticleCollection> orphans = event.put(cands);
322 
323 #ifdef DEBUG_PATGenCandsFromSimTracksProducer
324  std::cout << "Produced a list of " << orphans->size() << " genParticles." << std::endl;
325  for (GenParticleCollection::const_iterator it = orphans->begin(), ed = orphans->end(); it != ed; ++it) {
326  std::cout << " ";
327  std::cout << "GenParticle #" << (it - orphans->begin()) << ": pdgId " << it->pdgId()
328  << ", pt = " << it->pt() << ", eta = " << it->eta() << ", phi = " << it->phi()
329  << ", rho = " << it->vertex().Rho() << ", z = " << it->vertex().Z() << std::endl;
330  edm::Ref<GenParticleCollection> mom = it->motherRef();
331  size_t depth = 2;
332  while (mom.isNonnull()) {
333  if (mom.id() == orphans.id()) {
334  // I need to re-make the ref because they are not working until this module returns.
335  mom = edm::Ref<GenParticleCollection>(orphans, mom.key());
336  }
337  for (size_t i = 0; i < depth; ++i) std::cout << " ";
338  std::cout << "GenParticleRef [" << mom.id() << "/" << mom.key() << "]: pdgId " << mom->pdgId() << ", status = " << mom->status()
339  << ", pt = " << mom->pt() << ", eta = " << mom->eta() << ", phi = " << mom->phi()
340  << ", rho = " << mom->vertex().Rho() << ", z = " << mom->vertex().Z() << std::endl;
341  if (mom.id() != orphans.id()) break;
342  if ((mom->motherRef().id() == mom.id()) && (mom->motherRef().key() == mom.key())) {
343  throw cms::Exception("Corrupt Data") << "A particle is it's own mother.\n";
344  }
345  mom = mom->motherRef();
346  depth++;
347  }
348  }
349  std::cout << std::endl;
350 #endif
351 
352 }
353 
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:180
const edm::Handle< reco::GenParticleCollection > & gens
virtual void produce(edm::Event &, const edm::EventSetup &)
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).
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
edm::Ref< GenParticleCollection > GenParticleRef
persistent reference to a GenParticle
bool exists(std::string const &parameterName) const
checks if a parameter exists
edm::Ref< reco::GenParticleCollection > findRef(const SimTrack &tk, GlobalContext &g) const
#define abs(x)
Definition: mlp_lapack.h:159
bool writeAncestors_
If true, I&#39;ll save GenParticles corresponding to the ancestors of this GEANT particle. Common ancestors are only written once.
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
float charge() const
charge
Definition: CoreSimTrack.cc:3
double charge(const std::vector< uint8_t > &Ampls)
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)
Produces reco::GenParticle from SimTracks.
ProductID id() const
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:248
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
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
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
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:29
unsigned int trackId() const
Definition: CoreSimTrack.h:49
tuple filter
USE THIS FOR SKIMMED TRACKS process.p = cms.Path(process.hltLevel1GTSeed*process.skimming*process.offlineBeamSpot*process.TrackRefitter2) OTHERWISE USE THIS.
Definition: align_tpl.py:86
bool operator()(const SimTrack &tk1, unsigned int id) const
std::vector< SimVertex > SimVertexContainer
key_type key() const
Accessor for product key.
Definition: Ref.h:264
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:39
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:40
const math::XYZTLorentzVectorD & momentum() const
particle info...
Definition: CoreSimTrack.h:36
bool operator()(unsigned int id, const SimTrack &tk2) const
edm::InputTag genParticles_
Collection of GenParticles I need to make refs to. It must also have its associated vector&lt;int&gt; of ba...
math::XYZPoint Point
point in the space
Definition: Candidate.h:43
tuple cout
Definition: gather_cfg.py:41
bool operator()(const SimTrack &tk1, const SimTrack &tk2) const
ProductID id() const
Accessor for product ID.
Definition: Ref.h:254
bool noParent() const
Definition: SimVertex.h:34
std::vector< SimTrack > SimTrackContainer