Belle II Software  light-2303-iriomote
MCTruthVariables.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 // Own header.
10 #include <analysis/variables/MCTruthVariables.h>
11 
12 // include VariableManager
13 #include <analysis/VariableManager/Manager.h>
14 
15 #include <analysis/dataobjects/Particle.h>
16 #include <analysis/dataobjects/TauPairDecay.h>
17 #include <analysis/utility/MCMatching.h>
18 #include <analysis/utility/ReferenceFrame.h>
19 #include <analysis/utility/ValueIndexPairSorting.h>
20 
21 #include <mdst/dataobjects/MCParticle.h>
22 #include <mdst/dataobjects/ECLCluster.h>
23 
24 #include <framework/datastore/StoreArray.h>
25 #include <framework/datastore/StoreObjPtr.h>
26 #include <framework/dataobjects/EventMetaData.h>
27 #include <framework/gearbox/Const.h>
28 #include <framework/logging/Logger.h>
29 #include <framework/database/DBObjPtr.h>
30 #include <framework/dbobjects/BeamParameters.h>
31 
32 #include <queue>
33 
34 namespace Belle2 {
39  namespace Variable {
40 
41  static const double realNaN = std::numeric_limits<double>::quiet_NaN();
42 
43 
44  double isSignal(const Particle* part)
45  {
46  const MCParticle* mcparticle = part->getMCParticle();
47  if (!mcparticle) return realNaN;
48 
49  int status = MCMatching::getMCErrors(part, mcparticle);
50  return (status == MCMatching::c_Correct);
51  }
52 
53  double isSignalAcceptWrongFSPs(const Particle* part)
54  {
55  const MCParticle* mcparticle = part->getMCParticle();
56  if (!mcparticle) return realNaN;
57 
58  int status = MCMatching::getMCErrors(part, mcparticle);
59  //remove the following bits
60  status &= (~MCMatching::c_MisID);
61  status &= (~MCMatching::c_AddedWrongParticle);
62 
63  return (status == MCMatching::c_Correct);
64  }
65 
66  double isPrimarySignal(const Particle* part)
67  {
68  return (isSignal(part) > 0.5 and particleMCPrimaryParticle(part) > 0.5);
69  }
70 
71  double isMisidentified(const Particle* part)
72  {
73  const MCParticle* mcp = part->getMCParticle();
74  if (!mcp) return realNaN;
75  int st = MCMatching::getMCErrors(part, mcp);
76  return ((st & MCMatching::c_MisID) != 0);
77  }
78 
79  double isWrongCharge(const Particle* part)
80  {
81  const MCParticle* mcp = part->getMCParticle();
82  if (!mcp) return realNaN;
83  return (part->getCharge() != mcp->getCharge());
84  }
85 
86  double isCloneTrack(const Particle* particle)
87  {
88  // neutrals and composites don't make sense
89  if (!Const::chargedStableSet.contains(Const::ParticleType(abs(particle->getPDGCode()))))
90  return realNaN;
91  // get mcparticle weight (mcmatch weight)
92  const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
93  if (!mcpww.first) return realNaN;
94  return (mcpww.second < 0);
95  }
96 
97  double isOrHasCloneTrack(const Particle* particle)
98  {
99  // use std::queue to check daughters-- granddaughters etc recursively
100  std::queue<const Particle*> qq;
101  qq.push(particle);
102  while (!qq.empty()) {
103  const auto d = qq.front(); // get daughter
104  qq.pop(); // remove the daughter from the queue
105  if (isCloneTrack(d) == 1.0) return 1.0;
106  size_t nDau = d->getNDaughters(); // number of daughters of daughters
107  for (size_t iDau = 0; iDau < nDau; ++iDau)
108  qq.push(d->getDaughter(iDau));
109  }
110  return 0.0;
111  }
112 
113  double genNthMotherPDG(const Particle* part, const std::vector<double>& args)
114  {
115  const MCParticle* mcparticle = part->getMCParticle();
116  if (!mcparticle) return 0.0;
117 
118  unsigned int nLevels = args.empty() ? 0 : args[0];
119 
120  const MCParticle* curMCParticle = mcparticle;
121  for (unsigned int i = 0; i <= nLevels; ++i) {
122  const MCParticle* curMCMother = curMCParticle->getMother();
123  if (!curMCMother) return 0.0;
124  curMCParticle = curMCMother;
125  }
126  return curMCParticle->getPDG();
127  }
128 
129  double genNthMotherIndex(const Particle* part, const std::vector<double>& args)
130  {
131  const MCParticle* mcparticle = part->getMCParticle();
132  if (!mcparticle) return 0.0;
133 
134  unsigned int nLevels = args.empty() ? 0 : args[0];
135 
136  const MCParticle* curMCParticle = mcparticle;
137  for (unsigned int i = 0; i <= nLevels; ++i) {
138  const MCParticle* curMCMother = curMCParticle->getMother();
139  if (!curMCMother) return 0.0;
140  curMCParticle = curMCMother;
141  }
142  return curMCParticle->getArrayIndex();
143  }
144 
145  double genMotherPDG(const Particle* part)
146  {
147  return genNthMotherPDG(part, {});
148  }
149 
150  double genMotherP(const Particle* part)
151  {
152  const MCParticle* mcparticle = part->getMCParticle();
153  if (!mcparticle) return realNaN;
154 
155  const MCParticle* mcmother = mcparticle->getMother();
156  if (!mcmother) return realNaN;
157 
158  return mcmother->getMomentum().R();
159  }
160 
161  double genMotherIndex(const Particle* part)
162  {
163  return genNthMotherIndex(part, {});
164  }
165 
166  double genParticleIndex(const Particle* part)
167  {
168  const MCParticle* mcparticle = part->getMCParticle();
169  if (!mcparticle) return realNaN;
170  return mcparticle->getArrayIndex();
171  }
172 
173  double isSignalAcceptMissingNeutrino(const Particle* part)
174  {
175  const MCParticle* mcparticle = part->getMCParticle();
176  if (!mcparticle) return realNaN;
177 
178  int status = MCMatching::getMCErrors(part, mcparticle);
179  //remove the following bits
180  status &= (~MCMatching::c_MissNeutrino);
181 
182  return (status == MCMatching::c_Correct);
183  }
184 
185  double isSignalAcceptMissingMassive(const Particle* part)
186  {
187  const MCParticle* mcparticle = part->getMCParticle();
188  if (!mcparticle) return realNaN;
189 
190  int status = MCMatching::getMCErrors(part, mcparticle);
191  //remove the following bits
192  status &= (~MCMatching::c_MissMassiveParticle);
193  status &= (~MCMatching::c_MissKlong);
194 
195  return (status == MCMatching::c_Correct);
196  }
197 
198  double isSignalAcceptMissingGamma(const Particle* part)
199  {
200  const MCParticle* mcparticle = part->getMCParticle();
201  if (!mcparticle) return realNaN;
202 
203  int status = MCMatching::getMCErrors(part, mcparticle);
204  //remove the following bits
205  status &= (~MCMatching::c_MissGamma);
206 
207  return (status == MCMatching::c_Correct);
208  }
209 
210  double isSignalAcceptMissing(const Particle* part)
211  {
212  const MCParticle* mcparticle = part->getMCParticle();
213  if (!mcparticle) return realNaN;
214 
215  int status = MCMatching::getMCErrors(part, mcparticle);
216  //remove the following bits
217  status &= (~MCMatching::c_MissGamma);
218  status &= (~MCMatching::c_MissMassiveParticle);
219  status &= (~MCMatching::c_MissKlong);
220  status &= (~MCMatching::c_MissNeutrino);
221 
222  return (status == MCMatching::c_Correct);
223  }
224 
225  double isSignalAcceptBremsPhotons(const Particle* part)
226  {
227  const MCParticle* mcparticle = part->getMCParticle();
228  if (!mcparticle) return realNaN;
229 
230  int status = MCMatching::getMCErrors(part, mcparticle);
231  //remove the following bits
232  status &= (~MCMatching::c_AddedRecoBremsPhoton);
233 
234  return (status == MCMatching::c_Correct);
235  }
236 
237  double particleMCMatchPDGCode(const Particle* part)
238  {
239  const MCParticle* mcparticle = part->getMCParticle();
240  if (!mcparticle) return realNaN;
241  return mcparticle->getPDG();
242  }
243 
244  double particleMCErrors(const Particle* part)
245  {
246  return MCMatching::getMCErrors(part);
247  }
248 
249  double particleNumberOfMCMatch(const Particle* particle)
250  {
251  RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
252  return (mcRelations.size());
253  }
254 
255  double particleMCMatchWeight(const Particle* particle)
256  {
257  auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
258  if (!relWithWeight.first) return realNaN;
259  return relWithWeight.second;
260  }
261 
262  double particleMCMatchDecayTime(const Particle* part)
263  {
264  const MCParticle* mcparticle = part->getMCParticle();
265  if (!mcparticle) return realNaN;
266  return mcparticle->getDecayTime();
267  }
268 
269  double particleMCMatchLifeTime(const Particle* part)
270  {
271  const MCParticle* mcparticle = part->getMCParticle();
272  if (!mcparticle) return realNaN;
273  return mcparticle->getLifetime();
274  }
275 
276  double particleMCMatchPX(const Particle* part)
277  {
278  const MCParticle* mcparticle = part->getMCParticle();
279  if (!mcparticle) return realNaN;
280 
281  const auto& frame = ReferenceFrame::GetCurrent();
282  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
283  return frame.getMomentum(mcpP4).Px();
284  }
285 
286  double particleMCMatchPY(const Particle* part)
287  {
288  const MCParticle* mcparticle = part->getMCParticle();
289  if (!mcparticle) return realNaN;
290 
291  const auto& frame = ReferenceFrame::GetCurrent();
292  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
293  return frame.getMomentum(mcpP4).Py();
294  }
295 
296  double particleMCMatchPZ(const Particle* part)
297  {
298  const MCParticle* mcparticle = part->getMCParticle();
299  if (!mcparticle) return realNaN;
300 
301  const auto& frame = ReferenceFrame::GetCurrent();
302  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
303  return frame.getMomentum(mcpP4).Pz();
304  }
305 
306  double particleMCMatchPT(const Particle* part)
307  {
308  const MCParticle* mcparticle = part->getMCParticle();
309  if (!mcparticle) return realNaN;
310 
311  const auto& frame = ReferenceFrame::GetCurrent();
312  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
313  return frame.getMomentum(mcpP4).Pt();
314  }
315 
316  double particleMCMatchE(const Particle* part)
317  {
318  const MCParticle* mcparticle = part->getMCParticle();
319  if (!mcparticle) return realNaN;
320 
321  const auto& frame = ReferenceFrame::GetCurrent();
322  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
323  return frame.getMomentum(mcpP4).E();
324  }
325 
326  double particleMCMatchP(const Particle* part)
327  {
328  const MCParticle* mcparticle = part->getMCParticle();
329  if (!mcparticle) return realNaN;
330 
331  const auto& frame = ReferenceFrame::GetCurrent();
332  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
333  return frame.getMomentum(mcpP4).P();
334  }
335 
336  double particleMCMatchTheta(const Particle* part)
337  {
338  const MCParticle* mcparticle = part->getMCParticle();
339  if (!mcparticle) return realNaN;
340 
341  const auto& frame = ReferenceFrame::GetCurrent();
342  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
343  return frame.getMomentum(mcpP4).Theta();
344  }
345 
346  double particleMCMatchPhi(const Particle* part)
347  {
348  const MCParticle* mcparticle = part->getMCParticle();
349  if (!mcparticle) return realNaN;
350 
351  const auto& frame = ReferenceFrame::GetCurrent();
352  ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
353  return frame.getMomentum(mcpP4).Phi();
354  }
355 
356  double mcParticleNDaughters(const Particle* part)
357  {
358  const MCParticle* mcparticle = part->getMCParticle();
359 
360  if (!mcparticle) return realNaN;
361  return mcparticle->getNDaughters();
362  }
363 
364  double particleMCRecoilMass(const Particle* part)
365  {
366  StoreArray<MCParticle> mcparticles;
367  if (mcparticles.getEntries() < 1) return realNaN;
368 
369  ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
370  ROOT::Math::PxPyPzEVector pDaughters;
371  const std::vector<Particle*> daughters = part->getDaughters();
372  for (auto daughter : daughters) {
373  const MCParticle* mcD = daughter->getMCParticle();
374  if (!mcD) return realNaN;
375 
376  pDaughters += mcD->get4Vector();
377  }
378  return (pInitial - pDaughters).M();
379  }
380 
381  ROOT::Math::PxPyPzEVector MCInvisibleP4(const MCParticle* mcparticle)
382  {
383  ROOT::Math::PxPyPzEVector ResultP4;
384  int pdg = abs(mcparticle->getPDG());
385  bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
386 
387  if (mcparticle->getNDaughters() > 0) {
388  const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
389  for (auto daughter : daughters)
390  ResultP4 += MCInvisibleP4(daughter);
391  } else if (isNeutrino)
392  ResultP4 += mcparticle->get4Vector();
393 
394  return ResultP4;
395  }
396 
397  double particleMCCosThetaBetweenParticleAndNominalB(const Particle* part)
398  {
399  int particlePDG = abs(part->getPDGCode());
400  if (particlePDG != 511 and particlePDG != 521)
401  B2FATAL("The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
402 
403  PCmsLabTransform T;
404  double e_Beam = T.getCMSEnergy() / 2.0; // GeV
405  double m_B = part->getPDGMass();
406 
407  // Y(4S) mass according PDG (https://pdg.lbl.gov/2020/listings/rpp2020-list-upsilon-4S.pdf)
408  const double mY4S = 10.5794; // GeV
409 
410  // if this is a continuum run, use an approximate Y(4S) CMS energy
411  if (e_Beam * e_Beam - m_B * m_B < 0) {
412  e_Beam = mY4S / 2.0;
413  }
414  double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
415 
416  // Calculate cosThetaBY with daughter neutrino momenta subtracted
417  const MCParticle* mcB = part->getMCParticle();
418  if (!mcB) return realNaN;
419 
420  int mcParticlePDG = abs(mcB->getPDG());
421  if (mcParticlePDG != 511 and mcParticlePDG != 521)
422  return realNaN;
423 
424  ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
425  double e_d = p.E();
426  double m_d = p.M();
427  double p_d = p.P();
428 
429  double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
430  / (2 * p_B * p_d);
431  return theta_BY;
432  }
433 
434  double mcParticleSecondaryPhysicsProcess(const Particle* p)
435  {
436  const MCParticle* mcp = p->getMCParticle();
437  if (!mcp) return realNaN;
438  return mcp->getSecondaryPhysicsProcess();
439  }
440 
441  double mcParticleStatus(const Particle* p)
442  {
443  const MCParticle* mcp = p->getMCParticle();
444  if (!mcp) return realNaN;
445  return mcp->getStatus();
446  }
447 
448  double particleMCPrimaryParticle(const Particle* p)
449  {
450  const MCParticle* mcp = p->getMCParticle();
451  if (!mcp) return realNaN;
452 
453  unsigned int bitmask = MCParticle::c_PrimaryParticle;
454  return mcp->hasStatus(bitmask);
455  }
456 
457  double particleMCVirtualParticle(const Particle* p)
458  {
459  const MCParticle* mcp = p->getMCParticle();
460  if (!mcp) return realNaN;
461 
462  unsigned int bitmask = MCParticle::c_IsVirtual;
463  return mcp->hasStatus(bitmask);
464  }
465 
466  double particleMCInitialParticle(const Particle* p)
467  {
468  const MCParticle* mcp = p->getMCParticle();
469  if (!mcp) return realNaN;
470 
471  unsigned int bitmask = MCParticle::c_Initial;
472  return mcp->hasStatus(bitmask);
473  }
474 
475  double particleMCISRParticle(const Particle* p)
476  {
477  const MCParticle* mcp = p->getMCParticle();
478  if (!mcp) return realNaN;
479 
480  unsigned int bitmask = MCParticle::c_IsISRPhoton;
481  return mcp->hasStatus(bitmask);
482  }
483 
484  double particleMCFSRParticle(const Particle* p)
485  {
486  const MCParticle* mcp = p->getMCParticle();
487  if (!mcp) return realNaN;
488 
489  unsigned int bitmask = MCParticle::c_IsFSRPhoton;
490  return mcp->hasStatus(bitmask);
491  }
492 
493  double particleMCPhotosParticle(const Particle* p)
494  {
495  const MCParticle* mcp = p->getMCParticle();
496  if (!mcp) return realNaN;
497 
498  unsigned int bitmask = MCParticle::c_IsPHOTOSPhoton;
499  return mcp->hasStatus(bitmask);
500  }
501 
502  double generatorEventWeight(const Particle*)
503  {
504  StoreObjPtr<EventMetaData> evtMetaData;
505  if (!evtMetaData) return realNaN;
506  return evtMetaData->getGeneratedWeight();
507  }
508 
509  int tauPlusMcMode(const Particle*)
510  {
511  StoreObjPtr<TauPairDecay> tauDecay;
512  if (!tauDecay) {
513  B2WARNING("Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
514  return 0;
515  }
516  return tauDecay->getTauPlusIdMode();
517  }
518 
519  int tauMinusMcMode(const Particle*)
520  {
521  StoreObjPtr<TauPairDecay> tauDecay;
522  if (!tauDecay) {
523  B2WARNING("Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
524  return 0;
525  }
526  return tauDecay->getTauMinusIdMode();
527  }
528 
529  int tauPlusMcProng(const Particle*)
530  {
531  StoreObjPtr<TauPairDecay> tauDecay;
532  if (!tauDecay) {
533  B2WARNING("Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
534  return 0;
535  }
536  return tauDecay->getTauPlusMcProng();
537  }
538 
539  int tauMinusMcProng(const Particle*)
540  {
541  StoreObjPtr<TauPairDecay> tauDecay;
542  if (!tauDecay) {
543  B2WARNING("Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
544  return 0;
545  }
546  return tauDecay->getTauMinusMcProng();
547  }
548 
549  double isReconstructible(const Particle* p)
550  {
551  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
552  return realNaN;
553  const MCParticle* mcp = p->getMCParticle();
554  if (!mcp) return realNaN;
555 
556  // If charged: make sure it was seen in the SVD.
557  // If neutral: make sure it was seen in the ECL.
558  return (abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
559  }
560 
561  double seenInPXD(const Particle* p)
562  {
563  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
564  return realNaN;
565  const MCParticle* mcp = p->getMCParticle();
566  if (!mcp) return realNaN;
567  return mcp->hasSeenInDetector(Const::PXD);
568  }
569 
570  double seenInSVD(const Particle* p)
571  {
572  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
573  return realNaN;
574  const MCParticle* mcp = p->getMCParticle();
575  if (!mcp) return realNaN;
576  return mcp->hasSeenInDetector(Const::SVD);
577  }
578 
579  double seenInCDC(const Particle* p)
580  {
581  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
582  return realNaN;
583  const MCParticle* mcp = p->getMCParticle();
584  if (!mcp) return realNaN;
585  return mcp->hasSeenInDetector(Const::CDC);
586  }
587 
588  double seenInTOP(const Particle* p)
589  {
590  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
591  return realNaN;
592  const MCParticle* mcp = p->getMCParticle();
593  if (!mcp) return realNaN;
594  return mcp->hasSeenInDetector(Const::TOP);
595  }
596 
597  double seenInECL(const Particle* p)
598  {
599  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
600  return realNaN;
601  const MCParticle* mcp = p->getMCParticle();
602  if (!mcp) return realNaN;
603  return mcp->hasSeenInDetector(Const::ECL);
604  }
605 
606  double seenInARICH(const Particle* p)
607  {
608  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
609  return realNaN;
610  const MCParticle* mcp = p->getMCParticle();
611  if (!mcp) return realNaN;
612  return mcp->hasSeenInDetector(Const::ARICH);
613  }
614 
615  double seenInKLM(const Particle* p)
616  {
617  if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
618  return realNaN;
619  const MCParticle* mcp = p->getMCParticle();
620  if (!mcp) return realNaN;
621  return mcp->hasSeenInDetector(Const::KLM);
622  }
623 
624  int genNStepsToDaughter(const Particle* p, const std::vector<double>& arguments)
625  {
626  if (arguments.size() != 1)
627  B2FATAL("Wrong number of arguments for genNStepsToDaughter");
628 
629  const MCParticle* mcp = p->getMCParticle();
630  if (!mcp) {
631  B2WARNING("No MCParticle is associated to the particle");
632  return 0;
633  }
634 
635  int nChildren = p->getNDaughters();
636  if (arguments[0] >= nChildren) {
637  return 0;
638  }
639 
640  const Particle* daugP = p->getDaughter(arguments[0]);
641  const MCParticle* daugMCP = daugP->getMCParticle();
642  if (!daugMCP) {
643  // This is a strange case.
644  // The particle, p, has the related MC particle, but i-th daughter does not have the related MC Particle.
645  B2WARNING("No MCParticle is associated to the i-th daughter");
646  return 0;
647  }
648 
649  if (nChildren == 1) return 1;
650 
651  std::vector<int> genMothers;
652  MCMatching::fillGenMothers(daugMCP, genMothers);
653  auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
654  return match - genMothers.begin();
655  }
656 
657  int genNMissingDaughter(const Particle* p, const std::vector<double>& arguments)
658  {
659  if (arguments.size() < 1)
660  B2FATAL("Wrong number of arguments for genNMissingDaughter");
661 
662  const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
663 
664  const MCParticle* mcp = p->getMCParticle();
665  if (!mcp) {
666  B2WARNING("No MCParticle is associated to the particle");
667  return 0;
668  }
669 
670  return MCMatching::countMissingParticle(p, mcp, PDGcodes);
671  }
672 
673  double getHEREnergy(const Particle*)
674  {
675  static DBObjPtr<BeamParameters> beamParamsDB;
676  return (beamParamsDB->getHER()).E();
677  }
678 
679  double getLEREnergy(const Particle*)
680  {
681  static DBObjPtr<BeamParameters> beamParamsDB;
682  return (beamParamsDB->getLER()).E();
683  }
684 
685  double getCrossingAngleX(const Particle*)
686  {
687  // get the beam momenta from the DB
688  static DBObjPtr<BeamParameters> beamParamsDB;
689  B2Vector3D herVec = beamParamsDB->getHER().Vect();
690  B2Vector3D lerVec = beamParamsDB->getLER().Vect();
691 
692  // only looking at the horizontal (XZ plane) -> set y-coordinates to zero
693  herVec.SetY(0);
694  lerVec.SetY(0);
695 
696  //calculate the crossing angle
697  return herVec.Angle(-lerVec);
698  }
699 
700  double getCrossingAngleY(const Particle*)
701  {
702  // get the beam momenta from the DB
703  static DBObjPtr<BeamParameters> beamParamsDB;
704  B2Vector3D herVec = beamParamsDB->getHER().Vect();
705  B2Vector3D lerVec = beamParamsDB->getLER().Vect();
706 
707  // only looking at the vertical (YZ plane) -> set x-coordinates to zero
708  herVec.SetX(0);
709  lerVec.SetX(0);
710 
711  //calculate the crossing angle
712  return herVec.Angle(-lerVec);
713  }
714 
715 
716  double particleClusterMatchWeight(const Particle* particle)
717  {
718  /* Get the weight of the *cluster* mc match for the mcparticle matched to
719  * this particle.
720  *
721  * Note that for track-based particles this is different from the mc match
722  * of the particle (which it inherits from the mc match of the track)
723  */
724  const MCParticle* matchedToParticle = particle->getMCParticle();
725  if (!matchedToParticle) return realNaN;
726  int matchedToIndex = matchedToParticle->getArrayIndex();
727 
728  const ECLCluster* cluster = particle->getECLCluster();
729  if (!cluster) return realNaN;
730 
731  const auto mcps = cluster->getRelationsTo<MCParticle>();
732  for (unsigned int i = 0; i < mcps.size(); ++i)
733  if (mcps[i]->getArrayIndex() == matchedToIndex)
734  return mcps.weight(i);
735 
736  return realNaN;
737  }
738 
739  double particleClusterBestMCMatchWeight(const Particle* particle)
740  {
741  /* Get the weight of the best mc match of the cluster associated to
742  * this particle.
743  *
744  * Note for electrons (or any track-based particle) this may not be
745  * the same thing as the mc match of the particle (which is taken
746  * from the track).
747  *
748  * For photons (or any ECL-based particle) this will be the same as the
749  * mcMatchWeight
750  */
751  const ECLCluster* cluster = particle->getECLCluster();
752  if (!cluster) return realNaN;
753 
754  /* loop over all mcparticles related to this cluster, find the largest
755  * weight by std::sort-ing the doubles
756  */
757  auto mcps = cluster->getRelationsTo<MCParticle>();
758  if (mcps.size() == 0) return realNaN;
759 
760  std::vector<double> weights;
761  for (unsigned int i = 0; i < mcps.size(); ++i)
762  weights.emplace_back(mcps.weight(i));
763 
764  // sort descending by weight
765  std::sort(weights.begin(), weights.end());
766  std::reverse(weights.begin(), weights.end());
767  return weights[0];
768  }
769 
770  double particleClusterBestMCPDGCode(const Particle* particle)
771  {
772  /* Get the PDG code of the best mc match of the cluster associated to this
773  * particle.
774  *
775  * Note for electrons (or any track-based particle) this may not be the
776  * same thing as the mc match of the particle (which is taken from the track).
777  *
778  * For photons (or any ECL-based particle) this will be the same as the mcPDG
779  */
780  const ECLCluster* cluster = particle->getECLCluster();
781  if (!cluster) return realNaN;
782 
783  auto mcps = cluster->getRelationsTo<MCParticle>();
784  if (mcps.size() == 0) return realNaN;
785 
786  std::vector<std::pair<double, int>> weightsAndIndices;
787  for (unsigned int i = 0; i < mcps.size(); ++i)
788  weightsAndIndices.emplace_back(mcps.weight(i), i);
789 
790  // sort descending by weight
791  std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
792  ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
793  // cppcheck-suppress containerOutOfBounds
794  return mcps.object(weightsAndIndices[0].second)->getPDG();
795  }
796 
797  double particleClusterTotalMCMatchWeight(const Particle* particle)
798  {
799  const ECLCluster* cluster = particle->getECLCluster();
800  if (!cluster) return realNaN;
801 
802  auto mcps = cluster->getRelationsTo<MCParticle>();
803 
804  // if there are no relations to any MCParticles, we return 0!
805  double weightsum = 0;
806  for (unsigned int i = 0; i < mcps.size(); ++i)
807  weightsum += mcps.weight(i);
808 
809  return weightsum;
810  }
811 
812  double isBBCrossfeed(const Particle* particle)
813  {
814  if (particle == nullptr)
815  return std::numeric_limits<double>::quiet_NaN();
816 
817  int pdg = particle->getPDGCode();
818  if (abs(pdg) != 511 && abs(pdg) != 521 && abs(pdg) != 531)
819  return std::numeric_limits<double>::quiet_NaN();
820 
821  std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
822  int nDaughters = daughters.size();
823  if (nDaughters <= 1)
824  return 0;
825  std::vector<int> mother_ids;
826 
827  for (int j = 0; j < nDaughters; ++j) {
828  const MCParticle* curMCParticle = daughters[j]->getMCParticle();
829  while (curMCParticle != nullptr) {
830  pdg = curMCParticle->getPDG();
831  if (abs(pdg) == 511 || abs(pdg) == 521 || abs(pdg) == 531) {
832  mother_ids.emplace_back(curMCParticle->getArrayIndex());
833  break;
834  }
835  const MCParticle* curMCMother = curMCParticle->getMother();
836  curMCParticle = curMCMother;
837  }
838  if (curMCParticle == nullptr) {
839  return std::numeric_limits<double>::quiet_NaN();
840  }
841  }
842 
843  std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
844  if (distinctIDs.size() == 1)
845  return 0;
846  else
847  return 1;
848  }
849 
850  VARIABLE_GROUP("MC matching and MC truth");
851  REGISTER_VARIABLE("isSignal", isSignal,
852  "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n"
853  "It behaves according to DecayStringGrammar.");
854  REGISTER_VARIABLE("isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
855  "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
856  "Misidentification of charged FSP is allowed.");
857  REGISTER_VARIABLE("isPrimarySignal", isPrimarySignal,
858  "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
859  REGISTER_VARIABLE("isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
860  "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n"
861  "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
862  REGISTER_VARIABLE("genMotherPDG", genMotherPDG,
863  "Check the PDG code of a particles MC mother particle");
864  REGISTER_VARIABLE("genMotherPDG(i)", genNthMotherPDG,
865  "Check the PDG code of a particles n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc. :noindex:");
866 
867  REGISTER_VARIABLE("genMotherID", genMotherIndex,
868  "Check the array index of a particles generated mother");
869  REGISTER_VARIABLE("genMotherID(i)", genNthMotherIndex,
870  "Check the array index of a particle n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc. :noindex:");
871  // genMotherPDG and genMotherID are overloaded (each are two C++ functions
872  // sharing one variable name) so one of the two needs to be made the indexed
873  // variable in sphinx
874  REGISTER_VARIABLE("isBBCrossfeed", isBBCrossfeed,
875  "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
876  REGISTER_VARIABLE("genMotherP", genMotherP,
877  "Generated momentum of a particles MC mother particle\n\n", "GeV/c");
878  REGISTER_VARIABLE("genParticleID", genParticleIndex,
879  "Check the array index of a particle's related MCParticle");
880  REGISTER_VARIABLE("isSignalAcceptMissingNeutrino",
881  isSignalAcceptMissingNeutrino,
882  "Same as isSignal, but also accept missing neutrino");
883  REGISTER_VARIABLE("isSignalAcceptMissingMassive",
884  isSignalAcceptMissingMassive,
885  "Same as isSignal, but also accept missing massive particle");
886  REGISTER_VARIABLE("isSignalAcceptMissingGamma",
887  isSignalAcceptMissingGamma,
888  "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
889  REGISTER_VARIABLE("isSignalAcceptMissing",
890  isSignalAcceptMissing,
891  "Same as isSignal, but also accept missing particle");
892  REGISTER_VARIABLE("isMisidentified", isMisidentified,
893  "Return 1 if the particle is misidentified: at least one of the final state particles has the wrong PDG code assignment (including wrong charge), 0 if PDG code is fine, and NaN if no related MCParticle could be found.");
894  REGISTER_VARIABLE("isWrongCharge", isWrongCharge,
895  "Return 1 if the charge of the particle is wrongly assigned, 0 if it's the correct charge, and NaN if no related MCParticle could be found.");
896  REGISTER_VARIABLE("isCloneTrack", isCloneTrack,
897  "Return 1 if the charged final state particle comes from a cloned track, 0 if not a clone. Returns NAN if neutral, composite, or MCParticle not found (like for data or if not MCMatched)");
898  REGISTER_VARIABLE("isOrHasCloneTrack", isOrHasCloneTrack,
899  "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
900  REGISTER_VARIABLE("mcPDG", particleMCMatchPDGCode,
901  "The PDG code of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
902  REGISTER_VARIABLE("mcErrors", particleMCErrors,
903  "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
904  REGISTER_VARIABLE("mcMatchWeight", particleMCMatchWeight,
905  "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
906  REGISTER_VARIABLE("nMCMatches", particleNumberOfMCMatch,
907  "The number of relations of this Particle to MCParticle.");
908  REGISTER_VARIABLE("mcDecayTime", particleMCMatchDecayTime,
909  "The decay time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
910  "ns");
911  REGISTER_VARIABLE("mcLifeTime", particleMCMatchLifeTime,
912  "The life time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
913  "ns");
914  REGISTER_VARIABLE("mcPX", particleMCMatchPX,
915  "The px of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
916  "GeV/c");
917  REGISTER_VARIABLE("mcPY", particleMCMatchPY,
918  "The py of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
919  "GeV/c");
920  REGISTER_VARIABLE("mcPZ", particleMCMatchPZ,
921  "The pz of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
922  "GeV/c");
923  REGISTER_VARIABLE("mcPT", particleMCMatchPT,
924  "The pt of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
925  "GeV/c");
926  REGISTER_VARIABLE("mcE", particleMCMatchE,
927  "The energy of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
928  "GeV");
929  REGISTER_VARIABLE("mcP", particleMCMatchP,
930  "The total momentum of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
931  "GeV/c");
932  REGISTER_VARIABLE("mcPhi", particleMCMatchPhi,
933  "The phi of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
934  "rad");
935  REGISTER_VARIABLE("mcTheta", particleMCMatchTheta,
936  "The theta of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
937  "rad");
938  REGISTER_VARIABLE("nMCDaughters", mcParticleNDaughters,
939  "The number of daughters of the matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
940  REGISTER_VARIABLE("mcRecoilMass", particleMCRecoilMass,
941  "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
942  "GeV/:math:`\\text{c}^2`");
943  REGISTER_VARIABLE("mcCosThetaBetweenParticleAndNominalB",
944  particleMCCosThetaBetweenParticleAndNominalB,
945  "Cosine of the angle in CMS between momentum the particle and a nominal B particle. In this calculation, the momenta of all descendant neutrinos are subtracted from the B momentum.");
946 
947 
948  REGISTER_VARIABLE("mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
949  R"DOC(
950 Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle.
951 
952 Returns NaN if the particle is not matched to a MCParticle.
953 
954 Returns -1 in case of unknown process.
955 
956 Returns 0 if the particle is primary, i.e. produced by the event generator and not Geant4. Particles produced by Geant4 (i.e. secondary particles) include those produced in interaction with detector material, Bremsstrahlung, and the decay products of long-lived particles (e.g. muons, pions, K_S0, K_L0, Lambdas, ...).
957 
958 List of possible values (taken from the Geant4 source of
959 `G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_,
960 `G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_,
961 `G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and
962 `G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_)
963 
964 * 1 Coulomb scattering
965 * 2 Ionisation
966 * 3 Bremsstrahlung
967 * 4 Pair production by charged
968 * 5 Annihilation
969 * 6 Annihilation to mu mu
970 * 7 Annihilation to hadrons
971 * 8 Nuclear stopping
972 * 9 Electron general process
973 * 10 Multiple scattering
974 * 11 Rayleigh
975 * 12 Photo-electric effect
976 * 13 Compton scattering
977 * 14 Gamma conversion
978 * 15 Gamma conversion to mu mu
979 * 16 Gamma general process
980 * 21 Cerenkov
981 * 22 Scintillation
982 * 23 Synchrotron radiation
983 * 24 Transition radiation
984 * 91 Transportation
985 * 92 Coupled transportation
986 * 111 Hadron elastic
987 * 121 Hadron inelastic
988 * 131 Capture
989 * 132 Mu atomic capture
990 * 141 Fission
991 * 151 Hadron at rest
992 * 152 Lepton at rest
993 * 161 Charge exchange
994 * 201 Decay
995 * 202 Decay with spin
996 * 203 Decay (pion make spin)
997 * 210 Radioactive decay
998 * 211 Unknown decay
999 * 221 Mu atom decay
1000 * 231 External decay
1001 
1002 .. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``.
1003 )DOC");
1004  REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
1005  "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
1006  REGISTER_VARIABLE("mcPrimary", particleMCPrimaryParticle,
1007  "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, "
1008  "NaN if Particle is not related to MCParticle.");
1009  REGISTER_VARIABLE("mcVirtual", particleMCVirtualParticle,
1010  "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, "
1011  "NaN if Particle is not related to MCParticle.")
1012  REGISTER_VARIABLE("mcInitial", particleMCInitialParticle,
1013  "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, "
1014  "NaN if Particle is not related to MCParticle.")
1015  REGISTER_VARIABLE("mcISR", particleMCISRParticle,
1016  "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, "
1017  "NaN if Particle is not related to MCParticle.")
1018  REGISTER_VARIABLE("mcFSR", particleMCFSRParticle,
1019  "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ,"
1020  "NaN if Particle is not related to MCParticle.")
1021  REGISTER_VARIABLE("mcPhotos", particleMCPhotosParticle,
1022  "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, "
1023  "NaN if Particle is not related to MCParticle.")
1024  REGISTER_VARIABLE("generatorEventWeight", generatorEventWeight,
1025  "[Eventbased] Returns the event weight produced by the event generator")
1026 
1027  REGISTER_VARIABLE("genNStepsToDaughter(i)", genNStepsToDaughter,
1028  "Returns number of steps to i-th daughter from the particle at generator level. "
1029  "NaN if no MCParticle is associated to the particle or i-th daughter. "
1030  "NaN if i-th daughter does not exist.");
1031  REGISTER_VARIABLE("genNMissingDaughter(PDG)", genNMissingDaughter,
1032  "Returns the number of missing daughters having assigned PDG codes. "
1033  "NaN if no MCParticle is associated to the particle.");
1034  REGISTER_VARIABLE("Eher", getHEREnergy, R"DOC(
1035 [Eventbased] The nominal HER energy used by the generator.
1036 
1037 .. warning:: This variable does not make sense for data.
1038 
1039 )DOC","GeV");
1040  REGISTER_VARIABLE("Eler", getLEREnergy, R"DOC(
1041 [Eventbased] The nominal LER energy used by the generator.
1042 
1043 .. warning:: This variable does not make sense for data.
1044 
1045 )DOC","GeV");
1046  REGISTER_VARIABLE("XAngle", getCrossingAngleX, R"DOC(
1047 [Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics.
1048 
1049 .. warning:: This variable does not make sense for data.
1050 
1051 )DOC","rad");
1052  REGISTER_VARIABLE("YAngle", getCrossingAngleY, R"DOC(
1053 [Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics.
1054 
1055 .. warning:: This variable does not make sense for data.
1056 
1057 )DOC","rad");
1058 
1059  VARIABLE_GROUP("Generated tau decay information");
1060  REGISTER_VARIABLE("tauPlusMCMode", tauPlusMcMode,
1061  "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
1062  REGISTER_VARIABLE("tauMinusMCMode", tauMinusMcMode,
1063  "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
1064  REGISTER_VARIABLE("tauPlusMCProng", tauPlusMcProng,
1065  "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
1066  REGISTER_VARIABLE("tauMinusMCProng", tauMinusMcProng,
1067  "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
1068 
1069  VARIABLE_GROUP("MC particle seen in subdetectors");
1070  REGISTER_VARIABLE("isReconstructible", isReconstructible,
1071  "Checks charged particles were seen in the SVD and neutrals in the ECL, returns 1.0 if so, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1072  REGISTER_VARIABLE("seenInPXD", seenInPXD,
1073  "Returns 1.0 if the MC particle was seen in the PXD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1074  REGISTER_VARIABLE("seenInSVD", seenInSVD,
1075  "Returns 1.0 if the MC particle was seen in the SVD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1076  REGISTER_VARIABLE("seenInCDC", seenInCDC,
1077  "Returns 1.0 if the MC particle was seen in the CDC, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1078  REGISTER_VARIABLE("seenInTOP", seenInTOP,
1079  "Returns 1.0 if the MC particle was seen in the TOP, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1080  REGISTER_VARIABLE("seenInECL", seenInECL,
1081  "Returns 1.0 if the MC particle was seen in the ECL, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1082  REGISTER_VARIABLE("seenInARICH", seenInARICH,
1083  "Returns 1.0 if the MC particle was seen in the ARICH, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1084  REGISTER_VARIABLE("seenInKLM", seenInKLM,
1085  "Returns 1.0 if the MC particle was seen in the KLM, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
1086 
1087  VARIABLE_GROUP("MC Matching for ECLClusters");
1088  REGISTER_VARIABLE("clusterMCMatchWeight", particleClusterMatchWeight,
1089  "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. "
1090  "Returns NaN if: no cluster is related to the particle, the particle is not MC matched, or if there are no mcmatches for the cluster. "
1091  "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
1092  REGISTER_VARIABLE("clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
1093  "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
1094  REGISTER_VARIABLE("clusterBestMCPDG", particleClusterBestMCPDGCode,
1095  "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
1096  REGISTER_VARIABLE("clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
1097  "Returns the sum of all weights of the ECLCluster -> MCParticles relations.");
1098 
1099  }
1101 }
void SetX(DataType x)
set X/1st-coordinate
Definition: B2Vector3.h:457
void SetY(DataType y)
set Y/2nd-coordinate
Definition: B2Vector3.h:459
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:609
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
Definition: MCParticle.h:61
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
Definition: MCParticle.h:57
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition: MCParticle.h:63
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
Definition: MCParticle.h:55
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
Definition: MCParticle.h:59
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:946
static const ReferenceFrame & GetCurrent()
Get current rest frame.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23
static int countMissingParticle(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle, const std::vector< int > &daughterPDG)
Count the number of missing daughters of the 'particle'.
Definition: MCMatching.cc:561
@ c_Correct
This Particle and all its daughters are perfectly reconstructed.
Definition: MCMatching.h:34
@ c_MisID
One of the charged final state particles is mis-identified, i.e.
Definition: MCMatching.h:42
static int getMCErrors(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...
Definition: MCMatching.cc:282
static void fillGenMothers(const Belle2::MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.
Definition: MCMatching.cc:61