Belle II Software  release-08-01-10
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 
22 using namespace Belle2;
23 
24 MuidBuilder::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 
51 MuidBuilder::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 
109 double 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 informations 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.