CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TopDecaySubset.cc
Go to the documentation of this file.
3 
6 
8 
11  : srcToken_(consumes<reco::GenParticleCollection>(cfg.getParameter<edm::InputTag>("src"))),
12  genEventInfo_srcToken_(mayConsume<GenEventInfoProduct>(edm::InputTag("generator"))),
13  addRadiation_(cfg.getParameter<bool>("addRadiation")),
14  showerModel_(kStart),
15  runMode_(kRun1) {
16  // mapping of the corresponding fillMode; see FillMode
17  // enumerator of TopDecaySubset for available modes
18  std::string mode = cfg.getParameter<std::string>("fillMode");
19  if (mode == "kME")
20  fillMode_ = kME;
21  else if (mode == "kStable")
23  else
24  throw cms::Exception("Configuration") << mode << " is not a supported FillMode!\n";
25 
26  mode = cfg.getParameter<std::string>("runMode");
27  if (mode == "Run1")
28  runMode_ = kRun1;
29  else if (mode == "Run2")
30  runMode_ = kRun2;
31  else
32  throw cms::Exception("Configuration") << mode << " is not a supported RunMode!\n";
33 
34  // produces a set of GenParticles following
35  // the decay branch of top quarks to the first level of
36  // stable decay products
37  produces<reco::GenParticleCollection>();
38 }
39 
42 
45  // create target vector
46  std::unique_ptr<reco::GenParticleCollection> target(new reco::GenParticleCollection);
47 
48  // get source collection
50  event.getByToken(srcToken_, src);
51 
52  // find out what generator we are dealing with
53  if (showerModel_ == kStart && runMode_ == kRun2) {
55  }
56 
57  // find top quarks in list of input particles
58  std::vector<const reco::GenParticle*> tops;
59  if (runMode_ == kRun1)
60  tops = findTops(*src);
61  else
62  tops = findPrimalTops(*src);
63 
64  // determine shower model (only in first event)
65  if (showerModel_ == kStart && runMode_ == kRun1)
67 
68  if (showerModel_ != kNone) {
69  // check sanity of W bosons
70  if (runMode_ == kRun1)
71  checkWBosons(tops);
72  else {
73  // nothing for the moment
74  }
75 
76  // get ref product from the event
77  const reco::GenParticleRefProd ref = event.getRefBeforePut<reco::GenParticleCollection>();
78  // clear existing refs
80  if (runMode_ == kRun1) {
81  // fill output
82  fillListing(tops, *target);
83  // fill references
84  fillReferences(ref, *target);
85  } else {
86  std::vector<const reco::GenParticle*> decaying_tops = findDecayingTops(*src);
87  // fill output
88  fillListing(tops, decaying_tops, *target);
89  // fill references
90  fillReferences(ref, *target);
91  }
92  }
93 
94  // write vectors to the event
95  event.put(std::move(target));
96 }
97 
99 std::vector<const reco::GenParticle*> TopDecaySubset::findTops(const reco::GenParticleCollection& parts) {
100  std::vector<const reco::GenParticle*> tops;
101  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
102  if (std::abs(t->pdgId()) == TopDecayID::tID && t->status() == TopDecayID::unfrag)
103  tops.push_back(&(*t));
104  }
105  return tops;
106 }
107 
110 std::vector<const reco::GenParticle*> TopDecaySubset::findPrimalTops(const reco::GenParticleCollection& parts) {
111  std::vector<const reco::GenParticle*> tops;
112  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
113  if (std::abs(t->pdgId()) != TopDecayID::tID)
114  continue;
115 
116  bool hasTopMother = false;
117  for (unsigned idx = 0; idx < t->numberOfMothers(); ++idx) {
118  if (std::abs(t->mother(idx)->pdgId()) == TopDecayID::tID)
119  hasTopMother = true;
120  }
121 
122  if (hasTopMother) // not a primal top
123  continue;
124  tops.push_back(&(*t));
125  }
126 
127  return tops;
128 }
129 
132 std::vector<const reco::GenParticle*> TopDecaySubset::findDecayingTops(const reco::GenParticleCollection& parts) {
133  std::vector<const reco::GenParticle*> tops;
134  for (reco::GenParticleCollection::const_iterator t = parts.begin(); t != parts.end(); ++t) {
135  if (std::abs(t->pdgId()) != TopDecayID::tID)
136  continue;
137 
138  bool hasTopDaughter = false;
139  for (unsigned idx = 0; idx < t->numberOfDaughters(); ++idx) {
140  if (std::abs(t->daughter(idx)->pdgId()) == TopDecayID::tID)
141  hasTopDaughter = true;
142  }
143 
144  if (hasTopDaughter) // not a decaying top
145  continue;
146  tops.push_back(&(*t));
147  }
148 
149  return tops;
150 }
151 
155  unsigned int w_index = 0;
156  for (unsigned idx = 0; idx < top->numberOfDaughters(); ++idx) {
157  if (std::abs(top->daughter(idx)->pdgId()) == TopDecayID::WID) {
158  w_index = idx;
159  break;
160  }
161  }
162  return static_cast<const reco::GenParticle*>(top->daughter(w_index));
163 }
164 
167 //const reco::GenParticle* TopDecaySubset::findDecayingW(
168 // const reco::GenParticle* top) {
169 // const reco::GenParticle* decaying_W = findLastParticleInChain(findPrimalW(top));
170 // return findLastParticleInChain(findPrimalW(top));
171 //}
172 
178  int particleID = std::abs(p->pdgId());
179  bool containsItself = false;
180  unsigned int d_idx = 0;
181  for (unsigned idx = 0; idx < p->numberOfDaughters(); ++idx) {
182  if (std::abs(p->daughter(idx)->pdgId()) == particleID) {
183  containsItself = true;
184  d_idx = idx;
185  }
186  }
187 
188  if (!containsItself)
189  return p;
190  else {
191  if (showerModel_ == kPythia) {
192  // Pythia6 has a weird idea of W bosons (and maybe other particles)
193  // W (status == 3) -> q qbar' W. The new W is status 2 and has no daughters
194  if (p->status() == 3)
195  return p;
196  }
197  return findLastParticleInChain(static_cast<const reco::GenParticle*>(p->daughter(d_idx)));
198  }
199 }
200 
202 TopDecaySubset::ShowerModel TopDecaySubset::checkShowerModel(const std::vector<const reco::GenParticle*>& tops) const {
203  for (std::vector<const reco::GenParticle*>::const_iterator it = tops.begin(); it != tops.end(); ++it) {
204  const reco::GenParticle* top = *it;
205  // check for kHerwig type showers: here the status 3 top quark will
206  // have a single status 2 top quark as daughter, which has again 3
207  // or more status 2 daughters
208  if (top->numberOfDaughters() == 1) {
209  if (top->begin()->pdgId() == top->pdgId() && top->begin()->status() == TopDecayID::stable &&
210  top->begin()->numberOfDaughters() > 1)
211  return kHerwig;
212  }
213  // check for kPythia type showers: here the status 3 top quark will
214  // have all decay products and a status 2 top quark as daughters
215  // the status 2 top quark will be w/o further daughters
216  if (top->numberOfDaughters() > 1) {
217  bool containsWBoson = false, containsQuarkDaughter = false;
218  for (reco::GenParticle::const_iterator td = top->begin(); td != top->end(); ++td) {
219  if (std::abs(td->pdgId()) < TopDecayID::tID)
220  containsQuarkDaughter = true;
221  if (std::abs(td->pdgId()) == TopDecayID::WID)
222  containsWBoson = true;
223  }
224  if (containsQuarkDaughter && containsWBoson)
225  return kPythia;
226  }
227  }
228  // if neither Herwig nor Pythia like
229  if (tops.empty())
230  edm::LogInfo("decayChain") << " Failed to find top quarks in decay chain. Will assume that this a \n"
231  << " non-top sample and produce an empty decaySubset.\n";
232  else
234  " Can not find back any of the supported hadronization models. Models \n"
235  " which are supported are: \n"
236  " Pythia LO(+PS): Top(status 3) --> WBoson(status 3), Quark(status 3)\n"
237  " Herwig NLO(+PS): Top(status 2) --> Top(status 3) --> Top(status 2) \n");
238  return kNone;
239 }
240 
243  edm::Handle<GenEventInfoProduct> genEvtInfoProduct;
244  event.getByToken(genEventInfo_srcToken_, genEvtInfoProduct);
245 
246  std::string moduleName = "";
247  if (genEvtInfoProduct.isValid()) {
248  const edm::StableProvenance& prov = event.getStableProvenance(genEvtInfoProduct.id());
249  moduleName = edm::moduleName(prov, event.processHistory());
250  if (moduleName == "ExternalGeneratorFilter") {
251  moduleName = edm::parameterSet(prov, event.processHistory()).getParameter<std::string>("@external_type");
252  edm::LogInfo("SpecialModule") << "GEN events are produced by ExternalGeneratorFilter, "
253  << "which is a wrapper of the original module: " << moduleName;
254  }
255  }
256 
257  ShowerModel shower(kStart);
258  if (moduleName.find("Pythia6") != std::string::npos)
259  shower = kPythia;
260  else if (moduleName.find("Pythia8") != std::string::npos)
261  shower = kPythia8;
262  else if (moduleName.find("Herwig6") != std::string::npos)
263  shower = kHerwig;
264  else if (moduleName.find("ThePEG") != std::string::npos)
265  // Herwig++
266  shower = kHerwig;
267  else if (moduleName.find("Sherpa") != std::string::npos)
268  shower = kSherpa;
269  else
270  shower = kNone;
271  return shower;
272 }
274 void TopDecaySubset::checkWBosons(std::vector<const reco::GenParticle*>& tops) const {
275  unsigned nTops = tops.size();
276  for (std::vector<const reco::GenParticle*>::iterator it = tops.begin(); it != tops.end();) {
277  const reco::GenParticle* top = *it;
278  bool isContained = false;
279  bool expectedStatus = false;
280  if (showerModel_ != kPythia && top->begin() == top->end())
281  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && top->begin()==top->end()\n");
282  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? top->begin() : top->begin()->begin());
283  td != ((showerModel_ == kPythia) ? top->end() : top->begin()->end());
284  ++td) {
285  if (std::abs(td->pdgId()) == TopDecayID::WID) {
286  isContained = true;
287  if (((showerModel_ == kPythia) ? td->status() == TopDecayID::unfrag : td->status() == TopDecayID::stable)) {
288  expectedStatus = true;
289  break;
290  }
291  }
292  }
293  if (!expectedStatus) {
294  it = tops.erase(it);
295  if (isContained)
296  edm::LogInfo("decayChain") << " W boson does not have the expected status. This happens, e.g., \n"
297  << " with MC@NLO in the case of additional ttbar pairs from radiated \n"
298  << " gluons. We hope everything is fine, remove the correspdonding top \n"
299  << " quark from our list since it is not part of the primary ttbar pair \n"
300  << " and try to continue. \n";
301  } else
302  it++;
303  }
304  if (tops.empty() && nTops != 0)
306  " Did not find a W boson with appropriate status for any of the top \n"
307  " quarks in this event. This means that the hadronization of the W \n"
308  " boson might be screwed up or there is another problem with the \n"
309  " particle listing in this MC sample. Please contact an expert. \n");
310 }
311 
313 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& tops,
315  unsigned int statusFlag;
316  // determine status flag of the new
317  // particle depending on the FillMode
318  fillMode_ == kME ? statusFlag = 3 : statusFlag = 2;
319 
320  for (std::vector<const reco::GenParticle*>::const_iterator it = tops.begin(); it != tops.end(); ++it) {
321  const reco::GenParticle* t = *it;
322  // if particle is top or anti-top
323  std::unique_ptr<reco::GenParticle> topPtr(
324  new reco::GenParticle(t->threeCharge(), p4(it, statusFlag), t->vertex(), t->pdgId(), statusFlag, false));
325  target.push_back(*topPtr);
326  ++motherPartIdx_;
327  // keep the top index for the map to manage the daughter refs
328  int iTop = motherPartIdx_;
329  std::vector<int> topDaughters;
330  // define the W boson index (to be set later) for the map to
331  // manage the daughter refs
332  int iW = 0;
333  std::vector<int> wDaughters;
334  // sanity check
335  if (showerModel_ != kPythia && t->begin() == t->end())
336  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && t->begin()==t->end()\n");
337  //iterate over top daughters
338  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? t->begin() : t->begin()->begin());
339  td != ((showerModel_ == kPythia) ? t->end() : t->begin()->end());
340  ++td) {
341  if (td->status() == TopDecayID::unfrag && std::abs(td->pdgId()) <= TopDecayID::bID) {
342  // if particle is beauty or other quark
343  std::unique_ptr<reco::GenParticle> bPtr(
344  new reco::GenParticle(td->threeCharge(), p4(td, statusFlag), td->vertex(), td->pdgId(), statusFlag, false));
345  target.push_back(*bPtr);
346  // increment & push index of the top daughter
347  topDaughters.push_back(++motherPartIdx_);
348  if (addRadiation_) {
349  addRadiation(motherPartIdx_, td, target);
350  }
351  }
352  // sanity check
353  if (showerModel_ != kPythia && td->begin() == td->end())
354  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && td->begin()==td->end()\n");
356  if (buffer->status() == TopDecayID::unfrag && std::abs(buffer->pdgId()) == TopDecayID::WID) {
357  // if particle is a W boson
358  std::unique_ptr<reco::GenParticle> wPtr(new reco::GenParticle(
359  buffer->threeCharge(), p4(buffer, statusFlag), buffer->vertex(), buffer->pdgId(), statusFlag, true));
360  target.push_back(*wPtr);
361  // increment & push index of the top daughter
362  topDaughters.push_back(++motherPartIdx_);
363  // keep the W idx for the map
364  iW = motherPartIdx_;
365  if (addRadiation_) {
366  addRadiation(motherPartIdx_, buffer, target);
367  }
368  if (showerModel_ != kPythia && buffer->begin() == buffer->end())
369  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && buffer->begin()==buffer->end()\n");
370  // iterate over W daughters
372  ((showerModel_ == kPythia) ? buffer->begin() : buffer->begin()->begin());
373  wd != ((showerModel_ == kPythia) ? buffer->end() : buffer->begin()->end());
374  ++wd) {
375  // make sure the W daughter is of status unfrag and not the W itself
376  if (wd->status() == TopDecayID::unfrag && !(std::abs(wd->pdgId()) == TopDecayID::WID)) {
377  std::unique_ptr<reco::GenParticle> qPtr(new reco::GenParticle(
378  wd->threeCharge(), p4(wd, statusFlag), wd->vertex(), wd->pdgId(), statusFlag, false));
379  target.push_back(*qPtr);
380  // increment & push index of the top daughter
381  wDaughters.push_back(++motherPartIdx_);
382  if (wd->status() == TopDecayID::unfrag && std::abs(wd->pdgId()) == TopDecayID::tauID) {
383  // add tau daughters if the particle is a tau pass
384  // the daughter of the tau which is of status 2
385  //addDaughters(motherPartIdx_, wd->begin(), target);
386  // add tau daughters if the particle is a tau pass
387  // the tau itself, which may add a tau daughter of
388  // of status 2 to the listing
389  addDaughters(motherPartIdx_, wd, target);
390  }
391  }
392  }
393  }
394  if (addRadiation_ && buffer->status() == TopDecayID::stable &&
395  (buffer->pdgId() == TopDecayID::glueID || std::abs(buffer->pdgId()) < TopDecayID::bID)) {
396  // collect additional radiation from the top
397  std::unique_ptr<reco::GenParticle> radPtr(new reco::GenParticle(
398  buffer->threeCharge(), buffer->p4(), buffer->vertex(), buffer->pdgId(), statusFlag, false));
399  target.push_back(*radPtr);
400  // increment & push index of the top daughter
401  topDaughters.push_back(++motherPartIdx_);
402  }
403  }
404  // add potential sisters of the top quark;
405  // only for top to prevent double counting
406  if (t->numberOfMothers() > 0 && t->pdgId() == TopDecayID::tID) {
407  for (reco::GenParticle::const_iterator ts = t->mother()->begin(); ts != t->mother()->end(); ++ts) {
408  // loop over all daughters of the top mother i.e.
409  // the two top quarks and their potential sisters
410  if (std::abs(ts->pdgId()) != t->pdgId() && ts->pdgId() != t->mother()->pdgId()) {
411  // add all further particles but the two top quarks and potential
412  // cases where the mother of the top has itself as daughter
413  reco::GenParticle* cand =
414  new reco::GenParticle(ts->threeCharge(), ts->p4(), ts->vertex(), ts->pdgId(), ts->status(), false);
415  std::unique_ptr<reco::GenParticle> sPtr(cand);
416  target.push_back(*sPtr);
417  if (ts->begin() != ts->end()) {
418  // in case the sister has daughters increment
419  // and add the first generation of daughters
420  addDaughters(++motherPartIdx_, ts->begin(), target, false);
421  }
422  }
423  }
424  }
425  // fill the map for the administration
426  // of daughter indices
427  refs_[iTop] = topDaughters;
428  refs_[iW] = wDaughters;
429  }
430 }
431 
432 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& primalTops,
433  const std::vector<const reco::GenParticle*>& decayingTops,
435  std::vector<const reco::GenParticle*>::const_iterator top_start;
436  std::vector<const reco::GenParticle*>::const_iterator top_end;
437  if (fillMode_ == kME) {
438  top_start = primalTops.begin();
439  top_end = primalTops.end();
440  } else {
441  top_start = decayingTops.begin();
442  top_end = decayingTops.end();
443  }
444  for (std::vector<const reco::GenParticle*>::const_iterator it = top_start; it != top_end; ++it) {
445  const reco::GenParticle* t = *it;
446  // summation might happen here
447  std::unique_ptr<reco::GenParticle> topPtr(
448  new reco::GenParticle(t->threeCharge(), t->p4(), t->vertex(), t->pdgId(), t->status(), false));
449  target.push_back(*topPtr);
450  ++motherPartIdx_;
451 
452  // keep the top index for the map to manage the daughter refs
453  int iTop = motherPartIdx_;
454  std::vector<int> topDaughters;
455  // define the W boson index (to be set later) for the map to
456  // manage the daughter refs
457  int iW = 0;
458  std::vector<int> wDaughters;
459  const reco::GenParticle* final_top = findLastParticleInChain(t);
460 
461  //iterate over top daughters
462  for (reco::GenParticle::const_iterator td = final_top->begin(); td != final_top->end(); ++td) {
463  if (std::abs(td->pdgId()) <= TopDecayID::bID) {
464  // if particle is beauty or other quark
465  std::unique_ptr<reco::GenParticle> qPtr(
466  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
467  target.push_back(*qPtr);
468  // increment & push index of the top daughter
469  topDaughters.push_back(++motherPartIdx_);
470  if (addRadiation_) {
471  // for radation to be added we first need to
472  // pick the last quark in the MC chain
473  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
474  addRadiation(motherPartIdx_, last_q, target);
475  }
476  } else if (std::abs(td->pdgId()) == TopDecayID::WID) {
477  // ladies and gentleman, we have a W boson
478  std::unique_ptr<reco::GenParticle> WPtr(
479  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
480  target.push_back(*WPtr);
481  // increment & push index of the top daughter
482  topDaughters.push_back(++motherPartIdx_);
483  iW = motherPartIdx_;
484 
485  // next are the daughers of our W boson
486  // for Pythia 6 this is wrong as the last W has no daughters at all!
487  // instead the status 3 W has 3 daughters: q qbar' and W (WTF??!)
488  const reco::GenParticle* decaying_W = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
489  for (reco::GenParticle::const_iterator wd = decaying_W->begin(); wd != decaying_W->end(); ++wd) {
490  if (!(std::abs(wd->pdgId()) == TopDecayID::WID)) {
491  std::unique_ptr<reco::GenParticle> qPtr(
492  new reco::GenParticle(wd->threeCharge(), wd->p4(), wd->vertex(), wd->pdgId(), wd->status(), false));
493  target.push_back(*qPtr);
494  // increment & push index of the top daughter
495  wDaughters.push_back(++motherPartIdx_);
496  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*wd));
497  addRadiation(motherPartIdx_, last_q, target);
498  if (std::abs(wd->pdgId()) == TopDecayID::tauID) {
499  // add tau daughters
500  // currently it adds k-mesons etc as well, which
501  // is not what we want.
502  addDaughters(motherPartIdx_, wd, target);
503  }
504  }
505  }
506 
507  } else {
508  if (addRadiation_ && (td->pdgId() == TopDecayID::glueID || std::abs(td->pdgId()) < TopDecayID::bID)) {
509  // collect additional radiation from the top
510  std::unique_ptr<reco::GenParticle> radPtr(
511  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
512  target.push_back(*radPtr);
513  }
514  //other top daughters like Zq for FCNC
515  // for pythia 6 many gluons end up here
516  //std::cout << "other top daughters: to be implemented"
517  // << std::endl;
518  }
519  }
520 
521  // fill the map for the administration
522  // of daughter indices
523  refs_[iTop] = topDaughters;
524  refs_[iW] = wDaughters;
525  }
526 }
527 
529 reco::Particle::LorentzVector TopDecaySubset::p4(const std::vector<const reco::GenParticle*>::const_iterator top,
530  int statusFlag) {
531  // calculate the four vector for top/anti-top quarks from
532  // the W boson and the b quark plain or including all
533  // additional radiation depending on switch 'plain'
534  if (statusFlag == TopDecayID::unfrag) {
535  // return 4 momentum as it is
536  return (*top)->p4();
537  }
539  for (reco::GenParticle::const_iterator p = (*top)->begin(); p != (*top)->end(); ++p) {
540  if (p->status() == TopDecayID::unfrag) {
541  // descend by one level for each
542  // status 3 particle on the way
543  vec += p4(p, statusFlag);
544  } else {
545  if (std::abs((*top)->pdgId()) == TopDecayID::WID) {
546  // in case of a W boson skip the status
547  // 2 particle to prevent double counting
548  if (std::abs(p->pdgId()) != TopDecayID::WID)
549  vec += p->p4();
550  } else {
551  // add all four vectors for each stable
552  // particle (status 1 or 2) on the way
553  vec += p->p4();
554  if (vec.mass() - (*top)->mass() > 0) {
555  // continue adding up gluons and qqbar pairs on the top
556  // line untill the nominal top mass is reached; then
557  // break in order to prevent picking up virtualities
558  break;
559  }
560  }
561  }
562  }
563  return vec;
564 }
565 
568  // calculate the four vector for all top daughters from
569  // their daughters including additional radiation
570  if (statusFlag == TopDecayID::unfrag) {
571  // return 4 momentum as it is
572  return part->p4();
573  }
575  for (reco::GenParticle::const_iterator p = part->begin(); p != part->end(); ++p) {
576  if (p->status() <= TopDecayID::stable && std::abs(p->pdgId()) == TopDecayID::WID) {
577  vec = p->p4();
578  } else {
579  if (p->status() <= TopDecayID::stable) {
580  // sum up the p4 of all stable particles
581  // (of status 1 or 2)
582  vec += p->p4();
583  } else {
584  if (p->status() == TopDecayID::unfrag) {
585  // if the particle is unfragmented (i.e.
586  // status 3) descend by one level
587  vec += p4(p, statusFlag);
588  }
589  }
590  }
591  }
592  return vec;
593 }
594 
599  std::vector<int> daughters;
600  int idxBuffer = idx;
601  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
602  if (daughter->status() <= TopDecayID::stable && daughter->pdgId() != part->pdgId()) {
603  // skip comment lines and make sure that
604  // the particle is not double counted as
605  // daughter of itself
606  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
607  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
608  target.push_back(*ptr);
609  daughters.push_back(++idx); //push index of daughter
610  }
611  }
612  if (!daughters.empty()) {
613  refs_[idxBuffer] = daughters;
614  }
615 }
616 
618  std::vector<int> daughters;
619  int idxBuffer = idx;
620  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
621  // either pick daughters as long as they are different
622  // to the initial particle
623  if (daughter->pdgId() != part->pdgId()) {
624  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
625  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
626  target.push_back(*ptr);
627  daughters.push_back(++idx); //push index of daughter
628  }
629  }
630  if (!daughters.empty()) {
631  refs_[idxBuffer] = daughters;
632  }
633 }
634 
639  bool recursive) {
640  std::vector<int> daughters;
641  int idxBuffer = idx;
642  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
643  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
644  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
645  target.push_back(*ptr);
646  // increment & push index of daughter
647  daughters.push_back(++idx);
648  // continue recursively if desired
649  if (recursive) {
650  addDaughters(idx, daughter, target);
651  }
652  }
653  if (!daughters.empty()) {
654  refs_[idxBuffer] = daughters;
655  }
656 }
657 
660  // clear vector of references
661  refs_.clear();
662  // set idx for mother particles to a start value
663  // of -1 (the first entry will raise it to 0)
664  motherPartIdx_ = -1;
665 }
666 
669  int idx = 0;
670  for (reco::GenParticleCollection::iterator p = sel.begin(); p != sel.end(); ++p, ++idx) {
671  //find daughter reference vectors in refs_ and add daughters
672  std::map<int, std::vector<int> >::const_iterator daughters = refs_.find(idx);
673  if (daughters != refs_.end()) {
674  for (std::vector<int>::const_iterator daughter = daughters->second.begin(); daughter != daughters->second.end();
675  ++daughter) {
676  reco::GenParticle* part = dynamic_cast<reco::GenParticle*>(&(*p));
677  if (part == nullptr) {
678  throw edm::Exception(edm::errors::InvalidReference, "Not a GenParticle");
679  }
680  part->addDaughter(reco::GenParticleRef(ref, *daughter));
681  sel[*daughter].addMother(reco::GenParticleRef(ref, idx));
682  }
683  }
684  }
685 }
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
const Candidate * mother(size_type=0) const override
return mother at a given position, i = 0, ... numberOfMothers() - 1 (read only mode) ...
tuple cfg
Definition: looper.py:296
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
static const int bID
Definition: TopGenEvent.h:13
ShowerModel checkShowerModel(const std::vector< const reco::GenParticle * > &tops) const
check the decay chain for the used shower model
ShowerModel showerModel_
parton shower mode (filled in checkShowerModel)
ProductID id() const
Definition: HandleBase.cc:29
static const int glueID
Definition: TopGenEvent.h:14
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
virtual int threeCharge() const =0
electric charge
virtual int status() const =0
status word
static const int stable
Definition: TopGenEvent.h:10
size_t numberOfDaughters() const override
number of daughters
int status() const final
status word
const Point & vertex() const override
vertex position (overwritten by PF...)
size_t numberOfMothers() const override
number of mothers
std::vector< const reco::GenParticle * > findTops(const reco::GenParticleCollection &parts)
find top quarks in list of input particles
const LorentzVector & p4() const final
four-momentum Lorentz vector
void addDaughter(const typename daughters::value_type &)
add a daughter via a reference
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
virtual size_type numberOfDaughters() const =0
number of daughters
int threeCharge() const final
electric charge
~TopDecaySubset() override
default destructor
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
const_iterator end() const
last daughter const_iterator
Definition: Candidate.h:145
def move
Definition: eostools.py:511
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
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool addRadiation_
add radiation or not?
ShowerModel
classification of potential shower types
virtual const Point & vertex() const =0
vertex position
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
bool isValid() const
Definition: HandleBase.h:70
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)
ProcessHistory const & processHistory() const override
Definition: Event.cc:250
part
Definition: HCALResponse.h:20
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
TopDecaySubset(const edm::ParameterSet &cfg)
default constructor
RunMode runMode_
run mode (Run1 || Run2)
static const int WID
Definition: TopGenEvent.h:17
void fillListing(const std::vector< const reco::GenParticle * > &tops, reco::GenParticleCollection &target)
fill output vector for full decay chain
FillMode fillMode_
std::string moduleName(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:27
const_iterator begin() const
first daughter const_iterator
Definition: Candidate.h:143
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
const Candidate * daughter(size_type) const override
return daughter at a given position, i = 0, ... numberOfDaughters() - 1 (read only mode) ...
const reco::GenParticle * findPrimalW(const reco::GenParticle *top)
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
const reco::GenParticle * findLastParticleInChain(const reco::GenParticle *p)