Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:43

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