CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TopDecaySubset.cc
Go to the documentation of this file.
1 #include "TString.h"
4 
7 
10  src_ (cfg.getParameter<edm::InputTag>("src")),
11  addRadiation_(cfg.getParameter<bool>("addRadiation")),
12  showerModel_ (kStart)
13 {
14  // mapping of the corresponding fillMode; see FillMode
15  // enumerator of TopDecaySubset for available modes
16  if( cfg.getParameter<std::string>( "fillMode" ) == "kME" ){ fillMode_=kME; }
17  if( cfg.getParameter<std::string>( "fillMode" ) == "kStable" ){ fillMode_=kStable; }
18  // produces a set of gen particle collections following
19  // the decay branch of top quarks to the first level of
20  // stable decay products
21  produces<reco::GenParticleCollection>();
22 }
23 
26 {
27 }
28 
30 void
32 {
33  // get source collection
35  event.getByLabel(src_, src);
36 
37  // find top quarks in list of input particles
38  std::vector<const reco::GenParticle*> tops = findTops(*src);
39 
40  // determine shower model (only in first event)
41  if(showerModel_==kStart)
43 
44  // check sanity of W bosons
45  checkWBosons(tops);
46 
47  // create target vector
48  std::auto_ptr<reco::GenParticleCollection> target( new reco::GenParticleCollection );
49  // get ref product from the event
50  const reco::GenParticleRefProd ref = event.getRefBeforePut<reco::GenParticleCollection>();
51  // clear existing refs
52  clearReferences();
53  // fill output
54  fillListing(tops, *target);
55  // fill references
56  fillReferences(ref, *target);
57 
58  // write vectors to the event
59  event.put(target);
60 }
61 
63 std::vector<const reco::GenParticle*>
65 {
66  std::vector<const reco::GenParticle*> tops;
67  for(reco::GenParticleCollection::const_iterator t=parts.begin(); t!=parts.end(); ++t){
68  if( std::abs(t->pdgId())==TopDecayID::tID && t->status()==TopDecayID::unfrag )
69  tops.push_back( &(*t) );
70  }
71  return tops;
72 }
73 
76 TopDecaySubset::checkShowerModel(const std::vector<const reco::GenParticle*>& tops) const
77 {
78  for(std::vector<const reco::GenParticle*>::const_iterator it=tops.begin(); it!=tops.end(); ++it){
79  const reco::GenParticle* top = *it;
80  // check for kHerwig type showers: here the status 3 top quark will
81  // have a single status 2 top quark as daughter, which has again 3
82  // or more status 2 daughters
83  if( top->numberOfDaughters()==1){
84  if( top->begin()->pdgId()==top->pdgId() && top->begin()->status()==TopDecayID::stable && top->begin()->numberOfDaughters()>1)
85  return kHerwig;
86  }
87  // check for kPythia type showers: here the status 3 top quark will
88  // have all decay products and a status 2 top quark as daughters
89  // the status 2 top quark will be w/o further daughters
90  if( top->numberOfDaughters()>1 ){
91  bool containsWBoson=false, containsQuarkDaughter=false;
92  for(reco::GenParticle::const_iterator td=top->begin(); td!=top->end(); ++td){
93  if( std::abs(td->pdgId ()) <TopDecayID::tID ) containsQuarkDaughter=true;
94  if( std::abs(td->pdgId ())==TopDecayID::WID ) containsWBoson=true;
95  }
96  if(containsQuarkDaughter && containsWBoson)
97  return kPythia;
98  }
99  }
100  // if neither Herwig nor Pythia like
101  if(tops.size()==0)
102  edm::LogWarning("decayChain")
103  << " Failed to find top quarks in decay chain. Will assume that this a \n"
104  << " non-top sample and produce an empty decaySubset.\n";
105  else
107  " Can not find back any of the supported hadronization models. Models \n"
108  " which are supported are: \n"
109  " Pythia LO(+PS): Top(status 3) --> WBoson(status 3), Quark(status 3)\n"
110  " Herwig NLO(+PS): Top(status 2) --> Top(status 3) --> Top(status 2) \n");
111  return kNone;
112 }
113 
115 void
116 TopDecaySubset::checkWBosons(std::vector<const reco::GenParticle*>& tops) const
117 {
118  unsigned nTops = tops.size();
119  for(std::vector<const reco::GenParticle*>::iterator it=tops.begin(); it!=tops.end();) {
120  const reco::GenParticle* top = *it;
121  bool isContained=false;
122  bool expectedStatus=false;
123  for(reco::GenParticle::const_iterator td=((showerModel_==kPythia) ? top->begin() : top->begin()->begin());
124  td!=((showerModel_==kPythia) ? top->end() : top->begin()->end());
125  ++td){
126  if(std::abs(td->pdgId())==TopDecayID::WID) {
127  isContained=true;
128  if( ((showerModel_==kPythia) ? td->status()==TopDecayID::unfrag : td->status()==TopDecayID::stable) ) {
129  expectedStatus=true;
130  break;
131  }
132  }
133  }
134  if(!expectedStatus) {
135  it=tops.erase(it);
136  if(isContained)
137  edm::LogWarning("decayChain")
138  << " W boson does not have the expected status. This happens, e.g., \n"
139  << " with MC@NLO in the case of additional ttbar pairs from radiated \n"
140  << " gluons. We hope everything is fine, remove the correspdonding top \n"
141  << " quark from our list since it is not part of the primary ttbar pair \n"
142  << " and try to continue. \n";
143  }
144  else
145  it++;
146  }
147  if(tops.size()==0 && nTops!=0)
149  " Did not find a W boson with appropriate status for any of the top \n"
150  " quarks in this event. This means that the hadronization of the W \n"
151  " boson might be screwed up or there is another problem with the \n"
152  " particle listing in this MC sample. Please contact an expert. \n");
153 }
154 
156 void
157 TopDecaySubset::fillListing(const std::vector<const reco::GenParticle*>& tops, reco::GenParticleCollection& target)
158 {
159  unsigned int statusFlag;
160  // determine status flag of the new
161  // particle depending on the FillMode
162  fillMode_ == kME ? statusFlag=3 : statusFlag=2;
163 
164  for(std::vector<const reco::GenParticle*>::const_iterator it=tops.begin(); it!=tops.end(); ++it){
165  const reco::GenParticle* t = *it;
166  // if particle is top or anti-top
167  std::auto_ptr<reco::GenParticle> topPtr( new reco::GenParticle( t->threeCharge(), p4(it, statusFlag), t->vertex(), t->pdgId(), statusFlag, false ) );
168  target.push_back( *topPtr );
169  ++motherPartIdx_;
170  // keep the top index for the map to manage the daughter refs
171  int iTop=motherPartIdx_;
172  std::vector<int> topDaughters;
173  // define the W boson index (to be set later) for the map to
174  // manage the daughter refs
175  int iW = 0;
176  std::vector<int> wDaughters;
177  //iterate over top daughters
178  for(reco::GenParticle::const_iterator td=((showerModel_==kPythia)?t->begin():t->begin()->begin()); td!=((showerModel_==kPythia)?t->end():t->begin()->end()); ++td){
179  if( td->status()==TopDecayID::unfrag && std::abs( td->pdgId() )<=TopDecayID::bID ){
180  // if particle is beauty or other quark
181  std::auto_ptr<reco::GenParticle> bPtr( new reco::GenParticle( td->threeCharge(), p4( td, statusFlag ), td->vertex(), td->pdgId(), statusFlag, false ) );
182  target.push_back( *bPtr );
183  // increment & push index of the top daughter
184  topDaughters.push_back( ++motherPartIdx_ );
185  if(addRadiation_){
186  addRadiation(motherPartIdx_,td,target);
187  }
188  }
190  if( buffer->status()==TopDecayID::unfrag && std::abs( buffer->pdgId() )==TopDecayID::WID ){
191  // if particle is a W boson
192  std::auto_ptr<reco::GenParticle> wPtr( new reco::GenParticle( buffer->threeCharge(), p4( buffer, statusFlag), buffer->vertex(), buffer->pdgId(), statusFlag, true ) );
193  target.push_back( *wPtr );
194  // increment & push index of the top daughter
195  topDaughters.push_back( ++motherPartIdx_ );
196  // keep the W idx for the map
197  iW=motherPartIdx_;
198  if(addRadiation_){
199  addRadiation(motherPartIdx_,buffer,target);
200  }
201  // iterate over W daughters
202  for(reco::GenParticle::const_iterator wd=((showerModel_==kPythia)?buffer->begin():buffer->begin()->begin()); wd!=((showerModel_==kPythia)?buffer->end():buffer->begin()->end()); ++wd){
203  // make sure the W daughter is of status unfrag and not the W itself
204  if( wd->status()==TopDecayID::unfrag && !(std::abs(wd->pdgId())==TopDecayID::WID) ) {
205  std::auto_ptr<reco::GenParticle> qPtr( new reco::GenParticle( wd->threeCharge(), p4( wd, statusFlag ), wd->vertex(), wd->pdgId(), statusFlag, false) );
206  target.push_back( *qPtr );
207  // increment & push index of the top daughter
208  wDaughters.push_back( ++motherPartIdx_ );
209  if( wd->status()==TopDecayID::unfrag && std::abs( wd->pdgId() )==TopDecayID::tauID ){
210  // add tau daughters if the particle is a tau pass
211  // the daughter of the tau which is of status 2
212  //addDaughters(motherPartIdx_, wd->begin(), target);
213  // add tau daughters if the particle is a tau pass
214  // the tau itself, which may add a tau daughter of
215  // of status 2 to the listing
216  addDaughters(motherPartIdx_,wd,target);
217  }
218  }
219  }
220  }
221  if(addRadiation_ && buffer->status()==TopDecayID::stable && ( buffer->pdgId()==TopDecayID::glueID || std::abs(buffer->pdgId())<TopDecayID::bID)){
222  // collect additional radiation from the top
223  std::auto_ptr<reco::GenParticle> radPtr( new reco::GenParticle( buffer->threeCharge(), buffer->p4(), buffer->vertex(), buffer->pdgId(), statusFlag, false ) );
224  target.push_back( *radPtr );
225  // increment & push index of the top daughter
226  topDaughters.push_back( ++motherPartIdx_ );
227  }
228  }
229  // add potential sisters of the top quark;
230  // only for top to prevent double counting
231  if(t->numberOfMothers()>0 && t->pdgId()==TopDecayID::tID){
232  for(reco::GenParticle::const_iterator ts = t->mother()->begin(); ts!=t->mother()->end(); ++ts){
233  // loop over all daughters of the top mother i.e.
234  // the two top quarks and their potential sisters
235  if(std::abs(ts->pdgId())!=t->pdgId() && ts->pdgId()!=t->mother()->pdgId()){
236  // add all further particles but the two top quarks and potential
237  // cases where the mother of the top has itself as daughter
238  reco::GenParticle* cand = new reco::GenParticle( ts->threeCharge(), ts->p4(), ts->vertex(), ts->pdgId(), ts->status(), false );
239  std::auto_ptr<reco::GenParticle> sPtr( cand );
240  target.push_back( *sPtr );
241  if(ts->begin()!=ts->end()){
242  // in case the sister has daughters increment
243  // and add the first generation of daughters
244  addDaughters(++motherPartIdx_,ts->begin(),target,false);
245  }
246  }
247  }
248  }
249  // fill the map for the administration
250  // of daughter indices
251  refs_[ iTop ] = topDaughters;
252  refs_[ iW ] = wDaughters;
253  }
254 }
255 
258 TopDecaySubset::p4(const std::vector<const reco::GenParticle*>::const_iterator top, int statusFlag)
259 {
260  // calculate the four vector for top/anti-top quarks from
261  // the W boson and the b quark plain or including all
262  // additional radiation depending on switch 'plain'
263  if(statusFlag==TopDecayID::unfrag){
264  // return 4 momentum as it is
265  return (*top)->p4();
266  }
268  for(reco::GenParticle::const_iterator p=(*top)->begin(); p!=(*top)->end(); ++p){
269  if( p->status() == TopDecayID::unfrag ){
270  // descend by one level for each
271  // status 3 particle on the way
272  vec+=p4( p, statusFlag );
273  }
274  else{
275  if( std::abs((*top)->pdgId())==TopDecayID::WID ){
276  // in case of a W boson skip the status
277  // 2 particle to prevent double counting
278  if( std::abs(p->pdgId())!=TopDecayID::WID )
279  vec+=p->p4();
280  }
281  else{
282  // add all four vectors for each stable
283  // particle (status 1 or 2) on the way
284  vec+=p->p4();
285  if( vec.mass()-(*top)->mass()>0 ){
286  // continue adding up gluons and qqbar pairs on the top
287  // line untill the nominal top mass is reached; then
288  // break in order to prevent picking up virtualities
289  break;
290  }
291  }
292  }
293  }
294  return vec;
295 }
296 
300 {
301  // calculate the four vector for all top daughters from
302  // their daughters including additional radiation
303  if(statusFlag==TopDecayID::unfrag){
304  // return 4 momentum as it is
305  return part->p4();
306  }
308  for(reco::GenParticle::const_iterator p=part->begin(); p!=part->end(); ++p){
309  if( p->status()<=TopDecayID::stable && std::abs(p->pdgId ())==TopDecayID::WID){
310  vec=p->p4();
311  }
312  else{
313  if(p->status()<=TopDecayID::stable){
314  // sum up the p4 of all stable particles
315  // (of status 1 or 2)
316  vec+=p->p4();
317  }
318  else{
319  if( p->status()==TopDecayID::unfrag){
320  // if the particle is unfragmented (i.e.
321  // status 3) descend by one level
322  vec+=p4(p, statusFlag);
323  }
324  }
325  }
326  }
327  return vec;
328 }
329 
331 void
333 {
334  std::vector<int> daughters;
335  int idxBuffer = idx;
336  for(reco::GenParticle::const_iterator daughter=part->begin(); daughter!=part->end(); ++daughter){
337  if(daughter->status()<=TopDecayID::stable && daughter->pdgId()!=part->pdgId()){
338  // skip comment lines and make sure that
339  // the particle is not double counted as
340  // dasughter of itself
341  std::auto_ptr<reco::GenParticle> ptr( new reco::GenParticle( daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false) );
342  target.push_back( *ptr );
343  daughters.push_back( ++idx ); //push index of daughter
344  }
345  }
346  if(daughters.size()) {
347  refs_[ idxBuffer ] = daughters;
348  }
349 }
350 
352 void
354 {
355  std::vector<int> daughters;
356  int idxBuffer = idx;
357  for(reco::GenParticle::const_iterator daughter=part->begin(); daughter!=part->end(); ++daughter){
358  std::auto_ptr<reco::GenParticle> ptr( new reco::GenParticle( daughter->threeCharge(), daughter->p4(), daughter->vertex(), daughter->pdgId(), daughter->status(), false) );
359  target.push_back( *ptr );
360  // increment & push index of daughter
361  daughters.push_back( ++idx );
362  // continue recursively if desired
363  if(recursive){
364  addDaughters(idx,daughter,target);
365  }
366  }
367  if(daughters.size()) {
368  refs_[ idxBuffer ] = daughters;
369  }
370 }
371 
373 void
375 {
376  // clear vector of references
377  refs_.clear();
378  // set idx for mother particles to a start value
379  // of -1 (the first entry will raise it to 0)
380  motherPartIdx_=-1;
381 }
382 
384 void
386 {
387  int idx=0;
388  for(reco::GenParticleCollection::iterator p=sel.begin(); p!=sel.end(); ++p, ++idx){
389  //find daughter reference vectors in refs_ and add daughters
390  std::map<int, std::vector<int> >::const_iterator daughters=refs_.find( idx );
391  if( daughters!=refs_.end() ){
392  for(std::vector<int>::const_iterator daughter = daughters->second.begin();
393  daughter!=daughters->second.end(); ++daughter){
394  reco::GenParticle* part = dynamic_cast<reco::GenParticle* > (&(*p));
395  if(part == 0){
396  throw edm::Exception( edm::errors::InvalidReference, "Not a GenParticle" );
397  }
398  part->addDaughter( reco::GenParticleRef(ref, *daughter) );
399  sel[*daughter].addMother( reco::GenParticleRef(ref, idx) );
400  }
401  }
402  }
403 }
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
virtual int pdgId() const
PDG identifier.
static bool isContained(const std::vector< unsigned int > &list, int id)
Definition: JetInput.cc:89
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)
virtual void produce(edm::Event &event, const edm::EventSetup &setup)
write output into the event
virtual const Point & vertex() const
vertex position
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
virtual int threeCharge() const =0
electric charge
virtual int status() const =0
status word
static const int stable
Definition: TopGenEvent.h:11
#define abs(x)
Definition: mlp_lapack.h:159
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
static const int tauID
Definition: TopGenEvent.h:21
virtual size_type numberOfDaughters() const =0
number of daughters
virtual const_iterator end() const =0
last daughter const_iterator
virtual const_iterator begin() const
first daughter const_iterator
virtual size_t numberOfMothers() const
number of mothers
edm::InputTag src_
input tag for the genParticle source
virtual size_t numberOfDaughters() const
number of daughters
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
bool addRadiation_
add radiation or not?
ShowerModel
classification of potential shower types
virtual const Point & vertex() const =0
vertex position
virtual int threeCharge() const
electric charge
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
void fillReferences(const reco::GenParticleRefProd &refProd, reco::GenParticleCollection &target)
fill references for output vector
virtual int pdgId() const =0
PDG identifier.
part
Definition: HCALResponse.h:21
TopDecaySubset(const edm::ParameterSet &cfg)
default constructor
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_
virtual const_iterator begin() const =0
first daughter const_iterator
~TopDecaySubset()
default destructor
virtual const_iterator end() const
last daughter const_iterator
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:26
virtual const Candidate * mother(size_type=0) const
return mother at a given position, i = 0, ... numberOfMothers() - 1 (read only mode) ...
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
tuple src
Definition: align_tpl.py:87
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector