Belle II Software  release-06-02-00
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 #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>
19 
20 #include <analysis/utility/ParticleCopy.h>
21 
22 #include <TDatabasePDG.h>
23 
24 #include <gtest/gtest.h>
25 
26 using namespace std;
27 using namespace Belle2;
28 using namespace Belle2::ParticleCopy;
29 
30 namespace {
32  class ParticleTest : public ::testing::Test {
33  protected:
35  void SetUp() override
36  {
37  DataStore::Instance().setInitializeActive(true);
38  StoreObjPtr<ParticleExtraInfoMap> particleExtraInfo;
39  StoreArray<Particle> particles;
40  StoreArray<MCParticle> mcparticles;
42  StoreArray<ECLCluster> eclClusters;
43  StoreArray<KLMCluster> klmClusters;
44  StoreArray<V0> v0s;
45  particleExtraInfo.registerInDataStore();
46  particles.registerInDataStore();
47  mcparticles.registerInDataStore();
48  eclClusters.registerInDataStore();
49  roes.registerInDataStore();
50  klmClusters.registerInDataStore();
51  v0s.registerInDataStore();
52  particles.registerRelationTo(mcparticles);
53  particles.registerRelationTo(roes);
54  DataStore::Instance().setInitializeActive(false);
55  }
56 
58  void TearDown() override
59  {
60  DataStore::Instance().reset();
61  }
62  };
63 
64 
65  TEST_F(ParticleTest, Constructors)
66  {
67  {
68  Particle p;
69  EXPECT_EQ(0, p.getPDGCode());
70  EXPECT_TRUE(TLorentzVector(0, 0, 0, 0) == p.get4Vector());
71  EXPECT_EQ(Particle::c_Undefined, p.getParticleSource());
72  }
73  {
74  TLorentzVector momentum(1, 2, 3, 4);
75  Particle p(momentum, 421);
76  EXPECT_EQ(421, p.getPDGCode());
77  EXPECT_FLOAT_EQ(0.0, momentum.DeltaPhi(p.get4Vector()));
78  EXPECT_FLOAT_EQ(0.0, momentum.DeltaR(p.get4Vector()));
79  EXPECT_FLOAT_EQ(momentum.Energy(), p.get4Vector().Energy());
80  EXPECT_FLOAT_EQ(momentum.Energy(), p.getEnergy());
81  EXPECT_FLOAT_EQ(momentum.M(), p.getMass());
82  EXPECT_EQ(Particle::c_Undefined, p.getParticleSource());
83  }
84  {
85  TLorentzVector momentum(1, 2, 3, 4);
86  Particle p(momentum, 22, Particle::c_Unflavored, Particle::c_MCParticle, 123);
87  EXPECT_EQ(22, p.getPDGCode());
88  EXPECT_FLOAT_EQ(0.0, momentum.DeltaPhi(p.get4Vector()));
89  EXPECT_FLOAT_EQ(0.0, momentum.DeltaR(p.get4Vector()));
90  EXPECT_FLOAT_EQ(momentum.Energy(), p.get4Vector().Energy());
91  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
92  EXPECT_EQ(Particle::c_MCParticle, p.getParticleSource());
93  EXPECT_EQ(123u, p.getMdstArrayIndex());
94  }
95  {
96  // test constructor from ECLClusters
97  // (for now we can only create a photon this way)
98  StoreArray<ECLCluster> clusters;
99  ECLCluster* cluster = clusters.appendNew(ECLCluster());
100  cluster->setIsTrack(false);
101  cluster->addHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
102  cluster->setEnergy(1337);
103 
104  Particle p(cluster);
105  EXPECT_EQ(22, p.getPDGCode());
106  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
107  EXPECT_EQ(Particle::c_ECLCluster, p.getParticleSource());
108  EXPECT_FLOAT_EQ(1337, p.getEnergy());
109  EXPECT_EQ(cluster, p.getECLCluster());
110  EXPECT_EQ(nullptr, p.getTrack());
111  }
112  {
113  // test constructor used for V0s (there is not actually a V0 constructor,
114  // the heavy-lifting is done in the particle loader), but this is V0-style
115  // construction with EParticleSourceObject::V0 and the correct getters
116  StoreArray<V0> v0s;
117  V0* v0 = v0s.appendNew(V0());
118  TLorentzVector momentum(1, 2, 3, 4);
119  Particle p(momentum, 310, Particle::c_Unflavored, Particle::c_V0, 0);
120  EXPECT_EQ(310, p.getPDGCode());
121  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
122  EXPECT_EQ(Particle::c_V0, p.getParticleSource());
123  EXPECT_EQ(0u, p.getMdstArrayIndex());
124  EXPECT_EQ(p.getV0(), v0); // pointers should be same
125  }
126  }
127 
128  TEST_F(ParticleTest, Daughters)
129  {
130  TLorentzVector momentum;
131  const int nDaughters = 6;
132  StoreArray<Particle> particles;
133  std::vector<int> daughterIndices;
134  for (int i = 0; i < nDaughters; i++) {
135  Particle d(TLorentzVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
136  momentum += d.get4Vector();
137  Particle* newDaughters = particles.appendNew(d);
138  daughterIndices.push_back(newDaughters->getArrayIndex());
139  }
140 
141  const Particle& p = *(particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices));
142  EXPECT_EQ(411, p.getPDGCode());
143  EXPECT_FLOAT_EQ(0.0, momentum.DeltaPhi(p.get4Vector()));
144  EXPECT_FLOAT_EQ(0.0, momentum.DeltaR(p.get4Vector()));
145  EXPECT_FLOAT_EQ(momentum.Energy(), p.get4Vector().Energy());
146  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
147  EXPECT_EQ(Particle::c_Composite, p.getParticleSource());
148  EXPECT_EQ(0u, p.getMdstArrayIndex());
149  EXPECT_EQ((unsigned int)nDaughters, p.getNDaughters());
150  EXPECT_EQ((unsigned int)nDaughters, p.getDaughters().size());
151  EXPECT_EQ((unsigned int)nDaughters, p.getFinalStateDaughters().size());
152  EXPECT_EQ((unsigned int)nDaughters, p.getDaughterProperties().size());
153 
154  const Particle pLocal(momentum, 411, Particle::c_Unflavored, daughterIndices, particles.getPtr());
155  EXPECT_DOUBLE_EQ(p.getMass(), pLocal.getMass());
156  EXPECT_EQ((unsigned int)nDaughters, pLocal.getNDaughters());
157  EXPECT_EQ((unsigned int)nDaughters, pLocal.getDaughters().size());
158  EXPECT_EQ((unsigned int)nDaughters, pLocal.getFinalStateDaughters().size());
159  EXPECT_EQ((unsigned int)nDaughters, pLocal.getDaughterProperties().size());
160 
161  Particle outsideArray;
162  EXPECT_TRUE(outsideArray.getArrayPointer() == nullptr);
163  EXPECT_B2FATAL(Particle p2 = Particle(momentum, 411, Particle::c_Unflavored, daughterIndices));
164  }
165 
166  TEST_F(ParticleTest, DaughterProperties)
167  {
168  TLorentzVector momentum;
169  const int nDaughters = 6;
170  StoreArray<Particle> particles;
171  std::vector<int> daughterIndices;
172  std::vector<int> daughterProperties;
173  for (int i = 0; i < nDaughters; i++) {
174  Particle d(TLorentzVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
175  momentum += d.get4Vector();
176  Particle* newDaughters = particles.appendNew(d);
177  daughterIndices.push_back(newDaughters->getArrayIndex());
178  daughterProperties.push_back(Particle::PropertyFlags::c_Ordinary);
179  }
180 
181  const Particle& p = *(particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices));
182  EXPECT_EQ(411, p.getPDGCode());
183  EXPECT_FLOAT_EQ(0.0, momentum.DeltaPhi(p.get4Vector()));
184  EXPECT_FLOAT_EQ(0.0, momentum.DeltaR(p.get4Vector()));
185  EXPECT_FLOAT_EQ(momentum.Energy(), p.get4Vector().Energy());
186  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
187  EXPECT_EQ(Particle::c_Composite, p.getParticleSource());
188  EXPECT_EQ(0u, p.getMdstArrayIndex());
189  EXPECT_EQ((unsigned int)nDaughters, p.getNDaughters());
190  EXPECT_EQ((unsigned int)nDaughters, p.getDaughters().size());
191  EXPECT_EQ((unsigned int)nDaughters, p.getFinalStateDaughters().size());
192  EXPECT_EQ((unsigned int)nDaughters, p.getDaughterProperties().size());
193  EXPECT_EQ(Particle::PropertyFlags::c_Ordinary, (p.getDaughterProperties())[0]);
194 
195 
196  const Particle pLocal(momentum, 411, Particle::c_Unflavored, daughterIndices,
197  Particle::PropertyFlags::c_Ordinary, daughterProperties,
198  particles.getPtr());
199  EXPECT_DOUBLE_EQ(p.getMass(), pLocal.getMass());
200  EXPECT_EQ((unsigned int)nDaughters, pLocal.getNDaughters());
201  EXPECT_EQ((unsigned int)nDaughters, pLocal.getDaughters().size());
202  EXPECT_EQ((unsigned int)nDaughters, pLocal.getFinalStateDaughters().size());
203  EXPECT_EQ((unsigned int)nDaughters, pLocal.getDaughterProperties().size());
204 
205  Particle outsideArray;
206  EXPECT_TRUE(outsideArray.getArrayPointer() == nullptr);
207  EXPECT_B2FATAL(Particle p2 = Particle(momentum, 411, Particle::c_Unflavored, daughterIndices));
208  }
209 
211  struct ParticleChildrenCounter {
212  int count{0};
214  bool operator()(const Particle*) { ++count; return false; }
215  };
216 
217  TEST_F(ParticleTest, ForEachDaughters)
218  {
219  // setup a particle with some daughters and grand daughters
220  TLorentzVector momentum;
221  const int nDaughters = 6;
222  StoreArray<Particle> particles;
223  std::vector<int> daughterIndices;
224  int nGrandDaughters = 0;
225  for (int i = 0; i < nDaughters; i++) {
226  Particle d(TLorentzVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
227  momentum += d.get4Vector();
228  Particle* newDaughters = particles.appendNew(d);
229  daughterIndices.push_back(newDaughters->getArrayIndex());
230  if (i % 2 == 0) {
231  Particle* grandDaughter = particles.appendNew(d);
232  newDaughters->appendDaughter(grandDaughter);
233  ++nGrandDaughters;
234  }
235  }
236  const Particle& p = *(particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices));
237 
238  // Check if we get called the correct amount of times
239  int count{0};
240  auto counterFct = [&count](const Particle*) { ++count; return false; };
241  EXPECT_FALSE(p.forEachDaughter(counterFct, false, false));
242  EXPECT_EQ(count, nDaughters);
243  count = 0;
244  EXPECT_FALSE(p.forEachDaughter(counterFct, true, false));
245  EXPECT_EQ(count, nDaughters + nGrandDaughters);
246  count = 0;
247  EXPECT_FALSE(p.forEachDaughter(counterFct, false, true));
248  EXPECT_EQ(count, nDaughters + 1);
249  count = 0;
250  EXPECT_FALSE(p.forEachDaughter(counterFct, true, true));
251  EXPECT_EQ(count, nDaughters + nGrandDaughters + 1);
252 
253  // Functors passed by value don't return the state
254  ParticleChildrenCounter counterStruct;
255  EXPECT_FALSE(p.forEachDaughter(counterStruct));
256  EXPECT_EQ(counterStruct.count, 0);
257  // But if reference_wrapped it should work fine
258  EXPECT_FALSE(p.forEachDaughter(std::reference_wrapper<ParticleChildrenCounter>(counterStruct)));
259  EXPECT_EQ(counterStruct.count, nDaughters + nGrandDaughters + 1);
260 
261  // Test return value: if we return true the processing should be stopped so
262  // count should not be increased anymore
263  int maxchildren{1}, total{nDaughters + nGrandDaughters + 1};
264  auto returnFctTester = [&count, &maxchildren](const Particle*) {++count; return count >= maxchildren; };
265  for (; maxchildren < 2 * total; ++maxchildren) {
266  count = 0;
267  EXPECT_EQ(p.forEachDaughter(returnFctTester), maxchildren <= total);
268  EXPECT_EQ(count, std::min(maxchildren, total));
269  }
270  }
271 
273  TEST_F(ParticleTest, ExtraInfo)
274  {
275  Particle p;
276  //doesn't exist
277  EXPECT_THROW(p.getExtraInfo("htns"), std::runtime_error);
278 
279  p.addExtraInfo("htns", 32.0);
280 
281  //cannot add it again
282  EXPECT_THROW(p.addExtraInfo("htns", 1234.0), std::runtime_error);
283 
284  EXPECT_DOUBLE_EQ(32.0, p.getExtraInfo("htns"));
285 
286  }
287 
289  TEST_F(ParticleTest, Copies)
290  {
291  StoreArray<Particle> particles;
292  StoreArray<MCParticle> mcparticles;
293  StoreArray<ECLCluster> eclClusters;
294  ECLCluster* eclGamma1 = eclClusters. appendNew(ECLCluster());
295  eclGamma1->setConnectedRegionId(1);
296  eclGamma1->setClusterId(1);
297  eclGamma1->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
298  ECLCluster* eclGamma2 = eclClusters. appendNew(ECLCluster());
299  eclGamma2->setConnectedRegionId(1);
300  eclGamma2->setClusterId(2);
301  eclGamma2->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
302  ECLCluster* eclGamma3 = eclClusters. appendNew(ECLCluster());
303  eclGamma3->setConnectedRegionId(2);
304  eclGamma3->setClusterId(1);
305  eclGamma3->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
306  ECLCluster* eclKL = eclClusters. appendNew(ECLCluster());
307  eclKL->setConnectedRegionId(2);
308  eclKL->setClusterId(1);
309  eclKL->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
310 
311 
312 
313  // create some particles
314  Particle* T1Pion = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 211, Particle::c_Flavored, Particle::c_Track, 1));
315  Particle* T2Pion = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), -211, Particle::c_Flavored, Particle::c_Track, 2));
316 
317  // T1PionCopy is a copy of T1Pion (both are created from the same Track and are pions)
318  Particle* T1PionCopy = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 211, Particle::c_Flavored, Particle::c_Track, 1));
319 
320  // T1Kaon is not a coy of T1Pion (both are created from the same Track, but are of different hypothesis)
321  Particle* T1Kaon = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 321, Particle::c_Flavored, Particle::c_Track, 1));
322  Particle* T2Kaon = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), -321, Particle::c_Flavored, Particle::c_Track, 2));
323  Particle* T3Kaon = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 321, Particle::c_Flavored, Particle::c_Track, 3));
324  Particle* T4Kaon = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), -321, Particle::c_Flavored, Particle::c_Track, 4));
325 
326  // T1Gamma
327  Particle* T1Gamma = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 22, Particle::c_Unflavored, Particle::c_ECLCluster,
328  0));
329  // T2Gamma
330  Particle* T2Gamma = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 22, Particle::c_Unflavored, Particle::c_ECLCluster,
331  1));
332 
333  // T3Gamma
334  Particle* T3Gamma = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 22, Particle::c_Unflavored, Particle::c_ECLCluster,
335  2));
336  // T4KL
337  Particle* T4KL = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), Const::Klong.getPDGCode(), Particle::c_Unflavored,
338  Particle::c_ECLCluster,
339  3));
340  MCParticle* MC1Pion = mcparticles. appendNew(MCParticle());
341  MC1Pion->setPDG(Const::pion.getPDGCode());
342  MC1Pion->set4Vector(TLorentzVector(0, 0, 0, 0));
343  Particle* T1PionFromMC = particles.appendNew(Particle(MC1Pion));
344 
345  EXPECT_TRUE(T3Gamma->overlapsWith(T4KL));
346  EXPECT_FALSE(T3Gamma->overlapsWith(T2Gamma));
347  EXPECT_FALSE(T3Gamma->overlapsWith(T1Gamma));
348  EXPECT_FALSE(T1Gamma->overlapsWith(T2Gamma));
349 
350  EXPECT_TRUE(T1Pion->isCopyOf(T1PionCopy));
351  EXPECT_FALSE(T1Pion->isCopyOf(T1Kaon));
352  EXPECT_FALSE(T1Pion->isCopyOf(T1Gamma));
353  EXPECT_FALSE(T2Gamma->isCopyOf(T1Gamma));
354 
355  //detailed comparison
356  EXPECT_TRUE(T1Pion->isCopyOf(T1PionCopy, true));
357  EXPECT_TRUE(T1Pion->isCopyOf(T1Kaon, true));
358  EXPECT_FALSE(T2Gamma->isCopyOf(T1Gamma, true));
359  EXPECT_TRUE(T3Gamma->isCopyOf(T4KL, true));
360  EXPECT_FALSE(T1PionFromMC->isCopyOf(T1Pion, true));
361  EXPECT_FALSE(T1Pion->isCopyOf(T1PionFromMC, true));
362  // Construct composite particles
363  Particle* D0Pi1Pi2 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
364  D0Pi1Pi2->appendDaughter(T1Pion);
365  D0Pi1Pi2->appendDaughter(T2Pion);
366 
367  Particle* D0Pi1Pi2Copy = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
368  D0Pi1Pi2Copy->appendDaughter(T1Pion);
369  D0Pi1Pi2Copy->appendDaughter(T2Pion);
370 
371  Particle* D0Pi1Pi2Copy2 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
372  D0Pi1Pi2Copy2->appendDaughter(T1PionCopy);
373  D0Pi1Pi2Copy2->appendDaughter(T2Pion);
374 
375  Particle* D0K1K2 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
376  D0K1K2->appendDaughter(T1Kaon);
377  D0K1K2->appendDaughter(T2Kaon);
378 
379  Particle* D0K1Pi2 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
380  D0K1Pi2->appendDaughter(T1Kaon);
381  D0K1Pi2->appendDaughter(T2Pion);
382 
383  EXPECT_FALSE(D0Pi1Pi2->isCopyOf(D0K1K2));
384  EXPECT_FALSE(D0Pi1Pi2->isCopyOf(D0K1Pi2));
385  EXPECT_TRUE(D0Pi1Pi2->isCopyOf(D0Pi1Pi2Copy));
386  EXPECT_TRUE(D0Pi1Pi2->isCopyOf(D0Pi1Pi2Copy2));
387  EXPECT_TRUE(D0Pi1Pi2Copy->isCopyOf(D0Pi1Pi2Copy2));
388 
389  // even more composite particles
390  Particle* D0K3K4 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 421));
391  D0K3K4->appendDaughter(T3Kaon);
392  D0K3K4->appendDaughter(T4Kaon);
393 
394  Particle* B0_1 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 511));
395  B0_1->appendDaughter(D0Pi1Pi2);
396  B0_1->appendDaughter(D0K3K4);
397 
398  Particle* B0_2 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 511));
399  B0_2->appendDaughter(D0Pi1Pi2Copy);
400  B0_2->appendDaughter(D0K3K4);
401 
402  Particle* B0_3 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 511));
403  B0_3->appendDaughter(D0Pi1Pi2Copy2);
404  B0_3->appendDaughter(D0K3K4);
405 
406  EXPECT_TRUE(B0_1->isCopyOf(B0_2));
407  EXPECT_TRUE(B0_1->isCopyOf(B0_3));
408  EXPECT_TRUE(B0_2->isCopyOf(B0_3));
409 
410  Particle* B0_4 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 511));
411  B0_4->appendDaughter(D0Pi1Pi2);
412  B0_4->appendDaughter(D0K1K2);
413 
414  Particle* B0_5 = particles.appendNew(Particle(TLorentzVector(0, 0, 0, 0), 511));
415  B0_5->appendDaughter(D0Pi1Pi2);
416  B0_5->appendDaughter(T1Kaon);
417  B0_5->appendDaughter(T2Kaon);
418 
419  EXPECT_FALSE(B0_1->isCopyOf(B0_4));
420  EXPECT_FALSE(B0_4->isCopyOf(B0_5));
421  }
422 
424  TEST_F(ParticleTest, ExtraInfoMap)
425  {
427 
428  Particle p;
429  p.print();
430  p.addExtraInfo("htns", 1.0);
431  EXPECT_EQ(1u, map->getNMaps());
432 
433  //adding another variable should just extend the current map
434  p.addExtraInfo("somethingelse", 2.0);
435  EXPECT_EQ(1u, map->getNMaps());
436 
437  //storing same things in another particle shouldn't create a new map
438  Particle q;
439  q.addExtraInfo("htns", 11.0);
440  EXPECT_EQ(1u, map->getNMaps());
441  q.addExtraInfo("somethingelse", 12.0);
442  EXPECT_EQ(1u, map->getNMaps());
443 
444  //lets store something different in p and q
445  p.addExtraInfo("thirdvar_p", 3.0);
446  EXPECT_EQ(1u, map->getNMaps());
447  //different var in 3rd place, needs new map
448  q.addExtraInfo("thirdvar_q", 13.0);
449  EXPECT_EQ(2u, map->getNMaps());
450 
451 
452  //set same vars as with p and q again, one of them should switch maps
453  Particle s;
454  s.addExtraInfo("htns", 1.0);
455  s.addExtraInfo("somethingelse", 2.0);
456  s.addExtraInfo("thirdvar_p", 3.0);
457  Particle t;
458  t.addExtraInfo("htns", 1.0);
459  t.addExtraInfo("somethingelse", 2.0);
460  t.addExtraInfo("thirdvar_q", 3.0);
461  //if switching works, there should still be the same number of maps
462  EXPECT_EQ(2u, map->getNMaps());
463  //verify switching worked
464  EXPECT_THROW(s.getExtraInfo("thirdvar_q"), std::runtime_error);
465  EXPECT_THROW(t.getExtraInfo("thirdvar_p"), std::runtime_error);
466 
467  //reusing maps shouldn't cause it to find unset vars (e.g. when one value is set, but map has more entries)
468  Particle u;
469  EXPECT_THROW(u.getExtraInfo("htns"), std::runtime_error);
470  u.addExtraInfo("htns", 1.0);
471  EXPECT_THROW(u.getExtraInfo("somethingelse"), std::runtime_error);
472  EXPECT_THROW(u.getExtraInfo("thirdvar_p"), std::runtime_error);
473  EXPECT_THROW(u.getExtraInfo("thirdvar_q"), std::runtime_error);
474  u.addExtraInfo("somethingelse", 2.0);
475  EXPECT_THROW(u.getExtraInfo("thirdvar_p"), std::runtime_error);
476  EXPECT_THROW(u.getExtraInfo("thirdvar_q"), std::runtime_error);
477 
478 
479  //add something else first, followed by variables we already used
480  Particle v;
481  v.addExtraInfo("first", 0.0);
482  v.addExtraInfo("htns", 1.0);
483  v.addExtraInfo("somethingelse", 2.0);
484  v.addExtraInfo("thirdvar_q", 3.0);
485 
486 
487  //verify the values we set
488  EXPECT_DOUBLE_EQ(1.0, p.getExtraInfo("htns"));
489  EXPECT_DOUBLE_EQ(2.0, p.getExtraInfo("somethingelse"));
490  EXPECT_DOUBLE_EQ(3.0, p.getExtraInfo("thirdvar_p"));
491 
492  EXPECT_DOUBLE_EQ(11.0, q.getExtraInfo("htns"));
493  EXPECT_DOUBLE_EQ(12.0, q.getExtraInfo("somethingelse"));
494  EXPECT_DOUBLE_EQ(13.0, q.getExtraInfo("thirdvar_q"));
495 
496  EXPECT_DOUBLE_EQ(1.0, s.getExtraInfo("htns"));
497  EXPECT_DOUBLE_EQ(2.0, s.getExtraInfo("somethingelse"));
498  EXPECT_DOUBLE_EQ(3.0, s.getExtraInfo("thirdvar_p"));
499 
500  EXPECT_DOUBLE_EQ(1.0, t.getExtraInfo("htns"));
501  EXPECT_DOUBLE_EQ(2.0, t.getExtraInfo("somethingelse"));
502  EXPECT_DOUBLE_EQ(3.0, t.getExtraInfo("thirdvar_q"));
503 
504  EXPECT_DOUBLE_EQ(0.0, v.getExtraInfo("first"));
505  EXPECT_DOUBLE_EQ(1.0, v.getExtraInfo("htns"));
506  EXPECT_DOUBLE_EQ(2.0, v.getExtraInfo("somethingelse"));
507  EXPECT_DOUBLE_EQ(3.0, v.getExtraInfo("thirdvar_q"));
508 
509  //check data is copied with Particle
510  Particle tCopy = t;
511  EXPECT_DOUBLE_EQ(1.0, tCopy.getExtraInfo("htns"));
512  EXPECT_DOUBLE_EQ(2.0, tCopy.getExtraInfo("somethingelse"));
513  EXPECT_DOUBLE_EQ(3.0, tCopy.getExtraInfo("thirdvar_q"));
514  tCopy.print();
515  }
516 
517 
519  TEST_F(ParticleTest, ParticleCopyUtility)
520  {
521  StoreArray<Particle> particles;
522  StoreArray<MCParticle> mcparticles;
524 
525  // create some particles
526  Particle* T1Pion = particles.appendNew(Particle(TLorentzVector(1, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 1));
527  MCParticle* MC1 = mcparticles. appendNew(MCParticle());
528  MC1->setPDG(1);
529  T1Pion->addExtraInfo("test_var", 1.0);
530  T1Pion->addRelationTo(MC1);
531  Particle* T2Kaon = particles.appendNew(Particle(TLorentzVector(2, 2, 2, 2), -321, Particle::c_Flavored, Particle::c_Track, 2));
532  MCParticle* MC2 = mcparticles. appendNew(MCParticle());
533  MC1->setPDG(2);
534  T2Kaon->addExtraInfo("test_var", 2.0);
535  T2Kaon->addRelationTo(MC2);
536  Particle* T3Kaon = particles.appendNew(Particle(TLorentzVector(3, 3, 3, 3), 321, Particle::c_Flavored, Particle::c_Track, 3));
537  MCParticle* MC3 = mcparticles. appendNew(MCParticle());
538  MC3->setPDG(3);
539  T3Kaon->addExtraInfo("test_var", 3.0);
540  T3Kaon->addRelationTo(MC3);
541  Particle* ROEPion = particles.appendNew(Particle(TLorentzVector(3.5, 3.5, 3.5, 3.5), 211, Particle::c_Flavored,
542  Particle::c_Track, 4));
543 
544  // Construct composite particles
545  Particle* D0KK = particles.appendNew(Particle(TLorentzVector(4, 4, 4, 4), 421));
546  D0KK->appendDaughter(T2Kaon);
547  D0KK->appendDaughter(T3Kaon);
548 
549  Particle* B0 = particles.appendNew(Particle(TLorentzVector(5, 5, 5, 5), 511));
550  B0->appendDaughter(D0KK);
551  B0->appendDaughter(T1Pion);
552 
553  RestOfEvent* roe = roes.appendNew(RestOfEvent());
554 
555  roe->addParticles({ROEPion});
556  B0->addRelationTo(roe);
557 
558  // Perform tests
559  // First sanity check
560  // at this point the size of Particle/MCParticle/ROE StoreArray should be 6/3/1
561  EXPECT_EQ(particles.getEntries(), 6);
562  EXPECT_EQ(mcparticles.getEntries(), 3);
563  EXPECT_EQ(roes.getEntries(), 1);
564 
565  // now make a copy of B0
566  Particle* B0_copy = copyParticle(B0);
567  // at this point the size of Particle/MCParticle/ROE StoreArray should be 11/3/1
568  EXPECT_EQ(particles.getEntries(), 11);
569  EXPECT_EQ(mcparticles.getEntries(), 3);
570  EXPECT_EQ(roes.getEntries(), 1);
571 
572  // compare copy with original
573  EXPECT_EQ(B0->getPDGCode(), B0_copy->getPDGCode());
574  EXPECT_EQ(B0->getNDaughters(), B0_copy->getNDaughters());
575  EXPECT_EQ(B0->getDaughter(0)->getPDGCode(), B0_copy->getDaughter(0)->getPDGCode());
576  EXPECT_EQ(B0->getDaughter(1)->getPDGCode(), B0_copy->getDaughter(1)->getPDGCode());
577  EXPECT_EQ(B0->getDaughter(0)->getDaughter(0)->getPDGCode(), B0_copy->getDaughter(0)->getDaughter(0)->getPDGCode());
578  EXPECT_EQ(B0->getDaughter(0)->getDaughter(1)->getPDGCode(), B0_copy->getDaughter(0)->getDaughter(1)->getPDGCode());
579 
580  EXPECT_FALSE(B0->getArrayIndex() == B0_copy->getArrayIndex());
581  EXPECT_FALSE(B0->getDaughter(0)->getArrayIndex() == B0_copy->getDaughter(0)->getArrayIndex());
582  EXPECT_FALSE(B0->getDaughter(1)->getArrayIndex() == B0_copy->getDaughter(1)->getArrayIndex());
583  EXPECT_FALSE(B0->getDaughter(0)->getDaughter(0)->getArrayIndex() == B0_copy->getDaughter(0)->getDaughter(0)->getArrayIndex());
584  EXPECT_FALSE(B0->getDaughter(0)->getDaughter(1)->getArrayIndex() == B0_copy->getDaughter(0)->getDaughter(1)->getArrayIndex());
585 
586  EXPECT_TRUE(B0->get4Vector() == B0_copy->get4Vector());
587  EXPECT_TRUE(B0->getDaughter(0)->get4Vector() == B0_copy->getDaughter(0)->get4Vector());
588  EXPECT_TRUE(B0->getDaughter(1)->get4Vector() == B0_copy->getDaughter(1)->get4Vector());
589  EXPECT_TRUE(B0->getDaughter(0)->getDaughter(0)->get4Vector() == B0_copy->getDaughter(0)->getDaughter(0)->get4Vector());
590  EXPECT_TRUE(B0->getDaughter(0)->getDaughter(1)->get4Vector() == B0_copy->getDaughter(0)->getDaughter(1)->get4Vector());
591 
592  EXPECT_TRUE(B0->getDaughter(1)->getExtraInfo("test_var") == B0_copy->getDaughter(1)->getExtraInfo("test_var"));
593  EXPECT_TRUE(B0->getDaughter(0)->getDaughter(0)->getExtraInfo("test_var") == B0_copy->getDaughter(0)->getDaughter(
594  0)->getExtraInfo("test_var"));
595  EXPECT_TRUE(B0->getDaughter(0)->getDaughter(1)->getExtraInfo("test_var") == B0_copy->getDaughter(0)->getDaughter(
596  1)->getExtraInfo("test_var"));
597 
598  // check relations
599  const MCParticle* mc1orig = B0->getDaughter(1)->getRelated<MCParticle>();
600  const MCParticle* mc2orig = B0->getDaughter(0)->getDaughter(0)->getRelated<MCParticle>();
601  const MCParticle* mc3orig = B0->getDaughter(0)->getDaughter(1)->getRelated<MCParticle>();
602 
603  const MCParticle* mc1copy = B0_copy->getDaughter(1)->getRelated<MCParticle>();
604  const MCParticle* mc2copy = B0_copy->getDaughter(0)->getDaughter(0)->getRelated<MCParticle>();
605  const MCParticle* mc3copy = B0_copy->getDaughter(0)->getDaughter(1)->getRelated<MCParticle>();
606 
607  const RestOfEvent* roeorig = B0->getRelated<RestOfEvent>();
608  const RestOfEvent* roecopy = B0_copy->getRelated<RestOfEvent>();
609 
610  EXPECT_TRUE(mc1orig == mc1copy);
611  EXPECT_TRUE(mc2orig == mc2copy);
612  EXPECT_TRUE(mc3orig == mc3copy);
613 
614  EXPECT_TRUE(mc1orig->getPDG() == mc1copy->getPDG());
615  EXPECT_TRUE(mc2orig->getPDG() == mc2copy->getPDG());
616  EXPECT_TRUE(mc3orig->getPDG() == mc3copy->getPDG());
617 
618  EXPECT_TRUE(roeorig->hasParticle(ROEPion) && roecopy->hasParticle(ROEPion));
619 
620  // modify original and check the copy
621  MCParticle* MC4 = mcparticles. appendNew(MCParticle());
622  MC4->setPDG(4);
623  B0->getDaughter(0)->addRelationTo(MC4);
624 
625  const MCParticle* mc4orig = B0->getDaughter(0)->getRelated<MCParticle>();
626  const MCParticle* mc4copy = B0_copy->getDaughter(0)->getRelated<MCParticle>();
627 
628  EXPECT_FALSE(mc4orig == nullptr);
629  EXPECT_TRUE(mc4copy == nullptr);
630 
631  const_cast<Particle*>(B0->getDaughter(1))->addExtraInfo("origOnly_var", 10.0);
632 
633  EXPECT_DOUBLE_EQ(10.0, B0->getDaughter(1)->getExtraInfo("origOnly_var"));
634  EXPECT_THROW(B0_copy->getDaughter(1)->getExtraInfo("origOnly_var"), std::runtime_error);
635 
636  // modify copy and check the original
637  MCParticle* MC5 = mcparticles. appendNew(MCParticle());
638  MC5->setPDG(5);
639  B0_copy->addRelationTo(MC5);
640 
641  const MCParticle* mc5orig = B0->getRelated<MCParticle>();
642  const MCParticle* mc5copy = B0_copy->getRelated<MCParticle>();
643 
644  EXPECT_TRUE(mc5orig == nullptr);
645  EXPECT_FALSE(mc5copy == nullptr);
646 
647  const_cast<Particle*>(B0_copy->getDaughter(1))->addExtraInfo("copyOnly_var", 15.0);
648 
649  EXPECT_THROW(B0->getDaughter(1)->getExtraInfo("copyOnly_var"), std::runtime_error);
650  EXPECT_DOUBLE_EQ(15.0, B0_copy->getDaughter(1)->getExtraInfo("copyOnly_var"));
651 
652  }
653 
655  TEST_F(ParticleTest, ECLClusterBased)
656  {
657  StoreArray<ECLCluster> eclclusters;
658  {
659  ECLCluster* cluster = eclclusters.appendNew(ECLCluster());
660  cluster->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
661  cluster->setEnergy(1.);
662  cluster->setEnergyRaw(2.);
663 
664  Particle p(cluster);
665  EXPECT_FLOAT_EQ(1., p.getECLClusterEnergy());
666  EXPECT_FLOAT_EQ(1., p.getEnergy());
667  EXPECT_EQ(ECLCluster::EHypothesisBit::c_nPhotons, p.getECLClusterEHypothesisBit());
668  EXPECT_FLOAT_EQ(0, p.getMass());
669  }
670 
671  {
672  ECLCluster* cluster = eclclusters.appendNew(ECLCluster());
673  cluster->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
674  cluster->setEnergy(1.);
675  cluster->setEnergyRaw(2.);
676 
677  Particle p(cluster, Const::Klong);
678  EXPECT_EQ(130, p.getPDGCode());
679  EXPECT_FLOAT_EQ(2., p.getECLClusterEnergy());
680  EXPECT_FLOAT_EQ(std::sqrt(4. + 0.497614 * 0.497614), p.getEnergy());
681  EXPECT_EQ(ECLCluster::EHypothesisBit::c_neutralHadron, p.getECLClusterEHypothesisBit());
682  int pdg = Const::Klong.getPDGCode();
683  double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
684  EXPECT_FLOAT_EQ(m, p.getMass());
685  }
686 
687  {
688  ECLCluster* cluster = eclclusters.appendNew(ECLCluster());
689  cluster->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
690  cluster->setEnergy(1.);
691  cluster->setEnergyRaw(2.);
692 
693  Particle p(cluster, Const::neutron);
694  EXPECT_EQ(2112, p.getPDGCode());
695  EXPECT_FLOAT_EQ(2., p.getECLClusterEnergy());
696  EXPECT_FLOAT_EQ(std::sqrt(4. + 0.93956536 * 0.93956536), p.getEnergy());
697  EXPECT_EQ(ECLCluster::EHypothesisBit::c_neutralHadron, p.getECLClusterEHypothesisBit());
698  int pdg = Const::neutron.getPDGCode();
699  double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
700  EXPECT_FLOAT_EQ(m, p.getMass());
701  }
702  }
703 
705  TEST_F(ParticleTest, KLMClusterBased)
706  {
707  StoreArray<KLMCluster> klmClusters;
708  {
709  KLMCluster* cluster = klmClusters.appendNew(KLMCluster());
710  cluster->setTime(1.1);
711  cluster->setClusterPosition(1.1, 1.1, 1.0);
712  cluster->setLayers(1);
713  cluster->setInnermostLayer(1);
714  cluster->setMomentumMag(1.0);
715 
716  Particle p(cluster);
717  int pdg = Const::Klong.getPDGCode();
718  EXPECT_EQ(pdg, p.getPDGCode());
719  double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
720  EXPECT_FLOAT_EQ(sqrt(1. + m * m), p.getEnergy());
721  EXPECT_EQ(Particle::c_Unflavored, p.getFlavorType());
722  EXPECT_FLOAT_EQ(m, p.getMass());
723  }
724 
725  {
726  KLMCluster* cluster = klmClusters.appendNew(KLMCluster());
727  cluster->setTime(1.1);
728  cluster->setClusterPosition(1.1, 1.1, 1.0);
729  cluster->setLayers(1);
730  cluster->setInnermostLayer(1);
731  cluster->setMomentumMag(1.0);
732 
733  Particle p(cluster, Const::neutron.getPDGCode());
734  int pdg = Const::neutron.getPDGCode();
735  EXPECT_EQ(pdg, p.getPDGCode());
736  double m = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
737  EXPECT_FLOAT_EQ(sqrt(1. + m * m), p.getEnergy());
738  EXPECT_EQ(Particle::c_Flavored, p.getFlavorType());
739  EXPECT_FLOAT_EQ(m, p.getMass());
740  }
741  }
742 } // namespace
ECL cluster data.
Definition: ECLCluster.h:27
void setConnectedRegionId(int crid)
Set connected region id.
Definition: ECLCluster.h:142
void setClusterId(int clusterid)
Set cluster id.
Definition: ECLCluster.h:145
void setHypothesis(EHypothesisBit hypothesis)
Set hypotheses.
Definition: ECLCluster.h:123
KLM cluster data.
Definition: KLMCluster.h:28
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
void set4Vector(const TLorentzVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:435
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:332
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Class to store reconstructed particles.
Definition: Particle.h:74
bool overlapsWith(const Particle *oParticle) const
Returns true if final state ancestors of oParticle overlap.
Definition: Particle.cc:706
TClonesArray * getArrayPointer() const
Returns the pointer to the store array which holds the daughter particles.
Definition: Particle.h:866
bool isCopyOf(const Particle *oParticle, bool doDetailedComparison=false) const
Returns true if this Particle and oParticle are copies of each other.
Definition: Particle.cc:721
float getExtraInfo(const std::string &name) const
Return given value if set.
Definition: Particle.cc:1242
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:392
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1289
unsigned getNDaughters(void) const
Returns number of daughter particles.
Definition: Particle.h:647
TLorentzVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:477
void print() const
Prints the contents of a Particle object to standard output.
Definition: Particle.cc:1126
void appendDaughter(const Particle *daughter, const bool updateType=true)
Appends index of daughter to daughters index array.
Definition: Particle.cc:677
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
Definition: Particle.cc:639
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...
Definition: RestOfEvent.h:57
void addParticles(const std::vector< const Particle * > &particle)
Add StoreArray indices of given Particles to the list of unused particles in the event.
Definition: RestOfEvent.cc:25
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Object holding information for V0s.
Definition: V0.h:30
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
Definition: globalLabel.cc:72
Functions that create copies of Particles.
Definition: ParticleCopy.h:22
Particle * copyParticle(const Particle *original)
Function takes argument Particle and creates a copy of it and copies of all its (grand-)^n-daughters.
Definition: ParticleCopy.cc:18
Abstract base class for different kinds of events.