Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 07:51:25

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/SourceLink.hpp"
0012 #include "Acts/EventData/Types.hpp"
0013 #include "Acts/Utilities/EnumBitwiseOperators.hpp"
0014 #include "Acts/Utilities/TypeTraits.hpp"
0015 
0016 #include <cassert>
0017 #include <memory>
0018 #include <optional>
0019 #include <span>
0020 #include <stdexcept>
0021 #include <string>
0022 #include <unordered_map>
0023 #include <vector>
0024 
0025 #include <Eigen/Core>
0026 
0027 namespace Acts::Experimental {
0028 
0029 static constexpr float NoTime = std::numeric_limits<float>::quiet_NaN();
0030 
0031 template <bool read_only>
0032 class SpacePointProxy2;
0033 using MutableSpacePointProxy2 = SpacePointProxy2<false>;
0034 using ConstSpacePointProxy2 = SpacePointProxy2<true>;
0035 
0036 enum class SpacePointKnownExtraColumn : std::uint32_t {
0037   None = 0,  ///< No extra columns
0038 
0039   R = 1 << 0,                    ///< Radial coordinate
0040   Phi = 1 << 1,                  ///< Azimuthal angle
0041   Time = 1 << 2,                 ///< Time information
0042   VarianceZ = 1 << 3,            ///< Variance in Z direction
0043   VarianceR = 1 << 4,            ///< Variance in radial direction
0044   TopStripVector = 1 << 5,       ///< Vector for the top strip
0045   BottomStripVector = 1 << 6,    ///< Vector for the bottom strip
0046   StripCenterDistance = 1 << 7,  ///< Distance to the strip center
0047   TopStripCenter = 1 << 8,       ///< Center of the top strip
0048   CopyFromIndex = 1 << 9,        ///< Copy from index
0049 
0050   /// All strip-related columns
0051   Strip =
0052       TopStripVector | BottomStripVector | StripCenterDistance | TopStripCenter
0053 };
0054 
0055 ACTS_DEFINE_ENUM_BITWISE_OPERATORS(SpacePointKnownExtraColumn);
0056 
0057 /// Additional column of data that can be added to the space point container.
0058 /// The column is indexed by the space point index.
0059 template <typename T>
0060 class SpacePointExtraColumnProxy {
0061  public:
0062   using ValueType = T;
0063   using ContainerType = std::vector<ValueType>;
0064 
0065   explicit SpacePointExtraColumnProxy(const ContainerType &data)
0066       : m_data(&data) {}
0067   SpacePointExtraColumnProxy(const SpacePointExtraColumnProxy &other) = default;
0068   SpacePointExtraColumnProxy(SpacePointExtraColumnProxy &&other) noexcept =
0069       default;
0070   SpacePointExtraColumnProxy &operator=(
0071       const SpacePointExtraColumnProxy &other) = default;
0072   SpacePointExtraColumnProxy &operator=(
0073       SpacePointExtraColumnProxy &&other) noexcept = default;
0074 
0075  private:
0076   const ContainerType *m_data{};
0077 
0078   ContainerType &data() { return const_cast<ContainerType &>(*m_data); }
0079   const ContainerType &data() const { return *m_data; }
0080 
0081   friend class SpacePointContainer2;
0082 };
0083 
0084 class SpacePointColumnHolderBase {
0085  public:
0086   virtual ~SpacePointColumnHolderBase() = default;
0087 
0088   virtual std::unique_ptr<SpacePointColumnHolderBase> copy() const = 0;
0089 
0090   virtual std::size_t size() const = 0;
0091   virtual void reserve(std::size_t size) = 0;
0092   virtual void resize(std::size_t size) = 0;
0093   virtual void clear() = 0;
0094   virtual void emplace_back() = 0;
0095 };
0096 
0097 template <typename T>
0098 class SpacePointExtraColumnHolder final : public SpacePointColumnHolderBase {
0099  public:
0100   using ValueType = T;
0101   using ContainerType = std::vector<ValueType>;
0102   using ProxyType = SpacePointExtraColumnProxy<ValueType>;
0103 
0104   SpacePointExtraColumnHolder() = default;
0105   explicit SpacePointExtraColumnHolder(ValueType defaultValue)
0106       : m_default(std::move(defaultValue)) {}
0107 
0108   ProxyType proxy() const { return ProxyType(m_data); }
0109 
0110   std::unique_ptr<SpacePointColumnHolderBase> copy() const override {
0111     return std::make_unique<SpacePointExtraColumnHolder<T>>(*this);
0112   }
0113 
0114   std::size_t size() const override { return m_data.size(); }
0115   void reserve(std::size_t size) override { m_data.reserve(size); }
0116   void clear() override { m_data.clear(); }
0117   void resize(std::size_t size) override { m_data.resize(size, m_default); }
0118   void emplace_back() override { m_data.emplace_back(m_default); }
0119 
0120  private:
0121   ValueType m_default{};
0122   ContainerType m_data;
0123 };
0124 
0125 /// A container for space points, which can hold additional columns of data
0126 /// and allows for efficient access to space points and their associated source
0127 /// links. Individual space points are addressed via index. A proxy object
0128 /// simplifies the handling.
0129 class SpacePointContainer2 {
0130  public:
0131   using IndexType = SpacePointIndex2;
0132   using IndexRangeType = SpacePointIndexRange2;
0133   using MutableProxyType = MutableSpacePointProxy2;
0134   using ConstProxyType = ConstSpacePointProxy2;
0135 
0136   /// Constructs and empty space point container.
0137   SpacePointContainer2() noexcept = default;
0138 
0139   /// Constructs a copy of the given space point container.
0140   /// The extra columns are copied as well.
0141   /// @param other The space point container to copy.
0142   SpacePointContainer2(const SpacePointContainer2 &other) noexcept;
0143 
0144   /// Move constructs a space point container.
0145   /// The extra columns are moved as well.
0146   /// @param other The space point container to move.
0147   SpacePointContainer2(SpacePointContainer2 &&other) noexcept;
0148 
0149   /// Detructs the space point container.
0150   ~SpacePointContainer2() noexcept = default;
0151 
0152   /// Assignment operator for copying a space point container.
0153   /// The extra columns are copied as well.
0154   /// @param other The space point container to copy.
0155   /// @return A reference to this space point container.
0156   SpacePointContainer2 &operator=(const SpacePointContainer2 &other) noexcept;
0157 
0158   /// Move assignment operator for a space point container.
0159   /// The extra columns are moved as well.
0160   /// @param other The space point container to move.
0161   /// @return A reference to this space point container.
0162   SpacePointContainer2 &operator=(SpacePointContainer2 &&other) noexcept;
0163 
0164   /// Returns the number of space points in the container.
0165   /// @return The number of space points in the container.
0166   std::size_t size() const noexcept { return m_sourceLinkOffsets.size(); }
0167   /// Checks if the container is empty.
0168   /// @return True if the container is empty, false otherwise.
0169   [[nodiscard]] bool empty() const noexcept { return size() == 0; }
0170 
0171   /// Reserves space for the given number of space points.
0172   /// This will reserve space for the source links and the extra columns as
0173   /// well.
0174   /// @param size The number of space points to reserve space for.
0175   /// @param averageSourceLinks The average number of source links per space point.
0176   void reserve(std::size_t size, float averageSourceLinks = 1) noexcept;
0177 
0178   /// Clears the container, removing all space points and extra columns.
0179   void clear() noexcept;
0180 
0181   /// Emplaces a new space point with the given source links and coordinates.
0182   /// This will create a new space point at the end of the container.
0183   /// @param sourceLinks The source links associated with the space point.
0184   /// @param x The x coordinate of the space point.
0185   /// @param y The y coordinate of the space point.
0186   /// @param z The z coordinate of the space point.
0187   /// @return A mutable proxy to the newly created space point.
0188   MutableProxyType createSpacePoint(std::span<const SourceLink> sourceLinks,
0189                                     float x, float y, float z) noexcept;
0190 
0191   /// Returns a mutable proxy to the space point at the given index.
0192   /// If the index is out of range, an exception is thrown.
0193   /// @param index The index of the space point to access.
0194   /// @return A mutable proxy to the space point at the given index.
0195   /// @throws std::out_of_range if the index is out of range.
0196   MutableProxyType at(IndexType index);
0197   /// Returns a const proxy to the space point at the given index.
0198   /// If the index is out of range, an exception is thrown.
0199   /// @param index The index of the space point to access.
0200   /// @return A const proxy to the space point at the given index.
0201   /// @throws std::out_of_range if the index is out of range.
0202   ConstProxyType at(IndexType index) const;
0203 
0204   /// Returns a mutable proxy to the space point at the given index.
0205   /// @param index The index of the space point to access.
0206   /// @return A mutable proxy to the space point at the given index.
0207   MutableProxyType operator[](IndexType index) noexcept;
0208   /// Returns a const proxy to the space point at the given index.
0209   /// @param index The index of the space point to access.
0210   /// @return A const proxy to the space point at the given index.
0211   ConstProxyType operator[](IndexType index) const noexcept;
0212 
0213   /// Mutable access to the source links at the given index.
0214   /// @param index The index of the space point.
0215   /// @return A mutable reference to the source link at the given index.
0216   std::span<SourceLink> sourceLinks(IndexType index) {
0217     assert(index < m_x.size() && "Index out of bounds");
0218     return std::span<SourceLink>(
0219         m_sourceLinks.data() + m_sourceLinkOffsets[index],
0220         m_sourceLinkCounts[index]);
0221   }
0222   /// Mutable access to the x coordinate of the space point at the given index.
0223   /// @param index The index of the space point.
0224   /// @return A mutable reference to the x coordinate of the space point.
0225   float &x(IndexType index) noexcept {
0226     assert(index < m_y.size() && "Index out of bounds");
0227     return m_x[index];
0228   }
0229   /// Mutable access to the y coordinate of the space point at the given index.
0230   /// @param index The index of the space point.
0231   /// @return A mutable reference to the y coordinate of the space point.
0232   float &y(IndexType index) noexcept {
0233     assert(index < m_y.size() && "Index out of bounds");
0234     return m_y[index];
0235   }
0236   /// Mutable access to the z coordinate of the space point at the given index.
0237   /// @param index The index of the space point.
0238   /// @return A mutable reference to the z coordinate of the space point.
0239   float &z(IndexType index) noexcept {
0240     assert(index < m_z.size() && "Index out of bounds");
0241     return m_z[index];
0242   }
0243 
0244   /// Mutable access to the extra r coordinate of the space point at the given
0245   /// index.
0246   /// @param index The index of the space point.
0247   /// @return A mutable reference to the r coordinate of the space point.
0248   float &r(IndexType index) noexcept {
0249     assert(m_rColumn.has_value() && "Extra column 'r' does not exist");
0250     assert(index < m_rColumn->size() && "Index out of bounds");
0251     return extra(m_rColumn->proxy(), index);
0252   }
0253   /// Mutable access to the extra phi coordinate of the space point at the given
0254   /// index.
0255   /// @param index The index of the space point.
0256   /// @return A mutable reference to the phi coordinate of the space point.
0257   float &phi(IndexType index) noexcept {
0258     assert(m_phiColumn.has_value() && "Extra column 'phi' does not exist");
0259     assert(index < m_phiColumn->size() && "Index out of bounds");
0260     return extra(m_phiColumn->proxy(), index);
0261   }
0262   /// Mutable access to the extra time information of the space point at the
0263   /// given index.
0264   /// @param index The index of the space point.
0265   /// @return A mutable reference to the time information of the space point.
0266   float &time(IndexType index) noexcept {
0267     assert(m_timeColumn.has_value() && "Extra column 'time' does not exist");
0268     assert(index < m_timeColumn->size() && "Index out of bounds");
0269     return extra(m_timeColumn->proxy(), index);
0270   }
0271   /// Mutable access to the extra variance in Z direction of the space point at
0272   /// the given index.
0273   /// @param index The index of the space point.
0274   /// @return A mutable reference to the variance in Z direction of the space point.
0275   float &varianceZ(IndexType index) noexcept {
0276     assert(m_varianceZColumn.has_value() &&
0277            "Extra column 'varianceZ' does not exist");
0278     assert(index < m_varianceZColumn->size() && "Index out of bounds");
0279     return extra(m_varianceZColumn->proxy(), index);
0280   }
0281   /// Mutable access to the extra variance in R direction of the space
0282   /// point at the given index.
0283   /// @param index The index of the space point.
0284   /// @return A mutable reference to the variance in R direction of the space point.
0285   float &varianceR(IndexType index) noexcept {
0286     assert(m_varianceRColumn.has_value() &&
0287            "Extra column 'varianceR' does not exist");
0288     assert(index < m_varianceRColumn->size() && "Index out of bounds");
0289     return extra(m_varianceRColumn->proxy(), index);
0290   }
0291   /// Mutable access to the extra top strip vector of the space point at the
0292   /// given index.
0293   /// @param index The index of the space point.
0294   /// @return A mutable reference to the top strip vector of the space point.
0295   Eigen::Vector3f &topStripVector(IndexType index) noexcept {
0296     assert(m_topStripVectorColumn.has_value() &&
0297            "Extra column 'topStripVector' does not exist");
0298     assert(index < m_topStripVectorColumn->size() && "Index out of bounds");
0299     return extra(m_topStripVectorColumn->proxy(), index);
0300   }
0301   /// Mutable access to the extra bottom strip vector of the space point at the
0302   /// given index.
0303   /// @param index The index of the space point.
0304   /// @return A mutable reference to the bottom strip vector of the space point.
0305   Eigen::Vector3f &bottomStripVector(IndexType index) noexcept {
0306     assert(m_bottomStripVectorColumn.has_value() &&
0307            "Extra column 'bottomStripVector' does not exist");
0308     assert(index < m_bottomStripVectorColumn->size() && "Index out of bounds");
0309     return extra(m_bottomStripVectorColumn->proxy(), index);
0310   }
0311   /// Mutable access to the extra strip center distance of the space point at
0312   /// the given index.
0313   /// @param index The index of the space point.
0314   /// @return A mutable reference to the strip center distance of the space point.
0315   Eigen::Vector3f &stripCenterDistance(IndexType index) noexcept {
0316     assert(m_stripCenterDistanceColumn.has_value() &&
0317            "Extra column 'stripCenterDistance' does not exist");
0318     assert(index < m_stripCenterDistanceColumn->size() &&
0319            "Index out of bounds");
0320     return extra(m_stripCenterDistanceColumn->proxy(), index);
0321   }
0322   /// Mutable access to the extra top strip center of the space point at the
0323   /// given index.
0324   /// @param index The index of the space point.
0325   /// @return A mutable reference to the top strip center of the space point.
0326   Eigen::Vector3f &topStripCenter(IndexType index) noexcept {
0327     assert(m_topStripCenterColumn.has_value() &&
0328            "Extra column 'topStripCenter' does not exist");
0329     assert(index < m_topStripCenterColumn->size() && "Index out of bounds");
0330     return extra(m_topStripCenterColumn->proxy(), index);
0331   }
0332   /// Mutable access to the copy from index of the space point at the given
0333   /// index.
0334   /// @param index The index of the space point.
0335   /// @return A mutable reference to the copy from index of the space point.
0336   std::size_t &copyFromIndex(IndexType index) noexcept {
0337     assert(m_copyFromIndexColumn.has_value() &&
0338            "Extra column 'copyFromIndex' does not exist");
0339     assert(index < m_copyFromIndexColumn->size() && "Index out of bounds");
0340     return extra(m_copyFromIndexColumn->proxy(), index);
0341   }
0342 
0343   /// Const access to the source links at the given index.
0344   /// @param index The index of the space point.
0345   /// @return A const span to the source links at the given index.
0346   std::span<const SourceLink> sourceLinks(IndexType index) const noexcept {
0347     assert(index < m_sourceLinkCounts.size() && "Index out of bounds");
0348     assert(index < m_sourceLinkOffsets.size() && "Index out of bounds");
0349     return std::span<const SourceLink>(
0350         m_sourceLinks.data() + m_sourceLinkOffsets[index],
0351         m_sourceLinkCounts[index]);
0352   }
0353   /// Const access to the x coordinate of the space point at the given index.
0354   /// @param index The index of the space point.
0355   /// @return A const reference to the x coordinate of the space point.
0356   float x(IndexType index) const noexcept {
0357     assert(index < m_x.size() && "Index out of bounds");
0358     return m_x[index];
0359   }
0360   /// Const access to the y coordinate of the space point at the given index.
0361   /// @param index The index of the space point.
0362   /// @return A const reference to the y coordinate of the space point.
0363   float y(IndexType index) const noexcept {
0364     assert(index < m_y.size() && "Index out of bounds");
0365     return m_y[index];
0366   }
0367   /// Const access to the z coordinate of the space point at the given index.
0368   /// @param index The index of the space point.
0369   /// @return A const reference to the z coordinate of the space point.
0370   float z(IndexType index) const noexcept {
0371     assert(index < m_z.size() && "Index out of bounds");
0372     return m_z[index];
0373   }
0374 
0375   /// Const access to the extra r coordinate of the space point at the given
0376   /// index.
0377   /// @param index The index of the space point.
0378   /// @return A const reference to the r coordinate of the space point.
0379   float r(IndexType index) const noexcept {
0380     assert(m_rColumn.has_value() && "Extra column 'r' does not exist");
0381     assert(index < m_rColumn->size() && "Index out of bounds");
0382     return extra(m_rColumn->proxy(), index);
0383   }
0384   /// Const access to the extra phi coordinate of the space point at the given
0385   /// index.
0386   /// @param index The index of the space point.
0387   /// @return A const reference to the phi coordinate of the space point.
0388   float phi(IndexType index) const noexcept {
0389     assert(m_phiColumn.has_value() && "Extra column 'phi' does not exist");
0390     assert(index < m_phiColumn->size() && "Index out of bounds");
0391     return extra(m_phiColumn->proxy(), index);
0392   }
0393   /// Const access to the extra time information of the space point at the
0394   /// given index.
0395   /// @param index The index of the space point.
0396   /// @return A const reference to the time information of the space point.
0397   float time(IndexType index) const noexcept {
0398     assert(m_timeColumn.has_value() && "Extra column 'time' does not exist");
0399     assert(index < m_timeColumn->size() && "Index out of bounds");
0400     return extra(m_timeColumn->proxy(), index);
0401   }
0402   /// Const access to the extra variance in Z direction of the space point at
0403   /// the given index.
0404   /// @param index The index of the space point.
0405   /// @return A const reference to the variance in Z direction of the space point.
0406   float varianceZ(IndexType index) const noexcept {
0407     assert(m_varianceZColumn.has_value() &&
0408            "Extra column 'varianceZ' does not exist");
0409     assert(index < m_varianceZColumn->size() && "Index out of bounds");
0410     return extra(m_varianceZColumn->proxy(), index);
0411   }
0412   /// Const access to the extra variance in R direction of the space
0413   /// point at the given index.
0414   /// @param index The index of the space point.
0415   /// @return A const reference to the variance in R direction of the space point.
0416   float varianceR(IndexType index) const noexcept {
0417     assert(m_varianceRColumn.has_value() &&
0418            "Extra column 'varianceR' does not exist");
0419     assert(index < m_varianceRColumn->size() && "Index out of bounds");
0420     return extra(m_varianceRColumn->proxy(), index);
0421   }
0422   /// Const access to the extra top strip vector of the space point at the
0423   /// given index.
0424   /// @param index The index of the space point.
0425   /// @return A const reference to the top strip vector of the space point.
0426   const Eigen::Vector3f &topStripVector(IndexType index) const noexcept {
0427     assert(m_topStripVectorColumn.has_value() &&
0428            "Extra column 'topStripVector' does not exist");
0429     assert(index < m_topStripVectorColumn->size() && "Index out of bounds");
0430     return extra(m_topStripVectorColumn->proxy(), index);
0431   }
0432   /// Const access to the extra bottom strip vector of the space point at the
0433   /// given index.
0434   /// @param index The index of the space point.
0435   /// @return A const reference to the bottom strip vector of the space point.
0436   const Eigen::Vector3f &bottomStripVector(IndexType index) const noexcept {
0437     assert(m_bottomStripVectorColumn.has_value() &&
0438            "Extra column 'bottomStripVector' does not exist");
0439     assert(index < m_bottomStripVectorColumn->size() && "Index out of bounds");
0440     return extra(m_bottomStripVectorColumn->proxy(), index);
0441   }
0442   /// Const access to the extra strip center distance of the space point at
0443   /// the given index.
0444   /// @param index The index of the space point.
0445   /// @return A const reference to the strip center distance of the space point.
0446   const Eigen::Vector3f &stripCenterDistance(IndexType index) const noexcept {
0447     assert(m_stripCenterDistanceColumn.has_value() &&
0448            "Extra column 'stripCenterDistance' does not exist");
0449     assert(index < m_stripCenterDistanceColumn->size() &&
0450            "Index out of bounds");
0451     return extra(m_stripCenterDistanceColumn->proxy(), index);
0452   }
0453   /// Const access to the extra top strip center of the space point at the
0454   /// given index.
0455   /// @param index The index of the space point.
0456   /// @return A const reference to the top strip center of the space point.
0457   const Eigen::Vector3f &topStripCenter(IndexType index) const noexcept {
0458     assert(m_topStripCenterColumn.has_value() &&
0459            "Extra column 'topStripCenter' does not exist");
0460     assert(index < m_topStripCenterColumn->size() && "Index out of bounds");
0461     return extra(m_topStripCenterColumn->proxy(), index);
0462   }
0463   /// Const access to the copy from index of the space point at the given
0464   /// index.
0465   /// @param index The index of the space point.
0466   /// @return A const reference to the copy from index of the space point.
0467   std::size_t copyFromIndex(IndexType index) const noexcept {
0468     assert(m_copyFromIndexColumn.has_value() &&
0469            "Extra column 'copyFromIndex' does not exist");
0470     assert(index < m_copyFromIndexColumn->size() && "Index out of bounds");
0471     return extra(m_copyFromIndexColumn->proxy(), index);
0472   }
0473 
0474   template <typename T>
0475   T &extra(SpacePointExtraColumnProxy<T> column, IndexType index) noexcept {
0476     return column.data()[index];
0477   }
0478 
0479   template <typename T>
0480   const T &extra(const SpacePointExtraColumnProxy<T> &column,
0481                  IndexType index) const noexcept {
0482     return column.data()[index];
0483   }
0484 
0485   /// Creates extra columns based on the specified known extra columns.
0486   /// This will only create the columns if they do not already exist and fill
0487   /// them according to the size of the container with default values.
0488   /// @param columns The known extra columns to create.
0489   void createExtraColumns(SpacePointKnownExtraColumn columns) noexcept;
0490 
0491   /// Drops the specified extra columns from the container.
0492   /// This will only drop columns if they exist.
0493   /// @param columns The extra columns to drop.
0494   void dropExtraColumns(SpacePointKnownExtraColumn columns) noexcept;
0495 
0496   /// Checks if the container has the given extra columns.
0497   /// @param columns The extra columns to check for.
0498   /// @return True if the container has all the specified extra columns, false
0499   ///         otherwise.
0500   bool hasExtraColumns(SpacePointKnownExtraColumn columns) const noexcept {
0501     return (m_knownExtraColumns & columns) == columns;
0502   }
0503 
0504   /// Returns a proxy to the extra r coordinate column.
0505   /// If the column does not exist, an exception is thrown.
0506   /// @return A proxy to the extra r coordinate column.
0507   /// @throws std::runtime_error if the column does not exist.
0508   SpacePointExtraColumnProxy<float> rColumn() const {
0509     if (!m_rColumn.has_value()) {
0510       throw std::runtime_error("Extra column 'r' does not exist");
0511     }
0512     return m_rColumn->proxy();
0513   }
0514   /// Returns a proxy to the extra phi coordinate column.
0515   /// If the column does not exist, an exception is thrown.
0516   /// @return A proxy to the extra phi coordinate column.
0517   /// @throws std::runtime_error if the column does not exist.
0518   SpacePointExtraColumnProxy<float> phiColumn() const {
0519     if (!m_phiColumn.has_value()) {
0520       throw std::runtime_error("Extra column 'phi' does not exist");
0521     }
0522     return m_phiColumn->proxy();
0523   }
0524   /// Returns a proxy to the extra time column.
0525   /// If the column does not exist, an exception is thrown.
0526   /// @return A proxy to the extra time column.
0527   /// @throws std::runtime_error if the column does not exist.
0528   SpacePointExtraColumnProxy<float> timeColumn() const {
0529     if (!m_timeColumn.has_value()) {
0530       throw std::runtime_error("Extra column 'time' does not exist");
0531     }
0532     return m_timeColumn->proxy();
0533   }
0534   /// Returns a proxy to the extra variance in Z direction column.
0535   /// If the column does not exist, an exception is thrown.
0536   /// @return A proxy to the extra variance in Z direction column.
0537   /// @throws std::runtime_error if the column does not exist.
0538   SpacePointExtraColumnProxy<float> varianceZColumn() const {
0539     if (!m_varianceZColumn.has_value()) {
0540       throw std::runtime_error("Extra column 'varianceZ' does not exist");
0541     }
0542     return m_varianceZColumn->proxy();
0543   }
0544   /// Returns a proxy to the extra variance in R direction column.
0545   /// If the column does not exist, an exception is thrown.
0546   /// @return A proxy to the extra variance in R direction column.
0547   /// @throws std::runtime_error if the column does not exist.
0548   SpacePointExtraColumnProxy<float> varianceRColumn() const {
0549     if (!m_varianceRColumn.has_value()) {
0550       throw std::runtime_error("Extra column 'varianceR' does not exist");
0551     }
0552     return m_varianceRColumn->proxy();
0553   }
0554   /// Returns a proxy to the extra top strip vector column.
0555   /// If the column does not exist, an exception is thrown.
0556   /// @return A proxy to the extra top strip vector column.
0557   /// @throws std::runtime_error if the column does not exist.
0558   SpacePointExtraColumnProxy<Eigen::Vector3f> topStripVectorColumn() const {
0559     if (!m_topStripVectorColumn.has_value()) {
0560       throw std::runtime_error("Extra column 'topStripVector' does not exist");
0561     }
0562     return m_topStripVectorColumn->proxy();
0563   }
0564   /// Returns a proxy to the extra bottom strip vector column.
0565   /// If the column does not exist, an exception is thrown.
0566   /// @return A proxy to the extra bottom strip vector column.
0567   /// @throws std::runtime_error if the column does not exist.
0568   SpacePointExtraColumnProxy<Eigen::Vector3f> bottomStripVectorColumn() const {
0569     if (!m_bottomStripVectorColumn.has_value()) {
0570       throw std::runtime_error(
0571           "Extra column 'bottomStripVector' does not exist");
0572     }
0573     return m_bottomStripVectorColumn->proxy();
0574   }
0575   /// Returns a proxy to the extra strip center distance column.
0576   /// If the column does not exist, an exception is thrown.
0577   /// @return A proxy to the extra strip center distance column.
0578   /// @throws std::runtime_error if the column does not exist.
0579   SpacePointExtraColumnProxy<Eigen::Vector3f> stripCenterDistanceColumn()
0580       const {
0581     if (!m_stripCenterDistanceColumn.has_value()) {
0582       throw std::runtime_error(
0583           "Extra column 'stripCenterDistance' does not exist");
0584     }
0585     return m_stripCenterDistanceColumn->proxy();
0586   }
0587   /// Returns a proxy to the extra top strip center column.
0588   /// If the column does not exist, an exception is thrown.
0589   /// @return A proxy to the extra top strip center column.
0590   /// @throws std::runtime_error if the column does not exist.
0591   SpacePointExtraColumnProxy<Eigen::Vector3f> topStripCenterColumn() const {
0592     if (!m_topStripCenterColumn.has_value()) {
0593       throw std::runtime_error("Extra column 'topStripCenter' does not exist");
0594     }
0595     return m_topStripCenterColumn->proxy();
0596   }
0597   /// Returns a proxy to the extra copy from index column.
0598   /// If the column does not exist, an exception is thrown.
0599   /// @return A proxy to the extra copy from index column.
0600   /// @throws std::runtime_error if the column does not exist.
0601   SpacePointExtraColumnProxy<std::size_t> copyFromIndexColumn() const {
0602     if (!m_copyFromIndexColumn.has_value()) {
0603       throw std::runtime_error("Extra column 'copyFromIndex' does not exist");
0604     }
0605     return m_copyFromIndexColumn->proxy();
0606   }
0607 
0608   /// Creates a new column with the given name.
0609   /// If a column with the same name already exists, an exception is thrown.
0610   /// @param name The name of the column.
0611   /// @return A reference to the newly created column.
0612   /// @throws std::runtime_error if a column with the same name already exists.
0613   template <typename T>
0614   SpacePointExtraColumnProxy<T> createExtraColumn(const std::string &name) {
0615     return createExtraColumnImpl<SpacePointExtraColumnHolder<T>>(name);
0616   }
0617 
0618   /// Drops the extra column with the given name.
0619   /// If the column does not exist, an exception is thrown.
0620   /// @param name The name of the column.
0621   /// @throws std::runtime_error if the column does not exist.
0622   void dropExtraColumn(const std::string &name);
0623 
0624   /// Checks if an extra column with the given name exists.
0625   /// @param name The name of the column.
0626   /// @return True if the column exists, false otherwise.
0627   bool hasExtraColumn(const std::string &name) const noexcept;
0628 
0629   /// Returns a mutable reference to the extra column with the given name.
0630   /// If the column does not exist, an exception is thrown.
0631   /// @param name The name of the column.
0632   /// @return A mutable reference to the extra column.
0633   /// @throws std::runtime_error if the column does not exist.
0634   template <typename T>
0635   SpacePointExtraColumnProxy<T> extraColumn(const std::string &name) const {
0636     return extraColumnImpl<SpacePointExtraColumnHolder<T>>(name);
0637   }
0638 
0639   template <bool read_only>
0640   class Iterator {
0641    public:
0642     static constexpr bool ReadOnly = read_only;
0643 
0644     using ContainerType = const_if_t<ReadOnly, SpacePointContainer2>;
0645 
0646     using iterator_category = std::forward_iterator_tag;
0647     using value_type = SpacePointProxy2<ReadOnly>;
0648     using difference_type = std::ptrdiff_t;
0649 
0650     Iterator() noexcept = default;
0651     Iterator(ContainerType &container, IndexType index) noexcept
0652         : m_container(&container), m_index(index) {}
0653 
0654     Iterator &operator++() noexcept {
0655       ++m_index;
0656       return *this;
0657     }
0658     Iterator operator++(int) noexcept {
0659       Iterator tmp(*this);
0660       ++(*this);
0661       return tmp;
0662     }
0663 
0664     value_type operator*() const noexcept {
0665       return value_type(*m_container, m_index);
0666     }
0667 
0668    private:
0669     ContainerType *m_container{};
0670     IndexType m_index{};
0671 
0672     friend bool operator==(const Iterator &a, const Iterator &b) noexcept {
0673       return a.m_index == b.m_index && a.m_container == b.m_container;
0674     }
0675   };
0676   using iterator = Iterator<false>;
0677   using const_iterator = Iterator<true>;
0678 
0679   iterator begin() noexcept { return iterator(*this, 0); }
0680   iterator end() noexcept { return iterator(*this, size()); }
0681 
0682   const_iterator begin() const noexcept { return const_iterator(*this, 0); }
0683   const_iterator end() const noexcept { return const_iterator(*this, size()); }
0684 
0685   template <bool read_only>
0686   class Range {
0687    public:
0688     static constexpr bool ReadOnly = read_only;
0689     using ContainerType = const_if_t<ReadOnly, SpacePointContainer2>;
0690 
0691     using iterator = Iterator<read_only>;
0692     using const_iterator = Iterator<true>;
0693 
0694     Range(ContainerType &container, const IndexRangeType &range) noexcept
0695         : m_container(&container), m_range(range) {}
0696 
0697     std::size_t size() const noexcept { return m_range.second - m_range.first; }
0698     bool empty() const noexcept { return size() == 0; }
0699 
0700     iterator begin() const noexcept {
0701       return iterator(*m_container, m_range.first);
0702     }
0703     iterator end() const noexcept {
0704       return iterator(*m_container, m_range.second);
0705     }
0706 
0707     const_iterator cbegin() const noexcept {
0708       return const_iterator(*m_container, m_range.first);
0709     }
0710     const_iterator cend() const noexcept {
0711       return const_iterator(*m_container, m_range.second);
0712     }
0713 
0714    private:
0715     ContainerType *m_container{};
0716     IndexRangeType m_range{};
0717   };
0718   using MutableRange = Range<false>;
0719   using ConstRange = Range<true>;
0720 
0721   MutableRange range(const IndexRangeType &range) noexcept {
0722     return MutableRange(*this, range);
0723   }
0724   ConstRange range(const IndexRangeType &range) const noexcept {
0725     return ConstRange(*this, range);
0726   }
0727 
0728  private:
0729   std::vector<float> m_x;
0730   std::vector<float> m_y;
0731   std::vector<float> m_z;
0732   std::vector<std::size_t> m_sourceLinkOffsets;
0733   std::vector<std::uint8_t> m_sourceLinkCounts;
0734   std::vector<SourceLink> m_sourceLinks;
0735 
0736   // known extra columns
0737   SpacePointKnownExtraColumn m_knownExtraColumns{
0738       SpacePointKnownExtraColumn::None};
0739   // cylindrical coordinates
0740   std::optional<SpacePointExtraColumnHolder<float>> m_rColumn;
0741   std::optional<SpacePointExtraColumnHolder<float>> m_phiColumn;
0742   // time information
0743   std::optional<SpacePointExtraColumnHolder<float>> m_timeColumn;
0744   // covariance information
0745   std::optional<SpacePointExtraColumnHolder<float>> m_varianceZColumn;
0746   std::optional<SpacePointExtraColumnHolder<float>> m_varianceRColumn;
0747   // strip information
0748   std::optional<SpacePointExtraColumnHolder<Eigen::Vector3f>>
0749       m_topStripVectorColumn;
0750   std::optional<SpacePointExtraColumnHolder<Eigen::Vector3f>>
0751       m_bottomStripVectorColumn;
0752   std::optional<SpacePointExtraColumnHolder<Eigen::Vector3f>>
0753       m_stripCenterDistanceColumn;
0754   std::optional<SpacePointExtraColumnHolder<Eigen::Vector3f>>
0755       m_topStripCenterColumn;
0756   // copy information
0757   std::optional<SpacePointExtraColumnHolder<std::size_t>> m_copyFromIndexColumn;
0758 
0759   std::unordered_map<std::string, std::unique_ptr<SpacePointColumnHolderBase>>
0760       m_namedExtraColumns;
0761 
0762   std::vector<SpacePointColumnHolderBase *> m_extraColumns;
0763 
0764   auto knownExtraColumns() & noexcept {
0765     return std::tie(m_rColumn, m_phiColumn, m_timeColumn, m_varianceZColumn,
0766                     m_varianceRColumn, m_topStripVectorColumn,
0767                     m_bottomStripVectorColumn, m_stripCenterDistanceColumn,
0768                     m_topStripCenterColumn, m_copyFromIndexColumn);
0769   }
0770   auto knownExtraColumns() const & noexcept {
0771     return std::tie(m_rColumn, m_phiColumn, m_timeColumn, m_varianceZColumn,
0772                     m_varianceRColumn, m_topStripVectorColumn,
0773                     m_bottomStripVectorColumn, m_stripCenterDistanceColumn,
0774                     m_topStripCenterColumn, m_copyFromIndexColumn);
0775   }
0776   auto knownExtraColumns() && noexcept {
0777     return std::tuple(
0778         std::move(m_rColumn), std::move(m_phiColumn), std::move(m_timeColumn),
0779         std::move(m_varianceZColumn), std::move(m_varianceRColumn),
0780         std::move(m_topStripVectorColumn), std::move(m_bottomStripVectorColumn),
0781         std::move(m_stripCenterDistanceColumn),
0782         std::move(m_topStripCenterColumn), std::move(m_copyFromIndexColumn));
0783   }
0784 
0785   void copyExtraColumns(const SpacePointContainer2 &other);
0786   void moveExtraColumns(SpacePointContainer2 &other) noexcept;
0787 
0788   void initializeExtraColumns() noexcept;
0789 
0790   template <typename Holder>
0791   auto createExtraColumnImpl(const std::string &name) {
0792     if (hasExtraColumn(name)) {
0793       throw std::runtime_error("Extra column already exists: " + name);
0794     }
0795     auto holder = std::make_unique<Holder>();
0796     holder->resize(size());
0797     auto proxy = holder->proxy();
0798     m_extraColumns.push_back(holder.get());
0799     m_namedExtraColumns[name] = std::move(holder);
0800     return proxy;
0801   }
0802   template <typename Holder>
0803   auto extraColumnImpl(const std::string &name) const {
0804     auto it = m_namedExtraColumns.find(name);
0805     if (it == m_namedExtraColumns.end()) {
0806       throw std::runtime_error("Extra column not found: " + name);
0807     }
0808     auto &holder = dynamic_cast<Holder &>(*it->second);
0809     return holder.proxy();
0810   }
0811 };
0812 
0813 }  // namespace Acts::Experimental
0814 
0815 #include "Acts/EventData/SpacePointContainer2.ipp"