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