File indexing completed on 2026-08-05 08:21:13
0001
0002
0003
0004
0005
0006
0007
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
0036 static constexpr float NoTime = std::numeric_limits<float>::quiet_NaN();
0037
0038 template <bool>
0039 class SpacePointProxy;
0040
0041 using MutableSpacePointProxy = SpacePointProxy<false>;
0042
0043 using ConstSpacePointProxy = SpacePointProxy<true>;
0044
0045
0046
0047
0048
0049 class SpacePointContainer {
0050 public:
0051
0052 using Index = SpacePointIndex;
0053
0054 using IndexRange = SpacePointIndexRange;
0055
0056 using IndexSubset = SpacePointIndexSubset;
0057
0058 using MutableProxy = MutableSpacePointProxy;
0059
0060 using ConstProxy = ConstSpacePointProxy;
0061
0062 template <typename T>
0063 using MutableColumnProxy = MutableSpacePointColumnProxy<T>;
0064
0065 template <typename T>
0066 using ConstColumnProxy = ConstSpacePointColumnProxy<T>;
0067
0068
0069
0070 explicit SpacePointContainer(
0071 SpacePointColumns columns = SpacePointColumns::None) noexcept;
0072
0073
0074
0075 SpacePointContainer(const SpacePointContainer &other) noexcept;
0076
0077
0078
0079 SpacePointContainer(SpacePointContainer &&other) noexcept;
0080
0081
0082 ~SpacePointContainer() noexcept = default;
0083
0084
0085
0086
0087 SpacePointContainer &operator=(const SpacePointContainer &other) noexcept;
0088
0089
0090
0091
0092 SpacePointContainer &operator=(SpacePointContainer &&other) noexcept;
0093
0094
0095
0096 std::uint32_t size() const noexcept { return m_size; }
0097
0098
0099 [[nodiscard]] bool empty() const noexcept { return size() == 0; }
0100
0101
0102
0103
0104
0105 void reserve(std::uint32_t size, float averageSourceLinks = 1) noexcept;
0106
0107
0108 void clear() noexcept;
0109
0110
0111
0112 MutableProxy createSpacePoint() noexcept;
0113
0114
0115
0116
0117
0118
0119 void copyFrom(Index index, const SpacePointContainer &otherContainer,
0120 Index otherIndex, SpacePointColumns columnsToCopy);
0121
0122
0123
0124
0125 void createColumns(SpacePointColumns columns) noexcept;
0126
0127
0128
0129
0130 void dropColumns(SpacePointColumns columns) noexcept;
0131
0132
0133
0134
0135
0136 bool hasColumns(SpacePointColumns columns) const noexcept {
0137 return (m_knownColumns & columns) == columns;
0138 }
0139
0140
0141
0142
0143
0144
0145
0146 template <typename T>
0147 MutableColumnProxy<T> createColumn(const std::string &name) {
0148 return createColumnImpl<ColumnHolder<T>>(name);
0149 }
0150
0151
0152
0153
0154
0155
0156 void dropColumn(const std::string &name);
0157
0158
0159
0160
0161 bool hasColumn(const std::string &name) const noexcept {
0162 return m_allColumns.contains(name);
0163 }
0164
0165
0166
0167
0168
0169
0170 template <typename T>
0171 MutableColumnProxy<T> column(const std::string &name) {
0172 return columnImpl<ColumnHolder<T>>(name);
0173 }
0174
0175
0176
0177
0178
0179
0180 template <typename T>
0181 ConstColumnProxy<T> column(const std::string &name) const {
0182 return columnImpl<ColumnHolder<T>>(name);
0183 }
0184
0185
0186
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
0193
0194 MutableColumnProxy<float> xColumn() noexcept {
0195 assert(m_xColumn.has_value() && "Column 'x' does not exist");
0196 return m_xColumn->proxy(*this);
0197 }
0198
0199
0200 MutableColumnProxy<float> yColumn() noexcept {
0201 assert(m_yColumn.has_value() && "Column 'y' does not exist");
0202 return m_yColumn->proxy(*this);
0203 }
0204
0205
0206 MutableColumnProxy<float> zColumn() noexcept {
0207 assert(m_zColumn.has_value() && "Column 'z' does not exist");
0208 return m_zColumn->proxy(*this);
0209 }
0210
0211
0212 MutableColumnProxy<float> rColumn() noexcept {
0213 assert(m_rColumn.has_value() && "Column 'r' does not exist");
0214 return m_rColumn->proxy(*this);
0215 }
0216
0217
0218 MutableColumnProxy<float> phiColumn() noexcept {
0219 assert(m_phiColumn.has_value() && "Column 'phi' does not exist");
0220 return m_phiColumn->proxy(*this);
0221 }
0222
0223
0224 MutableColumnProxy<float> timeColumn() noexcept {
0225 assert(m_timeColumn.has_value() && "Column 'time' does not exist");
0226 return m_timeColumn->proxy(*this);
0227 }
0228
0229
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
0236
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
0243
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
0250
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
0258
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
0264
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
0270
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
0276
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
0282
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
0290
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
0297
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
0303
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
0309
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
0315
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
0321
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
0327
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
0333
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
0340
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
0347
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
0354
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
0362
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
0368
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
0374
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
0380
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
0386
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
0394
0395
0396
0397
0398 MutableProxy at(Index index);
0399
0400
0401
0402
0403
0404 ConstProxy at(Index index) const;
0405
0406
0407
0408
0409 MutableProxy operator[](Index index) noexcept;
0410
0411
0412
0413 ConstProxy operator[](Index index) const noexcept;
0414
0415
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
0423 using iterator = Iterator<false>;
0424
0425 using const_iterator = Iterator<true>;
0426
0427
0428
0429 iterator begin() noexcept { return {*this, 0}; }
0430
0431
0432 iterator end() noexcept { return {*this, size()}; }
0433
0434
0435
0436 const_iterator begin() const noexcept { return {*this, 0}; }
0437
0438
0439 const_iterator end() const noexcept { return {*this, size()}; }
0440
0441
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
0449 using Base =
0450 Acts::detail::ContainerRange<Range<read_only>, Range<true>,
0451 SpacePointContainer, Index, read_only>;
0452
0453 using Base::Base;
0454
0455
0456
0457
0458 template <typename... Ts>
0459 auto zip(const ConstColumnProxy<Ts> &...columns) const noexcept {
0460 return Base::container().zip(Base::range(), columns...);
0461 }
0462 };
0463
0464 using MutableRange = Range<false>;
0465
0466 using ConstRange = Range<true>;
0467
0468
0469
0470
0471 MutableRange range(const IndexRange &range) noexcept {
0472 return {*this, range};
0473 }
0474
0475
0476
0477 ConstRange range(const IndexRange &range) const noexcept {
0478 return {*this, range};
0479 }
0480
0481
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
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
0497
0498
0499 template <typename... Ts>
0500 auto zip(const ConstColumnProxy<Ts> &...columns) const noexcept {
0501 return Base::container().zip(Base::subset(), columns...);
0502 }
0503 };
0504
0505 using MutableSubset = Subset<false>;
0506
0507 using ConstSubset = Subset<true>;
0508
0509
0510
0511
0512 MutableSubset subset(const IndexSubset &subset) noexcept {
0513 return {*this, subset};
0514 }
0515
0516
0517
0518 ConstSubset subset(const IndexSubset &subset) const noexcept {
0519 return {*this, subset};
0520 }
0521
0522
0523
0524
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
0531
0532
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
0540
0541
0542
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
0551
0552
0553
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
0563
0564
0565
0566
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
0574
0575
0576
0577
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
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
0612 std::optional<ColumnHolder<float>> m_rColumn;
0613 std::optional<ColumnHolder<float>> m_phiColumn;
0614
0615 std::optional<ColumnHolder<float>> m_timeColumn;
0616
0617 std::optional<ColumnHolder<float>> m_varianceZColumn;
0618 std::optional<ColumnHolder<float>> m_varianceRColumn;
0619 std::optional<ColumnHolder<float>> m_varianceTColumn;
0620
0621
0622 std::optional<ColumnHolder<OuterStripSpacePointCalibrationDetails>>
0623 m_outerStripCalibrationDetailsColumn;
0624
0625
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 }
0718
0719 #include "Acts/EventData/SpacePointContainer.ipp"