37 const AmgSymMatrix(5)* measuredTrackCov = trackParameters->covariance();
39 if (!measuredTrackCov) {
44 const double p = globalMomentum.mag();
45 double pathcorrection = 1.;
46 if (materialProperties.
thickness() != 0) {
47 pathcorrection = pathLength / materialProperties.
thickness();
49 const double t = pathcorrection * materialProperties.
thicknessInX0();
51 const double E = std::sqrt(
p *
p +
m *
m);
58 cache.
deltaPhiCov = angularVariation / (sinTheta * sinTheta);
64 constexpr
double s_singleGaussianRange = 0.0001;
65 constexpr
double s_lowerRange = 0.002;
66 constexpr
double s_xOverRange = 0.10;
67 constexpr
double s_upperRange = 0.20;
68 constexpr
double s_componentMeanCut = 0.0;
71 using polyArray = std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>;
76 inline constexpr
double
77 hornerEvaluate(
const std::array<double, N>&
a,
const double&
x)
79 constexpr
size_t order =
N - 1;
80 if constexpr (
order == 0) {
82 }
else if constexpr (
order == 1) {
83 return a[0] *
x +
a[1];
84 }
else if constexpr (
order == 2) {
85 return (
a[0] *
x +
a[1]) *
x +
a[2];
86 }
else if constexpr (
order == 3) {
87 return ((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3];
88 }
else if constexpr (
order == 4) {
89 return (((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4];
90 }
else if constexpr (
order == 5) {
91 return ((((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4]) *
x +
a[5];
94 ((((
a[0] *
x +
a[1]) *
x +
a[2]) *
x +
a[3]) *
x +
a[4]) *
x +
a[5];
95 for (
size_t i = 6;
i <
N; ++
i) {
103 logisticFunction(
const double x)
110 correctWeights(BH::MixtureParameters& mixture,
const int numberOfComponents)
112 if (numberOfComponents < 1) {
116 double weightSum(0.);
117 for (
int i = 0;
i < numberOfComponents; ++
i) {
118 weightSum += mixture[
i].weight;
120 const double norm = 1. / weightSum;
122 for (
int i = 0;
i < numberOfComponents; ++
i) {
123 mixture[
i].weight *=
norm;
127 BH::MixtureParameters
128 getTransformedMixtureParameters(
129 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>& polynomialWeights,
130 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>& polynomialMeans,
131 const std::array<BH::Polynomial, GSFConstants::maxNumberofMatComponents>& polynomialVariances,
132 const double pathlengthInX0,
133 const int numberOfComponents)
135 BH::MixtureParameters mixture{};
137 for (
int i = 0;
i < numberOfComponents; ++
i) {
138 const double updatedWeight = hornerEvaluate(polynomialWeights[
i], pathlengthInX0);
139 const double updatedMean = hornerEvaluate(polynomialMeans[
i], pathlengthInX0);
140 const double updatedVariance = hornerEvaluate(polynomialVariances[
i], pathlengthInX0);
141 mixture[
i] = { logisticFunction(updatedWeight),
142 logisticFunction(updatedMean),
153 inline constexpr
bool inRange(
int var,
int lo,
int hi) {
154 return ((
var <= hi) and (
var >= lo));
157 BH::Polynomial readPolynomial(std::ifstream&
fin) {
158 BH::Polynomial
poly{};
161 throw std::logic_error(
"Reached end of stream but still expecting data.");
172 polyArray variances{};
173 int numberOfComponents{};
177 readPolys fillFromFile(
const std::string&
fileName) {
184 std::ostringstream
ss;
186 throw std::logic_error(
ss.str());
191 int orderPolynomial = 0;
192 fin >> orderPolynomial;
195 std::ostringstream
ss;
196 ss <<
"numberOfComponents Parameter out of range 0- "
198 <<
result.numberOfComponents;
199 throw std::logic_error(
ss.str());
202 std::ostringstream
ss;
203 ss <<
"orderPolynomial order != "
205 throw std::logic_error(
ss.str());
209 int componentIndex = 0;
210 for (; componentIndex <
result.numberOfComponents; ++componentIndex) {
211 result.weights[componentIndex] = readPolynomial(
fin);
212 result.means[componentIndex] = readPolynomial(
fin);
213 result.variances[componentIndex] = readPolynomial(
fin);
222 const std::string& parameterisationFileName,
223 const std::string& parameterisationFileNameHighX0) {
226 const std::string resolvedFileName =
228 if (resolvedFileName.empty()) {
229 std::ostringstream
ss;
230 ss <<
"Parameterisation file : " << parameterisationFileName
232 throw std::logic_error(
ss.str());
235 readPolys readin = fillFromFile(resolvedFileName);
243 const std::string resolvedFileName =
245 if (resolvedFileName.empty()) {
246 std::ostringstream
ss;
247 ss <<
"Parameterisation file : " << parameterisationFileNameHighX0
249 throw std::logic_error(
ss.str());
251 readPolys readin = fillFromFile(resolvedFileName);
258 std::ostringstream
ss;
259 ss <<
" numberOfComponentsHighX0 != numberOfComponents";
260 throw std::logic_error(
ss.str());
277 scattering(cache_multipleScatter, componentParameters, materialProperties, pathLength);
283 this->BetheHeitler(cache_energyLoss,
291 cache_energyLoss.
elements[0] = { 1, 0, 0 };
303 const double covPhi = cache_multipleScatter.
deltaPhiCov;
305 const double covQoverP = cache_energyLoss.
elements[
i].deltaQOvePCov;
311 0, 0, 0, covTheta, 0,
312 0, 0, 0, 0, covQoverP;
337 const double radiationLength = materialProperties.
x0();
338 const double momentum = globalMomentum.mag();
339 double pathlengthInX0 = pathLength / radiationLength;
341 if (pathlengthInX0 < s_singleGaussianRange) {
349 if (pathlengthInX0 < s_lowerRange) {
350 const double meanZ =
std::exp(-1. * pathlengthInX0);
356 double varQoverP(0.);
364 cache.
elements[0] = { 1., deltaP, varQoverP };
369 if (pathlengthInX0 > s_upperRange) {
370 pathlengthInX0 = s_upperRange;
375 if (pathlengthInX0 > s_xOverRange) {
376 mixture = getTransformedMixtureParameters(m_BHpolynomialWeightsHighX0,
377 m_BHpolynomialMeansHighX0,
378 m_BHpolynomialVariancesHighX0,
380 m_BHnumberOfComponents);
382 mixture = getTransformedMixtureParameters(m_BHpolynomialWeights,
384 m_BHpolynomialVariances,
386 m_BHnumberOfComponents);
389 correctWeights(mixture, m_BHnumberOfComponents);
390 int componentIndex = 0;
391 double weightToBeRemoved(0.);
392 int componentWithHighestMean(0);
394 for (; componentIndex < m_BHnumberOfComponents; ++componentIndex) {
395 if (mixture[componentIndex].
mean > mixture[componentWithHighestMean].
mean) {
396 componentWithHighestMean = componentIndex;
398 if (mixture[componentIndex].
mean >= s_componentMeanCut) {
401 weightToBeRemoved += mixture[componentIndex].weight;
405 for (; componentIndex < m_BHnumberOfComponents; ++componentIndex) {
406 double varianceInverseMomentum = 0;
409 if (mixture[componentIndex].
mean < s_componentMeanCut) {
413 double weight = mixture[componentIndex].weight;
414 if (componentIndex == componentWithHighestMean) {
415 weight += weightToBeRemoved;
420 deltaP =
momentum * (mixture[componentIndex].mean - 1.);
421 const double f = 1. / (
momentum * mixture[componentIndex].mean);
422 varianceInverseMomentum =
f *
f * mixture[componentIndex].variance;
424 deltaP =
momentum * (1. / mixture[componentIndex].mean - 1.);
425 varianceInverseMomentum = mixture[componentIndex].variance / (
momentum *
momentum);
431 varianceInverseMomentum };