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 static_cast<const 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  }
211  return findLastParticleInChain(static_cast<const reco::GenParticle*>(p->daughter(d_idx)));
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  if (moduleName == "ExternalGeneratorFilter") {
269  moduleName = edm::parameterSet(prov).getParameter<std::string>("@external_type");
270  edm::LogInfo("SpecialModule") << "GEN events are produced by ExternalGeneratorFilter, "
271  << "which is a wrapper of the original module: " << moduleName;
272  }
273  }
274 
275  ShowerModel shower(kStart);
276  if (moduleName.find("Pythia6") != std::string::npos)
277  shower = kPythia;
278  else if (moduleName.find("Pythia8") != std::string::npos)
279  shower = kPythia8;
280  else if (moduleName.find("Herwig6") != std::string::npos)
281  shower = kHerwig;
282  else if (moduleName.find("ThePEG") != std::string::npos)
283  // Herwig++
284  shower = kHerwig;
285  else if (moduleName.find("Sherpa") != std::string::npos)
286  shower = kSherpa;
287  else
288  shower = kNone;
289  return shower;
290 }
292 void
293 TopDecaySubset::checkWBosons(std::vector<const reco::GenParticle*>& tops) const
294 {
295  unsigned nTops = tops.size();
296  for(std::vector<const reco::GenParticle*>::iterator it=tops.begin(); it!=tops.end();) {
297  const reco::GenParticle* top = *it;
298  bool isContained=false;
299  bool expectedStatus=false;
300  if(showerModel_!=kPythia && top->begin()==top->end())
302  "showerModel_!=kPythia && top->begin()==top->end()\n");
303  for(reco::GenParticle::const_iterator td=((showerModel_==kPythia) ? top->begin() : top->begin()->begin());
304  td!=((showerModel_==kPythia) ? top->end() : top->begin()->end());
305  ++td){
306  if(std::abs(td->pdgId())==TopDecayID::WID) {
307  isContained=true;
308  if( ((showerModel_==kPythia) ? td->status()==TopDecayID::unfrag : td->status()==TopDecayID::stable) ) {
309  expectedStatus=true;
310  break;
311  }
312  }
313  }
314  if(!expectedStatus) {
315  it=tops.erase(it);
316  if(isContained)
317  edm::LogInfo("decayChain")
318  << " W boson does not have the expected status. This happens, e.g., \n"
319  << " with MC@NLO in the case of additional ttbar pairs from radiated \n"
320  << " gluons. We hope everything is fine, remove the correspdonding top \n"
321  << " quark from our list since it is not part of the primary ttbar pair \n"
322  << " and try to continue. \n";
323  }
324  else
325  it++;
326  }
327  if(tops.empty() && nTops!=0)
329  " Did not find a W boson with appropriate status for any of the top \n"
330  " quarks in this event. This means that the hadronization of the W \n"
331  " boson might be screwed up or there is another problem with the \n"
332  " particle listing in this MC sample. Please contact an expert. \n");
333 }
334 
336 void
337 TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& tops, reco::GenParticleCollection& target)
338 {
339  unsigned int statusFlag;
340  // determine status flag of the new
341  // particle depending on the FillMode
342  fillMode_ == kME ? statusFlag=3 : statusFlag=2;
343 
344  for(std::vector<const reco::GenParticle*>::const_iterator it=tops.begin(); it!=tops.end(); ++it){
345  const reco::GenParticle* t = *it;
346  // if particle is top or anti-top
347  std::unique_ptr<reco::GenParticle> topPtr( new reco::GenParticle( t->threeCharge(), p4(it, statusFlag), t->vertex(), t->pdgId(), statusFlag, false ) );
348  target.push_back( *topPtr );
349  ++motherPartIdx_;
350  // keep the top index for the map to manage the daughter refs
351  int iTop=motherPartIdx_;
352  std::vector<int> topDaughters;
353  // define the W boson index (to be set later) for the map to
354  // manage the daughter refs
355  int iW = 0;
356  std::vector<int> wDaughters;
357  // sanity check
358  if(showerModel_!=kPythia && t->begin()==t->end())
360  "showerModel_!=kPythia && t->begin()==t->end()\n");
361  //iterate over top daughters
362  for(reco::GenParticle::const_iterator td=((showerModel_==kPythia)?t->begin():t->begin()->begin()); td!=((showerModel_==kPythia)?t->end():t->begin()->end()); ++td){
363  if( td->status()==TopDecayID::unfrag && std::abs( td->pdgId() )<=TopDecayID::bID ){
364  // if particle is beauty or other quark
365  std::unique_ptr<reco::GenParticle> bPtr( new reco::GenParticle( td->threeCharge(), p4( td, statusFlag ), td->vertex(), td->pdgId(), statusFlag, false ) );
366  target.push_back( *bPtr );
367  // increment & push index of the top daughter
368  topDaughters.push_back( ++motherPartIdx_ );
369  if(addRadiation_){
370  addRadiation(motherPartIdx_,td,target);
371  }
372  }
373  // sanity check
374  if(showerModel_!=kPythia && td->begin()==td->end())
376  "showerModel_!=kPythia && td->begin()==td->end()\n");
378  if( buffer->status()==TopDecayID::unfrag && std::abs( buffer->pdgId() )==TopDecayID::WID ){
379  // if particle is a W boson
380  std::unique_ptr<reco::GenParticle> wPtr( new reco::GenParticle( buffer->threeCharge(), p4( buffer, statusFlag), buffer->vertex(), buffer->pdgId(), statusFlag, true ) );
381  target.push_back( *wPtr );
382  // increment & push index of the top daughter
383  topDaughters.push_back( ++motherPartIdx_ );
384  // keep the W idx for the map
385  iW=motherPartIdx_;
386  if(addRadiation_){
387  addRadiation(motherPartIdx_,buffer,target);
388  }
389  if(showerModel_!=kPythia && buffer->begin()==buffer->end())
391  "showerModel_!=kPythia && buffer->begin()==buffer->end()\n");
392  // iterate over W daughters
393  for(reco::GenParticle::const_iterator wd=((showerModel_==kPythia)?buffer->begin():buffer->begin()->begin()); wd!=((showerModel_==kPythia)?buffer->end():buffer->begin()->end()); ++wd){
394  // make sure the W daughter is of status unfrag and not the W itself
395  if( wd->status()==TopDecayID::unfrag && !(std::abs(wd->pdgId())==TopDecayID::WID) ) {
396  std::unique_ptr<reco::GenParticle> qPtr( new reco::GenParticle( wd->threeCharge(), p4( wd, statusFlag ), wd->vertex(), wd->pdgId(), statusFlag, false) );
397  target.push_back( *qPtr );
398  // increment & push index of the top daughter
399  wDaughters.push_back( ++motherPartIdx_ );
400  if( wd->status()==TopDecayID::unfrag && std::abs( wd->pdgId() )==TopDecayID::tauID ){
401  // add tau daughters if the particle is a tau pass
402  // the daughter of the tau which is of status 2
403  //addDaughters(motherPartIdx_, wd->begin(), target);
404  // add tau daughters if the particle is a tau pass
405  // the tau itself, which may add a tau daughter of
406  // of status 2 to the listing
407  addDaughters(motherPartIdx_,wd,target);
408  }
409  }
410  }
411  }
412  if(addRadiation_ && buffer->status()==TopDecayID::stable && ( buffer->pdgId()==TopDecayID::glueID || std::abs(buffer->pdgId())<TopDecayID::bID)){
413  // collect additional radiation from the top
414  std::unique_ptr<reco::GenParticle> radPtr( new reco::GenParticle( buffer->threeCharge(), buffer->p4(), buffer->vertex(), buffer->pdgId(), statusFlag, false ) );
415  target.push_back( *radPtr );
416  // increment & push index of the top daughter
417  topDaughters.push_back( ++motherPartIdx_ );
418  }
419  }
420  // add potential sisters of the top quark;
421  // only for top to prevent double counting
422  if(t->numberOfMothers()>0 && t->pdgId()==TopDecayID::tID){
423  for(reco::GenParticle::const_iterator ts = t->mother()->begin(); ts!=t->mother()->end(); ++ts){
424  // loop over all daughters of the top mother i.e.
425  // the two top quarks and their potential sisters
426  if(std::abs(ts->pdgId())!=t->pdgId() && ts->pdgId()!=t->mother()->pdgId()){
427  // add all further particles but the two top quarks and potential
428  // cases where the mother of the top has itself as daughter
429  reco::GenParticle* cand = new reco::GenParticle( ts->threeCharge(), ts->p4(), ts->vertex(), ts->pdgId(), ts->status(), false );
430  std::unique_ptr<reco::GenParticle> sPtr( cand );
431  target.push_back( *sPtr );
432  if(ts->begin()!=ts->end()){
433  // in case the sister has daughters increment
434  // and add the first generation of daughters
435  addDaughters(++motherPartIdx_,ts->begin(),target,false);
436  }
437  }
438  }
439  }
440  // fill the map for the administration
441  // of daughter indices
442  refs_[ iTop ] = topDaughters;
443  refs_[ iW ] = wDaughters;
444  }
445 }
446 
448  const std::vector<const reco::GenParticle*>& primalTops,
449  const std::vector<const reco::GenParticle*>& decayingTops,
451  std::vector<const reco::GenParticle*>::const_iterator top_start;
452  std::vector<const reco::GenParticle*>::const_iterator top_end;
453  if (fillMode_ == kME) {
454  top_start = primalTops.begin();
455  top_end = primalTops.end();
456  } else {
457  top_start = decayingTops.begin();
458  top_end = decayingTops.end();
459  }
460  for (std::vector<const reco::GenParticle*>::const_iterator it =
461  top_start; it != top_end; ++it) {
462  const reco::GenParticle* t = *it;
463  // summation might happen here
464  std::unique_ptr < reco::GenParticle
465  > topPtr(
466  new reco::GenParticle(t->threeCharge(), t->p4(),
467  t->vertex(), t->pdgId(), t->status(), false));
468  target.push_back(*topPtr);
469  ++motherPartIdx_;
470 
471  // keep the top index for the map to manage the daughter refs
472  int iTop = motherPartIdx_;
473  std::vector<int> topDaughters;
474  // define the W boson index (to be set later) for the map to
475  // manage the daughter refs
476  int iW = 0;
477  std::vector<int> wDaughters;
478  const reco::GenParticle* final_top = findLastParticleInChain(t);
479 
480  //iterate over top daughters
481  for (reco::GenParticle::const_iterator td = final_top->begin();
482  td != final_top->end(); ++td) {
483  if (std::abs(td->pdgId()) <= TopDecayID::bID) {
484  // if particle is beauty or other quark
485  std::unique_ptr < reco::GenParticle
486  > qPtr(
487  new reco::GenParticle(td->threeCharge(),
488  td->p4(), td->vertex(), td->pdgId(),
489  td->status(), false));
490  target.push_back(*qPtr);
491  // increment & push index of the top daughter
492  topDaughters.push_back(++motherPartIdx_);
493  if (addRadiation_) {
494  // for radation to be added we first need to
495  // pick the last quark in the MC chain
497  static_cast<const reco::GenParticle*>(&*td));
498  addRadiation(motherPartIdx_, last_q, target);
499  }
500  } else if (std::abs(td->pdgId()) == TopDecayID::WID) {
501  // ladies and gentleman, we have a W boson
502  std::unique_ptr < reco::GenParticle
503  > WPtr(
504  new reco::GenParticle(td->threeCharge(),
505  td->p4(), td->vertex(), td->pdgId(),
506  td->status(), false));
507  target.push_back(*WPtr);
508  // increment & push index of the top daughter
509  topDaughters.push_back(++motherPartIdx_);
510  iW = motherPartIdx_;
511 
512  // next are the daughers of our W boson
513  // for Pythia 6 this is wrong as the last W has no daughters at all!
514  // instead the status 3 W has 3 daughters: q qbar' and W (WTF??!)
515  const reco::GenParticle* decaying_W = findLastParticleInChain(
516  static_cast<const reco::GenParticle*>(&*td));
517  for (reco::GenParticle::const_iterator wd = decaying_W->begin();
518  wd != decaying_W->end(); ++wd) {
519  if (!(std::abs(wd->pdgId()) == TopDecayID::WID)) {
520  std::unique_ptr < reco::GenParticle
521  > qPtr(
522  new reco::GenParticle(wd->threeCharge(),
523  wd->p4(), wd->vertex(),
524  wd->pdgId(), wd->status(),
525  false));
526  target.push_back(*qPtr);
527  // increment & push index of the top daughter
528  wDaughters.push_back(++motherPartIdx_);
530  static_cast<const reco::GenParticle*>(&*wd));
531  addRadiation(motherPartIdx_, last_q, target);
532  if (std::abs(wd->pdgId()) == TopDecayID::tauID) {
533  // add tau daughters
534  // currently it adds k-mesons etc as well, which
535  // is not what we want.
536  addDaughters(motherPartIdx_, wd, target);
537  }
538  }
539  }
540 
541  } else {
542  if(addRadiation_ && ( td->pdgId()==TopDecayID::glueID ||
543  std::abs(td->pdgId())<TopDecayID::bID)){
544  // collect additional radiation from the top
545  std::unique_ptr<reco::GenParticle> radPtr(
546  new reco::GenParticle( td->threeCharge(),
547  td->p4(), td->vertex(), td->pdgId(), td->status(), false ) );
548  target.push_back( *radPtr );
549  }
550  //other top daughters like Zq for FCNC
551  // for pythia 6 many gluons end up here
552  //std::cout << "other top daughters: to be implemented"
553  // << std::endl;
554  }
555  }
556 
557  // fill the map for the administration
558  // of daughter indices
559  refs_[iTop] = topDaughters;
560  refs_[iW] = wDaughters;
561  }
562 }
563 
566 TopDecaySubset::p4(const std::vector<const reco::GenParticle*>::const_iterator top, int statusFlag)
567 {
568  // calculate the four vector for top/anti-top quarks from
569  // the W boson and the b quark plain or including all
570  // additional radiation depending on switch 'plain'
571  if(statusFlag==TopDecayID::unfrag){
572  // return 4 momentum as it is
573  return (*top)->p4();
574  }
576  for(reco::GenParticle::const_iterator p=(*top)->begin(); p!=(*top)->end(); ++p){
577  if( p->status() == TopDecayID::unfrag ){
578  // descend by one level for each
579  // status 3 particle on the way
580  vec+=p4( p, statusFlag );
581  }
582  else{
583  if( std::abs((*top)->pdgId())==TopDecayID::WID ){
584  // in case of a W boson skip the status
585  // 2 particle to prevent double counting
586  if( std::abs(p->pdgId())!=TopDecayID::WID )
587  vec+=p->p4();
588  }
589  else{
590  // add all four vectors for each stable
591  // particle (status 1 or 2) on the way
592  vec+=p->p4();
593  if( vec.mass()-(*top)->mass()>0 ){
594  // continue adding up gluons and qqbar pairs on the top
595  // line untill the nominal top mass is reached; then
596  // break in order to prevent picking up virtualities
597  break;
598  }
599  }
600  }
601  }
602  return vec;
603 }
604 
608 {
609  // calculate the four vector for all top daughters from
610  // their daughters including additional radiation
611  if(statusFlag==TopDecayID::unfrag){
612  // return 4 momentum as it is
613  return part->p4();
614  }
616  for(reco::GenParticle::const_iterator p=part->begin(); p!=part->end(); ++p){
617  if( p->status()<=TopDecayID::stable && std::abs(p->pdgId ())==TopDecayID::WID){
618  vec=p->p4();
619  }
620  else{
621  if(p->status()<=TopDecayID::stable){
622  // sum up the p4 of all stable particles
623  // (of status 1 or 2)
624  vec+=p->p4();
625  }
626  else{
627  if( p->status()==TopDecayID::unfrag){
628  // if the particle is unfragmented (i.e.
629  // status 3) descend by one level
630  vec+=p4(p, statusFlag);
631  }
632  }
633  }
634  }
635  return vec;
636 }
637 
639 void
641 {
642  std::vector<int> daughters;
643  int idxBuffer = idx;
644  for(reco::GenParticle::const_iterator daughter=part->begin(); daughter!=part->end(); ++daughter){
645  if(daughter->status()<=TopDecayID::stable && daughter->pdgId()!=part->pdgId()){
646  // skip comment lines and make sure that
647  // the particle is not double counted as
648  // daughter of itself
649  std::unique_ptr<reco::GenParticle> ptr( new reco::GenParticle( daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false) );
650  target.push_back( *ptr );
651  daughters.push_back( ++idx ); //push index of daughter
652  }
653  }
654  if(!daughters.empty()) {
655  refs_[ idxBuffer ] = daughters;
656  }
657 }
658 
661  std::vector<int> daughters;
662  int idxBuffer = idx;
663  for (reco::GenParticle::const_iterator daughter = part->begin();
664  daughter != part->end(); ++daughter) {
665  // either pick daughters as long as they are different
666  // to the initial particle
667  if (daughter->pdgId() != part->pdgId()) {
668  std::unique_ptr < reco::GenParticle
669  > ptr(
670  new reco::GenParticle(daughter->threeCharge(),
671  daughter->p4(), daughter->vertex(),
672  daughter->pdgId(), daughter->status(),
673  false));
674  target.push_back(*ptr);
675  daughters.push_back(++idx); //push index of daughter
676  }
677  }
678  if (!daughters.empty()) {
679  refs_[idxBuffer] = daughters;
680  }
681 }
682 
684 void
686 {
687  std::vector<int> daughters;
688  int idxBuffer = idx;
689  for(reco::GenParticle::const_iterator daughter=part->begin(); daughter!=part->end(); ++daughter){
690  std::unique_ptr<reco::GenParticle> ptr( new reco::GenParticle( daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false) );
691  target.push_back( *ptr );
692  // increment & push index of daughter
693  daughters.push_back( ++idx );
694  // continue recursively if desired
695  if(recursive){
696  addDaughters(idx,daughter,target);
697  }
698  }
699  if(!daughters.empty()) {
700  refs_[ idxBuffer ] = daughters;
701  }
702 }
703 
705 void
707 {
708  // clear vector of references
709  refs_.clear();
710  // set idx for mother particles to a start value
711  // of -1 (the first entry will raise it to 0)
712  motherPartIdx_=-1;
713 }
714 
716 void
718 {
719  int idx=0;
720  for(reco::GenParticleCollection::iterator p=sel.begin(); p!=sel.end(); ++p, ++idx){
721  //find daughter reference vectors in refs_ and add daughters
722  std::map<int, std::vector<int> >::const_iterator daughters=refs_.find( idx );
723  if( daughters!=refs_.end() ){
724  for(std::vector<int>::const_iterator daughter = daughters->second.begin();
725  daughter!=daughters->second.end(); ++daughter){
726  reco::GenParticle* part = dynamic_cast<reco::GenParticle* > (&(*p));
727  if(part == nullptr){
728  throw edm::Exception( edm::errors::InvalidReference, "Not a GenParticle" );
729  }
730  part->addDaughter( reco::GenParticleRef(ref, *daughter) );
731  sel[*daughter].addMother( reco::GenParticleRef(ref, idx) );
732  }
733  }
734  }
735 }
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:2
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
ParameterSet const & parameterSet(Provenance const &provenance)
Definition: Provenance.cc:11
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)