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