Belle II Software development
MuidBuilder.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/* Own header. */
10#include <klm/muid/MuidBuilder.h>
11
12/* KLM headers. */
13#include <klm/dataobjects/KLMMuidLikelihood.h>
14
15/* Basf2 headers. */
16#include <framework/logging/Logger.h>
17#include <framework/utilities/Spline.h>
18
19/* C++ headers. */
20#include <cmath>
21
22using namespace Belle2;
23
24MuidBuilder::MuidBuilder() : m_ReducedChiSquaredDx(0.0)
25{
26 for (int outcome = 1; outcome <= MuidElementNumbers::getMaximalOutcome(); ++outcome) {
27 for (int lastLayer = 0; lastLayer <= MuidElementNumbers::getMaximalBarrelLayer(); ++lastLayer) {
28 /* MuidElementNumbers::getMaximalBarrelLayer() and MuidElementNumbers::getMaximalEndcapForwardLayer() are 0 index based thus an addition of 2 is needed. */
29 for (unsigned int layer = 0;
31 ++layer) {
32 m_LayerPDF[outcome][lastLayer][layer] = 0.0;
33 }
34 }
35 }
36 for (int detector = 0; detector <= MuidElementNumbers::getMaximalDetector(); ++detector) {
37 for (int halfNdof = 0; halfNdof <= MuidElementNumbers::getMaximalHalfNdof(); ++halfNdof) {
38 m_ReducedChiSquaredThreshold[detector][halfNdof] = 0.0;
39 m_ReducedChiSquaredScaleY[detector][halfNdof] = 0.0;
40 m_ReducedChiSquaredScaleX[detector][halfNdof] = 0.0;
41 for (int i = 0; i < MuidElementNumbers::getSizeReducedChiSquared(); ++i) {
42 m_ReducedChiSquaredPDF[detector][halfNdof][i] = 0.0;
43 m_ReducedChiSquaredD1[detector][halfNdof][i] = 0.0;
44 m_ReducedChiSquaredD2[detector][halfNdof][i] = 0.0;
45 m_ReducedChiSquaredD3[detector][halfNdof][i] = 0.0;
46 }
47 }
48 }
49}
50
51MuidBuilder::MuidBuilder(int pdg) : m_ReducedChiSquaredDx(0.0)
52{
54 if (hypothesis == MuidElementNumbers::c_NotValid)
55 B2FATAL("The particle associated to the PDG code " << pdg << " is not supported.");
56 /* Fill PDFs by reading database. */
57 fillPDFs(hypothesis);
58 if (m_ReducedChiSquaredDx == 0.0)
59 B2FATAL("Invalid PDFs for PDG code " << pdg);
60}
61
63{
64}
65
67{
68 for (int outcome = 1; outcome <= MuidElementNumbers::getMaximalOutcome(); ++outcome) {
69 for (int lastLayer = 0; lastLayer <= MuidElementNumbers::getMaximalBarrelLayer(); ++lastLayer) {
70 if (!(MuidElementNumbers::checkExtrapolationOutcome(outcome, lastLayer)))
71 break;
72 std::vector<double> layerPDF = m_LikelihoodParameters->getLongitudinalPDF(hypothesis, outcome, lastLayer);
73 for (unsigned int layer = 0; layer < layerPDF.size(); ++layer) {
74 m_LayerPDF[outcome][lastLayer][layer] = layerPDF[layer];
75 }
76 }
77 }
80 for (int detector = 0; detector <= MuidElementNumbers::getMaximalDetector(); ++detector) {
81
82 for (int halfNdof = 1; halfNdof <= MuidElementNumbers::getMaximalHalfNdof(); ++halfNdof) {
83 m_ReducedChiSquaredThreshold[detector][halfNdof] = m_LikelihoodParameters->getTransverseThreshold(hypothesis, detector,
84 halfNdof * 2);
85 m_ReducedChiSquaredScaleY[detector][halfNdof] = m_LikelihoodParameters->getTransverseScaleY(hypothesis, detector, halfNdof * 2);
86 m_ReducedChiSquaredScaleX[detector][halfNdof] = m_LikelihoodParameters->getTransverseScaleX(hypothesis, detector, halfNdof * 2);
87 std::vector<double> reducedChiSquaredPDF = m_LikelihoodParameters->getTransversePDF(hypothesis, detector, halfNdof * 2);
88 if (reducedChiSquaredPDF.size() != MuidElementNumbers::getSizeReducedChiSquared()) {
89 B2ERROR("TransversePDF vector for hypothesis " << hypothesis << " detector " << detector
90 << " has " << reducedChiSquaredPDF.size() << " entries; should be " << MuidElementNumbers::getSizeReducedChiSquared());
91 m_ReducedChiSquaredDx = 0.0; /* Invalidate the PDFs for this hypothesis. */
92 } else {
93 for (int i = 0; i < MuidElementNumbers::getSizeReducedChiSquared(); ++i) {
94 m_ReducedChiSquaredPDF[detector][halfNdof][i] = reducedChiSquaredPDF[i];
95 }
97 &m_ReducedChiSquaredPDF[detector][halfNdof][0],
98 &m_ReducedChiSquaredD1[detector][halfNdof][0],
99 &m_ReducedChiSquaredD2[detector][halfNdof][0],
100 &m_ReducedChiSquaredD3[detector][halfNdof][0]);
104 }
105 }
106 }
107}
108
109double MuidBuilder::getPDF(const KLMMuidLikelihood* muid) const
110{
111 return getLongitudinalPDF(muid) * getTransversePDF(muid);
112}
113
115{
116 /* Setup the main ingredients for the calculation. */
117 unsigned int outcome = muid->getOutcome();
118 if ((outcome <= MuidElementNumbers::c_NotReached) || (outcome > MuidElementNumbers::getMaximalOutcome()))
119 return 0.0;
120 int barrelExtLayer = muid->getBarrelExtLayer();
121 if (barrelExtLayer > MuidElementNumbers::getMaximalBarrelLayer())
122 return 0.0;
123 int endcapExtLayer = muid->getEndcapExtLayer();
125 return 0.0;
126 unsigned int extLayerPattern = muid->getExtLayerPattern();
127 unsigned int hitLayerPattern = muid->getHitLayerPattern();
128 int lastLayer = (endcapExtLayer < 0) ? barrelExtLayer : endcapExtLayer;
129
130 /* Longitudinal PDF computation for barrel. */
131 double pdf = 1.0;
132 unsigned int testBit = 1;
133 for (int layer = 0; layer <= barrelExtLayer; ++layer) {
134 if ((testBit & extLayerPattern) != 0) {
135 if ((testBit & hitLayerPattern) != 0) { /* Checking the presence of a hit in the layer. */
136 pdf *= m_LayerPDF[outcome][lastLayer][layer];
137 } else {
138 if (((layer == 0) && (outcome < MuidElementNumbers::c_CrossBarrelStopInForwardMin))
139 || (layer == MuidElementNumbers::getMaximalBarrelLayer()) || (layer < barrelExtLayer)) {
140 pdf *= 1 - m_LayerPDF[outcome][lastLayer][layer] * muid->getExtBKLMEfficiencyValue(layer);
141 }
142 }
143 }
144 testBit <<= 1; /* Move to next bit. */
145 }
146 /* Longitudinal PDF computation for endcap. */
147 int maxLayer = muid->getIsForward() ? MuidElementNumbers::getMaximalEndcapForwardLayer() :
149 testBit = 1 << (MuidElementNumbers::getMaximalBarrelLayer() + 1);
150 for (int layer = 0; layer <= endcapExtLayer; ++layer) {
151 if ((testBit & extLayerPattern) != 0) {
152 if ((testBit & hitLayerPattern) != 0) { /* Checking the presence of a hit in the layer. */
153 pdf *= m_LayerPDF[outcome][lastLayer][layer + MuidElementNumbers::getMaximalBarrelLayer() + 1];
154 } else {
155 if ((layer == 0) || (layer == maxLayer) || (layer < endcapExtLayer)) {
156 pdf *= 1 - m_LayerPDF[outcome][lastLayer][layer + MuidElementNumbers::getMaximalBarrelLayer() + 1] *
157 muid->getExtEKLMEfficiencyValue(layer);
158 }
159 }
160 }
161 testBit <<= 1; /* move to next bit. */
162 }
163 return pdf;
164}
165
167{
168 /* Evaluate the transverse-coordinate PDF for this particleID hypothesis. */
169 int ndof = muid->getDegreesOfFreedom();
170 if (ndof <= 0)
171 return 1.0;
172 double chiSquared = muid->getChiSquared();
173 if (chiSquared < 0.0)
174 return 0.0;
175 int halfNdof = (ndof >> 1);
176 double x = chiSquared / ndof;
177
178 /* Assume that the track crossed both barrel and endcap. */
179 int detector = MuidElementNumbers::c_Both;
180 if (muid->getEndcapExtLayer() < 0) {
181 detector = MuidElementNumbers::c_OnlyBarrel; /* Crossed barrel only. */
182 } else if (muid->getBarrelExtLayer() < 0) {
183 detector = MuidElementNumbers::c_OnlyEndcap; /* Crossed endcap only. */
184 }
185
186 /* Use spline interpolation of the logarithms of the PDF to avoid binning artifacts.
187 * Use fitted tail function for reduced-chiSquared values beyond the tabulated threshold. */
188 double pdf = 0.0;
189 if (halfNdof > MuidElementNumbers::getMaximalHalfNdof()) { /* Extremely rare. */
191 pdf = m_ReducedChiSquaredScaleY[detector][MuidElementNumbers::getMaximalHalfNdof()] * std::pow(x, halfNdof - 1.0) * std::exp(-x);
192 } else {
193 if (x > m_ReducedChiSquaredThreshold[detector][halfNdof]) { /* Tail function for large x. */
194 x *= m_ReducedChiSquaredScaleX[detector][halfNdof] * halfNdof;
195 if (halfNdof == 1) {
196 pdf = m_ReducedChiSquaredScaleY[detector][halfNdof] * std::exp(-x);
197 } else if (halfNdof == 2) {
198 pdf = m_ReducedChiSquaredScaleY[detector][halfNdof] * x * std::exp(-x);
199 } else if (halfNdof == 3) {
200 pdf = m_ReducedChiSquaredScaleY[detector][halfNdof] * x * x * std::exp(-x);
201 } else {
202 pdf = m_ReducedChiSquaredScaleY[detector][halfNdof] * std::pow(x, halfNdof - 1.0) * std::exp(-x);
203 }
204 } else { /* Spline-interpolated histogram for small x. */
205 x -= 0.5 * m_ReducedChiSquaredDx;
206 int i = (int)(x / m_ReducedChiSquaredDx);
207 double logPdf = m_ReducedChiSquaredPDF[detector][halfNdof][i];
208 double dx = x - i * m_ReducedChiSquaredDx;
209 logPdf += dx * (m_ReducedChiSquaredD1[detector][halfNdof][i] +
210 dx * (m_ReducedChiSquaredD2[detector][halfNdof][i] +
211 dx * m_ReducedChiSquaredD3[detector][halfNdof][i]));
212 pdf = std::exp(logPdf);
213 }
214 }
215 return pdf;
216}
Class to store the likelihoods from KLM with additional information related to the extrapolation.
MuidBuilder()
Default constructor.
Definition: MuidBuilder.cc:24
double getLongitudinalPDF(const KLMMuidLikelihood *muid) const
Calculate the longitudinal PDF for a given hypothesis.
Definition: MuidBuilder.cc:114
double getTransversePDF(const KLMMuidLikelihood *muid) const
Calculate the transverse PDF for a given hypothesis.
Definition: MuidBuilder.cc:166
double m_LayerPDF[MuidElementNumbers::getMaximalOutcome()+1][MuidElementNumbers::getMaximalBarrelLayer()+1][MuidElementNumbers::getMaximalBarrelLayer()+MuidElementNumbers::getMaximalEndcapForwardLayer()+2]
Longitudinal PDF.
Definition: MuidBuilder.h:89
double m_ReducedChiSquaredPDF[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1][MuidElementNumbers::getSizeReducedChiSquared()]
Reduced chi-squared (transverse) PDF (overflows in last bin).
Definition: MuidBuilder.h:110
void fillPDFs(MuidElementNumbers::Hypothesis hypothesis)
Retrieve the PDFs from the database according to the given hypothesis.
Definition: MuidBuilder.cc:66
double m_ReducedChiSquaredDx
Reduced chi-squared (transverse) PDF's bin size.
Definition: MuidBuilder.h:133
double m_ReducedChiSquaredScaleY[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1]
Reduced chi-squared (transverse) analytical PDF: vertical scale.
Definition: MuidBuilder.h:104
double m_ReducedChiSquaredD1[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1][MuidElementNumbers::getSizeReducedChiSquared()]
First derivative of reduced chi-squared PDF (for spline interpolation).
Definition: MuidBuilder.h:116
double getPDF(const KLMMuidLikelihood *muid) const
Get total PDG for a given hypothesis.
Definition: MuidBuilder.cc:109
DBObjPtr< KLMLikelihoodParameters > m_LikelihoodParameters
Likelihood parameters.
Definition: MuidBuilder.h:138
double m_ReducedChiSquaredThreshold[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1]
Reduced chi-squared (transverse) analytical PDF: threshold.
Definition: MuidBuilder.h:94
~MuidBuilder()
Destructor.
Definition: MuidBuilder.cc:62
double m_ReducedChiSquaredD2[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1][MuidElementNumbers::getSizeReducedChiSquared()]
Second derivative of reduced chi-squared PDF (for spline interpolation).
Definition: MuidBuilder.h:122
double m_ReducedChiSquaredScaleX[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1]
Reduced chi-squared (transverse) analytical PDF: horizontal scale ~ 1.
Definition: MuidBuilder.h:99
double m_ReducedChiSquaredD3[MuidElementNumbers::getMaximalDetector()+1][MuidElementNumbers::getMaximalHalfNdof()+1][MuidElementNumbers::getSizeReducedChiSquared()]
Third derivative of reduced chi-squared PDF (for spline interpolation).
Definition: MuidBuilder.h:128
static constexpr int getMaximalDetector()
Get maximal value of the detector selector (for transverse scattering).
static constexpr int getMaximalEndcapForwardLayer()
Get maximal endcap-forward layer number (0-based).
static constexpr int getMaximalHalfNdof()
Get maximal value of NDof/2 (for transverse scattering).
static constexpr int getMaximalEndcapBackwardLayer()
Get maximal endcap-forward layer number (0-based).
static constexpr int getMaximalBarrelLayer()
Get maximal barrel layer number (0-based).
static constexpr double getMaximalReducedChiSquared()
Get maximal value of reduced chi-squared (for transverse scattering).
static bool checkExtrapolationOutcome(unsigned int outcome, int lastLayer)
Check the track extrapolation outcome.
static Hypothesis calculateHypothesisFromPDG(int pdg)
Calculate hypothesis number from PDG code.
static constexpr int getSizeReducedChiSquared()
Get size of array with reduced chi-squared values (for transverse scattering).
static constexpr int getMaximalOutcome()
Get maximal value of the track extrapolation outcome.
Abstract base class for different kinds of events.