ATLAS Offline Software
Loading...
Searching...
No Matches
MultiComponentStateCombiner.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
12
15//
16#include "CxxUtils/phihelper.h"
19
20namespace {
21
22struct MeanAndCovariance {
23 AmgVector(5) mean;
24 AmgSymMatrix(5) covariance;
25 double sumW = 0;
26};
27
38MeanAndCovariance
39findMeanAndCovariance(const Trk::MultiComponentState& uncombinedState) {
40
41 MeanAndCovariance toReturn;
42 toReturn.mean.setZero();
43 AmgSymMatrix(5) covariancePart1;
44 covariancePart1.setZero();
45 AmgSymMatrix(5) covariancePart2;
46 covariancePart2.setZero();
47 const double phiOfFirst = uncombinedState[0].params->parameters()[2];
48 const size_t numComponents = uncombinedState.size();
49 for (size_t i = 0; i < numComponents; ++i) {
50 const Trk::TrackParameters* trackParameters = uncombinedState[i].params.get();
51 const double weight = uncombinedState[i].weight;
52 AmgVector(5) parameters = trackParameters->parameters();
53 // Ensure that we don't have any problems with the cyclical nature of phi
54 // Use first state as reference poin
55 const double deltaPhi = phiOfFirst - parameters[2];
56 if (deltaPhi > M_PI) {
57 parameters[2] += 2 * M_PI;
58 } else if (deltaPhi < -M_PI) {
59 parameters[2] -= 2 * M_PI;
60 }
61 toReturn.sumW += weight;
62 toReturn.mean += weight * parameters;
63 // Extract local error matrix: Must make sure track parameters are
64 // measured, ie have an associated error matrix.
65 const AmgSymMatrix(5)* measuredCov = trackParameters->covariance();
66 // Calculate the combined covariance matrix
67 if (measuredCov) {
68 covariancePart1 += weight * (*measuredCov);
69 // Loop over all remaining components to find the second part of the
70 // covariance
71 for (size_t j = i + 1; j < numComponents; ++j) {
72 AmgVector(5) parameterDifference =
73 parameters - uncombinedState[j].params->parameters();
74 const double remainingWeight = uncombinedState[j].weight;
75 covariancePart2 += weight * remainingWeight * parameterDifference *
76 parameterDifference.transpose();
77
78 } // end loop over remaining components
79 } // end clause if errors are involved
80 } // end loop over all components
81 toReturn.mean /= toReturn.sumW;
82 // Ensure that phi is between -pi and pi
83 toReturn.mean[2] = CxxUtils::wrapToPi(toReturn.mean[2]);
84 toReturn.covariance = covariancePart1 / toReturn.sumW + covariancePart2 / (toReturn.sumW * toReturn.sumW);
85 return toReturn;
86}
87
88// Actual implementation method for combining
89// a multi component state.
90// Imoplements the mode option
91Trk::ComponentParameters combineToSingleImpl(
92 const Trk::MultiComponentState& uncombinedState, const bool useMode) {
93
94 if (uncombinedState.empty()) {
95 return {};
96 }
97 const Trk::TrackParameters* firstParameters = uncombinedState.front().params.get();
98
99 if (uncombinedState.size() == 1) {
100 return {uncombinedState.front().params->uniqueClone(),
101 uncombinedState.front().weight};
102 }
103
104 MeanAndCovariance res = findMeanAndCovariance (uncombinedState);
105
106 const int dimension = (uncombinedState.front()).params->parameters().rows();
107 if (useMode && dimension == 5) {
108 // Calculate the mode of the q/p distribution
109 std::array<double, 10> modes =
111 // Replace res.mean with mode if qOverP mode is not 0
112 if (modes[4] != 0) {
113 res.mean[0] = modes[0];
114 res.mean[1] = modes[1];
115 res.mean[2] = modes[2];
116 res.mean[3] = modes[3];
117 res.mean[4] = modes[4];
118
119 if (modes[5 + 0] > 0) {
120 double currentErr = sqrt((res.covariance)(0, 0));
121 currentErr = modes[5 + 0] / currentErr;
122 (res.covariance)(0, 0) = modes[5 + 0] * modes[5 + 0];
123 res.covariance.fillSymmetric(1, 0, (res.covariance)(1, 0) * currentErr);
124 res.covariance.fillSymmetric(2, 0, (res.covariance)(2, 0) * currentErr);
125 res.covariance.fillSymmetric(3, 0, (res.covariance)(3, 0) * currentErr);
126 res.covariance.fillSymmetric(4, 0, (res.covariance)(4, 0) * currentErr);
127 }
128 if (modes[5 + 1] > 0) {
129 double currentErr = sqrt((res.covariance)(1, 1));
130 currentErr = modes[5 + 1] / currentErr;
131 res.covariance.fillSymmetric(1, 0, (res.covariance)(1, 0) * currentErr);
132 (res.covariance)(1, 1) = modes[5 + 1] * modes[5 + 1];
133 res.covariance.fillSymmetric(2, 1, (res.covariance)(2, 1) * currentErr);
134 res.covariance.fillSymmetric(3, 1, (res.covariance)(3, 1) * currentErr);
135 res.covariance.fillSymmetric(4, 1, (res.covariance)(4, 1) * currentErr);
136 }
137 if (modes[5 + 2] > 0) {
138 double currentErr = sqrt((res.covariance)(2, 2));
139 currentErr = modes[5 + 2] / currentErr;
140 res.covariance.fillSymmetric(2, 0, (res.covariance)(2, 0) * currentErr);
141 res.covariance.fillSymmetric(2, 1, (res.covariance)(2, 1) * currentErr);
142 (res.covariance)(2, 2) = modes[5 + 2] * modes[5 + 2];
143 res.covariance.fillSymmetric(3, 2, (res.covariance)(3, 2) * currentErr);
144 res.covariance.fillSymmetric(4, 2, (res.covariance)(4, 2) * currentErr);
145 }
146 if (modes[5 + 3] > 0) {
147 double currentErr = sqrt((res.covariance)(3, 3));
148 currentErr = modes[5 + 3] / currentErr;
149 res.covariance.fillSymmetric(3, 0, (res.covariance)(3, 0) * currentErr);
150 res.covariance.fillSymmetric(3, 1, (res.covariance)(3, 1) * currentErr);
151 res.covariance.fillSymmetric(3, 2, (res.covariance)(3, 2) * currentErr);
152 (res.covariance)(3, 3) = modes[5 + 3] * modes[5 + 3];
153 res.covariance.fillSymmetric(4, 3, (res.covariance)(4, 3) * currentErr);
154 }
155 if (modes[5 + 4] > 0) {
156 double currentErr = sqrt((res.covariance)(4, 4));
157 currentErr = modes[5 + 4] / currentErr;
158 res.covariance.fillSymmetric(4, 0, (res.covariance)(4, 0) * currentErr);
159 res.covariance.fillSymmetric(4, 1, (res.covariance)(4, 1) * currentErr);
160 res.covariance.fillSymmetric(4, 2, (res.covariance)(4, 2) * currentErr);
161 res.covariance.fillSymmetric(4, 3, (res.covariance)(4, 3) * currentErr);
162 (res.covariance)(4, 4) = modes[5 + 4] * modes[5 + 4];
163 }
164
165 } // modes[4]!=0
166 } // useMode && dimensions==5
167
168 std::unique_ptr<Trk::TrackParameters> combinedTrackParameters = nullptr;
169 double const loc1 = res.mean[Trk::loc1];
170 double const loc2 = res.mean[Trk::loc2];
171 double const phi = res.mean[Trk::phi];
172 double const theta = res.mean[Trk::theta];
173 double const qoverp = res.mean[Trk::qOverP];
174 const AmgSymMatrix(5)* firstMeasuredCov = firstParameters->covariance();
175 if (firstMeasuredCov) {
176 combinedTrackParameters =
178 loc1, loc2, phi, theta, qoverp, std::move(res.covariance));
179 } else {
180 combinedTrackParameters =
182 loc1, loc2, phi, theta, qoverp, std::nullopt);
183 }
184
185 return {std::move(combinedTrackParameters), res.sumW};
186}
187} // end anonymous namespace
188
189std::unique_ptr<Trk::TrackParameters>
191const Trk::MultiComponentState& uncombinedState, const bool useMode) {
192 Trk::ComponentParameters combinedComponent = combineToSingleImpl(uncombinedState, useMode);
193 return std::move(combinedComponent.params);
194}
195
196
197// The following does heave use of Eigen
198// for covariance. Avoid out-of-line calls.
200void
202 AmgVector(5) & firstParameters,
203 double& firstWeight,
204 const AmgVector(5) & secondParameters,
205 const double secondWeight)
206{
207 double const totalWeight = firstWeight + secondWeight;
208 double const invTotalWeight = 1.0/totalWeight;
209 double const deltaPhi = firstParameters[2] - secondParameters[2];
210 if (deltaPhi > M_PI) {
211 firstParameters[2] -= 2 * M_PI;
212 } else if (deltaPhi < -M_PI) {
213 firstParameters[2] += 2 * M_PI;
214 }
215 firstParameters =
216 (firstWeight * firstParameters + secondWeight * secondParameters) *
217 invTotalWeight;
218 // Ensure that phi is between -pi and pi
219 firstParameters[2] = CxxUtils::wrapToPi(firstParameters[2]);
220 firstWeight = totalWeight;
221}
222
223// The following does heave use of Eigen
224// for covariance. Avoid out-of-line calls.
226void
228 const AmgVector(5) & firstParameters,
229 AmgSymMatrix(5) & firstMeasuredCov,
230 const double firstWeight,
231 const AmgVector(5) & secondParameters,
232 const AmgSymMatrix(5) & secondMeasuredCov,
233 const double secondWeight)
234{
235 double const invTotalWeight = 1.0/(firstWeight + secondWeight);
236 AmgVector(5) parameterDifference = firstParameters - secondParameters;
237 parameterDifference[2] = CxxUtils::wrapToPi(parameterDifference[2]);
238 parameterDifference *= invTotalWeight;
239 firstMeasuredCov = (firstWeight * firstMeasuredCov + secondWeight * secondMeasuredCov) * invTotalWeight;
240 firstMeasuredCov += firstWeight * secondWeight * parameterDifference * parameterDifference.transpose();
241}
242
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
Scalar theta() const
theta method
#define AmgSymMatrix(dim)
#define AmgVector(rows)
std::pair< std::vector< unsigned int >, bool > res
if(febId1==febId2)
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
#define ATH_FLATTEN
float modes(const std::vector< float > &mus, const std::vector< float > &log_sigma2s, const std::vector< float > &alphas)
T wrapToPi(T phi)
Wrap angle in radians to [-pi, pi].
Definition phihelper.h:24
void combineParametersWithWeight(AmgVector(5) &firstParameters, double &firstWeight, const AmgVector(5) &secondParameters, const double secondWeight)
Combine parameters based on their relevant weigths.
void combineCovWithWeight(const AmgVector(5) &firstParameters, AmgSymMatrix(5) &firstMeasuredCov, const double firstWeight, const AmgVector(5) &secondParameters, const AmgSymMatrix(5) &secondMeasuredCov, const double secondWeight)
Combine cov matrices based on their relevant weights.
std::unique_ptr< Trk::TrackParameters > combineToSingle(const MultiComponentState &, const bool useMode=false)
@bried Calculate combined state of many components
std::array< double, 10 > calculateMode(const MultiComponentState &)
Method to calculate mode with MultiComponentState state as input.
std::vector< ComponentParameters > MultiComponentState
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ phi
Definition ParamDefs.h:75
@ loc1
Definition ParamDefs.h:34
ParametersBase< TrackParametersDim, Charged > TrackParameters
Helper for azimuthal angle calculations.
std::unique_ptr< Trk::TrackParameters > params