Belle II Software light-2406-ragdoll
variables.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/variables/Variables.h>
10#include <analysis/variables/BasicParticleInformation.h>
11#include <analysis/variables/VertexVariables.h>
12#include <analysis/variables/PIDVariables.h>
13#include <analysis/variables/TrackVariables.h>
14
15#include <analysis/VariableManager/Manager.h>
16#include <analysis/VariableManager/Utility.h>
17
18#include <analysis/dataobjects/Particle.h>
19#include <analysis/dataobjects/ParticleExtraInfoMap.h>
20#include <analysis/dataobjects/ParticleList.h>
21#include <framework/dataobjects/EventExtraInfo.h>
22#include <analysis/dataobjects/RestOfEvent.h>
23#include <analysis/utility/ReferenceFrame.h>
24
25#include <framework/datastore/StoreArray.h>
26#include <framework/datastore/StoreObjPtr.h>
27#include <framework/utilities/TestHelpers.h>
28#include <framework/logging/Logger.h>
29#include <framework/gearbox/Gearbox.h>
30#include <framework/gearbox/Const.h>
31
32#include <mdst/dataobjects/MCParticle.h>
33#include <mdst/dataobjects/MCParticleGraph.h>
34#include <mdst/dataobjects/PIDLikelihood.h>
35#include <mdst/dataobjects/Track.h>
36#include <mdst/dataobjects/V0.h>
37#include <mdst/dataobjects/ECLCluster.h>
38#include <mdst/dataobjects/KLMCluster.h>
39
40#include <gtest/gtest.h>
41
42#include <TMatrixFSym.h>
43#include <TRandom3.h>
44#include <Math/Cartesian2D.h>
45#include <Math/Vector3D.h>
46#include <Math/Vector4D.h>
47#include <TMath.h>
48#include <utility>
49
50using namespace std;
51using namespace Belle2;
52using namespace Belle2::Variable;
53using namespace ROOT::Math;
54
55namespace {
56
58 TEST(KinematicVariableTest, Variable)
59 {
60
61 // Connect gearbox for CMS variables
62
63 Gearbox& gearbox = Gearbox::getInstance();
64 gearbox.setBackends({std::string("file:")});
65 gearbox.close();
66 gearbox.open("geometry/Belle2.xml", false);
67
68 {
69 Particle pH({0.290582573157898, 0, 6.99796952744559, 7.004}, 11);
70 Particle pL({0.166035330010433, 0, -3.99855423973071, 4.002}, -11);
71
72 Particle p({0, 0.999999869440028, 0, 1.0}, -11);
73 const double eps = 1e-15;
75
76 EXPECT_NEAR(0.0, particlePx(&pH), eps);
77 EXPECT_NEAR(0.0, particlePy(&pH), eps);
78 EXPECT_NEAR(0.0, particlePx(&pL), eps);
79 EXPECT_NEAR(0.0, particlePy(&pL), eps);
80 EXPECT_FLOAT_EQ(5.289778893721573, particlePz(&pH));
81 EXPECT_FLOAT_EQ(-5.289778893721573, particlePz(&pL));
82 EXPECT_FLOAT_EQ(10.579557836806245064 / 2, particleE(&pH));
83 EXPECT_FLOAT_EQ(10.579557836806245064 / 2, particleE(&pL));
84
85 EXPECT_FLOAT_EQ(0.999999869440028, particlePy(&p));
86 }
87
88 {
89 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 411);
90
91 TMatrixFSym error(7);
92 error.Zero();
93 error(0, 0) = 0.05;
94 error(1, 1) = 0.2;
95 error(2, 2) = 0.4;
96 error(0, 1) = -0.1;
97 error(0, 2) = 0.9;
98 p.setMomentumVertexErrorMatrix(error);
99
100 EXPECT_FLOAT_EQ(0.9, particleP(&p));
101 EXPECT_FLOAT_EQ(1.0, particleE(&p));
102 EXPECT_FLOAT_EQ(0.1, particlePx(&p));
103 EXPECT_FLOAT_EQ(-0.4, particlePy(&p));
104 EXPECT_FLOAT_EQ(0.8, particlePz(&p));
105 EXPECT_FLOAT_EQ(0.412310562, particlePt(&p));
106 EXPECT_FLOAT_EQ(0.8 / 0.9, particleCosTheta(&p));
107 EXPECT_FLOAT_EQ(-1.325817664, particlePhi(&p));
108
109 EXPECT_FLOAT_EQ(0.737446378, particlePErr(&p));
110 EXPECT_FLOAT_EQ(sqrt(0.05), particlePxErr(&p));
111 EXPECT_FLOAT_EQ(sqrt(0.2), particlePyErr(&p));
112 EXPECT_FLOAT_EQ(sqrt(0.4), particlePzErr(&p));
113 EXPECT_FLOAT_EQ(0.488093530, particlePtErr(&p));
114 EXPECT_FLOAT_EQ(0.156402664, particleCosThetaErr(&p));
115 EXPECT_FLOAT_EQ(0.263066820, particlePhiErr(&p));
116
117
118 {
120 EXPECT_FLOAT_EQ(0.68174648, particleP(&p));
121 EXPECT_FLOAT_EQ(0.80918372, particleE(&p));
122 EXPECT_FLOAT_EQ(0.058562335, particlePx(&p));
123 EXPECT_FLOAT_EQ(-0.40000001, particlePy(&p));
124 EXPECT_FLOAT_EQ(0.5489524, particlePz(&p));
125 EXPECT_FLOAT_EQ(0.40426421, particlePt(&p));
126 EXPECT_FLOAT_EQ(0.80521482, particleCosTheta(&p));
127 EXPECT_FLOAT_EQ(-1.4254233, particlePhi(&p));
128
129 EXPECT_FLOAT_EQ(sqrt(0.2), particlePyErr(&p));
130 }
131
132 {
134 EXPECT_ALL_NEAR(particleP(&p), 0.0, 1e-9);
135 EXPECT_FLOAT_EQ(0.4358899, particleE(&p));
136 EXPECT_ALL_NEAR(0.0, particlePx(&p), 1e-9);
137 EXPECT_ALL_NEAR(0.0, particlePy(&p), 1e-9);
138 EXPECT_ALL_NEAR(0.0, particlePz(&p), 1e-9);
139 EXPECT_ALL_NEAR(0.0, particlePt(&p), 1e-9);
140
141 }
142
143 {
145 EXPECT_FLOAT_EQ(0.9, particleP(&p));
146 EXPECT_FLOAT_EQ(1.0, particleE(&p));
147 EXPECT_FLOAT_EQ(0.1, particlePx(&p));
148 EXPECT_FLOAT_EQ(-0.4, particlePy(&p));
149 EXPECT_FLOAT_EQ(0.8, particlePz(&p));
150 EXPECT_FLOAT_EQ(0.412310562, particlePt(&p));
151 EXPECT_FLOAT_EQ(0.8 / 0.9, particleCosTheta(&p));
152 EXPECT_FLOAT_EQ(-1.325817664, particlePhi(&p));
153
154 EXPECT_FLOAT_EQ(0.737446378, particlePErr(&p));
155 EXPECT_FLOAT_EQ(sqrt(0.05), particlePxErr(&p));
156 EXPECT_FLOAT_EQ(sqrt(0.2), particlePyErr(&p));
157 EXPECT_FLOAT_EQ(sqrt(0.4), particlePzErr(&p));
158 EXPECT_FLOAT_EQ(0.488093530, particlePtErr(&p));
159 EXPECT_FLOAT_EQ(0.156402664, particleCosThetaErr(&p));
160 EXPECT_FLOAT_EQ(0.263066820, particlePhiErr(&p));
161 }
162
163 {
164 UseReferenceFrame<RotationFrame> dummy(XYZVector(1, 0, 0), XYZVector(0, 1, 0), XYZVector(0, 0, 1));
165 EXPECT_FLOAT_EQ(0.9, particleP(&p));
166 EXPECT_FLOAT_EQ(1.0, particleE(&p));
167 EXPECT_FLOAT_EQ(0.1, particlePx(&p));
168 EXPECT_FLOAT_EQ(-0.4, particlePy(&p));
169 EXPECT_FLOAT_EQ(0.8, particlePz(&p));
170 EXPECT_FLOAT_EQ(0.412310562, particlePt(&p));
171 EXPECT_FLOAT_EQ(0.8 / 0.9, particleCosTheta(&p));
172 EXPECT_FLOAT_EQ(-1.325817664, particlePhi(&p));
173
174 EXPECT_FLOAT_EQ(0.737446378, particlePErr(&p));
175 EXPECT_FLOAT_EQ(sqrt(0.05), particlePxErr(&p));
176 EXPECT_FLOAT_EQ(sqrt(0.2), particlePyErr(&p));
177 EXPECT_FLOAT_EQ(sqrt(0.4), particlePzErr(&p));
178 EXPECT_FLOAT_EQ(0.488093530, particlePtErr(&p));
179 EXPECT_FLOAT_EQ(0.156402664, particleCosThetaErr(&p));
180 EXPECT_FLOAT_EQ(0.263066820, particlePhiErr(&p));
181
182 const auto& frame = ReferenceFrame::GetCurrent();
183 EXPECT_FLOAT_EQ(-0.1, frame.getMomentumErrorMatrix(&p)(0, 1));
184 EXPECT_FLOAT_EQ(0.9, frame.getMomentumErrorMatrix(&p)(0, 2));
185 }
186
187 {
188 UseReferenceFrame<RotationFrame> dummy(XYZVector(1, 0, 0), XYZVector(0, 0, -1), XYZVector(0, 1, 0));
189 EXPECT_FLOAT_EQ(0.9, particleP(&p));
190 EXPECT_FLOAT_EQ(1.0, particleE(&p));
191 EXPECT_FLOAT_EQ(0.1, particlePx(&p));
192 EXPECT_FLOAT_EQ(-0.8, particlePy(&p));
193 EXPECT_FLOAT_EQ(-0.4, particlePz(&p));
194
195 EXPECT_FLOAT_EQ(0.737446378, particlePErr(&p));
196 EXPECT_FLOAT_EQ(sqrt(0.05), particlePxErr(&p));
197 EXPECT_FLOAT_EQ(sqrt(0.4), particlePyErr(&p));
198 EXPECT_FLOAT_EQ(sqrt(0.2), particlePzErr(&p));
199
200 const auto& frame = ReferenceFrame::GetCurrent();
201 EXPECT_FLOAT_EQ(-0.9, frame.getMomentumErrorMatrix(&p)(0, 1));
202 EXPECT_FLOAT_EQ(-0.1, frame.getMomentumErrorMatrix(&p)(0, 2));
203 }
204
205 {
206 UseReferenceFrame<CMSRotationFrame> dummy(XYZVector(1, 0, 0), XYZVector(0, 1, 0), XYZVector(0, 0, 1));
207 EXPECT_FLOAT_EQ(0.68174648, particleP(&p));
208 EXPECT_FLOAT_EQ(0.80918372, particleE(&p));
209 EXPECT_FLOAT_EQ(0.058562335, particlePx(&p));
210 EXPECT_FLOAT_EQ(-0.40000001, particlePy(&p));
211 EXPECT_FLOAT_EQ(0.5489524, particlePz(&p));
212 EXPECT_FLOAT_EQ(0.40426421, particlePt(&p));
213 EXPECT_FLOAT_EQ(0.80521482, particleCosTheta(&p));
214 EXPECT_FLOAT_EQ(-1.4254233, particlePhi(&p));
215
216 EXPECT_FLOAT_EQ(sqrt(0.2), particlePyErr(&p));
217 }
218
219 {
220 Particle pinv({ -0.1, 0.4, -0.8, 1.0 }, 411);
221 UseReferenceFrame<RestFrame> dummy(&pinv);
222 Particle p2({ 0.0, 0.0, 0.0, 0.4358899}, 411);
223 EXPECT_FLOAT_EQ(0.9, particleP(&p2));
224 EXPECT_FLOAT_EQ(1.0, particleE(&p2));
225 EXPECT_FLOAT_EQ(0.1, particlePx(&p2));
226 EXPECT_FLOAT_EQ(-0.4, particlePy(&p2));
227 EXPECT_FLOAT_EQ(0.8, particlePz(&p2));
228 EXPECT_FLOAT_EQ(0.412310562, particlePt(&p2));
229 EXPECT_FLOAT_EQ(0.8 / 0.9, particleCosTheta(&p2));
230 EXPECT_FLOAT_EQ(-1.325817664, particlePhi(&p2));
231 }
232 }
233
234 {
235 Particle p({ 0.0, 0.0, 0.0, 0.0 }, 411);
236 EXPECT_FLOAT_EQ(0.0, particleP(&p));
237 EXPECT_FLOAT_EQ(0.0, particleE(&p));
238 EXPECT_FLOAT_EQ(0.0, particlePx(&p));
239 EXPECT_FLOAT_EQ(0.0, particlePy(&p));
240 EXPECT_FLOAT_EQ(0.0, particlePz(&p));
241 EXPECT_FLOAT_EQ(0.0, particlePt(&p));
242 EXPECT_FLOAT_EQ(1.0, particleCosTheta(&p));
243 EXPECT_FLOAT_EQ(0.0, particlePhi(&p));
244
246 EXPECT_FLOAT_EQ(0.0, particleP(&p));
247 EXPECT_FLOAT_EQ(0.0, particleE(&p));
248 EXPECT_FLOAT_EQ(0.0, particlePx(&p));
249 EXPECT_FLOAT_EQ(0.0, particlePy(&p));
250 EXPECT_FLOAT_EQ(0.0, particlePz(&p));
251 EXPECT_FLOAT_EQ(0.0, particlePt(&p));
252 EXPECT_FLOAT_EQ(1.0, particleCosTheta(&p));
253 EXPECT_FLOAT_EQ(0.0, particlePhi(&p));
254 }
255
256 {
258 StoreArray<Particle> particles;
259 particles.registerInDataStore();
262 PxPyPzEVector vec0 = {0.0, 0.0, 0.0, T.getCMSEnergy()};
263 PxPyPzEVector vec1 = {0.0, +0.332174566, 0.0, T.getCMSEnergy() / 2.};
264 PxPyPzEVector vec2 = {0.0, -0.332174566, 0.0, T.getCMSEnergy() / 2.};
265 Particle* p0 = particles.appendNew(Particle(T.rotateCmsToLab() * vec0, 22));
266 Particle* p1 = particles.appendNew(Particle(T.rotateCmsToLab() * vec1, 22, Particle::c_Unflavored, Particle::c_Undefined, 1));
267 Particle* p2 = particles.appendNew(Particle(T.rotateCmsToLab() * vec2, 22, Particle::c_Unflavored, Particle::c_Undefined, 2));
268
269 p0->appendDaughter(p1->getArrayIndex());
270 p0->appendDaughter(p2->getArrayIndex());
271
272 EXPECT_ALL_NEAR(m2RecoilSignalSide(p0), 0.0, 1e-7);
273 }
274
275
276 }
277
278
279 TEST(VertexVariableTest, Variable)
280 {
281
282 // Connect gearbox for CMS variables
283
284 Gearbox& gearbox = Gearbox::getInstance();
285 gearbox.setBackends({std::string("file:")});
286 gearbox.close();
287 gearbox.open("geometry/Belle2.xml", false);
288
289 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 11);
290 p.setPValue(0.5);
291 p.setVertex(XYZVector(1.0, 2.0, 2.0));
292
293 EXPECT_FLOAT_EQ(1.0, particleDX(&p));
294 EXPECT_FLOAT_EQ(2.0, particleDY(&p));
295 EXPECT_FLOAT_EQ(2.0, particleDZ(&p));
296 EXPECT_FLOAT_EQ(std::sqrt(5.0), particleDRho(&p));
297 EXPECT_FLOAT_EQ(3.0, particleDistance(&p));
298 EXPECT_FLOAT_EQ(0.5, particlePvalue(&p));
299
300 {
302 EXPECT_FLOAT_EQ(1.026177, particleDX(&p));
303 EXPECT_FLOAT_EQ(2.0, particleDY(&p));
304 EXPECT_FLOAT_EQ(2.2568872, particleDZ(&p));
305 EXPECT_FLOAT_EQ(hypot(2.0, 1.026177), particleDRho(&p));
306 EXPECT_FLOAT_EQ(3.1853695, particleDistance(&p));
307 EXPECT_FLOAT_EQ(0.5, particlePvalue(&p));
308 }
309
310 {
311 Particle p2({ 0.1, -0.4, 0.8, 1.0 }, 11);
312 p2.setPValue(0.5);
313 p2.setVertex(XYZVector(1.0, 2.0, 2.0));
314
316 EXPECT_FLOAT_EQ(0.0, particleDX(&p));
317 EXPECT_FLOAT_EQ(0.0, particleDY(&p));
318 EXPECT_FLOAT_EQ(0.0, particleDZ(&p));
319 EXPECT_FLOAT_EQ(0.0, particleDRho(&p));
320 EXPECT_FLOAT_EQ(0.0, particleDistance(&p));
321 EXPECT_FLOAT_EQ(0.5, particlePvalue(&p));
322 }
323
324 /* Test with a distance between mother and daughter vertex. One
325 * has to calculate the result by hand to test the code....
326
327 {
328 Particle p2({ 0.0 , 1.0, 0.0, 1.0 }, 11);
329 p2.setPValue(0.5);
330 p2.setVertex(XYZVector(1.0, 0.0, 2.0));
331
332 UseReferenceFrame<RestFrame> dummy(&p2);
333 EXPECT_FLOAT_EQ(0.0, particleDX(&p));
334 EXPECT_FLOAT_EQ(2.0, particleDY(&p));
335 EXPECT_FLOAT_EQ(0.0, particleDZ(&p));
336 EXPECT_FLOAT_EQ(2.0, particleDRho(&p));
337 EXPECT_FLOAT_EQ(2.0, particleDistance(&p));
338 EXPECT_FLOAT_EQ(0.5, particlePvalue(&p));
339 }
340 */
341
342 }
343
344 TEST(TrackVariablesTest, Variable)
345 {
348 StoreArray<Track> myTracks;
349 StoreArray<V0> myV0s;
350 StoreArray<Particle> myParticles;
351 myResults.registerInDataStore();
352 myTracks.registerInDataStore();
353 myV0s.registerInDataStore();
354 myParticles.registerInDataStore();
356
357 TRandom3 generator;
358
359 const float pValue = 0.5;
360 const float bField = 1.5;
361 const int charge = 1;
362 TMatrixDSym cov6(6);
363
364 // Generate a random put orthogonal pair of vectors in the r-phi plane
365 ROOT::Math::Cartesian2D d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
366 ROOT::Math::Cartesian2D pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
367 d.SetXY(d.X(), -(d.X()*pt.X()) / pt.Y());
368
369 // Add a random z component
370 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
371 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
372
373 auto CDCValue = static_cast<unsigned long long int>(0x300000000000000);
374
375 myResults.appendNew(position, momentum, cov6, charge, Const::electron, pValue, bField, CDCValue, 16777215, 0);
376 Track mytrack;
378 Track* savedTrack = myTracks.appendNew(mytrack);
379
380 Particle* part = myParticles.appendNew(savedTrack, Const::ChargedStable(11));
381
382 const Manager::Var* vIsFromECL = Manager::Instance().getVariable("isFromECL");
383 const Manager::Var* vIsFromKLM = Manager::Instance().getVariable("isFromKLM");
384 const Manager::Var* vIsFromTrack = Manager::Instance().getVariable("isFromTrack");
385 const Manager::Var* vIsFromV0 = Manager::Instance().getVariable("isFromV0");
386
387 EXPECT_TRUE(std::get<bool>(vIsFromTrack->function(part)));
388 EXPECT_FALSE(std::get<bool>(vIsFromECL->function(part)));
389 EXPECT_FALSE(std::get<bool>(vIsFromKLM->function(part)));
390 EXPECT_FALSE(std::get<bool>(vIsFromV0->function(part)));
391 EXPECT_FLOAT_EQ(0.5, trackPValue(part));
392 EXPECT_FLOAT_EQ(position.Z(), trackZ0(part));
393 EXPECT_FLOAT_EQ(position.Rho(), trackD0(part));
394 EXPECT_FLOAT_EQ(3, trackNCDCHits(part));
395 EXPECT_FLOAT_EQ(24, trackNSVDHits(part));
396 EXPECT_FLOAT_EQ(12, trackNPXDHits(part));
397
398 //-----------------------------------------------------------------------
399 // now add another track and mock up a V0 and a V0-based particle
400 myResults.appendNew(position, momentum, cov6, charge * -1,
401 Const::electron, pValue, bField, CDCValue, 16777215, 0);
402 Track secondTrack;
404 Track* savedTrack2 = myTracks.appendNew(secondTrack);
405 myParticles.appendNew(savedTrack2, Const::ChargedStable(11));
406 myV0s.appendNew(V0(std::pair(savedTrack, myResults[0]), std::pair(savedTrack2, myResults[1]), 0.0, 0.0, 0.0));
407 const PxPyPzEVector v0Momentum(2 * momentum.X(), 2 * momentum.Y(), 2 * momentum.Z(), (momentum * 2).R());
408 auto v0particle = myParticles.appendNew(v0Momentum, 22,
409 Particle::c_Unflavored, Particle::c_V0, 0);
410 v0particle->appendDaughter(0, false);
411 v0particle->appendDaughter(1, false);
412 //-----------------------------------------------------------------------
413
414 EXPECT_FALSE(std::get<bool>(vIsFromTrack->function(v0particle)));
415 EXPECT_FALSE(std::get<bool>(vIsFromECL->function(v0particle)));
416 EXPECT_FALSE(std::get<bool>(vIsFromKLM->function(v0particle)));
417 EXPECT_TRUE(std::get<bool>(vIsFromV0->function(v0particle)));
418
419 const Manager::Var* vNDaughters = Manager::Instance().getVariable("nDaughters");
420 EXPECT_EQ(std::get<int>(vNDaughters->function(v0particle)), 2);
421 }
422
423 class MCTruthVariablesTest : public ::testing::Test {
424 protected:
425 virtual void SetUp()
426 {
427 // datastore things
430
431 // needed to mock up
432 StoreArray<ECLCluster> clusters;
433 StoreArray<MCParticle> mcparticles;
434 StoreArray<Track> tracks;
436 StoreArray<Particle> particles;
437
438 // register the arrays
439 clusters.registerInDataStore();
440 mcparticles.registerInDataStore();
441 tracks.registerInDataStore();
442 trackfits.registerInDataStore();
443 particles.registerInDataStore();
444
445 // register the relations for mock up mcmatching
446 clusters.registerRelationTo(mcparticles);
447 tracks.registerRelationTo(mcparticles);
448 particles.registerRelationTo(mcparticles);
449
450 // register the relation for mock up track <--> cluster matching
451 //clusters.registerRelationTo(tracks);
452 tracks.registerRelationTo(clusters);
453
454 // end datastore things
456
457 /* mock up an electron (track with a cluster AND a track-cluster match)
458 * and a photon (cluster, no track) and MCParticles for both
459 *
460 * this assumes that everything (tracking, clustering, track-cluster
461 * matching *and* mcmatching all worked)
462 *
463 * this can be extended to pions, kaons, etc but leave it simple for now
464 */
465
466 // create the true underlying mcparticles
467 auto* true_photon = mcparticles.appendNew(MCParticle());
468 true_photon->setPDG(Const::photon.getPDGCode());
469 auto* true_electron = mcparticles.appendNew(MCParticle());
470 true_electron->setPDG(Const::electron.getPDGCode());
471 auto* true_pion = mcparticles.appendNew(MCParticle());
472 true_pion->setPDG(-Const::pion.getPDGCode());
473
474 // create the reco clusters
475 auto* cl0 = clusters.appendNew(ECLCluster());
476 cl0->setEnergy(1.0);
477 cl0->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
478 cl0->setClusterId(0);
479
480 auto* cl1 = clusters.appendNew(ECLCluster());
481 cl1->setEnergy(0.5);
482 cl1->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
483 cl1->setClusterId(1);
484
485 // create a reco track (one has to also mock up a track fit result)
486 TMatrixDSym cov(6);
487 trackfits.appendNew(
488 ROOT::Math::XYZVector(), ROOT::Math::XYZVector(), cov, -1, Const::electron, 0.5, 1.5,
489 static_cast<unsigned long long int>(0x300000000000000), 16777215, 0);
490 auto* electron_tr = tracks.appendNew(Track());
491 electron_tr->setTrackFitResultIndex(Const::electron, 0);
492 electron_tr->addRelationTo(cl1); // a track <--> cluster match
493
494 TMatrixDSym cov1(6);
495 trackfits.appendNew(
496 ROOT::Math::XYZVector(), ROOT::Math::XYZVector(), cov1, -1, Const::pion, 0.51, 1.5,
497 static_cast<unsigned long long int>(0x300000000000000), 16777215, 0);
498 auto* pion_tr = tracks.appendNew(Track());
499 pion_tr->setTrackFitResultIndex(Const::pion, 0);
500 pion_tr->addRelationTo(cl1); // a track <--> cluster match
501
502 // now set mcmatch relations
503 cl0->addRelationTo(true_photon, 12.3);
504 cl0->addRelationTo(true_electron, 2.3);
505 cl1->addRelationTo(true_electron, 45.6);
506 cl1->addRelationTo(true_photon, 5.6);
507 cl1->addRelationTo(true_pion, 15.6);
508
509 electron_tr->addRelationTo(true_electron);
510 pion_tr->addRelationTo(true_pion);
511
512 // create belle2::Particles from the mdst objects
513 const auto* photon = particles.appendNew(Particle(cl0));
514 const auto* electron = particles.appendNew(Particle(electron_tr, Const::electron));
515 const auto* pion = particles.appendNew(Particle(pion_tr, Const::pion));
516 const auto* misid_photon = particles.appendNew(Particle(cl1));
517
518 // now set mcmatch relations
519 photon->addRelationTo(true_photon);
520 electron->addRelationTo(true_electron);
521 pion->addRelationTo(true_pion);
522 misid_photon->addRelationTo(true_electron); // assume MC matching caught this
523 }
524
525 virtual void TearDown()
526 {
528 }
529 };
530
531 TEST_F(MCTruthVariablesTest, mcCosThetaBetweenParticleAndNominalB)
532 {
535 StoreArray<MCParticle> mcParticles;
536 StoreArray<Particle> particles;
537 particles.registerInDataStore();
538 mcParticles.registerInDataStore();
539 particles.registerRelationTo(mcParticles);
541
542 // Create MC graph for B- -> (D0 -> K- e+ nu_e) pi-
543 MCParticleGraph mcGraph;
544
545 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
546 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
547 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
548 MCParticleGraph::GraphParticle& graphParticleGranddaughter1 = mcGraph.addParticle();
549 MCParticleGraph::GraphParticle& graphParticleGranddaughter2 = mcGraph.addParticle();
550 MCParticleGraph::GraphParticle& graphParticleGranddaughter3 = mcGraph.addParticle();
551
552 graphParticleDaughter1.comesFrom(graphParticleMother);
553 graphParticleDaughter2.comesFrom(graphParticleMother);
554 graphParticleGranddaughter1.comesFrom(graphParticleDaughter1);
555 graphParticleGranddaughter2.comesFrom(graphParticleDaughter1);
556 graphParticleGranddaughter3.comesFrom(graphParticleDaughter1);
557
558 graphParticleMother.setPDG(-521);
559 graphParticleDaughter1.setPDG(421);
560 graphParticleDaughter2.setPDG(-Const::pion.getPDGCode());
561 graphParticleGranddaughter1.setPDG(-Const::kaon.getPDGCode());
562 graphParticleGranddaughter2.setPDG(-Const::electron.getPDGCode());
563 graphParticleGranddaughter3.setPDG(12);
564
565 // Create the two 4-vectors that will factor into calculation, and set a mass that corresponds
566 // to the length of the 4-vector
568 graphParticleMother.set4Vector(T.rotateCmsToLab() * PxPyPzEVector(3.0, 4.0, 5.0, 18.0));
569 graphParticleGranddaughter3.set4Vector(T.rotateCmsToLab() * PxPyPzEVector(0.0, 0.0, 5.0, 5.0));
570 graphParticleMother.setMass(16.55294535724685);
571
572 // The following masses and momenta do not factor into the calculation, but we will set them non-zero
573 PxPyPzEVector dummyP4(1, 2, 1, 5);
574 double dummyM = 4.3589;
575 graphParticleDaughter1.set4Vector(dummyP4);
576 graphParticleDaughter1.setMass(dummyM);
577 graphParticleDaughter2.set4Vector(dummyP4);
578 graphParticleDaughter2.setMass(dummyM);
579 graphParticleGranddaughter1.set4Vector(dummyP4);
580 graphParticleGranddaughter1.setMass(dummyM);
581 graphParticleGranddaughter2.set4Vector(dummyP4);
582 graphParticleGranddaughter2.setMass(dummyM);
583
584 mcGraph.generateList();
585
586 // Create mockup particles and add relations to MC particles
587 auto* pMother = particles.appendNew(dummyP4, -521);
588 pMother->addRelationTo(mcParticles[0]);
589
590 particles.appendNew(dummyP4, 421)->addRelationTo(mcParticles[1]);
591 particles.appendNew(dummyP4, -211)->addRelationTo(mcParticles[2]);
592 particles.appendNew(dummyP4, -321)->addRelationTo(mcParticles[3]);
593 particles.appendNew(dummyP4, -11)->addRelationTo(mcParticles[4]);
594 particles.appendNew(dummyP4, 12)->addRelationTo(mcParticles[5]);
595
596 double E_B = T.getCMSEnergy() / 2.0;
597 double M_B = pMother->getPDGMass();
598 double p_B = std::sqrt(E_B * E_B - M_B * M_B);
599
600 PxPyPzEVector p4_Y_CMS = T.rotateLabToCms() * (graphParticleMother.get4Vector() - graphParticleGranddaughter3.get4Vector());
601 double E_Y = p4_Y_CMS.E(); // E_Mother - E_Granddaughter3
602 double p_Y = p4_Y_CMS.P(); // |p_Mother - p_Granddaughter3|
603 double M_Y = p4_Y_CMS.M(); // sqrt((p4_Mother - p4_Granddaughter3)^2)
604
605 double expectedCosBY = (2 * E_B * E_Y - M_B * M_B - M_Y * M_Y) / (2 * p_B * p_Y);
606
607 const auto* mcCosBY = Manager::Instance().getVariable("mcCosThetaBetweenParticleAndNominalB");
608
609 EXPECT_NEAR(std::get<double>(mcCosBY->function(pMother)), expectedCosBY, 1e-4);
610 }
611
612 TEST_F(MCTruthVariablesTest, ECLMCMatchWeightVariable)
613 {
614 StoreArray<Particle> particles{};
615 const auto* photon = particles[0];
616 const auto* electron = particles[1];
617 const auto* pion = particles[2];
618
619 const auto* weight = Manager::Instance().getVariable("clusterMCMatchWeight");
620 EXPECT_FLOAT_EQ(std::get<double>(weight->function(photon)), 12.3);
621 EXPECT_FLOAT_EQ(std::get<double>(weight->function(electron)), 45.6);
622 EXPECT_FLOAT_EQ(std::get<double>(weight->function(pion)), 15.6);
623 }
624
625 TEST_F(MCTruthVariablesTest, ECLBestMCMatchVariables)
626 {
627 StoreArray<Particle> particles{};
628 const auto* photon = particles[0];
629 const auto* electron = particles[1];
630 const auto* pion = particles[2];
631 const auto* misid_photon = particles[3];
632
633
634 const auto* pdgcode = Manager::Instance().getVariable("clusterBestMCPDG");
635 EXPECT_EQ(std::get<double>(pdgcode->function(photon)), Const::photon.getPDGCode());
636 EXPECT_EQ(std::get<double>(pdgcode->function(electron)), Const::electron.getPDGCode());
637 EXPECT_EQ(std::get<double>(pdgcode->function(pion)), Const::electron.getPDGCode());
638 EXPECT_EQ(std::get<double>(pdgcode->function(misid_photon)), Const::electron.getPDGCode());
639
640 const auto* weight = Manager::Instance().getVariable("clusterBestMCMatchWeight");
641 EXPECT_FLOAT_EQ(std::get<double>(weight->function(photon)), 12.3);
642 EXPECT_FLOAT_EQ(std::get<double>(weight->function(electron)), 45.6);
643 EXPECT_FLOAT_EQ(std::get<double>(weight->function(pion)), 45.6);
644 EXPECT_FLOAT_EQ(std::get<double>(weight->function(misid_photon)), 45.6);
645 }
646
647
648 class EventVariableTest : public ::testing::Test {
649 protected:
651 void SetUp() override
652 {
657
658 }
659
661 void TearDown() override
662 {
664 }
665 };
666
667 TEST_F(EventVariableTest, ExperimentRunEventDateAndTime)
668 {
669 const Manager::Var* exp = Manager::Instance().getVariable("expNum");
670 const Manager::Var* run = Manager::Instance().getVariable("runNum");
671 const Manager::Var* evt = Manager::Instance().getVariable("evtNum");
672 const Manager::Var* date = Manager::Instance().getVariable("date");
673 const Manager::Var* year = Manager::Instance().getVariable("year");
674 const Manager::Var* time = Manager::Instance().getVariable("eventTimeSeconds");
675
676 // there is no EventMetaData so expect nan
677 EXPECT_FALSE(std::get<double>(date->function(nullptr)) == std::get<double>(date->function(nullptr)));
678 EXPECT_FALSE(std::get<double>(year->function(nullptr)) == std::get<double>(year->function(nullptr)));
679 EXPECT_FALSE(std::get<double>(time->function(nullptr)) == std::get<double>(time->function(nullptr)));
680
682 StoreObjPtr<EventMetaData> evtMetaData;
683 evtMetaData.registerInDataStore();
685 evtMetaData.create();
686 evtMetaData->setExperiment(1337);
687 evtMetaData->setRun(12345);
688 evtMetaData->setEvent(54321);
689 evtMetaData->setTime(1288569600e9);
690 // 01/11/2010 is the date TDR was uploaded to arXiv ... experiment's birthday?
691
692
693 // -
694 EXPECT_EQ(std::get<int>(exp->function(nullptr)), 1337);
695 EXPECT_EQ(std::get<int>(run->function(nullptr)), 12345);
696 EXPECT_EQ(std::get<int>(evt->function(nullptr)), 54321);
697 EXPECT_FLOAT_EQ(std::get<double>(date->function(nullptr)), 20101101.);
698 EXPECT_FLOAT_EQ(std::get<double>(year->function(nullptr)), 2010.);
699 EXPECT_FLOAT_EQ(std::get<double>(time->function(nullptr)), 1288569600);
700 }
701
702 TEST_F(EventVariableTest, TestGlobalCounters)
703 {
704 StoreArray<MCParticle> mcParticles; // empty
705 const Manager::Var* var = Manager::Instance().getVariable("nMCParticles");
706 EXPECT_EQ(std::get<int>(var->function(nullptr)), 0);
707
708 for (unsigned i = 0; i < 10; ++i)
709 mcParticles.appendNew();
710
711 EXPECT_EQ(std::get<int>(var->function(nullptr)), 10);
712
713 // TODO: add other counters nTracks etc in here
714 }
715
716 TEST_F(EventVariableTest, TestIfContinuumEvent_ForContinuumEvent)
717 {
719 StoreArray<MCParticle> mcParticles;
720 StoreArray<Particle> particles;
721 particles.registerRelationTo(mcParticles);
723
724 auto* mcParticle = mcParticles.appendNew();
725 mcParticle->setPDG(Const::electron.getPDGCode());
726 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
727 auto* p1 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
728 p1->addRelationTo(mcParticle);
729
730 mcParticle = mcParticles.appendNew();
731 mcParticle->setPDG(-Const::electron.getPDGCode());
732 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
733 auto* p2 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
734 p2->addRelationTo(mcParticle);
735
736 const Manager::Var* var = Manager::Instance().getVariable("isContinuumEvent");
737 ASSERT_NE(var, nullptr);
738 EXPECT_TRUE(std::get<bool>(var->function(p1)));
739 EXPECT_TRUE(std::get<bool>(var->function(p2)));
740 const Manager::Var* varN = Manager::Instance().getVariable("isNotContinuumEvent");
741 ASSERT_NE(varN, nullptr);
742 EXPECT_FALSE(std::get<bool>(varN->function(p1)));
743 EXPECT_FALSE(std::get<bool>(varN->function(p2)));
744 }
745
746 TEST_F(EventVariableTest, TestIfContinuumEvent_ForUpsilon4SEvent)
747 {
749 StoreArray<MCParticle> mcParticles2;
750 StoreArray<Particle> particles2;
751 particles2.registerRelationTo(mcParticles2);
753
754 auto* mcParticle = mcParticles2.appendNew();
755 mcParticle->setPDG(Const::photon.getPDGCode());
756 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
757 auto* p3 = particles2.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
758 p3->addRelationTo(mcParticle);
759
760 mcParticle = mcParticles2.appendNew();
761 mcParticle->setPDG(300553);
762 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
763 auto* p4 = particles2.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 300553);
764 p4->addRelationTo(mcParticle);
765
766 const Manager::Var* var2 = Manager::Instance().getVariable("isContinuumEvent");
767 ASSERT_NE(var2, nullptr);
768 EXPECT_FALSE(std::get<bool>(var2->function(p3)));
769 EXPECT_FALSE(std::get<bool>(var2->function(p4)));
770 const Manager::Var* var2N = Manager::Instance().getVariable("isNotContinuumEvent");
771 ASSERT_NE(var2N, nullptr);
772 EXPECT_TRUE(std::get<bool>(var2N->function(p3)));
773 EXPECT_TRUE(std::get<bool>(var2N->function(p4)));
774 }
775
776 TEST_F(EventVariableTest, TestIfContinuumEvent_ForWrongReconstructedUpsilon4SEvent)
777 {
779 StoreArray<MCParticle> mcParticles3;
780 StoreArray<Particle> particles3;
781 particles3.registerRelationTo(mcParticles3);
783
784 auto* mcParticle = mcParticles3.appendNew();
785 mcParticle->setPDG(Const::photon.getPDGCode());
786 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
787 auto* p5 = particles3.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
788 p5->addRelationTo(mcParticle);
789
790 mcParticle = mcParticles3.appendNew();
791 mcParticle->setPDG(300553);
792 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
793 auto* p6 = particles3.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 15);
794 p6->addRelationTo(mcParticle);
795
796 const Manager::Var* var3 = Manager::Instance().getVariable("isContinuumEvent");
797 ASSERT_NE(var3, nullptr);
798 EXPECT_FALSE(std::get<bool>(var3->function(p5)));
799 EXPECT_FALSE(std::get<bool>(var3->function(p6)));
800 const Manager::Var* var3N = Manager::Instance().getVariable("isNotContinuumEvent");
801 ASSERT_NE(var3N, nullptr);
802 EXPECT_TRUE(std::get<bool>(var3N->function(p5)));
803 EXPECT_TRUE(std::get<bool>(var3N->function(p6)));
804 }
805
806
807 class MetaVariableTest : public ::testing::Test {
808 protected:
810 void SetUp() override
811 {
818 }
819
821 void TearDown() override
822 {
824 }
825 };
826
827 TEST_F(MetaVariableTest, countDaughters)
828 {
829 PxPyPzEVector momentum;
830 const int nDaughters = 6;
831 StoreArray<Particle> particles;
832 std::vector<int> daughterIndices;
833 for (int i = 0; i < nDaughters; i++) {
834 Particle d(PxPyPzEVector(1, 0, 0, 3.0), (i % 2) ? 211 : -211);
835 momentum += d.get4Vector();
836 Particle* newDaughters = particles.appendNew(d);
837 daughterIndices.push_back(newDaughters->getArrayIndex());
838 }
839 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
840
841 const Manager::Var* var = Manager::Instance().getVariable("countDaughters(charge > 0)");
842 ASSERT_NE(var, nullptr);
843 EXPECT_EQ(std::get<int>(var->function(p)), 3);
844
845 var = Manager::Instance().getVariable("countDaughters(abs(charge) > 0)");
846 ASSERT_NE(var, nullptr);
847 EXPECT_EQ(std::get<int>(var->function(p)), 6);
848
849 }
850
851 TEST_F(MetaVariableTest, useRestFrame)
852 {
853 Gearbox& gearbox = Gearbox::getInstance();
854 gearbox.setBackends({std::string("file:")});
855 gearbox.close();
856 gearbox.open("geometry/Belle2.xml", false);
857
858 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 411);
859 p.setVertex(XYZVector(1.0, 2.0, 2.0));
860
861 const Manager::Var* var = Manager::Instance().getVariable("p");
862 ASSERT_NE(var, nullptr);
863 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.9);
864
865 var = Manager::Instance().getVariable("E");
866 ASSERT_NE(var, nullptr);
867 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
868
869 var = Manager::Instance().getVariable("distance");
870 ASSERT_NE(var, nullptr);
871 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.0);
872
873 var = Manager::Instance().getVariable("useRestFrame(p)");
874 ASSERT_NE(var, nullptr);
875 EXPECT_NEAR(std::get<double>(var->function(&p)), 0.0, 1e-9);
876
877 var = Manager::Instance().getVariable("useRestFrame(E)");
878 ASSERT_NE(var, nullptr);
879 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.4358899);
880
881 var = Manager::Instance().getVariable("useRestFrame(distance)");
882 ASSERT_NE(var, nullptr);
883 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.0);
884 }
885
886 TEST_F(MetaVariableTest, useLabFrame)
887 {
888 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 411);
889 p.setVertex(XYZVector(1.0, 2.0, 2.0));
890
891 const Manager::Var* var = Manager::Instance().getVariable("p");
892 ASSERT_NE(var, nullptr);
893 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.9);
894
895 var = Manager::Instance().getVariable("E");
896 ASSERT_NE(var, nullptr);
897 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
898
899 var = Manager::Instance().getVariable("distance");
900 ASSERT_NE(var, nullptr);
901 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.0);
902
903 var = Manager::Instance().getVariable("useLabFrame(p)");
904 ASSERT_NE(var, nullptr);
905 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.9);
906
907 var = Manager::Instance().getVariable("useLabFrame(E)");
908 ASSERT_NE(var, nullptr);
909 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
910
911 var = Manager::Instance().getVariable("useLabFrame(distance)");
912 ASSERT_NE(var, nullptr);
913 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.0);
914 }
915
916 TEST_F(MetaVariableTest, useCMSFrame)
917 {
918 Gearbox& gearbox = Gearbox::getInstance();
919 gearbox.setBackends({std::string("file:")});
920 gearbox.close();
921 gearbox.open("geometry/Belle2.xml", false);
922
923 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 411);
924 p.setVertex(XYZVector(1.0, 2.0, 2.0));
925
926 const Manager::Var* var = Manager::Instance().getVariable("p");
927 ASSERT_NE(var, nullptr);
928 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.9);
929
930 var = Manager::Instance().getVariable("E");
931 ASSERT_NE(var, nullptr);
932 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
933
934 var = Manager::Instance().getVariable("distance");
935 ASSERT_NE(var, nullptr);
936 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.0);
937
938 var = Manager::Instance().getVariable("useCMSFrame(p)");
939 ASSERT_NE(var, nullptr);
940 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.68174650327489894064);
941
942 var = Manager::Instance().getVariable("useCMSFrame(E)");
943 ASSERT_NE(var, nullptr);
944 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.80918372124478121776);
945
946 var = Manager::Instance().getVariable("useCMSFrame(distance)");
947 ASSERT_NE(var, nullptr);
948 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.1853695);
949 }
950
951 TEST_F(MetaVariableTest, useTagSideRecoilRestFrame)
952 {
954 StoreArray<Particle> particles;
955 particles.registerInDataStore();
958 PxPyPzEVector vec0 = {0.0, 0.0, 0.0, T.getCMSEnergy()};
959 PxPyPzEVector vec1 = {0.0, +0.332174566, 0.0, T.getCMSEnergy() / 2.};
960 PxPyPzEVector vec2 = {0.0, -0.332174566, 0.0, T.getCMSEnergy() / 2.};
961 Particle* p0 = particles.appendNew(Particle(T.rotateCmsToLab() * vec0, 300553));
962 Particle* p1 = particles.appendNew(Particle(T.rotateCmsToLab() * vec1, 511, Particle::c_Unflavored, Particle::c_Undefined, 1));
963 Particle* p2 = particles.appendNew(Particle(T.rotateCmsToLab() * vec2, -511, Particle::c_Unflavored, Particle::c_Undefined, 2));
964
965 p0->appendDaughter(p1->getArrayIndex());
966 p0->appendDaughter(p2->getArrayIndex());
967
968 const Manager::Var* var = Manager::Instance().getVariable("useTagSideRecoilRestFrame(daughter(1, p), 0)");
969 ASSERT_NE(var, nullptr);
970 EXPECT_NEAR(std::get<double>(var->function(p0)), 0., 1e-6);
971
972 var = Manager::Instance().getVariable("useTagSideRecoilRestFrame(daughter(1, px), 0)");
973 ASSERT_NE(var, nullptr);
974 EXPECT_NEAR(std::get<double>(var->function(p0)), 0., 1e-6);
975
976 var = Manager::Instance().getVariable("useTagSideRecoilRestFrame(daughter(1, py), 0)");
977 ASSERT_NE(var, nullptr);
978 EXPECT_NEAR(std::get<double>(var->function(p0)), 0., 1e-6);
979
980 var = Manager::Instance().getVariable("useTagSideRecoilRestFrame(daughter(1, pz), 0)");
981 ASSERT_NE(var, nullptr);
982 EXPECT_NEAR(std::get<double>(var->function(p0)), 0., 1e-6);
983
984 var = Manager::Instance().getVariable("useTagSideRecoilRestFrame(daughter(1, E), 0)");
985 ASSERT_NE(var, nullptr);
986 EXPECT_NEAR(std::get<double>(var->function(p0)), p1->getMass(), 1e-6);
987 }
988
989
990 TEST_F(MetaVariableTest, extraInfo)
991 {
992 Particle p({ 0.1, -0.4, 0.8, 1.0 }, 11);
993 p.addExtraInfo("pi", 3.14);
994
995 const Manager::Var* var = Manager::Instance().getVariable("extraInfo(pi)");
996 ASSERT_NE(var, nullptr);
997 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 3.14);
998
999 // If nullptr is given, NaN is returned
1000 EXPECT_TRUE(std::isnan(std::get<double>(var->function(nullptr))));
1001 }
1002
1003 TEST_F(MetaVariableTest, eventExtraInfo)
1004 {
1005 StoreObjPtr<EventExtraInfo> eventExtraInfo;
1006 if (not eventExtraInfo.isValid())
1007 eventExtraInfo.create();
1008 eventExtraInfo->addExtraInfo("pi", 3.14);
1009 const Manager::Var* var = Manager::Instance().getVariable("eventExtraInfo(pi)");
1010 ASSERT_NE(var, nullptr);
1011 EXPECT_FLOAT_EQ(std::get<double>(var->function(nullptr)), 3.14);
1012 }
1013
1014 TEST_F(MetaVariableTest, eventCached)
1015 {
1016 const Manager::Var* var = Manager::Instance().getVariable("eventCached(constant(3.14))");
1017 ASSERT_NE(var, nullptr);
1018 EXPECT_FLOAT_EQ(std::get<double>(var->function(nullptr)), 3.14);
1019 StoreObjPtr<EventExtraInfo> eventExtraInfo;
1020 EXPECT_TRUE(eventExtraInfo.isValid());
1021 EXPECT_TRUE(eventExtraInfo->hasExtraInfo("__constant__bo3__pt14__bc"));
1022 EXPECT_FLOAT_EQ(eventExtraInfo->getExtraInfo("__constant__bo3__pt14__bc"), 3.14);
1023 eventExtraInfo->addExtraInfo("__eventExtraInfo__bopi__bc", 3.14);
1024 var = Manager::Instance().getVariable("eventCached(eventExtraInfo(pi))");
1025 ASSERT_NE(var, nullptr);
1026 EXPECT_FLOAT_EQ(std::get<double>(var->function(nullptr)), 3.14);
1027 }
1028
1029 TEST_F(MetaVariableTest, particleCached)
1030 {
1031 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 11);
1032 const Manager::Var* var = Manager::Instance().getVariable("particleCached(px)");
1033 ASSERT_NE(var, nullptr);
1034 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.1);
1035 EXPECT_TRUE(p.hasExtraInfo("__px"));
1036 EXPECT_FLOAT_EQ(p.getExtraInfo("__px"), 0.1);
1037 p.addExtraInfo("__py", -0.5); // NOT -0.4 because we want to see if the cache is used instead of py!
1038 var = Manager::Instance().getVariable("particleCached(py)");
1039 ASSERT_NE(var, nullptr);
1040 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -0.5);
1041 }
1042
1043 TEST_F(MetaVariableTest, basicMathTest)
1044 {
1045 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 411);
1046
1047 const Manager::Var* var = Manager::Instance().getVariable("abs(py)");
1048 ASSERT_NE(var, nullptr);
1049 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.4);
1050
1051 var = Manager::Instance().getVariable("min(E, pz)");
1052 ASSERT_NE(var, nullptr);
1053 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.8);
1054
1055 var = Manager::Instance().getVariable("max(E, pz)");
1056 ASSERT_NE(var, nullptr);
1057 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 2.0);
1058
1059 var = Manager::Instance().getVariable("log10(px)");
1060 ASSERT_NE(var, nullptr);
1061 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -1.0);
1062
1063 // sin 30 = 0.5
1064 var = Manager::Instance().getVariable("sin(0.5235987755983)");
1065 ASSERT_NE(var, nullptr);
1066 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.5);
1067
1068 // sin 90 = 1
1069 var = Manager::Instance().getVariable("sin(1.5707963267948966)");
1070 ASSERT_NE(var, nullptr);
1071 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
1072
1073 // asin 1 = 90
1074 var = Manager::Instance().getVariable("asin(1.0)");
1075 ASSERT_NE(var, nullptr);
1076 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.5707963267948966);
1077
1078 // cos 60 = 0.5
1079 var = Manager::Instance().getVariable("cos(1.0471975511965976)");
1080 ASSERT_NE(var, nullptr);
1081 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.5);
1082
1083 // acos 0 = 90
1084 var = Manager::Instance().getVariable("acos(0)");
1085 ASSERT_NE(var, nullptr);
1086 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.5707963267948966);
1087
1088 }
1089
1090 TEST_F(MetaVariableTest, formula)
1091 {
1092 // see also unit tests in framework/formula_parser.cc
1093 //
1094 // keep particle-based tests here, and operator precedence tests (etc) in
1095 // framework with the parser itself
1096
1097 Particle p({ 0.1, -0.4, 0.8, 2.0 }, -411);
1098
1099 const Manager::Var* var = Manager::Instance().getVariable("formula(px + py)");
1100 ASSERT_NE(var, nullptr);
1101 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -0.3);
1102
1103 var = Manager::Instance().getVariable("formula(px - py)");
1104 ASSERT_NE(var, nullptr);
1105 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.5);
1106
1107 var = Manager::Instance().getVariable("formula(px * py)");
1108 ASSERT_NE(var, nullptr);
1109 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -0.04);
1110
1111 var = Manager::Instance().getVariable("formula(py / px)");
1112 ASSERT_NE(var, nullptr);
1113 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -4.0);
1114
1115 var = Manager::Instance().getVariable("formula(px ^ E)");
1116 ASSERT_NE(var, nullptr);
1117 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.01);
1118
1119 var = Manager::Instance().getVariable("formula(px * py + pz)");
1120 ASSERT_NE(var, nullptr);
1121 EXPECT_NEAR(std::get<double>(var->function(&p)), 0.76, 1e-6);
1122
1123 var = Manager::Instance().getVariable("formula(pz + px * py)");
1124 ASSERT_NE(var, nullptr);
1125 EXPECT_NEAR(std::get<double>(var->function(&p)), 0.76, 1e-6);
1126
1127 var = Manager::Instance().getVariable("formula(pt)");
1128 ASSERT_NE(var, nullptr);
1129 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.41231057);
1130 double pt = std::get<double>(var->function(&p));
1131
1132 var = Manager::Instance().getVariable("formula((px**2 + py**2)**(1/2))");
1133 ASSERT_NE(var, nullptr);
1134 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), pt);
1135
1136 var = Manager::Instance().getVariable("formula(charge)");
1137 ASSERT_NE(var, nullptr);
1138 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -1.0);
1139
1140 var = Manager::Instance().getVariable("formula(charge**2)");
1141 ASSERT_NE(var, nullptr);
1142 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
1143
1144 var = Manager::Instance().getVariable("formula(charge^2)");
1145 ASSERT_NE(var, nullptr);
1146 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
1147
1148 var = Manager::Instance().getVariable("formula(PDG * charge)");
1149 ASSERT_NE(var, nullptr);
1150 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 411.0);
1151
1152 var = Manager::Instance().getVariable("formula(PDG**2 * charge)");
1153 ASSERT_NE(var, nullptr);
1154 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -168921.0);
1155
1156 var = Manager::Instance().getVariable("formula(10.58 - (px + py + pz - E)**2)");
1157 ASSERT_NE(var, nullptr);
1158 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 8.33);
1159
1160 var = Manager::Instance().getVariable("formula(-10.58 + (px + py + pz - E)**2)");
1161 ASSERT_NE(var, nullptr);
1162 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -8.33);
1163
1164 var = Manager::Instance().getVariable("formula(-1.0 * PDG)");
1165 ASSERT_NE(var, nullptr);
1166 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 411);
1167 }
1168
1169 TEST_F(MetaVariableTest, passesCut)
1170 {
1171 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 411);
1172 Particle p2({ 0.1, -0.4, 0.8, 4.0 }, 411);
1173
1174 const Manager::Var* var = Manager::Instance().getVariable("passesCut(E < 3)");
1175 ASSERT_NE(var, nullptr);
1176 EXPECT_TRUE(std::get<bool>(var->function(&p)));
1177 EXPECT_FALSE(std::get<bool>(var->function(&p2)));
1178 // EXPECT_TRUE(std::isnan(std::get<double>(var->function(nullptr)))); // Check that particle is present has been removed to allow change to bool as return type
1179
1180 }
1181
1182 TEST_F(MetaVariableTest, unmask)
1183 {
1185 StoreArray<MCParticle> mcParticles;
1186 StoreArray<Particle> particles;
1187 particles.registerInDataStore();
1188 mcParticles.registerInDataStore();
1189 particles.registerRelationTo(mcParticles);
1191
1192 // Create MC graph for B -> (muon -> electron + muon_neutrino) + anti_muon_neutrino
1193 MCParticleGraph mcGraph;
1194
1195 MCParticleGraph::GraphParticle& graphParticleGrandMother = mcGraph.addParticle();
1196
1197 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
1198 MCParticleGraph::GraphParticle& graphParticleAunt = mcGraph.addParticle();
1199
1200 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
1201 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
1202
1203 graphParticleGrandMother.setPDG(-521);
1204 graphParticleMother.setPDG(Const::muon.getPDGCode());
1205 graphParticleAunt.setPDG(-14);
1206 graphParticleDaughter1.setPDG(Const::electron.getPDGCode());
1207 graphParticleDaughter2.setPDG(14);
1208
1209 graphParticleMother.comesFrom(graphParticleGrandMother);
1210 graphParticleAunt.comesFrom(graphParticleGrandMother);
1211 graphParticleDaughter1.comesFrom(graphParticleMother);
1212 graphParticleDaughter2.comesFrom(graphParticleMother);
1213 mcGraph.generateList();
1214
1215
1216 // Get MC Particles from StoreArray
1217 auto* mcGrandMother = mcParticles[0];
1218 mcGrandMother->setStatus(MCParticle::c_PrimaryParticle);
1219
1220 auto* mcMother = mcParticles[1];
1221 mcMother->setStatus(MCParticle::c_PrimaryParticle);
1222
1223 auto* mcAunt = mcParticles[2];
1224 mcAunt->setStatus(MCParticle::c_PrimaryParticle);
1225
1226 auto* mcDaughter1 = mcParticles[3];
1227 mcDaughter1->setStatus(MCParticle::c_PrimaryParticle);
1228
1229 auto* mcDaughter2 = mcParticles[4];
1230 mcDaughter2->setStatus(MCParticle::c_PrimaryParticle);
1231
1232 auto* pGrandMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), -521);
1233 pGrandMother->addRelationTo(mcGrandMother);
1234
1235 auto* pMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 13);
1236 pMother->addRelationTo(mcMother);
1237
1238
1239 pMother->writeExtraInfo("mcErrors", 8);
1240 pGrandMother->writeExtraInfo("mcErrors", 8 | 16);
1241 const Manager::Var* var1 = Manager::Instance().getVariable("unmask(mcErrors, 8)");
1242 const Manager::Var* var2 = Manager::Instance().getVariable("unmask(mcErrors, 8, 16, 32, 64)");
1243 ASSERT_NE(var1, nullptr);
1244 EXPECT_FLOAT_EQ(std::get<double>(var1->function(pMother)), 0);
1245 EXPECT_FLOAT_EQ(std::get<double>(var1->function(pGrandMother)), 16);
1246 ASSERT_NE(var2, nullptr);
1247 EXPECT_FLOAT_EQ(std::get<double>(var2->function(pMother)), 0);
1248 EXPECT_FLOAT_EQ(std::get<double>(var2->function(pGrandMother)), 0);
1249
1250
1251 pMother->writeExtraInfo("mcErrors", 8 | 128);
1252 pGrandMother->writeExtraInfo("mcErrors", 8 | 16 | 512);
1253 ASSERT_NE(var1, nullptr);
1254 EXPECT_FLOAT_EQ(std::get<double>(var1->function(pMother)), 128);
1255 EXPECT_FLOAT_EQ(std::get<double>(var1->function(pGrandMother)), 16 | 512);
1256 ASSERT_NE(var2, nullptr);
1257 EXPECT_FLOAT_EQ(std::get<double>(var2->function(pMother)), 128);
1258 EXPECT_FLOAT_EQ(std::get<double>(var2->function(pGrandMother)), 512);
1259
1260 // unmask variable needs at least two arguments
1261 EXPECT_B2FATAL(Manager::Instance().getVariable("unmask(mcErrors)"));
1262
1263 // all but the first argument have to be integers
1264 EXPECT_B2FATAL(Manager::Instance().getVariable("unmask(mcErrors, NOTINT)"));
1265 }
1266
1267 TEST_F(MetaVariableTest, conditionalVariableSelector)
1268 {
1269 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 411);
1270
1271 const Manager::Var* var = Manager::Instance().getVariable("conditionalVariableSelector(E>1, px, py)");
1272 ASSERT_NE(var, nullptr);
1273 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.1);
1274
1275 var = Manager::Instance().getVariable("conditionalVariableSelector(E<1, px, py)");
1276 ASSERT_NE(var, nullptr);
1277 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), -0.4);
1278
1279 }
1280
1281 TEST_F(MetaVariableTest, nCleanedTracks)
1282 {
1284 StoreArray<TrackFitResult> track_fit_results;
1285 StoreArray<Track> tracks;
1286 track_fit_results.registerInDataStore();
1287 tracks.registerInDataStore();
1289
1290 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 11);
1291 Particle p2({ 0.1, -0.4, 0.8, 4.0 }, 11);
1292
1293 track_fit_results.appendNew(ROOT::Math::XYZVector(0.1, 0.1, 0.1), ROOT::Math::XYZVector(0.1, 0.0, 0.0),
1294 TMatrixDSym(6), 1, Const::pion, 0.01, 1.5, 0, 0, 0);
1295 track_fit_results.appendNew(ROOT::Math::XYZVector(0.1, 0.1, 0.1), ROOT::Math::XYZVector(0.15, 0.0, 0.0),
1296 TMatrixDSym(6), 1, Const::pion, 0.01, 1.5, 0, 0, 0);
1297 track_fit_results.appendNew(ROOT::Math::XYZVector(0.1, 0.1, 0.1), ROOT::Math::XYZVector(0.4, 0.0, 0.0),
1298 TMatrixDSym(6), 1, Const::pion, 0.01, 1.5, 0, 0, 0);
1299 track_fit_results.appendNew(ROOT::Math::XYZVector(0.1, 0.1, 0.1), ROOT::Math::XYZVector(0.6, 0.0, 0.0),
1300 TMatrixDSym(6), 1, Const::pion, 0.01, 1.5, 0, 0, 0);
1301
1302 tracks.appendNew()->setTrackFitResultIndex(Const::pion, 0);
1303 tracks.appendNew()->setTrackFitResultIndex(Const::pion, 1);
1304 tracks.appendNew()->setTrackFitResultIndex(Const::pion, 2);
1305 tracks.appendNew()->setTrackFitResultIndex(Const::pion, 3);
1306
1307 const Manager::Var* var1 = Manager::Instance().getVariable("nCleanedTracks(p > 0.5)");
1308 EXPECT_FLOAT_EQ(std::get<int>(var1->function(nullptr)), 1);
1309
1310 const Manager::Var* var2 = Manager::Instance().getVariable("nCleanedTracks(p > 0.2)");
1311 EXPECT_FLOAT_EQ(std::get<int>(var2->function(nullptr)), 2);
1312
1313 const Manager::Var* var3 = Manager::Instance().getVariable("nCleanedTracks()");
1314 EXPECT_FLOAT_EQ(std::get<int>(var3->function(nullptr)), 4);
1315
1316
1317 }
1318
1319 TEST_F(MetaVariableTest, NumberOfMCParticlesInEvent)
1320 {
1321 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 11);
1322 Particle p2({ 0.1, -0.4, 0.8, 4.0 }, 11);
1323
1324 StoreArray<MCParticle> mcParticles;
1325 auto* mcParticle = mcParticles.appendNew();
1326 mcParticle->setPDG(Const::electron.getPDGCode());
1327 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
1328 mcParticle = mcParticles.appendNew();
1329 mcParticle->setPDG(Const::photon.getPDGCode());
1330 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
1331 mcParticle = mcParticles.appendNew();
1332 mcParticle->setPDG(-Const::electron.getPDGCode());
1333 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
1334 mcParticle = mcParticles.appendNew();
1335 mcParticle->setPDG(Const::electron.getPDGCode());
1336
1337
1338 const Manager::Var* var = Manager::Instance().getVariable("NumberOfMCParticlesInEvent(11)");
1339 ASSERT_NE(var, nullptr);
1340 EXPECT_EQ(std::get<int>(var->function(nullptr)), 2);
1341
1342 }
1343
1344 TEST_F(MetaVariableTest, daughterInvM)
1345 {
1346 PxPyPzEVector momentum;
1347 const int nDaughters = 6;
1348 StoreArray<Particle> particles;
1349 std::vector<int> daughterIndices;
1350 for (int i = 0; i < nDaughters; i++) {
1351 Particle d(PxPyPzEVector(2, 2, 2, 4.0), (i % 2) ? 213 : -213);
1352 momentum += d.get4Vector();
1353 Particle* newDaughters = particles.appendNew(d);
1354 daughterIndices.push_back(newDaughters->getArrayIndex());
1355 }
1356 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1357
1358 const Manager::Var* var = Manager::Instance().getVariable("daughterInvM(6,5)");
1359 ASSERT_NE(var, nullptr);
1360 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
1361
1362 var = Manager::Instance().getVariable("daughterInvM(0, 1)");
1363 ASSERT_NE(var, nullptr);
1364 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 4.0);
1365
1366 var = Manager::Instance().getVariable("daughterInvM(0, 1, 2)");
1367 ASSERT_NE(var, nullptr);
1368 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 6.0);
1369 }
1370
1371 TEST_F(MetaVariableTest, daughter)
1372 {
1373 PxPyPzEVector momentum;
1374 const int nDaughters = 6;
1375 StoreArray<Particle> particles;
1376 std::vector<int> daughterIndices;
1377 for (int i = 0; i < nDaughters; i++) {
1378 Particle d(PxPyPzEVector(i * 1.0, 1, 1, 1), (i % 2) ? 211 : -211);
1379 momentum += d.get4Vector();
1380 Particle* newDaughters = particles.appendNew(d);
1381 daughterIndices.push_back(newDaughters->getArrayIndex());
1382 }
1383 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1384
1385 const Manager::Var* var = Manager::Instance().getVariable("daughter(6, px)");
1386 ASSERT_NE(var, nullptr);
1387 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
1388
1389 var = Manager::Instance().getVariable("daughter(0, px)");
1390 ASSERT_NE(var, nullptr);
1391 EXPECT_NEAR(std::get<double>(var->function(p)), 0.0, 1e-6);
1392
1393 var = Manager::Instance().getVariable("daughter(1, px)");
1394 ASSERT_NE(var, nullptr);
1395 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 1.0);
1396
1397 var = Manager::Instance().getVariable("daughter(2, px)");
1398 ASSERT_NE(var, nullptr);
1399 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 2.0);
1400 }
1401
1402 TEST_F(MetaVariableTest, mcDaughter)
1403 {
1405 StoreArray<MCParticle> mcParticles;
1406 StoreArray<Particle> particles;
1407 particles.registerInDataStore();
1408 mcParticles.registerInDataStore();
1409 particles.registerRelationTo(mcParticles);
1411
1412 // Create MC graph for B -> (muon -> electron + muon_neutrino) + anti_muon_neutrino
1413 MCParticleGraph mcGraph;
1414
1415 MCParticleGraph::GraphParticle& graphParticleGrandMother = mcGraph.addParticle();
1416
1417 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
1418 MCParticleGraph::GraphParticle& graphParticleAunt = mcGraph.addParticle();
1419
1420 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
1421 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
1422
1423 graphParticleGrandMother.setPDG(-521);
1424 graphParticleMother.setPDG(Const::muon.getPDGCode());
1425 graphParticleAunt.setPDG(-14);
1426 graphParticleDaughter1.setPDG(Const::electron.getPDGCode());
1427 graphParticleDaughter2.setPDG(14);
1428
1429 graphParticleMother.comesFrom(graphParticleGrandMother);
1430 graphParticleAunt.comesFrom(graphParticleGrandMother);
1431 graphParticleDaughter1.comesFrom(graphParticleMother);
1432 graphParticleDaughter2.comesFrom(graphParticleMother);
1433 mcGraph.generateList();
1434
1435 // Get MC Particles from StoreArray
1436 auto* mcGrandMother = mcParticles[0];
1437 mcGrandMother->setStatus(MCParticle::c_PrimaryParticle);
1438
1439 auto* mcMother = mcParticles[1];
1440 mcMother->setStatus(MCParticle::c_PrimaryParticle);
1441
1442 auto* mcAunt = mcParticles[2];
1443 mcAunt->setStatus(MCParticle::c_PrimaryParticle);
1444
1445 auto* mcDaughter1 = mcParticles[3];
1446 mcDaughter1->setStatus(MCParticle::c_PrimaryParticle);
1447
1448 auto* mcDaughter2 = mcParticles[4];
1449 mcDaughter2->setStatus(MCParticle::c_PrimaryParticle);
1450
1451 auto* pGrandMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), -521);
1452 pGrandMother->addRelationTo(mcGrandMother);
1453
1454 auto* pMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 13);
1455 pMother->addRelationTo(mcMother);
1456
1457 // Test for particle that has no MC match
1458 auto* p_noMC = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 13);
1459
1460 // Test for particle that has MC match, but MC match has no daughter
1461 auto* p_noDaughter = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1462 p_noDaughter->addRelationTo(mcDaughter1);
1463
1464 const Manager::Var* var = Manager::Instance().getVariable("mcDaughter(0, PDG)");
1465 ASSERT_NE(var, nullptr);
1466 EXPECT_FLOAT_EQ(std::get<double>(var->function(pGrandMother)), 13);
1467 EXPECT_FLOAT_EQ(std::get<double>(var->function(pMother)), 11);
1468 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p_noMC))));
1469 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p_noDaughter))));
1470 var = Manager::Instance().getVariable("mcDaughter(1, PDG)");
1471 EXPECT_FLOAT_EQ(std::get<double>(var->function(pGrandMother)), -14);
1472 EXPECT_FLOAT_EQ(std::get<double>(var->function(pMother)), 14);
1473 // Test for particle where mc daughter index is out of range of mc daughters
1474 var = Manager::Instance().getVariable("mcDaughter(2, PDG)");
1475 EXPECT_TRUE(std::isnan(std::get<double>(var->function(pGrandMother))));
1476 EXPECT_TRUE(std::isnan(std::get<double>(var->function(pMother))));
1477 // Test nested application of mcDaughter
1478 var = Manager::Instance().getVariable("mcDaughter(0, mcDaughter(0, PDG))");
1479 EXPECT_FLOAT_EQ(std::get<double>(var->function(pGrandMother)), 11);
1480 EXPECT_TRUE(std::isnan(std::get<double>(var->function(pMother))));
1481 var = Manager::Instance().getVariable("mcDaughter(0, mcDaughter(1, PDG))");
1482 EXPECT_FLOAT_EQ(std::get<double>(var->function(pGrandMother)), 14);
1483 var = Manager::Instance().getVariable("mcDaughter(0, mcDaughter(2, PDG))");
1484 EXPECT_TRUE(std::isnan(std::get<double>(var->function(pGrandMother))));
1485 var = Manager::Instance().getVariable("mcDaughter(1, mcDaughter(0, PDG))");
1486 EXPECT_TRUE(std::isnan(std::get<double>(var->function(pGrandMother))));
1487 }
1488
1489 TEST_F(MetaVariableTest, mcMother)
1490 {
1492 StoreArray<MCParticle> mcParticles;
1493 StoreArray<Particle> particles;
1494 particles.registerInDataStore();
1495 mcParticles.registerInDataStore();
1496 particles.registerRelationTo(mcParticles);
1498
1499 // Create MC graph for B -> (muon -> electron + muon_neutrino) + anti_muon_neutrino
1500 MCParticleGraph mcGraph;
1501
1502 MCParticleGraph::GraphParticle& graphParticleGrandMother = mcGraph.addParticle();
1503
1504 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
1505 MCParticleGraph::GraphParticle& graphParticleAunt = mcGraph.addParticle();
1506
1507 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
1508 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
1509
1510 graphParticleGrandMother.setPDG(-521);
1511 graphParticleMother.setPDG(Const::muon.getPDGCode());
1512 graphParticleAunt.setPDG(-14);
1513 graphParticleDaughter1.setPDG(Const::electron.getPDGCode());
1514 graphParticleDaughter2.setPDG(14);
1515
1516 graphParticleMother.comesFrom(graphParticleGrandMother);
1517 graphParticleAunt.comesFrom(graphParticleGrandMother);
1518 graphParticleDaughter1.comesFrom(graphParticleMother);
1519 graphParticleDaughter2.comesFrom(graphParticleMother);
1520
1521 mcGraph.generateList();
1522
1523 // Get MC Particles from StoreArray
1524 auto* mcGrandMother = mcParticles[0];
1525 mcGrandMother->setStatus(MCParticle::c_PrimaryParticle);
1526
1527 auto* mcMother = mcParticles[1];
1528 mcMother->setStatus(MCParticle::c_PrimaryParticle);
1529
1530 auto* mcAunt = mcParticles[2];
1531 mcAunt->setStatus(MCParticle::c_PrimaryParticle);
1532
1533 auto* mcDaughter1 = mcParticles[3];
1534 mcDaughter1->setStatus(MCParticle::c_PrimaryParticle);
1535
1536 auto* mcDaughter2 = mcParticles[4];
1537 mcDaughter2->setStatus(MCParticle::c_PrimaryParticle);
1538
1539 auto* p1 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1540 p1->addRelationTo(mcDaughter1);
1541
1542 auto* p2 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 14);
1543 p2->addRelationTo(mcDaughter2);
1544
1545 auto* pMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 13);
1546 pMother->addRelationTo(mcMother);
1547
1548 // For test of particle that has no MC match
1549 auto* p_noMC = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1550
1551 // For test of particle that has MC match, but MC match has no mother
1552 auto* p_noMother = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), -521);
1553 p_noMother->addRelationTo(mcGrandMother);
1554
1555 const Manager::Var* var = Manager::Instance().getVariable("mcMother(PDG)");
1556 ASSERT_NE(var, nullptr);
1557 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 13);
1558 EXPECT_FLOAT_EQ(std::get<double>(var->function(p2)), 13);
1559 EXPECT_FLOAT_EQ(std::get<double>(var->function(pMother)), -521);
1560 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p_noMC))));
1561 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p_noMother))));
1562
1563 // Test if nested calls of mcMother work correctly
1564 var = Manager::Instance().getVariable("mcMother(mcMother(PDG))");
1565 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -521);
1566 }
1567
1568 TEST_F(MetaVariableTest, genParticle)
1569 {
1571 StoreArray<MCParticle> mcParticles;
1572 StoreArray<Particle> particles;
1573 particles.registerInDataStore();
1574 mcParticles.registerInDataStore();
1575 particles.registerRelationTo(mcParticles);
1577
1578 // Create MC graph for Upsilon(4S) -> (B^- -> electron + anti_electron_neutrino) + B^+
1579 MCParticleGraph mcGraph;
1580
1581 MCParticleGraph::GraphParticle& graphParticleGrandMother = mcGraph.addParticle();
1582
1583 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
1584 MCParticleGraph::GraphParticle& graphParticleAunt = mcGraph.addParticle();
1585
1586 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
1587 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
1588
1589 graphParticleGrandMother.setPDG(300553);
1590 graphParticleMother.setPDG(-521);
1591 graphParticleAunt.setPDG(521);
1592 graphParticleDaughter1.setPDG(Const::electron.getPDGCode());
1593 graphParticleDaughter2.setPDG(-12);
1594
1595 graphParticleGrandMother.setMomentum(0.0, 0.0, 0.4);
1596 graphParticleMother.setMomentum(1.1, 1.3, 1.5);
1597
1598 graphParticleMother.comesFrom(graphParticleGrandMother);
1599 graphParticleAunt.comesFrom(graphParticleGrandMother);
1600 graphParticleDaughter1.comesFrom(graphParticleMother);
1601 graphParticleDaughter2.comesFrom(graphParticleMother);
1602
1603 mcGraph.generateList();
1604
1605 // Get MC Particles from StoreArray
1606 auto* mcGrandMother = mcParticles[0];
1607 mcGrandMother->setStatus(MCParticle::c_PrimaryParticle);
1608
1609 auto* mcMother = mcParticles[1];
1610 mcMother->setStatus(MCParticle::c_PrimaryParticle);
1611
1612 auto* mcAunt = mcParticles[2];
1613 mcAunt->setStatus(MCParticle::c_PrimaryParticle);
1614
1615 auto* mcDaughter1 = mcParticles[3];
1616 mcDaughter1->setStatus(MCParticle::c_PrimaryParticle);
1617
1618 auto* mcDaughter2 = mcParticles[4];
1619 mcDaughter2->setStatus(MCParticle::c_PrimaryParticle);
1620
1621 auto* p1 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1622 p1->addRelationTo(mcDaughter1);
1623
1624 // For test of particle that has no MC match
1625 auto* p_noMC = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 211);
1626
1627 const Manager::Var* var = Manager::Instance().getVariable("genParticle(0, PDG)");
1628 ASSERT_NE(var, nullptr);
1629 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 300553);
1630 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 300553);
1631
1632 var = Manager::Instance().getVariable("genParticle(0, matchedMC(pz))");
1633 ASSERT_NE(var, nullptr);
1634 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 0.4);
1635 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 0.4);
1636
1637 var = Manager::Instance().getVariable("genParticle(0, mcDaughter(0, PDG))");
1638 ASSERT_NE(var, nullptr);
1639 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -521);
1640 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), -521);
1641
1642 var = Manager::Instance().getVariable("genParticle(0, mcDaughter(0, matchedMC(px)))");
1643 ASSERT_NE(var, nullptr);
1644 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 1.1);
1645 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 1.1);
1646
1647 var = Manager::Instance().getVariable("genParticle(1, PDG)");
1648 ASSERT_NE(var, nullptr);
1649 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -521);
1650 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), -521);
1651
1652 var = Manager::Instance().getVariable("genParticle(4, PDG)");
1653 ASSERT_NE(var, nullptr);
1654 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -12);
1655 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), -12);
1656
1657 var = Manager::Instance().getVariable("genParticle(5, PDG)");
1658 ASSERT_NE(var, nullptr);
1659 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p1))));
1660 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p_noMC))));
1661 }
1662
1663 TEST_F(MetaVariableTest, genUpsilon4S)
1664 {
1666 StoreArray<MCParticle> mcParticles;
1667 StoreArray<Particle> particles;
1668 particles.registerInDataStore();
1669 mcParticles.registerInDataStore();
1670 particles.registerRelationTo(mcParticles);
1672
1673 // Create MC graph for Upsilon(4S) -> (B^- -> electron + anti_electron_neutrino) + B^+
1674 MCParticleGraph mcGraph;
1675
1676 MCParticleGraph::GraphParticle& graphParticleGrandMother = mcGraph.addParticle();
1677
1678 MCParticleGraph::GraphParticle& graphParticleMother = mcGraph.addParticle();
1679 MCParticleGraph::GraphParticle& graphParticleAunt = mcGraph.addParticle();
1680
1681 MCParticleGraph::GraphParticle& graphParticleDaughter1 = mcGraph.addParticle();
1682 MCParticleGraph::GraphParticle& graphParticleDaughter2 = mcGraph.addParticle();
1683
1684 graphParticleGrandMother.setPDG(300553);
1685 graphParticleMother.setPDG(-521);
1686 graphParticleAunt.setPDG(521);
1687 graphParticleDaughter1.setPDG(Const::electron.getPDGCode());
1688 graphParticleDaughter2.setPDG(-12);
1689
1690 graphParticleGrandMother.setMomentum(0.0, 0.0, 0.4);
1691 graphParticleMother.setMomentum(1.1, 1.3, 1.5);
1692
1693 graphParticleMother.comesFrom(graphParticleGrandMother);
1694 graphParticleAunt.comesFrom(graphParticleGrandMother);
1695 graphParticleDaughter1.comesFrom(graphParticleMother);
1696 graphParticleDaughter2.comesFrom(graphParticleMother);
1697
1698 mcGraph.generateList();
1699
1700 // Get MC Particles from StoreArray
1701 auto* mcGrandMother = mcParticles[0];
1702 mcGrandMother->setStatus(MCParticle::c_PrimaryParticle);
1703
1704 auto* mcMother = mcParticles[1];
1705 mcMother->setStatus(MCParticle::c_PrimaryParticle);
1706
1707 auto* mcAunt = mcParticles[2];
1708 mcAunt->setStatus(MCParticle::c_PrimaryParticle);
1709
1710 auto* mcDaughter1 = mcParticles[3];
1711 mcDaughter1->setStatus(MCParticle::c_PrimaryParticle);
1712
1713 auto* mcDaughter2 = mcParticles[4];
1714 mcDaughter2->setStatus(MCParticle::c_PrimaryParticle);
1715
1716 auto* p1 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1717 p1->addRelationTo(mcDaughter1);
1718
1719 // For test of particle that has no MC match
1720 auto* p_noMC = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 211);
1721
1722 const Manager::Var* var = Manager::Instance().getVariable("genUpsilon4S(PDG)");
1723 ASSERT_NE(var, nullptr);
1724 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 300553);
1725 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 300553);
1726
1727 var = Manager::Instance().getVariable("genUpsilon4S(matchedMC(pz))");
1728 ASSERT_NE(var, nullptr);
1729 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 0.4);
1730 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 0.4);
1731
1732 var = Manager::Instance().getVariable("genUpsilon4S(mcDaughter(0, PDG))");
1733 ASSERT_NE(var, nullptr);
1734 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -521);
1735 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), -521);
1736
1737 var = Manager::Instance().getVariable("genUpsilon4S(mcDaughter(0, matchedMC(px)))");
1738 ASSERT_NE(var, nullptr);
1739 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), 1.1);
1740 EXPECT_FLOAT_EQ(std::get<double>(var->function(p_noMC)), 1.1);
1741
1743 mcParticles.clear();
1744 particles.clear();
1745 MCParticleGraph mcGraph2;
1746
1747 MCParticleGraph::GraphParticle& graphParticle1 = mcGraph2.addParticle();
1748 MCParticleGraph::GraphParticle& graphParticle2 = mcGraph2.addParticle();
1749
1750 graphParticle1.setPDG(Const::electron.getPDGCode());
1751 graphParticle2.setPDG(-Const::electron.getPDGCode());
1752
1753 graphParticle1.setMomentum(1.1, 1.3, 1.4);
1754 graphParticle1.setMomentum(-1.1, -1.3, 1.4);
1755
1756 mcGraph2.generateList();
1757
1758 auto* mcP1 = mcParticles[0];
1759 mcP1->setStatus(MCParticle::c_PrimaryParticle);
1760
1761 auto* mcP2 = mcParticles[1];
1762 mcP2->setStatus(MCParticle::c_PrimaryParticle);
1763
1764 auto* someParticle = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
1765 someParticle->addRelationTo(mcP1);
1766
1767 var = Manager::Instance().getVariable("genUpsilon4S(PDG)");
1768 ASSERT_NE(var, nullptr);
1769 EXPECT_TRUE(std::isnan(std::get<double>(var->function(someParticle))));
1770 }
1771
1772 TEST_F(MetaVariableTest, daughterProductOf)
1773 {
1774 PxPyPzEVector momentum;
1775 const int nDaughters = 4;
1776 StoreArray<Particle> particles;
1777 std::vector<int> daughterIndices;
1778 for (int i = 0; i < nDaughters; i++) {
1779 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 2.0), (i % 2) ? 213 : -213);
1780 momentum += d.get4Vector();
1781 Particle* newDaughters = particles.appendNew(d);
1782 daughterIndices.push_back(newDaughters->getArrayIndex());
1783 }
1784 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1785
1786 const Manager::Var* var = Manager::Instance().getVariable("daughterProductOf(E)");
1787 ASSERT_NE(var, nullptr);
1788 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 120.0);
1789 }
1790
1791 TEST_F(MetaVariableTest, daughterSumOf)
1792 {
1793 PxPyPzEVector momentum;
1794 const int nDaughters = 4;
1795 StoreArray<Particle> particles;
1796 std::vector<int> daughterIndices;
1797 for (int i = 0; i < nDaughters; i++) {
1798 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 2.0), (i % 2) ? 213 : -213);
1799 momentum += d.get4Vector();
1800 Particle* newDaughters = particles.appendNew(d);
1801 daughterIndices.push_back(newDaughters->getArrayIndex());
1802 }
1803 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1804
1805 const Manager::Var* var = Manager::Instance().getVariable("daughterSumOf(E)");
1806 ASSERT_NE(var, nullptr);
1807 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 14.0);
1808 }
1809
1810 TEST_F(MetaVariableTest, daughterLowest)
1811 {
1812 PxPyPzEVector momentum;
1813 const int nDaughters = 4;
1814 StoreArray<Particle> particles;
1815 std::vector<int> daughterIndices;
1816 for (int i = 0; i < nDaughters; i++) {
1817 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 2.0), (i % 2) ? 213 : -213);
1818 momentum += d.get4Vector();
1819 Particle* newDaughters = particles.appendNew(d);
1820 daughterIndices.push_back(newDaughters->getArrayIndex());
1821 }
1822 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1823
1824 const Manager::Var* var = Manager::Instance().getVariable("daughterLowest(E)");
1825 ASSERT_NE(var, nullptr);
1826 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 2.0);
1827 }
1828
1829 TEST_F(MetaVariableTest, daughterHighest)
1830 {
1831 PxPyPzEVector momentum;
1832 const int nDaughters = 4;
1833 StoreArray<Particle> particles;
1834 std::vector<int> daughterIndices;
1835 for (int i = 0; i < nDaughters; i++) {
1836 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 1.0), (i % 2) ? 213 : -213);
1837 momentum += d.get4Vector();
1838 Particle* newDaughters = particles.appendNew(d);
1839 daughterIndices.push_back(newDaughters->getArrayIndex());
1840 }
1841 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1842
1843 const Manager::Var* var = Manager::Instance().getVariable("daughterHighest(E)");
1844 ASSERT_NE(var, nullptr);
1845 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 4.0);
1846 }
1847
1848 TEST_F(MetaVariableTest, daughterDiffOf)
1849 {
1850 PxPyPzEVector momentum;
1851 const int nDaughters = 4;
1852 StoreArray<Particle> particles;
1853 std::vector<int> daughterIndices;
1854 for (int i = 0; i < nDaughters; i++) {
1855 Particle d(PxPyPzEVector(-1, 1.0 - 2 * (i % 2), 1, i * 1.0 + 2.0), (i % 2) ? -11 : 211);
1856 momentum += d.get4Vector();
1857 Particle* newDaughters = particles.appendNew(d);
1858 daughterIndices.push_back(newDaughters->getArrayIndex());
1859 }
1860 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1861
1862 const Manager::Var* var = Manager::Instance().getVariable("daughterDiffOf(0, 1, PDG)");
1863 ASSERT_NE(var, nullptr);
1864 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -222);
1865
1866 var = Manager::Instance().getVariable("daughterDiffOf(1, 0, PDG)");
1867 ASSERT_NE(var, nullptr);
1868 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 222);
1869
1870 var = Manager::Instance().getVariable("daughterDiffOf(0, 1, abs(PDG))");
1871 ASSERT_NE(var, nullptr);
1872 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -200);
1873
1874 var = Manager::Instance().getVariable("daughterDiffOf(1, 1, PDG)");
1875 ASSERT_NE(var, nullptr);
1876 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1877
1878 var = Manager::Instance().getVariable("daughterDiffOf(1, 3, abs(PDG))");
1879 ASSERT_NE(var, nullptr);
1880 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1881
1882 var = Manager::Instance().getVariable("daughterDiffOf(0, 2, PDG)");
1883 ASSERT_NE(var, nullptr);
1884 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1885
1886 var = Manager::Instance().getVariable("daughterDiffOf(1, 0, phi)");
1887 ASSERT_NE(var, nullptr);
1888 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -1.5707964);
1889
1890 var = Manager::Instance().getVariable("daughterDiffOf(1, 0, useCMSFrame(phi))");
1891 ASSERT_NE(var, nullptr);
1892 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -1.5004894);
1893
1894 var = Manager::Instance().getVariable("daughterDiffOf(0, NOTINT, PDG)");
1895 ASSERT_NE(var, nullptr);
1896 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
1897 }
1898
1899
1900 TEST_F(MetaVariableTest, mcDaughterDiffOf)
1901 {
1903 PxPyPzEVector momentum;
1904 const int nDaughters = 4;
1905 StoreArray<Particle> particles;
1906 StoreArray<MCParticle> mcParticles;
1907 particles.registerRelationTo(mcParticles);
1908 std::vector<int> daughterIndices;
1910
1911 for (int i = 0; i < nDaughters; i++) {
1912 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 1.0), (i % 2) ? -11 : 211);
1913 momentum += d.get4Vector();
1914 Particle* newDaughters = particles.appendNew(d);
1915 daughterIndices.push_back(newDaughters->getArrayIndex());
1916 auto* mcParticle = mcParticles.appendNew();
1917 mcParticle->setPDG((i % 2) ? -Const::electron.getPDGCode() : Const::pion.getPDGCode());
1918 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
1919 newDaughters->addRelationTo(mcParticle);
1920 }
1921 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
1922
1923 const Manager::Var* var = Manager::Instance().getVariable("mcDaughterDiffOf(0, 1, PDG)");
1924 ASSERT_NE(var, nullptr);
1925 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -222);
1926
1927 var = Manager::Instance().getVariable("mcDaughterDiffOf(1, 0, PDG)");
1928 ASSERT_NE(var, nullptr);
1929 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 222);
1930
1931 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, 1, abs(PDG))");
1932 ASSERT_NE(var, nullptr);
1933 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -200);
1934
1935 var = Manager::Instance().getVariable("mcDaughterDiffOf(1, 1, PDG)");
1936 ASSERT_NE(var, nullptr);
1937 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1938
1939 var = Manager::Instance().getVariable("mcDaughterDiffOf(1, 3, abs(PDG))");
1940 ASSERT_NE(var, nullptr);
1941 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1942
1943 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, 2, PDG)");
1944 ASSERT_NE(var, nullptr);
1945 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
1946
1947 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, NOTINT, PDG)");
1948 ASSERT_NE(var, nullptr);
1949 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
1950 }
1951
1952
1953
1954 TEST_F(MetaVariableTest, daughterClusterAngleInBetween)
1955 {
1956 // declare all the array we need
1957 StoreArray<Particle> particles;
1958 std::vector<int> daughterIndices, daughterIndices_noclst;
1959
1960 //proxy initialize where to declare the needed array
1962 StoreArray<ECLCluster> eclclusters;
1963 eclclusters.registerInDataStore();
1964 particles.registerRelationTo(eclclusters);
1966
1967 // create two Lorentz vectors that are back to back in the CMS and boost them to the Lab frame
1968 const float px_CM = 2.;
1969 const float py_CM = 1.;
1970 const float pz_CM = 3.;
1971 float E_CM;
1972 E_CM = sqrt(pow(px_CM, 2) + pow(py_CM, 2) + pow(pz_CM, 2));
1973 PxPyPzEVector momentum, momentum_noclst;
1974 PxPyPzEVector dau0_4vec_CM(px_CM, py_CM, pz_CM, E_CM), dau1_4vec_CM(-px_CM, -py_CM, -pz_CM, E_CM);
1975 PxPyPzEVector dau0_4vec_Lab, dau1_4vec_Lab;
1976 dau0_4vec_Lab = PCmsLabTransform::cmsToLab(
1977 dau0_4vec_CM); //why is everybody using the extended method when there are the functions that do all the steps for us?
1978 dau1_4vec_Lab = PCmsLabTransform::cmsToLab(dau1_4vec_CM);
1979
1980 // add the two photons (now in the Lab frame) as the two daughters of some particle and create the latter
1981 Particle dau0_noclst(dau0_4vec_Lab, 22);
1982 momentum += dau0_noclst.get4Vector();
1983 Particle* newDaughter0_noclst = particles.appendNew(dau0_noclst);
1984 daughterIndices_noclst.push_back(newDaughter0_noclst->getArrayIndex());
1985 Particle dau1_noclst(dau1_4vec_Lab, 22);
1986 momentum += dau1_noclst.get4Vector();
1987 Particle* newDaughter1_noclst = particles.appendNew(dau1_noclst);
1988 daughterIndices_noclst.push_back(newDaughter1_noclst->getArrayIndex());
1989 const Particle* par_noclst = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices_noclst);
1990
1991 // grab variables
1992 const Manager::Var* var = Manager::Instance().getVariable("daughterClusterAngleInBetween(0, 1)");
1993 const Manager::Var* varCMS = Manager::Instance().getVariable("useCMSFrame(daughterClusterAngleInBetween(0, 1))");
1994
1995 // when no relations are set between the particles and the eclClusters, nan is expected to be returned
1996 ASSERT_NE(var, nullptr);
1997 EXPECT_TRUE(std::isnan(std::get<double>(var->function(par_noclst))));
1998
1999 // set relations between particles and eclClusters
2000 ECLCluster* eclst0 = eclclusters.appendNew(ECLCluster());
2001 eclst0->setEnergy(dau0_4vec_Lab.E());
2002 eclst0->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
2003 eclst0->setClusterId(1);
2004 eclst0->setTheta(dau0_4vec_Lab.Theta());
2005 eclst0->setPhi(dau0_4vec_Lab.Phi());
2006 eclst0->setR(148.4);
2007 ECLCluster* eclst1 = eclclusters.appendNew(ECLCluster());
2008 eclst1->setEnergy(dau1_4vec_Lab.E());
2009 eclst1->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
2010 eclst1->setClusterId(2);
2011 eclst1->setTheta(dau1_4vec_Lab.Theta());
2012 eclst1->setPhi(dau1_4vec_Lab.Phi());
2013 eclst1->setR(148.5);
2014
2015 const Particle* newDaughter0 = particles.appendNew(Particle(eclclusters[0]));
2016 daughterIndices.push_back(newDaughter0->getArrayIndex());
2017 const Particle* newDaughter1 = particles.appendNew(Particle(eclclusters[1]));
2018 daughterIndices.push_back(newDaughter1->getArrayIndex());
2019
2020 const Particle* par = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices);
2021
2022 //now we expect non-nan results
2023 EXPECT_FLOAT_EQ(std::get<double>(var->function(par)), 2.8613892);
2024 EXPECT_FLOAT_EQ(std::get<double>(varCMS->function(par)), M_PI);
2025 }
2026
2027 TEST_F(MetaVariableTest, grandDaughterDiffOfs)
2028 {
2029 // declare all the array we need
2030 StoreArray<Particle> particles;
2031 std::vector<int> daughterIndices0_noclst, daughterIndices1_noclst, daughterIndices2_noclst;
2032 std::vector<int> daughterIndices0, daughterIndices1, daughterIndices2;
2033
2034 //proxy initialize where to declare the needed array
2036 StoreArray<ECLCluster> eclclusters;
2037 eclclusters.registerInDataStore();
2038 particles.registerRelationTo(eclclusters);
2040
2041 // create two Lorentz vectors
2042 const float px_0 = 2.;
2043 const float py_0 = 1.;
2044 const float pz_0 = 3.;
2045 const float px_1 = 1.5;
2046 const float py_1 = 1.5;
2047 const float pz_1 = 2.5;
2048 float E_0, E_1;
2049 E_0 = sqrt(pow(px_0, 2) + pow(py_0, 2) + pow(pz_0, 2));
2050 E_1 = sqrt(pow(px_1, 2) + pow(py_1, 2) + pow(pz_1, 2));
2051 PxPyPzEVector momentum_0, momentum_1, momentum;
2052 PxPyPzEVector dau0_4vec(px_0, py_0, pz_0, E_0), dau1_4vec(px_1, py_1, pz_1, E_1);
2053
2054 // add the two photons as the two daughters of some particle and create the latter
2055 // Particle dau0_noclst(dau0_4vec, 22);
2056 // momentum += dau0_noclst.get4Vector();
2057 // Particle* newDaughter0_noclst = particles.appendNew(dau0_noclst);
2058 // daughterIndices_noclst.push_back(newDaughter0_noclst->getArrayIndex());
2059 // Particle dau1_noclst(dau1_4vec, 22);
2060 // momentum += dau1_noclst.get4Vector();
2061 // Particle* newDaughter1_noclst = particles.appendNew(dau1_noclst);
2062 // daughterIndices_noclst.push_back(newDaughter1_noclst->getArrayIndex());
2063 // const Particle* par_noclst = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices_noclst);
2064
2065 Particle dau0_noclst(dau0_4vec, 22);
2066 momentum_0 = dau0_4vec;
2067 Particle* newDaughter0_noclst = particles.appendNew(dau0_noclst);
2068 daughterIndices0_noclst.push_back(newDaughter0_noclst->getArrayIndex());
2069 const Particle* par0_noclst = particles.appendNew(momentum_0, 111, Particle::c_Unflavored, daughterIndices0_noclst);
2070 Particle dau1_noclst(dau1_4vec, 22);
2071 momentum_1 = dau1_4vec;
2072 Particle* newDaughter1_noclst = particles.appendNew(dau1_noclst);
2073 daughterIndices1_noclst.push_back(newDaughter1_noclst->getArrayIndex());
2074 const Particle* par1_noclst = particles.appendNew(momentum_1, 111, Particle::c_Unflavored, daughterIndices1_noclst);
2075
2076 momentum = momentum_0 + momentum_1;
2077 daughterIndices2_noclst.push_back(par0_noclst->getArrayIndex());
2078 daughterIndices2_noclst.push_back(par1_noclst->getArrayIndex());
2079 const Particle* parGranny_noclst = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices2_noclst);
2080
2081 // grab variables
2082 const Manager::Var* var_Theta = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,theta)");
2083 const Manager::Var* var_ClusterTheta = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,clusterTheta)");
2084 const Manager::Var* var_E = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,E)");
2085 const Manager::Var* var_ClusterE = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,clusterE)");
2086 const Manager::Var* var_E_wrongIndexes = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,2,3,E)");
2087 const Manager::Var* var_ClusterE_wrongIndexes = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,2,3,clusterE)");
2088
2089 const Manager::Var* var_ClusterPhi = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,clusterPhi)");
2090 const Manager::Var* var_Phi = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,0,0,phi)");
2091 const Manager::Var* var_ClusterPhi_wrongIndexes = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,2,3,clusterPhi)");
2092 const Manager::Var* var_Phi_wrongIndexes = Manager::Instance().getVariable("grandDaughterDiffOf(0,1,2,3,phi)");
2093
2094 // when no relations are set between the particles and the eclClusters, nan is expected to be returned for the Cluster- vars
2095 // no problems are supposed to happen for non-Cluster- vars
2096 // also, we expect NaN when we pass wrong indexes
2097 ASSERT_NE(var_ClusterPhi, nullptr);
2098 EXPECT_TRUE(std::isnan(std::get<double>(var_ClusterPhi->function(parGranny_noclst))));
2099 EXPECT_TRUE(std::isnan(std::get<double>(var_ClusterTheta->function(parGranny_noclst))));
2100 EXPECT_TRUE(std::isnan(std::get<double>(var_ClusterE->function(parGranny_noclst))));
2101 EXPECT_FLOAT_EQ(std::get<double>(var_Phi->function(parGranny_noclst)), 0.32175055);
2102 EXPECT_FLOAT_EQ(std::get<double>(var_Theta->function(parGranny_noclst)), 0.06311664);
2103 EXPECT_FLOAT_EQ(std::get<double>(var_E->function(parGranny_noclst)), -0.46293807);
2104 EXPECT_TRUE(std::isnan(std::get<double>(var_ClusterPhi_wrongIndexes->function(parGranny_noclst))));
2105 EXPECT_TRUE(std::isnan(std::get<double>(var_Phi_wrongIndexes->function(parGranny_noclst))));
2106 EXPECT_TRUE(std::isnan(std::get<double>(var_ClusterE_wrongIndexes->function(parGranny_noclst))));
2107 EXPECT_TRUE(std::isnan(std::get<double>(var_E_wrongIndexes->function(parGranny_noclst))));
2108
2109 // set relations between particles and eclClusters
2110 ECLCluster* eclst0 = eclclusters.appendNew(ECLCluster());
2111 eclst0->setEnergy(dau0_4vec.E());
2112 eclst0->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
2113 eclst0->setClusterId(1);
2114 eclst0->setTheta(dau0_4vec.Theta());
2115 eclst0->setPhi(dau0_4vec.Phi());
2116 eclst0->setR(148.4);
2117 ECLCluster* eclst1 = eclclusters.appendNew(ECLCluster());
2118 eclst1->setEnergy(dau1_4vec.E());
2119 eclst1->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
2120 eclst1->setClusterId(2);
2121 eclst1->setTheta(dau1_4vec.Theta());
2122 eclst1->setPhi(dau1_4vec.Phi());
2123 eclst1->setR(148.5);
2124
2125 const Particle* newDaughter0 = particles.appendNew(Particle(eclclusters[0]));
2126 daughterIndices0.push_back(newDaughter0->getArrayIndex());
2127 const Particle* par0 = particles.appendNew(momentum_0, 111, Particle::c_Unflavored, daughterIndices0);
2128
2129 const Particle* newDaughter1 = particles.appendNew(Particle(eclclusters[1]));
2130 daughterIndices1.push_back(newDaughter1->getArrayIndex());
2131 const Particle* par1 = particles.appendNew(momentum_1, 111, Particle::c_Unflavored, daughterIndices1);
2132
2133 daughterIndices2.push_back(par0->getArrayIndex());
2134 daughterIndices2.push_back(par1->getArrayIndex());
2135 const Particle* parGranny = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices2);
2136 //const Particle* par = particles.appendNew(momentum, 111, Particle::c_Unflavored, daughterIndices);
2137
2138 //now we expect non-nan results
2139 EXPECT_FLOAT_EQ(std::get<double>(var_ClusterPhi->function(parGranny)), 0.32175055);
2140 EXPECT_FLOAT_EQ(std::get<double>(var_Phi->function(parGranny)), 0.32175055);
2141 EXPECT_FLOAT_EQ(std::get<double>(var_ClusterTheta->function(parGranny)), 0.06311664);
2142 EXPECT_FLOAT_EQ(std::get<double>(var_Theta->function(parGranny)), 0.06311664);
2143 EXPECT_FLOAT_EQ(std::get<double>(var_ClusterE->function(parGranny)), -0.46293831);
2144 EXPECT_FLOAT_EQ(std::get<double>(var_E->function(parGranny)), -0.46293831);
2145 }
2146
2147 TEST_F(MetaVariableTest, daughterNormDiffOf)
2148 {
2149 PxPyPzEVector momentum;
2150 const int nDaughters = 4;
2151 StoreArray<Particle> particles;
2152 std::vector<int> daughterIndices;
2153 for (int i = 0; i < nDaughters; i++) {
2154 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 1.0), (i % 2) ? -11 : 211);
2155 momentum += d.get4Vector();
2156 Particle* newDaughters = particles.appendNew(d);
2157 daughterIndices.push_back(newDaughters->getArrayIndex());
2158 }
2159 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
2160
2161 const Manager::Var* var = Manager::Instance().getVariable("daughterNormDiffOf(0, 1, PDG)");
2162 ASSERT_NE(var, nullptr);
2163 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -222 / 200.);
2164
2165 var = Manager::Instance().getVariable("daughterNormDiffOf(1, 0, PDG)");
2166 ASSERT_NE(var, nullptr);
2167 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 222 / 200.);
2168
2169 var = Manager::Instance().getVariable("daughterNormDiffOf(0, 1, abs(PDG))");
2170 ASSERT_NE(var, nullptr);
2171 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -200 / 222.);
2172
2173 var = Manager::Instance().getVariable("daughterNormDiffOf(1, 1, PDG)");
2174 ASSERT_NE(var, nullptr);
2175 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), -0 / 22.);
2176
2177 var = Manager::Instance().getVariable("daughterNormDiffOf(1, 3, abs(PDG))");
2178 ASSERT_NE(var, nullptr);
2179 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0 / 22.);
2180
2181 var = Manager::Instance().getVariable("daughterNormDiffOf(0, 2, PDG)");
2182 ASSERT_NE(var, nullptr);
2183 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0 / 422.);
2184
2185 }
2186
2187 TEST_F(MetaVariableTest, daughterMotherDiffOf)
2188 {
2189 PxPyPzEVector momentum;
2190 const int nDaughters = 4;
2191 StoreArray<Particle> particles;
2192 std::vector<int> daughterIndices;
2193 for (int i = 0; i < nDaughters; i++) {
2194 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 1.0), (i % 2) ? -11 : 211);
2195 momentum += d.get4Vector();
2196 Particle* newDaughters = particles.appendNew(d);
2197 daughterIndices.push_back(newDaughters->getArrayIndex());
2198 }
2199 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
2200
2201 const Manager::Var* var = Manager::Instance().getVariable("daughterMotherDiffOf(1, PDG)");
2202 ASSERT_NE(var, nullptr);
2203 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 422);
2204
2205 var = Manager::Instance().getVariable("daughterMotherDiffOf(1, abs(PDG))");
2206 ASSERT_NE(var, nullptr);
2207 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 400);
2208
2209 var = Manager::Instance().getVariable("daughterMotherDiffOf(0, PDG)");
2210 ASSERT_NE(var, nullptr);
2211 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 200);
2212
2213 }
2214
2215 TEST_F(MetaVariableTest, daughterMotherNormDiffOf)
2216 {
2217 PxPyPzEVector momentum;
2218 const int nDaughters = 4;
2219 StoreArray<Particle> particles;
2220 std::vector<int> daughterIndices;
2221 for (int i = 0; i < nDaughters; i++) {
2222 Particle d(PxPyPzEVector(1, 1, 1, i * 1.0 + 1.0), (i % 2) ? -11 : 211);
2223 momentum += d.get4Vector();
2224 Particle* newDaughters = particles.appendNew(d);
2225 daughterIndices.push_back(newDaughters->getArrayIndex());
2226 }
2227 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Unflavored, daughterIndices);
2228
2229 const Manager::Var* var = Manager::Instance().getVariable("daughterMotherNormDiffOf(1, PDG)");
2230 ASSERT_NE(var, nullptr);
2231 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 422 / 400.);
2232
2233 var = Manager::Instance().getVariable("daughterMotherNormDiffOf(1, abs(PDG))");
2234 ASSERT_NE(var, nullptr);
2235 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 400 / 422.);
2236
2237 var = Manager::Instance().getVariable("daughterMotherNormDiffOf(0, PDG)");
2238 ASSERT_NE(var, nullptr);
2239 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 200 / 622.);
2240
2241 }
2242
2243 TEST_F(MetaVariableTest, constant)
2244 {
2245
2246 const Manager::Var* var = Manager::Instance().getVariable("constant(1)");
2247 ASSERT_NE(var, nullptr);
2248 EXPECT_FLOAT_EQ(std::get<double>(var->function(nullptr)), 1.0);
2249
2250 var = Manager::Instance().getVariable("constant(0)");
2251 ASSERT_NE(var, nullptr);
2252 EXPECT_FLOAT_EQ(std::get<double>(var->function(nullptr)), 0.0);
2253
2254 }
2255
2256 TEST_F(MetaVariableTest, abs)
2257 {
2258 Particle p({ 0.1, -0.4, 0.8, 2.0 }, 11);
2259 Particle p2({ -0.1, -0.4, 0.8, 4.0 }, -11);
2260
2261 const Manager::Var* var = Manager::Instance().getVariable("abs(px)");
2262 ASSERT_NE(var, nullptr);
2263 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 0.1);
2264 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p2)), 0.1);
2265
2266 }
2267
2268 TEST_F(MetaVariableTest, sin)
2269 {
2270 Particle p({ 3.14159265359 / 2.0, -0.4, 0.8, 1.0}, 11);
2271 Particle p2({ 0.0, -0.4, 0.8, 1.0 }, -11);
2272
2273 const Manager::Var* var = Manager::Instance().getVariable("sin(px)");
2274 ASSERT_NE(var, nullptr);
2275 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p)), 1.0);
2276 EXPECT_NEAR(std::get<double>(var->function(&p2)), 0.0, 1e-6);
2277
2278 }
2279
2280 TEST_F(MetaVariableTest, cos)
2281 {
2282 Particle p({ 3.14159265359 / 2.0, -0.4, 0.8, 1.0}, 11);
2283 Particle p2({ 0.0, -0.4, 0.8, 1.0 }, -11);
2284
2285 const Manager::Var* var = Manager::Instance().getVariable("cos(px)");
2286 ASSERT_NE(var, nullptr);
2287 EXPECT_NEAR(std::get<double>(var->function(&p)), 0.0, 1e-6);
2288 EXPECT_FLOAT_EQ(std::get<double>(var->function(&p2)), 1.0);
2289
2290 }
2291
2292 TEST_F(MetaVariableTest, NBDeltaIfMissingDeathTest)
2293 {
2294 //Variable got removed, test for absence
2295 EXPECT_B2FATAL(Manager::Instance().getVariable("NBDeltaIfMissing(TOP, 11)"));
2296 EXPECT_B2FATAL(Manager::Instance().getVariable("NBDeltaIfMissing(ARICH, 11)"));
2297 }
2298
2299 TEST_F(MetaVariableTest, matchedMC)
2300 {
2302 StoreArray<MCParticle> mcParticles;
2303 StoreArray<Particle> particles;
2304 particles.registerRelationTo(mcParticles);
2306
2307 auto* mcParticle = mcParticles.appendNew();
2308 mcParticle->setPDG(Const::electron.getPDGCode());
2309 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
2310 auto* p1 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
2311 p1->addRelationTo(mcParticle);
2312
2313 mcParticle = mcParticles.appendNew();
2314 mcParticle->setPDG(-Const::electron.getPDGCode());
2315 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
2316 auto* p2 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
2317 p2->addRelationTo(mcParticle);
2318
2319 mcParticle = mcParticles.appendNew();
2320 mcParticle->setPDG(Const::photon.getPDGCode());
2321 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
2322 auto* p3 = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 11);
2323 p3->addRelationTo(mcParticle);
2324
2325 // Test if matchedMC also works for particle which already is an MCParticle.
2326 auto* p4 = particles.appendNew(mcParticle);
2327
2328 const Manager::Var* var = Manager::Instance().getVariable("matchedMC(charge)");
2329 ASSERT_NE(var, nullptr);
2330 EXPECT_FLOAT_EQ(std::get<double>(var->function(p1)), -1);
2331 EXPECT_FLOAT_EQ(std::get<double>(var->function(p2)), 1);
2332 EXPECT_FLOAT_EQ(std::get<double>(var->function(p3)), 0);
2333 EXPECT_FLOAT_EQ(std::get<double>(var->function(p4)), 0);
2334 }
2335
2336 TEST_F(MetaVariableTest, countInList)
2337 {
2338 StoreArray<Particle> particles;
2340
2341 StoreObjPtr<ParticleList> outputList("pList1");
2343 outputList.registerInDataStore(flags);
2345 outputList.create();
2346 outputList->initialize(22, "pList1");
2347
2348 particles.appendNew(Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2));
2349 particles.appendNew(Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3));
2350 particles.appendNew(Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4));
2351 particles.appendNew(Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 5));
2352 particles.appendNew(Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 6));
2353
2354 outputList->addParticle(0, 22, Particle::c_Unflavored);
2355 outputList->addParticle(1, 22, Particle::c_Unflavored);
2356 outputList->addParticle(2, 22, Particle::c_Unflavored);
2357 outputList->addParticle(3, 22, Particle::c_Unflavored);
2358 outputList->addParticle(4, 22, Particle::c_Unflavored);
2359
2360 const Manager::Var* var = Manager::Instance().getVariable("countInList(pList1, E < 0.85)");
2361 ASSERT_NE(var, nullptr);
2362 EXPECT_EQ(std::get<int>(var->function(nullptr)), 2);
2363
2364 var = Manager::Instance().getVariable("countInList(pList1)");
2365 ASSERT_NE(var, nullptr);
2366 EXPECT_EQ(std::get<int>(var->function(nullptr)), 5);
2367
2368 var = Manager::Instance().getVariable("countInList(pList1, E > 5)");
2369 ASSERT_NE(var, nullptr);
2370 EXPECT_EQ(std::get<int>(var->function(nullptr)), 0);
2371
2372 var = Manager::Instance().getVariable("countInList(pList1, E < 5)");
2373 ASSERT_NE(var, nullptr);
2374 EXPECT_EQ(std::get<int>(var->function(nullptr)), 5);
2375 }
2376
2377 TEST_F(MetaVariableTest, isInList)
2378 {
2379 // we need the particles StoreArray
2380 StoreArray<Particle> particles;
2382
2383 // create a photon list for testing
2384 StoreObjPtr<ParticleList> gammalist("testGammaList");
2386 gammalist.registerInDataStore(flags);
2388 gammalist.create();
2389 gammalist->initialize(22, "testGammaList");
2390
2391 // mock up two photons
2392 Particle goingin({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0);
2393 Particle notgoingin({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1);
2394 auto* inthelist = particles.appendNew(goingin);
2395 auto* notinthelist = particles.appendNew(notgoingin);
2396
2397 // put the the zeroth one in the list the first on not in the list
2398 gammalist->addParticle(0, 22, Particle::c_Unflavored);
2399
2400 // get the variables
2401 const Manager::Var* vnonsense = Manager::Instance().getVariable("isInList(NONEXISTANTLIST)");
2402 const Manager::Var* vsensible = Manager::Instance().getVariable("isInList(testGammaList)");
2403
2404 // -
2405 EXPECT_B2FATAL(std::get<bool>(vnonsense->function(notinthelist)));
2406 EXPECT_TRUE(std::get<bool>(vsensible->function(inthelist)));
2407 EXPECT_FALSE(std::get<bool>(vsensible->function(notinthelist)));
2408 }
2409
2411 TEST_F(MetaVariableTest, cutIsInList)
2412 {
2413 StoreArray<Particle> particles;
2415
2416 // create a photon list for testing
2417 const std::string listname {"wil/d(-+)'':l*"};
2418
2419 StoreObjPtr<ParticleList> particlelist(listname);
2421 particlelist.registerInDataStore(flags);
2423 particlelist.create();
2424 particlelist->initialize(22, listname);
2425
2426 Particle goingin({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0);
2427 Particle notgoingin({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1);
2428 auto* inthelist = particles.appendNew(goingin);
2429 auto* notinthelist = particles.appendNew(notgoingin);
2430
2431 // put the the zeroth one in the list the first on not in the list
2432 particlelist->addParticle(0, 22, Particle::c_Unflavored);
2433
2434 // use passesCut metavariable to check cut parsing of isInList particle list.
2435 const Manager::Var* nonexistlist = Manager::Instance().getVariable("passesCut(isInList(NONEXISTANTLIST))");
2436 const Manager::Var* existlist = Manager::Instance().getVariable("passesCut(isInList(" + listname + "))");
2437
2438 EXPECT_B2FATAL(std::get<bool>(nonexistlist->function(inthelist)));
2439 EXPECT_FALSE(std::get<bool>(existlist->function(notinthelist)));
2440 EXPECT_TRUE(std::get<bool>(existlist->function(inthelist)));
2441 }
2442
2443 TEST_F(MetaVariableTest, sourceObjectIsInList)
2444 {
2445 // datastore things
2448
2449 // needed to mock up
2450 StoreArray<ECLCluster> clusters;
2451 StoreArray<Particle> particles;
2452 StoreObjPtr<ParticleList> gammalist("testGammaList");
2453
2454 clusters.registerInDataStore();
2455 particles.registerInDataStore();
2457 gammalist.registerInDataStore(flags);
2458
2459 // end datastore things
2461
2462 // of course we have to create the list...
2463 gammalist.create();
2464 gammalist->initialize(22, "testGammaList");
2465
2466 // mock up two clusters from the ECL let's say they both came from true Klongs
2467 // but one looked a little bit photon-like
2468 auto* cl0 = clusters.appendNew(ECLCluster());
2469 cl0->setEnergy(1.0);
2470 cl0->setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
2471 cl0->addHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
2472 cl0->setClusterId(0);
2473 auto* cl1 = clusters.appendNew(ECLCluster());
2474 cl1->setEnergy(1.0);
2475 cl1->setHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
2476 cl1->setClusterId(1);
2477
2478 // create particles from the clusters
2479 Particle myphoton(cl0, Const::photon);
2480 Particle iscopiedin(cl0, Const::Klong);
2481 Particle notcopiedin(cl1, Const::Klong);
2482
2483 // add the particle created from cluster zero to the gamma list
2484 auto* myphoton_ = particles.appendNew(myphoton);
2485 gammalist->addParticle(myphoton_);
2486
2487 auto* iscopied = particles.appendNew(iscopiedin); // a clone of this guy is now in the gamma list
2488 auto* notcopied = particles.appendNew(notcopiedin);
2489
2490 // get the variables
2491 const Manager::Var* vnonsense = Manager::Instance().getVariable("sourceObjectIsInList(NONEXISTANTLIST)");
2492 const Manager::Var* vsensible = Manager::Instance().getVariable("sourceObjectIsInList(testGammaList)");
2493
2494 // -
2495 EXPECT_B2FATAL(std::get<int>(vnonsense->function(iscopied)));
2496 EXPECT_EQ(std::get<int>(vsensible->function(iscopied)), 1);
2497 EXPECT_EQ(std::get<int>(vsensible->function(notcopied)), 0);
2498
2499 // now mock up some other type particles
2500 Particle composite({0.5, 0.4, 0.5, 0.8}, 512, Particle::c_Unflavored, Particle::c_Composite, 0);
2501 Particle undefined({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1);
2502 auto* composite_ = particles.appendNew(undefined);
2503 auto* undefined_ = particles.appendNew(composite);
2504 EXPECT_EQ(std::get<int>(vsensible->function(composite_)), -1);
2505 EXPECT_EQ(std::get<int>(vsensible->function(undefined_)), -1);
2506 }
2507
2508 TEST_F(MetaVariableTest, mcParticleIsInMCList)
2509 {
2510 // datastore things
2513
2514 // needed to mock up
2515 StoreArray<MCParticle> mcparticles;
2516 StoreArray<Particle> particles;
2517 StoreObjPtr<ParticleList> list("testList");
2518 StoreObjPtr<ParticleList> anotherlist("supplimentaryList");
2519
2520 mcparticles.registerInDataStore();
2521 particles.registerInDataStore();
2522 particles.registerRelationTo(mcparticles);
2524 list.registerInDataStore(flags);
2525 anotherlist.registerInDataStore(flags);
2526
2528 // end datastore setup
2529
2530 list.create();
2531 list->initialize(22, "testList");
2532
2533 anotherlist.create();
2534 anotherlist->initialize(22, "supplimentaryList");
2535
2536 // MCParticles
2537 auto* mcphoton = mcparticles.appendNew();
2538 mcphoton->setPDG(Const::photon.getPDGCode());
2539 mcphoton->setStatus(MCParticle::c_PrimaryParticle);
2540
2541 auto* mcelectron = mcparticles.appendNew();
2542 mcelectron->setPDG(Const::electron.getPDGCode());
2543 mcelectron->setStatus(MCParticle::c_PrimaryParticle);
2544
2545 auto* mcanotherelectron = mcparticles.appendNew();
2546 mcanotherelectron->setPDG(Const::photon.getPDGCode());
2547 mcanotherelectron->setStatus(MCParticle::c_PrimaryParticle);
2548
2549 auto* mcyetanotherelectron = mcparticles.appendNew();
2550 mcyetanotherelectron->setPDG(Const::photon.getPDGCode());
2551 mcyetanotherelectron->setStatus(MCParticle::c_PrimaryParticle);
2552
2553 // particles
2554 auto* photon = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 22);
2555 photon->addRelationTo(mcphoton);
2556 list->addParticle(photon);
2557
2558 auto* electron = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 22);
2559 electron->addRelationTo(mcelectron);
2560 list->addParticle(electron);
2561
2562 auto* other = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 22);
2563 other->addRelationTo(mcanotherelectron);
2564
2565 auto* yetanotherelectron = particles.appendNew(PxPyPzEVector({ 0.0, -0.4, 0.8, 1.0}), 22);
2566 yetanotherelectron->addRelationTo(mcyetanotherelectron);
2567 anotherlist->addParticle(yetanotherelectron);
2568 // not in the list
2569
2570 // get the variable
2571 const Manager::Var* vnonsense = Manager::Instance().getVariable("mcParticleIsInMCList(NONEXISTANTLIST)");
2572 const Manager::Var* vsensible = Manager::Instance().getVariable("mcParticleIsInMCList(testList)");
2573
2574 // -
2575 EXPECT_B2FATAL(std::get<bool>(vnonsense->function(photon)));
2576 EXPECT_TRUE(std::get<bool>(vsensible->function(photon)));
2577 EXPECT_TRUE(std::get<bool>(vsensible->function(electron)));
2578 EXPECT_FALSE(std::get<bool>(vsensible->function(other)));
2579 EXPECT_FALSE(std::get<bool>(vsensible->function(yetanotherelectron)));
2580
2581 // now mock up some other type particles
2582 Particle composite({0.5, 0.4, 0.5, 0.8}, 512, Particle::c_Unflavored, Particle::c_Composite, 0);
2583 Particle undefined({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1);
2584 auto* composite_ = particles.appendNew(undefined);
2585 auto* undefined_ = particles.appendNew(composite);
2586 EXPECT_FALSE(std::get<bool>(vsensible->function(composite_)));
2587 EXPECT_FALSE(std::get<bool>(vsensible->function(undefined_)));
2588 }
2589
2590 TEST_F(MetaVariableTest, mostB2BAndClosestParticles)
2591 {
2592 /* Mock up an event with a "photon" and an "electron" which are nearly back to
2593 * back, and second "photon" which is close-ish to the "electron".
2594 *
2595 * Other test of non-existent / empty lists and variables also included.
2596 */
2597
2598 // Connect gearbox for CMS variables
2599 Gearbox& gearbox = Gearbox::getInstance();
2600 gearbox.setBackends({std::string("file:")});
2601 gearbox.close();
2602 gearbox.open("geometry/Belle2.xml", false);
2603
2604 // we need the particles StoreArray
2605 StoreArray<Particle> particles;
2607
2608 // create a photon list for testing
2609 StoreObjPtr<ParticleList> gammalist("testGammaList");
2610 StoreObjPtr<ParticleList> emptylist("testEmptyList");
2612 gammalist.registerInDataStore(flags);
2613 emptylist.registerInDataStore(flags);
2615 gammalist.create();
2616 gammalist->initialize(22, "testGammaList");
2617 emptylist.create();
2618 emptylist->initialize(22, "testEmptyList");
2619
2620 // create some photons in an stdvector
2621 std::vector<Particle> gammavector = {
2622 Particle({ -1.0, -1.0, 0.8, 1.7}, // this should be the most b2b to our reference particle
2623 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2624 Particle({0.2, 0.7, 0.9, 3.4}, // should be the closest
2625 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2626 };
2627 // put the photons in the StoreArray
2628 for (const auto& g : gammavector)
2629 particles.appendNew(g);
2630
2631 // put the photons in the test list
2632 for (size_t i = 0; i < gammavector.size(); i++)
2633 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2634
2635 // add the reference particle (electron) to the StoreArray
2636 const auto* electron = particles.appendNew(
2637 Particle({1.0, 1.0, 0.5, 1.6}, // somewhere in the +ve quarter of the detector
2638 11, Particle::c_Unflavored, Particle::c_Undefined, 2) // needs to be incremented if we add to gamma vector
2639 );
2640
2641 {
2642 EXPECT_B2FATAL(Manager::Instance().getVariable("angleToClosestInList"));
2643 EXPECT_B2FATAL(Manager::Instance().getVariable("angleToClosestInList(A, B)"));
2644
2645 const auto* nonexistent = Manager::Instance().getVariable("angleToClosestInList(NONEXISTANTLIST)");
2646 EXPECT_B2FATAL(std::get<double>(nonexistent->function(electron)));
2647
2648 const auto* empty = Manager::Instance().getVariable("angleToClosestInList(testEmptyList)");
2649 EXPECT_TRUE(std::isnan(std::get<double>(empty->function(electron))));
2650
2651 const auto* closest = Manager::Instance().getVariable("angleToClosestInList(testGammaList)");
2652 EXPECT_FLOAT_EQ(std::get<double>(closest->function(electron)), 0.68014491);
2653
2654 const auto* closestCMS = Manager::Instance().getVariable("useCMSFrame(angleToClosestInList(testGammaList))");
2655 EXPECT_FLOAT_EQ(std::get<double>(closestCMS->function(electron)), 0.67901474);
2656 }
2657
2658 {
2659 EXPECT_B2FATAL(Manager::Instance().getVariable("closestInList"));
2660 EXPECT_B2FATAL(Manager::Instance().getVariable("closestInList(A, B, C)"));
2661
2662 const auto* nonexistent = Manager::Instance().getVariable("closestInList(NONEXISTANTLIST, E)");
2663 EXPECT_B2FATAL(std::get<double>(nonexistent->function(electron)));
2664
2665 const auto* empty = Manager::Instance().getVariable("closestInList(testEmptyList, E)");
2666 EXPECT_TRUE(std::isnan(std::get<double>(empty->function(electron))));
2667
2668 const auto* closest = Manager::Instance().getVariable("closestInList(testGammaList, E)");
2669 EXPECT_FLOAT_EQ(std::get<double>(closest->function(electron)), 3.4);
2670
2671 const auto* closestCMS = Manager::Instance().getVariable("useCMSFrame(closestInList(testGammaList, E))");
2672 EXPECT_FLOAT_EQ(std::get<double>(closestCMS->function(electron)), 3.2732551); // the energy gets smeared because of boost
2673
2674 const auto* closestCMSLabE = Manager::Instance().getVariable("useCMSFrame(closestInList(testGammaList, useLabFrame(E)))");
2675 EXPECT_FLOAT_EQ(std::get<double>(closestCMSLabE->function(electron)), 3.4); // aaand should be back to the lab frame value
2676 }
2677
2678 {
2679 EXPECT_B2FATAL(Manager::Instance().getVariable("angleToMostB2BInList"));
2680 EXPECT_B2FATAL(Manager::Instance().getVariable("angleToMostB2BInList(A, B)"));
2681
2682 const auto* nonexistent = Manager::Instance().getVariable("angleToMostB2BInList(NONEXISTANTLIST)");
2683 EXPECT_B2FATAL(std::get<double>(nonexistent->function(electron)));
2684
2685 const auto* empty = Manager::Instance().getVariable("angleToMostB2BInList(testEmptyList)");
2686 EXPECT_TRUE(std::isnan(std::get<double>(empty->function(electron))));
2687
2688 const auto* mostB2B = Manager::Instance().getVariable("angleToMostB2BInList(testGammaList)");
2689 EXPECT_FLOAT_EQ(std::get<double>(mostB2B->function(electron)), 2.2869499);
2690
2691 const auto* mostB2BCMS = Manager::Instance().getVariable("useCMSFrame(angleToMostB2BInList(testGammaList))");
2692 EXPECT_FLOAT_EQ(std::get<double>(mostB2BCMS->function(electron)), 2.8312778);
2693 }
2694
2695 {
2696 EXPECT_B2FATAL(Manager::Instance().getVariable("mostB2BInList"));
2697 EXPECT_B2FATAL(Manager::Instance().getVariable("mostB2BInList(A, B, C)"));
2698
2699 const auto* nonexistent = Manager::Instance().getVariable("mostB2BInList(NONEXISTANTLIST, E)");
2700 EXPECT_B2FATAL(std::get<double>(nonexistent->function(electron)));
2701
2702 const auto* empty = Manager::Instance().getVariable("mostB2BInList(testEmptyList, E)");
2703 EXPECT_TRUE(std::isnan(std::get<double>(empty->function(electron))));
2704
2705 const auto* mostB2B = Manager::Instance().getVariable("mostB2BInList(testGammaList, E)");
2706 EXPECT_FLOAT_EQ(std::get<double>(mostB2B->function(electron)), 1.7);
2707
2708 const auto* mostB2BCMS = Manager::Instance().getVariable("useCMSFrame(mostB2BInList(testGammaList, E))");
2709 EXPECT_FLOAT_EQ(std::get<double>(mostB2BCMS->function(electron)), 1.5848758); // the energy gets smeared because of boost
2710
2711 const auto* mostB2BCMSLabE = Manager::Instance().getVariable("useCMSFrame(mostB2BInList(testGammaList, useLabFrame(E)))");
2712 EXPECT_FLOAT_EQ(std::get<double>(mostB2BCMSLabE->function(electron)), 1.7); // aaand should be back to the lab frame value
2713 }
2714 }
2715
2716 TEST_F(MetaVariableTest, totalEnergyOfParticlesInList)
2717 {
2718 // we need the particles StoreArray
2719 StoreArray<Particle> particles;
2721
2722 // create a photon list for testing
2723 StoreObjPtr<ParticleList> gammalist("testGammaList");
2725 gammalist.registerInDataStore(flags);
2727 gammalist.create();
2728 gammalist->initialize(22, "testGammaList");
2729
2730 // create some photons in an stdvector
2731 std::vector<Particle> gammavector = {
2732 Particle({0.5, 0.4, 0.4, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2733 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2734 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
2735 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
2736 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
2737 };
2738
2739 // put the photons in the StoreArray
2740 for (const auto& g : gammavector)
2741 particles.appendNew(g);
2742
2743 // put the photons in the test list
2744 for (size_t i = 0; i < gammavector.size(); i++)
2745 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2746
2747 // get their total energy
2748 const Manager::Var* vnonsense = Manager::Instance().getVariable(
2749 "totalEnergyOfParticlesInList(NONEXISTANTLIST)");
2750 const Manager::Var* vsensible = Manager::Instance().getVariable(
2751 "totalEnergyOfParticlesInList(testGammaList)");
2752
2753 // -
2754 EXPECT_B2FATAL(std::get<double>(vnonsense->function(nullptr)));
2755 EXPECT_FLOAT_EQ(std::get<double>(vsensible->function(nullptr)), 4.3);
2756 }
2757 TEST_F(MetaVariableTest, totalPxOfParticlesInList)
2758 {
2759 // we need the particles StoreArray
2760 StoreArray<Particle> particles;
2762
2763 // create a photon list for testing
2764 StoreObjPtr<ParticleList> gammalist("testGammaList");
2766 gammalist.registerInDataStore(flags);
2768 gammalist.create();
2769 gammalist->initialize(22, "testGammaList");
2770
2771 // create some photons in an stdvector
2772 std::vector<Particle> gammavector = {
2773 Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2774 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2775 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
2776 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
2777 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
2778 };
2779
2780 // put the photons in the StoreArray
2781 for (const auto& g : gammavector)
2782 particles.appendNew(g);
2783
2784 // put the photons in the test list
2785 for (size_t i = 0; i < gammavector.size(); i++)
2786 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2787
2788 // get their total energy
2789 const Manager::Var* vnonsense = Manager::Instance().getVariable(
2790 "totalPxOfParticlesInList(NONEXISTANTLIST)");
2791 const Manager::Var* vsensible = Manager::Instance().getVariable(
2792 "totalPxOfParticlesInList(testGammaList)");
2793
2794 // -
2795 EXPECT_B2FATAL(std::get<double>(vnonsense->function(nullptr)));
2796 EXPECT_FLOAT_EQ(std::get<double>(vsensible->function(nullptr)), 2.2);
2797 }
2798 TEST_F(MetaVariableTest, totalPyOfParticlesInList)
2799 {
2800 // we need the particles StoreArray
2801 StoreArray<Particle> particles;
2803
2804 // create a photon list for testing
2805 StoreObjPtr<ParticleList> gammalist("testGammaList");
2807 gammalist.registerInDataStore(flags);
2809 gammalist.create();
2810 gammalist->initialize(22, "testGammaList");
2811
2812 // create some photons in an stdvector
2813 std::vector<Particle> gammavector = {
2814 Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2815 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2816 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
2817 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
2818 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
2819 };
2820
2821 // put the photons in the StoreArray
2822 for (const auto& g : gammavector)
2823 particles.appendNew(g);
2824
2825 // put the photons in the test list
2826 for (size_t i = 0; i < gammavector.size(); i++)
2827 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2828
2829 // get their total energy
2830 const Manager::Var* vnonsense = Manager::Instance().getVariable(
2831 "totalPyOfParticlesInList(NONEXISTANTLIST)");
2832 const Manager::Var* vsensible = Manager::Instance().getVariable(
2833 "totalPyOfParticlesInList(testGammaList)");
2834
2835 // -
2836 EXPECT_B2FATAL(std::get<double>(vnonsense->function(nullptr)));
2837 EXPECT_FLOAT_EQ(std::get<double>(vsensible->function(nullptr)), 1.5);
2838 }
2839 TEST_F(MetaVariableTest, totalPzOfParticlesInList)
2840 {
2841 // we need the particles StoreArray
2842 StoreArray<Particle> particles;
2844
2845 // create a photon list for testing
2846 StoreObjPtr<ParticleList> gammalist("testGammaList");
2848 gammalist.registerInDataStore(flags);
2850 gammalist.create();
2851 gammalist->initialize(22, "testGammaList");
2852
2853 // create some photons in an stdvector
2854 std::vector<Particle> gammavector = {
2855 Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2856 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2857 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
2858 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
2859 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
2860 };
2861
2862 // put the photons in the StoreArray
2863 for (const auto& g : gammavector)
2864 particles.appendNew(g);
2865
2866 // put the photons in the test list
2867 for (size_t i = 0; i < gammavector.size(); i++)
2868 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2869
2870 // get their total energy
2871 const Manager::Var* vnonsense = Manager::Instance().getVariable(
2872 "totalPzOfParticlesInList(NONEXISTANTLIST)");
2873 const Manager::Var* vsensible = Manager::Instance().getVariable(
2874 "totalPzOfParticlesInList(testGammaList)");
2875
2876 // -
2877 EXPECT_B2FATAL(std::get<double>(vnonsense->function(nullptr)));
2878 EXPECT_FLOAT_EQ(std::get<double>(vsensible->function(nullptr)), 3.1);
2879 }
2880 TEST_F(MetaVariableTest, maxPtInList)
2881 {
2882 // we need the particles StoreArray
2883 StoreArray<Particle> particles;
2885
2886 // create a photon list for testing
2887 StoreObjPtr<ParticleList> gammalist("testGammaList");
2889 gammalist.registerInDataStore(flags);
2891 gammalist.create();
2892 gammalist->initialize(22, "testGammaList");
2893
2894 // create some photons in an stdvector
2895 std::vector<Particle> gammavector = {
2896 Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
2897 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
2898 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
2899 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
2900 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
2901 };
2902
2903 // put the photons in the StoreArray
2904 for (const auto& g : gammavector)
2905 particles.appendNew(g);
2906
2907 // put the photons in the test list
2908 for (size_t i = 0; i < gammavector.size(); i++)
2909 gammalist->addParticle(i, 22, Particle::c_Unflavored);
2910
2911 // get their total energy
2912 const Manager::Var* vnonsense = Manager::Instance().getVariable(
2913 "maxPtInList(NONEXISTANTLIST)");
2914 const Manager::Var* vsensible = Manager::Instance().getVariable(
2915 "maxPtInList(testGammaList)");
2916
2917 // -
2918 EXPECT_B2FATAL(std::get<double>(vnonsense->function(nullptr)));
2919 EXPECT_FLOAT_EQ(std::get<double>(vsensible->function(nullptr)), sqrt(0.5 * 0.5 + 0.4 * 0.4));
2920 }
2921
2922
2923 TEST_F(MetaVariableTest, numberOfNonOverlappingParticles)
2924 {
2925 StoreArray<Particle> particles;
2927
2928 StoreObjPtr<ParticleList> outputList("pList1");
2930 outputList.registerInDataStore(flags);
2932 outputList.create();
2933 outputList->initialize(22, "pList1");
2934
2935 auto* p1 = particles.appendNew(Particle({0.5, 0.4, 0.5, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2));
2936 auto* p2 = particles.appendNew(Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3));
2937 auto* p3 = particles.appendNew(Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4));
2938
2939 outputList->addParticle(0, 22, Particle::c_Unflavored);
2940 outputList->addParticle(1, 22, Particle::c_Unflavored);
2941
2942 const Manager::Var* var = Manager::Instance().getVariable("numberOfNonOverlappingParticles(pList1)");
2943 ASSERT_NE(var, nullptr);
2944 EXPECT_EQ(std::get<int>(var->function(p1)), 1);
2945 EXPECT_EQ(std::get<int>(var->function(p2)), 1);
2946 EXPECT_EQ(std::get<int>(var->function(p3)), 2);
2947
2948 }
2949
2950 TEST_F(MetaVariableTest, veto)
2951 {
2952 StoreArray<Particle> particles;
2954
2955 const Particle* p = particles.appendNew(Particle({0.8, 0.8, 1.131370849898476039041351, 1.6}, 22,
2956 Particle::c_Unflavored, Particle::c_Undefined, 1));
2957
2958 StoreObjPtr<ParticleList> outputList("pList1");
2960 outputList.registerInDataStore(flags);
2962 outputList.create();
2963 outputList->initialize(22, "pList1");
2964
2965 particles.appendNew(Particle({0.5, 0.4953406774856531014212777, 0.5609256753154148484773173, 0.9}, 22,
2966 Particle::c_Unflavored, Particle::c_Undefined, 2)); //m=0.135
2967 particles.appendNew(Particle({0.5, 0.2, 0.72111, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3)); //m=0.3582
2968 particles.appendNew(Particle({0.4, 0.2, 0.78102, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)); //m=0.3908
2969 particles.appendNew(Particle({0.5, 0.4, 0.89443, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 5)); //m=0.2369
2970 particles.appendNew(Particle({0.3, 0.3, 0.42426, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 6)); //m=0.0036
2971
2972 outputList->addParticle(1, 22, Particle::c_Unflavored);
2973 outputList->addParticle(2, 22, Particle::c_Unflavored);
2974 outputList->addParticle(3, 22, Particle::c_Unflavored);
2975 outputList->addParticle(4, 22, Particle::c_Unflavored);
2976 outputList->addParticle(5, 22, Particle::c_Unflavored);
2977
2978 StoreObjPtr<ParticleList> outputList2("pList2");
2980 outputList2.registerInDataStore(flags);
2982 outputList2.create();
2983 outputList2->initialize(22, "pList2");
2984
2985 particles.appendNew(Particle({0.5, -0.4, 0.63246, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 7)); //m=1.1353
2986 particles.appendNew(Particle({0.5, 0.2, 0.72111, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 8)); //m=0.3582
2987 particles.appendNew(Particle({0.4, 0.2, 0.78102, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 9)); //m=0.3908
2988 particles.appendNew(Particle({0.5, 0.4, 0.89443, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 10)); //m=0.2369
2989 particles.appendNew(Particle({0.3, 0.3, 0.42426, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 11)); //m=0.0036
2990
2991 outputList2->addParticle(6, 22, Particle::c_Unflavored);
2992 outputList2->addParticle(7, 22, Particle::c_Unflavored);
2993 outputList2->addParticle(8, 22, Particle::c_Unflavored);
2994 outputList2->addParticle(9, 22, Particle::c_Unflavored);
2995 outputList2->addParticle(10, 22, Particle::c_Unflavored);
2996
2997 const Manager::Var* var = Manager::Instance().getVariable("veto(pList1, 0.130 < M < 0.140, 22)");
2998 ASSERT_NE(var, nullptr);
2999 EXPECT_TRUE(std::get<bool>(var->function(p)));
3000
3001 var = Manager::Instance().getVariable("veto(pList2, 0.130 < M < 0.140, 22)");
3002 ASSERT_NE(var, nullptr);
3003 EXPECT_FALSE(std::get<bool>(var->function(p)));
3004
3005 }
3006
3007 TEST_F(MetaVariableTest, averageValueInList)
3008 {
3009 // we need the particles StoreArray
3010 StoreArray<Particle> particles;
3012
3013 // create a photon list for testing
3014 StoreObjPtr<ParticleList> gammalist("testGammaList");
3016 gammalist.registerInDataStore(flags);
3018 gammalist.create();
3019 gammalist->initialize(22, "testGammaList");
3020
3021 // create some photons in an stdvector
3022 std::vector<Particle> gammavector = {
3023 Particle({0.5, 0.4, 0.4, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
3024 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
3025 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
3026 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
3027 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
3028 };
3029
3030 // put the photons in the StoreArray
3031 for (const auto& g : gammavector)
3032 particles.appendNew(g);
3033
3034 // put the photons in the test list
3035 for (size_t i = 0; i < gammavector.size(); i++)
3036 gammalist->addParticle(i, 22, Particle::c_Unflavored);
3037
3038 // get the average px, py, pz, E of the gammas in the list
3039 const Manager::Var* vmeanpx = Manager::Instance().getVariable(
3040 "averageValueInList(testGammaList, px)");
3041 const Manager::Var* vmeanpy = Manager::Instance().getVariable(
3042 "averageValueInList(testGammaList, py)");
3043 const Manager::Var* vmeanpz = Manager::Instance().getVariable(
3044 "averageValueInList(testGammaList, pz)");
3045 const Manager::Var* vmeanE = Manager::Instance().getVariable(
3046 "averageValueInList(testGammaList, E)");
3047
3048 EXPECT_FLOAT_EQ(std::get<double>(vmeanpx->function(nullptr)), 0.44);
3049 EXPECT_FLOAT_EQ(std::get<double>(vmeanpy->function(nullptr)), 0.3);
3050 EXPECT_FLOAT_EQ(std::get<double>(vmeanpz->function(nullptr)), 0.6);
3051 EXPECT_FLOAT_EQ(std::get<double>(vmeanE->function(nullptr)), 0.86);
3052
3053 // wrong number of arguments (no variable provided)
3054 EXPECT_B2FATAL(Manager::Instance().getVariable("averageValueInList(testGammaList)"));
3055
3056 // non-existing variable
3057 EXPECT_B2FATAL(Manager::Instance().getVariable("averageValueInList(testGammaList, NONEXISTANTVARIABLE)"));
3058
3059 // non-existing list
3060 const Manager::Var* vnolist = Manager::Instance().getVariable(
3061 "averageValueInList(NONEXISTANTLIST, px)");
3062
3063 EXPECT_B2FATAL(std::get<double>(vnolist->function(nullptr)));
3064 }
3065
3066 TEST_F(MetaVariableTest, medianValueInList)
3067 {
3068 // we need the particles StoreArray
3069 StoreArray<Particle> particles;
3071
3072 // create two photon lists for testing (one with odd and one with even number of particles)
3073 StoreObjPtr<ParticleList> oddgammalist("oddGammaList");
3075 oddgammalist.registerInDataStore(flags);
3077 oddgammalist.create();
3078 oddgammalist->initialize(22, "oddGammaList");
3079 StoreObjPtr<ParticleList> evengammalist("evenGammaList");
3081 evengammalist.registerInDataStore(flags);
3083 evengammalist.create();
3084 evengammalist->initialize(22, "evenGammaList");
3085
3086 // create some photons in an stdvector
3087 std::vector<Particle> gammavector = {
3088 Particle({0.5, 0.4, 0.4, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
3089 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
3090 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
3091 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
3092 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
3093 };
3094
3095 // put the photons in the StoreArray
3096 for (const auto& g : gammavector)
3097 particles.appendNew(g);
3098
3099 // put the photons in the test lists
3100 oddgammalist->addParticle(0, 22, Particle::c_Unflavored);
3101 for (size_t i = 1; i < gammavector.size(); i++) {
3102 oddgammalist->addParticle(i, 22, Particle::c_Unflavored);
3103 evengammalist->addParticle(i, 22, Particle::c_Unflavored);
3104 }
3105
3106 // get the median px, py, pz, E of the gammas in the list with odd number of particles
3107 const Manager::Var* voddmedianpx = Manager::Instance().getVariable(
3108 "medianValueInList(oddGammaList, px)");
3109 const Manager::Var* voddmedianpy = Manager::Instance().getVariable(
3110 "medianValueInList(oddGammaList, py)");
3111 const Manager::Var* voddmedianpz = Manager::Instance().getVariable(
3112 "medianValueInList(oddGammaList, pz)");
3113 const Manager::Var* voddmedianE = Manager::Instance().getVariable(
3114 "medianValueInList(oddGammaList, E)");
3115
3116 EXPECT_FLOAT_EQ(std::get<double>(voddmedianpx->function(nullptr)), 0.5);
3117 EXPECT_FLOAT_EQ(std::get<double>(voddmedianpy->function(nullptr)), 0.3);
3118 EXPECT_FLOAT_EQ(std::get<double>(voddmedianpz->function(nullptr)), 0.7);
3119 EXPECT_FLOAT_EQ(std::get<double>(voddmedianE->function(nullptr)), 0.9);
3120
3121 // get the median px, py, pz, E of the gammas in the list with odd number of particles
3122 const Manager::Var* vevenmedianpx = Manager::Instance().getVariable(
3123 "medianValueInList(evenGammaList, px)");
3124 const Manager::Var* vevenmedianpy = Manager::Instance().getVariable(
3125 "medianValueInList(evenGammaList, py)");
3126 const Manager::Var* vevenmedianpz = Manager::Instance().getVariable(
3127 "medianValueInList(evenGammaList, pz)");
3128 const Manager::Var* vevenmedianE = Manager::Instance().getVariable(
3129 "medianValueInList(evenGammaList, E)");
3130
3131 EXPECT_FLOAT_EQ(std::get<double>(vevenmedianpx->function(nullptr)), 0.45);
3132 EXPECT_FLOAT_EQ(std::get<double>(vevenmedianpy->function(nullptr)), 0.25);
3133 EXPECT_FLOAT_EQ(std::get<double>(vevenmedianpz->function(nullptr)), 0.7);
3134 EXPECT_FLOAT_EQ(std::get<double>(vevenmedianE->function(nullptr)), 0.9);
3135
3136 // wrong number of arguments (no variable provided)
3137 EXPECT_B2FATAL(Manager::Instance().getVariable("medianValueInList(oddGammaList)"));
3138
3139 // non-existing variable
3140 EXPECT_B2FATAL(Manager::Instance().getVariable("medianValueInList(oddGammaList, NONEXISTANTVARIABLE)"));
3141
3142 // non-existing list
3143 const Manager::Var* vnolist = Manager::Instance().getVariable(
3144 "medianValueInList(NONEXISTANTLIST, px)");
3145
3146 EXPECT_B2FATAL(std::get<double>(vnolist->function(nullptr)));
3147 }
3148
3149 TEST_F(MetaVariableTest, productValueInList)
3150 {
3151 // we need the particles StoreArray
3152 StoreArray<Particle> particles;
3154
3155 // create a photon list for testing
3156 StoreObjPtr<ParticleList> gammalist("testGammaList");
3158 gammalist.registerInDataStore(flags);
3160 gammalist.create();
3161 gammalist->initialize(22, "testGammaList");
3162
3163 // create some photons in an stdvector
3164 std::vector<Particle> gammavector = {
3165 Particle({0.5, 0.4, 0.4, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
3166 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
3167 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
3168 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
3169 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
3170 };
3171
3172 // put the photons in the StoreArray
3173 for (const auto& g : gammavector)
3174 particles.appendNew(g);
3175
3176 // put the photons in the test list
3177 for (size_t i = 0; i < gammavector.size(); i++)
3178 gammalist->addParticle(i, 22, Particle::c_Unflavored);
3179
3180 // get the product of the px, py, pz, E of the gammas in the list
3181 const Manager::Var* vproductpx = Manager::Instance().getVariable(
3182 "productValueInList(testGammaList, px)");
3183 const Manager::Var* vproductpy = Manager::Instance().getVariable(
3184 "productValueInList(testGammaList, py)");
3185 const Manager::Var* vproductpz = Manager::Instance().getVariable(
3186 "productValueInList(testGammaList, pz)");
3187 const Manager::Var* vproductE = Manager::Instance().getVariable(
3188 "productValueInList(testGammaList, E)");
3189
3190 EXPECT_FLOAT_EQ(std::get<double>(vproductpx->function(nullptr)), 0.015);
3191 EXPECT_FLOAT_EQ(std::get<double>(vproductpy->function(nullptr)), 0.00192);
3192 EXPECT_FLOAT_EQ(std::get<double>(vproductpz->function(nullptr)), 0.06272);
3193 EXPECT_FLOAT_EQ(std::get<double>(vproductE->function(nullptr)), 0.42768);
3194
3195 // wrong number of arguments (no variable provided)
3196 EXPECT_B2FATAL(Manager::Instance().getVariable("productValueInList(testGammaList)"));
3197
3198 // non-existing variable
3199 EXPECT_B2FATAL(Manager::Instance().getVariable("productValueInList(testGammaList, NONEXISTANTVARIABLE)"));
3200
3201 // non-existing list
3202 const Manager::Var* vnolist = Manager::Instance().getVariable(
3203 "productValueInList(NONEXISTANTLIST, px)");
3204
3205 EXPECT_B2FATAL(std::get<double>(vnolist->function(nullptr)));
3206 }
3207
3208 TEST_F(MetaVariableTest, sumValueInList)
3209 {
3210 // we need the particles StoreArray
3211 StoreArray<Particle> particles;
3213
3214 // create a photon list for testing
3215 StoreObjPtr<ParticleList> gammalist("testGammaList");
3217 gammalist.registerInDataStore(flags);
3219 gammalist.create();
3220 gammalist->initialize(22, "testGammaList");
3221
3222 // create some photons in an stdvector
3223 std::vector<Particle> gammavector = {
3224 Particle({0.5, 0.4, 0.4, 0.8}, 22, Particle::c_Unflavored, Particle::c_Undefined, 0),
3225 Particle({0.5, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 1),
3226 Particle({0.4, 0.2, 0.7, 0.9}, 22, Particle::c_Unflavored, Particle::c_Undefined, 2),
3227 Particle({0.5, 0.4, 0.8, 1.1}, 22, Particle::c_Unflavored, Particle::c_Undefined, 3),
3228 Particle({0.3, 0.3, 0.4, 0.6}, 22, Particle::c_Unflavored, Particle::c_Undefined, 4)
3229 };
3230
3231 // put the photons in the StoreArray
3232 for (const auto& g : gammavector)
3233 particles.appendNew(g);
3234
3235 // put the photons in the test list
3236 for (size_t i = 0; i < gammavector.size(); i++)
3237 gammalist->addParticle(i, 22, Particle::c_Unflavored);
3238
3239 // get the summed px, py, pz, E of the gammas in the list
3240 const Manager::Var* vsumpx = Manager::Instance().getVariable(
3241 "sumValueInList(testGammaList, px)");
3242 const Manager::Var* vsumpy = Manager::Instance().getVariable(
3243 "sumValueInList(testGammaList, py)");
3244 const Manager::Var* vsumpz = Manager::Instance().getVariable(
3245 "sumValueInList(testGammaList, pz)");
3247 "sumValueInList(testGammaList, E)");
3248
3249 EXPECT_FLOAT_EQ(std::get<double>(vsumpx->function(nullptr)), 2.2);
3250 EXPECT_FLOAT_EQ(std::get<double>(vsumpy->function(nullptr)), 1.5);
3251 EXPECT_FLOAT_EQ(std::get<double>(vsumpz->function(nullptr)), 3.0);
3252 EXPECT_FLOAT_EQ(std::get<double>(vsumE->function(nullptr)), 4.3);
3253
3254 // wrong number of arguments (no variable provided)
3255 EXPECT_B2FATAL(Manager::Instance().getVariable("sumValueInList(testGammaList)"));
3256
3257 // non-existing variable
3258 EXPECT_B2FATAL(Manager::Instance().getVariable("sumValueInList(testGammaList, NONEXISTANTVARIABLE)"));
3259
3260 // non-existing list
3261 const Manager::Var* vnolist = Manager::Instance().getVariable(
3262 "sumValueInList(NONEXISTANTLIST, px)");
3263
3264 EXPECT_B2FATAL(std::get<double>(vnolist->function(nullptr)));
3265 }
3266
3267 TEST_F(MetaVariableTest, pValueCombination)
3268 {
3269 PxPyPzEVector momentum;
3270 StoreArray<Particle> particles;
3271 std::vector<int> daughterIndices;
3272 Particle KS(PxPyPzEVector(1.164, 1.55200, 0, 2), 310, Particle::c_Unflavored, Particle::c_Composite, 0);
3273 KS.setPValue(0.1);
3274 momentum += KS.get4Vector();
3275 Particle* newDaughters = particles.appendNew(KS);
3276 daughterIndices.push_back(newDaughters->getArrayIndex());
3277 Particle Jpsi(PxPyPzEVector(-1, 1, 1, 3.548), 443, Particle::c_Unflavored, Particle::c_Composite, 1);
3278 Jpsi.setPValue(0.9);
3279 momentum += Jpsi.get4Vector();
3280 newDaughters = particles.appendNew(Jpsi);
3281 daughterIndices.push_back(newDaughters->getArrayIndex());
3282 Particle* B = particles.appendNew(momentum, 521, Particle::c_Flavored, daughterIndices);
3283 B->setPValue(0.5);
3284
3285 const Manager::Var* singlePvalue = Manager::Instance().getVariable("pValueCombination(chiProb)");
3286 ASSERT_NE(singlePvalue, nullptr);
3287 EXPECT_FLOAT_EQ(std::get<double>(singlePvalue->function(B)), 0.5);
3288
3289 const Manager::Var* twoPvalues = Manager::Instance().getVariable("pValueCombination(chiProb, daughter(0, chiProb))");
3290 ASSERT_NE(twoPvalues, nullptr);
3291 EXPECT_FLOAT_EQ(std::get<double>(twoPvalues->function(B)), 0.05 * (1 - log(0.05)));
3292
3293 const Manager::Var* threePvalues =
3294 Manager::Instance().getVariable("pValueCombination(chiProb, daughter(0, chiProb), daughter(1, chiProb))");
3295 ASSERT_NE(threePvalues, nullptr);
3296 EXPECT_FLOAT_EQ(std::get<double>(threePvalues->function(B)), 0.045 * (1 - log(0.045) + 0.5 * log(0.045) * log(0.045)));
3297
3298 // wrong number of arguments
3299 EXPECT_B2FATAL(Manager::Instance().getVariable("pValueCombination()"));
3300
3301 // non-existing variable
3302 EXPECT_B2FATAL(Manager::Instance().getVariable("pValueCombination(chiProb, NONEXISTANTVARIABLE)"));
3303 }
3304
3305
3306 TEST_F(MetaVariableTest, daughterCombinationOneGeneration)
3307 {
3308 const int nDaughters = 5;
3309 PxPyPzEVector momentum(0, 0, 0, 0);
3310 StoreArray<Particle> particles;
3311 std::vector<int> daughterIndices;
3312 std::vector<PxPyPzEVector> daughterMomenta;
3313
3314 for (int i = 0; i < nDaughters; i++) {
3315 PxPyPzEVector mom(1, i * 0.5, 1, i * 1.0 + 2.0);
3316 Particle d(mom, (i % 2) ? 111 : 113);
3317 Particle* newDaughters = particles.appendNew(d);
3318 daughterIndices.push_back(newDaughters->getArrayIndex());
3319 daughterMomenta.push_back(mom);
3320 momentum = momentum + mom;
3321 }
3322 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Flavored, daughterIndices);
3323
3324 // Test the invariant mass of several combinations
3325 const Manager::Var* var = Manager::Instance().getVariable("daughterCombination(M, 0,1,2)");
3326 double M_test = (daughterMomenta[0] + daughterMomenta[1] + daughterMomenta[2]).mag();
3327 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), M_test);
3328
3329 var = Manager::Instance().getVariable("daughterCombination(M, 0,4)");
3330 M_test = (daughterMomenta[0] + daughterMomenta[4]).mag();
3331 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), M_test);
3332
3333
3334 // Try with a non-lorentz invariant quantity
3335 var = Manager::Instance().getVariable("daughterCombination(p, 1, 0, 4)");
3336 double p_test = (daughterMomenta[0] + daughterMomenta[1] + daughterMomenta[4]).P();
3337 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), p_test);
3338
3339
3340 // errors and bad stuff
3341 EXPECT_B2FATAL(Manager::Instance().getVariable("daughterCombination(aVeryNonExistingVariableSillyName, 1, 0, 4)"));
3342
3343 var = Manager::Instance().getVariable("daughterCombination(M, 1, 0, 100)");
3344 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3345 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3346
3347
3348 var = Manager::Instance().getVariable("daughterCombination(M, 1, -1)");
3349 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3350 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3351
3352
3353 var = Manager::Instance().getVariable("daughterCombination(M, 1, 0:1:0:0:1)");
3354 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3355 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3356
3357 }
3358
3359
3360 TEST_F(MetaVariableTest, daughterCombinationTwoGenerations)
3361 {
3362 StoreArray<Particle> particles;
3363
3364 // make a 1 -> 3 particle
3365
3366 PxPyPzEVector momentum_1(0, 0, 0, 0);
3367 std::vector<PxPyPzEVector> daughterMomenta_1;
3368 std::vector<int> daughterIndices_1;
3369
3370 for (int i = 0; i < 3; i++) {
3371 PxPyPzEVector mom(i * 0.2, 1, 1, i * 1.0 + 2.0);
3372 Particle d(mom, (i % 2) ? 111 : 113);
3373 Particle* newDaughters = particles.appendNew(d);
3374 daughterIndices_1.push_back(newDaughters->getArrayIndex());
3375 daughterMomenta_1.push_back(mom);
3376 momentum_1 = momentum_1 + mom;
3377 }
3378
3379 const Particle* compositeDau_1 = particles.appendNew(momentum_1, 411, Particle::c_Flavored, daughterIndices_1);
3380
3381
3382 // make a 1 -> 2 particle
3383
3384 PxPyPzEVector momentum_2(0, 0, 0, 0);
3385 std::vector<PxPyPzEVector> daughterMomenta_2;
3386 std::vector<int> daughterIndices_2;
3387
3388 for (int i = 0; i < 2; i++) {
3389 PxPyPzEVector mom(1, 1, i * 0.3, i * 1.0 + 2.0);
3390 Particle d(mom, (i % 2) ? 111 : 113);
3391 Particle* newDaughters = particles.appendNew(d);
3392 daughterIndices_2.push_back(newDaughters->getArrayIndex());
3393 daughterMomenta_2.push_back(mom);
3394 momentum_2 = momentum_2 + mom;
3395 }
3396
3397 const Particle* compositeDau_2 = particles.appendNew(momentum_2, 411, Particle::c_Flavored, daughterIndices_2);
3398
3399
3400 // make the composite particle
3401 std::vector<int> daughterIndices = {compositeDau_1->getArrayIndex(), compositeDau_2->getArrayIndex()};
3402 const Particle* p = particles.appendNew(momentum_2 + momentum_1, 111, Particle::c_Unflavored, daughterIndices);
3403
3404
3405 // Test the invariant mass of several combinations
3406 const Manager::Var* var = Manager::Instance().getVariable("daughterCombination(M, 0,1)");
3407
3408 double M_test = (momentum_1 + momentum_2).mag();
3409 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), M_test);
3410
3411 // this should be the mass of the first daughter
3412 var = Manager::Instance().getVariable("daughterCombination(M, 0:0, 0:1, 0:2)");
3413 M_test = (momentum_1).mag();
3414 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), M_test);
3415
3416 // this should be a generic combinations
3417 var = Manager::Instance().getVariable("daughterCombination(M, 0:0, 0:1, 1:0)");
3418 M_test = (daughterMomenta_1[0] + daughterMomenta_1[1] + daughterMomenta_2[0]).mag();
3419 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), M_test);
3420
3421 }
3422
3423
3424 TEST_F(MetaVariableTest, useAlternativeDaughterHypothesis)
3425 {
3426 const int nDaughters = 5;
3427 StoreArray<Particle> particles;
3428
3429 // Build a first Particle
3430 PxPyPzEVector momentum(0, 0, 0, 0);
3431 std::vector<int> daughterIndices;
3432 for (int i = 0; i < nDaughters; i++) {
3433 double px = i * 0.1;
3434 double py = i * 0.3;
3435 double pz = -i * 0.1 - 0.2;
3436
3437 PxPyPzEVector mom(px, py, pz, 1);
3438 // all pions
3439 int pdgCode = Const::pion.getPDGCode();
3440 Particle d(mom, pdgCode);
3441 d.updateMass(pdgCode);
3442 mom = d.get4Vector();
3443
3444 Particle* daughters = particles.appendNew(d);
3445 daughterIndices.push_back(daughters->getArrayIndex());
3446 momentum = momentum + mom;
3447 }
3448 const Particle* p = particles.appendNew(momentum, 411, Particle::c_Flavored, daughterIndices);
3449
3450
3451 // Build a second Particle with same momenta, but different mass hyp.
3452 PxPyPzEVector momentumAlt(0, 0, 0, 0);
3453 std::vector<int> daughterIndicesAlt;
3454 for (int i = 0; i < nDaughters; i++) {
3455 double px = i * 0.1;
3456 double py = i * 0.3;
3457 double pz = -i * 0.1 - 0.2;
3458
3459 PxPyPzEVector mom(px, py, pz, 1);
3460 // all pions but the first two
3461 int pdgCode = Const::pion.getPDGCode();
3462 if (i == 0)
3463 pdgCode = Const::proton.getPDGCode(); // a proton
3464 if (i == 1)
3465 pdgCode = Const::kaon.getPDGCode(); // a K
3466 Particle d(mom, pdgCode);
3467 d.updateMass(pdgCode);
3468 mom = d.get4Vector();
3469
3470 Particle* daughters = particles.appendNew(d);
3471 daughterIndicesAlt.push_back(daughters->getArrayIndex());
3472 momentumAlt = momentumAlt + mom;
3473 }
3474 const Particle* pAlt = particles.appendNew(momentumAlt, 411, Particle::c_Flavored, daughterIndicesAlt);
3475
3476
3477 // Test the invariant mass under the alternative hypothesis
3478 std::cout << "mass test" << std::endl;
3479 const Manager::Var* var = Manager::Instance().getVariable("useAlternativeDaughterHypothesis(M, 0:p+,1:K+)");
3480 const Manager::Var* varAlt = Manager::Instance().getVariable("M");
3481 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), std::get<double>(varAlt->function(pAlt)));
3482
3483 // check it's really charge-insensitive...
3484 std::cout << "charge test" << std::endl;
3485 var = Manager::Instance().getVariable("useAlternativeDaughterHypothesis(M, 0:p+,1:K-)");
3486 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), std::get<double>(varAlt->function(pAlt)));
3487
3488 // check the variable is not changing the 3-momentum
3489 std::cout << "momentum test" << std::endl;
3490 var = Manager::Instance().getVariable("useAlternativeDaughterHypothesis(p, 0:p+,1:K-)");
3491 varAlt = Manager::Instance().getVariable("p");
3492 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), std::get<double>(varAlt->function(pAlt)));
3493 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), std::get<double>(varAlt->function(p)));
3494 EXPECT_FLOAT_EQ(std::get<double>(var->function(pAlt)), std::get<double>(varAlt->function(pAlt)));
3495 }
3496
3497
3498
3499
3500 TEST_F(MetaVariableTest, daughterAngle)
3501 {
3502 StoreArray<Particle> particles;
3503
3504 // make a 1 -> 3 particle
3505
3506 PxPyPzEVector momentum_1(0, 0, 0, 0);
3507 std::vector<PxPyPzEVector> daughterMomenta_1;
3508 std::vector<int> daughterIndices_1;
3509
3510 for (int i = 0; i < 3; i++) {
3511 PxPyPzEVector mom(i * 0.2, 1, 1, i * 1.0 + 2.0);
3512 Particle d(mom, (i % 2) ? -11 : 211);
3513 Particle* newDaughters = particles.appendNew(d);
3514 daughterIndices_1.push_back(newDaughters->getArrayIndex());
3515 daughterMomenta_1.push_back(mom);
3516 momentum_1 = momentum_1 + mom;
3517 }
3518
3519 const Particle* compositeDau_1 = particles.appendNew(momentum_1, 411, Particle::c_Flavored, daughterIndices_1);
3520
3521
3522 // make a 1 -> 2 particle
3523
3524 PxPyPzEVector momentum_2(0, 0, 0, 0);
3525 std::vector<PxPyPzEVector> daughterMomenta_2;
3526 std::vector<int> daughterIndices_2;
3527
3528 for (int i = 0; i < 2; i++) {
3529 PxPyPzEVector mom(1, 1, i * 0.3, i * 1.0 + 2.0);
3530 Particle d(mom, (i % 2) ? -11 : 211);
3531 Particle* newDaughters = particles.appendNew(d);
3532 daughterIndices_2.push_back(newDaughters->getArrayIndex());
3533 daughterMomenta_2.push_back(mom);
3534 momentum_2 = momentum_2 + mom;
3535 }
3536
3537 const Particle* compositeDau_2 = particles.appendNew(momentum_2, 411, Particle::c_Flavored, daughterIndices_2);
3538
3539
3540 // make the composite particle
3541 std::vector<int> daughterIndices = {compositeDau_1->getArrayIndex(), compositeDau_2->getArrayIndex()};
3542 const Particle* p = particles.appendNew(momentum_2 + momentum_1, 111, Particle::c_Unflavored, daughterIndices);
3543
3544
3545 // Test the invariant mass of several combinations
3546 const Manager::Var* var = Manager::Instance().getVariable("daughterAngle(0, 1)");
3547 double v_test = acos(momentum_1.Vect().Unit().Dot(momentum_2.Vect().Unit()));
3548
3549 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), v_test);
3550
3551 // this should be a generic combinations
3552 var = Manager::Instance().getVariable("daughterAngle(0:0, 1:0)");
3553 v_test = acos(daughterMomenta_1[0].Vect().Unit().Dot(daughterMomenta_2[0].Vect().Unit()));
3554 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), v_test);
3555
3556 var = Manager::Instance().getVariable("daughterAngle( 1, -1)");
3557 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3558 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3559
3560 var = Manager::Instance().getVariable("daughterAngle(1, 0:1:0:0:1)");
3561 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3562 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3563
3564 }
3565
3566 TEST_F(MetaVariableTest, mcDaughterVariables)
3567 {
3568
3570 StoreArray<Particle> particles;
3571 StoreArray<MCParticle> mcParticles;
3572 particles.registerRelationTo(mcParticles);
3574 // make a 1 -> 3 particle
3575
3576 PxPyPzEVector momentum_1(0, 0, 0, 0);
3577 std::vector<PxPyPzEVector> daughterMomenta_1;
3578 std::vector<int> daughterIndices_1;
3579
3580 for (int i = 0; i < 3; i++) {
3581 PxPyPzEVector mom(i * 0.2, 1, 1, i * 1.0 + 2.0);
3582 Particle d(mom, (i % 2) ? -11 : 211);
3583 Particle* newDaughters = particles.appendNew(d);
3584 daughterIndices_1.push_back(newDaughters->getArrayIndex());
3585 daughterMomenta_1.push_back(mom);
3586 momentum_1 = momentum_1 + mom;
3587
3588 auto* mcParticle = mcParticles.appendNew();
3589 mcParticle->setPDG((i % 2) ? -Const::electron.getPDGCode() : Const::pion.getPDGCode());
3590 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
3591 mcParticle->set4Vector(mom);
3592 newDaughters->addRelationTo(mcParticle);
3593 }
3594
3595 const Particle* compositeDau_1 = particles.appendNew(momentum_1, 411, Particle::c_Flavored, daughterIndices_1);
3596 auto* mcCompositeDau_1 = mcParticles.appendNew();
3597 mcCompositeDau_1->setPDG(411);
3598 mcCompositeDau_1->setStatus(MCParticle::c_PrimaryParticle);
3599 mcCompositeDau_1->set4Vector(momentum_1);
3600 compositeDau_1->addRelationTo(mcCompositeDau_1);
3601
3602 // make a 1 -> 2 particle
3603
3604 PxPyPzEVector momentum_2(0, 0, 0, 0);
3605 std::vector<PxPyPzEVector> daughterMomenta_2;
3606 std::vector<int> daughterIndices_2;
3607
3608 for (int i = 0; i < 2; i++) {
3609 PxPyPzEVector mom(1, 1, i * 0.3, i * 1.0 + 2.0);
3610 Particle d(mom, (i % 2) ? -11 : 211);
3611 Particle* newDaughters = particles.appendNew(d);
3612 daughterIndices_2.push_back(newDaughters->getArrayIndex());
3613 daughterMomenta_2.push_back(mom);
3614 momentum_2 = momentum_2 + mom;
3615
3616 auto* mcParticle = mcParticles.appendNew();
3617 mcParticle->setPDG((i % 2) ? -Const::electron.getPDGCode() : Const::pion.getPDGCode());
3618 mcParticle->setStatus(MCParticle::c_PrimaryParticle);
3619 mcParticle->set4Vector(mom);
3620 newDaughters->addRelationTo(mcParticle);
3621 }
3622
3623 const Particle* compositeDau_2 = particles.appendNew(momentum_2, 411, Particle::c_Flavored, daughterIndices_2);
3624 auto* mcCompositeDau_2 = mcParticles.appendNew();
3625 mcCompositeDau_2->setPDG(411);
3626 mcCompositeDau_2->setStatus(MCParticle::c_PrimaryParticle);
3627 mcCompositeDau_2->set4Vector(momentum_2);
3628 compositeDau_2->addRelationTo(mcCompositeDau_2);
3629
3630 // make the composite particle
3631 std::vector<int> daughterIndices = {compositeDau_1->getArrayIndex(), compositeDau_2->getArrayIndex()};
3632 const Particle* p = particles.appendNew(momentum_2 + momentum_1, 111, Particle::c_Unflavored, daughterIndices);
3633
3634
3635 // Test mcDaughterAngle
3636 const Manager::Var* var = Manager::Instance().getVariable("mcDaughterAngle(0, 1)");
3637 double v_test = acos(momentum_1.Vect().Unit().Dot(momentum_2.Vect().Unit()));
3638 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), v_test);
3639
3640 var = Manager::Instance().getVariable("mcDaughterAngle(0:0, 1:0)");
3641 v_test = acos(daughterMomenta_1[0].Vect().Unit().Dot(daughterMomenta_2[0].Vect().Unit()));
3642 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), v_test);
3643
3644 var = Manager::Instance().getVariable("mcDaughterAngle( 1, -1)");
3645 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3646 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3647
3648 var = Manager::Instance().getVariable("mcDaughterAngle(1, 0:1:0:0:1)");
3649 EXPECT_B2WARNING(std::get<double>(var->function(p)));
3650 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3651
3652 // Test mcDaughterDiffOf
3653 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, 1, PDG)");
3654 ASSERT_NE(var, nullptr);
3655 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), 0);
3656
3657 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, NOTINT, PDG)");
3658 ASSERT_NE(var, nullptr);
3659 EXPECT_TRUE(std::isnan(std::get<double>(var->function(p))));
3660
3661 // Test azimuthal angle as well
3662 var = Manager::Instance().getVariable("mcDaughterDiffOf(0, 1, phi)");
3663 ASSERT_NE(var, nullptr);
3664 v_test = momentum_2.Phi() - momentum_1.Phi();
3665 EXPECT_FLOAT_EQ(std::get<double>(var->function(p)), v_test);
3666
3667 }
3668
3669 TEST_F(MetaVariableTest, varForFirstMCAncestorOfType)
3670 {
3672 StoreArray<MCParticle> mcParticles;
3673 StoreArray<Particle> particles;
3674 particles.registerInDataStore();
3675 mcParticles.registerInDataStore();
3676 particles.registerRelationTo(mcParticles);
3677 StoreObjPtr<ParticleList> DList("D0:vartest");
3678 DList.registerInDataStore();
3679 DList.create();
3680 DList->initialize(421, "D0:vartest");
3682 PxPyPzEVector momentum;
3683 PxPyPzEVector momentum_0;
3684 PxPyPzEVector momentum_1;
3685 std::vector<int> D_daughterIndices;
3686 std::vector<int> D_grandDaughterIndices_0;
3687 std::vector<int> D_grandDaughterIndices_1;
3688
3689
3690 // Create MC graph for D -> (K0s -> pi+ + pi-) (K0s -> pi+ + pi-)
3691 MCParticleGraph mcGraph;
3692
3694 MCParticleGraph::GraphParticle& mcg_d_0 = mcGraph.addParticle();
3695 MCParticleGraph::GraphParticle& mcg_d_1 = mcGraph.addParticle();
3696 MCParticleGraph::GraphParticle& mcg_gd_0_0 = mcGraph.addParticle();
3697 MCParticleGraph::GraphParticle& mcg_gd_0_1 = mcGraph.addParticle();
3698 MCParticleGraph::GraphParticle& mcg_gd_1_0 = mcGraph.addParticle();
3699 MCParticleGraph::GraphParticle& mcg_gd_1_1 = mcGraph.addParticle();
3700 MCParticleGraph::GraphParticle& mcg_not_child = mcGraph.addParticle();
3701
3702 mcg_m.setPDG(421);
3703 mcg_m.set4Vector(PxPyPzEVector(7, 7, 7, 7));
3704 mcg_d_0.setPDG(-Const::Kshort.getPDGCode());
3705 mcg_d_0.set4Vector(PxPyPzEVector(6, 6, 6, 6));
3706 mcg_d_1.setPDG(Const::Kshort.getPDGCode());
3707 mcg_d_1.set4Vector(PxPyPzEVector(5, 5, 5, 5));
3708 mcg_gd_0_0.setPDG(Const::pion.getPDGCode());
3709 mcg_gd_0_0.set4Vector(PxPyPzEVector(4, 4, 4, 4));
3710 mcg_gd_0_1.setPDG(-Const::pion.getPDGCode());
3711 mcg_gd_0_1.set4Vector(PxPyPzEVector(3, 3, 3, 3));
3712 mcg_gd_1_0.setPDG(Const::pion.getPDGCode());
3713 mcg_gd_1_0.set4Vector(PxPyPzEVector(2, 1, 2, 2));
3714 mcg_gd_1_1.setPDG(-Const::pion.getPDGCode());
3715 mcg_gd_1_1.set4Vector(PxPyPzEVector(1, 1, 1, 1));
3716 mcg_not_child.setPDG(Const::pion.getPDGCode());
3717 mcg_not_child.set4Vector(PxPyPzEVector(10, 10, 10, 10));
3718
3719 mcg_d_0.comesFrom(mcg_m);
3720 mcg_d_1.comesFrom(mcg_m);
3721 mcg_gd_0_0.comesFrom(mcg_d_0);
3722 mcg_gd_0_1.comesFrom(mcg_d_0);
3723 mcg_gd_1_0.comesFrom(mcg_d_1);
3724 mcg_gd_1_1.comesFrom(mcg_d_1);
3725
3726 mcGraph.generateList();
3727
3728 // Get MC Particles from StoreArray
3729 auto* mc_not_child = mcParticles[0];
3730 auto* mc_m = mcParticles[1];
3731 auto* mc_d_0 = mcParticles[2];
3732 auto* mc_d_1 = mcParticles[3];
3733 auto* mc_gd_0_0 = mcParticles[4];
3734 auto* mc_gd_0_1 = mcParticles[5];
3735 auto* mc_gd_1_0 = mcParticles[6];
3736 auto* mc_gd_1_1 = mcParticles[7];
3737
3738
3739 mc_m->setStatus(MCParticle::c_PrimaryParticle);
3740 mc_d_0->setStatus(MCParticle::c_PrimaryParticle);
3741 mc_d_1->setStatus(MCParticle::c_PrimaryParticle);
3742 mc_gd_0_0->setStatus(MCParticle::c_PrimaryParticle);
3743 mc_gd_0_1->setStatus(MCParticle::c_PrimaryParticle);
3744 mc_gd_1_0->setStatus(MCParticle::c_PrimaryParticle);
3745 mc_gd_1_1->setStatus(MCParticle::c_PrimaryParticle);
3746 mc_not_child->setStatus(MCParticle::c_PrimaryParticle);
3747
3748 // Creation of D decay: D->K0s(->pi pi) K0s(->pi pi)
3749
3750 const Particle* D_gd_0_0 = particles.appendNew(PxPyPzEVector(0.0, 1, 1, 1), 211);
3751 const Particle* D_gd_0_1 = particles.appendNew(PxPyPzEVector(1.0, 1, 1, 1), -211);
3752 const Particle* D_gd_1_0 = particles.appendNew(PxPyPzEVector(2.0, 1, 1, 1), 211);
3753 const Particle* D_gd_1_1 = particles.appendNew(PxPyPzEVector(3.0, 1, 1, 1), -211);
3754
3755 D_grandDaughterIndices_0.push_back(D_gd_0_0->getArrayIndex());
3756 D_grandDaughterIndices_0.push_back(D_gd_0_1->getArrayIndex());
3757 D_grandDaughterIndices_1.push_back(D_gd_1_0->getArrayIndex());
3758 D_grandDaughterIndices_1.push_back(D_gd_1_1->getArrayIndex());
3759 momentum_0 = D_gd_0_0->get4Vector() + D_gd_0_1->get4Vector();
3760 momentum_1 = D_gd_1_0->get4Vector() + D_gd_1_1->get4Vector();
3761
3762
3763 const Particle* D_d_0 = particles.appendNew(momentum_0, 310, Particle::c_Unflavored, D_grandDaughterIndices_0);
3764 const Particle* D_d_1 = particles.appendNew(momentum_1, 310, Particle::c_Unflavored, D_grandDaughterIndices_1);
3765
3766
3767 momentum = D_d_0->get4Vector() + D_d_1->get4Vector();
3768 D_daughterIndices.push_back(D_d_0->getArrayIndex());
3769 D_daughterIndices.push_back(D_d_1->getArrayIndex());
3770
3771 const Particle* D_m = particles.appendNew(momentum, 421, Particle::c_Unflavored, D_daughterIndices);
3772 DList->addParticle(D_m);
3773
3774 // Particle that is not an child
3775 const Particle* not_child = particles.appendNew(PxPyPzEVector(5.0, 1, 1, 1), 211);
3776
3777 // Particle that is not an child and doesn't have MC particle
3778 const Particle* not_child_2 = particles.appendNew(PxPyPzEVector(6.0, 1, 1, 1), 211);
3779
3780 // MC matching
3781 D_gd_0_0->addRelationTo(mc_gd_0_0);
3782 D_gd_0_1->addRelationTo(mc_gd_0_1);
3783 D_gd_1_0->addRelationTo(mc_gd_1_0);
3784 D_gd_1_1->addRelationTo(mc_gd_1_1);
3785 D_d_0->addRelationTo(mc_d_0);
3786 D_d_1->addRelationTo(mc_d_1);
3787 D_m->addRelationTo(mc_m);
3788 not_child->addRelationTo(mc_not_child);
3789
3790 // All pions should have common D mother
3791 const Manager::Var* var_d = Manager::Instance().getVariable("varForFirstMCAncestorOfType(D0, mdstIndex)");
3792 ASSERT_NE(var_d, nullptr);
3793 EXPECT_TRUE(std::get<double>(var_d->function(D_gd_0_0)) >= 0);
3794 EXPECT_FLOAT_EQ(std::get<double>(var_d->function(D_gd_0_0)), std::get<double>(var_d->function(D_gd_0_1)));
3795 EXPECT_FLOAT_EQ(std::get<double>(var_d->function(D_gd_1_0)), std::get<double>(var_d->function(D_gd_1_1)));
3796 EXPECT_FLOAT_EQ(std::get<double>(var_d->function(D_gd_0_0)), std::get<double>(var_d->function(D_gd_1_0)));
3797 EXPECT_FLOAT_EQ(std::get<double>(var_d->function(D_gd_0_1)), std::get<double>(var_d->function(D_gd_1_1)));
3798 EXPECT_TRUE(std::isnan(std::get<double>(var_d->function(not_child))));
3799 EXPECT_TRUE(std::isnan(std::get<double>(var_d->function(not_child_2))));
3800
3801
3802 // // All but they have different K0s mothers
3803 const Manager::Var* var_310 = Manager::Instance().getVariable("varForFirstMCAncestorOfType(310, mdstIndex)");
3804 ASSERT_NE(var_310, nullptr);
3805 EXPECT_FLOAT_EQ(std::get<double>(var_310->function(D_gd_0_0)), std::get<double>(var_310->function(D_gd_0_1)));
3806 EXPECT_FLOAT_EQ(std::get<double>(var_310->function(D_gd_1_0)), std::get<double>(var_310->function(D_gd_1_1)));
3807 EXPECT_NE(std::get<double>(var_310->function(D_gd_0_0)), std::get<double>(var_310->function(D_gd_1_0)));
3808 EXPECT_NE(std::get<double>(var_310->function(D_gd_0_1)), std::get<double>(var_310->function(D_gd_1_1)));
3809 EXPECT_TRUE(std::isnan(std::get<double>(var_310->function(not_child))));
3810 EXPECT_TRUE(std::isnan(std::get<double>(var_310->function(not_child_2))));
3811 EXPECT_FLOAT_EQ(int(std::get<double>(Manager::Instance().getVariable("varForFirstMCAncestorOfType(310, E)")->function(D_gd_0_0))),
3812 10);
3813 }
3814
3815 TEST_F(MetaVariableTest, isDescendantOfList)
3816 {
3818 StoreObjPtr<ParticleList> DList("D0:vartest");
3819 DList.registerInDataStore();
3820 DList.create();
3821 DList->initialize(421, "D0:vartest");
3822 StoreObjPtr<ParticleList> BList("B:vartest");
3823 BList.registerInDataStore();
3824 BList.create();
3825 BList->initialize(521, "B:vartest");
3827
3828 PxPyPzEVector momentum;
3829 PxPyPzEVector momentum_0;
3830 PxPyPzEVector momentum_1;
3831 StoreArray<Particle> particles;
3832 std::vector<int> D_daughterIndices;
3833 std::vector<int> D_grandDaughterIndices_0;
3834 std::vector<int> D_grandDaughterIndices_1;
3835 std::vector<int> B_daughterIndices;
3836 std::vector<int> B_grandDaughterIndices;
3837 std::vector<int> B_grandGrandDaughterIndices;
3838
3839 // Creation of D decay: D->K0s(->pi pi) K0s(->pi pi)
3840
3841 const Particle* D_gd_0_0 = particles.appendNew(PxPyPzEVector(0.0, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 0);
3842 const Particle* D_gd_0_1 = particles.appendNew(PxPyPzEVector(1.0, 1, 1, 1), -211, Particle::c_Flavored, Particle::c_Track, 1);
3843 const Particle* D_gd_1_0 = particles.appendNew(PxPyPzEVector(2.0, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 2);
3844 const Particle* D_gd_1_1 = particles.appendNew(PxPyPzEVector(3.0, 1, 1, 1), -211, Particle::c_Flavored, Particle::c_Track, 3);
3845
3846 D_grandDaughterIndices_0.push_back(D_gd_0_0->getArrayIndex());
3847 D_grandDaughterIndices_0.push_back(D_gd_0_1->getArrayIndex());
3848 D_grandDaughterIndices_1.push_back(D_gd_1_0->getArrayIndex());
3849 D_grandDaughterIndices_1.push_back(D_gd_1_1->getArrayIndex());
3850 momentum_0 = D_gd_0_0->get4Vector() + D_gd_0_1->get4Vector();
3851 momentum_1 = D_gd_1_0->get4Vector() + D_gd_1_1->get4Vector();
3852
3853
3854 const Particle* D_d_0 = particles.appendNew(momentum_0, 310, Particle::c_Unflavored, D_grandDaughterIndices_0);
3855 const Particle* D_d_1 = particles.appendNew(momentum_1, 310, Particle::c_Unflavored, D_grandDaughterIndices_1);
3856
3857
3858 momentum = D_d_0->get4Vector() + D_d_1->get4Vector();
3859 D_daughterIndices.push_back(D_d_0->getArrayIndex());
3860 D_daughterIndices.push_back(D_d_1->getArrayIndex());
3861
3862 const Particle* D_m = particles.appendNew(momentum, 421, Particle::c_Unflavored, D_daughterIndices);
3863 DList->addParticle(D_m);
3864
3865 // Creation of B decay B -> D(->K0s(->pi pi) pi) pi
3866
3867 const Particle* B_d_1 = particles.appendNew(PxPyPzEVector(0.0, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 4);
3868 const Particle* B_gd_0_1 = particles.appendNew(PxPyPzEVector(1.0, 1, 1, 1), -211, Particle::c_Flavored, Particle::c_Track, 5);
3869 const Particle* B_ggd_0_0_0 = particles.appendNew(PxPyPzEVector(2.0, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 6);
3870 const Particle* B_ggd_0_0_1 = particles.appendNew(PxPyPzEVector(3.0, 1, 1, 1), -211, Particle::c_Flavored, Particle::c_Track, 7);
3871
3872 B_grandGrandDaughterIndices.push_back(B_ggd_0_0_0->getArrayIndex());
3873 B_grandGrandDaughterIndices.push_back(B_ggd_0_0_1->getArrayIndex());
3874 momentum_0 = B_ggd_0_0_0->get4Vector() + B_ggd_0_0_1->get4Vector();
3875 const Particle* B_gd_0_0 = particles.appendNew(momentum_0, 310, Particle::c_Unflavored, B_grandGrandDaughterIndices);
3876
3877 B_grandDaughterIndices.push_back(B_gd_0_0->getArrayIndex());
3878 B_grandDaughterIndices.push_back(B_gd_0_1->getArrayIndex());
3879 momentum_1 = B_gd_0_0->get4Vector() + B_gd_0_1->get4Vector();
3880 const Particle* B_d_0 = particles.appendNew(momentum_1, -411, Particle::c_Unflavored, B_grandDaughterIndices);
3881
3882 B_daughterIndices.push_back(B_d_0->getArrayIndex());
3883 B_daughterIndices.push_back(B_d_1->getArrayIndex());
3884 momentum = B_d_0->get4Vector() + B_d_1->get4Vector();
3885 const Particle* B_m = particles.appendNew(momentum, 521, Particle::c_Unflavored, B_daughterIndices);
3886 BList->addParticle(B_m);
3887
3888 // Particle that is not an child
3889 const Particle* not_child = particles.appendNew(PxPyPzEVector(5.0, 1, 1, 1), 211, Particle::c_Flavored, Particle::c_Track, 8);
3890
3891
3892 const Manager::Var* var_0 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest)");
3893 ASSERT_NE(var_0, nullptr);
3894 EXPECT_TRUE(std::get<bool>(var_0->function(D_gd_0_0)));
3895 EXPECT_TRUE(std::get<bool>(var_0->function(D_gd_0_1)));
3896 EXPECT_TRUE(std::get<bool>(var_0->function(D_gd_1_0)));
3897 EXPECT_TRUE(std::get<bool>(var_0->function(D_gd_1_1)));
3898 EXPECT_TRUE(std::get<bool>(var_0->function(D_d_0)));
3899 EXPECT_TRUE(std::get<bool>(var_0->function(D_d_1)));
3900 EXPECT_FALSE(std::get<bool>(var_0->function(B_ggd_0_0_0)));
3901 EXPECT_FALSE(std::get<bool>(var_0->function(B_ggd_0_0_1)));
3902 EXPECT_FALSE(std::get<bool>(var_0->function(B_gd_0_0)));
3903 EXPECT_FALSE(std::get<bool>(var_0->function(B_gd_0_1)));
3904 EXPECT_FALSE(std::get<bool>(var_0->function(B_d_0)));
3905 EXPECT_FALSE(std::get<bool>(var_0->function(B_d_1)));
3906 EXPECT_FALSE(std::get<bool>(var_0->function(not_child)));
3907
3908 const Manager::Var* var_0a = Manager::Instance().getVariable("isDaughterOfList(D0:vartest)");
3909 ASSERT_NE(var_0a, nullptr);
3910 EXPECT_FALSE(std::get<bool>(var_0a->function(D_gd_0_0)));
3911 EXPECT_FALSE(std::get<bool>(var_0a->function(D_gd_0_1)));
3912 EXPECT_FALSE(std::get<bool>(var_0a->function(D_gd_1_0)));
3913 EXPECT_FALSE(std::get<bool>(var_0a->function(D_gd_1_1)));
3914 EXPECT_TRUE(std::get<bool>(var_0a->function(D_d_0)));
3915 EXPECT_TRUE(std::get<bool>(var_0a->function(D_d_1)));
3916 EXPECT_FALSE(std::get<bool>(var_0a->function(B_ggd_0_0_0)));
3917 EXPECT_FALSE(std::get<bool>(var_0a->function(B_ggd_0_0_1)));
3918 EXPECT_FALSE(std::get<bool>(var_0a->function(B_gd_0_0)));
3919 EXPECT_FALSE(std::get<bool>(var_0a->function(B_gd_0_1)));
3920 EXPECT_FALSE(std::get<bool>(var_0a->function(B_d_0)));
3921 EXPECT_FALSE(std::get<bool>(var_0a->function(B_d_1)));
3922 EXPECT_FALSE(std::get<bool>(var_0a->function(not_child)));
3923
3924 const Manager::Var* var_0b = Manager::Instance().getVariable("isGrandDaughterOfList(D0:vartest)");
3925 ASSERT_NE(var_0b, nullptr);
3926 EXPECT_TRUE(std::get<bool>(var_0b->function(D_gd_0_0)));
3927 EXPECT_TRUE(std::get<bool>(var_0b->function(D_gd_0_1)));
3928 EXPECT_TRUE(std::get<bool>(var_0b->function(D_gd_1_0)));
3929 EXPECT_TRUE(std::get<bool>(var_0b->function(D_gd_1_1)));
3930 EXPECT_FALSE(std::get<bool>(var_0b->function(D_d_0)));
3931 EXPECT_FALSE(std::get<bool>(var_0b->function(D_d_1)));
3932 EXPECT_FALSE(std::get<bool>(var_0b->function(B_ggd_0_0_0)));
3933 EXPECT_FALSE(std::get<bool>(var_0b->function(B_ggd_0_0_1)));
3934 EXPECT_FALSE(std::get<bool>(var_0b->function(B_gd_0_0)));
3935 EXPECT_FALSE(std::get<bool>(var_0b->function(B_gd_0_1)));
3936 EXPECT_FALSE(std::get<bool>(var_0b->function(B_d_0)));
3937 EXPECT_FALSE(std::get<bool>(var_0b->function(B_d_1)));
3938 EXPECT_FALSE(std::get<bool>(var_0b->function(not_child)));
3939
3940 const Manager::Var* var_1 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, 1)");
3941 ASSERT_NE(var_1, nullptr);
3942 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_0_0)));
3943 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_0_1)));
3944 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_1_0)));
3945 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_1_1)));
3946 EXPECT_TRUE(std::get<bool>(var_1->function(D_d_0)));
3947 EXPECT_TRUE(std::get<bool>(var_1->function(D_d_1)));
3948 EXPECT_FALSE(std::get<bool>(var_1->function(B_ggd_0_0_0)));
3949 EXPECT_FALSE(std::get<bool>(var_1->function(B_ggd_0_0_1)));
3950 EXPECT_FALSE(std::get<bool>(var_1->function(B_gd_0_0)));
3951 EXPECT_FALSE(std::get<bool>(var_1->function(B_gd_0_1)));
3952 EXPECT_FALSE(std::get<bool>(var_1->function(B_d_0)));
3953 EXPECT_FALSE(std::get<bool>(var_1->function(B_d_1)));
3954 EXPECT_FALSE(std::get<bool>(var_1->function(not_child)));
3955
3956 const Manager::Var* var_2 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, 2)");
3957 ASSERT_NE(var_2, nullptr);
3958 EXPECT_TRUE(std::get<bool>(var_2->function(D_gd_0_0)));
3959 EXPECT_TRUE(std::get<bool>(var_2->function(D_gd_0_1)));
3960 EXPECT_TRUE(std::get<bool>(var_2->function(D_gd_1_0)));
3961 EXPECT_TRUE(std::get<bool>(var_2->function(D_gd_1_1)));
3962 EXPECT_FALSE(std::get<bool>(var_2->function(D_d_0)));
3963 EXPECT_FALSE(std::get<bool>(var_2->function(D_d_1)));
3964 EXPECT_FALSE(std::get<bool>(var_2->function(B_ggd_0_0_0)));
3965 EXPECT_FALSE(std::get<bool>(var_2->function(B_ggd_0_0_1)));
3966 EXPECT_FALSE(std::get<bool>(var_2->function(B_gd_0_0)));
3967 EXPECT_FALSE(std::get<bool>(var_2->function(B_gd_0_1)));
3968 EXPECT_FALSE(std::get<bool>(var_2->function(B_d_0)));
3969 EXPECT_FALSE(std::get<bool>(var_2->function(B_d_1)));
3970 EXPECT_FALSE(std::get<bool>(var_2->function(not_child)));
3971
3972 const Manager::Var* var_3 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, B:vartest)");
3973 ASSERT_NE(var_3, nullptr);
3974 EXPECT_TRUE(std::get<bool>(var_3->function(D_gd_0_0)));
3975 EXPECT_TRUE(std::get<bool>(var_3->function(D_gd_0_1)));
3976 EXPECT_TRUE(std::get<bool>(var_3->function(D_gd_1_0)));
3977 EXPECT_TRUE(std::get<bool>(var_3->function(D_gd_1_1)));
3978 EXPECT_TRUE(std::get<bool>(var_3->function(D_d_0)));
3979 EXPECT_TRUE(std::get<bool>(var_3->function(D_d_1)));
3980 EXPECT_TRUE(std::get<bool>(var_3->function(B_ggd_0_0_0)));
3981 EXPECT_TRUE(std::get<bool>(var_3->function(B_ggd_0_0_1)));
3982 EXPECT_TRUE(std::get<bool>(var_3->function(B_gd_0_0)));
3983 EXPECT_TRUE(std::get<bool>(var_3->function(B_gd_0_1)));
3984 EXPECT_TRUE(std::get<bool>(var_3->function(B_d_0)));
3985 EXPECT_TRUE(std::get<bool>(var_3->function(B_d_1)));
3986 EXPECT_FALSE(std::get<bool>(var_3->function(not_child)));
3987
3988 const Manager::Var* var_4 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, B:vartest, -1)");
3989 ASSERT_NE(var_4, nullptr);
3990 EXPECT_TRUE(std::get<bool>(var_4->function(D_gd_0_0)));
3991 EXPECT_TRUE(std::get<bool>(var_4->function(D_gd_0_1)));
3992 EXPECT_TRUE(std::get<bool>(var_4->function(D_gd_1_0)));
3993 EXPECT_TRUE(std::get<bool>(var_4->function(D_gd_1_1)));
3994 EXPECT_TRUE(std::get<bool>(var_4->function(D_d_0)));
3995 EXPECT_TRUE(std::get<bool>(var_4->function(D_d_1)));
3996 EXPECT_TRUE(std::get<bool>(var_4->function(B_ggd_0_0_0)));
3997 EXPECT_TRUE(std::get<bool>(var_4->function(B_ggd_0_0_1)));
3998 EXPECT_TRUE(std::get<bool>(var_4->function(B_gd_0_0)));
3999 EXPECT_TRUE(std::get<bool>(var_4->function(B_gd_0_1)));
4000 EXPECT_TRUE(std::get<bool>(var_4->function(B_d_0)));
4001 EXPECT_TRUE(std::get<bool>(var_4->function(B_d_1)));
4002 EXPECT_FALSE(std::get<bool>(var_4->function(not_child)));
4003
4004 const Manager::Var* var_5 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, B:vartest, 1)");
4005 ASSERT_NE(var_5, nullptr);
4006 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_0_0)));
4007 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_0_1)));
4008 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_1_0)));
4009 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_1_1)));
4010 EXPECT_TRUE(std::get<bool>(var_5->function(D_d_0)));
4011 EXPECT_TRUE(std::get<bool>(var_5->function(D_d_1)));
4012 EXPECT_FALSE(std::get<bool>(var_5->function(B_ggd_0_0_0)));
4013 EXPECT_FALSE(std::get<bool>(var_5->function(B_ggd_0_0_1)));
4014 EXPECT_FALSE(std::get<bool>(var_5->function(B_gd_0_0)));
4015 EXPECT_FALSE(std::get<bool>(var_5->function(B_gd_0_1)));
4016 EXPECT_TRUE(std::get<bool>(var_5->function(B_d_0)));
4017 EXPECT_TRUE(std::get<bool>(var_5->function(B_d_1)));
4018 EXPECT_FALSE(std::get<bool>(var_5->function(not_child)));
4019
4020 const Manager::Var* var_6 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, B:vartest, 2)");
4021 ASSERT_NE(var_6, nullptr);
4022 EXPECT_TRUE(std::get<bool>(var_6->function(D_gd_0_0)));
4023 EXPECT_TRUE(std::get<bool>(var_6->function(D_gd_0_1)));
4024 EXPECT_TRUE(std::get<bool>(var_6->function(D_gd_1_0)));
4025 EXPECT_TRUE(std::get<bool>(var_6->function(D_gd_1_1)));
4026 EXPECT_FALSE(std::get<bool>(var_6->function(D_d_0)));
4027 EXPECT_FALSE(std::get<bool>(var_6->function(D_d_1)));
4028 EXPECT_FALSE(std::get<bool>(var_6->function(B_ggd_0_0_0)));
4029 EXPECT_FALSE(std::get<bool>(var_6->function(B_ggd_0_0_1)));
4030 EXPECT_TRUE(std::get<bool>(var_6->function(B_gd_0_0)));
4031 EXPECT_TRUE(std::get<bool>(var_6->function(B_gd_0_1)));
4032 EXPECT_FALSE(std::get<bool>(var_6->function(B_d_0)));
4033 EXPECT_FALSE(std::get<bool>(var_6->function(B_d_1)));
4034 EXPECT_FALSE(std::get<bool>(var_6->function(not_child)));
4035
4036 const Manager::Var* var_7 = Manager::Instance().getVariable("isDescendantOfList(D0:vartest, B:vartest, 3)");
4037 ASSERT_NE(var_7, nullptr);
4038 EXPECT_FALSE(std::get<bool>(var_7->function(D_gd_0_0)));
4039 EXPECT_FALSE(std::get<bool>(var_7->function(D_gd_0_1)));
4040 EXPECT_FALSE(std::get<bool>(var_7->function(D_gd_1_0)));
4041 EXPECT_FALSE(std::get<bool>(var_7->function(D_gd_1_1)));
4042 EXPECT_FALSE(std::get<bool>(var_7->function(D_d_0)));
4043 EXPECT_FALSE(std::get<bool>(var_7->function(D_d_1)));
4044 EXPECT_TRUE(std::get<bool>(var_7->function(B_ggd_0_0_0)));
4045 EXPECT_TRUE(std::get<bool>(var_7->function(B_ggd_0_0_1)));
4046 EXPECT_FALSE(std::get<bool>(var_7->function(B_gd_0_0)));
4047 EXPECT_FALSE(std::get<bool>(var_7->function(B_gd_0_1)));
4048 EXPECT_FALSE(std::get<bool>(var_7->function(B_d_0)));
4049 EXPECT_FALSE(std::get<bool>(var_7->function(B_d_1)));
4050 EXPECT_FALSE(std::get<bool>(var_7->function(not_child)));
4051 }
4052
4053
4054 TEST_F(MetaVariableTest, isMCDescendantOfList)
4055 {
4057 StoreArray<MCParticle> mcParticles;
4058 StoreArray<Particle> particles;
4059 particles.registerInDataStore();
4060 mcParticles.registerInDataStore();
4061 particles.registerRelationTo(mcParticles);
4062 StoreObjPtr<ParticleList> BList("B:vartest");
4063 BList.registerInDataStore();
4064 BList.create();
4065 BList->initialize(521, "B:vartest");
4066 StoreObjPtr<ParticleList> DList("D0:vartest");
4067 DList.registerInDataStore();
4068 DList.create();
4069 DList->initialize(421, "D0:vartest");
4071 PxPyPzEVector momentum;
4072 PxPyPzEVector momentum_0;
4073 PxPyPzEVector momentum_1;
4074 std::vector<int> daughterIndices;
4075 std::vector<int> grandDaughterIndices;
4076 std::vector<int> grandGrandDaughterIndices;
4077 std::vector<int> D_daughterIndices;
4078 std::vector<int> D_grandDaughterIndices_0;
4079 std::vector<int> D_grandDaughterIndices_1;
4080
4081
4082 // Create MC graph for B+ -> (D -> (K0s -> pi+ + pi-) pi-) + pi+
4083 MCParticleGraph mcGraph;
4084
4086 MCParticleGraph::GraphParticle& mcg_d_0 = mcGraph.addParticle();
4087 MCParticleGraph::GraphParticle& mcg_d_1 = mcGraph.addParticle();
4088 MCParticleGraph::GraphParticle& mcg_gd_0_0 = mcGraph.addParticle();
4089 MCParticleGraph::GraphParticle& mcg_gd_0_1 = mcGraph.addParticle();
4090 MCParticleGraph::GraphParticle& mcg_ggd_0_0_0 = mcGraph.addParticle();
4091 MCParticleGraph::GraphParticle& mcg_ggd_0_0_1 = mcGraph.addParticle();
4092 MCParticleGraph::GraphParticle& mcg_not_child = mcGraph.addParticle();
4093
4094 mcg_m.setPDG(521);
4095 mcg_d_0.setPDG(-411);
4096 mcg_d_1.setPDG(Const::pion.getPDGCode());
4097 mcg_gd_0_0.setPDG(Const::Kshort.getPDGCode());
4098 mcg_gd_0_1.setPDG(-Const::pion.getPDGCode());
4099 mcg_ggd_0_0_0.setPDG(Const::pion.getPDGCode());
4100 mcg_ggd_0_0_1.setPDG(-Const::pion.getPDGCode());
4101 mcg_not_child.setPDG(Const::pion.getPDGCode());
4102
4103 mcg_d_0.comesFrom(mcg_m);
4104 mcg_d_1.comesFrom(mcg_m);
4105 mcg_gd_0_0.comesFrom(mcg_d_0);
4106 mcg_gd_0_1.comesFrom(mcg_d_0);
4107 mcg_ggd_0_0_0.comesFrom(mcg_gd_0_1);
4108 mcg_ggd_0_0_1.comesFrom(mcg_gd_0_1);
4109
4110 mcGraph.generateList();
4111
4112 // Get MC Particles from StoreArray
4113 auto* mc_m = mcParticles[0];
4114 auto* mc_d_0 = mcParticles[1];
4115 auto* mc_d_1 = mcParticles[2];
4116 auto* mc_gd_0_0 = mcParticles[3];
4117 auto* mc_gd_0_1 = mcParticles[4];
4118 auto* mc_ggd_0_0_0 = mcParticles[5];
4119 auto* mc_ggd_0_0_1 = mcParticles[6];
4120 auto* mc_not_child = mcParticles[7];
4121
4122 mc_m->setStatus(MCParticle::c_PrimaryParticle);
4123 mc_d_0->setStatus(MCParticle::c_PrimaryParticle);
4124 mc_d_1->setStatus(MCParticle::c_PrimaryParticle);
4125 mc_gd_0_0->setStatus(MCParticle::c_PrimaryParticle);
4126 mc_gd_0_1->setStatus(MCParticle::c_PrimaryParticle);
4127 mc_ggd_0_0_0->setStatus(MCParticle::c_PrimaryParticle);
4128 mc_ggd_0_0_1->setStatus(MCParticle::c_PrimaryParticle);
4129 mc_not_child->setStatus(MCParticle::c_PrimaryParticle);
4130
4131 // Creation of D decay: D->K0s(->pi pi) K0s(->pi pi) (not matched)
4132
4133 const Particle* D_gd_0_0 = particles.appendNew(PxPyPzEVector(0.0, 1, 1, 1), 211);
4134 const Particle* D_gd_0_1 = particles.appendNew(PxPyPzEVector(1.0, 1, 1, 1), -211);
4135 const Particle* D_gd_1_0 = particles.appendNew(PxPyPzEVector(2.0, 1, 1, 1), 211);
4136 const Particle* D_gd_1_1 = particles.appendNew(PxPyPzEVector(3.0, 1, 1, 1), -211);
4137
4138 D_grandDaughterIndices_0.push_back(D_gd_0_0->getArrayIndex());
4139 D_grandDaughterIndices_0.push_back(D_gd_0_1->getArrayIndex());
4140 D_grandDaughterIndices_1.push_back(D_gd_1_0->getArrayIndex());
4141 D_grandDaughterIndices_1.push_back(D_gd_1_1->getArrayIndex());
4142 momentum_0 = D_gd_0_0->get4Vector() + D_gd_0_1->get4Vector();
4143 momentum_1 = D_gd_1_0->get4Vector() + D_gd_1_1->get4Vector();
4144
4145
4146 const Particle* D_d_0 = particles.appendNew(momentum_0, 310, Particle::c_Unflavored, D_grandDaughterIndices_0);
4147 const Particle* D_d_1 = particles.appendNew(momentum_1, 310, Particle::c_Unflavored, D_grandDaughterIndices_1);
4148
4149
4150 momentum = D_d_0->get4Vector() + D_d_1->get4Vector();
4151 D_daughterIndices.push_back(D_d_0->getArrayIndex());
4152 D_daughterIndices.push_back(D_d_1->getArrayIndex());
4153
4154 const Particle* D_m = particles.appendNew(momentum, 421, Particle::c_Unflavored, D_daughterIndices);
4155 DList->addParticle(D_m);
4156
4157 // Creating B decay
4158 const Particle* d_1 = particles.appendNew(PxPyPzEVector(0.0, 1, 1, 1), 211);
4159 const Particle* gd_0_1 = particles.appendNew(PxPyPzEVector(1.0, 1, 1, 1), -211);
4160 const Particle* ggd_0_0_0 = particles.appendNew(PxPyPzEVector(2.0, 1, 1, 1), 211);
4161 const Particle* ggd_0_0_1 = particles.appendNew(PxPyPzEVector(3.0, 1, 1, 1), -211);
4162
4163 grandGrandDaughterIndices.push_back(ggd_0_0_0->getArrayIndex());
4164 grandGrandDaughterIndices.push_back(ggd_0_0_1->getArrayIndex());
4165 momentum_0 = ggd_0_0_0->get4Vector() + ggd_0_0_1->get4Vector();
4166 const Particle* gd_0_0 = particles.appendNew(momentum_0, 310, Particle::c_Unflavored, grandGrandDaughterIndices);
4167
4168 grandDaughterIndices.push_back(gd_0_0->getArrayIndex());
4169 grandDaughterIndices.push_back(gd_0_1->getArrayIndex());
4170 momentum_1 = gd_0_0->get4Vector() + gd_0_1->get4Vector();
4171 const Particle* d_0 = particles.appendNew(momentum_1, -411, Particle::c_Unflavored, grandDaughterIndices);
4172
4173 daughterIndices.push_back(d_0->getArrayIndex());
4174 daughterIndices.push_back(d_1->getArrayIndex());
4175 momentum = d_0->get4Vector() + d_1->get4Vector();
4176 const Particle* m = particles.appendNew(momentum, 521, Particle::c_Unflavored, daughterIndices);
4177 BList->addParticle(m);
4178
4179 // Particle that is not an child
4180 const Particle* not_child = particles.appendNew(PxPyPzEVector(5.0, 1, 1, 1), 211);
4181
4182 // Particle that is not an child and doesn't have MC particle
4183 const Particle* not_child_2 = particles.appendNew(PxPyPzEVector(6.0, 1, 1, 1), 211);
4184
4185 gd_0_0->addRelationTo(mc_gd_0_0);
4186 gd_0_1->addRelationTo(mc_gd_0_1);
4187 ggd_0_0_0->addRelationTo(mc_ggd_0_0_0);
4188 ggd_0_0_1->addRelationTo(mc_ggd_0_0_1);
4189 d_0->addRelationTo(mc_d_0);
4190 d_1->addRelationTo(mc_d_1);
4191 m->addRelationTo(mc_m);
4192 not_child->addRelationTo(mc_not_child);
4193
4194 const Manager::Var* var_0 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest)");
4195 ASSERT_NE(var_0, nullptr);
4196 EXPECT_FALSE(std::get<bool>(var_0->function(D_gd_0_0)));
4197 EXPECT_FALSE(std::get<bool>(var_0->function(D_gd_0_1)));
4198 EXPECT_FALSE(std::get<bool>(var_0->function(D_gd_1_0)));
4199 EXPECT_FALSE(std::get<bool>(var_0->function(D_gd_1_1)));
4200 EXPECT_FALSE(std::get<bool>(var_0->function(D_d_0)));
4201 EXPECT_FALSE(std::get<bool>(var_0->function(D_d_1)));
4202 EXPECT_TRUE(std::get<bool>(var_0->function(ggd_0_0_0)));
4203 EXPECT_TRUE(std::get<bool>(var_0->function(ggd_0_0_1)));
4204 EXPECT_TRUE(std::get<bool>(var_0->function(gd_0_0)));
4205 EXPECT_TRUE(std::get<bool>(var_0->function(gd_0_1)));
4206 EXPECT_TRUE(std::get<bool>(var_0->function(d_0)));
4207 EXPECT_TRUE(std::get<bool>(var_0->function(d_1)));
4208 EXPECT_FALSE(std::get<bool>(var_0->function(not_child)));
4209 EXPECT_FALSE(std::get<bool>(var_0->function(not_child_2)));
4210
4211 const Manager::Var* var_1 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest, D0:vartest)");
4212 ASSERT_NE(var_1, nullptr);
4213 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_0_0)));
4214 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_0_1)));
4215 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_1_0)));
4216 EXPECT_FALSE(std::get<bool>(var_1->function(D_gd_1_1)));
4217 EXPECT_FALSE(std::get<bool>(var_1->function(D_d_0)));
4218 EXPECT_FALSE(std::get<bool>(var_1->function(D_d_1)));
4219 EXPECT_TRUE(std::get<bool>(var_1->function(ggd_0_0_0)));
4220 EXPECT_TRUE(std::get<bool>(var_1->function(ggd_0_0_1)));
4221 EXPECT_TRUE(std::get<bool>(var_1->function(gd_0_0)));
4222 EXPECT_TRUE(std::get<bool>(var_1->function(gd_0_1)));
4223 EXPECT_TRUE(std::get<bool>(var_1->function(d_0)));
4224 EXPECT_TRUE(std::get<bool>(var_1->function(d_1)));
4225 EXPECT_FALSE(std::get<bool>(var_1->function(not_child)));
4226 EXPECT_FALSE(std::get<bool>(var_1->function(not_child_2)));
4227
4228 const Manager::Var* var_2 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest, -1)");
4229 ASSERT_NE(var_2, nullptr);
4230 EXPECT_FALSE(std::get<bool>(var_2->function(D_gd_0_0)));
4231 EXPECT_FALSE(std::get<bool>(var_2->function(D_gd_0_1)));
4232 EXPECT_FALSE(std::get<bool>(var_2->function(D_gd_1_0)));
4233 EXPECT_FALSE(std::get<bool>(var_2->function(D_gd_1_1)));
4234 EXPECT_FALSE(std::get<bool>(var_2->function(D_d_0)));
4235 EXPECT_FALSE(std::get<bool>(var_2->function(D_d_1)));
4236 EXPECT_TRUE(std::get<bool>(var_2->function(ggd_0_0_0)));
4237 EXPECT_TRUE(std::get<bool>(var_2->function(ggd_0_0_1)));
4238 EXPECT_TRUE(std::get<bool>(var_2->function(gd_0_0)));
4239 EXPECT_TRUE(std::get<bool>(var_2->function(gd_0_1)));
4240 EXPECT_TRUE(std::get<bool>(var_2->function(d_0)));
4241 EXPECT_TRUE(std::get<bool>(var_2->function(d_1)));
4242 EXPECT_FALSE(std::get<bool>(var_2->function(not_child)));
4243 EXPECT_FALSE(std::get<bool>(var_2->function(not_child_2)));
4244
4245 const Manager::Var* var_3 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest, 1)");
4246 ASSERT_NE(var_3, nullptr);
4247 EXPECT_FALSE(std::get<bool>(var_3->function(D_gd_0_0)));
4248 EXPECT_FALSE(std::get<bool>(var_3->function(D_gd_0_1)));
4249 EXPECT_FALSE(std::get<bool>(var_3->function(D_gd_1_0)));
4250 EXPECT_FALSE(std::get<bool>(var_3->function(D_gd_1_1)));
4251 EXPECT_FALSE(std::get<bool>(var_3->function(D_d_0)));
4252 EXPECT_FALSE(std::get<bool>(var_3->function(D_d_1)));
4253 EXPECT_FALSE(std::get<bool>(var_3->function(ggd_0_0_0)));
4254 EXPECT_FALSE(std::get<bool>(var_3->function(ggd_0_0_1)));
4255 EXPECT_FALSE(std::get<bool>(var_3->function(gd_0_0)));
4256 EXPECT_FALSE(std::get<bool>(var_3->function(gd_0_1)));
4257 EXPECT_TRUE(std::get<bool>(var_3->function(d_0)));
4258 EXPECT_TRUE(std::get<bool>(var_3->function(d_1)));
4259 EXPECT_FALSE(std::get<bool>(var_3->function(not_child)));
4260 EXPECT_FALSE(std::get<bool>(var_3->function(not_child_2)));
4261
4262 const Manager::Var* var_4 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest, 2)");
4263 ASSERT_NE(var_4, nullptr);
4264 EXPECT_FALSE(std::get<bool>(var_4->function(D_gd_0_0)));
4265 EXPECT_FALSE(std::get<bool>(var_4->function(D_gd_0_1)));
4266 EXPECT_FALSE(std::get<bool>(var_4->function(D_gd_1_0)));
4267 EXPECT_FALSE(std::get<bool>(var_4->function(D_gd_1_1)));
4268 EXPECT_FALSE(std::get<bool>(var_4->function(D_d_0)));
4269 EXPECT_FALSE(std::get<bool>(var_4->function(D_d_1)));
4270 EXPECT_FALSE(std::get<bool>(var_4->function(ggd_0_0_0)));
4271 EXPECT_FALSE(std::get<bool>(var_4->function(ggd_0_0_1)));
4272 EXPECT_TRUE(std::get<bool>(var_4->function(gd_0_0)));
4273 EXPECT_TRUE(std::get<bool>(var_4->function(gd_0_1)));
4274 EXPECT_FALSE(std::get<bool>(var_4->function(d_0)));
4275 EXPECT_FALSE(std::get<bool>(var_4->function(d_1)));
4276 EXPECT_FALSE(std::get<bool>(var_4->function(not_child)));
4277 EXPECT_FALSE(std::get<bool>(var_4->function(not_child_2)));
4278
4279
4280 const Manager::Var* var_5 = Manager::Instance().getVariable("isMCDescendantOfList(B:vartest, 3)");
4281 ASSERT_NE(var_5, nullptr);
4282 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_0_0)));
4283 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_0_1)));
4284 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_1_0)));
4285 EXPECT_FALSE(std::get<bool>(var_5->function(D_gd_1_1)));
4286 EXPECT_FALSE(std::get<bool>(var_5->function(D_d_0)));
4287 EXPECT_FALSE(std::get<bool>(var_5->function(D_d_1)));
4288 EXPECT_TRUE(std::get<bool>(var_5->function(ggd_0_0_0)));
4289 EXPECT_TRUE(std::get<bool>(var_5->function(ggd_0_0_1)));
4290 EXPECT_FALSE(std::get<bool>(var_5->function(gd_0_0)));
4291 EXPECT_FALSE(std::get<bool>(var_5->function(gd_0_1)));
4292 EXPECT_FALSE(std::get<bool>(var_5->function(d_0)));
4293 EXPECT_FALSE(std::get<bool>(var_5->function(d_1)));
4294 EXPECT_FALSE(std::get<bool>(var_5->function(not_child)));
4295 EXPECT_FALSE(std::get<bool>(var_5->function(not_child_2)));
4296 }
4297
4298
4299
4300
4301
4302 class PIDVariableTest : public ::testing::Test {
4303 protected:
4305 void SetUp() override
4306 {
4310 StoreArray<MCParticle> mcparticles;
4311 StoreArray<PIDLikelihood> likelihood;
4312 StoreArray<Particle> particles;
4313 StoreArray<Track> tracks;
4314 peim.registerInDataStore();
4315 tfrs.registerInDataStore();
4316 mcparticles.registerInDataStore();
4317 likelihood.registerInDataStore();
4318 particles.registerInDataStore();
4319 tracks.registerInDataStore();
4320 particles.registerRelationTo(likelihood);
4321 tracks.registerRelationTo(likelihood);
4323 }
4324
4326 void TearDown() override
4327 {
4329 }
4330 };
4331
4332 TEST_F(PIDVariableTest, LogLikelihood)
4333 {
4334 StoreArray<PIDLikelihood> likelihood;
4335 StoreArray<Particle> particles;
4336 StoreArray<Track> tracks;
4338
4339 // create tracks and trackFitResutls
4340 TRandom3 generator;
4341 const float pValue = 0.5;
4342 const float bField = 1.5;
4343 const int charge = 1;
4344 TMatrixDSym cov6(6);
4345 // Generate a random put orthogonal pair of vectors in the r-phi plane
4346 ROOT::Math::Cartesian2D d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
4347 ROOT::Math::Cartesian2D pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
4348 d.SetXY(d.X(), -(d.X()*pt.X()) / pt.Y());
4349 // Add a random z component
4350 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
4351 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
4352
4353 auto CDCValue = static_cast<unsigned long long int>(0x300000000000000);
4354 tfrs.appendNew(position, momentum, cov6, charge, Const::electron, pValue, bField, CDCValue, 16777215, 0);
4355 Track mytrack;
4357 Track* allTrack = tracks.appendNew(mytrack);
4358 Track* noSVDTrack = tracks.appendNew(mytrack);
4359 Track* noPIDTrack = tracks.appendNew(mytrack);
4360 Track* dEdxTrack = tracks.appendNew(mytrack);
4361
4362 // Fill by hand likelihood values for all the detectors and hypothesis
4363 // This is clearly not a physical case, since a particle cannot leave good
4364 // signals in both TOP and ARICH
4365 auto* lAll = likelihood.appendNew();
4366 lAll->setLogLikelihood(Const::TOP, Const::electron, 0.18);
4367 lAll->setLogLikelihood(Const::ARICH, Const::electron, 0.16);
4368 lAll->setLogLikelihood(Const::ECL, Const::electron, 0.14);
4369 lAll->setLogLikelihood(Const::CDC, Const::electron, 0.12);
4370 lAll->setLogLikelihood(Const::SVD, Const::electron, 0.1);
4371 lAll->setLogLikelihood(Const::KLM, Const::electron, 0.01);
4372
4373 lAll->setLogLikelihood(Const::TOP, Const::muon, 0.5);
4374 lAll->setLogLikelihood(Const::ARICH, Const::muon, 0.52);
4375 lAll->setLogLikelihood(Const::ECL, Const::muon, 0.54);
4376 lAll->setLogLikelihood(Const::CDC, Const::muon, 0.56);
4377 lAll->setLogLikelihood(Const::SVD, Const::muon, 0.58);
4378 lAll->setLogLikelihood(Const::KLM, Const::muon, 0.8);
4379
4380 lAll->setLogLikelihood(Const::TOP, Const::pion, 0.2);
4381 lAll->setLogLikelihood(Const::ARICH, Const::pion, 0.22);
4382 lAll->setLogLikelihood(Const::ECL, Const::pion, 0.24);
4383 lAll->setLogLikelihood(Const::CDC, Const::pion, 0.26);
4384 lAll->setLogLikelihood(Const::SVD, Const::pion, 0.28);
4385 lAll->setLogLikelihood(Const::KLM, Const::pion, 0.2);
4386
4387 lAll->setLogLikelihood(Const::TOP, Const::kaon, 0.3);
4388 lAll->setLogLikelihood(Const::ARICH, Const::kaon, 0.32);
4389 lAll->setLogLikelihood(Const::ECL, Const::kaon, 0.34);
4390 lAll->setLogLikelihood(Const::CDC, Const::kaon, 0.36);
4391 lAll->setLogLikelihood(Const::SVD, Const::kaon, 0.38);
4392 lAll->setLogLikelihood(Const::KLM, Const::kaon, 0.2);
4393
4394 lAll->setLogLikelihood(Const::TOP, Const::proton, 0.4);
4395 lAll->setLogLikelihood(Const::ARICH, Const::proton, 0.42);
4396 lAll->setLogLikelihood(Const::ECL, Const::proton, 0.44);
4397 lAll->setLogLikelihood(Const::CDC, Const::proton, 0.46);
4398 lAll->setLogLikelihood(Const::SVD, Const::proton, 0.48);
4399 lAll->setLogLikelihood(Const::KLM, Const::proton, 0.02);
4400
4401 lAll->setLogLikelihood(Const::TOP, Const::deuteron, 0.6);
4402 lAll->setLogLikelihood(Const::ARICH, Const::deuteron, 0.62);
4403 lAll->setLogLikelihood(Const::ECL, Const::deuteron, 0.64);
4404 lAll->setLogLikelihood(Const::CDC, Const::deuteron, 0.66);
4405 lAll->setLogLikelihood(Const::SVD, Const::deuteron, 0.68);
4406 lAll->setLogLikelihood(Const::KLM, Const::deuteron, 0.02);
4407
4408 // Likelihoods for all detectors but SVD
4409 auto* lAllNoSVD = likelihood.appendNew();
4410
4411 for (const auto& det : Const::PIDDetectorSet::set()) {
4412 for (const auto& hypo : Const::chargedStableSet) {
4413 if (det != Const::SVD) {
4414 lAllNoSVD->setLogLikelihood(det, hypo, lAll->getLogL(hypo, det));
4415 }
4416 }
4417 }
4418
4419 // Likelihoods for a dEdx only case
4420 auto* ldEdx = likelihood.appendNew();
4421 ldEdx->setLogLikelihood(Const::CDC, Const::electron, 0.12);
4422 ldEdx->setLogLikelihood(Const::SVD, Const::electron, 0.1);
4423
4424 ldEdx->setLogLikelihood(Const::CDC, Const::pion, 0.26);
4425 ldEdx->setLogLikelihood(Const::SVD, Const::pion, 0.28);
4426
4427 ldEdx->setLogLikelihood(Const::CDC, Const::kaon, 0.36);
4428 ldEdx->setLogLikelihood(Const::SVD, Const::kaon, 0.38);
4429
4430 ldEdx->setLogLikelihood(Const::CDC, Const::proton, 0.46);
4431 ldEdx->setLogLikelihood(Const::SVD, Const::proton, 0.48);
4432
4433 ldEdx->setLogLikelihood(Const::CDC, Const::muon, 0.56);
4434 ldEdx->setLogLikelihood(Const::SVD, Const::muon, 0.58);
4435
4436 ldEdx->setLogLikelihood(Const::CDC, Const::deuteron, 0.66);
4437 ldEdx->setLogLikelihood(Const::SVD, Const::deuteron, 0.68);
4438
4439 allTrack->addRelationTo(lAll);
4440 noSVDTrack->addRelationTo(lAllNoSVD);
4441 dEdxTrack->addRelationTo(ldEdx);
4442
4443 // Table with the sum(LogL) for several cases
4444 // All dEdx AllNoSVD
4445 // e 0.71 0.22 0.61
4446 // mu 3.5 1.14 2.92
4447 // pi 1.4 0.54 1.12
4448 // k 1.9 0.74 1.52
4449 // p 2.22 0.94 1.74
4450 // d 3.22 1.34 2.54
4451
4452 auto* particleAll = particles.appendNew(allTrack, Const::pion);
4453 auto* particleNoSVD = particles.appendNew(noSVDTrack, Const::pion);
4454 auto* particledEdx = particles.appendNew(dEdxTrack, Const::pion);
4455 auto* particleNoID = particles.appendNew(noPIDTrack, Const::pion);
4456
4457 double numsumexp = std::exp(0.71) + std::exp(3.5) + std::exp(1.4) + std::exp(1.9) + std::exp(2.22) + std::exp(3.22);
4458 double numsumexp_noSVD = std::exp(0.61) + std::exp(2.92) + std::exp(1.12) + std::exp(1.52) + std::exp(1.74) + std::exp(2.54);
4459
4460 // Basic PID quantities. Currently just wrappers for global probability.
4461 EXPECT_FLOAT_EQ(electronID(particleAll), std::exp(0.71) / numsumexp);
4462 EXPECT_FLOAT_EQ(muonID(particleAll), std::exp(3.5) / numsumexp);
4463 EXPECT_FLOAT_EQ(pionID(particleAll), std::exp(1.4) / numsumexp);
4464 EXPECT_FLOAT_EQ(kaonID(particleAll), std::exp(1.9) / numsumexp);
4465 EXPECT_FLOAT_EQ(protonID(particleAll), std::exp(2.22) / numsumexp);
4466 EXPECT_FLOAT_EQ(deuteronID(particleAll), std::exp(3.22) / numsumexp);
4467
4468 // smart PID that takes the hypothesis into account
4469 auto* particleElectron = particles.appendNew(allTrack, Const::electron);
4470 auto* particleMuon = particles.appendNew(allTrack, Const::muon);
4471 auto* particleKaon = particles.appendNew(allTrack, Const::kaon);
4472 auto* particleProton = particles.appendNew(allTrack, Const::proton);
4473 auto* particleDeuteron = particles.appendNew(allTrack, Const::deuteron);
4474
4475 EXPECT_FLOAT_EQ(particleID(particleAll), std::exp(1.4) / numsumexp); // there's already a pion
4476 EXPECT_FLOAT_EQ(particleID(particleElectron), std::exp(0.71) / numsumexp);
4477 EXPECT_FLOAT_EQ(particleID(particleMuon), std::exp(3.5) / numsumexp);
4478 EXPECT_FLOAT_EQ(particleID(particleKaon), std::exp(1.9) / numsumexp);
4479 EXPECT_FLOAT_EQ(particleID(particleProton), std::exp(2.22) / numsumexp);
4480 EXPECT_FLOAT_EQ(particleID(particleDeuteron), std::exp(3.22) / numsumexp);
4481
4482 // TEMP: PID w/o the SVD.
4483 EXPECT_FLOAT_EQ(electronID_noSVD(particleNoSVD), std::exp(0.61) / numsumexp_noSVD);
4484 EXPECT_FLOAT_EQ(muonID_noSVD(particleNoSVD), std::exp(2.92) / numsumexp_noSVD);
4485 EXPECT_FLOAT_EQ(pionID_noSVD(particleNoSVD), std::exp(1.12) / numsumexp_noSVD);
4486 EXPECT_FLOAT_EQ(kaonID_noSVD(particleNoSVD), std::exp(1.52) / numsumexp_noSVD);
4487 EXPECT_FLOAT_EQ(protonID_noSVD(particleNoSVD), std::exp(1.74) / numsumexp_noSVD);
4488 EXPECT_FLOAT_EQ(deuteronID_noSVD(particleNoSVD), std::exp(2.54) / numsumexp_noSVD);
4489
4490 // Binary PID
4491 std::vector<double> v_pi_K {211., 321.};
4492 std::vector<double> v_pi_p {211., 2212.};
4493 std::vector<double> v_K_p {321., 2212.};
4494 EXPECT_FLOAT_EQ(binaryPID(particleAll, v_pi_K), std::exp(1.4) / (std::exp(1.4) + std::exp(1.9)));
4495 EXPECT_FLOAT_EQ(binaryPID(particleAll, v_pi_p), std::exp(1.4) / (std::exp(1.4) + std::exp(2.22)));
4496 EXPECT_FLOAT_EQ(binaryPID(particleAll, v_K_p), std::exp(1.9) / (std::exp(1.9) + std::exp(2.22)));
4497
4498 // Check what happens if no Likelihood is available
4499 EXPECT_TRUE(std::isnan(electronID(particleNoID)));
4500 EXPECT_TRUE(std::isnan(muonID(particleNoID)));
4501 EXPECT_TRUE(std::isnan(pionID(particleNoID)));
4502 EXPECT_TRUE(std::isnan(kaonID(particleNoID)));
4503 EXPECT_TRUE(std::isnan(protonID(particleNoID)));
4504 EXPECT_TRUE(std::isnan(deuteronID(particleNoID)));
4505
4506 //expert stuff: LogL values
4507 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidLogLikelihoodValueExpert(11, TOP)")->function(particleAll)),
4508 0.18);
4509 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidLogLikelihoodValueExpert(11, ALL)")->function(particleAll)),
4510 0.71);
4511 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidLogLikelihoodValueExpert(2212, TOP, CDC)")->function(
4512 particleAll)), 0.86);
4513
4514 // global probability
4515 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(1000010020, ALL)")->function(particleAll)),
4516 std::exp(3.22) / numsumexp);
4517 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(2212, ALL)")->function(particleAll)),
4518 std::exp(2.22) / numsumexp);
4519 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, ALL)")->function(particleAll)),
4520 std::exp(1.4) / numsumexp);
4521 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(321, ALL)")->function(particleAll)),
4522 std::exp(1.9) / numsumexp);
4523 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(13, ALL)")->function(particleAll)),
4524 std::exp(3.5) / numsumexp);
4525 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(11, ALL)")->function(particleAll)),
4526 std::exp(0.71) / numsumexp);
4527 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, ALL)")->function(particledEdx)),
4528 std::exp(0.54) / (std::exp(0.22) + std::exp(1.14) + std::exp(0.54) + std::exp(0.74) + std::exp(0.94) + std::exp(1.34)));
4529 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, ALL)")->function(particledEdx)),
4530 std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, CDC, SVD)")->function(particleAll)));
4531 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, CDC)")->function(particledEdx)),
4532 std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(211, CDC)")->function(particleAll)));
4533 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidProbabilityExpert(321, CDC)")->function(particleAll)),
4534 std::exp(0.36) / (std::exp(0.12) + std::exp(0.26) + std::exp(0.36) + std::exp(0.46) + std::exp(0.56) + std::exp(0.66)));
4535
4536 // binary probability
4537 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, ALL)")->function(
4538 particleAll)),
4539 1.0 / (1.0 + std::exp(2.22 - 1.9)));
4540 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, ALL)")->function(
4541 particledEdx)),
4542 1.0 / (1.0 + std::exp(0.94 - 0.74)));
4543 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, CDC, SVD)")->function(
4544 particleAll)),
4545 1.0 / (1.0 + std::exp(0.94 - 0.74)));
4546
4547 // No likelihood available
4548 EXPECT_TRUE(std::isnan(std::get<double>(Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, KLM)")->function(
4549 particledEdx))));
4550 EXPECT_TRUE(std::isnan(std::get<double>(Manager::Instance().getVariable("pidLogLikelihoodValueExpert(11, TOP, CDC, SVD)")->function(
4551 particleNoID))));
4552 EXPECT_TRUE(std::isnan(std::get<double>(Manager::Instance().getVariable("pidLogLikelihoodValueExpert(11, TOP)")->function(
4553 particledEdx))));
4554 EXPECT_TRUE(std::isnan(std::get<double>(Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, KLM)")->function(
4555 particledEdx))));
4556 EXPECT_TRUE(std::isnan(std::get<double>
4557 (Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, ECL, TOP, ARICH)")->function(
4558 particledEdx))));
4559 EXPECT_FALSE(std::isnan(std::get<double>
4560 (Manager::Instance().getVariable("pidPairProbabilityExpert(321, 2212, ECL, TOP, ARICH, SVD)")->function(
4561 particledEdx))));
4562 //Mostlikely PDG tests:
4563 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG()")->function(particledEdx)), 1.00001e+09);
4564 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0.5, 0.1, 0.1, 0.1, 0.1, 0.1)")->function(
4565 particledEdx)),
4566 Const::electron.getPDGCode());
4567 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0.1, 0.5, 0.1, 0.1, 0.1, 0.1)")->function(
4568 particledEdx)),
4569 Const::muon.getPDGCode());
4570 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0.1, 0.1, 0.5, 0.1, 0.1, 0.1)")->function(
4571 particledEdx)),
4572 Const::pion.getPDGCode());
4573 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0.1, 0.1, 0.1, 0.5, 0.1, 0.1)")->function(
4574 particledEdx)),
4575 Const::kaon.getPDGCode());
4576 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0.1, 0.1, 0.1, 0.1, 0.5, 0.1)")->function(
4577 particledEdx)),
4578 Const::proton.getPDGCode());
4579 EXPECT_FLOAT_EQ(std::get<double>(Manager::Instance().getVariable("pidMostLikelyPDG(0, 1., 0, 0, 0, 0)")->function(particledEdx)),
4580 Const::muon.getPDGCode());
4581 }
4582
4583 TEST_F(PIDVariableTest, MissingLikelihood)
4584 {
4585 StoreArray<PIDLikelihood> likelihood;
4586 StoreArray<Particle> particles;
4587 StoreArray<Track> tracks;
4589
4590 // create tracks and trackFitResutls
4591 TRandom3 generator;
4592 const float pValue = 0.5;
4593 const float bField = 1.5;
4594 const int charge = 1;
4595 TMatrixDSym cov6(6);
4596 // Generate a random put orthogonal pair of vectors in the r-phi plane
4597 ROOT::Math::Cartesian2D d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
4598 ROOT::Math::Cartesian2D pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
4599 d.SetXY(d.X(), -(d.X()*pt.X()) / pt.Y());
4600 // Add a random z component
4601 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
4602 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
4603
4604 auto CDCValue = static_cast<unsigned long long int>(0x300000000000000);
4605 tfrs.appendNew(position, momentum, cov6, charge, Const::electron, pValue, bField, CDCValue, 16777215, 0);
4606 Track mytrack;
4608 Track* savedTrack1 = tracks.appendNew(mytrack);
4609 Track* savedTrack2 = tracks.appendNew(mytrack);
4610 Track* savedTrack3 = tracks.appendNew(mytrack);
4611 Track* savedTrack4 = tracks.appendNew(mytrack);
4612
4613 auto* l1 = likelihood.appendNew();
4614 l1->setLogLikelihood(Const::TOP, Const::electron, 0.18);
4615 l1->setLogLikelihood(Const::ECL, Const::electron, 0.14);
4616 savedTrack1->addRelationTo(l1);
4617
4618 auto* electron = particles.appendNew(savedTrack1, Const::electron);
4619
4620 auto* l2 = likelihood.appendNew();
4621 l2->setLogLikelihood(Const::TOP, Const::pion, 0.2);
4622 l2->setLogLikelihood(Const::ARICH, Const::pion, 0.22);
4623 l2->setLogLikelihood(Const::ECL, Const::pion, 0.24);
4624 l2->setLogLikelihood(Const::CDC, Const::pion, 0.26);
4625 l2->setLogLikelihood(Const::SVD, Const::pion, 0.28);
4626 savedTrack2->addRelationTo(l2);
4627
4628 auto* pion = particles.appendNew(savedTrack2, Const::pion);
4629
4630 auto* l3 = likelihood.appendNew();
4631 l3->setLogLikelihood(Const::TOP, Const::kaon, 0.3);
4632 l3->setLogLikelihood(Const::ARICH, Const::kaon, 0.32);
4633 savedTrack3->addRelationTo(l3);
4634
4635 auto* kaon = particles.appendNew(savedTrack3, Const::kaon);
4636
4637 auto* l4 = likelihood.appendNew();
4638 l4->setLogLikelihood(Const::ARICH, Const::proton, 0.42);
4639 l4->setLogLikelihood(Const::ECL, Const::proton, 0.44);
4640 l4->setLogLikelihood(Const::CDC, Const::proton, 0.46);
4641 l4->setLogLikelihood(Const::SVD, Const::proton, 0.48);
4642 savedTrack4->addRelationTo(l4);
4643
4644 auto* proton = particles.appendNew(savedTrack4, Const::proton);
4645
4646 const Manager::Var* varMissECL = Manager::Instance().getVariable("pidMissingProbabilityExpert(ECL)");
4647 const Manager::Var* varMissTOP = Manager::Instance().getVariable("pidMissingProbabilityExpert(TOP)");
4648 const Manager::Var* varMissARICH = Manager::Instance().getVariable("pidMissingProbabilityExpert(ARICH)");
4649
4650
4651 EXPECT_FLOAT_EQ(std::get<double>(varMissTOP->function(electron)), 0.0);
4652 EXPECT_FLOAT_EQ(std::get<double>(varMissTOP->function(pion)), 0.0);
4653 EXPECT_FLOAT_EQ(std::get<double>(varMissTOP->function(kaon)), 0.0);
4654 EXPECT_FLOAT_EQ(std::get<double>(varMissTOP->function(proton)), 1.0);
4655
4656 EXPECT_FLOAT_EQ(std::get<double>(varMissARICH->function(electron)), 1.0);
4657 EXPECT_FLOAT_EQ(std::get<double>(varMissARICH->function(pion)), 0.0);
4658 EXPECT_FLOAT_EQ(std::get<double>(varMissARICH->function(kaon)), 0.0);
4659 EXPECT_FLOAT_EQ(std::get<double>(varMissARICH->function(proton)), 0.0);
4660
4661 EXPECT_FLOAT_EQ(std::get<double>(varMissECL->function(electron)), 0.0);
4662 EXPECT_FLOAT_EQ(std::get<double>(varMissECL->function(pion)), 0.0);
4663 EXPECT_FLOAT_EQ(std::get<double>(varMissECL->function(kaon)), 1.0);
4664 EXPECT_FLOAT_EQ(std::get<double>(varMissECL->function(proton)), 0.0);
4665 }
4666
4667 class FlightInfoTest : public ::testing::Test {
4668 protected:
4670 void SetUp() override
4671 {
4675 StoreArray<MCParticle> mcParticles;
4676 StoreArray<Particle> particles;
4677 particles.registerRelationTo(mcParticles);
4680
4681
4682 // Insert MC particle logic here
4683 MCParticle mcKs;
4684 mcKs.setPDG(Const::Kshort.getPDGCode());
4685 mcKs.setProductionVertex(1.0, 1.0, 0.0);
4686 mcKs.setDecayVertex(4.0, 5.0, 0.0);
4687 mcKs.setProductionTime(0);
4688 mcKs.setMassFromPDG();
4689 mcKs.setMomentum(1.164, 1.55200, 0);
4690 float decayTime = 5 * mcKs.getMass() / mcKs.getEnergy();
4691 mcKs.setDecayTime(decayTime);
4693 MCParticle* newMCKs = mcParticles.appendNew(mcKs);
4694
4695
4696
4697 MCParticle mcDp;
4698 mcDp.setPDG(411);
4699 mcDp.setDecayVertex(1.0, 1.0, 0.0);
4700 mcDp.setMassFromPDG();
4702 MCParticle* newMCDp = mcParticles.appendNew(mcDp);
4703
4704 // Insert Reco particle logic here
4705 PxPyPzEVector momentum;
4706 TMatrixFSym error(7);
4707 error.Zero();
4708 error(0, 0) = 0.05;
4709 error(1, 1) = 0.2;
4710 error(2, 2) = 0.4;
4711 error(3, 3) = 0.01;
4712 error(4, 4) = 0.04;
4713 error(5, 5) = 0.00875;
4714 error(6, 6) = 0.01;
4715 Particle pi(PxPyPzEVector(1.59607, 1.19705, 0, 2), 211);
4716 momentum += pi.get4Vector();
4717 Particle* newpi = particles.appendNew(pi);
4718
4719
4720 Particle Ks(PxPyPzEVector(1.164, 1.55200, 0, 2), 310, Particle::c_Unflavored, Particle::c_Composite, 0);
4721 Ks.setVertex(XYZVector(4.0, 5.0, 0.0));
4722 Ks.setMomentumVertexErrorMatrix(error); // (order: px,py,pz,E,x,y,z)
4723 momentum += Ks.get4Vector();
4724 Ks.addExtraInfo("prodVertX", 1.0);
4725 Ks.addExtraInfo("prodVertY", 1.0);
4726 Ks.addExtraInfo("prodVertZ", 0.0);
4727 Ks.addExtraInfo("prodVertSxx", 0.04);
4728 Ks.addExtraInfo("prodVertSxy", 0.0);
4729 Ks.addExtraInfo("prodVertSxz", 0.0);
4730 Ks.addExtraInfo("prodVertSyx", 0.0);
4731 Ks.addExtraInfo("prodVertSyy", 0.00875);
4732 Ks.addExtraInfo("prodVertSyz", 0.0);
4733 Ks.addExtraInfo("prodVertSzx", 0.0);
4734 Ks.addExtraInfo("prodVertSzy", 0.0);
4735 Ks.addExtraInfo("prodVertSzz", 0.01);
4736 Particle* newKs = particles.appendNew(Ks);
4737 newKs->addRelationTo(newMCKs);
4738
4739
4740 Particle Dp(momentum, 411, Particle::c_Flavored, Particle::c_Composite, 0);
4741 Dp.appendDaughter(newpi);
4742 Dp.appendDaughter(newKs);
4743 XYZVector motherVtx(1.0, 1.0, 0.0);
4744 Dp.setVertex(motherVtx);
4745 Dp.setMomentumVertexErrorMatrix(error); // (order: px,py,pz,E,x,y,z)
4746 Dp.addExtraInfo("prodVertX", 0.0);
4747 Dp.addExtraInfo("prodVertY", 1.0);
4748 Dp.addExtraInfo("prodVertZ", -2.0);
4749 Dp.addExtraInfo("prodVertSxx", 0.04);
4750 Dp.addExtraInfo("prodVertSxy", 0.0);
4751 Dp.addExtraInfo("prodVertSxz", 0.0);
4752 Dp.addExtraInfo("prodVertSyx", 0.0);
4753 Dp.addExtraInfo("prodVertSyy", 0.01);
4754 Dp.addExtraInfo("prodVertSyz", 0.0);
4755 Dp.addExtraInfo("prodVertSzx", 0.0);
4756 Dp.addExtraInfo("prodVertSzy", 0.0);
4757 Dp.addExtraInfo("prodVertSzz", 0.1575);
4758 Particle* newDp = particles.appendNew(Dp);
4759 newDp->addRelationTo(newMCDp);
4760
4761 }
4762
4764 void TearDown() override
4765 {
4767 }
4768 };
4769 TEST_F(FlightInfoTest, flightDistance)
4770 {
4771 StoreArray<Particle> particles{};
4772 const Particle* newKs = particles[1]; // Ks had flight distance of 5 cm
4773
4774 const Manager::Var* var = Manager::Instance().getVariable("flightDistance");
4775 ASSERT_NE(var, nullptr);
4776 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 5.0);
4777 }
4778 TEST_F(FlightInfoTest, flightDistanceErr)
4779 {
4780 StoreArray<Particle> particles{};
4781 const Particle* newKs = particles[1]; // Ks had flight distance of 5 cm
4782
4783 const Manager::Var* var = Manager::Instance().getVariable("flightDistanceErr");
4784 ASSERT_NE(var, nullptr);
4785 EXPECT_GT(std::get<double>(var->function(newKs)), 0.0);
4786 }
4787 TEST_F(FlightInfoTest, flightTime)
4788 {
4789 StoreArray<Particle> particles{};
4790 const Particle* newKs = particles[1]; // Ks had flight time of 0.0427 us (t = d/c * m/p)
4791
4792 const Manager::Var* var = Manager::Instance().getVariable("flightTime");
4793 ASSERT_NE(var, nullptr);
4794 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 5.0 / Const::speedOfLight * newKs->getPDGMass() / newKs->getP());
4795 }
4796
4797 TEST_F(FlightInfoTest, flightTimeErr)
4798 {
4799 StoreArray<Particle> particles{};
4800 const Particle* newKs = particles[1]; // Ks should have positive flight distance uncertainty
4801
4802 const Manager::Var* var = Manager::Instance().getVariable("flightTimeErr");
4803 ASSERT_NE(var, nullptr);
4804 EXPECT_GT(std::get<double>(var->function(newKs)), 0.0);
4805 }
4806
4807 TEST_F(FlightInfoTest, flightDistanceOfDaughter)
4808 {
4809 StoreArray<Particle> particles{};
4810 const Particle* newDp = particles[2]; // Get D+, its daughter Ks had flight distance of 5 cm
4811
4812 const Manager::Var* var = Manager::Instance().getVariable("flightDistanceOfDaughter(1)");
4813 ASSERT_NE(var, nullptr);
4814 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 5.0);
4815
4816 var = Manager::Instance().getVariable("flightDistanceOfDaughter(3)");
4817 ASSERT_NE(var, nullptr);
4818 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4819 }
4820 TEST_F(FlightInfoTest, flightDistanceOfDaughterErr)
4821 {
4822 StoreArray<Particle> particles{};
4823 const Particle* newDp = particles[2]; // Get D+, its daughter Ks should have positive flight distance uncertainty
4824
4825 const Manager::Var* var = Manager::Instance().getVariable("flightDistanceOfDaughterErr(1)");
4826 ASSERT_NE(var, nullptr);
4827 EXPECT_GT(std::get<double>(var->function(newDp)), 0.0);
4828
4829 var = Manager::Instance().getVariable("flightDistanceOfDaughterErr(3)");
4830 ASSERT_NE(var, nullptr);
4831 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4832 }
4833 TEST_F(FlightInfoTest, flightTimeOfDaughter)
4834 {
4835 StoreArray<Particle> particles{};
4836 const Particle* newDp = particles[2]; // Get D+, its daughter Ks had flight time of 0.0427 us (t = d/c * m/p)
4837
4838 const Manager::Var* var = Manager::Instance().getVariable("flightTimeOfDaughter(1)");
4839 ASSERT_NE(var, nullptr);
4840 const Particle* Ks = newDp->getDaughter(1);
4841
4842 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 5.0 / Const::speedOfLight * Ks->getPDGMass() / Ks->getP());
4843
4844 var = Manager::Instance().getVariable("flightTimeOfDaughter(3)");
4845 ASSERT_NE(var, nullptr);
4846 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4847 }
4848 TEST_F(FlightInfoTest, flightTimeOfDaughterErr)
4849 {
4850 StoreArray<Particle> particles{};
4851 const Particle* newDp = particles[2]; // Get D+, its daughter Ks should have positive flight time uncertainty
4852
4853 const Manager::Var* var = Manager::Instance().getVariable("flightTimeOfDaughterErr(1)");
4854 ASSERT_NE(var, nullptr);
4855 EXPECT_GT(std::get<double>(var->function(newDp)), 0.0);
4856
4857 var = Manager::Instance().getVariable("flightTimeOfDaughterErr(3)");
4858 ASSERT_NE(var, nullptr);
4859 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4860 }
4861 TEST_F(FlightInfoTest, mcFlightDistanceOfDaughter)
4862 {
4863 StoreArray<Particle> particles{};
4864 const Particle* newDp = particles[2]; // Get D+, its daughter Ks had flight distance of 5 cm
4865
4866 const Manager::Var* var = Manager::Instance().getVariable("mcFlightDistanceOfDaughter(1)");
4867 ASSERT_NE(var, nullptr);
4868
4869 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 5.0);
4870
4871 var = Manager::Instance().getVariable("mcFlightDistanceOfDaughter(3)");
4872 ASSERT_NE(var, nullptr);
4873 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4874 }
4875 TEST_F(FlightInfoTest, mcFlightTimeOfDaughter)
4876 {
4877 StoreArray<Particle> particles{};
4878 const Particle* newDp = particles[2]; // Get D+, its daughter Ks had flight time of 0.0427 us (t = d/c * m/p)
4879
4880 const Manager::Var* var = Manager::Instance().getVariable("mcFlightTimeOfDaughter(1)");
4881 ASSERT_NE(var, nullptr);
4882 auto* Ks = newDp->getDaughter(1)->getRelatedTo<MCParticle>();
4883 // double p = Ks->getMomentum().Mag();
4884 // EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 5.0 / Const::speedOfLight * Ks->getMass() / p);
4885
4886 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), Ks->getLifetime() / Ks->getEnergy()*Ks->getMass());
4887
4888 var = Manager::Instance().getVariable("mcFlightTimeOfDaughter(3)");
4889 ASSERT_NE(var, nullptr);
4890 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4891 }
4892
4893 TEST_F(FlightInfoTest, vertexDistance)
4894 {
4895 StoreArray<Particle> particles{};
4896 const Particle* newKS = particles[1]; // Get KS, as it has both a production and decay vertex
4897
4898 const Manager::Var* var = Manager::Instance().getVariable("vertexDistance");
4899 ASSERT_NE(var, nullptr);
4900 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKS)), 5.0);
4901 }
4902
4903 TEST_F(FlightInfoTest, vertexDistanceError)
4904 {
4905 StoreArray<Particle> particles{};
4906 const Particle* newKS = particles[1]; // Get KS, as it has both a production and decay vertex
4907
4908 const Manager::Var* var = Manager::Instance().getVariable("vertexDistanceErr");
4909 ASSERT_NE(var, nullptr);
4910 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKS)), 0.2);
4911 }
4912
4913 TEST_F(FlightInfoTest, vertexDistanceSignificance)
4914 {
4915 StoreArray<Particle> particles{};
4916 const Particle* newKS = particles[1]; // Get KS, as it has both a production and decay vertex
4917
4918 const Manager::Var* var = Manager::Instance().getVariable("vertexDistanceSignificance");
4919 ASSERT_NE(var, nullptr);
4920 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKS)), 25);
4921 }
4922
4923 TEST_F(FlightInfoTest, vertexDistanceOfDaughter)
4924 {
4925 StoreArray<Particle> particles{};
4926 const Particle* newDp = particles[2]; // Get D+, its daughter KS has both a production and decay vertex
4927
4928 const Manager::Var* var = Manager::Instance().getVariable("vertexDistanceOfDaughter(1, 0)");
4929 ASSERT_NE(var, nullptr);
4930 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 5.0);
4931
4932 var = Manager::Instance().getVariable("vertexDistanceOfDaughter(1)");
4933 ASSERT_NE(var, nullptr);
4934 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 6.0);
4935
4936 var = Manager::Instance().getVariable("vertexDistanceOfDaughter(2)");
4937 ASSERT_NE(var, nullptr);
4938 EXPECT_TRUE(std::isnan(std::get<double>(var->function(newDp))));
4939 }
4940
4941 TEST_F(FlightInfoTest, vertexDistanceOfDaughterError)
4942 {
4943 StoreArray<Particle> particles{};
4944 const Particle* newDp = particles[2]; // Get D+, its daughter KS has both a production and decay vertex
4945
4946 const Manager::Var* var = Manager::Instance().getVariable("vertexDistanceOfDaughterErr(1, 0)");
4947 ASSERT_NE(var, nullptr);
4948 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 0.2);
4949
4950 var = Manager::Instance().getVariable("vertexDistanceOfDaughterErr(1)");
4951 ASSERT_NE(var, nullptr);
4952 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 0.25);
4953 }
4954
4955 TEST_F(FlightInfoTest, vertexDistanceOfDaughterSignificance)
4956 {
4957 StoreArray<Particle> particles{};
4958 const Particle* newDp = particles[2]; // Get D+, its daughter KS has both a production and decay vertex
4959
4960 const Manager::Var* var = Manager::Instance().getVariable("vertexDistanceOfDaughterSignificance(1, 0)");
4961 ASSERT_NE(var, nullptr);
4962 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 25);
4963
4964 var = Manager::Instance().getVariable("vertexDistanceOfDaughterSignificance(1)");
4965 ASSERT_NE(var, nullptr);
4966 EXPECT_FLOAT_EQ(std::get<double>(var->function(newDp)), 24);
4967 }
4968
4969 class VertexVariablesTest : public ::testing::Test {
4970 protected:
4972 void SetUp() override
4973 {
4977 StoreArray<MCParticle> mcParticles;
4978 StoreArray<Particle> particles;
4979 particles.registerRelationTo(mcParticles);
4982
4983
4984 // Insert MC particle logic here
4985 MCParticle mcKs;
4986 mcKs.setPDG(Const::Kshort.getPDGCode());
4987 mcKs.setDecayVertex(4.0, 5.0, 0.0);
4988 mcKs.setProductionVertex(1.0, 2.0, 3.0);
4989 mcKs.setMassFromPDG();
4990 mcKs.setMomentum(1.164, 1.55200, 0);
4992 MCParticle* newMCKs = mcParticles.appendNew(mcKs);
4993
4994 Particle Ks(PxPyPzEVector(1.164, 1.55200, 0, 2), 310);
4995 Ks.setVertex(XYZVector(4.0, 5.0, 0.0));
4996 Ks.addExtraInfo("prodVertX", 1.0);
4997 Ks.addExtraInfo("prodVertY", 2.0);
4998 Ks.addExtraInfo("prodVertZ", 3.0);
4999 Ks.addExtraInfo("prodVertSxx", 0.1);
5000 Ks.addExtraInfo("prodVertSxy", 0.2);
5001 Ks.addExtraInfo("prodVertSxz", 0.3);
5002 Ks.addExtraInfo("prodVertSyx", 0.4);
5003 Ks.addExtraInfo("prodVertSyy", 0.5);
5004 Ks.addExtraInfo("prodVertSyz", 0.6);
5005 Ks.addExtraInfo("prodVertSzx", 0.7);
5006 Ks.addExtraInfo("prodVertSzy", 0.8);
5007 Ks.addExtraInfo("prodVertSzz", 0.9);
5008 Particle* newKs = particles.appendNew(Ks);
5009 newKs->addRelationTo(newMCKs);
5010 }
5011
5013 void TearDown() override
5014 {
5016 }
5017 };
5018
5019 // MC vertex tests
5020 TEST_F(VertexVariablesTest, mcDecayVertexX)
5021 {
5022 StoreArray<Particle> particles{};
5023 const Particle* newKs = particles[0]; // Ks had truth decay x is 4.0
5024
5025 const Manager::Var* var = Manager::Instance().getVariable("mcDecayVertexX");
5026 ASSERT_NE(var, nullptr);
5027 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 4.0);
5028 }
5029
5030 TEST_F(VertexVariablesTest, mcDecayVertexY)
5031 {
5032 StoreArray<Particle> particles{};
5033 const Particle* newKs = particles[0]; // Ks had truth decay y is 5.0
5034
5035 const Manager::Var* var = Manager::Instance().getVariable("mcDecayVertexY");
5036 ASSERT_NE(var, nullptr);
5037 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 5.0);
5038 }
5039
5040 TEST_F(VertexVariablesTest, mcDecayVertexZ)
5041 {
5042 StoreArray<Particle> particles{};
5043 const Particle* newKs = particles[0]; // Ks had truth decay z is 0.0
5044
5045 const Manager::Var* var = Manager::Instance().getVariable("mcDecayVertexZ");
5046 ASSERT_NE(var, nullptr);
5047 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.0);
5048 }
5049
5050
5051 TEST_F(VertexVariablesTest, mcDecayVertexFromIPDistance)
5052 {
5053 StoreArray<Particle> particles{};
5054 const Particle* newKs = particles[0]; // Ks had truth distance of sqrt(41)
5055
5056 const Manager::Var* var = Manager::Instance().getVariable("mcDecayVertexFromIPDistance");
5057 ASSERT_NE(var, nullptr);
5058 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), sqrt(4.0 * 4.0 + 5.0 * 5.0));
5059 }
5060
5061 TEST_F(VertexVariablesTest, mcDecayVertexRho)
5062 {
5063 StoreArray<Particle> particles{};
5064 const Particle* newKs = particles[0]; // Ks had truth rho of sqrt(41)
5065
5066 const Manager::Var* var = Manager::Instance().getVariable("mcDecayVertexRho");
5067 ASSERT_NE(var, nullptr);
5068 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), sqrt(4.0 * 4.0 + 5.0 * 5.0));
5069 }
5070
5071 TEST_F(VertexVariablesTest, mcProductionVertexX)
5072 {
5073 StoreArray<Particle> particles{};
5074 const Particle* newKs = particles[0]; // Ks had production vertex x of 1.0 cm
5075
5076 const Manager::Var* var = Manager::Instance().getVariable("mcProductionVertexX");
5077 ASSERT_NE(var, nullptr);
5078 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 1.0);
5079 }
5080
5081 TEST_F(VertexVariablesTest, mcProductionVertexY)
5082 {
5083 StoreArray<Particle> particles{};
5084 const Particle* newKs = particles[0]; // Ks had production vertex y of 2.0 cm
5085
5086 const Manager::Var* var = Manager::Instance().getVariable("mcProductionVertexY");
5087 ASSERT_NE(var, nullptr);
5088 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 2.0);
5089 }
5090
5091 TEST_F(VertexVariablesTest, mcProductionVertexZ)
5092 {
5093 StoreArray<Particle> particles{};
5094 const Particle* newKs = particles[0]; // Ks had production vertex z of 3.0 cm
5095
5096 const Manager::Var* var = Manager::Instance().getVariable("mcProductionVertexZ");
5097 ASSERT_NE(var, nullptr);
5098 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 3.0);
5099 }
5100
5101 // Production position tests
5102
5103 TEST_F(VertexVariablesTest, prodVertexX)
5104 {
5105 StoreArray<Particle> particles{};
5106 const Particle* newKs = particles[0]; // Ks had production vertex x of 1.0 cm
5107
5108 const Manager::Var* var = Manager::Instance().getVariable("prodVertexX");
5109 ASSERT_NE(var, nullptr);
5110 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 1.0);
5111 }
5112 TEST_F(VertexVariablesTest, prodVertexY)
5113 {
5114 StoreArray<Particle> particles{};
5115 const Particle* newKs = particles[0]; // Ks had production vertex y of 2.0 cm
5116
5117 const Manager::Var* var = Manager::Instance().getVariable("prodVertexY");
5118 ASSERT_NE(var, nullptr);
5119 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 2.0);
5120 }
5121 TEST_F(VertexVariablesTest, prodVertexZ)
5122 {
5123 StoreArray<Particle> particles{};
5124 const Particle* newKs = particles[0]; // Ks had production vertex z of 3.0 cm
5125
5126 const Manager::Var* var = Manager::Instance().getVariable("prodVertexZ");
5127 ASSERT_NE(var, nullptr);
5128 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 3.0);
5129 }
5130
5131 // Production Covariance tests
5132
5133 TEST_F(VertexVariablesTest, prodVertexCov)
5134 {
5135 StoreArray<Particle> particles{};
5136 const Particle* newKs = particles[0]; // Ks had production vertex covariance xx of .1 cm
5137
5138 //const Manager::Var* var = Manager::Instance().getVariable("prodVertexCovXX");
5139 const Manager::Var* var = Manager::Instance().getVariable("prodVertexCov(0,0)");
5140 ASSERT_NE(var, nullptr);
5141 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.1);
5142 var = Manager::Instance().getVariable("prodVertexCov(0,1)");
5143 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.2);
5144 var = Manager::Instance().getVariable("prodVertexCov(0,2)");
5145 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.3);
5146 var = Manager::Instance().getVariable("prodVertexCov(1,0)");
5147 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.4);
5148 var = Manager::Instance().getVariable("prodVertexCov(1,1)");
5149 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.5);
5150 var = Manager::Instance().getVariable("prodVertexCov(1,2)");
5151 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.6);
5152 var = Manager::Instance().getVariable("prodVertexCov(2,0)");
5153 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.7);
5154 var = Manager::Instance().getVariable("prodVertexCov(2,1)");
5155 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.8);
5156 var = Manager::Instance().getVariable("prodVertexCov(2,2)");
5157 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), 0.9);
5158 var = Manager::Instance().getVariable("prodVertexXErr");
5159 ASSERT_NE(var, nullptr);
5160 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), sqrt(0.1));
5161 var = Manager::Instance().getVariable("prodVertexYErr");
5162 ASSERT_NE(var, nullptr);
5163 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), sqrt(0.5));
5164 var = Manager::Instance().getVariable("prodVertexZErr");
5165 ASSERT_NE(var, nullptr);
5166 EXPECT_FLOAT_EQ(std::get<double>(var->function(newKs)), sqrt(0.9));
5167 }
5168
5169 // Tests of ContinuumSuppressionVariables
5170
5171 TEST_F(MetaVariableTest, KSFWVariables)
5172 {
5173 // simple tests that do not require the ROE builder nor the CS builder
5174
5175 // check that garbage input throws helpful B2FATAL
5176 EXPECT_B2FATAL(Manager::Instance().getVariable("KSFWVariables(NONSENSE)"));
5177
5178 // check for NaN if we don't have a CS object for this particle
5179 StoreArray<Particle> myParticles;
5180 const Particle* particle_with_no_cs = myParticles.appendNew();
5181 const Manager::Var* var = Manager::Instance().getVariable("KSFWVariables(mm2)");
5182 EXPECT_TRUE(std::isnan(std::get<double>(var->function(particle_with_no_cs))));
5183
5184 // check that FS1 set as third argument, throws a B2ERROR
5185 EXPECT_B2ERROR(Manager::Instance().getVariable("KSFWVariables(et, mask, FS1)"));
5186 }
5187
5188 TEST_F(MetaVariableTest, CleoConeCS)
5189 {
5190 // simple tests that do not require the ROE builder nor the CS builder
5191
5192 // check that garbage input throws helpful B2FATAL
5193 EXPECT_B2FATAL(Manager::Instance().getVariable("CleoConeCS(NONSENSE)"));
5194
5195 // check for NaN if we don't have a CS object for this particle
5196 StoreArray<Particle> myParticles;
5197 const Particle* particle_with_no_cs = myParticles.appendNew();
5198 const Manager::Var* var = Manager::Instance().getVariable("CleoConeCS(0)");
5199 EXPECT_TRUE(std::isnan(std::get<double>(var->function(particle_with_no_cs))));
5200
5201 // check that string other than ROE as second argument, which is interpreted as mask name, returns NaN
5202 var = Manager::Instance().getVariable("CleoConeCS(0, NOTROE)");
5203 EXPECT_TRUE(std::isnan(std::get<double>(var->function(particle_with_no_cs))));
5204
5205 // check that ROE set as third argument, throws a B2ERROR
5206 EXPECT_B2ERROR(Manager::Instance().getVariable("CleoConeCS(0, mask, ROE)"));
5207 }
5208
5209 TEST_F(MetaVariableTest, TransformedNetworkOutput)
5210 {
5211 // check that garbage input throws helpful B2FATAL
5212 EXPECT_B2FATAL(Manager::Instance().getVariable("transformedNetworkOutput(NONSENSE)"));
5213
5214 // check that helpful B2FATAL is thrown if second or third argument is not a double
5215 EXPECT_B2FATAL(Manager::Instance().getVariable("transformedNetworkOutput(NONEXISTENT, 0, NOTDOUBLE)"));
5216 EXPECT_B2FATAL(Manager::Instance().getVariable("transformedNetworkOutput(NONEXISTENT, NOTDOUBLE, 1)"));
5217
5218 // check for NaN if network output variable does not exist (no matter whether particle is provided or not)
5219 StoreArray<Particle> myParticles;
5220 const Particle* particle = myParticles.appendNew();
5221 const Manager::Var* var = Manager::Instance().getVariable("transformedNetworkOutput(NONEXISTENT, 0, 1)");
5222 EXPECT_TRUE(std::isnan(std::get<double>(var->function(particle))));
5223 StoreObjPtr<EventExtraInfo> eventExtraInfo;
5224 if (not eventExtraInfo.isValid())
5225 eventExtraInfo.create();
5226 var = Manager::Instance().getVariable("transformedNetworkOutput(NONEXISTENT, 0, 1)");
5227 EXPECT_TRUE(std::isnan(std::get<double>(var->function(nullptr))));
5228 }
5229}
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:589
int getPDGCode() const
PDG code.
Definition: Const.h:473
static DetectorSet set()
Accessor for the set of valid detector IDs.
Definition: Const.h:333
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 ChargedStable pion
charged pion particle
Definition: Const.h:661
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:678
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
static const ChargedStable proton
proton particle
Definition: Const.h:663
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:677
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:662
static const ParticleType photon
photon particle
Definition: Const.h:673
static const ChargedStable electron
electron particle
Definition: Const.h:659
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:664
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
ECL cluster data.
Definition: ECLCluster.h:27
void setTheta(double theta)
Set Theta of Shower (radian).
Definition: ECLCluster.h:217
void setPhi(double phi)
Set Phi of Shower (radian).
Definition: ECLCluster.h:220
void setClusterId(int clusterid)
Set cluster id.
Definition: ECLCluster.h:145
void setHypothesis(EHypothesisBit hypothesis)
Set hypotheses.
Definition: ECLCluster.h:123
void setEnergy(double energy)
Set Corrected Energy (GeV).
Definition: ECLCluster.h:226
void setR(double r)
Set R (in cm).
Definition: ECLCluster.h:223
Singleton class responsible for loading detector parameters from an XML file.
Definition: Gearbox.h:34
Class to represent Particle data in graph.
void comesFrom(GraphParticle &mother)
Tells the graph that this particle is a decay product of mother.
Class to build, validate and sort a particle decay chain.
void generateList(const std::string &name="", int options=c_setNothing)
Generates the MCParticle list and stores it in the StoreArray with the given name.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
float getEnergy() const
Return particle energy in GeV.
Definition: MCParticle.h:147
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
void setDecayTime(float time)
Set decay time.
Definition: MCParticle.h:390
void setMass(float mass)
Set particle mass.
Definition: MCParticle.h:366
void setDecayVertex(const ROOT::Math::XYZVector &vertex)
Set decay vertex.
Definition: MCParticle.h:447
float getMass() const
Return the particle mass in GeV.
Definition: MCParticle.h:135
void setProductionVertex(const ROOT::Math::XYZVector &vertex)
Set production vertex position.
Definition: MCParticle.h:396
ROOT::Math::PxPyPzEVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:207
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:335
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:438
void setMomentum(const ROOT::Math::XYZVector &momentum)
Set particle momentum.
Definition: MCParticle.h:417
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:346
void setProductionTime(float time)
Set production time.
Definition: MCParticle.h:384
void setMassFromPDG()
Sets the mass for the particle from the particle's PDG code.
Definition: MCParticle.cc:28
Class to hold Lorentz transformations from/to CMS and boost vector.
double getCMSEnergy() const
Returns CMS energy of e+e- (aka.
const ROOT::Math::LorentzRotation rotateLabToCms() const
Returns Lorentz transformation from Lab to CMS.
static ROOT::Math::PxPyPzMVector cmsToLab(const ROOT::Math::PxPyPzMVector &vec)
Transforms Lorentz vector into Laboratory System.
const ROOT::Math::LorentzRotation rotateCmsToLab() const
Returns Lorentz transformation from CMS to Lab.
Class to store reconstructed particles.
Definition: Particle.h:75
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:676
void setVertex(const ROOT::Math::XYZVector &vertex)
Sets position (decay vertex)
Definition: Particle.h:295
double getEnergy() const
Returns total energy.
Definition: Particle.h:535
double getPDGMass(void) const
Returns uncertainty on the invariant mass (requires valid momentum error matrix)
Definition: Particle.cc:604
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:547
void addExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1336
void setPValue(double pValue)
Sets chi^2 probability of fit.
Definition: Particle.h:366
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:95
@ c_Flavored
Is either particle or antiparticle.
Definition: Particle.h:96
double getP() const
Returns momentum magnitude (same as getMomentumMagnitude but with shorter name)
Definition: Particle.h:578
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
Definition: Particle.cc:631
double getMass() const
Returns invariant mass (= nominal for FS particles)
Definition: Particle.h:507
static const ReferenceFrame & GetCurrent()
Get current rest frame.
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.
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
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
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
void clear() override
Delete all entries in this array.
Definition: StoreArray.h:207
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
Class that bundles various TrackFitResults.
Definition: Track.h:25
void setTrackFitResultIndex(const Const::ChargedStable &chargedStable, short index)
Set an index (for positive values) or unavailability-code (index = -1) for a specific mass hypothesis...
Definition: Track.h:174
The Unit class.
Definition: Unit.h:40
A template class to apply the reference frame.
Object holding information for V0s.
Definition: V0.h:34
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:57
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:25
static Gearbox & getInstance()
Return reference to the Gearbox instance.
Definition: Gearbox.cc:81
GraphParticle & addParticle()
Add new particle to the graph.
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Definition: EvtPDLUtil.cc:44
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:24
STL namespace.
A variable returning a floating-point value for a given Particle.
Definition: Manager.h:146
FunctionPtr function
Pointer to function.
Definition: Manager.h:147