12#include <gtest/gtest.h>
14#include <Math/Cartesian2D.h>
16#include <analysis/ParticleCombiner/ParticleCombiner.h>
19#include <analysis/VariableManager/Manager.h>
20#include <analysis/dataobjects/Particle.h>
21#include <analysis/dataobjects/ParticleList.h>
24#include <mdst/dataobjects/ECLCluster.h>
25#include <mdst/dataobjects/KLMCluster.h>
26#include <mdst/dataobjects/Track.h>
29#include <framework/datastore/StoreArray.h>
30#include <framework/datastore/StoreObjPtr.h>
31#include <framework/utilities/TestHelpers.h>
32#include <framework/gearbox/Const.h>
33#include <framework/gearbox/Gearbox.h>
36using namespace Belle2::Variable;
41 class ECLVariableTest :
public ::testing::Test {
51 particles.registerInDataStore();
55 tracks.registerInDataStore();
62 tracks.registerRelationTo(eclclusters);
68 tracks.appendNew(
Track());
73 tracks.appendNew(
Track());
74 tracks.appendNew(
Track());
79 auto CDCValue =
static_cast<unsigned long long int>(0x300000000000000);
81 for (
int i = 0; i < tracks.getEntries(); ++i) {
82 int charge = (i % 2 == 0) ? +1 : -1;
83 ROOT::Math::Cartesian2D d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
84 ROOT::Math::Cartesian2D pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
85 d.SetXY(d.X(), -(d.X()*pt.X()) / pt.Y());
86 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
87 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
88 trackFits.
appendNew(position, momentum, cov6, charge,
Const::pion, 0.5, 1.5, CDCValue, 16777215, 0);
117 e3->
addHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron);
131 t1->addRelationTo(e4);
138 t2->addRelationTo(e5);
145 t3->addRelationTo(e6);
154 void TearDown()
override
160 TEST_F(ECLVariableTest, b2bKinematicsTest)
169 gearbox.setBackends({std::string(
"file:")});
171 gearbox.open(
"geometry/Belle2.xml",
false);
181 gammalist->initialize(22, gammalist.getName());
184 for (
int i = 0; i < eclclusters.
getEntries(); ++i) {
185 if (!eclclusters[i]->isTrack()) {
187 gammalist->addParticle(p);
198 EXPECT_EQ(gammalist->getListSize(), 3);
200 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterTheta->function(gammalist->getParticle(0))), 3.0276554);
201 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterPhi->function(gammalist->getParticle(0))), 0.0);
202 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterTheta->function(gammalist->getParticle(1))), 1.6035342);
203 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterPhi->function(gammalist->getParticle(1))), -1.0607308);
204 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterTheta->function(gammalist->getParticle(2))), 2.7839828);
205 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterPhi->function(gammalist->getParticle(2))), -1.3155545);
208 ASSERT_TRUE(std::isnan(std::get<double>(b2bClusterTheta->function(noclustertrack))));
209 ASSERT_TRUE(std::isnan(std::get<double>(b2bClusterPhi->function(noclustertrack))));
216 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterTheta->function(gammalist->getParticle(0))),
217 std::get<double>(b2bTheta->function(gammalist->getParticle(0))));
218 EXPECT_FLOAT_EQ(std::get<double>(b2bClusterPhi->function(gammalist->getParticle(0))),
219 std::get<double>(b2bPhi->function(gammalist->getParticle(0))));
222 TEST_F(ECLVariableTest, clusterKinematicsTest)
231 gearbox.setBackends({std::string(
"file:")});
233 gearbox.open(
"geometry/Belle2.xml",
false);
243 gammalist->initialize(22, gammalist.getName());
246 for (
int i = 0; i < eclclusters.
getEntries(); ++i) {
247 if (!eclclusters[i]->isTrack()) {
249 gammalist->addParticle(p);
259 EXPECT_FLOAT_EQ(std::get<double>(clusterPhi->
function(gammalist->getParticle(1))), 2.0);
260 EXPECT_FLOAT_EQ(std::get<double>(clusterPhiCMS->
function(gammalist->getParticle(1))), 2.0442522);
261 EXPECT_FLOAT_EQ(std::get<double>(clusterTheta->
function(gammalist->getParticle(1))), 1.0);
262 EXPECT_FLOAT_EQ(std::get<double>(clusterThetaCMS->
function(gammalist->getParticle(1))), 1.2625608);
265 EXPECT_FLOAT_EQ(std::get<double>(clusterPhi->
function(gammalist->getParticle(0))), eclclusters[0]->getPhi());
266 EXPECT_FLOAT_EQ(std::get<double>(clusterTheta->
function(gammalist->getParticle(0))), eclclusters[0]->getTheta());
269 TEST_F(ECLVariableTest, HypothesisVariables)
283 gammalist->initialize(22, gammalist.getName());
286 for (
int i = 0; i < eclclusters.
getEntries(); ++i)
287 if (!eclclusters[i]->isTrack()) {
289 gammalist->addParticle(p);
297 for (
size_t i = 0; i < gammalist->getListSize(); ++i) {
298 EXPECT_FLOAT_EQ(std::get<double>(vHasNPhotons->
function(gammalist->getParticle(i))), 1.0);
300 EXPECT_FLOAT_EQ(std::get<double>(vHasNeutHadr->
function(gammalist->getParticle(i))), 1.0);
302 EXPECT_FLOAT_EQ(std::get<double>(vHasNeutHadr->
function(gammalist->getParticle(i))), 0.0);
307 TEST_F(ECLVariableTest, IsFromECL)
317 for (
int i = 0; i < eclclusters.
getEntries(); ++i)
318 if (!eclclusters[i]->isTrack()) {
320 EXPECT_TRUE(std::get<bool>(vIsFromECL->
function(p)));
321 EXPECT_FALSE(std::get<bool>(vIsFromKLM->
function(p)));
322 EXPECT_FALSE(std::get<bool>(vIsFromTrack->
function(p)));
323 EXPECT_FALSE(std::get<bool>(vIsFromV0->
function(p)));
327 TEST_F(ECLVariableTest, ECLThetaAndPhiId)
340 clusters[0]->setMaxECellId(1);
341 EXPECT_FLOAT_EQ(std::get<double>(clusterThetaID->
function(p)), 0);
342 EXPECT_FLOAT_EQ(std::get<double>(clusterPhiID->
function(p)), 0);
345 clusters[0]->setMaxECellId(6903);
346 EXPECT_FLOAT_EQ(std::get<double>(clusterThetaID->
function(p)), 52);
347 EXPECT_FLOAT_EQ(std::get<double>(clusterPhiID->
function(p)), 134);
350 clusters[0]->setMaxECellId(8457);
351 EXPECT_FLOAT_EQ(std::get<double>(clusterThetaID->
function(p)), 65);
352 EXPECT_FLOAT_EQ(std::get<double>(clusterPhiID->
function(p)), 8);
357 TEST_F(ECLVariableTest, WholeEventClosure)
378 gammalist->initialize(22, gammalist.getName());
380 pionslist->initialize(211, pionslist.getName());
382 apionslist->initialize(-211, apionslist.getName());
383 apionslist->bindAntiParticleList(*(pionslist));
386 double eclEnergy = 0.0;
387 for (
int i = 0; i < eclclusters.
getEntries(); ++i) {
388 eclEnergy += eclclusters[i]->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
389 if (!eclclusters[i]->isTrack()) {
391 gammalist->addParticle(p);
397 for (
int i = 0; i < tracks.getEntries(); ++i) {
399 pionslist->addParticle(p);
407 double totalNeutralClusterE = 0.0;
408 for (
size_t i = 0; i < gammalist->getListSize(); ++i)
409 totalNeutralClusterE += std::get<double>(vClusterE->
function(gammalist->getParticle(i)));
412 double totalTrackClusterE = 0.0;
413 for (
size_t i = 0; i < pionslist->getListSize(); ++i) {
414 double clusterE = std::get<double>(vClusterE->
function(pionslist->getParticle(i)));
415 double nOtherCl = std::get<double>(vClNTrack->
function(pionslist->getParticle(i)));
417 totalTrackClusterE += clusterE / nOtherCl;
420 EXPECT_FLOAT_EQ(totalNeutralClusterE + totalTrackClusterE, eclEnergy);
423 TEST_F(ECLVariableTest, eclClusterOnlyInvariantMass)
427 std::vector<int> daughterIndices, daughterIndices_noclst;
433 particles.registerRelationTo(eclclusters_new);
437 const float px_0 = 2.;
438 const float py_0 = 1.;
439 const float pz_0 = 3.;
440 const float px_1 = 1.5;
441 const float py_1 = 1.5;
442 const float pz_1 = 2.5;
444 E_0 =
sqrt(pow(px_0, 2) + pow(py_0, 2) + pow(pz_0, 2));
445 E_1 =
sqrt(pow(px_1, 2) + pow(py_1, 2) + pow(pz_1, 2));
446 ROOT::Math::PxPyPzEVector momentum;
447 ROOT::Math::PxPyPzEVector dau0_4vec(px_0, py_0, pz_0, E_0), dau1_4vec(px_1, py_1, pz_1, E_1);
450 Particle dau0_noclst(dau0_4vec, 22);
451 momentum += dau0_noclst.get4Vector();
452 Particle* newDaughter0_noclst = particles.appendNew(dau0_noclst);
453 daughterIndices_noclst.push_back(newDaughter0_noclst->
getArrayIndex());
454 Particle dau1_noclst(dau1_4vec, 22);
455 momentum += dau1_noclst.get4Vector();
456 Particle* newDaughter1_noclst = particles.appendNew(dau1_noclst);
457 daughterIndices_noclst.push_back(newDaughter1_noclst->
getArrayIndex());
464 ASSERT_NE(var,
nullptr);
465 EXPECT_TRUE(std::isnan(std::get<double>(var->function(par_noclst))));
470 eclst0->
setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
472 eclst0->
setTheta(dau0_4vec.Theta());
473 eclst0->
setPhi(dau0_4vec.Phi());
477 eclst1->
setHypothesis(ECLCluster::EHypothesisBit::c_nPhotons);
479 eclst1->
setTheta(dau1_4vec.Theta());
480 eclst1->
setPhi(dau1_4vec.Phi());
484 const Particle* newDaughter0 = particles.appendNew(
Particle(eclclusters_new[6]));
486 const Particle* newDaughter1 = particles.appendNew(
Particle(eclclusters_new[7]));
492 EXPECT_FLOAT_EQ(std::get<double>(var->function(par)), 0.73190731);
495 TEST_F(ECLVariableTest, averageECLTimeQuantities)
513 gammalist->initialize(22, gammalist.getName());
515 pionslist->initialize(111, pionslist.getName());
518 for (
int i = 0; i < eclclusters.
getEntries(); ++i) {
519 if (!eclclusters[i]->isTrack()) {
521 gammalist->addParticle(p);
526 ParticleGenerator combiner_pi0(
"pi0:testPizAllList -> gamma:testGammaAllList gamma:testGammaAllList");
528 while (combiner_pi0.loadNext()) {
529 const Particle& particle = combiner_pi0.getCurrentParticle();
531 particles.appendNew(particle);
532 int iparticle = particles.getEntries() - 1;
534 pionslist->addParticle(iparticle, particle.getPDGCode(), particle.getFlavorType());
542 EXPECT_TRUE(std::isnan(std::get<double>(weightedAverageECLTime->function(gammalist->getParticle(0)))));
545 EXPECT_FLOAT_EQ(std::get<double>(weightedAverageECLTime->function(pionslist->getParticle(0))), 1.2);
548 EXPECT_FLOAT_EQ(std::get<double>(maxDist->
function(pionslist->getParticle(0))), 4.0);
551 TEST_F(ECLVariableTest, photonHasOverlap)
572 gammalist->initialize(22, gammalist.getName());
573 gammalist->setEditable(
true);
576 for (
int i = 0; i < eclclusters.
getEntries(); ++i) {
577 if (!eclclusters[i]->isTrack()) {
579 gammalist->addParticle(p);
582 gammalist->setEditable(
false);
586 pionlist->initialize(211, pionlist.getName());
587 piminuslist.create();
588 piminuslist->initialize(-211, piminuslist.getName());
589 piminuslist->bindAntiParticleList(*(pionlist));
590 pionlist->setEditable(
true);
593 for (
int i = 0; i < tracks.getEntries(); ++i) {
595 pionlist->addParticle(p);
597 pionlist->setEditable(
false);
602 EXPECT_TRUE(std::isnan(std::get<double>(photonHasOverlapNoArgs->
function(particles[0]))));
607 EXPECT_TRUE(std::get<double>(photonHasOverlapAll->
function(particles[0])));
609 EXPECT_TRUE(std::isnan(std::get<double>(photonHasOverlapAll->
function(particles[3]))));
614 EXPECT_FALSE(std::get<double>(photonHasOverlapBarrel->
function(particles[0])));
617 class KLMVariableTest :
public ::testing::Test {
620 void SetUp()
override
627 particles.registerInDataStore();
631 tracks.registerInDataStore();
638 tracks.registerRelationTo(klmClusters);
645 void TearDown()
override
651 TEST_F(KLMVariableTest, WholeEventClosure)
673 kLongList->initialize(
Const::Klong.getPDGCode(), kLongList.getName());
675 muonsList->initialize(
Const::muon.getPDGCode(), muonsList.getName());
677 amuonsList->initialize(-
Const::muon.getPDGCode(), amuonsList.getName());
678 amuonsList->bindAntiParticleList(*(muonsList));
684 tracks.appendNew(
Track());
685 tracks.appendNew(
Track());
690 auto CDCValue =
static_cast<unsigned long long int>(0x300000000000000);
692 for (
int i = 0; i < tracks.getEntries(); ++i) {
693 int charge = (i % 2 == 0) ? +1 : -1;
694 ROOT::Math::Cartesian2D d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
695 ROOT::Math::Cartesian2D pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
696 d.SetXY(d.X(), -(d.X()*pt.X()) / pt.Y());
697 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
698 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
699 trackFits.
appendNew(position, momentum, cov6, charge,
Const::muon, 0.5, 1.5, CDCValue, 16777215, 0);
712 klm2->setClusterPosition(1.2, 1.2, 2.0);
714 klm2->setInnermostLayer(2);
715 klm2->setMomentumMag(1.0);
731 t1->addRelationTo(klm4);
740 t2->addRelationTo(klm5);
741 t3->addRelationTo(klm5);
747 double klmMomentum = 0.0;
748 for (
int i = 0; i < klmClusters.
getEntries(); ++i) {
749 klmMomentum += klmClusters[i]->getMomentumMag();
750 if (!klmClusters[i]->getAssociatedTrackFlag()) {
752 kLongList->addParticle(p);
757 for (
int i = 0; i < tracks.getEntries(); ++i) {
759 muonsList->addParticle(p);
767 double totalKLongMomentum = 0.0;
768 for (
size_t i = 0; i < kLongList->getListSize(); ++i)
769 totalKLongMomentum += std::get<double>(vClusterP->
function(kLongList->getParticle(i)));
772 double totalMuonMomentum = 0.0;
773 for (
size_t i = 0; i < muonsList->getListSize(); ++i) {
774 double muonMomentum = std::get<double>(vClusterP->
function(muonsList->getParticle(i)));
775 double nOtherCl = std::get<double>(vClNTrack->
function(muonsList->getParticle(i)));
777 totalMuonMomentum += muonMomentum / nOtherCl;
780 EXPECT_FLOAT_EQ(5.0, klmMomentum);
781 EXPECT_FLOAT_EQ(totalKLongMomentum + totalMuonMomentum, klmMomentum);
784 TEST_F(KLMVariableTest, TrackToKLMClusterMatchingTest)
792 ROOT::Math::XYZVector position(1.0, 0, 0);
793 ROOT::Math::XYZVector momentum(0, 1.0, 0);
796 const float pValue = 0.5;
797 const float bField = 1.5;
798 auto CDCValue =
static_cast<unsigned long long int>(0x300000000000000);
799 trackFits.
appendNew(position, momentum, cov6, charge,
Const::muon, pValue, bField, CDCValue, 16777215, 0);
804 Track* muonTrack = tracks.appendNew(myTrack);
815 klm2->setClusterPosition(1.2, 1.2, 2.0);
817 klm2->setInnermostLayer(2);
818 klm2->setMomentumMag(1.0);
825 float distance1 = 11.1;
827 float distance2 = 2.2;
838 EXPECT_POSITIVE(std::get<double>(vTrNClusters->
function(muon)));
839 EXPECT_FLOAT_EQ(1.0, std::get<double>(vClusterInnermostLayer->
function(muon)));
840 EXPECT_FLOAT_EQ(distance1, std::get<double>(vClusterTrackDistance->
function(muon)));
843 trackFits.
appendNew(position, momentum, cov6, charge,
Const::pion, pValue, bField, CDCValue, 16777215, 0);
846 Track* pionTrack = tracks.appendNew(mySecondTrack);
849 EXPECT_FLOAT_EQ(0.0, std::get<double>(vTrNClusters->
function(pion)));
static const ChargedStable muon
muon particle
static const ChargedStable pion
charged pion particle
static const ParticleType Klong
K^0_L particle.
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
static DataStore & Instance()
Instance of singleton Store.
void setInitializeActive(bool active)
Setter for m_initializeActive.
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
void addHypothesis(EHypothesisBit bitmask)
Add bitmask to current hypothesis.
void setTheta(double theta)
Set Theta of Shower (radian).
void setConnectedRegionId(int crid)
Set connected region id.
void setPhi(double phi)
Set Phi of Shower (radian).
void setTime(double time)
Set time information.
void setDeltaTime99(double dtime99)
Set 99% time containment range.
void setClusterId(int clusterid)
Set cluster id.
void setHypothesis(EHypothesisBit hypothesis)
Set hypotheses.
void setEnergy(double energy)
Set Corrected Energy (GeV).
void setIsTrack(bool istrack)
Set m_isTrack true if the cluster matches with a track.
void setR(double r)
Set R (in cm).
Singleton class responsible for loading detector parameters from an XML file.
void setLayers(int layers)
Set number of layers with hits.
void setClusterPosition(float globalX, float globalY, float globalZ)
Set global position.
void setTime(float time)
Set time.
void setInnermostLayer(int innermostLayer)
Set number of the innermost layer with hits.
void setMomentumMag(float momentumMag)
Set momentum magnitude.
ParticleGenerator is a generator for all the particles combined from the given ParticleLists.
Class to store reconstructed particles.
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
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.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
T * appendNew()
Construct a new T object at the end of the array.
int getEntries() const
Get the number of objects in the array.
Type-safe access to single objects in the data store.
Class that bundles various TrackFitResults.
void setTrackFitResultIndex(const Const::ChargedStable &chargedStable, short index)
Set an index (for positive values) or unavailability-code (index = -1) for a specific mass hypothesis...
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
static Gearbox & getInstance()
Return reference to the Gearbox instance.
double sqrt(double a)
sqrt for double
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Abstract base class for different kinds of events.
A variable returning a floating-point value for a given Particle.
FunctionPtr function
Pointer to function.