All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
MCOperator.cc
Go to the documentation of this file.
1 #include "MCOperator.hh"
2 using std::vector;
3 using std::string;
4 using EVENT::LCCollection;
5 using EVENT::MCParticle;
6 using IMPL::MCParticleImpl;
7 using namespace lcio;
8 namespace TTbarAnalysis
9 {
10  MCOperator:: MCOperator (LCCollection * col, LCCollection * rel)
11  {
12  myCollection = col;
13  myRelCollection = rel;
14  myPrimaryVertex[0] = 0.0;
15  myPrimaryVertex[1] = 0.0;
16  myPrimaryVertex[2] = 0.0;
17  myAngleCut = 0.5; // \pi/4
18  }
19  DecayChain * MCOperator::RefineDecayChain(DecayChain * initial, vector<PDGTYPE> typeOfProducts)
20  {
21  if (!initial || initial->GetSize() < 2)
22  {
23  return NULL;
24  }
25  int size = initial->GetSize();
26  DecayChain * result = new DecayChain(initial->GetName(), initial->GetParentPDG());
27  for (int i = 1; i < size; i++)
28  {
29  MCParticle * particle = initial->Get(i);
30  vector< MCParticle * > parents = particle->getParents();
31  MCParticle * parent = NULL;
32  if (parents.size() == 1 && CheckParticle(parents[0],typeOfProducts[i-1]))
33  {
34  parent = parents[0];
35  }
36  else
37  {
38  parent = initial->Get(i-1);
39  }
40  if (parent)
41  {
42  result->Add(parent);
43  }
44  }
45 
46  result->Add(initial->Get(size-1));
47  return result;
48  }
49  DecayChain * MCOperator::Construct(string name, int pdg, vector<PDGTYPE> typeOfProducts)
50  {
51  DecayChain * result = new DecayChain(name, pdg);
52  int number = myCollection->getNumberOfElements();
53  bool finished = false;
54  for (int i = 0; i < number; i++)
55  {
56  MCParticle * particle = dynamic_cast<MCParticle*>( myCollection->getElementAt(i) ) ;
57  if (i > 100 && result->GetSize() == 0)
58  {
59  streamlog_out(MESSAGE) << "WARNING: EVENT RUN OUT OF TRIALS!\n";
60  break;
61  }
62  if (particle->getPDG() == pdg)
63  {
64  if (CheckForUnification(particle, pdg))
65  {
66  // streamlog_out(MESSAGE) << "WARNING: found a quark-antiquark merging!\n";
67  continue;
68  }
69  for (unsigned int j = 0; j < typeOfProducts.size(); j++)
70  {
71  PDGTYPE currentPDG = typeOfProducts[j];
72  MCParticle * found = FindYoungestChild(particle, currentPDG);
73  if (found)
74  {
75  if (CheckForColorString(found, pdg))
76  {
77  MCParticle * service = found->getParents()[0];
78  MCParticle * consistent = GetConsistentDaughter(particle, service, currentPDG);
79  if (consistent)
80  {
81  result->Add(consistent);
82  found = consistent;
83  finished = true;
84  }
85  }
86  else
87  {
88  result->Add(found);
89  finished = true;
90  }
91  }
92  else
93  {
94  break;
95  }
96  particle =(finished)? found : NULL;
97  }
98  }
99  if (finished)
100  {
101  break;
102  }
103  }
104  return result;
105  }
106  bool MCOperator::CheckForUnification(MCParticle * particle, int pdg)
107  {
108  vector< MCParticle * > daughters = particle->getDaughters();
109  if (daughters.size() == 0)
110  {
111  return false;
112  }
113  if (daughters.size() == 1 && daughters[0]->getPDG() == pdg)
114  {
115  return CheckForUnification(daughters[0], pdg);
116  }
117  if (daughters.size() == 1 && (daughters[0]->getPDG() == 92 || daughters[0]->getPDG() == 94))
118  {
119  vector< MCParticle * > grandDaughters = daughters[0]->getDaughters();
120  bool foundParticle = false;
121  bool foundAntiparticle = false;
122  for (unsigned int i = 0; i < grandDaughters.size(); i++)
123  {
124  if (grandDaughters[i]->getPDG() == pdg)
125  {
126  foundParticle = true;
127  }
128  if (grandDaughters[i]->getPDG() == -pdg)
129  {
130  foundAntiparticle = true;
131  }
132  }
133  return foundParticle && foundAntiparticle;
134  }
135  return false;
136 
137  }
138  bool MCOperator::CheckParticle(MCParticle * particle, PDGTYPE type)
139  {
140  bool result = false;
141  vector<int> pdg = ConstantStorage::GET_PDG(type);
142  for (unsigned int i = 0; i < pdg.size(); i++)
143  {
144  if (abs(particle->getPDG()) == pdg[i])
145  {
146  result = true;
147  break;
148  }
149  }
150  return result;
151  }
152  bool MCOperator::CheckForColorString(EVENT::MCParticle * daughter, int pdgOfParent)
153  {
154  vector< MCParticle * > parents = daughter->getParents();
155  if (parents.size() == 1)
156  {
157  MCParticle * parent = parents[0];
158  if (parent->getPDG() == 92)
159  {
160  vector< MCParticle * > grandParents = parent->getParents();
161  int count = 0;
162  for (unsigned int i = 0; i < grandParents.size(); i++)
163  {
164  if (abs(grandParents[i]->getPDG()) == abs(pdgOfParent))
165  {
166  count++;
167  }
168  if (count > 1)
169  {
170  streamlog_out(MESSAGE) << "United color string found for PDG " << pdgOfParent <<"!\n";
171  return true;
172  }
173  }
174  }
175  }
176  return false;
177  }
178 
179  MCParticle * MCOperator::GetConsistentDaughter(MCParticle * parent, MCParticle * service, PDGTYPE type)
180  {
181  vector< MCParticle * > daughters = SelectDaughtersOfType(service, type); //service->getDaughters();
182  streamlog_out(MESSAGE) << "Parent PDG: " << parent->getPDG() << ";\n";
183  int size = daughters.size();
184  vector<float> angle;
185  if (size == 1)
186  {
187  //streamlog_out(MESSAGE) << "We have only 1 meson of type " << type << '\n';
188  }
189  float dE = 10.0;
190  for (int i = 0; i < size; i++)
191  {
192  MCParticle * daughter = daughters[i];
193  //streamlog_out(MESSAGE) << "Daughter PDG: " << daughter->getPDG() << ";\n";
194  if (MathOperator::getModule(daughter->getMomentum()) > MathOperator::getModule(parent->getMomentum())+dE)// ||
195  {
196  streamlog_out(MESSAGE) << "Discarded by energy!\n";
197  //continue;
198  }
199  if (daughter->getCharge()*parent->getCharge() > 0.0
200  && (type == BOTTOM_MESONS || type == CHARMED_MESONS || type == STRANGE_MESONS))
201  //&& type != BOTTOM_HADRONS
202  //&& type != BOTTOM_BARYONS
203  //&& type != CHARMED_HADRONS
204  //&& type != CHARMED_BARYONS)
205  {
206  //streamlog_out(MESSAGE) << "Same sign of charge!\n";
207  return daughter;
208  }
209  angle.push_back(MathOperator::getAngle(daughter->getMomentum(), parent->getMomentum()));
210  }
211  float minAngle = myAngleCut;
212  int winner = -1;
213  //streamlog_out(MESSAGE) << "Checking angles...\n";
214  for (unsigned int i = 0; i < angle.size(); i++)
215  {
216  //streamlog_out(MESSAGE) << "Angle " << i << ": " << angle[i] << '\n';
217  if (angle[i] < minAngle)// &&
218  //daughters[i]->getEnergy() < parent->getEnergy()+dE &&
219  //(daughters[i]->getCharge()*parent->getCharge() > -0.0001 && ( type == BOTTOM_MESONS || type == CHARMED_MESONS || type == STRANGE_MESONS )))
220  {
221  minAngle = angle[i];
222  winner = i;
223  }
224  }
225  if (winner > -1)
226  {
227  //streamlog_out(MESSAGE) << "Choosing angle " << winner << "\n";
228  if (daughters[winner]->getCharge()*parent->getCharge() < -0.0001 && type != BOTTOM_HADRONS && type != BOTTOM_BARYONS)
229  {
230  streamlog_out(MESSAGE) << "INFO: Charge is wrong!\n";
231 
232  }
233  return daughters[winner];
234  }
235  //streamlog_out(MESSAGE) << "Angle is wrong!\n";
236  return NULL;
237 
238  }
239  bool MCOperator::IsReconstructed(MCParticle * particle)
240  {
241  LCRelationNavigator navigator(myRelCollection);
242  vector< LCObject * > obj = navigator.getRelatedFromObjects(particle);
243  int nvtx = obj.size();
244  if (nvtx < 1)
245  {
246  streamlog_out(MESSAGE) << "INFO: Particle not reconstructed\n";
247  return false;
248  }
249  const vector< float > weights = navigator.getRelatedFromWeights(particle);
250  if (nvtx > 0)
251  {
252  int winner = -1;
253  float maxweight = 0.0;
254  for (unsigned int j = 0; j < obj.size(); j++)
255  {
256  ReconstructedParticle * reco = dynamic_cast< ReconstructedParticle * >(obj[j]);
257  if (weights[j] > maxweight && std::abs(reco->getCharge()) > 0.09)
258  {
259  maxweight = weights[j];
260  winner = j;
261  }
262  }
263  return winner > -1;
264  }
265  return nvtx > 0 && weights[0] > 0.5;
266 
267  }
268  PDGTYPE MCOperator::GetParticleType(MCParticle * particle)
269  {
270  PDGTYPE result = EXCEPTIONAL_PDGTYPE;
271  int count = _max_MESONS;
272  for (int i = 1; i < count; i++)
273  {
274  PDGTYPE candidate = static_cast<PDGTYPE>(i);
275  vector<int> pdg = ConstantStorage::GET_PDG(candidate);
276  for (unsigned int j = 0; j < pdg.size(); j++)
277  {
278  if (abs(particle->getPDG()) == pdg[j])
279  {
280  result = candidate;
281  break;
282  }
283  }
284  }
285  return result;
286 
287  }
288  MCParticle * MCOperator::FindExceptionalChild(MCParticle * parent, PDGTYPE parentType)
289  {
290  if (!parent)
291  {
292  //streamlog_out(MESSAGE) << "ERROR: Input particle is NULL!\n";
293  return NULL;
294  }
295  vector< MCParticle * > daughters = parent->getDaughters();
296  if (daughters.size() < 1)
297  {
298  //streamlog_out(MESSAGE)<<"ERROR: Found 0 daughters!\n";
299  return NULL;
300  }
301  if (parentType == EXCEPTIONAL_PDGTYPE)
302  {
303  parentType = GetParticleType(parent);
304  if (parentType == EXCEPTIONAL_PDGTYPE)
305  {
306  streamlog_out(MESSAGE) << "ERROR: Probably, parent is not meson, to be continue....\n";
307  return NULL;
308  }
309  }
310  bool found = false;
311  for (unsigned int i = 0; i < daughters.size(); i++)
312  {
313  MCParticle * daughter = daughters.at(i);
314  if (CheckParticle(daughter,parentType))
315  {
316  //streamlog_out(MESSAGE) << "Found PDG to exclude: " << daughter->getPDG() << "; Going recursion\n";
317  found = true;
318  }
319  }
320  if (!found)
321  {
322  //streamlog_out(MESSAGE) << "Found state without initial mesons!\n";
323  return daughters[0];
324  }
325  //streamlog_out(MESSAGE)<<"Not found in I gen. Checking next gen.\n";
326  for (unsigned int i = 0; i < daughters.size(); i++)
327  {
328  MCParticle * daughter = daughters.at(i);
329  if (daughter->getEnergy() < 1.0 && daughter->getMass() < 300.0)
330  {
331  //streamlog_out(MESSAGE)<<"Daughter does not pass the selection cuts\n";
332  continue;
333  }
334  return FindExceptionalChild(daughter, parentType);
335  }
336  return NULL;
337  }
338  MCParticle * MCOperator::FindYoungestChild(MCParticle * parent, PDGTYPE type)
339  {
340  if (!parent)
341  {
342  //streamlog_out(MESSAGE) << "ERROR: Input particle is NULL!\n";
343  return NULL;
344  }
345  if (type == TAU_LEPTON && CheckParticle(parent,type))
346  {
347  return parent;
348  }
349  if (type == EXCEPTIONAL_PDGTYPE)
350  {
351  return FindExceptionalChild(parent, EXCEPTIONAL_PDGTYPE);
352  }
353  vector< MCParticle * > daughters = parent->getDaughters();
354  if (daughters.size() < 1)
355  {
356  streamlog_out(MESSAGE)<<"ERROR: Found 0 daughters!\n";
357  return NULL;
358  }
359  //streamlog_out(MESSAGE)<<"Checking " << daughters.size() <<" I gen of daughters. \n";
360  MCParticle * result = NULL;
361  int count = 0;
362  for (unsigned int i = 0; i < daughters.size(); i++)
363  {
364  MCParticle * daughter = daughters.at(i);
365  if (CheckParticle(daughter,type))
366  {
367  //streamlog_out(MESSAGE) << "Found PDG: " << daughter->getPDG() << ";\n";
368  count++;
369  result = daughter;
370  }
371  }
372  if (result)
373  {
374  if (count > 1 && abs(parent->getPDG()) !=92 && (type == CHARMED_MESONS || type == CHARMED_HADRONS))
375  {
376  streamlog_out(MESSAGE)<<"FATAL: Daughter multiplicity found for meson type " << type << " and parent " << parent->getPDG() <<"!\n";
377  return NULL;
378  }
379  return result;
380  }
381  //streamlog_out(MESSAGE)<<"Not found in I gen. Checking next gen.\n";
382  for (unsigned int i = 0; i < daughters.size(); i++)
383  {
384  MCParticle * daughter = daughters.at(i);
385  if (daughter->getEnergy() < 1.0 && daughter->getMass() < 300.0)
386  {
387  //streamlog_out(MESSAGE)<<"Daughter does not pass the selection cuts\n";
388  //continue;
389  }
390  return FindYoungestChild(daughter, type);
391  }
392  return NULL;
393  }
394  EVENT::MCParticle * MCOperator::cureDoubleCharmDecay(std::vector< EVENT::MCParticle * > & selected)
395  {
396  MCParticleImpl * newparticle = new MCParticleImpl();
397  newparticle->setMomentum(selected[0]->getMomentum());
398  newparticle->setMass(selected[0]->getMass());
399  newparticle->setCharge(selected[0]->getCharge());
400  newparticle->setPDG(selected[0]->getPDG() + selected[1]->getPDG());
401  return newparticle;
402  }
403  vector< MCParticle * > MCOperator::SelectDaughtersOfType(MCParticle * parent, PDGTYPE type)
404  {
405  vector< MCParticle * > daughters = parent->getDaughters();
406  vector< MCParticle * > result;
407  for (unsigned int i = 0; i < daughters.size(); i++)
408  {
409  if (CheckParticle(daughters[i], type))
410  {
411  result.push_back(daughters[i]);
412  }
413  }
414  return result;
415  }
416 
417  vector< MCParticle * > MCOperator::GetPairParticles(int pdg)
418  {
419  pdg = abs(pdg);
420  vector< MCParticle * > pair;
421  if (pdg < 1)
422  {
423  return pair;
424  }
425  int number = myCollection->getNumberOfElements();
426  MCParticle * b = NULL;
427  MCParticle * bbar = NULL;
428  for (int i = 0; i < number; i++)
429  {
430  MCParticle * particle = dynamic_cast<MCParticle*>( myCollection->getElementAt(i) );
431  if (particle->getPDG() == pdg)// && countParticle == 0)
432  {
433  b = particle;
434  }
435  if (particle->getPDG() == -pdg)// && countAntiparticle == 0)
436  {
437  bbar = particle;
438  }
439  }
440  if (b)
441  {
442  pair.push_back(new MCParticleImpl((const IMPL::MCParticleImpl&)(*b)));
443  streamlog_out(MESSAGE)<<"INFO: Found b!\n";
444  }
445  if (bbar)
446  {
447  pair.push_back(new MCParticleImpl((const IMPL::MCParticleImpl&)(*bbar)));
448  streamlog_out(MESSAGE)<<"INFO: Found bbar!\n";
449  }
450  return pair;
451  }
452  vector< MCParticle * > MCOperator::GetPairParticles(PDGTYPE type)
453  {
454  vector< MCParticle * > pair;
455  int number = myCollection->getNumberOfElements();
456  for (int i = 0; i < number; i++)
457  {
458  MCParticle * particle = dynamic_cast<MCParticle*>( myCollection->getElementAt(i) );
459  if (CheckParticle(particle, type) && particle->getParents()[0]->getPDG() == 92)
460  {
461  pair.push_back(new MCParticleImpl((const IMPL::MCParticleImpl&)(*particle)));
462  streamlog_out(MESSAGE)<<"Found a suitable particle of type " << particle->getPDG() << '\n';
463  }
464  if (pair.size() > 1)
465  {
466  break;
467  }
468  }
469  return pair;
470  }
471  /*bool MCOperator::CheckProcessForPair(int pdg)
472  {
473  pdg = abs(pdg);
474  if (pdg < 1)
475  {
476  return false;
477  }
478  int countParticle = 0;
479  int countAntiparticle = 0;
480  int number = myCollection->getNumberOfElements();
481  for (int i = 0; i < number; i++)
482  {
483  MCParticle * particle = dynamic_cast<MCParticle*>( myCollection->getElementAt(i) );
484  if (particle->getPDG() == pdg)
485  {
486  countParticle++;
487  }
488  if (particle->getPDG() == 0-pdg)
489  {
490  countAntiparticle++;
491  }
492  }
493  streamlog_out(MESSAGE)<<"INFO: " << countParticle << " quarks and " << countAntiparticle << " antiquarks\n";
494  return countParticle && countAntiparticle;
495  }//*/
496  vector< MCParticle * > * MCOperator::CheckProcessForPair(int pdg)
497  {
498  pdg = abs(pdg);
499  if (pdg < 1)
500  {
501  return NULL;
502  }
503  MCParticle * particle = NULL;
504  MCParticle * antiparticle = NULL;
505  vector< MCParticle * > * result = NULL;
506  int number = (myCollection->getNumberOfElements() > 100)? 100 : myCollection->getNumberOfElements();
507  for (int i = 0; i < number; i++)
508  {
509  MCParticle * candidate = dynamic_cast<MCParticle*>( myCollection->getElementAt(i) );
510  if (candidate->getPDG() == pdg && !particle)
511  {
512  particle = candidate;
513  streamlog_out(MESSAGE)<<"Found a suitable particle of type " << particle->getPDG() << '\n';
514  }
515  if (candidate->getPDG() == -pdg && !antiparticle)
516  {
517  antiparticle = candidate;
518  streamlog_out(MESSAGE)<<"Found a suitable particle of type " << antiparticle->getPDG() << '\n';
519  }
520  }
521  if (particle && antiparticle)
522  {
523  result = new vector< MCParticle * >();
524  result->push_back(particle);
525  result->push_back(antiparticle);
526  }
527  return result;
528  }
529  vector< MCParticle * > MCOperator::SelectStableCloseDaughters(MCParticle * parent,int excludePDG, bool selectReco, vector<MCParticle *> * misReconstructed)
530  {
531  vector< MCParticle * > result;
532  if (!parent ||
533  CheckParticle(parent, NONTRACKABLE_PARTICLES) ||
534  parent->getPDG() == excludePDG)//(CheckParticle(parent, CHARMED_MESONS) && discardCharmedMesons))
535  {
536  return result;
537  }
538  vector< MCParticle * > daughters = parent->getDaughters();
539  if (daughters.size()<1)
540  {
541  return result;
542  }
543  if ( parent && MathOperator::getDistance(daughters[0]->getVertex(), parent->getVertex()) > 100.0) // Long distance!!!
544  {
545  streamlog_out(MESSAGE)<<"WARNING: Long-lived noninteracting particle " << parent->getPDG() <<"!\n";
546  return result;
547  }
548  bool finished = false;
549  for (unsigned int i = 0; i < daughters.size(); i++)
550  {
551  MCParticle * daughter = daughters[i];
552  if (CheckParticle(daughter, TRACKABLE_PARTICLES))
553  {
554  //streamlog_out(MESSAGE)<<"\tDaughter reached calorimeter!\n";
555  if (MathOperator::getModule(daughter->getMomentum()) < 0.1)
556  {
557  //streamlog_out(MESSAGE)<<"CAUTION: Low momentum particle of " << MathOperator::getModule(daughter->getMomentum()) << " GeV!\n";
558  }
559  finished = true;
560  if (selectReco && IsReconstructed(daughter))
561  {
562  result.push_back(daughter);
563  }
564  if (!selectReco)
565  {
566  result.push_back(daughter);
567  }
568  if (misReconstructed && !IsReconstructed(daughter))
569  {
570  misReconstructed->push_back(daughter);
571  }
572  }
573  else
574  {
575  vector< MCParticle * > grannies = SelectStableCloseDaughters(daughter, excludePDG);
576  for (unsigned int j = 0; j < grannies.size(); j++)
577  {
578  result.push_back(grannies[j]);
579  }
580  }
581  }
582  return result;
583  }
584  float MCOperator::GetAccuracy(MCParticle * particle, float a, float b)
585  {
586  float p = MathOperator::getModule(particle->getMomentum());
587  float m = particle->getMass();
588  float gamma = sqrt( 1 + (p * p) / (m * m));
589  vector<float> direction = MathOperator::getDirection(particle->getMomentum());
590  vector<float> angles = MathOperator::getAngles(direction);
591  float accuracy = sqrt(a*a + b*b /( p * p * pow(sin(angles[1]), 4.0/3.0)) );
592  return gamma*accuracy;
593  }
594  bool MCOperator::CheckCompatibility(const vector< MCParticle * > & daughters, MCParticle * parent, int plusCharge)
595  {
596  int charge = 0;
597  float mass = 0.0;
598  for (unsigned int i = 0; i < daughters.size(); i++)
599  {
600  MCParticle * daughter = daughters[i];
601  mass += daughter->getMass();
602  charge += daughter->getCharge();
603  }
604  if (charge + plusCharge != (int)(parent->getCharge()))
605  {
606  streamlog_out(MESSAGE)<< "CAUTION: Charge is not compatible: charges " << charge << " and " << parent->getCharge() << ", " << plusCharge <<"!\n";
607  return false;
608  }
609  if (mass > parent->getMass())
610  {
611  streamlog_out(MESSAGE)<< "CAUTION: Mass is not compatible!\n";
612  return false;
613  }
614  return true;
615  }
616  vector< MCParticle * > MCOperator::CheckDaughterVisibility(const vector< MCParticle * > & daughters)
617  {
618  int size = daughters.size();
619  vector< MCParticle * > filtered;
620  for (int i = 0; i < size; i++)
621  {
622  MCParticle * daughter = daughters[i];
623  vector< float > direction = MathOperator::getDirection(daughter->getMomentum());
624  float offset = MathOperator::getDistanceTo(myPrimaryVertex, direction, daughter->getVertex());
625  float pt = MathOperator::getPt(daughter->getMomentum());
626  float p = MathOperator::getModule(daughter->getMomentum());
627  float eta = MathOperator::getAngles(direction)[1];
628  streamlog_out(MESSAGE) << "\tPDG: " << daughter->getPDG()
629  << " p: " << p
630  << " pt: " << pt
631  << " teta: " << eta
632  << " offset: " << offset
633  << '\n';
634  if (offset > 0.01 && std::fabs(eta) < 4 && p > 0.6)
635  {
636  filtered.push_back(daughter);
637  }
638  }
639  return filtered;
640  }
641 } /* */
static const float m
int GetParentPDG() const
Definition: DecayChain.cc:50
std::string GetName() const
Definition: DecayChain.cc:46
void Add(EVENT::MCParticle *particle)
Definition: DecayChain.cc:19
EVENT::MCParticle * Get(int i)
Definition: DecayChain.cc:23