File indexing completed on 2026-05-10 08:16:04
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "Acts/Definitions/Algebra.hpp"
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/Charge.hpp"
0013 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0014 #include "Acts/EventData/MultiTrajectory.hpp"
0015 #include "Acts/EventData/TrackContainer.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/EventData/TrackProxyConcept.hpp"
0018 #include "Acts/EventData/TrackStatePropMask.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Surfaces/PerigeeSurface.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 #include "Acts/Utilities/UnitVectors.hpp"
0024
0025 #include <stdexcept>
0026
0027 #include <Eigen/src/Core/util/Memory.h>
0028 #include <boost/graph/graph_traits.hpp>
0029 #include <edm4hep/MCParticle.h>
0030 #include <edm4hep/MutableSimTrackerHit.h>
0031 #include <edm4hep/MutableTrack.h>
0032 #include <edm4hep/SimTrackerHit.h>
0033 #include <edm4hep/Track.h>
0034 #include <edm4hep/TrackState.h>
0035 #include <podio/podioVersion.h>
0036
0037 #if podio_VERSION_MAJOR == 0 || \
0038 (podio_VERSION_MAJOR == 1 && podio_VERSION_MINOR <= 2)
0039
0040 template <>
0041 struct std::hash<podio::ObjectID> {
0042 std::size_t operator()(const podio::ObjectID& id) const noexcept {
0043 auto hash_collectionID = std::hash<std::uint32_t>{}(id.collectionID);
0044 auto hash_index = std::hash<int>{}(id.index);
0045
0046 return hash_collectionID ^ hash_index;
0047 }
0048 };
0049
0050 #endif
0051
0052 namespace ActsPlugins::EDM4hepUtil {
0053
0054 static constexpr std::int32_t EDM4HEP_ACTS_POSITION_TYPE = 42;
0055
0056 namespace detail {
0057 struct Parameters {
0058 Acts::ActsVector<6> values{};
0059
0060 Acts::ParticleHypothesis particleHypothesis =
0061 Acts::ParticleHypothesis::pion();
0062 std::optional<Acts::BoundSquareMatrix> covariance;
0063 std::shared_ptr<const Acts::Surface> surface;
0064 };
0065
0066 Acts::ActsSquareMatrix<6> jacobianToEdm4hep(double theta, double qOverP,
0067 double Bz);
0068
0069 Acts::ActsSquareMatrix<6> jacobianFromEdm4hep(double tanLambda, double omega,
0070 double Bz);
0071
0072 void unpackCovariance(const float* from, Acts::ActsSquareMatrix<6>& to);
0073 void packCovariance(const Acts::ActsSquareMatrix<6>& from, float* to);
0074
0075 Parameters convertTrackParametersToEdm4hep(
0076 const Acts::GeometryContext& gctx, double Bz,
0077 const Acts::BoundTrackParameters& params);
0078
0079 Acts::BoundTrackParameters convertTrackParametersFromEdm4hep(
0080 double Bz, const Parameters& params);
0081
0082 }
0083
0084
0085 edm4hep::MCParticle getParticle(const edm4hep::SimTrackerHit& hit);
0086
0087 void setParticle(edm4hep::MutableSimTrackerHit& hit,
0088 const edm4hep::MCParticle& particle);
0089
0090 template <Acts::TrackProxyConcept track_proxy_t>
0091 void writeTrack(const Acts::GeometryContext& gctx, track_proxy_t track,
0092 edm4hep::MutableTrack to, double Bz,
0093 const Acts::Logger& logger = Acts::getDummyLogger()) {
0094 ACTS_VERBOSE("Converting track to EDM4hep");
0095 to.setChi2(track.chi2());
0096 to.setNdf(track.nDoF());
0097
0098 std::vector<edm4hep::TrackState> outTrackStates;
0099 outTrackStates.reserve(track.nTrackStates());
0100
0101 auto setParameters = [](edm4hep::TrackState& trackState,
0102 const detail::Parameters& params) {
0103 trackState.D0 = params.values[0];
0104 trackState.Z0 = params.values[1];
0105 trackState.phi = params.values[2];
0106 trackState.tanLambda = params.values[3];
0107 trackState.omega = params.values[4];
0108 trackState.time = params.values[5];
0109
0110 if (params.covariance) {
0111 detail::packCovariance(params.covariance.value(),
0112 trackState.covMatrix.data());
0113 }
0114 };
0115
0116 ACTS_VERBOSE("Converting " << track.nTrackStates() << " track states");
0117
0118 for (const auto& state : track.trackStatesReversed()) {
0119 auto typeFlags = state.typeFlags();
0120 if (!typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) {
0121 continue;
0122 }
0123
0124 edm4hep::TrackState& trackState = outTrackStates.emplace_back();
0125 trackState.location = edm4hep::TrackState::AtOther;
0126
0127 Acts::BoundTrackParameters params{state.referenceSurface().getSharedPtr(),
0128 state.parameters(), state.covariance(),
0129 track.particleHypothesis()};
0130
0131
0132 detail::Parameters converted =
0133 detail::convertTrackParametersToEdm4hep(gctx, Bz, params);
0134
0135
0136 setParameters(trackState, converted);
0137 ACTS_VERBOSE("- parameters: " << state.parameters().transpose() << " -> "
0138 << converted.values.transpose());
0139 ACTS_VERBOSE("- covariance: \n"
0140 << state.covariance() << "\n->\n"
0141 << converted.covariance.value());
0142
0143
0144
0145 auto center = converted.surface->center(gctx);
0146 trackState.referencePoint.x = center.x();
0147 trackState.referencePoint.y = center.y();
0148 trackState.referencePoint.z = center.z();
0149 ACTS_VERBOSE("- ref surface ctr: " << center.transpose());
0150 }
0151 outTrackStates.front().location = edm4hep::TrackState::AtLastHit;
0152 outTrackStates.back().location = edm4hep::TrackState::AtFirstHit;
0153
0154
0155 auto& ipState = outTrackStates.emplace_back();
0156
0157
0158 Acts::BoundTrackParameters trackParams{
0159 track.referenceSurface().getSharedPtr(), track.parameters(),
0160 track.covariance(), track.particleHypothesis()};
0161
0162
0163 auto converted =
0164 detail::convertTrackParametersToEdm4hep(gctx, Bz, trackParams);
0165 setParameters(ipState, converted);
0166 ipState.location = edm4hep::TrackState::AtIP;
0167 ACTS_VERBOSE("Writing track level quantities as IP track state");
0168 ACTS_VERBOSE("- parameters: " << track.parameters().transpose());
0169 ACTS_VERBOSE(" -> " << converted.values.transpose());
0170 ACTS_VERBOSE("- covariance: \n"
0171 << track.covariance() << "\n->\n"
0172 << converted.covariance.value());
0173
0174
0175
0176
0177
0178 auto center = converted.surface->center(gctx);
0179 ipState.referencePoint.x = center.x();
0180 ipState.referencePoint.y = center.y();
0181 ipState.referencePoint.z = center.z();
0182
0183 ACTS_VERBOSE("- ref surface ctr: " << center.transpose());
0184
0185 for (auto& trackState : outTrackStates) {
0186 to.addToTrackStates(trackState);
0187 }
0188 }
0189
0190 template <Acts::TrackProxyConcept track_proxy_t>
0191 void readTrack(const edm4hep::Track& from, track_proxy_t& track, double Bz,
0192 const Acts::Logger& logger = Acts::getDummyLogger()) {
0193 using namespace Acts;
0194 ACTS_VERBOSE("Reading track from EDM4hep");
0195 TrackStatePropMask mask = TrackStatePropMask::Smoothed;
0196
0197 std::optional<edm4hep::TrackState> ipState;
0198
0199 auto unpack =
0200 [](const edm4hep::TrackState& trackState) -> detail::Parameters {
0201 detail::Parameters params;
0202 params.covariance = BoundMatrix::Zero();
0203 params.values = BoundVector::Zero();
0204 detail::unpackCovariance(trackState.covMatrix.data(),
0205 params.covariance.value());
0206 params.values[0] = trackState.D0;
0207 params.values[1] = trackState.Z0;
0208 params.values[2] = trackState.phi;
0209 params.values[3] = trackState.tanLambda;
0210 params.values[4] = trackState.omega;
0211 params.values[5] = trackState.time;
0212
0213 Vector3 center = {
0214 trackState.referencePoint.x,
0215 trackState.referencePoint.y,
0216 trackState.referencePoint.z,
0217 };
0218 params.surface = Acts::Surface::makeShared<PerigeeSurface>(center);
0219
0220 return params;
0221 };
0222
0223 ACTS_VERBOSE("Reading " << from.trackStates_size()
0224 << " track states (including IP state)");
0225
0226
0227 for (std::size_t i = from.trackStates_size() - 1;
0228 i <= from.trackStates_size(); i--) {
0229 auto trackState = from.getTrackStates(i);
0230 if (trackState.location == edm4hep::TrackState::AtIP) {
0231 ipState = trackState;
0232 continue;
0233 }
0234
0235 auto params = unpack(trackState);
0236
0237 auto ts = track.appendTrackState(mask);
0238 ts.typeFlags().set(MeasurementFlag);
0239
0240 auto converted = detail::convertTrackParametersFromEdm4hep(Bz, params);
0241
0242 ts.smoothed() = converted.parameters();
0243 ts.smoothedCovariance() =
0244 converted.covariance().value_or(BoundMatrix::Zero());
0245 ts.setReferenceSurface(params.surface);
0246 }
0247
0248 if (!ipState.has_value()) {
0249 ACTS_ERROR("Did not find IP state in edm4hep input");
0250 throw std::runtime_error{"Did not find IP state in edm4hep input"};
0251 }
0252
0253 detail::Parameters params = unpack(ipState.value());
0254
0255 auto converted = detail::convertTrackParametersFromEdm4hep(Bz, params);
0256
0257 ACTS_VERBOSE("IP state parameters: " << converted.parameters().transpose());
0258 ACTS_VERBOSE("-> covariance:\n"
0259 << converted.covariance().value_or(BoundMatrix::Zero()));
0260
0261 track.parameters() = converted.parameters();
0262 track.covariance() = converted.covariance().value_or(BoundMatrix::Zero());
0263 track.setReferenceSurface(params.surface);
0264
0265 track.chi2() = from.getChi2();
0266 track.nDoF() = from.getNdf();
0267 track.nMeasurements() = track.nTrackStates();
0268 }
0269
0270 class SimHitAssociation {
0271 public:
0272 void reserve(std::size_t size);
0273
0274 std::size_t size() const;
0275
0276 void add(std::size_t internalIndex, const edm4hep::SimTrackerHit& edm4hepHit);
0277
0278 [[nodiscard]]
0279 edm4hep::SimTrackerHit lookup(std::size_t internalIndex) const;
0280
0281 std::size_t lookup(const edm4hep::SimTrackerHit& hit) const;
0282
0283 private:
0284 std::vector<edm4hep::SimTrackerHit> m_internalToEdm4hep;
0285 std::unordered_map<podio::ObjectID, std::size_t> m_edm4hepToInternal;
0286 };
0287
0288 }