File indexing completed on 2025-07-09 08:04:03
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/EventData/MultiTrajectory.hpp"
0012 #include "Acts/EventData/ParticleHypothesis.hpp"
0013 #include "Acts/EventData/TrackContainer.hpp"
0014 #include "Acts/EventData/TrackStateProxy.hpp"
0015 #include "Acts/EventData/detail/DynamicColumn.hpp"
0016 #include "Acts/Plugins/Podio/PodioDynamicColumns.hpp"
0017 #include "Acts/Plugins/Podio/PodioUtil.hpp"
0018
0019 #pragma GCC diagnostic push
0020 #pragma GCC diagnostic ignored "-Wold-style-cast"
0021 #include "ActsPodioEdm/ParticleHypothesis.h"
0022 #include "ActsPodioEdm/Track.h"
0023 #include "ActsPodioEdm/TrackCollection.h"
0024 #include "ActsPodioEdm/TrackInfo.h"
0025 #pragma GCC diagnostic pop
0026
0027 #include <mutex>
0028 #include <stdexcept>
0029 #include <type_traits>
0030
0031 #include <podio/Frame.h>
0032
0033 namespace Acts {
0034
0035 class MutablePodioTrackContainer;
0036 class ConstPodioTrackContainer;
0037
0038 template <>
0039 struct IsReadOnlyTrackContainer<MutablePodioTrackContainer> : std::false_type {
0040 };
0041
0042 template <>
0043 struct IsReadOnlyTrackContainer<ConstPodioTrackContainer> : std::true_type {};
0044
0045 class PodioTrackContainerBase {
0046 public:
0047 using IndexType = MultiTrajectoryTraits::IndexType;
0048 static constexpr auto kInvalid = MultiTrajectoryTraits::kInvalid;
0049 static constexpr auto MeasurementSizeMax =
0050 MultiTrajectoryTraits::MeasurementSizeMax;
0051
0052 using Parameters =
0053 typename detail_lt::FixedSizeTypes<eBoundSize, false>::CoefficientsMap;
0054 using Covariance =
0055 typename detail_lt::FixedSizeTypes<eBoundSize, false>::CovarianceMap;
0056
0057 using ConstParameters =
0058 typename detail_lt::FixedSizeTypes<eBoundSize, true>::CoefficientsMap;
0059 using ConstCovariance =
0060 typename detail_lt::FixedSizeTypes<eBoundSize, true>::CovarianceMap;
0061
0062 protected:
0063 PodioTrackContainerBase(const PodioUtil::ConversionHelper& helper)
0064 : m_helper{helper} {}
0065
0066 template <bool EnsureConst, typename T>
0067 static std::any component_impl(T& instance, HashedString key,
0068 IndexType itrack) {
0069 using namespace Acts::HashedStringLiteral;
0070 if constexpr (EnsureConst) {
0071 static_assert(std::is_const_v<std::remove_reference_t<T>>,
0072 "Is not const");
0073 }
0074
0075 using namespace Acts::HashedStringLiteral;
0076 auto track = instance.m_collection->at(itrack);
0077 std::conditional_t<EnsureConst, const ActsPodioEdm::TrackInfo*,
0078 ActsPodioEdm::TrackInfo*>
0079 dataPtr;
0080 if constexpr (EnsureConst) {
0081 dataPtr = &track.getData();
0082 } else {
0083 dataPtr = &PodioUtil::getDataMutable(track);
0084 }
0085 auto& data = *dataPtr;
0086 switch (key) {
0087 case "tipIndex"_hash:
0088 return &data.tipIndex;
0089 case "stemIndex"_hash:
0090 return &data.stemIndex;
0091 case "params"_hash:
0092 return data.parameters.data();
0093 case "cov"_hash:
0094 return data.covariance.data();
0095 case "nMeasurements"_hash:
0096 return &data.nMeasurements;
0097 case "nHoles"_hash:
0098 return &data.nHoles;
0099 case "chi2"_hash:
0100 return &data.chi2;
0101 case "ndf"_hash:
0102 return &data.ndf;
0103 case "nOutliers"_hash:
0104 return &data.nOutliers;
0105 case "nSharedHits"_hash:
0106 return &data.nSharedHits;
0107 default:
0108 auto it = instance.m_dynamic.find(key);
0109 if (it == instance.m_dynamic.end()) {
0110 throw std::runtime_error("Unable to handle this component");
0111 }
0112
0113 std::conditional_t<EnsureConst,
0114 const podio_detail::ConstDynamicColumnBase*,
0115 podio_detail::DynamicColumnBase*>
0116 col = it->second.get();
0117 assert(col && "Dynamic column is null");
0118 return col->get(itrack);
0119 }
0120 }
0121
0122 template <typename T>
0123 static auto dynamicKeys_impl(T& instance) {
0124 using column_type =
0125 typename decltype(instance.m_dynamic)::mapped_type::element_type;
0126 return detail::DynamicKeyRange<column_type>{instance.m_dynamic.begin(),
0127 instance.m_dynamic.end()};
0128 }
0129
0130 template <typename T>
0131 static ParticleHypothesis particleHypothesis_impl(T& instance,
0132 IndexType itrack) {
0133 auto track = instance.m_collection->at(itrack);
0134 const auto& src = track.getParticleHypothesis();
0135 return ParticleHypothesis{static_cast<PdgParticle>(src.absPdg), src.mass,
0136 src.absQ};
0137 }
0138
0139 static void populateSurfaceBuffer(
0140 const PodioUtil::ConversionHelper& helper,
0141 const ActsPodioEdm::TrackCollection& collection,
0142 std::vector<std::shared_ptr<const Surface>>& surfaces) noexcept {
0143 surfaces.reserve(collection.size());
0144 for (ActsPodioEdm::Track track : collection) {
0145 surfaces.push_back(PodioUtil::convertSurfaceFromPodio(
0146 helper, track.getReferenceSurface()));
0147 }
0148 }
0149
0150 std::reference_wrapper<const PodioUtil::ConversionHelper> m_helper;
0151 std::vector<std::shared_ptr<const Surface>> m_surfaces;
0152 };
0153
0154 class MutablePodioTrackContainer : public PodioTrackContainerBase {
0155 public:
0156 MutablePodioTrackContainer(const PodioUtil::ConversionHelper& helper)
0157 : PodioTrackContainerBase{helper},
0158 m_collection{std::make_unique<ActsPodioEdm::TrackCollection>()} {
0159 populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0160 }
0161
0162 MutablePodioTrackContainer(const MutablePodioTrackContainer& other);
0163 MutablePodioTrackContainer(MutablePodioTrackContainer&& other) = default;
0164
0165 MutablePodioTrackContainer(const ConstPodioTrackContainer& other);
0166
0167
0168
0169 private:
0170 std::shared_ptr<const Surface> getOrCreateSurface(IndexType itrack) {
0171 std::shared_ptr<const Surface>& ptr = m_surfaces.at(itrack);
0172 if (!ptr) {
0173 ActsPodioEdm::Track track = m_collection->at(itrack);
0174 ptr = PodioUtil::convertSurfaceFromPodio(m_helper,
0175 track.getReferenceSurface());
0176 }
0177 return ptr;
0178 }
0179
0180 public:
0181 std::any component_impl(HashedString key, IndexType itrack) {
0182 return PodioTrackContainerBase::component_impl<false>(*this, key, itrack);
0183 }
0184
0185 std::any component_impl(HashedString key, IndexType itrack) const {
0186 return PodioTrackContainerBase::component_impl<true>(*this, key, itrack);
0187 }
0188
0189 bool hasColumn_impl(HashedString key) const {
0190 return m_dynamic.find(key) != m_dynamic.end();
0191 }
0192
0193 std::size_t size_impl() const { return m_collection->size(); }
0194
0195 void clear() { m_collection->clear(); }
0196
0197
0198
0199 const Surface* referenceSurface_impl(IndexType itrack) const {
0200 return m_surfaces.at(itrack).get();
0201 }
0202
0203 ParticleHypothesis particleHypothesis_impl(IndexType itrack) const {
0204 return PodioTrackContainerBase::particleHypothesis_impl(*this, itrack);
0205 }
0206
0207 void setReferenceSurface_impl(IndexType itrack,
0208 std::shared_ptr<const Surface> surface) {
0209 auto track = m_collection->at(itrack);
0210 track.setReferenceSurface(
0211 PodioUtil::convertSurfaceToPodio(m_helper, *surface));
0212 m_surfaces.at(itrack) = std::move(surface);
0213 }
0214
0215 public:
0216
0217
0218 IndexType addTrack_impl() {
0219 auto track = m_collection->create();
0220 PodioUtil::getReferenceSurfaceMutable(track).surfaceType =
0221 PodioUtil::kNoSurface;
0222 m_surfaces.emplace_back();
0223 for (const auto& [key, vec] : m_dynamic) {
0224 vec->add();
0225 }
0226 return m_collection->size() - 1;
0227 };
0228
0229 void removeTrack_impl(IndexType itrack);
0230
0231 template <typename T>
0232 constexpr void addColumn_impl(std::string_view key) {
0233 Acts::HashedString hashedKey = hashString(key);
0234 m_dynamic.insert(
0235 {hashedKey, std::make_unique<podio_detail::DynamicColumn<T>>(key)});
0236 }
0237
0238 Parameters parameters(IndexType itrack) {
0239 return Parameters{
0240 PodioUtil::getDataMutable(m_collection->at(itrack)).parameters.data()};
0241 }
0242
0243 ConstParameters parameters(IndexType itrack) const {
0244 return ConstParameters{
0245 m_collection->at(itrack).getData().parameters.data()};
0246 }
0247
0248 Covariance covariance(IndexType itrack) {
0249 return Covariance{
0250 PodioUtil::getDataMutable(m_collection->at(itrack)).covariance.data()};
0251 }
0252
0253 ConstCovariance covariance(IndexType itrack) const {
0254 return ConstCovariance{
0255 m_collection->at(itrack).getData().covariance.data()};
0256 }
0257
0258 void copyDynamicFrom_impl(IndexType dstIdx, HashedString key,
0259 const std::any& srcPtr) {
0260 auto it = m_dynamic.find(key);
0261 if (it == m_dynamic.end()) {
0262 throw std::invalid_argument{
0263 "Destination container does not have matching dynamic column"};
0264 }
0265
0266 it->second->copyFrom(dstIdx, srcPtr);
0267 }
0268
0269 void ensureDynamicColumns_impl(const MutablePodioTrackContainer& other);
0270
0271 void reserve(IndexType ) {}
0272
0273 ActsPodioEdm::TrackCollection& trackCollection() { return *m_collection; }
0274
0275 void releaseInto(podio::Frame& frame, const std::string& suffix = "") {
0276 std::string s = suffix;
0277 if (!s.empty()) {
0278 s = "_" + s;
0279 }
0280 frame.put(std::move(m_collection), "tracks" + s);
0281 m_surfaces.clear();
0282
0283 for (const auto& [key, col] : m_dynamic) {
0284 col->releaseInto(frame, "tracks" + s + "_extra__");
0285 }
0286 }
0287
0288 detail::DynamicKeyRange<podio_detail::DynamicColumnBase> dynamicKeys_impl()
0289 const {
0290 return PodioTrackContainerBase::dynamicKeys_impl(*this);
0291 }
0292
0293 void setParticleHypothesis_impl(
0294 IndexType itrack, const ParticleHypothesis& particleHypothesis) {
0295 ActsPodioEdm::ParticleHypothesis pHypo;
0296 pHypo.absPdg = particleHypothesis.absolutePdg();
0297 pHypo.mass = particleHypothesis.mass();
0298 pHypo.absQ = particleHypothesis.absoluteCharge();
0299 m_collection->at(itrack).setParticleHypothesis(pHypo);
0300 }
0301
0302
0303
0304 private:
0305 friend PodioTrackContainerBase;
0306
0307 std::unique_ptr<ActsPodioEdm::TrackCollection> m_collection;
0308 std::vector<HashedString> m_dynamicKeys;
0309 std::unordered_map<HashedString,
0310 std::unique_ptr<podio_detail::DynamicColumnBase>>
0311 m_dynamic;
0312 };
0313
0314 static_assert(
0315 TrackContainerBackend<MutablePodioTrackContainer>,
0316 "MutablePodioTrackContainer does not fulfill TrackContainerBackend");
0317
0318 class ConstPodioTrackContainer : public PodioTrackContainerBase {
0319 public:
0320 ConstPodioTrackContainer(const PodioUtil::ConversionHelper& helper,
0321 const ActsPodioEdm::TrackCollection& collection)
0322 : PodioTrackContainerBase{helper}, m_collection{&collection} {
0323
0324 populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0325 }
0326
0327 ConstPodioTrackContainer(const PodioUtil::ConversionHelper& helper,
0328 const podio::Frame& frame,
0329 const std::string& suffix = "")
0330 : PodioTrackContainerBase{helper} {
0331 std::string s = suffix.empty() ? suffix : "_" + suffix;
0332 std::string tracksKey = "tracks" + s;
0333
0334 std::vector<std::string> available = frame.getAvailableCollections();
0335 if (std::find(available.begin(), available.end(), tracksKey) ==
0336 available.end()) {
0337 throw std::runtime_error{"Track collection '" + tracksKey +
0338 "' not found in frame"};
0339 }
0340
0341 const auto* collection = frame.get(tracksKey);
0342
0343 if (const auto* d =
0344 dynamic_cast<const ActsPodioEdm::TrackCollection*>(collection);
0345 d != nullptr) {
0346 m_collection = d;
0347 } else {
0348 throw std::runtime_error{"Unable to get collection " + tracksKey};
0349 }
0350
0351 populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0352
0353 podio_detail::recoverDynamicColumns(frame, tracksKey, m_dynamic);
0354 }
0355
0356 std::any component_impl(HashedString key, IndexType itrack) const {
0357 return PodioTrackContainerBase::component_impl<true>(*this, key, itrack);
0358 }
0359
0360 bool hasColumn_impl(HashedString key) const {
0361 return m_dynamic.find(key) != m_dynamic.end();
0362 }
0363
0364 std::size_t size_impl() const { return m_collection->size(); }
0365
0366 const Surface* referenceSurface_impl(IndexType itrack) const {
0367 return m_surfaces.at(itrack).get();
0368 }
0369
0370 ParticleHypothesis particleHypothesis_impl(IndexType itrack) const {
0371 return PodioTrackContainerBase::particleHypothesis_impl(*this, itrack);
0372 }
0373
0374 ConstParameters parameters(IndexType itrack) const {
0375 return ConstParameters{
0376 m_collection->at(itrack).getData().parameters.data()};
0377 }
0378
0379 ConstCovariance covariance(IndexType itrack) const {
0380 return ConstCovariance{
0381 m_collection->at(itrack).getData().covariance.data()};
0382 }
0383
0384 const ActsPodioEdm::TrackCollection& trackCollection() {
0385 return *m_collection;
0386 }
0387
0388 detail::DynamicKeyRange<podio_detail::ConstDynamicColumnBase>
0389 dynamicKeys_impl() const {
0390 return PodioTrackContainerBase::dynamicKeys_impl(*this);
0391 }
0392
0393 private:
0394 friend PodioTrackContainerBase;
0395
0396 const ActsPodioEdm::TrackCollection* m_collection;
0397 std::unordered_map<HashedString,
0398 std::unique_ptr<podio_detail::ConstDynamicColumnBase>>
0399 m_dynamic;
0400 std::vector<HashedString> m_dynamicKeys;
0401 };
0402
0403 static_assert(
0404 ConstTrackContainerBackend<ConstPodioTrackContainer>,
0405 "ConstPodioTrackContainer does not fulfill ConstTrackContainerBackend");
0406
0407 }