CMS 3D CMS Logo

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::Provenance& prov = event.getProvenance(genEvtInfoProduct.id());
249  moduleName = edm::moduleName(prov);
250  }
251 
252  ShowerModel shower(kStart);
253  if (moduleName.find("Pythia6") != std::string::npos)
254  shower = kPythia;
255  else if (moduleName.find("Pythia8") != std::string::npos)
256  shower = kPythia8;
257  else if (moduleName.find("Herwig6") != std::string::npos)
258  shower = kHerwig;
259  else if (moduleName.find("ThePEG") != std::string::npos)
260  // Herwig++
261  shower = kHerwig;
262  else if (moduleName.find("Sherpa") != std::string::npos)
263  shower = kSherpa;
264  else
265  shower = kNone;
266  return shower;
267 }
269 void TopDecaySubset::checkWBosons(std::vector<const reco::GenParticle*>& tops) const {
270  unsigned nTops = tops.size();
271  for (std::vector<const reco::GenParticle*>::iterator it = tops.begin(); it != tops.end();) {
272  const reco::GenParticle* top = *it;
273  bool isContained = false;
274  bool expectedStatus = false;
275  if (showerModel_ != kPythia && top->begin() == top->end())
276  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && top->begin()==top->end()\n");
277  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? top->begin() : top->begin()->begin());
278  td != ((showerModel_ == kPythia) ? top->end() : top->begin()->end());
279  ++td) {
280  if (std::abs(td->pdgId()) == TopDecayID::WID) {
281  isContained = true;
282  if (((showerModel_ == kPythia) ? td->status() == TopDecayID::unfrag : td->status() == TopDecayID::stable)) {
283  expectedStatus = true;
284  break;
285  }
286  }
287  }
288  if (!expectedStatus) {
289  it = tops.erase(it);
290  if (isContained)
291  edm::LogInfo("decayChain") << " W boson does not have the expected status. This happens, e.g., \n"
292  << " with MC@NLO in the case of additional ttbar pairs from radiated \n"
293  << " gluons. We hope everything is fine, remove the correspdonding top \n"
294  << " quark from our list since it is not part of the primary ttbar pair \n"
295  << " and try to continue. \n";
296  } else
297  it++;
298  }
299  if (tops.empty() && nTops != 0)
301  " Did not find a W boson with appropriate status for any of the top \n"
302  " quarks in this event. This means that the hadronization of the W \n"
303  " boson might be screwed up or there is another problem with the \n"
304  " particle listing in this MC sample. Please contact an expert. \n");
305 }
306 
308 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& tops,
310  unsigned int statusFlag;
311  // determine status flag of the new
312  // particle depending on the FillMode
313  fillMode_ == kME ? statusFlag = 3 : statusFlag = 2;
314 
315  for (std::vector<const reco::GenParticle*>::const_iterator it = tops.begin(); it != tops.end(); ++it) {
316  const reco::GenParticle* t = *it;
317  // if particle is top or anti-top
318  std::unique_ptr<reco::GenParticle> topPtr(
319  new reco::GenParticle(t->threeCharge(), p4(it, statusFlag), t->vertex(), t->pdgId(), statusFlag, false));
320  target.push_back(*topPtr);
321  ++motherPartIdx_;
322  // keep the top index for the map to manage the daughter refs
323  int iTop = motherPartIdx_;
324  std::vector<int> topDaughters;
325  // define the W boson index (to be set later) for the map to
326  // manage the daughter refs
327  int iW = 0;
328  std::vector<int> wDaughters;
329  // sanity check
330  if (showerModel_ != kPythia && t->begin() == t->end())
331  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && t->begin()==t->end()\n");
332  //iterate over top daughters
333  for (reco::GenParticle::const_iterator td = ((showerModel_ == kPythia) ? t->begin() : t->begin()->begin());
334  td != ((showerModel_ == kPythia) ? t->end() : t->begin()->end());
335  ++td) {
336  if (td->status() == TopDecayID::unfrag && std::abs(td->pdgId()) <= TopDecayID::bID) {
337  // if particle is beauty or other quark
338  std::unique_ptr<reco::GenParticle> bPtr(
339  new reco::GenParticle(td->threeCharge(), p4(td, statusFlag), td->vertex(), td->pdgId(), statusFlag, false));
340  target.push_back(*bPtr);
341  // increment & push index of the top daughter
342  topDaughters.push_back(++motherPartIdx_);
343  if (addRadiation_) {
344  addRadiation(motherPartIdx_, td, target);
345  }
346  }
347  // sanity check
348  if (showerModel_ != kPythia && td->begin() == td->end())
349  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && td->begin()==td->end()\n");
351  if (buffer->status() == TopDecayID::unfrag && std::abs(buffer->pdgId()) == TopDecayID::WID) {
352  // if particle is a W boson
353  std::unique_ptr<reco::GenParticle> wPtr(new reco::GenParticle(
354  buffer->threeCharge(), p4(buffer, statusFlag), buffer->vertex(), buffer->pdgId(), statusFlag, true));
355  target.push_back(*wPtr);
356  // increment & push index of the top daughter
357  topDaughters.push_back(++motherPartIdx_);
358  // keep the W idx for the map
359  iW = motherPartIdx_;
360  if (addRadiation_) {
361  addRadiation(motherPartIdx_, buffer, target);
362  }
363  if (showerModel_ != kPythia && buffer->begin() == buffer->end())
364  throw edm::Exception(edm::errors::LogicError, "showerModel_!=kPythia && buffer->begin()==buffer->end()\n");
365  // iterate over W daughters
367  ((showerModel_ == kPythia) ? buffer->begin() : buffer->begin()->begin());
368  wd != ((showerModel_ == kPythia) ? buffer->end() : buffer->begin()->end());
369  ++wd) {
370  // make sure the W daughter is of status unfrag and not the W itself
371  if (wd->status() == TopDecayID::unfrag && !(std::abs(wd->pdgId()) == TopDecayID::WID)) {
372  std::unique_ptr<reco::GenParticle> qPtr(new reco::GenParticle(
373  wd->threeCharge(), p4(wd, statusFlag), wd->vertex(), wd->pdgId(), statusFlag, false));
374  target.push_back(*qPtr);
375  // increment & push index of the top daughter
376  wDaughters.push_back(++motherPartIdx_);
377  if (wd->status() == TopDecayID::unfrag && std::abs(wd->pdgId()) == TopDecayID::tauID) {
378  // add tau daughters if the particle is a tau pass
379  // the daughter of the tau which is of status 2
380  //addDaughters(motherPartIdx_, wd->begin(), target);
381  // add tau daughters if the particle is a tau pass
382  // the tau itself, which may add a tau daughter of
383  // of status 2 to the listing
384  addDaughters(motherPartIdx_, wd, target);
385  }
386  }
387  }
388  }
389  if (addRadiation_ && buffer->status() == TopDecayID::stable &&
390  (buffer->pdgId() == TopDecayID::glueID || std::abs(buffer->pdgId()) < TopDecayID::bID)) {
391  // collect additional radiation from the top
392  std::unique_ptr<reco::GenParticle> radPtr(new reco::GenParticle(
393  buffer->threeCharge(), buffer->p4(), buffer->vertex(), buffer->pdgId(), statusFlag, false));
394  target.push_back(*radPtr);
395  // increment & push index of the top daughter
396  topDaughters.push_back(++motherPartIdx_);
397  }
398  }
399  // add potential sisters of the top quark;
400  // only for top to prevent double counting
401  if (t->numberOfMothers() > 0 && t->pdgId() == TopDecayID::tID) {
402  for (reco::GenParticle::const_iterator ts = t->mother()->begin(); ts != t->mother()->end(); ++ts) {
403  // loop over all daughters of the top mother i.e.
404  // the two top quarks and their potential sisters
405  if (std::abs(ts->pdgId()) != t->pdgId() && ts->pdgId() != t->mother()->pdgId()) {
406  // add all further particles but the two top quarks and potential
407  // cases where the mother of the top has itself as daughter
409  new reco::GenParticle(ts->threeCharge(), ts->p4(), ts->vertex(), ts->pdgId(), ts->status(), false);
410  std::unique_ptr<reco::GenParticle> sPtr(cand);
411  target.push_back(*sPtr);
412  if (ts->begin() != ts->end()) {
413  // in case the sister has daughters increment
414  // and add the first generation of daughters
415  addDaughters(++motherPartIdx_, ts->begin(), target, false);
416  }
417  }
418  }
419  }
420  // fill the map for the administration
421  // of daughter indices
422  refs_[iTop] = topDaughters;
423  refs_[iW] = wDaughters;
424  }
425 }
426 
427 void TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& primalTops,
428  const std::vector<const reco::GenParticle*>& decayingTops,
430  std::vector<const reco::GenParticle*>::const_iterator top_start;
431  std::vector<const reco::GenParticle*>::const_iterator top_end;
432  if (fillMode_ == kME) {
433  top_start = primalTops.begin();
434  top_end = primalTops.end();
435  } else {
436  top_start = decayingTops.begin();
437  top_end = decayingTops.end();
438  }
439  for (std::vector<const reco::GenParticle*>::const_iterator it = top_start; it != top_end; ++it) {
440  const reco::GenParticle* t = *it;
441  // summation might happen here
442  std::unique_ptr<reco::GenParticle> topPtr(
443  new reco::GenParticle(t->threeCharge(), t->p4(), t->vertex(), t->pdgId(), t->status(), false));
444  target.push_back(*topPtr);
445  ++motherPartIdx_;
446 
447  // keep the top index for the map to manage the daughter refs
448  int iTop = motherPartIdx_;
449  std::vector<int> topDaughters;
450  // define the W boson index (to be set later) for the map to
451  // manage the daughter refs
452  int iW = 0;
453  std::vector<int> wDaughters;
454  const reco::GenParticle* final_top = findLastParticleInChain(t);
455 
456  //iterate over top daughters
457  for (reco::GenParticle::const_iterator td = final_top->begin(); td != final_top->end(); ++td) {
458  if (std::abs(td->pdgId()) <= TopDecayID::bID) {
459  // if particle is beauty or other quark
460  std::unique_ptr<reco::GenParticle> qPtr(
461  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
462  target.push_back(*qPtr);
463  // increment & push index of the top daughter
464  topDaughters.push_back(++motherPartIdx_);
465  if (addRadiation_) {
466  // for radation to be added we first need to
467  // pick the last quark in the MC chain
468  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
469  addRadiation(motherPartIdx_, last_q, target);
470  }
471  } else if (std::abs(td->pdgId()) == TopDecayID::WID) {
472  // ladies and gentleman, we have a W boson
473  std::unique_ptr<reco::GenParticle> WPtr(
474  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
475  target.push_back(*WPtr);
476  // increment & push index of the top daughter
477  topDaughters.push_back(++motherPartIdx_);
478  iW = motherPartIdx_;
479 
480  // next are the daughers of our W boson
481  // for Pythia 6 this is wrong as the last W has no daughters at all!
482  // instead the status 3 W has 3 daughters: q qbar' and W (WTF??!)
483  const reco::GenParticle* decaying_W = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*td));
484  for (reco::GenParticle::const_iterator wd = decaying_W->begin(); wd != decaying_W->end(); ++wd) {
485  if (!(std::abs(wd->pdgId()) == TopDecayID::WID)) {
486  std::unique_ptr<reco::GenParticle> qPtr(
487  new reco::GenParticle(wd->threeCharge(), wd->p4(), wd->vertex(), wd->pdgId(), wd->status(), false));
488  target.push_back(*qPtr);
489  // increment & push index of the top daughter
490  wDaughters.push_back(++motherPartIdx_);
491  const reco::GenParticle* last_q = findLastParticleInChain(static_cast<const reco::GenParticle*>(&*wd));
492  addRadiation(motherPartIdx_, last_q, target);
493  if (std::abs(wd->pdgId()) == TopDecayID::tauID) {
494  // add tau daughters
495  // currently it adds k-mesons etc as well, which
496  // is not what we want.
497  addDaughters(motherPartIdx_, wd, target);
498  }
499  }
500  }
501 
502  } else {
503  if (addRadiation_ && (td->pdgId() == TopDecayID::glueID || std::abs(td->pdgId()) < TopDecayID::bID)) {
504  // collect additional radiation from the top
505  std::unique_ptr<reco::GenParticle> radPtr(
506  new reco::GenParticle(td->threeCharge(), td->p4(), td->vertex(), td->pdgId(), td->status(), false));
507  target.push_back(*radPtr);
508  }
509  //other top daughters like Zq for FCNC
510  // for pythia 6 many gluons end up here
511  //std::cout << "other top daughters: to be implemented"
512  // << std::endl;
513  }
514  }
515 
516  // fill the map for the administration
517  // of daughter indices
518  refs_[iTop] = topDaughters;
519  refs_[iW] = wDaughters;
520  }
521 }
522 
524 reco::Particle::LorentzVector TopDecaySubset::p4(const std::vector<const reco::GenParticle*>::const_iterator top,
525  int statusFlag) {
526  // calculate the four vector for top/anti-top quarks from
527  // the W boson and the b quark plain or including all
528  // additional radiation depending on switch 'plain'
529  if (statusFlag == TopDecayID::unfrag) {
530  // return 4 momentum as it is
531  return (*top)->p4();
532  }
534  for (reco::GenParticle::const_iterator p = (*top)->begin(); p != (*top)->end(); ++p) {
535  if (p->status() == TopDecayID::unfrag) {
536  // descend by one level for each
537  // status 3 particle on the way
538  vec += p4(p, statusFlag);
539  } else {
540  if (std::abs((*top)->pdgId()) == TopDecayID::WID) {
541  // in case of a W boson skip the status
542  // 2 particle to prevent double counting
543  if (std::abs(p->pdgId()) != TopDecayID::WID)
544  vec += p->p4();
545  } else {
546  // add all four vectors for each stable
547  // particle (status 1 or 2) on the way
548  vec += p->p4();
549  if (vec.mass() - (*top)->mass() > 0) {
550  // continue adding up gluons and qqbar pairs on the top
551  // line untill the nominal top mass is reached; then
552  // break in order to prevent picking up virtualities
553  break;
554  }
555  }
556  }
557  }
558  return vec;
559 }
560 
563  // calculate the four vector for all top daughters from
564  // their daughters including additional radiation
565  if (statusFlag == TopDecayID::unfrag) {
566  // return 4 momentum as it is
567  return part->p4();
568  }
570  for (reco::GenParticle::const_iterator p = part->begin(); p != part->end(); ++p) {
571  if (p->status() <= TopDecayID::stable && std::abs(p->pdgId()) == TopDecayID::WID) {
572  vec = p->p4();
573  } else {
574  if (p->status() <= TopDecayID::stable) {
575  // sum up the p4 of all stable particles
576  // (of status 1 or 2)
577  vec += p->p4();
578  } else {
579  if (p->status() == TopDecayID::unfrag) {
580  // if the particle is unfragmented (i.e.
581  // status 3) descend by one level
582  vec += p4(p, statusFlag);
583  }
584  }
585  }
586  }
587  return vec;
588 }
589 
594  std::vector<int> daughters;
595  int idxBuffer = idx;
596  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
597  if (daughter->status() <= TopDecayID::stable && daughter->pdgId() != part->pdgId()) {
598  // skip comment lines and make sure that
599  // the particle is not double counted as
600  // daughter of itself
601  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
602  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
603  target.push_back(*ptr);
604  daughters.push_back(++idx); //push index of daughter
605  }
606  }
607  if (!daughters.empty()) {
608  refs_[idxBuffer] = daughters;
609  }
610 }
611 
613  std::vector<int> daughters;
614  int idxBuffer = idx;
615  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
616  // either pick daughters as long as they are different
617  // to the initial particle
618  if (daughter->pdgId() != part->pdgId()) {
619  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
620  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
621  target.push_back(*ptr);
622  daughters.push_back(++idx); //push index of daughter
623  }
624  }
625  if (!daughters.empty()) {
626  refs_[idxBuffer] = daughters;
627  }
628 }
629 
634  bool recursive) {
635  std::vector<int> daughters;
636  int idxBuffer = idx;
637  for (reco::GenParticle::const_iterator daughter = part->begin(); daughter != part->end(); ++daughter) {
638  std::unique_ptr<reco::GenParticle> ptr(new reco::GenParticle(
639  daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false));
640  target.push_back(*ptr);
641  // increment & push index of daughter
642  daughters.push_back(++idx);
643  // continue recursively if desired
644  if (recursive) {
645  addDaughters(idx, daughter, target);
646  }
647  }
648  if (!daughters.empty()) {
649  refs_[idxBuffer] = daughters;
650  }
651 }
652 
655  // clear vector of references
656  refs_.clear();
657  // set idx for mother particles to a start value
658  // of -1 (the first entry will raise it to 0)
659  motherPartIdx_ = -1;
660 }
661 
664  int idx = 0;
665  for (reco::GenParticleCollection::iterator p = sel.begin(); p != sel.end(); ++p, ++idx) {
666  //find daughter reference vectors in refs_ and add daughters
667  std::map<int, std::vector<int> >::const_iterator daughters = refs_.find(idx);
668  if (daughters != refs_.end()) {
669  for (std::vector<int>::const_iterator daughter = daughters->second.begin(); daughter != daughters->second.end();
670  ++daughter) {
671  reco::GenParticle* part = dynamic_cast<reco::GenParticle*>(&(*p));
672  if (part == nullptr) {
673  throw edm::Exception(edm::errors::InvalidReference, "Not a GenParticle");
674  }
675  part->addDaughter(reco::GenParticleRef(ref, *daughter));
676  sel[*daughter].addMother(reco::GenParticleRef(ref, idx));
677  }
678  }
679  }
680 }
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
int pdgId() const final
PDG identifier.
const Candidate * daughter(size_type) const override
return daughter at a given position, i = 0, ... numberOfDaughters() - 1 (read only mode) ...
int threeCharge() const final
electric charge
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:13
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
static const int stable
Definition: TopGenEvent.h:10
size_t numberOfMothers() const override
number of mothers
virtual int threeCharge() const =0
electric charge
std::vector< const reco::GenParticle * > findTops(const reco::GenParticleCollection &parts)
find top quarks in list of input particles
void addDaughter(const typename daughters::value_type &)
add a daughter via a reference
void clearReferences()
clear references
static const int tID
Definition: TopGenEvent.h:12
virtual int status() const =0
status word
static const int tauID
Definition: TopGenEvent.h:20
edm::EDGetTokenT< GenEventInfoProduct > genEventInfo_srcToken_
input tag for the genEventInfo source
std::string moduleName(Provenance const &provenance)
Definition: Provenance.cc:27
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
virtual int pdgId() const =0
PDG identifier.
~TopDecaySubset() override
default destructor
const_iterator end() const
last daughter const_iterator
Definition: Candidate.h:146
const Point & vertex() const override
vertex position (overwritten by PF...)
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?
const LorentzVector & p4() const final
four-momentum Lorentz vector
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
bool isValid() const
Definition: HandleBase.h:70
void fillReferences(const reco::GenParticleRefProd &refProd, reco::GenParticleCollection &target)
fill references for output vector
std::vector< const reco::GenParticle * > findPrimalTops(const reco::GenParticleCollection &parts)
part
Definition: HCALResponse.h:20
size_t numberOfDaughters() const override
number of daughters
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_
fixed size matrix
HLT enums.
int status() const final
status word
const_iterator begin() const
first daughter const_iterator
Definition: Candidate.h:144
virtual const Point & vertex() const =0
vertex position
virtual size_type numberOfDaughters() const =0
number of daughters
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
def move(src, dest)
Definition: eostools.py:511
const Candidate * mother(size_type=0) const override
return mother at a given position, i = 0, ... numberOfMothers() - 1 (read only mode) ...
Definition: event.py:1
const reco::GenParticle * findPrimalW(const reco::GenParticle *top)
const reco::GenParticle * findLastParticleInChain(const reco::GenParticle *p)