Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-05 08:21:13

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/SpacePointColumnProxy.hpp"
0013 #include "Acts/EventData/SpacePointColumns.hpp"
0014 #include "Acts/EventData/StripSpacePointCalibrationDetails.hpp"
0015 #include "Acts/EventData/Types.hpp"
0016 #include "Acts/EventData/detail/SpacePointContainerColumn.hpp"
0017 #include "Acts/Utilities/Zip.hpp"
0018 #include "Acts/Utilities/detail/ContainerIterator.hpp"
0019 #include "Acts/Utilities/detail/ContainerRange.hpp"
0020 #include "Acts/Utilities/detail/ContainerSubset.hpp"
0021 
0022 #include <cassert>
0023 #include <limits>
0024 #include <memory>
0025 #include <optional>
0026 #include <ranges>
0027 #include <stdexcept>
0028 #include <string>
0029 #include <type_traits>
0030 #include <unordered_map>
0031 #include <vector>
0032 
0033 namespace Acts {
0034 
0035 /// Sentinel value for space points without timing information
0036 static constexpr float NoTime = std::numeric_limits<float>::quiet_NaN();
0037 
0038 template <bool>
0039 class SpacePointProxy;
0040 /// Mutable proxy to a space point allowing modification
0041 using MutableSpacePointProxy = SpacePointProxy<false>;
0042 /// Const proxy to a space point for read-only access
0043 using ConstSpacePointProxy = SpacePointProxy<true>;
0044 
0045 /// A container for space points, which can hold additional columns of data
0046 /// and allows for efficient access to space points and their associated source
0047 /// links. Individual space points are addressed via index. A proxy object
0048 /// simplifies the handling.
0049 class SpacePointContainer {
0050  public:
0051   /// Type alias for space point index in container
0052   using Index = SpacePointIndex;
0053   /// Type alias for range of space point indices
0054   using IndexRange = SpacePointIndexRange;
0055   /// Type alias for subset of space point indices
0056   using IndexSubset = SpacePointIndexSubset;
0057   /// Type alias for mutable space point proxy
0058   using MutableProxy = MutableSpacePointProxy;
0059   /// Type alias for const space point proxy
0060   using ConstProxy = ConstSpacePointProxy;
0061   /// Type alias for mutable column proxy
0062   template <typename T>
0063   using MutableColumnProxy = MutableSpacePointColumnProxy<T>;
0064   /// Type alias for const column proxy
0065   template <typename T>
0066   using ConstColumnProxy = ConstSpacePointColumnProxy<T>;
0067 
0068   /// Constructs and empty space point container.
0069   /// @param columns The columns to create in the container.
0070   explicit SpacePointContainer(
0071       SpacePointColumns columns = SpacePointColumns::None) noexcept;
0072 
0073   /// Constructs a copy of the given space point container.
0074   /// @param other The space point container to copy.
0075   SpacePointContainer(const SpacePointContainer &other) noexcept;
0076 
0077   /// Move constructs a space point container.
0078   /// @param other The space point container to move.
0079   SpacePointContainer(SpacePointContainer &&other) noexcept;
0080 
0081   /// Detructs the space point container.
0082   ~SpacePointContainer() noexcept = default;
0083 
0084   /// Assignment operator for copying a space point container.
0085   /// @param other The space point container to copy.
0086   /// @return A reference to this space point container.
0087   SpacePointContainer &operator=(const SpacePointContainer &other) noexcept;
0088 
0089   /// Move assignment operator for a space point container.
0090   /// @param other The space point container to move.
0091   /// @return A reference to this space point container.
0092   SpacePointContainer &operator=(SpacePointContainer &&other) noexcept;
0093 
0094   /// Returns the number of space points in the container.
0095   /// @return The number of space points in the container.
0096   std::uint32_t size() const noexcept { return m_size; }
0097   /// Checks if the container is empty.
0098   /// @return True if the container is empty, false otherwise.
0099   [[nodiscard]] bool empty() const noexcept { return size() == 0; }
0100 
0101   /// Reserves space for the given number of space points.
0102   /// This will reserve space for the source links and other columns as well.
0103   /// @param size The number of space points to reserve space for.
0104   /// @param averageSourceLinks The average number of source links per space point.
0105   void reserve(std::uint32_t size, float averageSourceLinks = 1) noexcept;
0106 
0107   /// Clears the container, removing all space points and columns.
0108   void clear() noexcept;
0109 
0110   /// Creates a new space point at the end of the container.
0111   /// @return A mutable proxy to the newly created space point.
0112   MutableProxy createSpacePoint() noexcept;
0113 
0114   /// Copies the specified columns from another space point to this space point
0115   /// @param index The index of the space point to copy to in this container.
0116   /// @param otherContainer The space point container to copy from.
0117   /// @param otherIndex The index of the space point to copy from in the other container.
0118   /// @param columnsToCopy The columns to copy from the other space point.
0119   void copyFrom(Index index, const SpacePointContainer &otherContainer,
0120                 Index otherIndex, SpacePointColumns columnsToCopy);
0121 
0122   /// Creates additional columns. This will create the columns if they do not
0123   /// already exist.
0124   /// @param columns The columns to create.
0125   void createColumns(SpacePointColumns columns) noexcept;
0126 
0127   /// Drops the specified columns from the container.
0128   /// This will only drop columns if they exist.
0129   /// @param columns The columns to drop.
0130   void dropColumns(SpacePointColumns columns) noexcept;
0131 
0132   /// Checks if the container has the given Columns.
0133   /// @param columns The Columns to check for.
0134   /// @return True if the container has all the specified Columns, false
0135   ///         otherwise.
0136   bool hasColumns(SpacePointColumns columns) const noexcept {
0137     return (m_knownColumns & columns) == columns;
0138   }
0139 
0140   /// Creates a new column with the given name.
0141   /// If a column with the same name already exists, an exception is thrown.
0142   /// @param name The name of the column.
0143   /// @return A reference to the newly created column.
0144   /// @throws std::runtime_error if a column with the same name already exists.
0145   /// @throws std::runtime_error if the column name is reserved.
0146   template <typename T>
0147   MutableColumnProxy<T> createColumn(const std::string &name) {
0148     return createColumnImpl<ColumnHolder<T>>(name);
0149   }
0150 
0151   /// Drops the column with the given name.
0152   /// If the column does not exist, an exception is thrown.
0153   /// @param name The name of the column.
0154   /// @throws std::runtime_error if the column does not exist.
0155   /// @throws std::runtime_error if the column name is reserved.
0156   void dropColumn(const std::string &name);
0157 
0158   /// Checks if an Column with the given name exists.
0159   /// @param name The name of the column.
0160   /// @return True if the column exists, false otherwise.
0161   bool hasColumn(const std::string &name) const noexcept {
0162     return m_allColumns.contains(name);
0163   }
0164 
0165   /// Returns a mutable reference to the column with the given name.
0166   /// If the column does not exist, an exception is thrown.
0167   /// @param name The name of the column.
0168   /// @return A mutable reference to the column.
0169   /// @throws std::runtime_error if the column does not exist.
0170   template <typename T>
0171   MutableColumnProxy<T> column(const std::string &name) {
0172     return columnImpl<ColumnHolder<T>>(name);
0173   }
0174 
0175   /// Returns a const reference to the column with the given name.
0176   /// If the column does not exist, an exception is thrown.
0177   /// @param name The name of the column.
0178   /// @return A const reference to the column.
0179   /// @throws std::runtime_error if the column does not exist.
0180   template <typename T>
0181   ConstColumnProxy<T> column(const std::string &name) const {
0182     return columnImpl<ColumnHolder<T>>(name);
0183   }
0184 
0185   /// Returns a mutable proxy to the `copied from index` column.
0186   /// @return A mutable proxy to the `copied from index` column.
0187   MutableColumnProxy<SpacePointIndex> copiedFromIndexColumn() noexcept {
0188     assert(m_copiedFromIndexColumn.has_value() &&
0189            "Column 'copiedFromIndex' does not exist");
0190     return m_copiedFromIndexColumn->proxy(*this);
0191   }
0192   /// Returns a mutable proxy to the `x` column.
0193   /// @return A mutable proxy to the `x` column.
0194   MutableColumnProxy<float> xColumn() noexcept {
0195     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0196     return m_xColumn->proxy(*this);
0197   }
0198   /// Returns a mutable proxy to the `y` column.
0199   /// @return A mutable proxy to the `y` column.
0200   MutableColumnProxy<float> yColumn() noexcept {
0201     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0202     return m_yColumn->proxy(*this);
0203   }
0204   /// Returns a mutable proxy to the `z` column.
0205   /// @return A mutable proxy to the `z` column.
0206   MutableColumnProxy<float> zColumn() noexcept {
0207     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0208     return m_zColumn->proxy(*this);
0209   }
0210   /// Returns a mutable proxy to the `r` column.
0211   /// @return A mutable proxy to the `r` column.
0212   MutableColumnProxy<float> rColumn() noexcept {
0213     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0214     return m_rColumn->proxy(*this);
0215   }
0216   /// Returns a mutable proxy to the `phi` column.
0217   /// @return A mutable proxy to the `phi` column.
0218   MutableColumnProxy<float> phiColumn() noexcept {
0219     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0220     return m_phiColumn->proxy(*this);
0221   }
0222   /// Returns a mutable proxy to the `time` column.
0223   /// @return A mutable proxy to the `time` column.
0224   MutableColumnProxy<float> timeColumn() noexcept {
0225     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0226     return m_timeColumn->proxy(*this);
0227   }
0228   /// Returns a mutable proxy to the `variance z` column.
0229   /// @return A mutable proxy to the `variance z` column.
0230   MutableColumnProxy<float> varianceZColumn() noexcept {
0231     assert(m_varianceZColumn.has_value() &&
0232            "Column 'varianceZ' does not exist");
0233     return m_varianceZColumn->proxy(*this);
0234   }
0235   /// Returns a mutable proxy to the `variance r` column.
0236   /// @return A mutable proxy to the `variance r` column.
0237   MutableColumnProxy<float> varianceRColumn() noexcept {
0238     assert(m_varianceRColumn.has_value() &&
0239            "Column 'varianceR' does not exist");
0240     return m_varianceRColumn->proxy(*this);
0241   }
0242   /// Returns a mutable proxy to the `variance t` column.
0243   /// @return A mutable proxy to the `variance t` column.
0244   MutableColumnProxy<float> varianceTColumn() noexcept {
0245     assert(m_varianceTColumn.has_value() &&
0246            "Column 'varianceT' does not exist");
0247     return m_varianceTColumn->proxy(*this);
0248   }
0249   /// Returns a mutable proxy to the `outer strip calibration details` column.
0250   /// @return A mutable proxy to the `outer strip calibration details` column.
0251   MutableColumnProxy<OuterStripSpacePointCalibrationDetails>
0252   outerStripCalibrationDetailsColumn() noexcept {
0253     assert(m_outerStripCalibrationDetailsColumn.has_value() &&
0254            "Column 'outerStripCalibrationDetails' does not exist");
0255     return m_outerStripCalibrationDetailsColumn->proxy(*this);
0256   }
0257   /// Returns a mutable proxy to the `xy` coordinates column.
0258   /// @return A mutable proxy to the `xy` coordinates column.
0259   MutableColumnProxy<std::array<float, 2>> xyColumn() noexcept {
0260     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0261     return m_xyColumn->proxy(*this);
0262   }
0263   /// Returns a mutable proxy to the `zr` coordinates column.
0264   /// @return A mutable proxy to the `zr` coordinates column.
0265   MutableColumnProxy<std::array<float, 2>> zrColumn() noexcept {
0266     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0267     return m_zrColumn->proxy(*this);
0268   }
0269   /// Returns a mutable proxy to the `xyz` coordinates column.
0270   /// @return A mutable proxy to the `xyz` coordinates column.
0271   MutableColumnProxy<std::array<float, 3>> xyzColumn() noexcept {
0272     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0273     return m_xyzColumn->proxy(*this);
0274   }
0275   /// Returns a mutable proxy to the `xyzr` coordinates column.
0276   /// @return A mutable proxy to the `xyzr` coordinates column.
0277   MutableColumnProxy<std::array<float, 4>> xyzrColumn() noexcept {
0278     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0279     return m_xyzrColumn->proxy(*this);
0280   }
0281   /// Returns a mutable proxy to the `variance zr` column.
0282   /// @return A mutable proxy to the `variance zr` column.
0283   MutableColumnProxy<std::array<float, 2>> varianceZRColumn() noexcept {
0284     assert(m_varianceZRColumn.has_value() &&
0285            "Column 'varianceZR' does not exist");
0286     return m_varianceZRColumn->proxy(*this);
0287   }
0288 
0289   /// Returns a const proxy to the `copied from index` column.
0290   /// @return A const proxy to the `copied from index` column.
0291   ConstColumnProxy<SpacePointIndex> copiedFromIndexColumn() const noexcept {
0292     assert(m_copiedFromIndexColumn.has_value() &&
0293            "Column 'copiedFromIndex' does not exist");
0294     return m_copiedFromIndexColumn->proxy(*this);
0295   }
0296   /// Returns a const proxy to the `x` column.
0297   /// @return A const proxy to the `x` column.
0298   ConstColumnProxy<float> xColumn() const noexcept {
0299     assert(m_xColumn.has_value() && "Column 'x' does not exist");
0300     return m_xColumn->proxy(*this);
0301   }
0302   /// Returns a const proxy to the `y` column.
0303   /// @return A const proxy to the `y` column.
0304   ConstColumnProxy<float> yColumn() const noexcept {
0305     assert(m_yColumn.has_value() && "Column 'y' does not exist");
0306     return m_yColumn->proxy(*this);
0307   }
0308   /// Returns a const proxy to the `z` column.
0309   /// @return A const proxy to the `z` column.
0310   ConstColumnProxy<float> zColumn() const noexcept {
0311     assert(m_zColumn.has_value() && "Column 'z' does not exist");
0312     return m_zColumn->proxy(*this);
0313   }
0314   /// Returns a const proxy to the `r` column.
0315   /// @return A const proxy to the `r` column.
0316   ConstColumnProxy<float> rColumn() const noexcept {
0317     assert(m_rColumn.has_value() && "Column 'r' does not exist");
0318     return m_rColumn->proxy(*this);
0319   }
0320   /// Returns a const proxy to the `phi` column.
0321   /// @return A const proxy to the `phi` column.
0322   ConstColumnProxy<float> phiColumn() const noexcept {
0323     assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0324     return m_phiColumn->proxy(*this);
0325   }
0326   /// Returns a const proxy to the `time` column.
0327   /// @return A const proxy to the `time` column.
0328   ConstColumnProxy<float> timeColumn() const noexcept {
0329     assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0330     return m_timeColumn->proxy(*this);
0331   }
0332   /// Returns a const proxy to the `variance z` column.
0333   /// @return A const proxy to the `variance z` column.
0334   ConstColumnProxy<float> varianceZColumn() const noexcept {
0335     assert(m_varianceZColumn.has_value() &&
0336            "Column 'varianceZ' does not exist");
0337     return m_varianceZColumn->proxy(*this);
0338   }
0339   /// Returns a const proxy to the `variance r` column.
0340   /// @return A const proxy to the `variance r` column.
0341   ConstColumnProxy<float> varianceRColumn() const noexcept {
0342     assert(m_varianceRColumn.has_value() &&
0343            "Column 'varianceR' does not exist");
0344     return m_varianceRColumn->proxy(*this);
0345   }
0346   /// Returns a const proxy to the `variance t` column.
0347   /// @return A const proxy to the `variance t` column.
0348   ConstColumnProxy<float> varianceTColumn() const noexcept {
0349     assert(m_varianceTColumn.has_value() &&
0350            "Column 'varianceT' does not exist");
0351     return m_varianceTColumn->proxy(*this);
0352   }
0353   /// Returns a const proxy to the `outer strip calibration details` column.
0354   /// @return A const proxy to the `outer strip calibration details` column.
0355   ConstColumnProxy<OuterStripSpacePointCalibrationDetails>
0356   outerStripCalibrationDetailsColumn() const noexcept {
0357     assert(m_outerStripCalibrationDetailsColumn.has_value() &&
0358            "Column 'outerStripCalibrationDetails' does not exist");
0359     return m_outerStripCalibrationDetailsColumn->proxy(*this);
0360   }
0361   /// Returns a const proxy to the `xy` coordinates column.
0362   /// @return A const proxy to the `xy` coordinates column.
0363   ConstColumnProxy<std::array<float, 2>> xyColumn() const noexcept {
0364     assert(m_xyColumn.has_value() && "Column 'xy' does not exist");
0365     return m_xyColumn->proxy(*this);
0366   }
0367   /// Returns a const proxy to the `zr` coordinates column.
0368   /// @return A const proxy to the `zr` coordinates column.
0369   ConstColumnProxy<std::array<float, 2>> zrColumn() const noexcept {
0370     assert(m_zrColumn.has_value() && "Column 'zr' does not exist");
0371     return m_zrColumn->proxy(*this);
0372   }
0373   /// Returns a const proxy to the `xyz` coordinates column.
0374   /// @return A const proxy to the `xyz` coordinates column.
0375   ConstColumnProxy<std::array<float, 3>> xyzColumn() const noexcept {
0376     assert(m_xyzColumn.has_value() && "Column 'xyz' does not exist");
0377     return m_xyzColumn->proxy(*this);
0378   }
0379   /// Returns a const proxy to the `xyzr` coordinates column.
0380   /// @return A const proxy to the `xyzr` coordinates column.
0381   ConstColumnProxy<std::array<float, 4>> xyzrColumn() const noexcept {
0382     assert(m_xyzrColumn.has_value() && "Column 'xyzr' does not exist");
0383     return m_xyzrColumn->proxy(*this);
0384   }
0385   /// Returns a const proxy to the `variance zr` column.
0386   /// @return A const proxy to the `variance zr` column.
0387   ConstColumnProxy<std::array<float, 2>> varianceZRColumn() const noexcept {
0388     assert(m_varianceZRColumn.has_value() &&
0389            "Column 'varianceZR' does not exist");
0390     return m_varianceZRColumn->proxy(*this);
0391   }
0392 
0393   /// Returns a mutable proxy to the space point at the given index.
0394   /// If the index is out of range, an exception is thrown.
0395   /// @param index The index of the space point to access.
0396   /// @return A mutable proxy to the space point at the given index.
0397   /// @throws std::out_of_range if the index is out of range.
0398   MutableProxy at(Index index);
0399   /// Returns a const proxy to the space point at the given index.
0400   /// If the index is out of range, an exception is thrown.
0401   /// @param index The index of the space point to access.
0402   /// @return A const proxy to the space point at the given index.
0403   /// @throws std::out_of_range if the index is out of range.
0404   ConstProxy at(Index index) const;
0405 
0406   /// Returns a mutable proxy to the space point at the given index.
0407   /// @param index The index of the space point to access.
0408   /// @return A mutable proxy to the space point at the given index.
0409   MutableProxy operator[](Index index) noexcept;
0410   /// Returns a const proxy to the space point at the given index.
0411   /// @param index The index of the space point to access.
0412   /// @return A const proxy to the space point at the given index.
0413   ConstProxy operator[](Index index) const noexcept;
0414 
0415   /// Type alias for template iterator over space points in container
0416   template <bool read_only>
0417   using Iterator = Acts::detail::ContainerIterator<
0418       SpacePointContainer,
0419       std::conditional_t<read_only, ConstProxy, MutableProxy>, Index,
0420       read_only>;
0421 
0422   /// Type alias for mutable iterator over space points
0423   using iterator = Iterator<false>;
0424   /// Type alias for const iterator over space points
0425   using const_iterator = Iterator<true>;
0426 
0427   /// @brief Returns mutable iterator to the beginning of the container
0428   /// @return Mutable iterator pointing to the first space point
0429   iterator begin() noexcept { return {*this, 0}; }
0430   /// @brief Returns mutable iterator to the end of the container
0431   /// @return Mutable iterator pointing past the last space point
0432   iterator end() noexcept { return {*this, size()}; }
0433 
0434   /// @brief Returns const iterator to the beginning of the container
0435   /// @return Const iterator pointing to the first space point
0436   const_iterator begin() const noexcept { return {*this, 0}; }
0437   /// @brief Returns const iterator to the end of the container
0438   /// @return Const iterator pointing past the last space point
0439   const_iterator end() const noexcept { return {*this, size()}; }
0440 
0441   /// Range facade over contiguous index spans.
0442   template <bool read_only>
0443   class Range
0444       : public Acts::detail::ContainerRange<Range<read_only>, Range<true>,
0445                                             SpacePointContainer, Index,
0446                                             read_only> {
0447    public:
0448     /// Base class type
0449     using Base =
0450         Acts::detail::ContainerRange<Range<read_only>, Range<true>,
0451                                      SpacePointContainer, Index, read_only>;
0452 
0453     using Base::Base;
0454 
0455     /// Zip this range with additional columns
0456     /// @param columns Additional columns to zip with the range
0457     /// @return Zipped range with additional columns
0458     template <typename... Ts>
0459     auto zip(const ConstColumnProxy<Ts> &...columns) const noexcept {
0460       return Base::container().zip(Base::range(), columns...);
0461     }
0462   };
0463   /// Type alias for mutable range of space points
0464   using MutableRange = Range<false>;
0465   /// Type alias for const range of space points
0466   using ConstRange = Range<true>;
0467 
0468   /// Creates a range of space points from the given index range.
0469   /// @param range The index range to create the range from.
0470   /// @return A mutable range of space points.
0471   MutableRange range(const IndexRange &range) noexcept {
0472     return {*this, range};
0473   }
0474   /// Creates a range of space points from the given index range.
0475   /// @param range The index range to create the range from.
0476   /// @return A const range of space points.
0477   ConstRange range(const IndexRange &range) const noexcept {
0478     return {*this, range};
0479   }
0480 
0481   /// Subset facade over arbitrary index sets.
0482   template <bool read_only>
0483   class Subset : public Acts::detail::ContainerSubset<
0484                      Subset<read_only>, Subset<true>, SpacePointContainer,
0485                      std::conditional_t<read_only, ConstProxy, MutableProxy>,
0486                      std::span<const Index>, read_only> {
0487    public:
0488     /// Base class type
0489     using Base = Acts::detail::ContainerSubset<
0490         Subset<read_only>, Subset<true>, SpacePointContainer,
0491         std::conditional_t<read_only, ConstProxy, MutableProxy>,
0492         std::span<const Index>, read_only>;
0493 
0494     using Base::Base;
0495 
0496     /// Zip this subset with additional columns
0497     /// @param columns Additional columns to zip with the subset
0498     /// @return Zipped subset with additional columns
0499     template <typename... Ts>
0500     auto zip(const ConstColumnProxy<Ts> &...columns) const noexcept {
0501       return Base::container().zip(Base::subset(), columns...);
0502     }
0503   };
0504   /// Type alias for mutable subset of space points
0505   using MutableSubset = Subset<false>;
0506   /// Type alias for const subset of space points
0507   using ConstSubset = Subset<true>;
0508 
0509   /// Creates a mutable subset of space points from the given index subset.
0510   /// @param subset The index subset to create the subset from.
0511   /// @return A mutable subset of space points.
0512   MutableSubset subset(const IndexSubset &subset) noexcept {
0513     return {*this, subset};
0514   }
0515   /// Creates a const subset of space points from the given index subset.
0516   /// @param subset The index subset to create the subset from.
0517   /// @return A const subset of space points.
0518   ConstSubset subset(const IndexSubset &subset) const noexcept {
0519     return {*this, subset};
0520   }
0521 
0522   /// Creates a zipped mutable range of space point data from the given columns.
0523   /// @param columns The columns to zip.
0524   /// @return A zipped mutable range of space point data.
0525   template <typename... Ts>
0526   auto zip(const MutableColumnProxy<Ts> &...columns) noexcept {
0527     return Acts::zip(std::ranges::iota_view<Index, Index>(0, size()),
0528                      columns.data()...);
0529   }
0530   /// Creates a zipped const range of space point data from the given columns.
0531   /// @param columns The columns to zip.
0532   /// @return A zipped const range of space point data.
0533   template <typename... Ts>
0534   auto zip(const ConstColumnProxy<Ts> &...columns) const noexcept {
0535     return Acts::zip(std::ranges::iota_view<Index, Index>(0, size()),
0536                      columns.data()...);
0537   }
0538 
0539   /// Creates a zipped mutable range of space point data from the given columns.
0540   /// @param range The index range to zip.
0541   /// @param columns The columns to zip.
0542   /// @return A zipped mutable range of space point data.
0543   template <typename... Ts>
0544   auto zip(const IndexRange &range,
0545            const MutableColumnProxy<Ts> &...columns) noexcept {
0546     return Acts::zip(
0547         std::ranges::iota_view<Index, Index>(range.first, range.second),
0548         columns.data().subspan(range.first, range.second - range.first)...);
0549   }
0550   /// Creates a zipped const range of space point data from the given columns.
0551   /// @param range The index range to create the zipped range from.
0552   /// @param columns The columns to zip.
0553   /// @return A zipped const range of space point data.
0554   template <typename... Ts>
0555   auto zip(const IndexRange &range,
0556            const ConstColumnProxy<Ts> &...columns) const noexcept {
0557     return Acts::zip(
0558         std::ranges::iota_view<Index, Index>(range.first, range.second),
0559         columns.data().subspan(range.first, range.second - range.first)...);
0560   }
0561 
0562   /// @brief Create a zipped range over subset indices and mutable column data
0563   /// @tparam Ts Column data types to zip with indices
0564   /// @param subset Index subset to iterate over
0565   /// @param columns Mutable column proxies to zip with indices
0566   /// @return Zipped range for iteration over indices and column data
0567   template <typename... Ts>
0568   auto zip(const IndexSubset &subset,
0569            const MutableColumnProxy<Ts> &...columns) noexcept {
0570     return Acts::zip(subset, columns.subset(subset)...);
0571   }
0572 
0573   /// @brief Create a zipped range over subset indices and const column data
0574   /// @tparam Ts Column data types to zip with indices
0575   /// @param subset Index subset to iterate over
0576   /// @param columns Const column proxies to zip with indices
0577   /// @return Const zipped range for iteration over indices and column data
0578   template <typename... Ts>
0579   auto zip(const IndexSubset &subset,
0580            const ConstColumnProxy<Ts> &...columns) const noexcept {
0581     return Acts::zip(subset, columns.subset(subset)...);
0582   }
0583 
0584  private:
0585   template <bool>
0586   friend class SpacePointProxy;
0587 
0588   using ColumnHolderBase = detail::sp::ColumnHolderBase;
0589   template <typename T>
0590   using ColumnHolder = detail::sp::ColumnHolder<T>;
0591 
0592   std::uint32_t m_size{0};
0593 
0594   std::unordered_map<std::string, ColumnHolderBase *> m_allColumns;
0595   SpacePointColumns m_knownColumns{SpacePointColumns::None};
0596   std::unordered_map<std::string, std::unique_ptr<ColumnHolderBase>>
0597       m_dynamicColumns;
0598 
0599   std::vector<SourceLink> m_sourceLinks;
0600 
0601   std::optional<ColumnHolder<std::uint32_t>> m_sourceLinkOffsetColumn;
0602   std::optional<ColumnHolder<std::uint8_t>> m_sourceLinkCountColumn;
0603 
0604   // copy information
0605   std::optional<ColumnHolder<SpacePointIndex>> m_copiedFromIndexColumn;
0606 
0607   std::optional<ColumnHolder<float>> m_xColumn;
0608   std::optional<ColumnHolder<float>> m_yColumn;
0609   std::optional<ColumnHolder<float>> m_zColumn;
0610 
0611   // cylindrical coordinates
0612   std::optional<ColumnHolder<float>> m_rColumn;
0613   std::optional<ColumnHolder<float>> m_phiColumn;
0614   // time information
0615   std::optional<ColumnHolder<float>> m_timeColumn;
0616   // covariance information
0617   std::optional<ColumnHolder<float>> m_varianceZColumn;
0618   std::optional<ColumnHolder<float>> m_varianceRColumn;
0619   std::optional<ColumnHolder<float>> m_varianceTColumn;
0620 
0621   // strip information
0622   std::optional<ColumnHolder<OuterStripSpacePointCalibrationDetails>>
0623       m_outerStripCalibrationDetailsColumn;
0624 
0625   // packed columns
0626   std::optional<ColumnHolder<std::array<float, 2>>> m_xyColumn;
0627   std::optional<ColumnHolder<std::array<float, 2>>> m_zrColumn;
0628   std::optional<ColumnHolder<std::array<float, 3>>> m_xyzColumn;
0629   std::optional<ColumnHolder<std::array<float, 4>>> m_xyzrColumn;
0630   std::optional<ColumnHolder<std::array<float, 2>>> m_varianceZRColumn;
0631 
0632   static auto knownColumnMasks() noexcept {
0633     using enum SpacePointColumns;
0634     return std::tuple(SourceLinks, SourceLinks, CopiedFromIndex, X, Y, Z, R,
0635                       Phi, Time, VarianceZ, VarianceR, VarianceT,
0636                       StripCalibrationDetails, PackedXY, PackedZR, PackedXYZ,
0637                       PackedXYZR, PackedVarianceZR);
0638   }
0639 
0640   static auto knownColumnNames() noexcept {
0641     return std::tuple("sourceLinkOffset", "sourceLinkCount", "copiedFromIndex",
0642                       "x", "y", "z", "r", "phi", "time", "varianceZ",
0643                       "varianceR", "varianceT", "stripCalibrationDetails", "xy",
0644                       "zr", "xyz", "xyzr", "varianceZR");
0645   }
0646 
0647   static auto knownColumnDefaults() noexcept {
0648     return std::tuple(
0649         std::uint32_t{0}, std::uint8_t{0}, std::uint32_t{0}, float{0}, float{0},
0650         float{0}, float{0}, float{0}, float{NoTime}, float{0}, float{0},
0651         float{NoTime}, OuterStripSpacePointCalibrationDetails{},
0652         std::array<float, 2>{0, 0}, std::array<float, 2>{0, 0},
0653         std::array<float, 3>{0, 0, 0}, std::array<float, 4>{0, 0, 0, 0},
0654         std::array<float, 2>{0, 0});
0655   }
0656 
0657   template <typename Self>
0658   static auto knownColumns(Self &&self) noexcept {
0659     return std::tie(self.m_sourceLinkOffsetColumn, self.m_sourceLinkCountColumn,
0660                     self.m_copiedFromIndexColumn, self.m_xColumn,
0661                     self.m_yColumn, self.m_zColumn, self.m_rColumn,
0662                     self.m_phiColumn, self.m_timeColumn, self.m_varianceZColumn,
0663                     self.m_varianceRColumn, self.m_varianceTColumn,
0664                     self.m_outerStripCalibrationDetailsColumn, self.m_xyColumn,
0665                     self.m_zrColumn, self.m_xyzColumn, self.m_xyzrColumn,
0666                     self.m_varianceZRColumn);
0667   }
0668   auto knownColumns() & noexcept { return knownColumns(*this); }
0669   auto knownColumns() const & noexcept { return knownColumns(*this); }
0670   auto knownColumns() && noexcept { return knownColumns(*this); }
0671 
0672   void copyColumns(const SpacePointContainer &other);
0673   void moveColumns(SpacePointContainer &other) noexcept;
0674 
0675   static bool reservedColumn(const std::string &name) noexcept;
0676 
0677   template <typename Holder>
0678   MutableColumnProxy<typename Holder::Value> createColumnImpl(
0679       const std::string &name) {
0680     if (reservedColumn(name)) {
0681       throw std::runtime_error("Column name is reserved: " + name);
0682     }
0683     if (hasColumn(name)) {
0684       throw std::runtime_error("Column already exists: " + name);
0685     }
0686     auto holder = std::make_unique<Holder>();
0687     holder->resize(size());
0688     auto proxy = holder->proxy(*this);
0689     m_allColumns.try_emplace(name, holder.get());
0690     m_dynamicColumns.try_emplace(name, std::move(holder));
0691     return proxy;
0692   }
0693 
0694   template <typename Holder, typename Self>
0695   static auto columnImpl(Self &&self, const std::string &name) {
0696     const auto it = self.m_allColumns.find(name);
0697     if (it == self.m_allColumns.end()) {
0698       throw std::runtime_error("Column not found: " + name);
0699     }
0700     auto &holder = dynamic_cast<Holder &>(*it->second);
0701     return holder.proxy(self);
0702   }
0703 
0704   template <typename Holder>
0705   MutableColumnProxy<typename Holder::Value> columnImpl(
0706       const std::string &name) {
0707     return columnImpl<Holder>(*this, name);
0708   }
0709 
0710   template <typename Holder>
0711   ConstColumnProxy<typename Holder::Value> columnImpl(
0712       const std::string &name) const {
0713     return columnImpl<Holder>(*this, name);
0714   }
0715 };
0716 
0717 }  // namespace Acts
0718 
0719 #include "Acts/EventData/SpacePointContainer.ipp"