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