Belle II Software development
eclChargedPID.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <framework/gearbox/Const.h>
9#include <framework/gearbox/Unit.h>
10#include <framework/datastore/StoreArray.h>
11
12#include <ecl/dataobjects/ECLPidLikelihood.h>
13#include <ecl/dbobjects/ECLChargedPidPDFs.h>
14
15#include <utility>
16#include <gtest/gtest.h>
17
18#include <TF1.h>
19
20namespace Belle2 {
27 class ECLChargedPIDTest : public ::testing::Test {
28
29 protected:
31 virtual void SetUp()
32 {
34
35 StoreArray<ECLPidLikelihood> ecl_likelihoods;
36 ecl_likelihoods.registerInDataStore();
37
38 StoreArray<ECLPidLikelihood> ecl_likelihoods_plus;
39 ecl_likelihoods_plus.registerInDataStore();
40
41 StoreArray<ECLPidLikelihood> ecl_likelihoods_minus;
42 ecl_likelihoods_minus.registerInDataStore();
43
45 }
46
48 virtual void TearDown()
49 {
51 }
52
53 };
54
56 TEST_F(ECLChargedPIDTest, ECLPidLikelihoodSettersAndGetters)
57 {
58
59 StoreArray<ECLPidLikelihood> ecl_likelihoods;
60
61 auto* lk = ecl_likelihoods.appendNew();
62
63 lk->setLogLikelihood(Const::electron, 0.12);
64 lk->setLogLikelihood(Const::muon, 0.58);
65 lk->setLogLikelihood(Const::pion, 0.28);
66 lk->setLogLikelihood(Const::kaon, 0.38);
67 lk->setLogLikelihood(Const::proton, 0.48);
68
69 EXPECT_FLOAT_EQ(lk->getLogLikelihood(Const::electron), 0.12);
70 EXPECT_FLOAT_EQ(lk->getLogLikelihood(Const::muon), 0.58);
71 EXPECT_FLOAT_EQ(lk->getLogLikelihood(Const::pion), 0.28);
72 EXPECT_FLOAT_EQ(lk->getLogLikelihood(Const::kaon), 0.38);
73 EXPECT_FLOAT_EQ(lk->getLogLikelihood(Const::proton), 0.48);
74
75 } // Testcases for ECLPidLikelihood setters and getters.
76
78 TEST_F(ECLChargedPIDTest, TestECLPdfs)
79 {
80
81 ECLChargedPidPDFs eclPdfs;
82
83 float pmin_vals[] = {0.2, 0.6, 1.0, 100.0};
84 float thetamin_vals[] = {0.21, 0.56, 2.24, 2.70};
85
86 TH2F histgrid("binsgrid",
87 "bins grid",
88 sizeof(thetamin_vals) / sizeof(float) - 1,
89 thetamin_vals,
90 sizeof(pmin_vals) / sizeof(float) - 1,
91 pmin_vals);
92
93 eclPdfs.setEnergyUnit(Unit::GeV);
95
96 eclPdfs.setPdfCategories(&histgrid);
97
98 // Create a set of fictitious (normalised) PDFs of E/p, for various signed particle hypotheses.
99 // The first element in the pair is the true charge.
100
101 typedef std::pair<int, TF1> pdfSet;
102
103 pdfSet pdf_el = std::make_pair(-1, TF1("pdf_el", "TMath::Gaus(x, 1.0, 0.2, true)", 0.0, 1.3));
104 pdfSet pdf_elanti = std::make_pair(1, TF1("pdf_elanti", "TMath::Gaus(x, 0.9, 0.2, true)", 0.0, 1.2));
105
106 pdfSet pdf_mu = std::make_pair(-1, TF1("pdf_mu", "TMath::Gaus(x, 0.3, 0.2, true)", 0.0, 1.0));
107 pdfSet pdf_muanti = std::make_pair(1, TF1("pdf_muanti", "TMath::Gaus(x, 0.35, 0.22, true)", 0.0, 1.0));
108
109 pdfSet pdf_pi = std::make_pair(1, TF1("pdf_pi", "TMath::Gaus(x, 0.4, 0.1, true)", 0.0, 1.0));
110 pdfSet pdf_pianti = std::make_pair(-1, TF1("pdf_pianti", "TMath::Gaus(x, 0.38, 0.15, true)", 0.0, 1.0));
111
112 pdfSet pdf_k = std::make_pair(1, TF1("pdf_k", "TMath::Gaus(x, 0.38, 0.2, true)", 0.0, 1.0));
113 pdfSet pdf_kanti = std::make_pair(-1, TF1("pdf_kanti", "TMath::Gaus(x, 0.5, 0.22, true)", 0.0, 1.0));
114
115 pdfSet pdf_p = std::make_pair(1, TF1("pdf_p", "TMath::Gaus(x, 1.0, 0.4, true)", 0.0, 1.6));
116 pdfSet pdf_panti = std::make_pair(-1, TF1("pdf_panti", "TMath::Gaus(x, 1.3, 0.5, true)", 0.0, 2.0));
117
118 pdfSet pdf_d = std::make_pair(1, TF1("pdf_d", "TMath::Gaus(x, 1.1, 0.45, true)", 0.0, 1.6));
119 pdfSet pdf_danti = std::make_pair(-1, TF1("pdf_danti", "TMath::Gaus(x, 1.2, 0.6, true)", 0.0, 2.0));
120
121 std::map<unsigned int, std::vector<pdfSet>> pdfs = {
122 {Const::electron.getPDGCode(), std::vector<pdfSet>{pdf_el, pdf_elanti}},
123 {Const::muon.getPDGCode(), std::vector<pdfSet>{pdf_mu, pdf_muanti}},
124 {Const::pion.getPDGCode(), std::vector<pdfSet>{pdf_pi, pdf_pianti}},
125 {Const::kaon.getPDGCode(), std::vector<pdfSet>{pdf_k, pdf_kanti}},
126 {Const::proton.getPDGCode(), std::vector<pdfSet>{pdf_p, pdf_panti}},
127 {Const::deuteron.getPDGCode(), std::vector<pdfSet>{pdf_d, pdf_danti}},
128 };
129
130 // E/p is the only variable considered in the test.
131 std::vector<ECLChargedPidPDFs::InputVar> varids = {ECLChargedPidPDFs::InputVar::c_EoP};
132
133 // Fill the DB PDF map.
134 // (Use the same PDF for all (clusterTheta, p) bins for simplicity).
135 for (auto& [pdg, pdf_setlist] : pdfs) {
136 for (auto& pdf_set : pdf_setlist) {
137 for (int ip(1); ip <= histgrid.GetNbinsY(); ++ip) {
138 for (int jth(1); jth <= histgrid.GetNbinsX(); ++jth) {
139 for (const auto& varid : varids) {
140 eclPdfs.add(pdg, pdf_set.first, ip, jth, varid, &pdf_set.second);
141 }
142 }
143 }
144 }
145 }
146
147 // Store the value of the PDFs in here, and pass it to the ECLPidLikelihood object later on.
148 float likelihoods_plus[Const::ChargedStable::c_SetSize];
149 float likelihoods_minus[Const::ChargedStable::c_SetSize];
150
151 // Choose an arbitrary set of (clusterTheta, p), and of E/p.
152 double clusterTheta = 1.047; // (X) --> clusterTheta [rad] = 60 [deg]
153 double p = 0.85; // (Y) --> P [GeV] = 850 [MeV]
154 double eop = 0.87;
155
156 // Now read the PDFs.
157 for (const auto& [pdg, pdf_setlist] : pdfs) {
158 for (const auto& pdf_set : pdf_setlist) {
159 float pdfval = eclPdfs.getPdf(pdg, pdf_set.first, p, clusterTheta, varids.at(0))->Eval(eop);
160 EXPECT_NEAR(pdf_set.second.Eval(eop), pdfval, 0.001);
161 if (pdf_set.first < 0) {
162 likelihoods_minus[Const::chargedStableSet.find(pdg).getIndex()] = log(pdfval);
163 } else {
164 likelihoods_plus[Const::chargedStableSet.find(pdg).getIndex()] = log(pdfval);
165 }
166 }
167 }
168
169 // Set the ECL likelihood dataobjects
170 StoreArray<ECLPidLikelihood> ecl_likelihoods_minus;
171 const auto* lk_minus = ecl_likelihoods_minus.appendNew(likelihoods_minus);
172 StoreArray<ECLPidLikelihood> ecl_likelihoods_plus;
173 const auto* lk_plus = ecl_likelihoods_plus.appendNew(likelihoods_plus);
174
175 for (const auto& [pdg, pdf_setlist] : pdfs) {
176 for (const auto& pdf_set : pdf_setlist) {
177 float logl;
178 float logl_expect = log(pdf_set.second.Eval(eop));
179 if (pdf_set.first < 0) {
180 logl = lk_minus->getLogLikelihood(Const::chargedStableSet.find(pdg));
181 } else {
182 logl = lk_plus->getLogLikelihood(Const::chargedStableSet.find(pdg));
183 }
184 EXPECT_NEAR(logl_expect, logl, 0.01);
185 }
186 }
187
188 } // Testcases for ECL PDFs.
189
191} // namespace
static const unsigned int c_SetSize
Number of elements (for use in array bounds etc.)
Definition: Const.h:615
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
Definition: Const.h:571
int getPDGCode() const
PDG code.
Definition: Const.h:473
int getIndex() const
This particle's index in the associated set.
Definition: Const.h:461
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 ChargedStable proton
proton particle
Definition: Const.h:663
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:662
static const ChargedStable electron
electron particle
Definition: Const.h:659
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:664
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:86
Test the ECL charged PID.
virtual void TearDown()
Clear datastore.
virtual void SetUp()
Set up a few arrays and objects in the datastore.
Class representing the DB payload w/ information about ECL PDF parameters for a set of particle hypot...
void add(const unsigned int pdg, const int true_charge, const unsigned int i, const unsigned int j, const InputVar varid, TF1 *pdf)
Fills the internal maps for a given hypothesis and category (clusterTheta, p).
void setPdfCategories(TH2F *h)
Set the 2D (clusterTheta, p) grid representing the categories for which PDFs are defined.
const TF1 * getPdf(const unsigned int pdg, const int charge, const double &p, const double &theta, const InputVar varid) const
Return the PDF of this observable for this candidate's reconstructed (p, clusterTheta),...
void setAngularUnit(const double &unit)
Set the angular unit to be consistent w/ the one used in the fit.
void setEnergyUnit(const double &unit)
Set the energy unit to be consistent w/ the one used in the fit.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
static const double rad
Standard of [angle].
Definition: Unit.h:50
static const double GeV
Standard of [energy, momentum, mass].
Definition: Unit.h:51
Abstract base class for different kinds of events.