Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-11 09:39:49

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/SpacePointColumnProxy2.hpp"
0013 #include "Acts/EventData/Types.hpp"
0014 #include "Acts/EventData/detail/SpacePointContainer2Column.hpp"
0015 #include "Acts/Utilities/EnumBitwiseOperators.hpp"
0016 #include "Acts/Utilities/Zip.hpp"
0017 #include "Acts/Utilities/detail/ContainerIterator.hpp"
0018 #include "Acts/Utilities/detail/ContainerRange.hpp"
0019 #include "Acts/Utilities/detail/ContainerSubset.hpp"
0020 
0021 #include <cassert>
0022 #include <limits>
0023 #include <memory>
0024 #include <optional>
0025 #include <ranges>
0026 #include <span>
0027 #include <stdexcept>
0028 #include <string>
0029 #include <type_traits>
0030 #include <unordered_map>
0031 #include <vector>
0032 
0033 namespace Acts {
0034 
0035 static constexpr float NoTime = std::numeric_limits<float>::quiet_NaN();
0036 
0037 class SpacePointContainer2;
0038 template <bool read_only>
0039 class SpacePointProxy2;
0040 using MutableSpacePointProxy2 = SpacePointProxy2<false>;
0041 using ConstSpacePointProxy2 = SpacePointProxy2<true>;
0042 
0043 enum class SpacePointColumns : std::uint32_t {
0044   None = 0,  ///< No columns
0045 
0046   SourceLinks = 1 << 0,           ///< Source link information
0047   X = 1 << 1,                     ///< X coordinate
0048   Y = 1 << 2,                     ///< Y coordinate
0049   Z = 1 << 3,                     ///< Z coordinate
0050   R = 1 << 4,                     ///< Radial coordinate
0051   Phi = 1 << 5,                   ///< Azimuthal angle
0052   Time = 1 << 6,                  ///< Time information
0053   VarianceZ = 1 << 7,             ///< Variance in Z direction
0054   VarianceR = 1 << 8,             ///< Variance in radial direction
0055   TopStripVector = 1 << 9,        ///< Vector for the top strip
0056   BottomStripVector = 1 << 10,    ///< Vector for the bottom strip
0057   StripCenterDistance = 1 << 11,  ///< Distance to the strip center
0058   TopStripCenter = 1 << 12,       ///< Center of the top strip
0059   CopyFromIndex = 1 << 13,        ///< Copy from index
0060 
0061   // packed columns for performance reasons
0062   XY = 1 << 14,          ///< X and Y coordinates
0063   ZR = 1 << 15,          ///< Z and R coordinates
0064   XYZ = 1 << 16,         ///< X, Y, and Z coordinates
0065   XYZR = 1 << 17,        ///< X, Y, Z, and R coordinates
0066   VarianceZR = 1 << 18,  ///< Variance in Z and R directions
0067 
0068   /// All strip-related columns
0069   Strip =
0070       TopStripVector | BottomStripVector | StripCenterDistance | TopStripCenter,
0071 };
0072 
0073 ACTS_DEFINE_ENUM_BITWISE_OPERATORS(SpacePointColumns);
0074 
0075 /// A container for space points, which can hold additional columns of data
0076 /// and allows for efficient access to space points and their associated source
0077 /// links. Individual space points are addressed via index. A proxy object
0078 /// simplifies the handling.
0079 class SpacePointContainer2 {
0080  public:
0081   /// Type alias for space point index in container
0082   using Index = SpacePointIndex2;
0083   /// Type alias for range of space point indices
0084   using IndexRange = SpacePointIndexRange2;
0085   /// Type alias for subset of space point indices
0086   using IndexSubset = SpacePointIndexSubset2;
0087   /// Type alias for mutable space point proxy
0088   using MutableProxy = MutableSpacePointProxy2;
0089   /// Type alias for const space point proxy
0090   using ConstProxy = ConstSpacePointProxy2;
0091 
0092   /// Constructs and empty space point container.
0093   /// @param columns The columns to create in the container.
0094   explicit SpacePointContainer2(
0095       SpacePointColumns columns = SpacePointColumns::None) noexcept;
0096 
0097   /// Constructs a copy of the given space point container.
0098   /// @param other The space point container to copy.
0099   SpacePointContainer2(const SpacePointContainer2 &other) noexcept;
0100 
0101   /// Move constructs a space point container.
0102   /// @param other The space point container to move.
0103   SpacePointContainer2(SpacePointContainer2 &&other) noexcept;
0104 
0105   /// Detructs the space point container.
0106   ~SpacePointContainer2() noexcept = default;
0107 
0108   /// Assignment operator for copying a space point container.
0109   /// @param other The space point container to copy.
0110   /// @return A reference to this space point container.
0111   SpacePointContainer2 &operator=(const SpacePointContainer2 &other) noexcept;
0112 
0113   /// Move assignment operator for a space point container.
0114   /// @param other The space point container to move.
0115   /// @return A reference to this space point container.
0116   SpacePointContainer2 &operator=(SpacePointContainer2 &&other) noexcept;
0117 
0118   /// Returns the number of space points in the container.
0119   /// @return The number of space points in the container.
0120   std::uint32_t size() const noexcept { return m_size; }
0121   /// Checks if the container is empty.
0122   /// @return True if the container is empty, false otherwise.
0123   [[nodiscard]] bool empty() const noexcept { return size() == 0; }
0124 
0125   /// Reserves space for the given number of space points.
0126   /// This will reserve space for the source links and other columns as well.
0127   /// @param size The number of space points to reserve space for.
0128   /// @param averageSourceLinks The average number of source links per space point.
0129   void reserve(std::uint32_t size, float averageSourceLinks = 1) noexcept;
0130 
0131   /// Clears the container, removing all space points and columns.
0132   void clear() noexcept;
0133 
0134   /// Creates a new space point at the end of the container.
0135   /// @return A mutable proxy to the newly created space point.
0136   MutableProxy createSpacePoint() noexcept;
0137 
0138   /// Creates additional columns. This will create the columns if they do not
0139   /// already exist.
0140   /// @param columns The columns to create.
0141   void createColumns(SpacePointColumns columns) noexcept;
0142 
0143   /// Drops the specified columns from the container.
0144   /// This will only drop columns if they exist.
0145   /// @param columns The columns to drop.
0146   void dropColumns(SpacePointColumns columns) noexcept;
0147 
0148   /// Checks if the container has the given Columns.
0149   /// @param columns The Columns to check for.
0150   /// @return True if the container has all the specified Columns, false
0151   ///         otherwise.
0152   bool hasColumns(SpacePointColumns columns) const noexcept {
0153     return (m_knownColumns & columns) == columns;
0154   }
0155 
0156   /// Creates a new column with the given name.
0157   /// If a column with the same name already exists, an exception is thrown.
0158   /// @param name The name of the column.
0159   /// @return A reference to the newly created column.
0160   /// @throws std::runtime_error if a column with the same name already exists.
0161   /// @throws std::runtime_error if the column name is reserved.
0162   template <typename T>
0163   MutableSpacePointColumnProxy<T> createColumn(const std::string &name) {
0164     return createColumnImpl<ColumnHolder<T>>(name);
0165   }
0166 
0167   /// Drops the column with the given name.
0168   /// If the column does not exist, an exception is thrown.
0169   /// @param name The name of the column.
0170   /// @throws std::runtime_error if the column does not exist.
0171   /// @throws std::runtime_error if the column name is reserved.
0172   void dropColumn(const std::string &name);
0173 
0174   /// Checks if an Column with the given name exists.
0175   /// @param name The name of the column.
0176   /// @return True if the column exists, false otherwise.
0177   bool hasColumn(const std::string &name) const noexcept {
0178     return m_namedColumns.contains(name);
0179   }
0180 
0181   /// Returns a mutable reference to the Column with the given name.
0182   /// If the column does not exist, an exception is thrown.
0183   /// @param name The name of the column.
0184   /// @return A mutable reference to the Column.
0185   /// @throws std::runtime_error if the column does not exist.
0186   template <typename T>
0187   ConstSpacePointColumnProxy<T> column(const std::string &name) const {
0188     return columnImpl<ColumnHolder<T>>(name);
0189   }
0190 
0191   /// Returns a mutable proxy to the x coordinate column.
0192   /// @return A mutable proxy to the x coordinate column.
0193   MutableSpacePointColumnProxy<float> xColumn() noexcept {
0194     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0195     return m_xColumn->proxy(*this);
0196   }
0197   /// Returns a mutable proxy to the y coordinate column.
0198   /// @return A mutable proxy to the y coordinate column.
0199   MutableSpacePointColumnProxy<float> yColumn() noexcept {
0200     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0201     return m_yColumn->proxy(*this);
0202   }
0203   /// Returns a mutable proxy to the z coordinate column.
0204   /// @return A mutable proxy to the z coordinate column.
0205   MutableSpacePointColumnProxy<float> zColumn() noexcept {
0206     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0207     return m_zColumn->proxy(*this);
0208   }
0209   /// Returns a mutable proxy to the r coordinate column.
0210   /// @return A mutable proxy to the r coordinate column.
0211   MutableSpacePointColumnProxy<float> rColumn() noexcept {
0212     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0213     return m_rColumn->proxy(*this);
0214   }
0215   /// Returns a mutable proxy to the phi coordinate column.
0216   /// @return A mutable proxy to the phi coordinate column.
0217   MutableSpacePointColumnProxy<float> phiColumn() noexcept {
0218     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0219     return m_phiColumn->proxy(*this);
0220   }
0221   /// Returns a mutable proxy to the time column.
0222   /// @return A mutable proxy to the time column.
0223   MutableSpacePointColumnProxy<float> timeColumn() noexcept {
0224     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0225     return m_timeColumn->proxy(*this);
0226   }
0227   /// Returns a mutable proxy to the variance in Z direction column.
0228   /// @return A mutable proxy to the variance in Z direction column.
0229   MutableSpacePointColumnProxy<float> varianceZColumn() noexcept {
0230     assert(m_varianceZColumn.has_value() &&
0231            "Column 'varianceZ' does not exist");
0232     return m_varianceZColumn->proxy(*this);
0233   }
0234   /// Returns a mutable proxy to the variance in R direction column.
0235   /// @return A mutable proxy to the variance in R direction column.
0236   MutableSpacePointColumnProxy<float> varianceRColumn() noexcept {
0237     assert(m_varianceRColumn.has_value() &&
0238            "Column 'varianceR' does not exist");
0239     return m_varianceRColumn->proxy(*this);
0240   }
0241   /// Returns a mutable proxy to the top strip vector column.
0242   /// @return A mutable proxy to the top strip vector column.
0243   MutableSpacePointColumnProxy<std::array<float, 3>>
0244   topStripVectorColumn() noexcept {
0245     assert(m_topStripVectorColumn.has_value() &&
0246            "Column 'topStripVector' does not exist");
0247     return m_topStripVectorColumn->proxy(*this);
0248   }
0249   /// Returns a mutable proxy to the bottom strip vector column.
0250   /// @return A mutable proxy to the bottom strip vector column.
0251   MutableSpacePointColumnProxy<std::array<float, 3>>
0252   bottomStripVectorColumn() noexcept {
0253     assert(m_bottomStripVectorColumn.has_value() &&
0254            "Column 'bottomStripVector' does not exist");
0255     return m_bottomStripVectorColumn->proxy(*this);
0256   }
0257   /// Returns a mutable proxy to the strip center distance column.
0258   /// @return A mutable proxy to the strip center distance column.
0259   MutableSpacePointColumnProxy<std::array<float, 3>>
0260   stripCenterDistanceColumn() noexcept {
0261     assert(m_stripCenterDistanceColumn.has_value() &&
0262            "Column 'stripCenterDistance' does not exist");
0263     return m_stripCenterDistanceColumn->proxy(*this);
0264   }
0265   /// Returns a mutable proxy to the top strip center column.
0266   /// @return A mutable proxy to the top strip center column.
0267   MutableSpacePointColumnProxy<std::array<float, 3>>
0268   topStripCenterColumn() noexcept {
0269     assert(m_topStripCenterColumn.has_value() &&
0270            "Column 'topStripCenter' does not exist");
0271     return m_topStripCenterColumn->proxy(*this);
0272   }
0273   /// Returns a mutable proxy to the copy from index column.
0274   /// @return A mutable proxy to the copy from index column.
0275   MutableSpacePointColumnProxy<SpacePointIndex2>
0276   copyFromIndexColumn() noexcept {
0277     assert(m_copyFromIndexColumn.has_value() &&
0278            "Column 'copyFromIndex' does not exist");
0279     return m_copyFromIndexColumn->proxy(*this);
0280   }
0281   /// Returns a mutable proxy to the xy coordinates column.
0282   /// @return A mutable proxy to the xy coordinates column.
0283   MutableSpacePointColumnProxy<std::array<float, 2>> xyColumn() noexcept {
0284     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0285     return m_xyColumn->proxy(*this);
0286   }
0287   /// Returns a mutable proxy to the zr coordinates column.
0288   /// @return A mutable proxy to the zr coordinates column.
0289   MutableSpacePointColumnProxy<std::array<float, 2>> zrColumn() noexcept {
0290     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0291     return m_zrColumn->proxy(*this);
0292   }
0293   /// Returns a mutable proxy to the xyz coordinates column.
0294   /// @return A mutable proxy to the xyz coordinates column.
0295   MutableSpacePointColumnProxy<std::array<float, 3>> xyzColumn() noexcept {
0296     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0297     return m_xyzColumn->proxy(*this);
0298   }
0299   /// Returns a mutable proxy to the xyzr coordinates column.
0300   /// @return A mutable proxy to the xyzr coordinates column.
0301   MutableSpacePointColumnProxy<std::array<float, 4>> xyzrColumn() noexcept {
0302     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0303     return m_xyzrColumn->proxy(*this);
0304   }
0305   /// Returns a mutable proxy to the variance zr column.
0306   /// @return A mutable proxy to the variance zr column.
0307   MutableSpacePointColumnProxy<std::array<float, 2>>
0308   varianceZRColumn() noexcept {
0309     assert(m_varianceZRColumn.has_value() &&
0310            "Column 'varianceZR' does not exist");
0311     return m_varianceZRColumn->proxy(*this);
0312   }
0313 
0314   /// Returns a const proxy to the x coordinate column.
0315   /// @return A const proxy to the x coordinate column.
0316   ConstSpacePointColumnProxy<float> xColumn() const noexcept {
0317     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0318     return m_xColumn->proxy(*this);
0319   }
0320   /// Returns a const proxy to the y coordinate column.
0321   /// @return A const proxy to the y coordinate column.
0322   ConstSpacePointColumnProxy<float> yColumn() const noexcept {
0323     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0324     return m_yColumn->proxy(*this);
0325   }
0326   /// Returns a const proxy to the z coordinate column.
0327   /// @return A const proxy to the z coordinate column.
0328   ConstSpacePointColumnProxy<float> zColumn() const noexcept {
0329     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0330     return m_zColumn->proxy(*this);
0331   }
0332   /// Returns a const proxy to the r coordinate column.
0333   /// @return A const proxy to the r coordinate column.
0334   ConstSpacePointColumnProxy<float> rColumn() const noexcept {
0335     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0336     return m_rColumn->proxy(*this);
0337   }
0338   /// Returns a const proxy to the phi coordinate column.
0339   /// @return A const proxy to the phi coordinate column.
0340   ConstSpacePointColumnProxy<float> phiColumn() const noexcept {
0341     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0342     return m_phiColumn->proxy(*this);
0343   }
0344   /// Returns a const proxy to the time column.
0345   /// @return A const proxy to the time column.
0346   ConstSpacePointColumnProxy<float> timeColumn() const noexcept {
0347     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0348     return m_timeColumn->proxy(*this);
0349   }
0350   /// Returns a const proxy to the variance in Z direction column.
0351   /// @return A const proxy to the variance in Z direction column.
0352   ConstSpacePointColumnProxy<float> varianceZColumn() const noexcept {
0353     assert(m_varianceZColumn.has_value() &&
0354            "Column 'varianceZ' does not exist");
0355     return m_varianceZColumn->proxy(*this);
0356   }
0357   /// Returns a const proxy to the variance in R direction column.
0358   /// @return A const proxy to the variance in R direction column.
0359   ConstSpacePointColumnProxy<float> varianceRColumn() const noexcept {
0360     assert(m_varianceRColumn.has_value() &&
0361            "Column 'varianceR' does not exist");
0362     return m_varianceRColumn->proxy(*this);
0363   }
0364   /// Returns a const proxy to the top strip vector column.
0365   /// @return A const proxy to the top strip vector column.
0366   ConstSpacePointColumnProxy<std::array<float, 3>> topStripVectorColumn()
0367       const noexcept {
0368     assert(m_topStripVectorColumn.has_value() &&
0369            "Column 'topStripVector' does not exist");
0370     return m_topStripVectorColumn->proxy(*this);
0371   }
0372   /// Returns a const proxy to the bottom strip vector column.
0373   /// @return A const proxy to the bottom strip vector column.
0374   ConstSpacePointColumnProxy<std::array<float, 3>> bottomStripVectorColumn()
0375       const noexcept {
0376     assert(m_bottomStripVectorColumn.has_value() &&
0377            "Column 'bottomStripVector' does not exist");
0378     return m_bottomStripVectorColumn->proxy(*this);
0379   }
0380   /// Returns a const proxy to the strip center distance column.
0381   /// @return A const proxy to the strip center distance column.
0382   ConstSpacePointColumnProxy<std::array<float, 3>> stripCenterDistanceColumn()
0383       const noexcept {
0384     assert(m_stripCenterDistanceColumn.has_value() &&
0385            "Column 'stripCenterDistance' does not exist");
0386     return m_stripCenterDistanceColumn->proxy(*this);
0387   }
0388   /// Returns a const proxy to the top strip center column.
0389   /// @return A const proxy to the top strip center column.
0390   ConstSpacePointColumnProxy<std::array<float, 3>> topStripCenterColumn()
0391       const noexcept {
0392     assert(m_topStripCenterColumn.has_value() &&
0393            "Column 'topStripCenter' does not exist");
0394     return m_topStripCenterColumn->proxy(*this);
0395   }
0396   /// Returns a const proxy to the copy from index column.
0397   /// @return A const proxy to the copy from index column.
0398   ConstSpacePointColumnProxy<SpacePointIndex2> copyFromIndexColumn()
0399       const noexcept {
0400     assert(m_copyFromIndexColumn.has_value() &&
0401            "Column 'copyFromIndex' does not exist");
0402     return m_copyFromIndexColumn->proxy(*this);
0403   }
0404   /// Returns a const proxy to the xy coordinates column.
0405   /// @return A const proxy to the xy coordinates column.
0406   ConstSpacePointColumnProxy<std::array<float, 2>> xyColumn() const noexcept {
0407     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0408     return m_xyColumn->proxy(*this);
0409   }
0410   /// Returns a const proxy to the zr coordinates column.
0411   /// @return A const proxy to the zr coordinates column.
0412   ConstSpacePointColumnProxy<std::array<float, 2>> zrColumn() const noexcept {
0413     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0414     return m_zrColumn->proxy(*this);
0415   }
0416   /// Returns a const proxy to the xyz coordinates column.
0417   /// @return A const proxy to the xyz coordinates column.
0418   ConstSpacePointColumnProxy<std::array<float, 3>> xyzColumn() const noexcept {
0419     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0420     return m_xyzColumn->proxy(*this);
0421   }
0422   /// Returns a const proxy to the xyzr coordinates column.
0423   /// @return A const proxy to the xyzr coordinates column.
0424   ConstSpacePointColumnProxy<std::array<float, 4>> xyzrColumn() const noexcept {
0425     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0426     return m_xyzrColumn->proxy(*this);
0427   }
0428   /// Returns a const proxy to the variance zr column.
0429   /// @return A const proxy to the variance zr column.
0430   ConstSpacePointColumnProxy<std::array<float, 2>> varianceZRColumn()
0431       const noexcept {
0432     assert(m_varianceZRColumn.has_value() &&
0433            "Column 'varianceZR' does not exist");
0434     return m_varianceZRColumn->proxy(*this);
0435   }
0436 
0437   /// Returns a mutable proxy to the space point at the given index.
0438   /// If the index is out of range, an exception is thrown.
0439   /// @param index The index of the space point to access.
0440   /// @return A mutable proxy to the space point at the given index.
0441   /// @throws std::out_of_range if the index is out of range.
0442   MutableProxy at(Index index);
0443   /// Returns a const proxy to the space point at the given index.
0444   /// If the index is out of range, an exception is thrown.
0445   /// @param index The index of the space point to access.
0446   /// @return A const proxy to the space point at the given index.
0447   /// @throws std::out_of_range if the index is out of range.
0448   ConstProxy at(Index index) const;
0449 
0450   /// Returns a mutable proxy to the space point at the given index.
0451   /// @param index The index of the space point to access.
0452   /// @return A mutable proxy to the space point at the given index.
0453   MutableProxy operator[](Index index) noexcept;
0454   /// Returns a const proxy to the space point at the given index.
0455   /// @param index The index of the space point to access.
0456   /// @return A const proxy to the space point at the given index.
0457   ConstProxy operator[](Index index) const noexcept;
0458 
0459   /// Assigns source links to the space point at the given index.
0460   /// @param index The index of the space point to assign source links to.
0461   /// @param sourceLinks A span of source links to assign to the space point.
0462   /// @throws std::out_of_range if the index is out of range.
0463   /// @throws std::logic_error if no source links column is available.
0464   /// @throws std::logic_error if source links are already assigned to the space point.
0465   void assignSourceLinks(Index index, std::span<const SourceLink> sourceLinks);
0466 
0467   /// Mutable access to the source links at the given index.
0468   /// @param index The index of the space point.
0469   /// @return A mutable reference to the source link at the given index.
0470   std::span<SourceLink> sourceLinks(Index index) {
0471     assert(m_sourceLinkOffsetColumn.has_value() &&
0472            m_sourceLinkCountColumn.has_value() &&
0473            "Column 'sourceLinks' does not exist");
0474     assert(index < m_sourceLinkOffsetColumn->size() &&
0475            index < m_sourceLinkCountColumn->size() && "Index out of bounds");
0476     return std::span<SourceLink>(
0477         m_sourceLinks.data() + m_sourceLinkOffsetColumn->proxy(*this)[index],
0478         m_sourceLinkCountColumn->proxy(*this)[index]);
0479   }
0480   /// Mutable access to the x coordinate of the space point at the given index.
0481   /// @param index The index of the space point.
0482   /// @return A mutable reference to the x coordinate of the space point.
0483   float &x(Index index) noexcept {
0484     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0485     assert(index < m_xColumn->size() && "Index out of bounds");
0486     return m_xColumn->proxy(*this)[index];
0487   }
0488   /// Mutable access to the y coordinate of the space point at the given index.
0489   /// @param index The index of the space point.
0490   /// @return A mutable reference to the y coordinate of the space point.
0491   float &y(Index index) noexcept {
0492     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0493     assert(index < m_yColumn->size() && "Index out of bounds");
0494     return m_yColumn->proxy(*this)[index];
0495   }
0496   /// Mutable access to the z coordinate of the space point at the given index.
0497   /// @param index The index of the space point.
0498   /// @return A mutable reference to the z coordinate of the space point.
0499   float &z(Index index) noexcept {
0500     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0501     assert(index < m_zColumn->size() && "Index out of bounds");
0502     return m_zColumn->proxy(*this)[index];
0503   }
0504   /// Mutable access to the r coordinate of the space point at the given
0505   /// index.
0506   /// @param index The index of the space point.
0507   /// @return A mutable reference to the r coordinate of the space point.
0508   float &r(Index index) noexcept {
0509     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0510     assert(index < m_rColumn->size() && "Index out of bounds");
0511     return m_rColumn->proxy(*this)[index];
0512   }
0513   /// Mutable access to the phi coordinate of the space point at the given
0514   /// index.
0515   /// @param index The index of the space point.
0516   /// @return A mutable reference to the phi coordinate of the space point.
0517   float &phi(Index index) noexcept {
0518     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0519     assert(index < m_phiColumn->size() && "Index out of bounds");
0520     return m_phiColumn->proxy(*this)[index];
0521   }
0522   /// Mutable access to the time information of the space point at the
0523   /// given index.
0524   /// @param index The index of the space point.
0525   /// @return A mutable reference to the time information of the space point.
0526   float &time(Index index) noexcept {
0527     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0528     assert(index < m_timeColumn->size() && "Index out of bounds");
0529     return m_timeColumn->proxy(*this)[index];
0530   }
0531   /// Mutable access to the variance in Z direction of the space point at
0532   /// the given index.
0533   /// @param index The index of the space point.
0534   /// @return A mutable reference to the variance in Z direction of the space point.
0535   float &varianceZ(Index index) noexcept {
0536     assert(m_varianceZColumn.has_value() &&
0537            "Column 'varianceZ' does not exist");
0538     assert(index < m_varianceZColumn->size() && "Index out of bounds");
0539     return m_varianceZColumn->proxy(*this)[index];
0540   }
0541   /// Mutable access to the variance in R direction of the space
0542   /// point at the given index.
0543   /// @param index The index of the space point.
0544   /// @return A mutable reference to the variance in R direction of the space point.
0545   float &varianceR(Index index) noexcept {
0546     assert(m_varianceRColumn.has_value() &&
0547            "Column 'varianceR' does not exist");
0548     assert(index < m_varianceRColumn->size() && "Index out of bounds");
0549     return m_varianceRColumn->proxy(*this)[index];
0550   }
0551   /// Mutable access to the top strip vector of the space point at the
0552   /// given index.
0553   /// @param index The index of the space point.
0554   /// @return A mutable reference to the top strip vector of the space point.
0555   std::array<float, 3> &topStripVector(Index index) noexcept {
0556     assert(m_topStripVectorColumn.has_value() &&
0557            "Column 'topStripVector' does not exist");
0558     assert(index < m_topStripVectorColumn->size() && "Index out of bounds");
0559     return m_topStripVectorColumn->proxy(*this)[index];
0560   }
0561   /// Mutable access to the bottom strip vector of the space point at the
0562   /// given index.
0563   /// @param index The index of the space point.
0564   /// @return A mutable reference to the bottom strip vector of the space point.
0565   std::array<float, 3> &bottomStripVector(Index index) noexcept {
0566     assert(m_bottomStripVectorColumn.has_value() &&
0567            "Column 'bottomStripVector' does not exist");
0568     assert(index < m_bottomStripVectorColumn->size() && "Index out of bounds");
0569     return m_bottomStripVectorColumn->proxy(*this)[index];
0570   }
0571   /// Mutable access to the strip center distance of the space point at
0572   /// the given index.
0573   /// @param index The index of the space point.
0574   /// @return A mutable reference to the strip center distance of the space point.
0575   std::array<float, 3> &stripCenterDistance(Index index) noexcept {
0576     assert(m_stripCenterDistanceColumn.has_value() &&
0577            "Column 'stripCenterDistance' does not exist");
0578     assert(index < m_stripCenterDistanceColumn->size() &&
0579            "Index out of bounds");
0580     return m_stripCenterDistanceColumn->proxy(*this)[index];
0581   }
0582   /// Mutable access to the top strip center of the space point at the
0583   /// given index.
0584   /// @param index The index of the space point.
0585   /// @return A mutable reference to the top strip center of the space point.
0586   std::array<float, 3> &topStripCenter(Index index) noexcept {
0587     assert(m_topStripCenterColumn.has_value() &&
0588            "Column 'topStripCenter' does not exist");
0589     assert(index < m_topStripCenterColumn->size() && "Index out of bounds");
0590     return m_topStripCenterColumn->proxy(*this)[index];
0591   }
0592   /// Mutable access to the copy from index of the space point at the given
0593   /// index.
0594   /// @param index The index of the space point.
0595   /// @return A mutable reference to the copy from index of the space point.
0596   SpacePointIndex2 &copyFromIndex(Index index) noexcept {
0597     assert(m_copyFromIndexColumn.has_value() &&
0598            "Column 'copyFromIndex' does not exist");
0599     assert(index < m_copyFromIndexColumn->size() && "Index out of bounds");
0600     return m_copyFromIndexColumn->proxy(*this)[index];
0601   }
0602   /// Mutable access to the xy coordinates of the space point at the given
0603   /// index.
0604   /// @param index The index of the space point.
0605   /// @return A mutable reference to the xy coordinates of the space point.
0606   std::array<float, 2> &xy(Index index) noexcept {
0607     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0608     assert(index < m_xyColumn->size() && "Index out of bounds");
0609     return m_xyColumn->proxy(*this)[index];
0610   }
0611   /// Mutable access to the zr coordinates of the space point at the given
0612   /// index.
0613   /// @param index The index of the space point.
0614   /// @return A mutable reference to the zr coordinates of the space point.
0615   std::array<float, 2> &zr(Index index) noexcept {
0616     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0617     assert(index < m_zrColumn->size() && "Index out of bounds");
0618     return m_zrColumn->proxy(*this)[index];
0619   }
0620   /// Mutable access to the xyz coordinates of the space point at the given
0621   /// index.
0622   /// @param index The index of the space point.
0623   /// @return A mutable reference to the xyz coordinates of the space point.
0624   std::array<float, 3> &xyz(Index index) noexcept {
0625     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0626     assert(index < m_xyzColumn->size() && "Index out of bounds");
0627     return m_xyzColumn->proxy(*this)[index];
0628   }
0629   /// Mutable access to the xyzr coordinates of the space point at the given
0630   /// index.
0631   /// @param index The index of the space point.
0632   /// @return A mutable reference to the xyzr coordinates of the space point.
0633   std::array<float, 4> &xyzr(Index index) noexcept {
0634     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0635     assert(index < m_xyzrColumn->size() && "Index out of bounds");
0636     return m_xyzrColumn->proxy(*this)[index];
0637   }
0638   /// Mutable access to the variance zr of the space point at the given
0639   /// index.
0640   /// @param index The index of the space point.
0641   /// @return A mutable reference to the variance zr of the space point.
0642   std::array<float, 2> &varianceZR(Index index) noexcept {
0643     assert(m_varianceZRColumn.has_value() &&
0644            "Column 'varianceZR' does not exist");
0645     assert(index < m_varianceZRColumn->size() && "Index out of bounds");
0646     return m_varianceZRColumn->proxy(*this)[index];
0647   }
0648 
0649   /// Const access to the source links at the given index.
0650   /// @param index The index of the space point.
0651   /// @return A const span to the source links at the given index.
0652   std::span<const SourceLink> sourceLinks(Index index) const noexcept {
0653     assert(m_sourceLinkOffsetColumn.has_value() &&
0654            m_sourceLinkCountColumn.has_value() &&
0655            "Column 'sourceLinks' does not exist");
0656     assert(index < m_sourceLinkOffsetColumn->size() &&
0657            index < m_sourceLinkCountColumn->size() && "Index out of bounds");
0658     return std::span<const SourceLink>(
0659         m_sourceLinks.data() + m_sourceLinkOffsetColumn->proxy(*this)[index],
0660         m_sourceLinkCountColumn->proxy(*this)[index]);
0661   }
0662   /// Const access to the x coordinate of the space point at the given index.
0663   /// @param index The index of the space point.
0664   /// @return A const reference to the x coordinate of the space point.
0665   float x(Index index) const noexcept {
0666     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0667     assert(index < m_xColumn->size() && "Index out of bounds");
0668     return m_xColumn->proxy(*this)[index];
0669   }
0670   /// Const access to the y coordinate of the space point at the given index.
0671   /// @param index The index of the space point.
0672   /// @return A const reference to the y coordinate of the space point.
0673   float y(Index index) const noexcept {
0674     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0675     assert(index < m_yColumn->size() && "Index out of bounds");
0676     return m_yColumn->proxy(*this)[index];
0677   }
0678   /// Const access to the z coordinate of the space point at the given index.
0679   /// @param index The index of the space point.
0680   /// @return A const reference to the z coordinate of the space point.
0681   float z(Index index) const noexcept {
0682     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0683     assert(index < m_zColumn->size() && "Index out of bounds");
0684     return m_zColumn->proxy(*this)[index];
0685   }
0686   /// Const access to the r coordinate of the space point at the given
0687   /// index.
0688   /// @param index The index of the space point.
0689   /// @return A const reference to the r coordinate of the space point.
0690   float r(Index index) const noexcept {
0691     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0692     assert(index < m_rColumn->size() && "Index out of bounds");
0693     return m_rColumn->proxy(*this)[index];
0694   }
0695   /// Const access to the phi coordinate of the space point at the given
0696   /// index.
0697   /// @param index The index of the space point.
0698   /// @return A const reference to the phi coordinate of the space point.
0699   float phi(Index index) const noexcept {
0700     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0701     assert(index < m_phiColumn->size() && "Index out of bounds");
0702     return m_phiColumn->proxy(*this)[index];
0703   }
0704   /// Const access to the time information of the space point at the
0705   /// given index.
0706   /// @param index The index of the space point.
0707   /// @return A const reference to the time information of the space point.
0708   float time(Index index) const noexcept {
0709     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0710     assert(index < m_timeColumn->size() && "Index out of bounds");
0711     return m_timeColumn->proxy(*this)[index];
0712   }
0713   /// Const access to the variance in Z direction of the space point at
0714   /// the given index.
0715   /// @param index The index of the space point.
0716   /// @return A const reference to the variance in Z direction of the space point.
0717   float varianceZ(Index index) const noexcept {
0718     assert(m_varianceZColumn.has_value() &&
0719            "Column 'varianceZ' does not exist");
0720     assert(index < m_varianceZColumn->size() && "Index out of bounds");
0721     return m_varianceZColumn->proxy(*this)[index];
0722   }
0723   /// Const access to the variance in R direction of the space
0724   /// point at the given index.
0725   /// @param index The index of the space point.
0726   /// @return A const reference to the variance in R direction of the space point.
0727   float varianceR(Index index) const noexcept {
0728     assert(m_varianceRColumn.has_value() &&
0729            "Column 'varianceR' does not exist");
0730     assert(index < m_varianceRColumn->size() && "Index out of bounds");
0731     return m_varianceRColumn->proxy(*this)[index];
0732   }
0733   /// Const access to the top strip vector of the space point at the
0734   /// given index.
0735   /// @param index The index of the space point.
0736   /// @return A const reference to the top strip vector of the space point.
0737   const std::array<float, 3> &topStripVector(Index index) const noexcept {
0738     assert(m_topStripVectorColumn.has_value() &&
0739            "Column 'topStripVector' does not exist");
0740     assert(index < m_topStripVectorColumn->size() && "Index out of bounds");
0741     return m_topStripVectorColumn->proxy(*this)[index];
0742   }
0743   /// Const access to the bottom strip vector of the space point at the
0744   /// given index.
0745   /// @param index The index of the space point.
0746   /// @return A const reference to the bottom strip vector of the space point.
0747   const std::array<float, 3> &bottomStripVector(Index index) const noexcept {
0748     assert(m_bottomStripVectorColumn.has_value() &&
0749            "Column 'bottomStripVector' does not exist");
0750     assert(index < m_bottomStripVectorColumn->size() && "Index out of bounds");
0751     return m_bottomStripVectorColumn->proxy(*this)[index];
0752   }
0753   /// Const access to the strip center distance of the space point at
0754   /// the given index.
0755   /// @param index The index of the space point.
0756   /// @return A const reference to the strip center distance of the space point.
0757   const std::array<float, 3> &stripCenterDistance(Index index) const noexcept {
0758     assert(m_stripCenterDistanceColumn.has_value() &&
0759            "Column 'stripCenterDistance' does not exist");
0760     assert(index < m_stripCenterDistanceColumn->size() &&
0761            "Index out of bounds");
0762     return m_stripCenterDistanceColumn->proxy(*this)[index];
0763   }
0764   /// Const access to the top strip center of the space point at the
0765   /// given index.
0766   /// @param index The index of the space point.
0767   /// @return A const reference to the top strip center of the space point.
0768   const std::array<float, 3> &topStripCenter(Index index) const noexcept {
0769     assert(m_topStripCenterColumn.has_value() &&
0770            "Column 'topStripCenter' does not exist");
0771     assert(index < m_topStripCenterColumn->size() && "Index out of bounds");
0772     return m_topStripCenterColumn->proxy(*this)[index];
0773   }
0774   /// Const access to the copy from index of the space point at the given
0775   /// index.
0776   /// @param index The index of the space point.
0777   /// @return A const reference to the copy from index of the space point.
0778   SpacePointIndex2 copyFromIndex(Index index) const noexcept {
0779     assert(m_copyFromIndexColumn.has_value() &&
0780            "Column 'copyFromIndex' does not exist");
0781     assert(index < m_copyFromIndexColumn->size() && "Index out of bounds");
0782     return m_copyFromIndexColumn->proxy(*this)[index];
0783   }
0784   /// Const access to the xy coordinates of the space point at the given index.
0785   /// @param index The index of the space point.
0786   /// @return A const reference to the xy coordinates of the space point.
0787   const std::array<float, 2> &xy(Index index) const noexcept {
0788     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0789     assert(index < m_xyColumn->size() && "Index out of bounds");
0790     return m_xyColumn->proxy(*this)[index];
0791   }
0792   /// Const access to the zr coordinates of the space point at the given index.
0793   /// @param index The index of the space point.
0794   /// @return A const reference to the zr coordinates of the space point.
0795   const std::array<float, 2> &zr(Index index) const noexcept {
0796     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0797     assert(index < m_zrColumn->size() && "Index out of bounds");
0798     return m_zrColumn->proxy(*this)[index];
0799   }
0800   /// Const access to the xyz coordinates of the space point at the given
0801   /// index.
0802   /// @param index The index of the space point.
0803   /// @return A const reference to the xyz coordinates of the space point.
0804   const std::array<float, 3> &xyz(Index index) const noexcept {
0805     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0806     assert(index < m_xyzColumn->size() && "Index out of bounds");
0807     return m_xyzColumn->proxy(*this)[index];
0808   }
0809   /// Const access to the xyzr coordinates of the space point at the given
0810   /// index.
0811   /// @param index The index of the space point.
0812   /// @return A const reference to the xyzr coordinates of the space point.
0813   const std::array<float, 4> &xyzr(Index index) const noexcept {
0814     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0815     assert(index < m_xyzrColumn->size() && "Index out of bounds");
0816     return m_xyzrColumn->proxy(*this)[index];
0817   }
0818   /// Const access to the variance zr of the space point at the given index.
0819   /// @param index The index of the space point.
0820   /// @return A const reference to the variance zr of the space point.
0821   const std::array<float, 2> &varianceZR(Index index) const noexcept {
0822     assert(m_varianceZRColumn.has_value() &&
0823            "Column 'varianceZR' does not exist");
0824     assert(index < m_varianceZRColumn->size() && "Index out of bounds");
0825     return m_varianceZRColumn->proxy(*this)[index];
0826   }
0827 
0828   /// Resolves the index to the actual index in the container.
0829   /// If the copyFromIndex column is set, it will return the index from that
0830   /// column. Otherwise, it will return the index itself.
0831   /// @param index The index to resolve.
0832   /// @return The resolved index.
0833   SpacePointIndex2 resolvedIndex(Index index) const noexcept {
0834     if (m_copyFromIndexColumn.has_value()) {
0835       return this->copyFromIndex(index);
0836     }
0837     return index;
0838   }
0839 
0840   /// Type alias for template iterator over space points in container
0841   template <bool read_only>
0842   using Iterator = Acts::detail::ContainerIterator<
0843       SpacePointContainer2,
0844       std::conditional_t<read_only, ConstSpacePointProxy2,
0845                          MutableSpacePointProxy2>,
0846       Index, read_only>;
0847 
0848   /// Type alias for mutable iterator over space points
0849   using iterator = Iterator<false>;
0850   /// Type alias for const iterator over space points
0851   using const_iterator = Iterator<true>;
0852 
0853   /// @brief Returns mutable iterator to the beginning of the container
0854   /// @return Mutable iterator pointing to the first space point
0855   iterator begin() noexcept { return iterator(*this, 0); }
0856   /// @brief Returns mutable iterator to the end of the container
0857   /// @return Mutable iterator pointing past the last space point
0858   iterator end() noexcept { return iterator(*this, size()); }
0859 
0860   /// @brief Returns const iterator to the beginning of the container
0861   /// @return Const iterator pointing to the first space point
0862   const_iterator begin() const noexcept { return const_iterator(*this, 0); }
0863   /// @brief Returns const iterator to the end of the container
0864   /// @return Const iterator pointing past the last space point
0865   const_iterator end() const noexcept { return const_iterator(*this, size()); }
0866 
0867   template <bool read_only>
0868   class Range
0869       : public Acts::detail::ContainerRange<Range<read_only>, Range<true>,
0870                                             SpacePointContainer2, Index,
0871                                             read_only> {
0872    public:
0873     using Base =
0874         Acts::detail::ContainerRange<Range<read_only>, Range<true>,
0875                                      SpacePointContainer2, Index, read_only>;
0876 
0877     using Base::Base;
0878 
0879     template <typename... Ts>
0880     auto zip(const ConstSpacePointColumnProxy<Ts> &...columns) const noexcept {
0881       return Base::container().zip(Base::range(), columns...);
0882     }
0883   };
0884   /// Type alias for mutable range of space points
0885   using MutableRange = Range<false>;
0886   /// Type alias for const range of space points
0887   using ConstRange = Range<true>;
0888 
0889   /// Creates a range of space points from the given index range.
0890   /// @param range The index range to create the range from.
0891   /// @return A mutable range of space points.
0892   MutableRange range(const IndexRange &range) noexcept {
0893     return MutableRange(*this, range);
0894   }
0895   /// Creates a range of space points from the given index range.
0896   /// @param range The index range to create the range from.
0897   /// @return A const range of space points.
0898   ConstRange range(const IndexRange &range) const noexcept {
0899     return ConstRange(*this, range);
0900   }
0901 
0902   template <bool read_only>
0903   class Subset : public Acts::detail::ContainerSubset<
0904                      Subset<read_only>, Subset<true>, SpacePointContainer2,
0905                      std::conditional_t<read_only, ConstSpacePointProxy2,
0906                                         MutableSpacePointProxy2>,
0907                      SpacePointIndex2, read_only> {
0908    public:
0909     using Base = Acts::detail::ContainerSubset<
0910         Subset<read_only>, Subset<true>, SpacePointContainer2,
0911         std::conditional_t<read_only, ConstSpacePointProxy2,
0912                            MutableSpacePointProxy2>,
0913         SpacePointIndex2, read_only>;
0914 
0915     using Base::Base;
0916 
0917     template <typename... Ts>
0918     auto zip(const ConstSpacePointColumnProxy<Ts> &...columns) const noexcept {
0919       return Base::container().zip(Base::subset(), columns...);
0920     }
0921   };
0922   /// Type alias for mutable subset of space points
0923   using MutableSubset = Subset<false>;
0924   /// Type alias for const subset of space points
0925   using ConstSubset = Subset<true>;
0926 
0927   /// Creates a mutable subset of space points from the given index subset.
0928   /// @param subset The index subset to create the subset from.
0929   /// @return A mutable subset of space points.
0930   MutableSubset subset(const IndexSubset &subset) noexcept {
0931     return MutableSubset(*this, subset);
0932   }
0933   /// Creates a const subset of space points from the given index subset.
0934   /// @param subset The index subset to create the subset from.
0935   /// @return A const subset of space points.
0936   ConstSubset subset(const IndexSubset &subset) const noexcept {
0937     return ConstSubset(*this, subset);
0938   }
0939 
0940   /// Creates a zipped mutable range of space point data from the given columns.
0941   /// @param columns The columns to zip.
0942   /// @return A zipped mutable range of space point data.
0943   template <typename... Ts>
0944   auto zip(const MutableSpacePointColumnProxy<Ts> &...columns) noexcept {
0945     return Acts::zip(std::ranges::iota_view<Index, Index>(0, size()),
0946                      columns.data()...);
0947   }
0948   /// Creates a zipped const range of space point data from the given columns.
0949   /// @param columns The columns to zip.
0950   /// @return A zipped const range of space point data.
0951   template <typename... Ts>
0952   auto zip(const ConstSpacePointColumnProxy<Ts> &...columns) const noexcept {
0953     return Acts::zip(std::ranges::iota_view<Index, Index>(0, size()),
0954                      columns.data()...);
0955   }
0956 
0957   /// Creates a zipped mutable range of space point data from the given columns.
0958   /// @param range The index range to zip.
0959   /// @param columns The columns to zip.
0960   /// @return A zipped mutable range of space point data.
0961   template <typename... Ts>
0962   auto zip(const IndexRange &range,
0963            const MutableSpacePointColumnProxy<Ts> &...columns) noexcept {
0964     return Acts::zip(
0965         std::ranges::iota_view<Index, Index>(range.first, range.second),
0966         columns.data().subspan(range.first, range.second - range.first)...);
0967   }
0968   /// Creates a zipped const range of space point data from the given columns.
0969   /// @param range The index range to create the zipped range from.
0970   /// @param columns The columns to zip.
0971   /// @return A zipped const range of space point data.
0972   template <typename... Ts>
0973   auto zip(const IndexRange &range,
0974            const ConstSpacePointColumnProxy<Ts> &...columns) const noexcept {
0975     return Acts::zip(
0976         std::ranges::iota_view<Index, Index>(range.first, range.second),
0977         columns.data().subspan(range.first, range.second - range.first)...);
0978   }
0979 
0980   /// @brief Create a zipped range over subset indices and mutable column data
0981   /// @tparam Ts Column data types to zip with indices
0982   /// @param subset Index subset to iterate over
0983   /// @param columns Mutable column proxies to zip with indices
0984   /// @return Zipped range for iteration over indices and column data
0985   template <typename... Ts>
0986   auto zip(const IndexSubset &subset,
0987            const MutableSpacePointColumnProxy<Ts> &...columns) noexcept {
0988     return Acts::zip(subset, columns.subset(subset)...);
0989   }
0990 
0991   /// @brief Create a zipped range over subset indices and const column data
0992   /// @tparam Ts Column data types to zip with indices
0993   /// @param subset Index subset to iterate over
0994   /// @param columns Const column proxies to zip with indices
0995   /// @return Const zipped range for iteration over indices and column data
0996   template <typename... Ts>
0997   auto zip(const IndexSubset &subset,
0998            const ConstSpacePointColumnProxy<Ts> &...columns) const noexcept {
0999     return Acts::zip(subset, columns.subset(subset)...);
1000   }
1001 
1002  private:
1003   using ColumnHolderBase = detail::sp::ColumnHolderBase;
1004   template <typename T>
1005   using ColumnHolder = detail::sp::ColumnHolder<T>;
1006 
1007   std::uint32_t m_size{0};
1008 
1009   std::unordered_map<
1010       std::string,
1011       std::pair<ColumnHolderBase *, std::unique_ptr<ColumnHolderBase>>,
1012       std::hash<std::string_view>, std::equal_to<>>
1013       m_namedColumns;
1014   SpacePointColumns m_knownColumns{SpacePointColumns::None};
1015 
1016   std::vector<SourceLink> m_sourceLinks;
1017 
1018   std::optional<ColumnHolder<SpacePointIndex2>> m_sourceLinkOffsetColumn;
1019   std::optional<ColumnHolder<std::uint8_t>> m_sourceLinkCountColumn;
1020 
1021   std::optional<ColumnHolder<float>> m_xColumn;
1022   std::optional<ColumnHolder<float>> m_yColumn;
1023   std::optional<ColumnHolder<float>> m_zColumn;
1024 
1025   // cylindrical coordinates
1026   std::optional<ColumnHolder<float>> m_rColumn;
1027   std::optional<ColumnHolder<float>> m_phiColumn;
1028   // time information
1029   std::optional<ColumnHolder<float>> m_timeColumn;
1030   // covariance information
1031   std::optional<ColumnHolder<float>> m_varianceZColumn;
1032   std::optional<ColumnHolder<float>> m_varianceRColumn;
1033   // strip information
1034   std::optional<ColumnHolder<std::array<float, 3>>> m_topStripVectorColumn;
1035   std::optional<ColumnHolder<std::array<float, 3>>> m_bottomStripVectorColumn;
1036   std::optional<ColumnHolder<std::array<float, 3>>> m_stripCenterDistanceColumn;
1037   std::optional<ColumnHolder<std::array<float, 3>>> m_topStripCenterColumn;
1038   // copy information
1039   std::optional<ColumnHolder<SpacePointIndex2>> m_copyFromIndexColumn;
1040 
1041   std::optional<ColumnHolder<std::array<float, 2>>> m_xyColumn;
1042   std::optional<ColumnHolder<std::array<float, 2>>> m_zrColumn;
1043   std::optional<ColumnHolder<std::array<float, 3>>> m_xyzColumn;
1044   std::optional<ColumnHolder<std::array<float, 4>>> m_xyzrColumn;
1045   std::optional<ColumnHolder<std::array<float, 2>>> m_varianceZRColumn;
1046 
1047   static auto knownColumnMasks() noexcept {
1048     using enum SpacePointColumns;
1049     return std::tuple(SourceLinks, SourceLinks, X, Y, Z, R, Phi, Time,
1050                       VarianceZ, VarianceR, TopStripVector, BottomStripVector,
1051                       StripCenterDistance, TopStripCenter, CopyFromIndex, XY,
1052                       ZR, XYZ, XYZR, VarianceZR);
1053   }
1054 
1055   static auto knownColumnNames() noexcept {
1056     return std::tuple("sourceLinkOffset", "sourceLinkCount", "x", "y", "z", "r",
1057                       "phi", "time", "varianceZ", "varianceR", "topStripVector",
1058                       "bottomStripVector", "stripCenterDistance",
1059                       "topStripCenter", "copyFromIndex", "xy", "zr", "xyz",
1060                       "xyzr", "varianceZR");
1061   }
1062 
1063   static auto knownColumnDefaults() noexcept {
1064     return std::tuple(
1065         SpacePointIndex2{0}, std::uint8_t{0}, float{0}, float{0}, float{0},
1066         float{0}, float{0}, float{NoTime}, float{0}, float{0},
1067         std::array<float, 3>{0, 0, 0}, std::array<float, 3>{0, 0, 0},
1068         std::array<float, 3>{0, 0, 0}, std::array<float, 3>{0, 0, 0},
1069         SpacePointIndex2{0}, std::array<float, 2>{0, 0},
1070         std::array<float, 2>{0, 0}, std::array<float, 3>{0, 0, 0},
1071         std::array<float, 4>{0, 0, 0, 0}, std::array<float, 2>{0, 0});
1072   }
1073 
1074   auto knownColumns() & noexcept {
1075     return std::tie(m_sourceLinkOffsetColumn, m_sourceLinkCountColumn,
1076                     m_xColumn, m_yColumn, m_zColumn, m_rColumn, m_phiColumn,
1077                     m_timeColumn, m_varianceZColumn, m_varianceRColumn,
1078                     m_topStripVectorColumn, m_bottomStripVectorColumn,
1079                     m_stripCenterDistanceColumn, m_topStripCenterColumn,
1080                     m_copyFromIndexColumn, m_xyColumn, m_zrColumn, m_xyzColumn,
1081                     m_xyzrColumn, m_varianceZRColumn);
1082   }
1083   auto knownColumns() const & noexcept {
1084     return std::tie(m_sourceLinkOffsetColumn, m_sourceLinkCountColumn,
1085                     m_xColumn, m_yColumn, m_zColumn, m_rColumn, m_phiColumn,
1086                     m_timeColumn, m_varianceZColumn, m_varianceRColumn,
1087                     m_topStripVectorColumn, m_bottomStripVectorColumn,
1088                     m_stripCenterDistanceColumn, m_topStripCenterColumn,
1089                     m_copyFromIndexColumn, m_xyColumn, m_zrColumn, m_xyzColumn,
1090                     m_xyzrColumn, m_varianceZRColumn);
1091   }
1092   auto knownColumns() && noexcept {
1093     return std::tuple(
1094         std::move(m_sourceLinkOffsetColumn), std::move(m_sourceLinkCountColumn),
1095         std::move(m_xColumn), std::move(m_yColumn), std::move(m_zColumn),
1096         std::move(m_rColumn), std::move(m_phiColumn), std::move(m_timeColumn),
1097         std::move(m_varianceZColumn), std::move(m_varianceRColumn),
1098         std::move(m_topStripVectorColumn), std::move(m_bottomStripVectorColumn),
1099         std::move(m_stripCenterDistanceColumn),
1100         std::move(m_topStripCenterColumn), std::move(m_copyFromIndexColumn),
1101         std::move(m_xyColumn), std::move(m_zrColumn), std::move(m_xyzColumn),
1102         std::move(m_xyzrColumn), std::move(m_varianceZRColumn));
1103   }
1104 
1105   void copyColumns(const SpacePointContainer2 &other);
1106   void moveColumns(SpacePointContainer2 &other) noexcept;
1107 
1108   static bool reservedColumn(const std::string &name) noexcept;
1109 
1110   template <typename Holder>
1111   auto createColumnImpl(const std::string &name) {
1112     if (reservedColumn(name)) {
1113       throw std::runtime_error("Column name is reserved: " + name);
1114     }
1115     if (hasColumn(name)) {
1116       throw std::runtime_error("Column already exists: " + name);
1117     }
1118     auto holder = std::make_unique<Holder>();
1119     holder->resize(size());
1120     auto proxy = holder->proxy(*this);
1121     m_namedColumns.try_emplace(name,
1122                                std::pair{holder.get(), std::move(holder)});
1123     return proxy;
1124   }
1125 
1126   template <typename Holder>
1127   auto columnImpl(const std::string &name) const {
1128     auto it = m_namedColumns.find(name);
1129     if (it == m_namedColumns.end()) {
1130       throw std::runtime_error("Column not found: " + name);
1131     }
1132     auto &holder = dynamic_cast<Holder &>(*it->second.first);
1133     return holder.proxy();
1134   }
1135 };
1136 
1137 }  // namespace Acts
1138 
1139 #include "Acts/EventData/SpacePointContainer2.ipp"