CMS 3D CMS Logo

TopDecaySubset.cc
Go to the documentation of this file.
1 #include <memory>
2 #include <string>
3 #include <vector>
4 #include <map>
5 
9 
16 
19 
33 public:
36  enum FillMode { kStable, kME };
40  enum RunMode { kRun1, kRun2 };
41 
43  explicit TopDecaySubset(const edm::ParameterSet& cfg);
45  void produce(edm::Event& event, const edm::EventSetup& setup) override;
46 
47 private:
49  std::vector<const reco::GenParticle*> findTops(const reco::GenParticleCollection& parts);
52  std::vector<const reco::GenParticle*> findPrimalTops(const reco::GenParticleCollection& parts);
55  std::vector<const reco::GenParticle*> findDecayingTops(const reco::GenParticleCollection& parts);
61  // const reco::GenParticle* findDecayingW(const reco::GenParticle* top);
68  ShowerModel checkShowerModel(const std::vector<const reco::GenParticle*>& tops) const;
71  void checkWBosons(std::vector<const reco::GenParticle*>& tops) const;
73  void fillListing(const std::vector<const reco::GenParticle*>& tops, reco::GenParticleCollection& target);
75  void fillListing(const std::vector<const reco::GenParticle*>& primalTops,
76  const std::vector<const reco::GenParticle*>& decayingTops,
78 
80  void clearReferences();
84  reco::Particle::LorentzVector p4(const std::vector<const reco::GenParticle*>::const_iterator top, int statusFlag);
88  void addDaughters(int& idx,
91  bool recursive = true);
95 
96 private:
110 
116  std::map<int, std::vector<int> > refs_;
117 };
118 
121  : srcToken_(consumes<reco::GenParticleCollection>(cfg.getParameter<edm::InputTag>("src"))),
122  genEventInfo_srcToken_(mayConsume<GenEventInfoProduct>(edm::InputTag("generator"))),
123  addRadiation_(cfg.getParameter<bool>("addRadiation")),
124  showerModel_(kStart),
125  runMode_(kRun1) {
126  // mapping of the corresponding fillMode; see FillMode
127  // enumerator of TopDecaySubset for available modes
128  std::string mode = cfg.getParameter<std::string>("fillMode");
129  if (mode == "kME")
130  fillMode_ = kME;
131  else if (mode == "kStable")
132  fillMode_ = kStable;
133  else
134  throw cms::Exception("Configuration") << mode << " is not a supported FillMode!\n";
135 
136  mode = cfg.getParameter<std::string>("runMode");
137  if (mode == "Run1")
138  runMode_ = kRun1;
139  else if (mode == "Run2")
140  runMode_ = kRun2;
141  else
142  throw cms::Exception("Configuration") << mode << " is not a supported RunMode!\n";
143 
144  // produces a set of GenParticles following
145  // the decay branch of top quarks to the first level of
146  // stable decay products
147  produces<reco::GenParticleCollection>();
148 }
149 
152  // create target vector
153  std::unique_ptr<reco::GenParticleCollection> target(new reco::GenParticleCollection);
154 
155  // get source collection
157  event.getByToken(srcToken_, src);
158 
159  // find out what generator we are dealing with
160  if (showerModel_ == kStart && runMode_ == kRun2) {
162  }
163 
164  // find top quarks in list of input particles
165  std::vector<const reco::GenParticle*> tops;
166  if (runMode_ == kRun1)
167  tops = findTops(*src);
168  else
169  tops = findPrimalTops(*src);
170 
171  // determine shower model (only in first event)
172  if (showerModel_ == kStart && runMode_ == kRun1)
174 
175  if (showerModel_ != kNone) {
176  // check sanity of W bosons
177  if (runMode_ == kRun1)
178  checkWBosons(tops);
179  else {
180  // nothing for the moment
181  }
182 
183  // get ref product from the event
184  const reco::GenParticleRefProd ref = event.getRefBeforePut<reco::GenParticleCollection>();
185  // clear existing refs
186  clearReferences();
187  if (runMode_ == kRun1) {
188  // fill output
189  fillListing(tops, *target);
190  // fill references
191  fillReferences(ref, *target);
192  } else {
193  std::vector<const reco::GenParticle*> decaying_tops = findDecayingTops(*src);
194  // fill output
195  fillListing(tops, decaying_tops, *target);
196  // fill references
197  fillReferences(ref, *target);
198  }
199  }
200 
201  // write vectors to the event
202  event.put(std::move(target));
203 }
204 
206 std::vector<const reco::GenParticle*> TopDecaySubset::findTops(const reco::GenParticleCollection& parts) {
207  std::vector<const reco::GenParticle*> tops;
208  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
209  if (std::abs(t->pdgId()) == TopDecayID::tID && t->status() == TopDecayID::unfrag)
210  tops.push_back(&(*t));
211  }
212  return tops;
213 }
214 
217 std::vector<const reco::GenParticle*> TopDecaySubset::findPrimalTops(const reco::GenParticleCollection& parts) {
218  std::vector<const reco::GenParticle*> tops;
219  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
220  if (std::abs(t->pdgId()) != TopDecayID::tID)
221  continue;
222 
223  bool hasTopMother = false;
224  for (unsigned idx = 0; idx < t->numberOfMothers(); ++idx) {
225  if (std::abs(t->mother(idx)->pdgId()) == TopDecayID::tID)
226  hasTopMother = true;
227  }
228 
229  if (hasTopMother) // not a primal top
230  continue;
231  tops.push_back(&(*t));
232  }
233 
234  return tops;
235 }
236 
239 std::vector<const reco::GenParticle*> TopDecaySubset::findDecayingTops(const reco::GenParticleCollection& parts) {
240  std::vector<const reco::GenParticle*> tops;
241  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
242  if (std::abs(t->pdgId()) != TopDecayID::tID)
243  continue;
244 
245  bool hasTopDaughter = false;
246  for (unsigned idx = 0; idx < t->numberOfDaughters(); ++idx) {
247  if (std::abs(t->daughter(idx)->pdgId()) == TopDecayID::tID)
248  hasTopDaughter = true;
249  }
250 
251  if (hasTopDaughter) // not a decaying top
252  continue;
253  tops.push_back(&(*t));
254  }
255 
256  return tops;
257 }
258 
262  unsigned int w_index = 0;
263  for (unsigned idx = 0; idx < top->numberOfDaughters(); ++idx) {
264  if (std::abs(top->daughter(idx)->pdgId()) == TopDecayID::WID) {
265  w_index = idx;
266  break;
267  }
268  }
269  return static_cast<const reco::GenParticle*>(top->daughter(w_index));
270 }
271 
274 //const reco::GenParticle* TopDecaySubset::findDecayingW(
275 // const reco::GenParticle* top) {
276 // const reco::GenParticle* decaying_W = findLastParticleInChain(findPrimalW(top));
277 // return findLastParticleInChain(findPrimalW(top));
278 //}
279 
285  int particleID = std::abs(p->pdgId());
286  bool containsItself = false;
287  unsigned int d_idx = 0;
288  for (unsigned idx = 0; idx < p->numberOfDaughters(); ++idx) {
289  if (std::abs(p->daughter(idx)->pdgId()) == particleID) {
290  containsItself = true;
291  d_idx = idx;
292  }
293  }
294 
295  if (!containsItself)
296  return p;
297  else {
298  if (showerModel_ == kPythia) {
299  // Pythia6 has a weird idea of W bosons (and maybe other particles)
300  // W (status == 3) -> q qbar' W. The new W is status 2 and has no daughters
301  if (p->status() == 3)
302  return p;
303  }
304  return findLastParticleInChain(static_cast<const reco::GenParticle*>(p->daughter(d_idx)));
305  }
306 }
307 
309 TopDecaySubset::ShowerModel TopDecaySubset::checkShowerModel(const std::vector<const reco::GenParticle*>& tops) const {
310  for (std::vector<const reco::GenParticle*>::const_iterator it = tops.begin(); it != tops.end(); ++it) {
311  const reco::GenParticle* top = *it;
312  // check for kHerwig type showers: here the status 3 top quark will
313  // have a single status 2 top quark as daughter, which has again 3
314  // or more status 2 daughters
315  if (top->numberOfDaughters() == 1) {
316  if (top->begin()->pdgId() == top->pdgId() && top->begin()->status() == TopDecayID::stable &&
317  top->begin()->numberOfDaughters() > 1)
318  return kHerwig;
319  }
320  // check for kPythia type showers: here the status 3 top quark will
321  // have all decay products and a status 2 top quark as daughters
322  // the status 2 top quark will be w/o further daughters
323  if (top->numberOfDaughters() > 1) {
324  bool containsWBoson = false, containsQuarkDaughter = false;
325  for (reco::GenParticle::const_iterator td = top->begin(); td != top->end(); ++td) {
326  if (std::abs(td->pdgId()) < TopDecayID::tID)
327  containsQuarkDaughter = true;
328  if (std::abs(td->pdgId()) == TopDecayID::WID)
329  containsWBoson = true;
330  }
331  if (containsQuarkDaughter && containsWBoson)
332  return kPythia;
333  }
334  }
335  // if neither Herwig nor Pythia like
336  if (tops.empty())
337  edm::LogInfo("decayChain") << " Failed to find top quarks in decay chain. Will assume that this a \n"
338  << " non-top sample and produce an empty decaySubset.\n";
339  else
341  " Can not find back any of the supported hadronization models. Models \n"
342  " which are supported are: \n"
343  " Pythia LO(+PS): Top(status 3) --> WBoson(status 3), Quark(status 3)\n"
344  " Herwig NLO(+PS): Top(status 2) --> Top(status 3) --> Top(status 2) \n");
345  return kNone;
346 }
347 
350  edm::Handle<GenEventInfoProduct> genEvtInfoProduct;
351  event.getByToken(genEventInfo_srcToken_, genEvtInfoProduct);
352 
353  std::string moduleName = "";
354  if (genEvtInfoProduct.isValid()) {
355  const edm::StableProvenance& prov = event.getStableProvenance(genEvtInfoProduct.id());
356  moduleName = edm::moduleName(prov, event.processHistory());
357  if (moduleName == "ExternalGeneratorFilter") {
358  moduleName = edm::parameterSet(prov, event.processHistory()).getParameter<std::string>("@external_type");
359  edm::LogInfo("SpecialModule") << "GEN events are produced by ExternalGeneratorFilter, "
360  << "which is a wrapper of the original module: " << moduleName;
361  }
362  }
363 
364  ShowerModel shower(kStart);
365  if (moduleName.find("Pythia6") != std::string::npos)
366  shower = kPythia;
367  else if (moduleName.find("Pythia8") != std::string::npos)
368  shower = kPythia8;
369  else if (moduleName.find("Herwig6") != std::string::npos)
370  shower = kHerwig;
371  else if (moduleName.find("ThePEG") != std::string::npos)
372  // Herwig++
373  shower = kHerwig;
374  else if (moduleName.find("Sherpa") != std::string::npos)
375  shower = kSherpa;
376  else
377  shower = kNone;
378  return shower;
379 }
381 void TopDecaySubset::checkWBosons(std::vector<const reco::GenParticle*>& tops) const {
382  unsigned nTops = tops.size();
383  for (std::vector<const reco::GenParticle*>::iterator it = tops.begin(); it != tops.end();) {
384  const reco::GenParticle* top = *it;
385  bool isContained = false;
386  bool expectedStatus = false;
387  if (showerModel_ != kPythia && top->begin() == top->end())
388  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && top->begin()==top->end()\n");
389  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? top->begin() : top->begin()->begin());
390  td != ((showerModel_ == kPythia) ? top->end() : top->begin()->end());
391  ++td) {
392  if (std::abs(td->pdgId()) == TopDecayID::WID) {
393  isContained = true;
394  if (((showerModel_ == kPythia) ? td->status() == TopDecayID::unfrag : td->status() == TopDecayID::stable)) {
395  expectedStatus = true;
396  break;
397  }
398  }
399  }
400  if (!expectedStatus) {
401  it = tops.erase(it);
402  if (isContained)
403  edm::LogInfo("decayChain") << " W boson does not have the expected status. This happens, e.g., \n"
404  << " with MC@NLO in the case of additional ttbar pairs from radiated \n"
405  << " gluons. We hope everything is fine, remove the correspdonding top \n"
406  << " quark from our list since it is not part of the primary ttbar pair \n"
407  << " and try to continue. \n";
408  } else
409  it++;
410  }
411  if (tops.empty() && nTops != 0)
413  " Did not find a W boson with appropriate status for any of the top \n"
414  " quarks in this event. This means that the hadronization of the W \n"
415  " boson might be screwed up or there is another problem with the \n"
416  " particle listing in this MC sample. Please contact an expert. \n");
417 }
418 
420 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& tops,
422  unsigned int statusFlag;
423  // determine status flag of the new
424  // particle depending on the FillMode
425  fillMode_ == kME ? statusFlag = 3 : statusFlag = 2;
426 
427  for (std::vector<const reco::GenParticle*>::const_iterator it = tops.begin(); it != tops.end(); ++it) {
428  const reco::GenParticle* t = *it;
429  // if particle is top or anti-top
430  std::unique_ptr<reco::GenParticle> topPtr(
431  new reco::GenParticle(t->threeCharge(), p4(it, statusFlag), t->vertex(), t->pdgId(), statusFlag, false));
432  target.push_back(*topPtr);
433  ++motherPartIdx_;
434  // keep the top index for the map to manage the daughter refs
435  int iTop = motherPartIdx_;
436  std::vector<int> topDaughters;
437  // define the W boson index (to be set later) for the map to
438  // manage the daughter refs
439  int iW = 0;
440  std::vector<int> wDaughters;
441  // sanity check
442  if (showerModel_ != kPythia && t->begin() == t->end())
443  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && t->begin()==t->end()\n");
444  //iterate over top daughters
445  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? t->begin() : t->begin()->begin());
446  td != ((showerModel_ == kPythia) ? t->end() : t->begin()->end());
447  ++td) {
448  if (td->status() == TopDecayID::unfrag && std::abs(td->pdgId()) <= TopDecayID::bID) {
449  // if particle is beauty or other quark
450  std::unique_ptr<reco::GenParticle> bPtr(
451  new reco::GenParticle(td->threeCharge(), p4(td, statusFlag), td->vertex(), td->pdgId(), statusFlag, false));
452  target.push_back(*bPtr);
453  // increment & push index of the top daughter
454  topDaughters.push_back(++motherPartIdx_);
455  if (addRadiation_) {
457  }
458  }
459  // sanity check
460  if (showerModel_ != kPythia && td->begin() == td->end())
461  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && td->begin()==td->end()\n");
463  if (buffer->status() == TopDecayID::unfrag && std::abs(buffer->pdgId()) == TopDecayID::WID) {
464  // if particle is a W boson
465  std::unique_ptr<reco::GenParticle> wPtr(new reco::GenParticle(
466  buffer->threeCharge(), p4(buffer, statusFlag), buffer->vertex(), buffer->pdgId(), statusFlag, true));
467  target.push_back(*wPtr);
468  // increment & push index of the top daughter
469  topDaughters.push_back(++motherPartIdx_);
470  // keep the W idx for the map
471  iW = motherPartIdx_;
472  if (addRadiation_) {
474  }
475  if (showerModel_ != kPythia && buffer->begin() == buffer->end())
476  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && buffer->begin()==buffer->end()\n");
477  // iterate over W daughters
479  ((showerModel_ == kPythia) ? buffer->begin() : buffer->begin()->begin());
480  wd != ((showerModel_ == kPythia) ? buffer->end() : buffer->begin()->end());
481  ++wd) {
482  // make sure the W daughter is of status unfrag and not the W itself
483  if (wd->status() == TopDecayID::unfrag && !(std::abs(wd->pdgId()) == TopDecayID::WID)) {
484  std::unique_ptr<reco::GenParticle> qPtr(new reco::GenParticle(
485  wd->threeCharge(), p4(wd, statusFlag), wd->vertex(), wd->pdgId(), statusFlag, false));
486  target.push_back(*qPtr);
487  // increment & push index of the top daughter
488  wDaughters.push_back(++motherPartIdx_);
489  if (wd->status() == TopDecayID::unfrag && std::abs(wd->pdgId()) == TopDecayID::tauID) {
490  // add tau daughters if the particle is a tau pass
491  // the daughter of the tau which is of status 2
492  //addDaughters(motherPartIdx_, wd->begin(), target);
493  // add tau daughters if the particle is a tau pass
494  // the tau itself, which may add a tau daughter of
495  // of status 2 to the listing
497  }
498  }
499  }
500  }
501  if (addRadiation_ && buffer->status() == TopDecayID::stable &&
502  (buffer->pdgId() == TopDecayID::glueID || std::abs(buffer->pdgId()) < TopDecayID::bID)) {
503  // collect additional radiation from the top
504  std::unique_ptr<reco::GenParticle> radPtr(new reco::GenParticle(
505  buffer->threeCharge(), buffer->p4(), buffer->vertex(), buffer->pdgId(), statusFlag, false));
506  target.push_back(*radPtr);
507  // increment & push index of the top daughter
508  topDaughters.push_back(++motherPartIdx_);
509  }
510  }
511  // add potential sisters of the top quark;
512  // only for top to prevent double counting
513  if (t->numberOfMothers() > 0 && t->pdgId() == TopDecayID::tID) {
514  for (reco::GenParticle::const_iterator ts = t->mother()->begin(); ts != t->mother()->end(); ++ts) {
515  // loop over all daughters of the top mother i.e.
516  // the two top quarks and their potential sisters
517  if (std::abs(ts->pdgId()) != t->pdgId() && ts->pdgId() != t->mother()->pdgId()) {
518  // add all further particles but the two top quarks and potential
519  // cases where the mother of the top has itself as daughter
521  new reco::GenParticle(ts->threeCharge(), ts->p4(), ts->vertex(), ts->pdgId(), ts->status(), false);
522  std::unique_ptr<reco::GenParticle> sPtr(cand);
523  target.push_back(*sPtr);
524  if (ts->begin() != ts->end()) {
525  // in case the sister has daughters increment
526  // and add the first generation of daughters
527  addDaughters(++motherPartIdx_, ts->begin(), target, false);
528  }
529  }
530  }
531  }
532  // fill the map for the administration
533  // of daughter indices
534  refs_[iTop] = topDaughters;
535  refs_[iW] = wDaughters;
536  }
537 }
538 
539 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& primalTops,
540  const std::vector<const reco::GenParticle*>& decayingTops,
542  std::vector<const reco::GenParticle*>::const_iterator top_start;
543  std::vector<const reco::GenParticle*>::const_iterator top_end;
544  if (fillMode_ == kME) {
545  top_start = primalTops.begin();
546  top_end = primalTops.end();
547  } else {
548  top_start = decayingTops.begin();
549  top_end = decayingTops.end();
550  }
551  for (std::vector<const reco::GenParticle*>::const_iterator it = top_start; it != top_end; ++it) {
552  const reco::GenParticle* t = *it;
553  // summation might happen here
554  std::unique_ptr<reco::GenParticle> topPtr(
555  new reco::GenParticle(t->threeCharge(), t->p4(), t->vertex(), t->pdgId(), t->status(), false));
556  target.push_back(*topPtr);
557  ++motherPartIdx_;
558 
559  // keep the top index for the map to manage the daughter refs
560  int iTop = motherPartIdx_;
561  std::vector<int> topDaughters;
562  // define the W boson index (to be set later) for the map to
563  // manage the daughter refs
564  int iW = 0;
565  std::vector<int> wDaughters;
566  const reco::GenParticle* final_top = findLastParticleInChain(t);
567 
568  //iterate over top daughters
569  for (reco::GenParticle::const_iterator td = final_top->begin(); td != final_top->end(); ++td) {
570  if (std::abs(td->pdgId()) <= TopDecayID::bID) {
571  // if particle is beauty or other quark
572  std::unique_ptr<reco::GenParticle> qPtr(
573  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
574  target.push_back(*qPtr);
575  // increment & push index of the top daughter
576  topDaughters.push_back(++motherPartIdx_);
577  if (addRadiation_) {
578  // for radation to be added we first need to
579  // pick the last quark in the MC chain
580  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
582  }
583  } else if (std::abs(td->pdgId()) == TopDecayID::WID) {
584  // ladies and gentleman, we have a W boson
585  std::unique_ptr<reco::GenParticle> WPtr(
586  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
587  target.push_back(*WPtr);
588  // increment & push index of the top daughter
589  topDaughters.push_back(++motherPartIdx_);
590  iW = motherPartIdx_;
591 
592  // next are the daughers of our W boson
593  // for Pythia 6 this is wrong as the last W has no daughters at all!
594  // instead the status 3 W has 3 daughters: q qbar' and W (WTF??!)
595  const reco::GenParticle* decaying_W = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
596  for (reco::GenParticle::const_iterator wd = decaying_W->begin(); wd != decaying_W->end(); ++wd) {
597  if (!(std::abs(wd->pdgId()) == TopDecayID::WID)) {
598  std::unique_ptr<reco::GenParticle> qPtr(
599  new reco::GenParticle(wd->threeCharge(), wd->p4(), wd->vertex(), wd->pdgId(), wd->status(), false));
600  target.push_back(*qPtr);
601  // increment & push index of the top daughter
602  wDaughters.push_back(++motherPartIdx_);
603  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*wd));
605  if (std::abs(wd->pdgId()) == TopDecayID::tauID) {
606  // add tau daughters
607  // currently it adds k-mesons etc as well, which
608  // is not what we want.
610  }
611  }
612  }
613 
614  } else {
615  if (addRadiation_ && (td->pdgId() == TopDecayID::glueID || std::abs(td->pdgId()) < TopDecayID::bID)) {
616  // collect additional radiation from the top
617  std::unique_ptr<reco::GenParticle> radPtr(
618  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
619  target.push_back(*radPtr);
620  }
621  //other top daughters like Zq for FCNC
622  // for pythia 6 many gluons end up here
623  //std::cout << "other top daughters: to be implemented"
624  // << std::endl;
625  }
626  }
627 
628  // fill the map for the administration
629  // of daughter indices
630  refs_[iTop] = topDaughters;
631  refs_[iW] = wDaughters;
632  }
633 }
634 
636 reco::Particle::LorentzVector TopDecaySubset::p4(const std::vector<const reco::GenParticle*>::const_iterator top,
637  int statusFlag) {
638  // calculate the four vector for top/anti-top quarks from
639  // the W boson and the b quark plain or including all
640  // additional radiation depending on switch 'plain'
641  if (statusFlag == TopDecayID::unfrag) {
642  // return 4 momentum as it is
643  return (*top)->p4();
644  }
646  for (reco::GenParticle::const_iterator p = (*top)->begin(); p != (*top)->end(); ++p) {
647  if (p->status() == TopDecayID::unfrag) {
648  // descend by one level for each
649  // status 3 particle on the way
650  vec += p4(p, statusFlag);
651  } else {
652  if (std::abs((*top)->pdgId()) == TopDecayID::WID) {
653  // in case of a W boson skip the status
654  // 2 particle to prevent double counting
655  if (std::abs(p->pdgId()) != TopDecayID::WID)
656  vec += p->p4();
657  } else {
658  // add all four vectors for each stable
659  // particle (status 1 or 2) on the way
660  vec += p->p4();
661  if (vec.mass() - (*top)->mass() > 0) {
662  // continue adding up gluons and qqbar pairs on the top
663  // line untill the nominal top mass is reached; then
664  // break in order to prevent picking up virtualities
665  break;
666  }
667  }
668  }
669  }
670  return vec;
671 }
672 
675  // calculate the four vector for all top daughters from
676  // their daughters including additional radiation
677  if (statusFlag == TopDecayID::unfrag) {
678  // return 4 momentum as it is
679  return part->p4();
680  }
682  for (reco::GenParticle::const_iterator p = part->begin(); p != part->end(); ++p) {
683  if (p->status() <= TopDecayID::stable && std::abs(p->pdgId()) == TopDecayID::WID) {
684  vec = p->p4();
685  } else {
686  if (p->status() <= TopDecayID::stable) {
687  // sum up the p4 of all stable particles
688  // (of status 1 or 2)
689  vec += p->p4();
690  } else {
691  if (p->status() == TopDecayID::unfrag) {
692  // if the particle is unfragmented (i.e.
693  // status 3) descend by one level
694  vec += p4(p, statusFlag);
695  }
696  }
697  }
698  }
699  return vec;
700 }
701 
706  std::vector<int> daughters;
707  int idxBuffer = idx;
708  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
709  if (daughter->status() <= TopDecayID::stable && daughter->pdgId() != part->pdgId()) {
710  // skip comment lines and make sure that
711  // the particle is not double counted as
712  // daughter of itself
713  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
714  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
715  target.push_back(*ptr);
716  daughters.push_back(++idx); //push index of daughter
717  }
718  }
719  if (!daughters.empty()) {
720  refs_[idxBuffer] = daughters;
721  }
722 }
723 
725  std::vector<int> daughters;
726  int idxBuffer = idx;
727  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
728  // either pick daughters as long as they are different
729  // to the initial particle
730  if (daughter->pdgId() != part->pdgId()) {
731  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
732  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
733  target.push_back(*ptr);
734  daughters.push_back(++idx); //push index of daughter
735  }
736  }
737  if (!daughters.empty()) {
738  refs_[idxBuffer] = daughters;
739  }
740 }
741 
746  bool recursive) {
747  std::vector<int> daughters;
748  int idxBuffer = idx;
749  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
750  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
751  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
752  target.push_back(*ptr);
753  // increment & push index of daughter
754  daughters.push_back(++idx);
755  // continue recursively if desired
756  if (recursive) {
757  addDaughters(idx, daughter, target);
758  }
759  }
760  if (!daughters.empty()) {
761  refs_[idxBuffer] = daughters;
762  }
763 }
764 
767  // clear vector of references
768  refs_.clear();
769  // set idx for mother particles to a start value
770  // of -1 (the first entry will raise it to 0)
771  motherPartIdx_ = -1;
772 }
773 
776  int idx = 0;
777  for (reco::GenParticleCollection::iterator p = sel.begin(); p != sel.end(); ++p, ++idx) {
778  //find daughter reference vectors in refs_ and add daughters
779  std::map<int, std::vector<int> >::const_iterator daughters = refs_.find(idx);
780  if (daughters != refs_.end()) {
781  for (std::vector<int>::const_iterator daughter = daughters->second.begin(); daughter != daughters->second.end();
782  ++daughter) {
783  reco::GenParticle* part = dynamic_cast<reco::GenParticle*>(&(*p));
784  if (part == nullptr) {
785  throw edm::Exception(edm::errors::InvalidReference, "Not a GenParticle");
786  }
787  part->addDaughter(reco::GenParticleRef(ref, *daughter));
788  sel[*daughter].addMother(reco::GenParticleRef(ref, idx));
789  }
790  }
791  }
792 }
793 
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
void addDaughters(int &idx, const reco::GenParticle::const_iterator part, reco::GenParticleCollection &target, bool recursive=true)
recursively fill vector for all further decay particles of a given particle
std::map< int, std::vector< int > > refs_
management of daughter indices for fillRefs
ProductID id() const
Definition: HandleBase.cc:29
static const int bID
Definition: TopGenEvent.h:13
ShowerModel showerModel_
parton shower mode (filled in checkShowerModel)
static const int glueID
Definition: TopGenEvent.h:14
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void addRadiation(int &idx, const reco::GenParticle::const_iterator part, reco::GenParticleCollection &target)
fill vector including all radiations from quarks originating from W/top
static const int unfrag
Definition: TopGenEvent.h:11
RunMode
supported modes to run the code
virtual int status() const =0
status word
static const int stable
Definition: TopGenEvent.h:10
size_t numberOfDaughters() const override
number of daughters
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
std::vector< const reco::GenParticle * > findTops(const reco::GenParticleCollection &parts)
find top quarks in list of input particles
void clearReferences()
clear references
int pdgId() const final
PDG identifier.
static const int tID
Definition: TopGenEvent.h:12
static const int tauID
Definition: TopGenEvent.h:20
edm::EDGetTokenT< GenEventInfoProduct > genEventInfo_srcToken_
input tag for the genEventInfo source
void fillListing(const std::vector< const reco::GenParticle *> &tops, reco::GenParticleCollection &target)
fill output vector for full decay chain
virtual size_type numberOfDaughters() const =0
number of daughters
ShowerModel checkShowerModel(const std::vector< const reco::GenParticle *> &tops) const
check the decay chain for the used shower model
reco::Particle::LorentzVector p4(const std::vector< const reco::GenParticle *>::const_iterator top, int statusFlag)
calculate lorentz vector from input (dedicated to top reconstruction)
void checkWBosons(std::vector< const reco::GenParticle *> &tops) const
check whether W bosons are contained in the original gen particle listing
const_iterator end() const
last daughter const_iterator
Definition: Candidate.h:145
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool addRadiation_
add radiation or not?
ShowerModel
classification of potential shower types
void produce(edm::Event &event, const edm::EventSetup &setup) override
write output into the event
std::vector< const reco::GenParticle * > findDecayingTops(const reco::GenParticleCollection &parts)
edm::EDGetTokenT< reco::GenParticleCollection > srcToken_
input tag for the genParticle source
void fillReferences(const reco::GenParticleRefProd &refProd, reco::GenParticleCollection &target)
fill references for output vector
virtual int pdgId() const =0
PDG identifier.
Log< level::Info, false > LogInfo
std::vector< const reco::GenParticle * > findPrimalTops(const reco::GenParticleCollection &parts)
part
Definition: HCALResponse.h:20
TopDecaySubset(const edm::ParameterSet &cfg)
default constructor
RunMode runMode_
run mode (Run1 || Run2)
static const int WID
Definition: TopGenEvent.h:17
bool isValid() const
Definition: HandleBase.h:70
std::string moduleName(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:27
fixed size matrix
HLT enums.
Module to produce the subset of generator particles directly contained in top decay chains...
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
def move(src, dest)
Definition: eostools.py:511
const Candidate * daughter(size_type) const override
return daughter at a given position, i = 0, ... numberOfDaughters() - 1 (read only mode) ...
Definition: event.py:1
const reco::GenParticle * findPrimalW(const reco::GenParticle *top)
const_iterator begin() const
first daughter const_iterator
Definition: Candidate.h:143
const reco::GenParticle * findLastParticleInChain(const reco::GenParticle *p)