Belle II Software development
Particle.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#include <analysis/dataobjects/Particle.h>
10#include <analysis/dataobjects/ParticleExtraInfoMap.h>
11
12#include <analysis/ClusterUtility/ClusterUtils.h>
13
14#include <mdst/dataobjects/Kink.h>
15#include <mdst/dataobjects/KLMCluster.h>
16#include <mdst/dataobjects/MCParticle.h>
17#include <mdst/dataobjects/PIDLikelihood.h>
18#include <mdst/dataobjects/Track.h>
19#include <mdst/dataobjects/TrackFitResult.h>
20#include <mdst/dataobjects/V0.h>
21#include <mdst/dbobjects/CollisionBoostVector.h>
22#include <mdst/dbobjects/CollisionInvariantMass.h>
23
24#include <framework/datastore/StoreArray.h>
25#include <framework/datastore/StoreObjPtr.h>
26#include <framework/database/DBObjPtr.h>
27#include <framework/logging/Logger.h>
28#include <framework/utilities/HTML.h>
29#include <framework/utilities/Conversion.h>
30
31#include <TClonesArray.h>
32#include <TDatabasePDG.h>
33#include <TMatrixFSym.h>
34#include <Math/Boost.h>
35
36#include <cmath>
37#include <iomanip>
38#include <stdexcept>
39#include <queue>
40
41#include <boost/algorithm/string.hpp>
42
43using namespace Belle2;
44using namespace ROOT::Math;
45
47 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
48 m_pValue(nan("")), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0),
49 m_properties(0),
50 m_arrayPointer(nullptr)
51{
53}
54
55
56Particle::Particle(const ROOT::Math::PxPyPzEVector& momentum, const int pdgCode) :
57 m_pdgCode(pdgCode), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
58 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0), m_properties(0),
59 m_arrayPointer(nullptr)
60{
62 set4Vector(momentum);
64 // set mass of stable charged particle to its nominal value
67 }
68}
69
70
71Particle::Particle(const ROOT::Math::PxPyPzEVector& momentum,
72 const int pdgCode,
73 EFlavorType flavorType,
74 const EParticleSourceObject source,
75 const unsigned mdstIndex) :
76 m_pdgCode(pdgCode), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
77 m_pValue(-1), m_flavorType(flavorType), m_particleSource(source), m_trackFitResultIndex(0), m_properties(0), m_arrayPointer(nullptr)
78{
79 if (flavorType == c_Unflavored and pdgCode < 0)
80 m_pdgCode = -pdgCode;
81
82 setMdstArrayIndex(mdstIndex);
83 set4Vector(momentum);
85 // set mass of stable charged particle to its nominal value
88 }
89}
90
91
92Particle::Particle(const ROOT::Math::PxPyPzEVector& momentum,
93 const int pdgCode,
94 EFlavorType flavorType,
95 const std::vector<int>& daughterIndices,
96 TClonesArray* arrayPointer) :
97 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
98 m_pValue(-1),
99 m_daughterIndices(daughterIndices),
100 m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0),
101 m_properties(0), m_arrayPointer(arrayPointer)
102{
103 m_pdgCode = pdgCode;
104 m_flavorType = flavorType;
105 if (flavorType == c_Unflavored and pdgCode < 0)
106 m_pdgCode = -pdgCode;
107 set4Vector(momentum);
109 // set mass of stable charged particle to its nominal value
112 }
113
114 if (!daughterIndices.empty()) {
115 m_particleSource = c_Composite;
116 if (getArrayPointer() == nullptr) {
117 B2FATAL("Composite Particle (with daughters) was constructed outside StoreArray without specifying daughter array!");
118 }
119 for (unsigned int i = 0; i < m_daughterIndices.size(); i++) {
120 m_daughterProperties.push_back(Particle::PropertyFlags::c_Ordinary);
121 }
122 }
123}
124
125Particle::Particle(const ROOT::Math::PxPyPzEVector& momentum,
126 const int pdgCode,
127 EFlavorType flavorType,
128 const std::vector<int>& daughterIndices,
129 const int properties,
130 TClonesArray* arrayPointer) :
131 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
132 m_pValue(-1),
133 m_daughterIndices(daughterIndices),
134 m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0),
135 m_arrayPointer(arrayPointer)
136{
137 m_pdgCode = pdgCode;
138 m_flavorType = flavorType;
139 if (flavorType == c_Unflavored and pdgCode < 0)
140 m_pdgCode = -pdgCode;
141 set4Vector(momentum);
143 // set mass of stable charged particle to its nominal value
146 }
147 m_properties = properties;
148
149 if (!daughterIndices.empty()) {
150 m_particleSource = c_Composite;
151 if (getArrayPointer() == nullptr) {
152 B2FATAL("Composite Particle (with daughters) was constructed outside StoreArray without specifying daughter array!");
153 }
154 for (unsigned int i = 0; i < m_daughterIndices.size(); i++) {
155 m_daughterProperties.push_back(Particle::PropertyFlags::c_Ordinary);
156 }
157 }
158}
159
160
161Particle::Particle(const ROOT::Math::PxPyPzEVector& momentum,
162 const int pdgCode,
163 EFlavorType flavorType,
164 const std::vector<int>& daughterIndices,
165 const int properties,
166 const std::vector<int>& daughterProperties,
167 TClonesArray* arrayPointer) :
168 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
169 m_pValue(-1),
170 m_daughterIndices(daughterIndices),
171 m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0),
172 m_daughterProperties(daughterProperties),
173 m_arrayPointer(arrayPointer)
174{
175 m_pdgCode = pdgCode;
176 m_flavorType = flavorType;
177 if (flavorType == c_Unflavored and pdgCode < 0)
178 m_pdgCode = -pdgCode;
179 set4Vector(momentum);
181 // set mass of stable charged particle to its nominal value
184 }
185 m_properties = properties;
186
187 if (!daughterIndices.empty()) {
188 m_particleSource = c_Composite;
189 if (getArrayPointer() == nullptr) {
190 B2FATAL("Composite Particle (with daughters) was constructed outside StoreArray without specifying daughter array!");
191 }
192 }
193}
194
195
197 const Const::ChargedStable& chargedStable) :
198 Particle(track ? track->getArrayIndex() : 0, track ? track->getTrackFitResultWithClosestMass(chargedStable) : nullptr,
199 chargedStable)
200{
201}
202
203Particle::Particle(const int trackArrayIndex,
204 const TrackFitResult* trackFit,
205 const Const::ChargedStable& chargedStable) :
206 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
207 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0), m_properties(0),
208 m_arrayPointer(nullptr)
209{
210 if (!trackFit) return;
211
212 m_flavorType = c_Flavored; //tracks are charged
213 m_particleSource = c_Track;
214
215 setMdstArrayIndex(trackArrayIndex);
216
218 m_pdgCode = generatePDGCodeFromCharge(trackFit->getChargeSign(), chargedStable);
219
220 // set mass
221 if (TDatabasePDG::Instance()->GetParticle(m_pdgCode) == nullptr)
222 B2FATAL("PDG=" << m_pdgCode << " ***code unknown to TDatabasePDG");
223 m_mass = TDatabasePDG::Instance()->GetParticle(m_pdgCode)->Mass() ;
224
225 // set momentum, position and error matrix
227}
228
229Particle::Particle(const Kink* kink, const Const::ChargedStable& chargedStable, const unsigned trackFitResultIndex) :
230 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
231 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_trackFitResultIndex(0), m_properties(0),
232 m_arrayPointer(nullptr)
233{
234 if (!kink) return;
235
237 m_particleSource = c_Kink;
238
240 m_trackFitResultIndex = trackFitResultIndex;
241
242 StoreArray<TrackFitResult> trackFitResults{};
243 const TrackFitResult* particleTrackFitResult = trackFitResults[m_trackFitResultIndex];
244
245 m_pdgCode = generatePDGCodeFromCharge(particleTrackFitResult->getChargeSign(), chargedStable);
246
247 // set mass
248 if (TDatabasePDG::Instance()->GetParticle(m_pdgCode) == nullptr)
249 B2FATAL("PDG=" << m_pdgCode << " ***code unknown to TDatabasePDG");
250 m_mass = TDatabasePDG::Instance()->GetParticle(m_pdgCode)->Mass() ;
251
252 // set momentum, position and error matrix
253 setMomentumPositionErrorMatrix(particleTrackFitResult);
254}
255
256Particle::Particle(const ECLCluster* eclCluster, const Const::ParticleType& type) :
257 m_pdgCode(type.getPDGCode()), m_mass(type.getMass()), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
258 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_properties(0), m_arrayPointer(nullptr)
259{
260 if (!eclCluster) return;
261
263
264 // returns default vertex from clusterutils (from beam parameters if available)
265 // leave it like that for the moment to make it transparent
266 ClusterUtils C;
267 const XYZVector clustervertex = C.GetIPPosition();
268 setVertex(clustervertex);
269
270 const PxPyPzEVector clustermom = C.Get4MomentumFromCluster(eclCluster, clustervertex, getECLClusterEHypothesisBit());
271 m_px = clustermom.Px();
272 m_py = clustermom.Py();
273 m_pz = clustermom.Pz();
274
275 m_particleSource = c_ECLCluster;
276 setMdstArrayIndex(eclCluster->getArrayIndex());
277
278 // set Chi^2 probability:
279 //TODO: gamma quality can be written here
280 m_pValue = 1;
281
282 // get error matrix.
284
285}
286
287
289{
290 ClusterUtils C;
291
292 const ECLCluster* cluster = this->getECLCluster();
293
294 const XYZVector clustervertex = C.GetIPPosition();
295
296 // Get Jacobi matrix.
297 TMatrixD jacobi = C.GetJacobiMatrix4x6FromCluster(cluster, clustervertex, getECLClusterEHypothesisBit());
298 storeJacobiMatrix(jacobi);
299
300 // Propagate the photon energy scaling to jacobian elements that were calculated using energy.
301 TMatrixD scaledJacobi(4, 6);
302
303 int element = 0;
304
305 for (int irow = 0; irow < 4; irow++) {
306 for (int icol = 0; icol < 6; icol++) {
307 if (icol != 0 && irow != 3) {
308 scaledJacobi(irow, icol) = m_jacobiMatrix[element] * m_momentumScale;
309 } else {
310 scaledJacobi(irow, icol) = m_jacobiMatrix[element];
311 }
312 element++;
313 }
314 }
315
316 storeJacobiMatrix(scaledJacobi);
317
318 // Get covariance matrix of IP distribution.
319 const TMatrixDSym clustervertexcovmat = C.GetIPPositionCovarianceMatrix();
320
321 // Set error matrix.
322 TMatrixDSym clustercovmat = C.GetCovarianceMatrix7x7FromCluster(cluster, clustervertexcovmat, scaledJacobi);
323 storeErrorMatrix(clustercovmat);
324}
325
326Particle::Particle(const KLMCluster* klmCluster, const int pdgCode) :
327 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
328 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_properties(0), m_arrayPointer(nullptr)
329{
330 if (!klmCluster) return;
331
332 m_pdgCode = pdgCode;
334
335 set4Vector(klmCluster->getMomentum());
336 setVertex(XYZVector(0, 0, 0)); // so far KLMCluster don't provide reliable / usable position information
337 updateMass(m_pdgCode); // KLMCluster internally use Klong mass, overwrite here to allow neutrons
338
339 m_particleSource = c_KLMCluster;
340 setMdstArrayIndex(klmCluster->getArrayIndex());
341
342 // set Chi^2 probability:
343 //TODO: KL quality can be written here
344 m_pValue = -1;
345
346 // TODO: set error matrix
348 //storeErrorMatrix(klmCluster->getErrorMatrix());
349}
350
351
352Particle::Particle(const MCParticle* mcParticle) :
353 m_pdgCode(0), m_mass(0), m_px(0), m_py(0), m_pz(0), m_x(0), m_y(0), m_z(0),
354 m_pValue(-1), m_flavorType(c_Unflavored), m_particleSource(c_Undefined), m_mdstIndex(0), m_properties(0), m_arrayPointer(nullptr)
355{
356 if (!mcParticle) return;
357
358 m_pdgCode = mcParticle->getPDG();
359 m_particleSource = c_MCParticle; // TODO: what about daughters if not FS particle?
360
361 setMdstArrayIndex(mcParticle->getArrayIndex());
362
363
365
366 // mass and momentum
367 m_mass = mcParticle->getMass();
368 m_px = mcParticle->getMomentum().X();
369 m_py = mcParticle->getMomentum().Y();
370 m_pz = mcParticle->getMomentum().Z();
371 // production vertex
372 // TODO: good only for FS particles, for composite we must use decay vertex
373 setVertex(mcParticle->getVertex());
374
376}
377
378
379Particle::~Particle() = default;
380
381void Particle::setMdstArrayIndex(const int arrayIndex)
382{
383 m_mdstIndex = arrayIndex;
384
385 // set the identifier
386 if (m_particleSource == c_ECLCluster) {
387 const ECLCluster* cluster = this->getECLCluster();
388 if (cluster) {
389 m_identifier = cluster->getUniqueClusterId();
390 } else {
391 B2ERROR("Particle is of type = ECLCluster has identifier not set and no relation to ECLCluster.\n"
392 "This has happen because old microDST is analysed with newer version of software.");
393 }
394 } else {
396 }
397}
398
399
401{
402 // Is identifier already set
403 if (m_identifier > -1)
404 return m_identifier + (m_particleSource << 24);
405
406 // Identifier is not set.
407 int identifier = 0;
408 if (m_particleSource == c_ECLCluster) {
409 const ECLCluster* cluster = this->getECLCluster();
410 if (cluster) {
411 identifier = cluster->getUniqueClusterId();
412 } else {
413 B2ERROR("Particle is of type = ECLCluster has identifier not set and no relation to ECLCluster.\n"
414 "This has happen because old microDST is analysed with newer version of software.");
415 }
416 } else {
417 identifier = m_mdstIndex;
418 }
419
420 return identifier + (m_particleSource << 24);
421}
422
423
425{
426 // check if provided Error Matrix is of dimension 7x7
427 // if not, reset the error matrix and print warning
428 if (m.GetNrows() != c_DimMatrix || m.GetNcols() != c_DimMatrix) {
430 B2WARNING("Error Matrix is not 7x7 ");
431 return;
432 }
434
435}
436
437
438void Particle::setJacobiMatrix(const TMatrixF& m)
439{
440 // check if provided Jacobi Matrix is of dimension 4x6
441 // if not, reset the error matrix and print warning
442 if (m.GetNrows() != 4 || m.GetNcols() != 6) {
444 B2WARNING("Jacobi Matrix is not 4x6 ");
445 return;
446 }
448}
449
450
452{
453 TMatrixFSym m(c_DimMatrix);
454
455 int element = 0;
456 for (int irow = 0; irow < c_DimMatrix; irow++) {
457 for (int icol = irow; icol < c_DimMatrix; icol++) {
458 m(irow, icol) = m(icol, irow) = m_errMatrix[element];
459 element++;
460 }
461 }
462 return m;
463}
464
465
467{
468 TMatrixFSym mom;
469 const TMatrixFSym& full = getMomentumVertexErrorMatrix();
470
471 // get 4x4 (momentum) submatrix from the full error matrix
472 // momentum related elements are in [0,...,3]x[0,...,3] block
473 full.GetSub(0, 3, mom, "S");
474
475 return mom;
476}
477
479{
480 TMatrixFSym pos;
481 const TMatrixFSym& full = getMomentumVertexErrorMatrix();
482
483 // get 3x3 (position) submatrix from the full error matrix
484 // vertex related elements are in [4,5,6]x[4,5,6] block
485 full.GetSub(4, 6, pos, "S");
486
487 return pos;
488}
489
490double Particle::getCosHelicity(const Particle* mother) const
491{
492 // boost vector to the rest frame of the particle
493 Boost boost(get4Vector().BoostToCM());
494
495 // momentum of the mother in the particle's rest frame
496 PxPyPzEVector pMother;
497 if (mother) {
498 pMother = mother->get4Vector();
499 } else {
500 static DBObjPtr<CollisionBoostVector> cmsBoost;
502 pMother.SetE(cmsMass->getMass());
503 pMother = Boost(cmsBoost->getBoost()) * pMother;
504 }
505 pMother = boost * pMother;
506
507 // momentum of the daughter (or normal vector) in the particle's rest frame
508 PxPyPzEVector pDaughter;
509 if (getNDaughters() == 2) { // two body decay
510 pDaughter = boost * getDaughter(0)->get4Vector();
511 } else if (getNDaughters() == 3) {
512 if (getPDGCode() == Const::pi0.getPDGCode()) { // pi0 Dalitz decay
513 for (auto& daughter : getDaughters()) {
514 if (daughter->getPDGCode() == Const::photon.getPDGCode()) {
515 pDaughter = daughter->get4Vector();
516 }
517 }
518 pDaughter = boost * pDaughter;
519 } else { // three body decay
520 PxPyPzEVector pDaughter0 = boost * getDaughter(0)->get4Vector();
521 PxPyPzEVector pDaughter1 = boost * getDaughter(1)->get4Vector();
522
523 XYZVector pDaughterNormal(pDaughter0.Vect().Cross(pDaughter1.Vect()));
524 pDaughter.SetPxPyPzE(pDaughterNormal.X(), pDaughterNormal.Y(), pDaughterNormal.Z(), 0); // energy doesn't matter
525 }
526 }
527
528 double mag2 = pMother.P2() * pDaughter.P2();
529 if (mag2 <= 0) return std::numeric_limits<double>::quiet_NaN();
530 return -pMother.Vect().Dot(pDaughter.Vect()) / sqrt(mag2);
531}
532
533double Particle::getCosHelicityDaughter(unsigned iDaughter, unsigned iGrandDaughter) const
534{
535 // check existence of daughter
536 if (getNDaughters() <= iDaughter) {
537 B2ERROR("No daughter of particle 'name' with index 'iDaughter' for calculation of helicity angle"
538 << LogVar("name", getName()) << LogVar("iDaughter", iDaughter));
539 return std::numeric_limits<double>::quiet_NaN();
540 }
541
542 // boost vector to the rest frame of the daughter particle
543 const Particle* daughter = getDaughter(iDaughter);
544 Boost boost(daughter->get4Vector().BoostToCM());
545
546 // momentum of the this particle in the daughter's rest frame
547 PxPyPzEVector pMother = boost * get4Vector();
548
549 // check existence of grand daughter
550 if (daughter->getNDaughters() <= iGrandDaughter) {
551 B2ERROR("No grand daughter of daughter 'iDaughter' of particle 'name' with index 'iGrandDaughter' for calculation of helicity angle"
552 << LogVar("name", getName()) << LogVar("iDaughter", iDaughter) << LogVar("iGrandDaughter", iGrandDaughter));
553 return std::numeric_limits<double>::quiet_NaN();
554 }
555
556 // momentum of the grand daughter in the daughter's rest frame
557 PxPyPzEVector pGrandDaughter = boost * daughter->getDaughter(iGrandDaughter)->get4Vector();
558
559 double mag2 = pMother.P2() * pGrandDaughter.P2();
560 if (mag2 <= 0) return std::numeric_limits<double>::quiet_NaN();
561 return -pMother.Vect().Dot(pGrandDaughter.Vect()) / sqrt(mag2);
562}
563
565{
566 // check that we have a decay to two daughters and then two grand daughters each
567 if (getNDaughters() != 2) {
568 B2ERROR("Cannot calculate acoplanarity of particle 'name' because the number of daughters is not 2"
569 << LogVar("name", getName()) << LogVar("# of daughters", getNDaughters()));
570 return std::numeric_limits<double>::quiet_NaN();
571 }
572 const Particle* daughter0 = getDaughter(0);
573 const Particle* daughter1 = getDaughter(1);
574 if ((daughter0->getNDaughters() != 2) || (daughter1->getNDaughters() != 2)) {
575 B2ERROR("Cannot calculate acoplanarity of particle 'name' because the number of grand daughters is not 2"
576 << LogVar("name", getName()) << LogVar("# of grand daughters of first daughter", daughter0->getNDaughters())
577 << LogVar("# of grand daughters of second daughter", daughter1->getNDaughters()));
578 return std::numeric_limits<double>::quiet_NaN();
579 }
580
581 // boost vector to the rest frame of the particle
582 Boost boost(get4Vector().BoostToCM());
583
584 // momenta of the daughters and grand daughters in the particle's rest frame
585 PxPyPzEVector pDaughter0 = boost * daughter0->get4Vector();
586 PxPyPzEVector pGrandDaughter0 = boost * daughter0->getDaughter(0)->get4Vector();
587 PxPyPzEVector pDaughter1 = boost * daughter1->get4Vector();
588 PxPyPzEVector pGrandDaughter1 = boost * daughter1->getDaughter(0)->get4Vector();
589
590 // calculate angle between normal vectors
591 XYZVector normal0 = pDaughter0.Vect().Cross(pGrandDaughter0.Vect());
592 XYZVector normal1 = -pDaughter1.Vect().Cross(pGrandDaughter1.Vect());
593 double result = acos(normal0.Unit().Dot(normal1.Unit()));
594 if (normal0.Cross(normal1).Dot(pDaughter0.Vect()) < 0) result = -result;
595
596 return result;
597}
598
599
600/*
601double Particle::getMassError(void) const
602{
603 double result = 0.0;
604
605 if(m_pValue<0)
606 return result;
607
608 double invMass = getMass();
609
610 TMatrixFSym covarianceMatrix = getMomentumErrorMatrix();
611 TVectorF jacobian(c_DimMomentum);
612 jacobian[0] = -1.0*getPx()/invMass;
613 jacobian[1] = -1.0*getPy()/invMass;
614 jacobian[2] = -1.0*getPz()/invMass;
615 jacobian[3] = 1.0*getEnergy()/invMass;
616
617 result = jacobian * (covarianceMatrix * jacobian);
618
619 covarianceMatrix.Print();
620
621 if(result<0.0)
622 result = 0.0;
623
624 return TMath::Sqrt(result);
625}
626*/
627
628void Particle::updateMass(const int pdgCode)
629{
630 if (TDatabasePDG::Instance()->GetParticle(pdgCode) == nullptr)
631 B2FATAL("PDG=" << pdgCode << " ***code unknown to TDatabasePDG");
632 m_mass = TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass() ;
633}
634
636{
637 if (TDatabasePDG::Instance()->GetParticle(m_pdgCode) == nullptr) {
638 B2ERROR("PDG=" << m_pdgCode << " ***code unknown to TDatabasePDG");
639 return 0.0;
640 }
641 return TDatabasePDG::Instance()->GetParticle(m_pdgCode)->Mass();
642}
643
645{
646 if (TDatabasePDG::Instance()->GetParticle(m_pdgCode) == nullptr) {
647 B2ERROR("PDG=" << m_pdgCode << " ***code unknown to TDatabasePDG");
648 return 0.0;
649 }
650 return TDatabasePDG::Instance()->GetParticle(m_pdgCode)->Lifetime();
651}
652
654{
655 if (TDatabasePDG::Instance()->GetParticle(m_pdgCode) == nullptr) {
656 B2ERROR("PDG=" << m_pdgCode << " ***code unknown to TDatabasePDG");
657 return 0.0;
658 }
659 return TDatabasePDG::Instance()->GetParticle(m_pdgCode)->Charge() / 3.0;
660}
661
662const Particle* Particle::getDaughter(unsigned i) const
663{
664 if (i >= getNDaughters()) return nullptr;
665 return static_cast<Particle*>(getArrayPointer()->At(m_daughterIndices[i]));
666}
667
668std::vector<Belle2::Particle*> Particle::getDaughters() const
669{
670 const unsigned int nDaughters = getNDaughters();
671 std::vector<Particle*> daughters(nDaughters);
672
673 const TClonesArray* array = getArrayPointer();
674 for (unsigned i = 0; i < nDaughters; i++)
675 daughters[i] = static_cast<Particle*>(array->At(m_daughterIndices[i]));
676
677 return daughters;
678}
679
680std::vector<const Belle2::Particle*> Particle::getFinalStateDaughters() const
681{
682 std::vector<const Particle*> fspDaughters;
683 fillFSPDaughters(fspDaughters);
684
685 return fspDaughters;
686}
687
688std::vector<const Belle2::Particle*> Particle::getAllDaughters() const
689{
690 std::vector<const Particle*> allDaughters;
691 fillAllDaughters(allDaughters);
692
693 return allDaughters;
694}
695
697{
698 std::vector<int> mdstIndices;
699 for (const Particle* fsp : getFinalStateDaughters()) {
700 // is this FSP daughter constructed from given MDST source
701 if (fsp->getParticleSource() == source)
702 mdstIndices.push_back(fsp->getMdstArrayIndex());
703 }
704 return mdstIndices;
705}
706
707void Particle::appendDaughter(const Particle* daughter, const bool updateType, const int daughterProperty)
708{
709 if (updateType) {
710 // is it a composite particle or fsr corrected?
711 m_particleSource = c_Composite;
712 }
713
714 // add daughter index
715 m_daughterIndices.push_back(daughter->getArrayIndex());
716 m_daughterProperties.push_back(daughterProperty);
717}
718
719void Particle::removeDaughter(const Particle* daughter, const bool updateType)
720{
721 if (getNDaughters() == 0)
722 return;
723
724 for (unsigned i = 0; i < getNDaughters(); i++) {
725 if (m_daughterIndices[i] == daughter->getArrayIndex()) {
726 m_daughterIndices.erase(m_daughterIndices.begin() + i);
728 i--;
729 }
730 }
731
732 if (getNDaughters() == 0 and updateType)
733 m_particleSource = c_Undefined;
734}
735
736bool Particle::replaceDaughter(const Particle* oldDaughter, Particle* newDaughter)
737{
738 int index = oldDaughter->getArrayIndex();
739
740 for (unsigned i = 0; i < getNDaughters(); i++) {
741 if (m_daughterIndices[i] == index) {
742 auto ite_index = m_daughterIndices.erase(m_daughterIndices.begin() + i);
743 m_daughterIndices.insert(ite_index, newDaughter->getArrayIndex());
744 auto ite_property = m_daughterProperties.erase(m_daughterProperties.begin() + i);
745 m_daughterProperties.insert(ite_property, Particle::PropertyFlags::c_Ordinary);
746
747 newDaughter->writeExtraInfo("original_index", index);
748 return true;
749 }
750 }
751 return false;
752}
753
754bool Particle::replaceDaughterRecursively(const Particle* oldDaughter, Particle* newDaughter)
755{
756 bool isReplaced = this->replaceDaughter(oldDaughter, newDaughter);
757 if (isReplaced)
758 return true;
759 for (auto& daughter : this->getDaughters()) {
760 isReplaced = daughter->replaceDaughterRecursively(oldDaughter, newDaughter);
761 if (isReplaced)
762 return true;
763 }
764 return false;
765}
766
767
768bool Particle::overlapsWith(const Particle* oParticle) const
769{
770 // obtain vectors of daughter final state particles
771 std::vector<const Particle*> thisFSPs = this->getFinalStateDaughters();
772 std::vector<const Particle*> otherFSPs = oParticle->getFinalStateDaughters();
773
774 // check if they share any of the FSPs
775 for (auto& thisFSP : thisFSPs)
776 for (auto& otherFSP : otherFSPs)
777 if (thisFSP->getMdstSource() == otherFSP->getMdstSource())
778 return true;
779
780 return false;
781}
782
783bool Particle::isCopyOf(const Particle* oParticle, bool doDetailedComparison) const
784{
785 // the name of the game is to as quickly as possible determine
786 // that the Particles are not copies
787 if (this->getPDGCode() != oParticle->getPDGCode() and !doDetailedComparison)
788 return false;
789
790 unsigned nDaughters = this->getNDaughters();
791 if (nDaughters != oParticle->getNDaughters())
792 return false;
793
794 if (nDaughters) {
795 // has daughters: check if the decay chain is the same and it ends with
796 // the same FSPs
797 std::vector<int> thisDecayChain(nDaughters * 2);
798 std::vector<int> othrDecayChain(nDaughters * 2);
799
800 for (unsigned i = 0; i < nDaughters; i++) {
801 this->getDaughter(i)->fillDecayChain(thisDecayChain);
802 oParticle->getDaughter(i)->fillDecayChain(othrDecayChain);
803 }
804
805 // Even if the daughters have been provided in a different order in the
806 // decay string the particles should be identified as copies / duplicates.
807 // Therefore, the decay chain vectors, which contain both the pdg codes and
808 // the mdst sources, are sorted here before comparing them.
809 sort(thisDecayChain.begin(), thisDecayChain.end());
810 sort(othrDecayChain.begin(), othrDecayChain.end());
811
812 for (unsigned i = 0; i < thisDecayChain.size(); i++)
813 if (thisDecayChain[i] != othrDecayChain[i])
814 return false;
815
816 } else if (this->getMdstSource() != oParticle->getMdstSource() and !doDetailedComparison) {
817 // has no daughters: it's a FSP, compare MDST source and index
818 // Check if this or compared particle is a kink. If so, check that the particle is not a copy of daughter or mother.
819 // For consistency, return true if the daughter or mother is a copy of the target particle.
820 if (this->getParticleSource() == EParticleSourceObject::c_Kink &&
821 oParticle->getParticleSource() == EParticleSourceObject::c_Track) {
822 const Kink* kink = this->getKink();
823 const short motherTrackIndex = kink->getMotherTrackIndex();
824 const short daughterTrackIndex = kink->getDaughterTrackIndex();
825 const short trackIndex = oParticle->getTrack()->getArrayIndex();
826 if (trackIndex == motherTrackIndex || trackIndex == daughterTrackIndex)
827 return true;
828 }
829 if (this->getParticleSource() == EParticleSourceObject::c_Track &&
830 oParticle->getParticleSource() == EParticleSourceObject::c_Kink) {
831 const Kink* kink = oParticle->getKink();
832 const short motherTrackIndex = kink->getMotherTrackIndex();
833 const short daughterTrackIndex = kink->getDaughterTrackIndex();
834 const short trackIndex = this->getTrack()->getArrayIndex();
835 if (trackIndex == motherTrackIndex || trackIndex == daughterTrackIndex)
836 return true;
837 }
838 return false;
839 }
840 // Stop here if we do not want a detailed comparison
841 if (!doDetailedComparison)
842 return true;
843 //If we compare here a reconstructed Particle to a generated MCParticle
844 //it means that something went horribly wrong and we must stop
845 if ((this->getParticleSource() == EParticleSourceObject::c_MCParticle
846 and oParticle->getParticleSource() != EParticleSourceObject::c_MCParticle)
847 or (this->getParticleSource() != EParticleSourceObject::c_MCParticle
848 and oParticle->getParticleSource() == EParticleSourceObject::c_MCParticle)) {
849 B2WARNING("Something went wrong: MCParticle is being compared to a non MC Particle. Please check your script!\n"
850 " If the MCParticle <-> Particle comparison happens in the RestOfEventBuilder,\n"
851 " the Rest Of Event may contain signal side particles.");
852 return false;
853 }
854 if (this->getParticleSource() == EParticleSourceObject::c_MCParticle
855 and oParticle->getParticleSource() == EParticleSourceObject::c_MCParticle) {
856 return this->getMCParticle() == oParticle->getMCParticle();
857 }
858 if (this->getParticleSource() != oParticle->getParticleSource()) {
859 // Check if this or compared particle is a kink. If so, check that the particle is not a copy of daughter or mother.
860 // For consistency, return true if the daughter or mother is a copy of the target particle.
861 if (this->getParticleSource() == EParticleSourceObject::c_Kink &&
862 oParticle->getParticleSource() == EParticleSourceObject::c_Track) {
863 const Kink* kink = this->getKink();
864 const short motherTrackIndex = kink->getMotherTrackIndex();
865 const short daughterTrackIndex = kink->getDaughterTrackIndex();
866 const short trackIndex = oParticle->getTrack()->getArrayIndex();
867 if (trackIndex == motherTrackIndex || trackIndex == daughterTrackIndex)
868 return true;
869 }
870 if (this->getParticleSource() == EParticleSourceObject::c_Track &&
871 oParticle->getParticleSource() == EParticleSourceObject::c_Kink) {
872 const Kink* kink = oParticle->getKink();
873 const short motherTrackIndex = kink->getMotherTrackIndex();
874 const short daughterTrackIndex = kink->getDaughterTrackIndex();
875 const short trackIndex = this->getTrack()->getArrayIndex();
876 if (trackIndex == motherTrackIndex || trackIndex == daughterTrackIndex)
877 return true;
878 }
879 return false;
880 }
881 if (this->getMdstSource() == oParticle->getMdstSource()) {
882 return true;
883 }
884 if (this->getTrack() && oParticle->getTrack() &&
885 this->getTrack()->getArrayIndex() != oParticle->getTrack()->getArrayIndex()) {
886 return false;
887 }
888 if (this->getKLMCluster() && oParticle->getKLMCluster()
889 && this->getKLMCluster()->getArrayIndex() != oParticle->getKLMCluster()->getArrayIndex()) {
890 return false;
891 }
892
893 // It can be a bit more complicated for ECLClusters as we might also have to ensure they are connected-region unique
894 if (this->getECLCluster() && oParticle->getECLCluster()
895 && this->getECLCluster()->getArrayIndex() != oParticle->getECLCluster()->getArrayIndex()) {
896
897 // if either is a track then they must be different
898 if (this->getECLCluster()->isTrack() or oParticle->getECLCluster()->isTrack())
899 return false;
900
901 // we cannot combine two particles of different hypotheses from the same
902 // connected region (as their energies overlap)
904 return false;
905
906 // in the rare case that both are neutral and the hypotheses are different,
907 // we must also check that they are from different connected regions
908 // otherwise they come from the "same" underlying ECLShower
909 if (this->getECLCluster()->getConnectedRegionId() != oParticle->getECLCluster()->getConnectedRegionId())
910 return false;
911 }
912 return true;
913
914}
915
917{
918 if (m_particleSource == c_Track) {
919 StoreArray<Track> tracks{};
920 return tracks[m_mdstIndex];
921 } else
922 return nullptr;
923}
924
926{
927 // if the particle is related to a TrackFitResult then return this
928 auto* selfrelated = this->getRelatedTo<TrackFitResult>();
929 if (selfrelated && !std::isnan(selfrelated->getPValue()))
930 return selfrelated;
931
932 if (m_particleSource == c_Kink) {
933 StoreArray<TrackFitResult> trackFitResults{};
934 return trackFitResults[m_trackFitResultIndex];
935 }
936
937 // if not get the TFR with closest mass to this particle
938 auto* selftrack = this->getTrack();
939 if (selftrack)
940 return selftrack->getTrackFitResultWithClosestMass(
941 Belle2::Const::ChargedStable(std::abs(this->getPDGCode())));
942
943 // otherwise we're probably not a track based particle
944 return nullptr;
945}
946
948{
949 if (m_particleSource == c_Track) {
950 StoreArray<Track> tracks{};
951 return tracks[m_mdstIndex]->getRelated<PIDLikelihood>();
952 } else
953 return nullptr;
954}
955
956const V0* Particle::getV0() const
957{
958 if (m_particleSource == c_V0) {
959 StoreArray<V0> v0s{};
960 return v0s[m_mdstIndex];
961 } else {
962 return nullptr;
963 }
964}
965
967{
968 if (m_particleSource == c_Kink) {
969 StoreArray<Kink> kinks{};
970 return kinks[m_mdstIndex];
971 } else {
972 return nullptr;
973 }
974}
975
977{
978 if (m_particleSource == c_ECLCluster) {
979 StoreArray<ECLCluster> eclClusters{};
980 return eclClusters[m_mdstIndex];
981 } else if (m_particleSource == c_Track) {
982 // a track may be matched to several clusters under different hypotheses
983 // take the most energetic of the c_nPhotons hypothesis as "the" cluster
984 StoreArray<Track> tracks{};
985 const ECLCluster* bestTrackMatchedCluster = nullptr;
986 double highestEnergy = -1.0;
987 // loop over all clusters matched to this track
988 for (const ECLCluster& cluster : tracks[m_mdstIndex]->getRelationsTo<ECLCluster>()) {
989 // ignore everything except the nPhotons hypothesis
990 if (!cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
991 continue;
992 // check if we're most energetic thus far
993 if (cluster.getEnergy(ECLCluster::EHypothesisBit::c_nPhotons) > highestEnergy) {
994 highestEnergy = cluster.getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
995 bestTrackMatchedCluster = &cluster;
996 }
997 }
998 return bestTrackMatchedCluster;
999 } else {
1000 return nullptr;
1001 }
1002}
1003
1005{
1006 const ECLCluster* cluster = this->getECLCluster();
1007 if (!cluster) return 0;
1008 return cluster->getEnergy(this->getECLClusterEHypothesisBit());
1009}
1010
1012{
1013 if (m_particleSource == c_KLMCluster) {
1014 StoreArray<KLMCluster> klmClusters{};
1015 return klmClusters[m_mdstIndex];
1016 } else if (m_particleSource == c_Track) {
1017 // If there is an associated KLMCluster, it's the closest one
1018 StoreArray<Track> tracks{};
1019 const KLMCluster* klmCluster = tracks[m_mdstIndex]->getRelatedTo<KLMCluster>();
1020 return klmCluster;
1021 } else {
1022 return nullptr;
1023 }
1024}
1025
1026
1028{
1029 if (m_particleSource == c_MCParticle) {
1030 StoreArray<MCParticle> mcParticles{};
1031 return mcParticles[m_mdstIndex];
1032 } else {
1033 const MCParticle* related = this->getRelated<MCParticle>();
1034 if (related)
1035 return related;
1036 }
1037 return nullptr;
1038}
1039
1040
1041const Particle* Particle::getParticleFromGeneralizedIndexString(const std::string& generalizedIndex) const
1042{
1043 // Split the generalizedIndex string in a vector of strings.
1044 std::vector<std::string> generalizedIndexes;
1045 boost::split(generalizedIndexes, generalizedIndex, boost::is_any_of(":"));
1046
1047 if (generalizedIndexes.empty()) {
1048 B2WARNING("Generalized index of daughter particle is empty. Skipping.");
1049 return nullptr;
1050 }
1051
1052 // To explore a decay tree of unknown depth, we need a place to store
1053 // both the root particle and the daughter particle at each iteration
1054 const Particle* dauPart =
1055 nullptr; // This will be eventually returned
1056 const Particle* currentPart = this; // This is the root particle of the next iteration
1057
1058 // Loop over the generalizedIndexes until you get to the particle you want
1059 for (auto& indexString : generalizedIndexes) {
1060 // indexString is a string. First try to convert it into an int
1061 int dauIndex = 0;
1062 try {
1063 dauIndex = Belle2::convertString<int>(indexString);
1064 } catch (std::invalid_argument&) {
1065 B2WARNING("Found the string " << indexString << "instead of a daughter index.");
1066 return nullptr;
1067 }
1068
1069 // Check that the daughter index is smaller than the number of daughters of the current root particle
1070 if (dauIndex >= int(currentPart->getNDaughters()) or dauIndex < 0) {
1071 B2WARNING("Daughter index out of range" << LogVar("Daughter index", dauIndex));
1072 B2WARNING("Trying to access non-existing particle.");
1073 return nullptr;
1074 } else {
1075 dauPart = currentPart->getDaughter(dauIndex); // Pick the particle indicated by the generalizedIndex
1076 currentPart = dauPart;
1077 }
1078 }
1079 return dauPart;
1080}
1081
1082
1083
1084//--- private methods --------------------------------------------
1085
1087{
1088 // set momentum
1089 m_px = trackFit->getMomentum().X();
1090 m_py = trackFit->getMomentum().Y();
1091 m_pz = trackFit->getMomentum().Z();
1092
1093 // set position at which the momentum is given (= POCA)
1094 setVertex(trackFit->getPosition());
1095
1096 // set Chi^2 probability
1097 m_pValue = trackFit->getPValue();
1098
1099 // set error matrix
1100 const auto cov6 = trackFit->getCovariance6();
1101 constexpr unsigned order[] = {c_X, c_Y, c_Z, c_Px, c_Py, c_Pz};
1102
1103 TMatrixFSym errMatrix(c_DimMatrix);
1104 for (int i = 0; i < 6; i++) {
1105 for (int j = i; j < 6; j++) {
1106 // although it seems to make no sense to fill all elements of the
1107 // symmetric matrix, it has to be (do not touch this code)
1108 errMatrix(order[j], order[i]) = errMatrix(order[i], order[j]) = cov6(i, j);
1109 }
1110 }
1111
1112 /*
1113 E = sqrt(px^2 + py^2 + pz^2 + m^2) thus:
1114 cov(x,E) = cov(px,x) *dE/dpx + cov(py,x) *dE/dpy + cov(pz,x) *dE/dpz
1115 cov(y,E) = cov(px,y) *dE/dpx + cov(py,y) *dE/dpy + cov(pz,y) *dE/dpz
1116 cov(z,E) = cov(px,z) *dE/dpx + cov(py,z) *dE/dpy + cov(pz,z) *dE/dpz
1117 cov(px,E) = cov(px,px)*dE/dpx + cov(px,py)*dE/dpy + cov(px,pz)*dE/dpz
1118 cov(py,E) = cov(py,px)*dE/dpx + cov(py,py)*dE/dpy + cov(py,pz)*dE/dpz
1119 cov(pz,E) = cov(pz,px)*dE/dpx + cov(pz,py)*dE/dpy + cov(pz,pz)*dE/dpz
1120 cov(E,E) = cov(px,px)*(dE/dpx)^2 + cov(py,py)*(dE/dpy)^2 + cov(pz,pz)*(dE/dpz)^2
1121 + 2*cov(px,py)*dE/dpx*dE/dpy
1122 + 2*cov(py,pz)*dE/dpy*dE/dpz
1123 + 2*cov(pz,px)*dE/dpz*dE/dpx
1124 dE/dpx = px/E etc.
1125 */
1126
1127 const double E = getEnergy();
1128 const double dEdp[] = {m_px / E, m_py / E, m_pz / E};
1129 constexpr unsigned compMom[] = {c_Px, c_Py, c_Pz};
1130 constexpr unsigned compPos[] = {c_X, c_Y, c_Z};
1131
1132 // covariances (p,E)
1133 for (unsigned int i : compMom) {
1134 double Cov = 0;
1135 for (int k = 0; k < 3; k++) {
1136 Cov += errMatrix(i, compMom[k]) * dEdp[k];
1137 }
1138 errMatrix(i, c_E) = Cov;
1139 }
1140
1141 // covariances (x,E)
1142 for (unsigned int comp : compPos) {
1143 double Cov = 0;
1144 for (int k = 0; k < 3; k++) {
1145 Cov += errMatrix(comp, compMom[k]) * dEdp[k];
1146 }
1147 errMatrix(c_E, comp) = Cov;
1148 }
1149
1150 // variance (E,E)
1151 double Cov = 0;
1152 for (int i = 0; i < 3; i++) {
1153 Cov += errMatrix(compMom[i], compMom[i]) * dEdp[i] * dEdp[i];
1154 }
1155 for (int i = 0; i < 3; i++) {
1156 int k = (i + 1) % 3;
1157 Cov += 2 * errMatrix(compMom[i], compMom[k]) * dEdp[i] * dEdp[k];
1158 }
1159 errMatrix(c_E, c_E) = Cov;
1160
1161 storeErrorMatrix(errMatrix);
1162}
1163
1165{
1166 for (double& i : m_errMatrix)
1167 i = 0.0;
1168}
1169
1171{
1172 for (double& i : m_jacobiMatrix)
1173 i = 0.0;
1174}
1175
1176void Particle::storeErrorMatrix(const TMatrixFSym& m)
1177{
1178 int element = 0;
1179 for (int irow = 0; irow < c_DimMatrix; irow++) {
1180 for (int icol = irow; icol < c_DimMatrix; icol++) {
1181 m_errMatrix[element] = m(irow, icol);
1182 element++;
1183 }
1184 }
1185}
1186
1187void Particle::storeJacobiMatrix(const TMatrixF& m)
1188{
1189 int element = 0;
1190 for (int irow = 0; irow < 4; irow++) {
1191 for (int icol = 0; icol < 6; icol++) {
1192 m_jacobiMatrix[element] = m(irow, icol);
1193 element++;
1194 }
1195 }
1196}
1197
1198
1199void Particle::fillFSPDaughters(std::vector<const Belle2::Particle*>& fspDaughters) const
1200{
1201 // this is FSP
1202 if (getNDaughters() == 0) {
1203 fspDaughters.push_back(this);
1204 return;
1205 }
1206
1207 // this is not FSP (go one level down)
1208 for (unsigned i = 0; i < getNDaughters(); i++)
1209 getDaughter(i)->fillFSPDaughters(fspDaughters);
1210}
1211
1212void Particle::fillAllDaughters(std::vector<const Belle2::Particle*>& allDaughters) const
1213{
1214 // this is FSP
1215 if (getNDaughters() == 0)
1216 return;
1217
1218 // this is not FSP (fill it and go one level down)
1219 for (unsigned i = 0; i < getNDaughters(); i++) {
1220 allDaughters.push_back(getDaughter(i));
1221 getDaughter(i)->fillAllDaughters(allDaughters);
1222 }
1223}
1224
1225void Particle::fillDecayChain(std::vector<int>& decayChain) const
1226{
1227 decayChain.push_back(m_pdgCode);
1228 decayChain.push_back(getMdstSource());
1229
1230 for (unsigned i = 0; i < getNDaughters(); i++)
1231 getDaughter(i)->fillDecayChain(decayChain);
1232}
1233
1234
1236{
1238 if (m_pdgCode < 0) return;
1239 if (m_pdgCode == Const::photon.getPDGCode()) {m_flavorType = c_Unflavored; return;} // gamma
1240 if (m_pdgCode == Const::Kshort.getPDGCode()) {m_flavorType = c_Unflavored; return;} // K_s
1241 if (m_pdgCode == Const::Klong.getPDGCode()) {m_flavorType = c_Unflavored; return;} // K_L
1242 if (m_pdgCode == 43) {m_flavorType = c_Unflavored; return;} // Xu0
1243 int nnn = m_pdgCode / 10;
1244 int q3 = nnn % 10; nnn /= 10;
1245 int q2 = nnn % 10; nnn /= 10;
1246 int q1 = nnn % 10;
1247 if (q1 == 0 && q2 == q3) m_flavorType = c_Unflavored; // unflavored meson
1248}
1249
1250std::string Particle::getName() const
1251{
1252 return TDatabasePDG::Instance()->GetParticle(m_pdgCode)->GetName();
1253}
1254
1256{
1257 B2INFO(getInfo());
1258}
1259
1260std::vector<std::string> Particle::getExtraInfoNames() const
1261{
1262 std::vector<std::string> out;
1263 if (!m_extraInfo.empty()) {
1265 if (!extraInfoMap)
1266 B2FATAL("ParticleExtraInfoMap not available, but needed for storing extra info in Particle!");
1267 const ParticleExtraInfoMap::IndexMap& map = extraInfoMap->getMap(m_extraInfo[0]);
1268 for (auto const& ee : map) out.push_back(ee.first);
1269 }
1270 return out;
1271}
1272
1273std::string Particle::getInfoHTML() const
1274{
1275 std::stringstream stream;
1276 stream << std::setprecision(4);
1277 stream << "<b>collection</b>=" << getArrayName();
1278 stream << "<br>";
1279 stream << " <b>PDGCode</b>=" << m_pdgCode;
1280 stream << " <b>Charge</b>=" << getCharge();
1281 stream << " <b>PDGMass</b>=" << getPDGMass();
1282 stream << "<br>";
1283 stream << " <b>flavorType</b>=" << m_flavorType;
1284 stream << " <b>particleSource</b>=" << m_particleSource;
1285 stream << " <b>particleTypeUsedForFit</b>=" << m_pdgCodeUsedForFit;
1286 stream << "<br>";
1287
1288 stream << " <b>mdstIndex</b>=" << m_mdstIndex;
1289 stream << " <b>arrayIndex</b>=" << getArrayIndex();
1290 stream << " <b>identifier</b>=" << m_identifier;
1291 stream << " <b>daughterIndices</b>: ";
1292 for (int daughterIndex : m_daughterIndices) {
1293 stream << daughterIndex << ", ";
1294 }
1295 if (m_daughterIndices.empty()) stream << " (none)";
1296 stream << "<br>";
1297
1298 if (!m_daughterIndices.empty()) {
1299 stream << " <b>daughter PDGCodes</b>: ";
1300 for (unsigned i = 0; i < m_daughterIndices.size(); i++) {
1301 const Particle* p = getDaughter(i);
1302 if (p) {stream << p->getPDGCode() << ", ";}
1303 else {stream << "?, ";}
1304 }
1305 stream << "<br>";
1306 }
1307
1308 stream << " <b>mass</b>=" << m_mass;
1309 stream << "<br>";
1310
1311 stream << " <b>momentum</b>=" << HTML::getString(ROOT::Math::XYZVector(getPx(), getPy(), getPz()));
1312 stream << " <b>p</b>=" << getP();
1313 stream << "<br>";
1314
1315 stream << " <b>momentum scaling factor</b>=" << m_momentumScale;
1316 stream << "<br>";
1317
1318 stream << " <b>Energy loss correction</b>=" << m_energyLossCorrection;
1319 stream << "<br>";
1320
1321 stream << " <b>position</b>=" << HTML::getString(ROOT::Math::XYZVector(m_x, m_y, m_z));
1322 stream << "<br>";
1323
1324 stream << " <b>p-value of fit</b> (if done): ";
1325 stream << m_pValue;
1326 stream << "<br>";
1327
1328 stream << " <b>error matrix</b> (px, py, pz, E, x, y ,z):<br>";
1330
1331 stream << " <b>extra info</b>=( ";
1332 if (!m_extraInfo.empty()) {
1334 if (!extraInfoMap) {
1335 B2FATAL("ParticleExtraInfoMap not available, but needed for storing extra info in Particle!");
1336 }
1337 const ParticleExtraInfoMap::IndexMap& map = extraInfoMap->getMap(m_extraInfo[0]);
1338 const unsigned int nVars = m_extraInfo.size();
1339 for (const auto& pair : map) {
1340 if (pair.second < nVars) {
1341 stream << pair.first << "=" << m_extraInfo[pair.second] << " ";
1342 }
1343 }
1344
1345 }
1346 stream << ") " << "<br>";
1347
1348 return stream.str();
1349}
1350
1351bool Particle::hasExtraInfo(const std::string& name) const
1352{
1353 if (m_extraInfo.empty())
1354 return false;
1355
1356 //get index for name
1357 const auto mapID = (unsigned int)m_extraInfo[0];
1359 if (!extraInfoMap) {
1360 B2FATAL("ParticleExtraInfoMap not available, but needed for storing extra info in Particle!");
1361 }
1362 unsigned int index = extraInfoMap->getIndex(mapID, name);
1363 if (index == 0 or index >= m_extraInfo.size()) //actually indices start at 1
1364 return false;
1365
1366 return true;
1367}
1368
1370{
1371 m_extraInfo.clear();
1372}
1373
1374double Particle::getExtraInfo(const std::string& name) const
1375{
1376 if (m_extraInfo.empty())
1377 throw std::runtime_error(std::string("getExtraInfo: Value '") + name + "' not found in Particle!");
1378
1379 //get index for name
1380 const auto mapID = (unsigned int)m_extraInfo[0];
1382 if (!extraInfoMap) {
1383 B2FATAL("ParticleExtraInfoMap not available, but needed for storing extra info in Particle!");
1384 }
1385 unsigned int index = extraInfoMap->getIndex(mapID, name);
1386 if (index == 0 or index >= m_extraInfo.size()) //actually indices start at 1
1387 throw std::runtime_error(std::string("getExtraInfo: Value '") + name + "' not found in Particle!");
1388
1389 return m_extraInfo[index];
1390
1391}
1392
1393void Particle::writeExtraInfo(const std::string& name, const double value)
1394{
1395 if (this->hasExtraInfo(name)) {
1396 this->setExtraInfo(name, value);
1397 } else {
1398 this->addExtraInfo(name, value);
1399 }
1400}
1401
1402void Particle::setExtraInfo(const std::string& name, double value)
1403{
1404 if (m_extraInfo.empty())
1405 throw std::runtime_error(std::string("setExtraInfo: Value '") + name + "' not found in Particle!");
1406
1407 //get index for name
1408 const auto mapID = (unsigned int)m_extraInfo[0];
1410 if (!extraInfoMap) {
1411 B2FATAL("ParticleExtraInfoMap not available, but needed for storing extra info in Particle!");
1412 }
1413 unsigned int index = extraInfoMap->getIndex(mapID, name);
1414 if (index == 0 or index >= m_extraInfo.size()) //actually indices start at 1
1415 throw std::runtime_error(std::string("setExtraInfo: Value '") + name + "' not found in Particle!");
1416
1417 m_extraInfo[index] = value;
1418
1419}
1420
1421void Particle::addExtraInfo(const std::string& name, double value)
1422{
1423 if (hasExtraInfo(name))
1424 throw std::runtime_error(std::string("addExtraInfo: Value '") + name + "' already set!");
1425
1427 if (!extraInfoMap)
1428 extraInfoMap.create();
1429 if (m_extraInfo.empty()) {
1430 unsigned int mapID = extraInfoMap->getMapForNewVar(name);
1431 m_extraInfo.push_back(mapID);
1432 m_extraInfo.push_back(value);
1433 } else {
1434 unsigned int oldMapID = m_extraInfo[0];
1435 unsigned int insertIndex = m_extraInfo.size();
1436 unsigned int mapID = extraInfoMap->getMapForNewVar(name, oldMapID, insertIndex);
1437
1438 m_extraInfo[0] = mapID; //update map
1439 m_extraInfo.push_back(value); //add value
1440 }
1441}
1442
1443bool Particle::forEachDaughter(const std::function<bool(const Particle*)>& function,
1444 bool recursive, bool includeSelf) const
1445{
1446 std::queue<const Particle*> qq;
1447 // If we include ourselves add only this, otherwise directly all children
1448 if (includeSelf) {
1449 qq.push(this);
1450 } else {
1451 for (size_t i = 0; i < getNDaughters(); ++i) qq.push(getDaughter(i));
1452 }
1453 // Now just repeat until done: take the child, run the functor, remove the
1454 // child, add all children if needed
1455 while (!qq.empty()) {
1456 const Particle* p = qq.front();
1457 if (function(p)) return true;
1458 qq.pop();
1459 // Add children if we go through all children recursively or if we look at
1460 // the current particle: we always want the direct children.
1461 if (recursive || p == this)
1462 for (size_t i = 0; i < p->getNDaughters(); ++i) qq.push(p->getDaughter(i));
1463 }
1464 return false;
1465}
1466
1467int Particle::generatePDGCodeFromCharge(const int chargeSign, const Const::ChargedStable& chargedStable)
1468{
1469 int absPDGCode = chargedStable.getPDGCode();
1470 int PDGCode = absPDGCode * chargeSign;
1471 // flip sign of PDG code for leptons: their PDG code is positive if the lepton charge is negative and vice versa
1472 if (chargedStable == Const::muon || chargedStable == Const::electron) PDGCode = -PDGCode;
1473 return PDGCode;
1474}
1475
1477{
1478 const PIDLikelihood* likelihood = Particle::getPIDLikelihood();
1479 if (likelihood) return likelihood->getMostLikely().getPDGCode() == std::abs(m_pdgCode);
1480 else return false;
1481}
1482
1483std::pair<Const::ChargedStable, const TrackFitResult*> Particle::getMostLikelyTrackFitResult() const
1484{
1485
1486 const auto track = this->getTrack();
1487
1488 if (!track) {
1489 return std::make_pair(Const::ChargedStable(std::abs(this->getPDGCode())), nullptr);
1490 }
1491
1492 // Find the track fit with the highest pValue
1493 auto trackFitResults = track->getTrackFitResults();
1494 auto it_maxPValue = std::max_element(std::begin(trackFitResults), std::end(trackFitResults),
1495 [](auto tfrAndM1, auto tfrAndM2) {return tfrAndM1.second->getPValue() < tfrAndM2.second->getPValue();});
1496
1497 return trackFitResults[std::distance(std::begin(trackFitResults), it_maxPValue)];
1498
1499}
1500
1502{
1503 const auto trackFit = this->getTrackFitResult();
1504 if (!trackFit) return false;
1505
1506 return (trackFit == this->getMostLikelyTrackFitResult().second);
1507}
R E
internal precision of FFTW codelets
Class to provide momentum-related information from ECLClusters.
Definition: ClusterUtils.h:38
const TMatrixDSym GetCovarianceMatrix7x7FromCluster(const ECLCluster *cluster, const TMatrixD &jacobiMatrix)
Returns 7x7 covariance matrix (px, py, pz, E, x, y, z)
const ROOT::Math::PxPyPzEVector Get4MomentumFromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns four momentum vector.
Definition: ClusterUtils.cc:25
const TMatrixD GetJacobiMatrix4x6FromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns 4x6 Jacobi matrix (px, py, pz, E)
Definition: ClusterUtils.cc:54
const TMatrixDSym GetIPPositionCovarianceMatrix()
Returns default IP position covariance matrix from beam parameters.
const ROOT::Math::XYZVector GetIPPosition()
Returns default IP position from beam parameters.
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:589
The ParticleType class for identifying different particle types.
Definition: Const.h:408
int getPDGCode() const
PDG code.
Definition: Const.h:473
static const ParticleType pi0
neutral pion particle
Definition: Const.h:674
static const ChargedStable muon
muon particle
Definition: Const.h:660
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:618
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:678
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:677
static const ParticleType photon
photon particle
Definition: Const.h:673
static const ChargedStable electron
electron particle
Definition: Const.h:659
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
ECL cluster data.
Definition: ECLCluster.h:27
bool isTrack() const
Return true if the cluster matches with track.
Definition: ECLCluster.h:235
int getConnectedRegionId() const
Return connected region id.
Definition: ECLCluster.h:250
@ c_nPhotons
CR is split into n photons (N1)
KLM cluster data.
Definition: KLMCluster.h:28
ROOT::Math::PxPyPzEVector getMomentum() const
Get momentum.
Definition: KLMCluster.cc:49
Object holding information for Kinks.
Definition: Kink.h:32
short getDaughterTrackIndex() const
Get index of the daughter Track (it is the same as mother's in case of track splitting).
Definition: Kink.h:73
short getMotherTrackIndex() const
Get index of the mother Track.
Definition: Kink.h:67
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
float getMass() const
Return the particle mass in GeV.
Definition: MCParticle.h:124
ROOT::Math::XYZVector getVertex() const
Return production vertex position, shorthand for getProductionVertex().
Definition: MCParticle.h:172
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:233
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:101
ROOT::Math::XYZVector getMomentum() const
Return momentum.
Definition: MCParticle.h:187
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Definition: PIDLikelihood.h:29
Const::ChargedStable getMostLikely(const double *fractions=nullptr, Const::PIDDetectorSet set=Const::PIDDetectorSet::set()) const
Return most likely particle among chargedStableSet; if prior fractions not given equal prior probabil...
std::map< std::string, unsigned int > IndexMap
string -> index map.
Class to store reconstructed particles.
Definition: Particle.h:76
void removeExtraInfo()
Remove all stored extra info fields.
Definition: Particle.cc:1369
double getPx() const
Returns x component of momentum.
Definition: Particle.h:607
void updateJacobiMatrix()
Propagate the photon energy scaling to jacobian elements that were calculated using energy.
Definition: Particle.cc:288
TMatrixFSym getVertexErrorMatrix() const
Returns the 3x3 position error sub-matrix.
Definition: Particle.cc:478
bool isMostLikely() const
Returns true if the (track-based) particle is created with its most likely mass hypothesis based on P...
Definition: Particle.cc:1476
const KLMCluster * getKLMCluster() const
Returns the pointer to the KLMCluster object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:1011
bool replaceDaughter(const Particle *oldDaughter, Particle *newDaughter)
Replace index of given daughter with new daughter, return true if a replacement is made.
Definition: Particle.cc:736
const Track * getTrack() const
Returns the pointer to the Track object that was used to create this Particle (ParticleType == c_Trac...
Definition: Particle.cc:916
void setMomentumPositionErrorMatrix(const TrackFitResult *trackFit)
Sets the momentum, position and error matrix for this particle (created from charged Track)
Definition: Particle.cc:1086
void storeErrorMatrix(const TMatrixFSym &errMatrix)
Stores 7x7 error matrix into private member m_errMatrix.
Definition: Particle.cc:1176
bool forEachDaughter(const std::function< bool(const Particle *)> &function, bool recursive=true, bool includeSelf=true) const
Apply a function to all daughters of this particle.
Definition: Particle.cc:1443
std::vector< const Belle2::Particle * > getFinalStateDaughters() const
Returns a vector of pointers to Final State daughter particles.
Definition: Particle.cc:680
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:1027
void appendDaughter(const Particle *daughter, const bool updateType=true, const int daughterProperty=c_Ordinary)
Appends index of daughter to daughters index array.
Definition: Particle.cc:707
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition: Particle.cc:976
void setExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1402
EParticleSourceObject
particle source enumerators
Definition: Particle.h:83
double m_pValue
chi^2 probability of the fit.
Definition: Particle.h:1097
double m_pz
momentum component z
Definition: Particle.h:1087
int m_pdgCodeUsedForFit
PDG code used for the track fit.
Definition: Particle.h:1083
double m_momentumScale
effective momentum scale factor
Definition: Particle.h:1088
std::string getName() const override
Return name of this particle.
Definition: Particle.cc:1250
bool overlapsWith(const Particle *oParticle) const
Returns true if final state ancestors of oParticle overlap.
Definition: Particle.cc:768
double getCosHelicityDaughter(unsigned iDaughter, unsigned iGrandDaughter=0) const
Returns cosine of the helicity angle of the given daughter defined by given grand daughter.
Definition: Particle.cc:533
double getPz() const
Returns z component of momentum.
Definition: Particle.h:625
std::vector< std::string > getExtraInfoNames() const
get a list of the extra info names
Definition: Particle.cc:1260
bool isCopyOf(const Particle *oParticle, bool doDetailedComparison=false) const
Returns true if this Particle and oParticle are copies of each other.
Definition: Particle.cc:783
void writeExtraInfo(const std::string &name, const double value)
Sets the user defined extraInfo.
Definition: Particle.cc:1393
void setVertex(const ROOT::Math::XYZVector &vertex)
Sets position (decay vertex)
Definition: Particle.h:306
std::vector< int > getMdstArrayIndices(EParticleSourceObject type) const
Returns a vector of StoreArray indices of given MDST dataobjects.
Definition: Particle.cc:696
double m_jacobiMatrix[c_SizeMatrix]
error matrix (1D representation)
Definition: Particle.h:1096
void resetJacobiMatrix()
Resets 4x6 error matrix All elements are set to 0.0.
Definition: Particle.cc:1170
void storeJacobiMatrix(const TMatrixF &jacobiMatrix)
Stores 4x6 Jacobi matrix into private member m_jacobiMatrix.
Definition: Particle.cc:1187
bool isMostLikelyTrackFitResult() const
Returns true if the (track-based) particle is created with its most likely mass hypothesis based on T...
Definition: Particle.cc:1501
std::vector< double > m_extraInfo
Stores associated user defined values.
Definition: Particle.h:1120
unsigned m_mdstIndex
0-based index of MDST store array object
Definition: Particle.h:1101
void setFlavorType()
sets m_flavorType using m_pdgCode
Definition: Particle.cc:1235
double getEnergy() const
Returns total energy.
Definition: Particle.h:555
int getMdstSource() const
Returns unique identifier of final state particle (needed in particle combiner)
Definition: Particle.cc:400
void fillAllDaughters(std::vector< const Belle2::Particle * > &allDaughters) const
Fill all generations' daughters into a vector.
Definition: Particle.cc:1212
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
Definition: Particle.cc:1351
std::string getInfoHTML() const override
Return a short summary of this object's contents in HTML format.
Definition: Particle.cc:1273
void setMdstArrayIndex(const int arrayIndex)
set mdst array index
Definition: Particle.cc:381
const Particle * getParticleFromGeneralizedIndexString(const std::string &generalizedIndex) const
Explores the decay tree of the particle and returns the (grand^n)daughter identified by a generalized...
Definition: Particle.cc:1041
double m_py
momentum component y
Definition: Particle.h:1086
double m_x
position component x
Definition: Particle.h:1092
double m_px
momentum component x
Definition: Particle.h:1085
std::pair< Const::ChargedStable, const TrackFitResult * > getMostLikelyTrackFitResult() const
For a (track-based) particle, returns the charged stable mass hypothesis associated to the most proba...
Definition: Particle.cc:1483
~Particle()
Destructor.
void fillFSPDaughters(std::vector< const Belle2::Particle * > &fspDaughters) const
Fill final state particle daughters into a vector.
Definition: Particle.cc:1199
const PIDLikelihood * getPIDLikelihood() const
Returns the pointer to the PIDLikelihood object that is related to the Track, which was used to creat...
Definition: Particle.cc:947
const V0 * getV0() const
Returns the pointer to the V0 object that was used to create this Particle (if ParticleType == c_V0).
Definition: Particle.cc:956
const Kink * getKink() const
Returns the pointer to the Kink object that was used to create this Particle (if ParticleType == c_Ki...
Definition: Particle.cc:966
EParticleSourceObject m_particleSource
(mdst) source of particle
Definition: Particle.h:1100
void fillDecayChain(std::vector< int > &decayChain) const
Fill vector with (PDGCode, MdstSource) pairs for the entire decay chain.
Definition: Particle.cc:1225
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:465
double getPy() const
Returns y component of momentum.
Definition: Particle.h:616
double getCosHelicity(const Particle *mother=nullptr) const
Returns cosine of the helicity angle The helicity angle is defined in the rest frame of the particle ...
Definition: Particle.cc:490
unsigned getNDaughters(void) const
Returns number of daughter particles.
Definition: Particle.h:747
std::vector< Belle2::Particle * > getDaughters() const
Returns a vector of pointers to daughter particles.
Definition: Particle.cc:668
TClonesArray * getArrayPointer() const
Returns the pointer to the store array which holds the daughter particles.
Definition: Particle.h:981
void resetErrorMatrix()
Resets 7x7 error matrix All elements are set to 0.0.
Definition: Particle.cc:1164
double getPDGMass(void) const
Returns uncertainty on the invariant mass (requires valid momentum error matrix)
Definition: Particle.cc:635
EFlavorType m_flavorType
flavor type.
Definition: Particle.h:1099
double m_energyLossCorrection
energy loss correction.
Definition: Particle.h:1091
int generatePDGCodeFromCharge(const int chargedSign, const Const::ChargedStable &chargedStable)
Generate the PDG code with correct sign, using the charge.
Definition: Particle.cc:1467
double getCharge(void) const
Returns particle charge.
Definition: Particle.cc:653
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:567
Particle()
Default constructor.
Definition: Particle.cc:46
TMatrixFSym getMomentumErrorMatrix() const
Returns the 4x4 momentum error matrix.
Definition: Particle.cc:466
double m_mass
particle (invariant) mass
Definition: Particle.h:1084
std::vector< const Belle2::Particle * > getAllDaughters() const
Returns a vector of pointers to all generations' daughter particles.
Definition: Particle.cc:688
double getAcoplanarity() const
Returns acoplanarity angle defined as the angle between the decay planes of the grand daughters in th...
Definition: Particle.cc:564
std::vector< int > m_daughterProperties
daughter particle properties
Definition: Particle.h:1104
double m_errMatrix[c_SizeMatrix]
error matrix (1D representation)
Definition: Particle.h:1095
std::vector< int > m_daughterIndices
daughter particle indices
Definition: Particle.h:1098
unsigned m_trackFitResultIndex
0-based index of related TrackFitResult, relevant for kinks
Definition: Particle.h:1102
void addExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1421
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets Lorentz vector.
Definition: Particle.h:282
void setJacobiMatrix(const TMatrixF &jacobiMatrix)
Sets 4x6 jacobi matrix.
Definition: Particle.cc:438
double getPDGLifetime() const
Returns particle nominal lifetime.
Definition: Particle.cc:644
void setMomentumVertexErrorMatrix(const TMatrixFSym &errMatrix)
Sets 7x7 error matrix.
Definition: Particle.cc:424
EParticleSourceObject getParticleSource() const
Returns particle source as defined with enum EParticleSourceObject.
Definition: Particle.h:489
void updateMass(const int pdgCode)
Updates particle mass with the mass of the particle corresponding to the given PDG.
Definition: Particle.cc:628
double m_z
position component z
Definition: Particle.h:1094
void print() const
Prints the contents of a Particle object to standard output.
Definition: Particle.cc:1255
EFlavorType
describes flavor type, see getFlavorType().
Definition: Particle.h:96
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:97
@ c_Flavored
Is either particle or antiparticle.
Definition: Particle.h:98
int m_pdgCode
PDG code.
Definition: Particle.h:1082
TMatrixFSym getMomentumVertexErrorMatrix() const
Returns 7x7 error matrix.
Definition: Particle.cc:451
double getECLClusterEnergy() const
Returns the energy of the ECLCluster for the particle.
Definition: Particle.cc:1004
const TrackFitResult * getTrackFitResult() const
Returns the pointer to the TrackFitResult that was used to create this Particle (ParticleType == c_Tr...
Definition: Particle.cc:925
void removeDaughter(const Particle *daughter, const bool updateType=true)
Removes index of daughter from daughters index array.
Definition: Particle.cc:719
double getP() const
Returns momentum magnitude (same as getMomentumMagnitude but with shorter name)
Definition: Particle.h:598
double m_y
position component y
Definition: Particle.h:1093
int m_identifier
Identifier that can be used to identify whether the particle is unique or is a copy or representation...
Definition: Particle.h:1113
int m_properties
particle property
Definition: Particle.h:1103
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
Definition: Particle.cc:662
double getExtraInfo(const std::string &name) const
Return given value if set.
Definition: Particle.cc:1374
ECLCluster::EHypothesisBit getECLClusterEHypothesisBit() const
Returns the ECLCluster EHypothesisBit for this Particle.
Definition: Particle.h:1029
bool replaceDaughterRecursively(const Particle *oldDaughter, Particle *newDaughter)
Apply replaceDaughter to all Particles in the decay tree by looping recursively through it,...
Definition: Particle.cc:754
std::string getArrayName() const
Get name of array this object is stored in, or "" if not found.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
std::string getInfo() const
Return a short summary of this object's contents in raw text format.
bool create(bool replace=false)
Create a default object in the data store.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
double getPValue() const
Getter for Chi2 Probability of the track fit.
TMatrixDSym getCovariance6() const
Position and Momentum Covariance Matrix.
Const::ParticleType getParticleType() const
Getter for ParticleType of the mass hypothesis of the track fit.
ROOT::Math::XYZVector getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
ROOT::Math::XYZVector getPosition() const
Getter for vector of position at closest approach of track in r/phi projection.
Class that bundles various TrackFitResults.
Definition: Track.h:25
Object holding information for V0s.
Definition: V0.h:34
Class to store variables with their name which were sent to the logging service.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
std::string getString(const TMatrixFBase &matrix, int precision=2, bool color=true)
get HTML table representing a matrix.
Definition: HTML.cc:24
Abstract base class for different kinds of events.