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