Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:33:17

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/EventData/MultiTrajectory.hpp"
0012 #include "Acts/EventData/MultiTrajectoryBackendConcept.hpp"
0013 #include "Acts/EventData/TrackContainer.hpp"
0014 #include "Acts/EventData/TrackStatePropMask.hpp"
0015 #include "Acts/EventData/Types.hpp"
0016 #include "Acts/EventData/detail/DynamicKeyIterator.hpp"
0017 #include "Acts/Plugins/Podio/PodioDynamicColumns.hpp"
0018 #include "Acts/Plugins/Podio/PodioTrackContainer.hpp"
0019 #include "Acts/Plugins/Podio/PodioUtil.hpp"
0020 #include "Acts/Utilities/HashedString.hpp"
0021 #include "Acts/Utilities/Helpers.hpp"
0022 
0023 #pragma GCC diagnostic push
0024 #pragma GCC diagnostic ignored "-Wold-style-cast"
0025 #include "ActsPodioEdm/BoundParametersCollection.h"
0026 #include "ActsPodioEdm/JacobianCollection.h"
0027 #include "ActsPodioEdm/TrackStateCollection.h"
0028 #include "ActsPodioEdm/TrackStateInfo.h"
0029 #pragma GCC diagnostic pop
0030 
0031 #include <any>
0032 #include <memory>
0033 #include <stdexcept>
0034 #include <tuple>
0035 #include <type_traits>
0036 
0037 #include <podio/CollectionBase.h>
0038 #include <podio/Frame.h>
0039 
0040 namespace Acts {
0041 
0042 class MutablePodioTrackStateContainer;
0043 class ConstPodioTrackStateContainer;
0044 
0045 class PodioTrackStateContainerBase {
0046  public:
0047   using Parameters =
0048       typename detail_lt::FixedSizeTypes<eBoundSize, false>::CoefficientsMap;
0049   using Covariance =
0050       typename detail_lt::FixedSizeTypes<eBoundSize, false>::CovarianceMap;
0051 
0052   using ConstParameters =
0053       typename detail_lt::FixedSizeTypes<eBoundSize, true>::CoefficientsMap;
0054   using ConstCovariance =
0055       typename detail_lt::FixedSizeTypes<eBoundSize, true>::CovarianceMap;
0056 
0057  protected:
0058   template <typename T>
0059   static constexpr bool has_impl(T& instance, HashedString key,
0060                                  TrackIndexType istate) {
0061     constexpr auto kInvalid = MultiTrajectoryTraits::kInvalid;
0062     using namespace Acts::HashedStringLiteral;
0063     auto trackState = instance.m_collection->at(istate);
0064     const auto& data = trackState.getData();
0065     switch (key) {
0066       case "predicted"_hash:
0067         return data.ipredicted != kInvalid;
0068       case "filtered"_hash:
0069         return data.ifiltered != kInvalid;
0070       case "smoothed"_hash:
0071         return data.ismoothed != kInvalid;
0072       case "calibrated"_hash:
0073         return data.measdim != kInvalid;
0074       case "calibratedCov"_hash:
0075         return data.measdim != kInvalid;
0076       case "jacobian"_hash:
0077         return data.ijacobian != kInvalid;
0078       case "projector"_hash:
0079         return data.hasProjector;
0080       case "uncalibratedSourceLink"_hash:
0081         return data.uncalibratedIdentifier != PodioUtil::kNoIdentifier;
0082       case "previous"_hash:
0083       case "next"_hash:
0084       case "measdim"_hash:
0085       case "referenceSurface"_hash:
0086       case "chi2"_hash:
0087       case "pathLength"_hash:
0088       case "typeFlags"_hash:
0089         return true;
0090       default:
0091         return instance.m_dynamic.contains(key);
0092     }
0093 
0094     return false;
0095   }
0096 
0097   template <bool EnsureConst, typename T>
0098   static std::any component_impl(T& instance, HashedString key,
0099                                  TrackIndexType istate) {
0100     if constexpr (EnsureConst) {
0101       static_assert(std::is_const_v<std::remove_reference_t<T>>,
0102                     "Is not const");
0103     }
0104     using namespace Acts::HashedStringLiteral;
0105     auto trackState = instance.m_collection->at(istate);
0106     std::conditional_t<EnsureConst, const ActsPodioEdm::TrackStateInfo*,
0107                        ActsPodioEdm::TrackStateInfo*>
0108         dataPtr;
0109     if constexpr (EnsureConst) {
0110       dataPtr = &trackState.getData();
0111     } else {
0112       dataPtr = &PodioUtil::getDataMutable(trackState);
0113     }
0114     auto& data = *dataPtr;
0115     switch (key) {
0116       case "previous"_hash:
0117         return &data.previous;
0118       case "next"_hash:
0119         return &data.next;
0120       case "predicted"_hash:
0121         return &data.ipredicted;
0122       case "filtered"_hash:
0123         return &data.ifiltered;
0124       case "smoothed"_hash:
0125         return &data.ismoothed;
0126       case "projector"_hash:
0127         return &data.projector;
0128       case "measdim"_hash:
0129         return &data.measdim;
0130       case "chi2"_hash:
0131         return &data.chi2;
0132       case "pathLength"_hash:
0133         return &data.pathLength;
0134       case "typeFlags"_hash:
0135         return &data.typeFlags;
0136       default:
0137         auto it = instance.m_dynamic.find(key);
0138         if (it == instance.m_dynamic.end()) {
0139           throw std::runtime_error("Unable to handle this component");
0140         }
0141         std::conditional_t<EnsureConst,
0142                            const podio_detail::ConstDynamicColumnBase*,
0143                            podio_detail::DynamicColumnBase*>
0144             col = it->second.get();
0145         assert(col && "Dynamic column is null");
0146         return col->get(istate);
0147     }
0148   }
0149 
0150   template <typename T>
0151   static constexpr bool hasColumn_impl(T& instance, HashedString key) {
0152     using namespace Acts::HashedStringLiteral;
0153     switch (key) {
0154       case "predicted"_hash:
0155       case "filtered"_hash:
0156       case "smoothed"_hash:
0157       case "jacobian"_hash:
0158       case "projector"_hash:
0159       case "previous"_hash:
0160       case "next"_hash:
0161       case "uncalibratedSourceLink"_hash:
0162       case "referenceSurface"_hash:
0163       case "measdim"_hash:
0164       case "chi2"_hash:
0165       case "pathLength"_hash:
0166       case "typeFlags"_hash:
0167         return true;
0168       default:
0169         return instance.m_dynamic.contains(key);
0170     }
0171   }
0172 
0173   static void populateSurfaceBuffer(
0174       const PodioUtil::ConversionHelper& helper,
0175       const ActsPodioEdm::TrackStateCollection& collection,
0176       std::vector<std::shared_ptr<const Surface>>& surfaces) noexcept {
0177     surfaces.reserve(collection.size());
0178     for (ActsPodioEdm::TrackState trackState : collection) {
0179       surfaces.push_back(PodioUtil::convertSurfaceFromPodio(
0180           helper, trackState.getReferenceSurface()));
0181     }
0182   }
0183 };
0184 
0185 template <>
0186 struct IsReadOnlyMultiTrajectory<ConstPodioTrackStateContainer>
0187     : std::true_type {};
0188 
0189 class ConstPodioTrackStateContainer final
0190     : public PodioTrackStateContainerBase,
0191       public MultiTrajectory<ConstPodioTrackStateContainer> {
0192  public:
0193   ConstPodioTrackStateContainer(
0194       const PodioUtil::ConversionHelper& helper,
0195       const ActsPodioEdm::TrackStateCollection& trackStates,
0196       const ActsPodioEdm::BoundParametersCollection& params,
0197       const ActsPodioEdm::JacobianCollection& jacs)
0198       : m_helper{helper},
0199         m_collection{&trackStates},
0200         m_params{&params},
0201         m_jacs{&jacs} {
0202     // Not much we can do to recover dynamic columns here
0203     populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0204   }
0205 
0206   /// Construct a const track state container from a mutable
0207   /// @warning If the source mutable container is modified, this container
0208   ///          will be corrupted, as surface buffer and dynamic column state can
0209   ///          not be synchronized!
0210   ConstPodioTrackStateContainer(const MutablePodioTrackStateContainer& other);
0211 
0212   ConstPodioTrackStateContainer(const PodioUtil::ConversionHelper& helper,
0213                                 const podio::Frame& frame,
0214                                 const std::string& suffix = "")
0215       : m_helper{helper},
0216         m_collection{nullptr},
0217         m_params{nullptr},
0218         m_jacs{nullptr} {
0219     std::string s = suffix.empty() ? suffix : "_" + suffix;
0220 
0221     std::vector<std::string> available = frame.getAvailableCollections();
0222 
0223     std::string trackStatesKey = "trackStates" + s;
0224     std::string paramsKey = "trackStateParameters" + s;
0225     std::string jacsKey = "trackStateJacobians" + s;
0226 
0227     if (!rangeContainsValue(available, trackStatesKey)) {
0228       throw std::runtime_error{"Track state collection '" + trackStatesKey +
0229                                "' not found in frame"};
0230     }
0231 
0232     if (!rangeContainsValue(available, paramsKey)) {
0233       throw std::runtime_error{"Track state parameters collection '" +
0234                                paramsKey + "' not found in frame"};
0235     }
0236 
0237     if (!rangeContainsValue(available, jacsKey)) {
0238       throw std::runtime_error{"Track state jacobian collection '" + jacsKey +
0239                                "' not found in frame"};
0240     }
0241 
0242     loadCollection<ActsPodioEdm::TrackStateCollection>(m_collection, frame,
0243                                                        trackStatesKey);
0244     loadCollection<ActsPodioEdm::BoundParametersCollection>(m_params, frame,
0245                                                             paramsKey);
0246     loadCollection<ActsPodioEdm::JacobianCollection>(m_jacs, frame, jacsKey);
0247 
0248     populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0249 
0250     podio_detail::recoverDynamicColumns(frame, trackStatesKey, m_dynamic);
0251   }
0252 
0253   detail::DynamicKeyRange<podio_detail::ConstDynamicColumnBase>
0254   dynamicKeys_impl() const {
0255     return {m_dynamic.begin(), m_dynamic.end()};
0256   }
0257 
0258  private:
0259   template <typename collection_t>
0260   static void loadCollection(collection_t const*& dest,
0261                              const podio::Frame& frame,
0262                              const std::string& key) {
0263     const auto* collection = frame.get(key);
0264 
0265     if (const auto* d = dynamic_cast<const collection_t*>(collection);
0266         d != nullptr) {
0267       dest = d;
0268     } else {
0269       throw std::runtime_error{"Unable to get collection " + key};
0270     }
0271   }
0272 
0273  public:
0274   ConstParameters parameters_impl(IndexType istate) const {
0275     return ConstParameters{m_params->at(istate).getData().values.data()};
0276   }
0277 
0278   ConstCovariance covariance_impl(IndexType istate) const {
0279     return ConstCovariance{m_params->at(istate).getData().covariance.data()};
0280   }
0281 
0282   ConstCovariance jacobian_impl(IndexType istate) const {
0283     IndexType ijacobian = m_collection->at(istate).getData().ijacobian;
0284     return ConstCovariance{m_jacs->at(ijacobian).getData().values.data()};
0285   }
0286 
0287   template <std::size_t measdim>
0288   ConstTrackStateProxy::Calibrated<measdim> calibrated_impl(
0289       IndexType index) const {
0290     return ConstTrackStateProxy::Calibrated<measdim>{
0291         m_collection->at(index).getData().measurement.data()};
0292   }
0293 
0294   template <std::size_t measdim>
0295   ConstTrackStateProxy::CalibratedCovariance<measdim> calibratedCovariance_impl(
0296       IndexType index) const {
0297     return ConstTrackStateProxy::CalibratedCovariance<measdim>{
0298         m_collection->at(index).getData().measurementCovariance.data()};
0299   }
0300 
0301   IndexType size_impl() const { return m_collection->size(); }
0302 
0303   std::any component_impl(HashedString key, IndexType istate) const {
0304     return PodioTrackStateContainerBase::component_impl<true>(*this, key,
0305                                                               istate);
0306   }
0307 
0308   constexpr bool hasColumn_impl(HashedString key) const {
0309     return PodioTrackStateContainerBase::hasColumn_impl(*this, key);
0310   }
0311 
0312   constexpr bool has_impl(HashedString key, IndexType istate) const {
0313     return PodioTrackStateContainerBase::has_impl(*this, key, istate);
0314   }
0315 
0316   MultiTrajectoryTraits::IndexType calibratedSize_impl(IndexType istate) const {
0317     return m_collection->at(istate).getData().measdim;
0318   }
0319 
0320   SourceLink getUncalibratedSourceLink_impl(IndexType istate) const {
0321     return m_helper.get().identifierToSourceLink(
0322         m_collection->at(istate).getData().uncalibratedIdentifier);
0323   }
0324 
0325   const Surface* referenceSurface_impl(IndexType istate) const {
0326     return m_surfaces.at(istate).get();
0327   }
0328 
0329  private:
0330   friend class PodioTrackStateContainerBase;
0331 
0332   std::reference_wrapper<const PodioUtil::ConversionHelper> m_helper;
0333   const ActsPodioEdm::TrackStateCollection* m_collection;
0334   const ActsPodioEdm::BoundParametersCollection* m_params;
0335   const ActsPodioEdm::JacobianCollection* m_jacs;
0336   std::vector<std::shared_ptr<const Surface>> m_surfaces;
0337 
0338   std::unordered_map<HashedString,
0339                      std::unique_ptr<podio_detail::ConstDynamicColumnBase>>
0340       m_dynamic;
0341   std::vector<HashedString> m_dynamicKeys;
0342 };
0343 
0344 static_assert(IsReadOnlyMultiTrajectory<ConstPodioTrackStateContainer>::value,
0345               "MutablePodioTrackStateContainer should not be read-only");
0346 
0347 static_assert(
0348     ConstMultiTrajectoryBackend<ConstPodioTrackStateContainer>,
0349     "ConstPodioTrackStateContainer does not fulfill TrackContainerBackend");
0350 
0351 template <>
0352 struct IsReadOnlyMultiTrajectory<MutablePodioTrackStateContainer>
0353     : std::false_type {};
0354 
0355 class MutablePodioTrackStateContainer final
0356     : public PodioTrackStateContainerBase,
0357       public MultiTrajectory<MutablePodioTrackStateContainer> {
0358  public:
0359   MutablePodioTrackStateContainer(PodioUtil::ConversionHelper& helper)
0360       : m_helper{helper} {
0361     m_collection = std::make_unique<ActsPodioEdm::TrackStateCollection>();
0362     m_jacs = std::make_unique<ActsPodioEdm::JacobianCollection>();
0363     m_params = std::make_unique<ActsPodioEdm::BoundParametersCollection>();
0364 
0365     populateSurfaceBuffer(m_helper, *m_collection, m_surfaces);
0366   }
0367 
0368   ConstParameters parameters_impl(IndexType istate) const {
0369     return ConstParameters{m_params->at(istate).getData().values.data()};
0370   }
0371 
0372   Parameters parameters_impl(IndexType istate) {
0373     return Parameters{
0374         PodioUtil::getDataMutable(m_params->at(istate)).values.data()};
0375   }
0376 
0377   ConstCovariance covariance_impl(IndexType istate) const {
0378     return ConstCovariance{m_params->at(istate).getData().covariance.data()};
0379   }
0380 
0381   Covariance covariance_impl(IndexType istate) {
0382     return Covariance{
0383         PodioUtil::getDataMutable(m_params->at(istate)).covariance.data()};
0384   }
0385 
0386   ConstCovariance jacobian_impl(IndexType istate) const {
0387     IndexType ijacobian = m_collection->at(istate).getData().ijacobian;
0388     return ConstCovariance{m_jacs->at(ijacobian).getData().values.data()};
0389   }
0390 
0391   Covariance jacobian_impl(IndexType istate) {
0392     IndexType ijacobian = m_collection->at(istate).getData().ijacobian;
0393     return Covariance{
0394         PodioUtil::getDataMutable(m_jacs->at(ijacobian)).values.data()};
0395   }
0396 
0397   template <std::size_t measdim>
0398   ConstTrackStateProxy::Calibrated<measdim> calibrated_impl(
0399       IndexType index) const {
0400     return ConstTrackStateProxy::Calibrated<measdim>{
0401         m_collection->at(index).getData().measurement.data()};
0402   }
0403 
0404   template <std::size_t measdim>
0405   TrackStateProxy::Calibrated<measdim> calibrated_impl(IndexType index) {
0406     return TrackStateProxy::Calibrated<measdim>{
0407         PodioUtil::getDataMutable(m_collection->at(index)).measurement.data()};
0408   }
0409 
0410   template <std::size_t measdim>
0411   ConstTrackStateProxy::CalibratedCovariance<measdim> calibratedCovariance_impl(
0412       IndexType index) const {
0413     return ConstTrackStateProxy::CalibratedCovariance<measdim>{
0414         m_collection->at(index).getData().measurementCovariance.data()};
0415   }
0416 
0417   template <std::size_t measdim>
0418   TrackStateProxy::CalibratedCovariance<measdim> calibratedCovariance_impl(
0419       IndexType index) {
0420     return TrackStateProxy::CalibratedCovariance<measdim>{
0421         PodioUtil::getDataMutable(m_collection->at(index))
0422             .measurementCovariance.data()};
0423   }
0424 
0425   IndexType size_impl() const { return m_collection->size(); }
0426 
0427   std::any component_impl(HashedString key, IndexType istate) const {
0428     return PodioTrackStateContainerBase::component_impl<true>(*this, key,
0429                                                               istate);
0430   }
0431 
0432   std::any component_impl(HashedString key, IndexType istate) {
0433     return PodioTrackStateContainerBase::component_impl<false>(*this, key,
0434                                                                istate);
0435   }
0436 
0437   constexpr bool hasColumn_impl(HashedString key) const {
0438     return PodioTrackStateContainerBase::hasColumn_impl(*this, key);
0439   }
0440 
0441   constexpr bool has_impl(HashedString key, IndexType istate) const {
0442     return PodioTrackStateContainerBase::has_impl(*this, key, istate);
0443   }
0444 
0445   IndexType addTrackState_impl(
0446       TrackStatePropMask mask = TrackStatePropMask::All,
0447       TrackIndexType iprevious = kTrackIndexInvalid) {
0448     auto trackState = m_collection->create();
0449     auto& data = PodioUtil::getDataMutable(trackState);
0450     data.previous = iprevious;
0451     data.ipredicted = kInvalid;
0452     data.ifiltered = kInvalid;
0453     data.ismoothed = kInvalid;
0454     data.ijacobian = kInvalid;
0455 
0456     PodioUtil::getReferenceSurfaceMutable(trackState).surfaceType =
0457         PodioUtil::kNoSurface;
0458 
0459     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Predicted)) {
0460       m_params->create();
0461       data.ipredicted = m_params->size() - 1;
0462     }
0463     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Filtered)) {
0464       m_params->create();
0465       data.ifiltered = m_params->size() - 1;
0466     }
0467     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Smoothed)) {
0468       m_params->create();
0469       data.ismoothed = m_params->size() - 1;
0470     }
0471     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Jacobian)) {
0472       m_jacs->create();
0473       data.ijacobian = m_jacs->size() - 1;
0474     }
0475     data.measdim = kInvalid;
0476     data.hasProjector = false;
0477     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Calibrated)) {
0478       data.hasProjector = true;
0479     }
0480     m_surfaces.emplace_back();
0481 
0482     data.uncalibratedIdentifier = PodioUtil::kNoIdentifier;
0483     assert(m_collection->size() == m_surfaces.size() &&
0484            "Inconsistent surface buffer");
0485 
0486     for (const auto& [key, vec] : m_dynamic) {
0487       vec->add();
0488     }
0489 
0490     return m_collection->size() - 1;
0491   }
0492 
0493   void addTrackStateComponents_impl(IndexType istate, TrackStatePropMask mask) {
0494     auto& data = PodioUtil::getDataMutable(m_collection->at(istate));
0495 
0496     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Predicted) &&
0497         data.ipredicted == kInvalid) {
0498       m_params->create();
0499       data.ipredicted = m_params->size() - 1;
0500     }
0501 
0502     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Filtered) &&
0503         data.ifiltered == kInvalid) {
0504       m_params->create();
0505       data.ifiltered = m_params->size() - 1;
0506     }
0507 
0508     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Smoothed) &&
0509         data.ismoothed == kInvalid) {
0510       m_params->create();
0511       data.ismoothed = m_params->size() - 1;
0512     }
0513 
0514     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Jacobian) &&
0515         data.ijacobian == kInvalid) {
0516       m_jacs->create();
0517       data.ijacobian = m_jacs->size() - 1;
0518     }
0519 
0520     if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Calibrated) &&
0521         !data.hasProjector) {
0522       data.hasProjector = true;
0523     }
0524   }
0525 
0526   void shareFrom_impl(TrackIndexType iself, TrackIndexType iother,
0527                       TrackStatePropMask shareSource,
0528                       TrackStatePropMask shareTarget) {
0529     auto& self = PodioUtil::getDataMutable(m_collection->at(iself));
0530     auto& other = PodioUtil::getDataMutable(m_collection->at(iother));
0531 
0532     assert(ACTS_CHECK_BIT(getTrackState(iother).getMask(), shareSource) &&
0533            "Source has incompatible allocation");
0534 
0535     using PM = TrackStatePropMask;
0536 
0537     IndexType sourceIndex{kInvalid};
0538     switch (shareSource) {
0539       case PM::Predicted:
0540         sourceIndex = other.ipredicted;
0541         break;
0542       case PM::Filtered:
0543         sourceIndex = other.ifiltered;
0544         break;
0545       case PM::Smoothed:
0546         sourceIndex = other.ismoothed;
0547         break;
0548       case PM::Jacobian:
0549         sourceIndex = other.ijacobian;
0550         break;
0551       default:
0552         throw std::domain_error{"Unable to share this component"};
0553     }
0554 
0555     assert(sourceIndex != kInvalid);
0556 
0557     switch (shareTarget) {
0558       case PM::Predicted:
0559         assert(shareSource != PM::Jacobian);
0560         self.ipredicted = sourceIndex;
0561         break;
0562       case PM::Filtered:
0563         assert(shareSource != PM::Jacobian);
0564         self.ifiltered = sourceIndex;
0565         break;
0566       case PM::Smoothed:
0567         assert(shareSource != PM::Jacobian);
0568         self.ismoothed = sourceIndex;
0569         break;
0570       case PM::Jacobian:
0571         assert(shareSource == PM::Jacobian);
0572         self.ijacobian = sourceIndex;
0573         break;
0574       default:
0575         throw std::domain_error{"Unable to share this component"};
0576     }
0577   }
0578 
0579   void unset_impl(TrackStatePropMask target, TrackIndexType istate) {
0580     auto& data = PodioUtil::getDataMutable(m_collection->at(istate));
0581     switch (target) {
0582       case TrackStatePropMask::Predicted:
0583         data.ipredicted = kInvalid;
0584         break;
0585       case TrackStatePropMask::Filtered:
0586         data.ifiltered = kInvalid;
0587         break;
0588       case TrackStatePropMask::Smoothed:
0589         data.ismoothed = kInvalid;
0590         break;
0591       case TrackStatePropMask::Jacobian:
0592         data.ijacobian = kInvalid;
0593         break;
0594       case TrackStatePropMask::Calibrated:
0595         data.measdim = kInvalid;
0596         break;
0597       default:
0598         throw std::domain_error{"Unable to unset this component"};
0599     }
0600   }
0601 
0602   void clear_impl() {
0603     m_collection->clear();
0604     m_params->clear();
0605     m_surfaces.clear();
0606     for (const auto& [key, vec] : m_dynamic) {
0607       vec->clear();
0608     }
0609   }
0610 
0611   template <typename T>
0612   constexpr void addColumn_impl(std::string_view key) {
0613     HashedString hashedKey = hashStringDynamic(key);
0614     m_dynamic.insert(
0615         {hashedKey, std::make_unique<podio_detail::DynamicColumn<T>>(key)});
0616   }
0617 
0618   template <typename val_t, typename cov_t>
0619   void allocateCalibrated_impl(IndexType istate,
0620                                const Eigen::DenseBase<val_t>& val,
0621                                const Eigen::DenseBase<cov_t>& cov)
0622     requires(Concepts::eigen_base_is_fixed_size<val_t> &&
0623              Eigen::PlainObjectBase<val_t>::RowsAtCompileTime <=
0624                  toUnderlying(eBoundSize) &&
0625              Concepts::eigen_bases_have_same_num_rows<val_t, cov_t> &&
0626              Concepts::eigen_base_is_square<cov_t>)
0627   {
0628     constexpr std::size_t measdim = val_t::RowsAtCompileTime;
0629 
0630     auto& data = PodioUtil::getDataMutable(m_collection->at(istate));
0631 
0632     if (data.measdim != kInvalid && data.measdim != measdim) {
0633       throw std::invalid_argument{
0634           "Measurement dimension does not match the allocated dimension"};
0635     }
0636 
0637     data.measdim = measdim;
0638 
0639     Eigen::Map<ActsVector<measdim>> valMap(data.measurement.data());
0640     valMap = val;
0641 
0642     Eigen::Map<ActsSquareMatrix<measdim>> covMap(
0643         data.measurementCovariance.data());
0644     covMap = cov;
0645   }
0646 
0647   void setUncalibratedSourceLink_impl(IndexType istate,
0648                                       const SourceLink& sourceLink) {
0649     PodioUtil::Identifier id =
0650         m_helper.get().sourceLinkToIdentifier(sourceLink);
0651     auto& data = PodioUtil::getDataMutable(m_collection->at(istate));
0652     data.uncalibratedIdentifier = id;
0653   }
0654 
0655   void setReferenceSurface_impl(IndexType istate,
0656                                 std::shared_ptr<const Surface> surface) {
0657     auto trackState = m_collection->at(istate);
0658     trackState.setReferenceSurface(
0659         PodioUtil::convertSurfaceToPodio(m_helper, *surface));
0660     m_surfaces.at(istate) = std::move(surface);
0661   }
0662 
0663   MultiTrajectoryTraits::IndexType calibratedSize_impl(IndexType istate) const {
0664     return m_collection->at(istate).getData().measdim;
0665   }
0666 
0667   SourceLink getUncalibratedSourceLink_impl(IndexType istate) const {
0668     return m_helper.get().identifierToSourceLink(
0669         m_collection->at(istate).getData().uncalibratedIdentifier);
0670   }
0671 
0672   const Surface* referenceSurface_impl(IndexType istate) const {
0673     return m_surfaces.at(istate).get();
0674   }
0675 
0676   void releaseInto(podio::Frame& frame, const std::string& suffix = "") {
0677     std::string s = suffix;
0678     if (!s.empty()) {
0679       s = "_" + s;
0680     }
0681     frame.put(std::move(m_collection), "trackStates" + s);
0682     frame.put(std::move(m_params), "trackStateParameters" + s);
0683     frame.put(std::move(m_jacs), "trackStateJacobians" + s);
0684     m_surfaces.clear();
0685 
0686     for (const auto& [key, col] : m_dynamic) {
0687       col->releaseInto(frame, "trackStates" + s + "_extra__");
0688     }
0689 
0690     m_dynamic.clear();
0691   }
0692 
0693   detail::DynamicKeyRange<podio_detail::DynamicColumnBase> dynamicKeys_impl()
0694       const {
0695     return {m_dynamic.begin(), m_dynamic.end()};
0696   }
0697 
0698   void copyDynamicFrom_impl(IndexType dstIdx, HashedString key,
0699                             const std::any& srcPtr) {
0700     auto it = m_dynamic.find(key);
0701     if (it == m_dynamic.end()) {
0702       throw std::invalid_argument{
0703           "Destination container does not have matching dynamic column"};
0704     }
0705 
0706     it->second->copyFrom(dstIdx, srcPtr);
0707   }
0708 
0709  private:
0710   friend class PodioTrackStateContainerBase;
0711   friend class ConstPodioTrackStateContainer;
0712 
0713   std::reference_wrapper<PodioUtil::ConversionHelper> m_helper;
0714   std::unique_ptr<ActsPodioEdm::TrackStateCollection> m_collection;
0715   std::unique_ptr<ActsPodioEdm::BoundParametersCollection> m_params;
0716   std::unique_ptr<ActsPodioEdm::JacobianCollection> m_jacs;
0717   std::vector<std::shared_ptr<const Surface>> m_surfaces;
0718 
0719   std::unordered_map<HashedString,
0720                      std::unique_ptr<podio_detail::DynamicColumnBase>>
0721       m_dynamic;
0722   std::vector<HashedString> m_dynamicKeys;
0723 };
0724 
0725 static_assert(
0726     !IsReadOnlyMultiTrajectory<MutablePodioTrackStateContainer>::value,
0727     "MutablePodioTrackStateContainer should not be read-only");
0728 
0729 static_assert(MutableMultiTrajectoryBackend<MutablePodioTrackStateContainer>,
0730               "MutablePodioTrackStateContainer does not fulfill "
0731               "TrackStateContainerBackend");
0732 
0733 inline ConstPodioTrackStateContainer::ConstPodioTrackStateContainer(
0734     const MutablePodioTrackStateContainer& other)
0735     : m_helper{other.m_helper},
0736       m_collection{other.m_collection.get()},
0737       m_params{other.m_params.get()},
0738       m_jacs{other.m_jacs.get()},
0739       m_surfaces{other.m_surfaces} {
0740   for (const auto& [key, col] : other.m_dynamic) {
0741     m_dynamic.insert({key, col->asConst()});
0742   }
0743 }
0744 
0745 }  // namespace Acts