8#include <analysis/dataobjects/Particle.h>
9#include <analysis/dataobjects/RestOfEvent.h>
10#include <analysis/dataobjects/ParticleExtraInfoMap.h>
11#include <mdst/dataobjects/MCParticle.h>
12#include <mdst/dataobjects/ECLCluster.h>
13#include <mdst/dataobjects/KLMCluster.h>
14#include <mdst/dataobjects/V0.h>
15#include <framework/datastore/StoreArray.h>
16#include <framework/datastore/StoreObjPtr.h>
17#include <framework/gearbox/Const.h>
18#include <framework/utilities/TestHelpers.h>
20#include <analysis/utility/ParticleCopy.h>
22#include <TDatabasePDG.h>
24#include <gtest/gtest.h>
29using namespace ROOT::Math;
33 class ParticleTest :
public ::testing::Test {
47 particles.registerInDataStore();
53 particles.registerRelationTo(mcparticles);
54 particles.registerRelationTo(roes);
59 void TearDown()
override
66 TEST_F(ParticleTest, Constructors)
70 EXPECT_EQ(0, p.getPDGCode());
71 EXPECT_TRUE(PxPyPzEVector(0, 0, 0, 0) == p.get4Vector());
72 EXPECT_EQ(Particle::c_Undefined, p.getParticleSource());
75 PxPyPzEVector momentum(1, 2, 3, 4);
77 EXPECT_EQ(421, p.getPDGCode());
78 EXPECT_FLOAT_EQ(0.0, momentum.phi() - p.get4Vector().phi());
79 EXPECT_FLOAT_EQ(0.0, momentum.Rapidity() - p.get4Vector().Rapidity());
80 EXPECT_FLOAT_EQ(momentum.energy(), p.get4Vector().energy());
81 EXPECT_FLOAT_EQ(momentum.energy(), p.getEnergy());
82 EXPECT_FLOAT_EQ(momentum.M(), p.getMass());
83 EXPECT_EQ(Particle::c_Undefined, p.getParticleSource());
86 PxPyPzEVector momentum(1, 2, 3, 4);
88 EXPECT_EQ(22, p.getPDGCode());
89 EXPECT_FLOAT_EQ(0.0, momentum.phi() - p.get4Vector().phi());
90 EXPECT_FLOAT_EQ(0.0, momentum.Rapidity() - p.get4Vector().Rapidity());
91 EXPECT_FLOAT_EQ(momentum.energy(), p.get4Vector().energy());
93 EXPECT_EQ(Particle::c_MCParticle, p.getParticleSource());
94 EXPECT_EQ(123u, p.getMdstArrayIndex());
101 cluster->setIsTrack(
false);
102 cluster->addHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
103 cluster->setEnergy(1337);
106 EXPECT_EQ(22, p.getPDGCode());
108 EXPECT_EQ(Particle::c_ECLCluster, p.getParticleSource());
109 EXPECT_FLOAT_EQ(1337, p.getEnergy());
110 EXPECT_EQ(cluster, p.getECLCluster());
111 EXPECT_EQ(
nullptr, p.getTrack());
119 PxPyPzEVector momentum(1, 2, 3, 4);
121 EXPECT_EQ(310, p.getPDGCode());
123 EXPECT_EQ(Particle::c_V0, p.getParticleSource());
124 EXPECT_EQ(0u, p.getMdstArrayIndex());
125 EXPECT_EQ(p.getV0(), v0);
129 TEST_F(ParticleTest, Daughters)
131 PxPyPzEVector momentum;
132 const int nDaughters = 6;
134 std::vector<int> daughterIndices;
135 for (
int i = 0; i < nDaughters; i++) {
136 Particle d(PxPyPzEVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
137 momentum += d.get4Vector();
138 Particle* newDaughters = particles.appendNew(d);
143 EXPECT_EQ(411, p.getPDGCode());
144 EXPECT_FLOAT_EQ(0.0, momentum.phi() - p.get4Vector().phi());
145 EXPECT_FLOAT_EQ(0.0, momentum.Rapidity() - p.get4Vector().Rapidity());
146 EXPECT_FLOAT_EQ(momentum.energy(), p.get4Vector().energy());
148 EXPECT_EQ(Particle::c_Composite, p.getParticleSource());
149 EXPECT_EQ(0u, p.getMdstArrayIndex());
150 EXPECT_EQ((
unsigned int)nDaughters, p.getNDaughters());
151 EXPECT_EQ((
unsigned int)nDaughters, p.getDaughters().size());
152 EXPECT_EQ((
unsigned int)nDaughters, p.getFinalStateDaughters().size());
153 EXPECT_EQ((
unsigned int)nDaughters, p.getDaughterProperties().size());
156 EXPECT_DOUBLE_EQ(p.getMass(), pLocal.getMass());
157 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getNDaughters());
158 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getDaughters().size());
159 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getFinalStateDaughters().size());
160 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getDaughterProperties().size());
167 TEST_F(ParticleTest, DaughterProperties)
169 PxPyPzEVector momentum;
170 const int nDaughters = 6;
172 std::vector<int> daughterIndices;
173 std::vector<int> daughterProperties;
174 for (
int i = 0; i < nDaughters; i++) {
175 Particle d(PxPyPzEVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
176 momentum += d.get4Vector();
177 Particle* newDaughters = particles.appendNew(d);
179 daughterProperties.push_back(Particle::PropertyFlags::c_Ordinary);
183 EXPECT_EQ(411, p.getPDGCode());
184 EXPECT_FLOAT_EQ(0.0, momentum.phi() - p.get4Vector().phi());
185 EXPECT_FLOAT_EQ(0.0, momentum.Rapidity() - p.get4Vector().Rapidity());
186 EXPECT_FLOAT_EQ(momentum.energy(), p.get4Vector().energy());
188 EXPECT_EQ(Particle::c_Composite, p.getParticleSource());
189 EXPECT_EQ(0u, p.getMdstArrayIndex());
190 EXPECT_EQ((
unsigned int)nDaughters, p.getNDaughters());
191 EXPECT_EQ((
unsigned int)nDaughters, p.getDaughters().size());
192 EXPECT_EQ((
unsigned int)nDaughters, p.getFinalStateDaughters().size());
193 EXPECT_EQ((
unsigned int)nDaughters, p.getDaughterProperties().size());
194 EXPECT_EQ(Particle::PropertyFlags::c_Ordinary, (p.getDaughterProperties())[0]);
198 Particle::PropertyFlags::c_Ordinary, daughterProperties,
200 EXPECT_DOUBLE_EQ(p.getMass(), pLocal.getMass());
201 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getNDaughters());
202 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getDaughters().size());
203 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getFinalStateDaughters().size());
204 EXPECT_EQ((
unsigned int)nDaughters, pLocal.getDaughterProperties().size());
212 struct ParticleChildrenCounter {
215 bool operator()(
const Particle*) { ++count;
return false; }
218 TEST_F(ParticleTest, ForEachDaughters)
221 PxPyPzEVector momentum;
222 const int nDaughters = 6;
224 std::vector<int> daughterIndices;
225 int nGrandDaughters = 0;
226 for (
int i = 0; i < nDaughters; i++) {
227 Particle d(PxPyPzEVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
228 momentum += d.get4Vector();
229 Particle* newDaughters = particles.appendNew(d);
232 Particle* grandDaughter = particles.appendNew(d);
241 auto counterFct = [&count](
const Particle*) { ++count;
return false; };
242 EXPECT_FALSE(p.forEachDaughter(counterFct,
false,
false));
243 EXPECT_EQ(count, nDaughters);
245 EXPECT_FALSE(p.forEachDaughter(counterFct,
true,
false));
246 EXPECT_EQ(count, nDaughters + nGrandDaughters);
248 EXPECT_FALSE(p.forEachDaughter(counterFct,
false,
true));
249 EXPECT_EQ(count, nDaughters + 1);
251 EXPECT_FALSE(p.forEachDaughter(counterFct,
true,
true));
252 EXPECT_EQ(count, nDaughters + nGrandDaughters + 1);
255 ParticleChildrenCounter counterStruct;
256 EXPECT_FALSE(p.forEachDaughter(counterStruct));
257 EXPECT_EQ(counterStruct.count, 0);
259 EXPECT_FALSE(p.forEachDaughter(std::reference_wrapper<ParticleChildrenCounter>(counterStruct)));
260 EXPECT_EQ(counterStruct.count, nDaughters + nGrandDaughters + 1);
264 int maxchildren{1}, total{nDaughters + nGrandDaughters + 1};
265 auto returnFctTester = [&count, &maxchildren](
const Particle*) {++count;
return count >= maxchildren; };
266 for (; maxchildren < 2 * total; ++maxchildren) {
268 EXPECT_EQ(p.forEachDaughter(returnFctTester), maxchildren <= total);
269 EXPECT_EQ(count, std::min(maxchildren, total));
274 TEST_F(ParticleTest, ExtraInfo)
278 EXPECT_THROW(p.getExtraInfo(
"htns"), std::runtime_error);
280 p.addExtraInfo(
"htns", 32.0);
283 EXPECT_THROW(p.addExtraInfo(
"htns", 1234.0), std::runtime_error);
285 EXPECT_DOUBLE_EQ(32.0, p.getExtraInfo(
"htns"));
290 TEST_F(ParticleTest, Copies)
298 eclGamma1->
setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
302 eclGamma2->
setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
306 eclGamma3->
setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
310 eclKL->
setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
339 Particle::c_ECLCluster,
343 MC1Pion->
set4Vector(PxPyPzEVector(0, 0, 0, 0));
351 EXPECT_TRUE(T1Pion->
isCopyOf(T1PionCopy));
352 EXPECT_FALSE(T1Pion->
isCopyOf(T1Kaon));
353 EXPECT_FALSE(T1Pion->
isCopyOf(T1Gamma));
354 EXPECT_FALSE(T2Gamma->
isCopyOf(T1Gamma));
357 EXPECT_TRUE(T1Pion->
isCopyOf(T1PionCopy,
true));
358 EXPECT_TRUE(T1Pion->
isCopyOf(T1Kaon,
true));
359 EXPECT_FALSE(T2Gamma->
isCopyOf(T1Gamma,
true));
360 EXPECT_TRUE(T3Gamma->
isCopyOf(T4KL,
true));
361 EXPECT_FALSE(T1PionFromMC->
isCopyOf(T1Pion,
true));
362 EXPECT_FALSE(T1Pion->
isCopyOf(T1PionFromMC,
true));
364 Particle* D0Pi1Pi2 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
368 Particle* D0Pi1Pi2Copy = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
372 Particle* D0Pi1Pi2Copy2 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
376 Particle* D0K1K2 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
380 Particle* D0K1Pi2 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
384 EXPECT_FALSE(D0Pi1Pi2->
isCopyOf(D0K1K2));
385 EXPECT_FALSE(D0Pi1Pi2->
isCopyOf(D0K1Pi2));
386 EXPECT_TRUE(D0Pi1Pi2->
isCopyOf(D0Pi1Pi2Copy));
387 EXPECT_TRUE(D0Pi1Pi2->
isCopyOf(D0Pi1Pi2Copy2));
388 EXPECT_TRUE(D0Pi1Pi2Copy->
isCopyOf(D0Pi1Pi2Copy2));
391 Particle* D0K3K4 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 421));
395 Particle* B0_1 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 511));
399 Particle* B0_2 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 511));
403 Particle* B0_3 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 511));
411 Particle* B0_4 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 511));
415 Particle* B0_5 = particles.appendNew(
Particle(PxPyPzEVector(0, 0, 0, 0), 511));
425 TEST_F(ParticleTest, ExtraInfoMap)
431 p.addExtraInfo(
"htns", 1.0);
432 EXPECT_EQ(1u, map->getNMaps());
435 p.addExtraInfo(
"somethingelse", 2.0);
436 EXPECT_EQ(1u, map->getNMaps());
441 EXPECT_EQ(1u, map->getNMaps());
443 EXPECT_EQ(1u, map->getNMaps());
446 p.addExtraInfo(
"thirdvar_p", 3.0);
447 EXPECT_EQ(1u, map->getNMaps());
450 EXPECT_EQ(2u, map->getNMaps());
459 t.addExtraInfo(
"htns", 1.0);
460 t.addExtraInfo(
"somethingelse", 2.0);
461 t.addExtraInfo(
"thirdvar_q", 3.0);
463 EXPECT_EQ(2u, map->getNMaps());
465 EXPECT_THROW(s.
getExtraInfo(
"thirdvar_q"), std::runtime_error);
466 EXPECT_THROW(t.getExtraInfo(
"thirdvar_p"), std::runtime_error);
470 EXPECT_THROW(u.
getExtraInfo(
"htns"), std::runtime_error);
472 EXPECT_THROW(u.
getExtraInfo(
"somethingelse"), std::runtime_error);
473 EXPECT_THROW(u.
getExtraInfo(
"thirdvar_p"), std::runtime_error);
474 EXPECT_THROW(u.
getExtraInfo(
"thirdvar_q"), std::runtime_error);
476 EXPECT_THROW(u.
getExtraInfo(
"thirdvar_p"), std::runtime_error);
477 EXPECT_THROW(u.
getExtraInfo(
"thirdvar_q"), std::runtime_error);
489 EXPECT_DOUBLE_EQ(1.0, p.getExtraInfo(
"htns"));
490 EXPECT_DOUBLE_EQ(2.0, p.getExtraInfo(
"somethingelse"));
491 EXPECT_DOUBLE_EQ(3.0, p.getExtraInfo(
"thirdvar_p"));
494 EXPECT_DOUBLE_EQ(12.0, q.
getExtraInfo(
"somethingelse"));
501 EXPECT_DOUBLE_EQ(1.0, t.getExtraInfo(
"htns"));
502 EXPECT_DOUBLE_EQ(2.0, t.getExtraInfo(
"somethingelse"));
503 EXPECT_DOUBLE_EQ(3.0, t.getExtraInfo(
"thirdvar_q"));
513 EXPECT_DOUBLE_EQ(2.0, tCopy.
getExtraInfo(
"somethingelse"));
514 EXPECT_DOUBLE_EQ(3.0, tCopy.
getExtraInfo(
"thirdvar_q"));
520 TEST_F(ParticleTest, ParticleCopyUtility)
543 Particle::c_Track, 4));
546 Particle* D0KK = particles.appendNew(
Particle(PxPyPzEVector(4, 4, 4, 4), 421));
550 Particle* B0 = particles.appendNew(
Particle(PxPyPzEVector(5, 5, 5, 5), 511));
562 EXPECT_EQ(particles.getEntries(), 6);
569 EXPECT_EQ(particles.getEntries(), 11);
611 EXPECT_TRUE(mc1orig == mc1copy);
612 EXPECT_TRUE(mc2orig == mc2copy);
613 EXPECT_TRUE(mc3orig == mc3copy);
615 EXPECT_TRUE(mc1orig->
getPDG() == mc1copy->getPDG());
616 EXPECT_TRUE(mc2orig->getPDG() == mc2copy->getPDG());
617 EXPECT_TRUE(mc3orig->getPDG() == mc3copy->getPDG());
619 EXPECT_TRUE(roeorig->hasParticle(ROEPion) && roecopy->hasParticle(ROEPion));
629 EXPECT_FALSE(mc4orig ==
nullptr);
630 EXPECT_TRUE(mc4copy ==
nullptr);
645 EXPECT_TRUE(mc5orig ==
nullptr);
646 EXPECT_FALSE(mc5copy ==
nullptr);
656 TEST_F(ParticleTest, ECLClusterBased)
661 cluster->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
662 cluster->setEnergy(1.);
663 cluster->setEnergyRaw(2.);
666 EXPECT_FLOAT_EQ(1., p.getECLClusterEnergy());
667 EXPECT_FLOAT_EQ(1., p.getEnergy());
668 EXPECT_EQ(ECLCluster::EHypothesisBit::c_nPhotons, p.getECLClusterEHypothesisBit());
669 EXPECT_FLOAT_EQ(0, p.getMass());
674 cluster->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
675 cluster->setEnergy(1.);
676 cluster->setEnergyRaw(2.);
679 EXPECT_EQ(130, p.getPDGCode());
680 EXPECT_FLOAT_EQ(2., p.getECLClusterEnergy());
681 EXPECT_FLOAT_EQ(std::sqrt(4. + 0.497614 * 0.497614), p.getEnergy());
682 EXPECT_EQ(ECLCluster::EHypothesisBit::c_neutralHadron, p.getECLClusterEHypothesisBit());
684 double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
685 EXPECT_FLOAT_EQ(m, p.getMass());
690 cluster->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
691 cluster->setEnergy(1.);
692 cluster->setEnergyRaw(2.);
695 EXPECT_EQ(2112, p.getPDGCode());
696 EXPECT_FLOAT_EQ(2., p.getECLClusterEnergy());
697 EXPECT_FLOAT_EQ(std::sqrt(4. + 0.93956536 * 0.93956536), p.getEnergy());
698 EXPECT_EQ(ECLCluster::EHypothesisBit::c_neutralHadron, p.getECLClusterEHypothesisBit());
700 double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
701 EXPECT_FLOAT_EQ(m, p.getMass());
706 TEST_F(ParticleTest, KLMClusterBased)
711 cluster->setTime(1.1);
712 cluster->setClusterPosition(1.1, 1.1, 1.0);
713 cluster->setLayers(1);
714 cluster->setInnermostLayer(1);
715 cluster->setMomentumMag(1.0);
719 EXPECT_EQ(pdg, p.getPDGCode());
720 double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
721 EXPECT_FLOAT_EQ(sqrt(1. + m * m), p.getEnergy());
723 EXPECT_FLOAT_EQ(m, p.getMass());
728 cluster->setTime(1.1);
729 cluster->setClusterPosition(1.1, 1.1, 1.0);
730 cluster->setLayers(1);
731 cluster->setInnermostLayer(1);
732 cluster->setMomentumMag(1.0);
736 EXPECT_EQ(pdg, p.getPDGCode());
737 double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
738 EXPECT_FLOAT_EQ(sqrt(1. + m * m), p.getEnergy());
740 EXPECT_FLOAT_EQ(m, p.getMass());
int getPDGCode() const
PDG code.
static const ParticleType neutron
neutron particle
static const ChargedStable pion
charged pion particle
static const ParticleType Klong
K^0_L particle.
static DataStore & Instance()
Instance of singleton Store.
void setInitializeActive(bool active)
Setter for m_initializeActive.
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
void setConnectedRegionId(int crid)
Set connected region id.
void setClusterId(int clusterid)
Set cluster id.
void setHypothesis(EHypothesisBit hypothesis)
Set hypotheses.
A Class to store the Monte Carlo particle information.
void setPDG(int pdg)
Set PDG code of the particle.
int getPDG() const
Return PDG code of particle.
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets the 4Vector of particle.
Class to store reconstructed particles.
void appendDaughter(const Particle *daughter, const bool updateType=true, const int daughterProperty=c_Ordinary)
Appends index of daughter to daughters index array.
bool overlapsWith(const Particle *oParticle) const
Returns true if final state ancestors of oParticle overlap.
bool isCopyOf(const Particle *oParticle, bool doDetailedComparison=false) const
Returns true if this Particle and oParticle are copies of each other.
int getPDGCode(void) const
Returns PDG code.
unsigned getNDaughters(void) const
Returns number of daughter particles.
TClonesArray * getArrayPointer() const
Returns the pointer to the store array which holds the daughter particles.
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
void addExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
void print() const
Prints the contents of a Particle object to standard output.
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
double getExtraInfo(const std::string &name) const
Return given value if set.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
This is a general purpose class for collecting reconstructed MDST data objects that are not used in r...
void addParticles(const std::vector< const Particle * > &particle)
Add StoreArray indices of given Particles to the list of unused particles in the event.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
T * appendNew()
Construct a new T object at the end of the array.
int getEntries() const
Get the number of objects in the array.
Type-safe access to single objects in the data store.
Object holding information for V0s.
Functions that create copies of Particles.
Particle * copyParticle(const Particle *original)
Function takes argument Particle and creates a copy of it and copies of all its (grand-)^n-daughters.
Abstract base class for different kinds of events.