25 constexpr
double s_singleGaussianRange = 0.0001;
26 constexpr
double s_lowerRange = 0.002;
27 constexpr
double s_xOverRange = 0.10;
28 constexpr
double s_upperRange = 0.20;
29 constexpr
double s_componentMeanCut = 0.0;
36 inline constexpr
double
37 hornerEvaluate(
const std::array<double, N>&
a,
const double&
x)
39 constexpr
size_t order =
N - 1;
40 if constexpr (
order == 0) {
42 }
else if constexpr (
order == 1) {
43 return a[0] *
x +
a[1];
44 }
else if constexpr (
order == 2) {
45 return (
a[0] *
x +
a[1]) *
x +
a[2];
46 }
else if constexpr (
order == 3) {
47 return ((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3];
48 }
else if constexpr (
order == 4) {
49 return (((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4];
50 }
else if constexpr (
order == 5) {
51 return ((((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4]) *
x +
a[5];
54 ((((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4]) *
x +
a[5];
55 for (
size_t i = 6;
i <
N; ++
i) {
64 return ((
var <= hi) and (
var >= lo));
69 logisticFunction(
const double x)
77 correctWeights(BH::MixtureParameters& mixture,
const int numberOfComponents)
79 if (numberOfComponents < 1) {
84 for (
int i = 0;
i < numberOfComponents; ++
i) {
85 weightSum += mixture[
i].weight;
87 double norm = 1. / weightSum;
89 for (
int i = 0;
i < numberOfComponents; ++
i) {
90 mixture[
i].weight *=
norm;
95 getTransformedMixtureParameters(
96 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
98 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
100 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
102 const double pathlengthInX0,
103 const int numberOfComponents)
105 BH::MixtureParameters mixture{};
106 for (
int i = 0;
i < numberOfComponents; ++
i) {
107 const double updatedWeight =
108 hornerEvaluate(polynomialWeights[
i], pathlengthInX0);
109 const double updatedMean =
110 hornerEvaluate(polynomialMeans[
i], pathlengthInX0);
111 const double updatedVariance =
112 hornerEvaluate(polynomialVariances[
i], pathlengthInX0);
113 mixture[
i] = { logisticFunction(updatedWeight),
114 logisticFunction(updatedMean),
120 BH::MixtureParameters
121 getMixtureParameters(
122 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
124 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
126 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>&
128 const double pathlengthInX0,
129 const int numberOfComponents)
131 BH::MixtureParameters mixture{};
132 for (
int i = 0;
i < numberOfComponents; ++
i) {
133 const double updatedWeight =
134 hornerEvaluate(polynomialWeights[
i], pathlengthInX0);
135 const double updatedMean =
136 hornerEvaluate(polynomialMeans[
i], pathlengthInX0);
137 const double updatedVariance =
138 hornerEvaluate(polynomialVariances[
i], pathlengthInX0);
139 mixture[
i] = { updatedWeight,
141 updatedVariance * updatedVariance };
157 const AmgSymMatrix(5)* measuredTrackCov = trackParameters->covariance();
159 if (!measuredTrackCov) {
164 const double p = globalMomentum.mag();
165 double pathcorrection = 1.;
166 if (materialProperties.
thickness() != 0) {
167 pathcorrection = pathLength / materialProperties.
thickness();
169 const double t = pathcorrection * materialProperties.
thicknessInX0();
171 const double E = sqrt(
p *
p +
m *
m);
172 const double beta =
p /
E;
174 const double angularVariation =
sigma *
sigma;
178 cache.
deltaPhiCov = angularVariation / (sinTheta * sinTheta);
183 readPolynomial(std::ifstream&
fin)
188 throw std::logic_error(
"Reached end of stream but still expecting data.");
199 const std::string& parameterisationFileName,
200 const std::string& parameterisationFileNameHighX0)
206 std::string resolvedFileName =
208 if (resolvedFileName.empty()) {
209 std::ostringstream
ss;
210 ss <<
"Parameterisation file : " << parameterisationFileName
212 throw std::logic_error(
ss.str());
215 const char*
filename = resolvedFileName.c_str();
218 std::ostringstream
ss;
219 ss <<
"Error opening file: " << resolvedFileName;
220 throw std::logic_error(
ss.str());
224 int orderPolynomial = 0;
225 fin >> orderPolynomial;
229 std::ostringstream
ss;
230 ss <<
"numberOfComponents Parameter out of range 0- "
233 throw std::logic_error(
ss.str());
236 std::ostringstream
ss;
237 ss <<
"orderPolynomial order != "
239 throw std::logic_error(
ss.str());
242 std::ostringstream
ss;
243 ss <<
"transformationCode Parameter out of range 0-1: "
245 throw std::logic_error(
ss.str());
248 std::ostringstream
ss;
249 ss <<
"Error while reading file : " << resolvedFileName;
250 throw std::logic_error(
ss.str());
253 int componentIndex = 0;
262 std::string resolvedFileName =
264 if (resolvedFileName.empty()) {
265 std::ostringstream
ss;
266 ss <<
"Parameterisation file : " << parameterisationFileNameHighX0
268 throw std::logic_error(
ss.str());
271 const char*
filename = resolvedFileName.c_str();
274 std::ostringstream
ss;
275 ss <<
"Error opening file: " << resolvedFileName;
276 throw std::logic_error(
ss.str());
279 int orderPolynomial = 0;
280 fin >> orderPolynomial;
286 std::ostringstream
ss;
287 ss <<
"numberOfComponentsHighX0 Parameter out of range 0- "
290 throw std::logic_error(
ss.str());
293 std::ostringstream
ss;
294 ss <<
" numberOfComponentsHighX0 != numberOfComponents";
295 throw std::logic_error(
ss.str());
298 std::ostringstream
ss;
299 ss <<
"orderPolynomial order != "
301 throw std::logic_error(
ss.str());
304 std::ostringstream
ss;
305 ss <<
"transformationCode Parameter out of range "
308 throw std::logic_error(
ss.str());
312 int componentIndex = 0;
335 cache_multipleScatter, componentParameters, materialProperties, pathLength);
340 this->BetheHeitler(cache_energyLoss,
350 cache_energyLoss.
elements[0] = { 1, 0, 0 };
359 double combinedWeight = cache_energyLoss.
elements[
i].weight;
360 double combinedDeltaP = cache_energyLoss.
elements[
i].deltaP;
365 const double covPhi = cache_multipleScatter.
deltaPhiCov;
367 const double covQoverP = cache_energyLoss.
elements[
i].deltaQOvePCov;
371 0, 0, 0, covTheta, 0,
372 0, 0, 0, 0, covQoverP;
397 const double radiationLength = materialProperties.
x0();
398 const double momentum = globalMomentum.mag();
399 double pathlengthInX0 = pathLength / radiationLength;
401 if (pathlengthInX0 < s_singleGaussianRange) {
409 if (pathlengthInX0 < s_lowerRange) {
410 const double meanZ =
std::exp(-1. * pathlengthInX0);
416 double varQoverP(0.);
424 cache.
elements[0] = { 1., deltaP, varQoverP };
430 if (pathlengthInX0 > s_upperRange) {
431 pathlengthInX0 = s_upperRange;
436 if (pathlengthInX0 > s_xOverRange) {
437 if (m_BHtransformationCodeHighX0) {
438 mixture = getTransformedMixtureParameters(m_BHpolynomialWeightsHighX0,
439 m_BHpolynomialMeansHighX0,
440 m_BHpolynomialVariancesHighX0,
442 m_BHnumberOfComponents);
444 mixture = getMixtureParameters(m_BHpolynomialWeightsHighX0,
445 m_BHpolynomialMeansHighX0,
446 m_BHpolynomialVariancesHighX0,
448 m_BHnumberOfComponents);
451 if (m_BHtransformationCode) {
452 mixture = getTransformedMixtureParameters(m_BHpolynomialWeights,
454 m_BHpolynomialVariances,
456 m_BHnumberOfComponents);
458 mixture = getMixtureParameters(m_BHpolynomialWeights,
460 m_BHpolynomialVariances,
462 m_BHnumberOfComponents);
466 correctWeights(mixture, m_BHnumberOfComponents);
467 int componentIndex = 0;
468 double weightToBeRemoved(0.);
469 int componentWithHighestMean(0);
470 for (; componentIndex < m_BHnumberOfComponents; ++componentIndex) {
471 if (mixture[componentIndex].
mean > mixture[componentWithHighestMean].
mean) {
472 componentWithHighestMean = componentIndex;
474 if (mixture[componentIndex].
mean >= s_componentMeanCut) {
477 weightToBeRemoved += mixture[componentIndex].weight;
481 for (; componentIndex < m_BHnumberOfComponents; ++componentIndex) {
482 double varianceInverseMomentum = 0;
484 if (mixture[componentIndex].
mean < s_componentMeanCut) {
487 double weight = mixture[componentIndex].weight;
488 if (componentIndex == componentWithHighestMean) {
489 weight += weightToBeRemoved;
494 deltaP =
momentum * (mixture[componentIndex].mean - 1.);
495 const double f = 1. / (
momentum * mixture[componentIndex].mean);
496 varianceInverseMomentum =
f *
f * mixture[componentIndex].variance;
500 deltaP =
momentum * (1. / mixture[componentIndex].mean - 1.);
501 varianceInverseMomentum =
508 varianceInverseMomentum };