File indexing completed on 2025-10-14 08:01:37
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsPlugins/EDM4hep/EDM4hepUtil.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/EventData/MultiTrajectory.hpp"
0015 #include "Acts/EventData/MultiTrajectoryHelpers.hpp"
0016 #include "Acts/Propagator/detail/CovarianceEngine.hpp"
0017 #include "Acts/Propagator/detail/JacobianEngine.hpp"
0018
0019 #include <numbers>
0020
0021 #include <edm4hep/EDM4hepVersion.h>
0022 #include <edm4hep/MCParticle.h>
0023 #include <edm4hep/MutableSimTrackerHit.h>
0024 #include <edm4hep/SimTrackerHit.h>
0025 #include <edm4hep/TrackState.h>
0026
0027 using namespace Acts;
0028 using namespace Acts::detail;
0029
0030 namespace ActsPlugins::EDM4hepUtil {
0031 namespace detail {
0032
0033 ActsSquareMatrix<6> jacobianToEdm4hep(double theta, double qOverP, double Bz) {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 ActsSquareMatrix<6> J;
0059 J.setIdentity();
0060 double sinTheta = std::sin(theta);
0061 J(3, 3) = -1.0 / (sinTheta * sinTheta);
0062 J(4, 4) = Bz / sinTheta;
0063 J(4, 3) = -Bz * qOverP * std::cos(theta) /
0064 (sinTheta * sinTheta);
0065 return J;
0066 }
0067
0068 ActsSquareMatrix<6> jacobianFromEdm4hep(double tanLambda, double omega,
0069 double Bz) {
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 ActsSquareMatrix<6> J;
0094 J.setIdentity();
0095 J(3, 3) = -1 / (tanLambda * tanLambda + 1);
0096 J(4, 3) = -1 * omega * tanLambda /
0097 (Bz * std::pow(tanLambda * tanLambda + 1, 3. / 2.));
0098 J(4, 4) = 1 / (Bz * std::hypot(tanLambda, 1));
0099
0100 return J;
0101 }
0102
0103 void packCovariance(const ActsSquareMatrix<6>& from, float* to) {
0104 for (int i = 0; i < from.rows(); i++) {
0105 for (int j = 0; j <= i; j++) {
0106 std::size_t k = (i + 1) * i / 2 + j;
0107 to[k] = from(i, j);
0108 }
0109 }
0110 }
0111
0112 void unpackCovariance(const float* from, ActsSquareMatrix<6>& to) {
0113 auto k = [](std::size_t i, std::size_t j) { return (i + 1) * i / 2 + j; };
0114 for (int i = 0; i < to.rows(); i++) {
0115 for (int j = 0; j < to.cols(); j++) {
0116 to(i, j) = from[j <= i ? k(i, j) : k(j, i)];
0117 }
0118 }
0119 }
0120
0121 Parameters convertTrackParametersToEdm4hep(const GeometryContext& gctx,
0122 double Bz,
0123 const BoundTrackParameters& params) {
0124 Vector3 global = params.referenceSurface().localToGlobal(
0125 gctx, params.parameters().template head<2>(), params.direction());
0126
0127 std::shared_ptr<const Surface> refSurface =
0128 params.referenceSurface().getSharedPtr();
0129 BoundVector targetPars = params.parameters();
0130 std::optional<BoundSquareMatrix> targetCov = params.covariance();
0131
0132
0133
0134
0135 if (dynamic_cast<const PerigeeSurface*>(refSurface.get()) == nullptr) {
0136 refSurface = Surface::makeShared<PerigeeSurface>(global);
0137
0138
0139
0140
0141
0142 auto perigeeParams =
0143 boundToBoundConversion(gctx, params, *refSurface, Vector3{0, 0, Bz})
0144 .value();
0145 targetPars = perigeeParams.parameters();
0146 targetCov = perigeeParams.covariance();
0147 }
0148
0149 Parameters result;
0150 result.surface = refSurface;
0151
0152
0153 if (targetCov) {
0154 ActsSquareMatrix<6> J = jacobianToEdm4hep(targetPars[eBoundTheta],
0155 targetPars[eBoundQOverP], Bz);
0156 result.covariance = J * targetCov.value() * J.transpose();
0157 }
0158
0159 result.values[0] = targetPars[eBoundLoc0];
0160 result.values[1] = targetPars[eBoundLoc1];
0161 result.values[2] = targetPars[eBoundPhi];
0162 result.values[3] = std::tan(std::numbers::pi / 2. - targetPars[eBoundTheta]);
0163 result.values[4] =
0164 targetPars[eBoundQOverP] / std::sin(targetPars[eBoundTheta]) * Bz;
0165 result.values[5] = targetPars[eBoundTime];
0166
0167 result.particleHypothesis = params.particleHypothesis();
0168
0169 return result;
0170 }
0171
0172 BoundTrackParameters convertTrackParametersFromEdm4hep(
0173 double Bz, const Parameters& params) {
0174 BoundVector targetPars;
0175
0176 ActsSquareMatrix<6> J =
0177 jacobianFromEdm4hep(params.values[3], params.values[4], Bz);
0178
0179 std::optional<BoundMatrix> cov;
0180 if (params.covariance.has_value()) {
0181 cov = J * params.covariance.value() * J.transpose();
0182 }
0183
0184 targetPars[eBoundLoc0] = params.values[0];
0185 targetPars[eBoundLoc1] = params.values[1];
0186 targetPars[eBoundPhi] = params.values[2];
0187 targetPars[eBoundTheta] = std::numbers::pi / 2. - std::atan(params.values[3]);
0188 targetPars[eBoundQOverP] =
0189 params.values[4] * std::sin(targetPars[eBoundTheta]) / Bz;
0190 targetPars[eBoundTime] = params.values[5];
0191
0192 return {params.surface, targetPars, cov, params.particleHypothesis};
0193 }
0194
0195 }
0196
0197 #if EDM4HEP_VERSION_MAJOR >= 1 || \
0198 (EDM4HEP_VERSION_MAJOR == 0 && EDM4HEP_VERSION_MINOR == 99)
0199 edm4hep::MCParticle getParticle(const edm4hep::SimTrackerHit& hit) {
0200 return hit.getParticle();
0201 }
0202
0203 void setParticle(edm4hep::MutableSimTrackerHit& hit,
0204 const edm4hep::MCParticle& particle) {
0205 hit.setParticle(particle);
0206 }
0207 #else
0208 edm4hep::MCParticle getParticle(const edm4hep::SimTrackerHit& hit) {
0209 return hit.getMCParticle();
0210 }
0211
0212 void setParticle(edm4hep::MutableSimTrackerHit& hit,
0213 const edm4hep::MCParticle& particle) {
0214 hit.setMCParticle(particle);
0215 }
0216 #endif
0217
0218 }