File indexing completed on 2026-07-20 07:51:14
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/MeasurementHelpers.hpp"
0014 #include "Acts/EventData/SourceLink.hpp"
0015 #include "Acts/EventData/TrackStatePropMask.hpp"
0016 #include "Acts/EventData/TrackStateProxy.hpp"
0017 #include "Acts/EventData/Types.hpp"
0018 #include "Acts/Utilities/HashedString.hpp"
0019 #include "Acts/Utilities/ThrowAssert.hpp"
0020
0021 #include <cstddef>
0022 #include <iterator>
0023 #include <memory>
0024 #include <optional>
0025 #include <string_view>
0026 #include <type_traits>
0027
0028 #include <Eigen/Core>
0029
0030 namespace Acts {
0031
0032
0033 template <typename derived_t>
0034 class MultiTrajectory;
0035 class Surface;
0036
0037 namespace detail_anytstate {
0038 template <typename trajectory_t, bool read_only>
0039 class TrackStateHandler;
0040 }
0041
0042 namespace detail_lt {
0043
0044
0045 template <bool reverse, typename trajectory_t, std::size_t M, bool ReadOnly>
0046 class TrackStateRange {
0047 using ProxyType = TrackStateProxy<trajectory_t, M, ReadOnly>;
0048 using IndexType = typename ProxyType::IndexType;
0049 static constexpr IndexType kInvalid = ProxyType::kInvalid;
0050
0051 public:
0052
0053
0054 struct Iterator {
0055 std::optional<ProxyType> proxy;
0056
0057 using iterator_category = std::forward_iterator_tag;
0058 using value_type = ProxyType;
0059 using difference_type = std::ptrdiff_t;
0060 using pointer = void;
0061 using reference = void;
0062
0063 Iterator& operator++() {
0064 if (!proxy) {
0065 return *this;
0066 }
0067 if constexpr (reverse) {
0068 if (proxy->hasPrevious()) {
0069 proxy = proxy->trajectory().getTrackState(proxy->previous());
0070 return *this;
0071 } else {
0072 proxy = std::nullopt;
0073 return *this;
0074 }
0075 } else {
0076 IndexType next =
0077 proxy->template component<IndexType, hashString("next")>();
0078 if (next != kInvalid) {
0079 proxy = proxy->trajectory().getTrackState(next);
0080 return *this;
0081 } else {
0082 proxy = std::nullopt;
0083 return *this;
0084 }
0085 }
0086 }
0087
0088 Iterator operator++(int) {
0089 Iterator tmp(*this);
0090 operator++();
0091 return tmp;
0092 }
0093
0094 bool operator==(const Iterator& other) const {
0095 if (!proxy && !other.proxy) {
0096 return true;
0097 }
0098 if (proxy && other.proxy) {
0099 return proxy->index() == other.proxy->index();
0100 }
0101 return false;
0102 }
0103
0104 ProxyType operator*() const { return *proxy; }
0105 ProxyType operator*() { return *proxy; }
0106 };
0107
0108 explicit TrackStateRange(ProxyType _begin) : m_begin{_begin} {}
0109 TrackStateRange() : m_begin{std::nullopt} {}
0110
0111 Iterator begin() { return Iterator{m_begin}; }
0112 Iterator end() { return Iterator{std::nullopt}; }
0113
0114 Iterator cbegin() const { return Iterator{m_begin}; }
0115 Iterator cend() const { return Iterator{std::nullopt}; }
0116
0117 private:
0118 Iterator m_begin;
0119 };
0120
0121
0122 template <typename T, typename TS>
0123 concept VisitorConcept = requires(T& t, TS& ts) {
0124 { t(ts) } -> Concepts::same_as_any_of<void, bool>;
0125 };
0126
0127 }
0128
0129 template <typename T>
0130 struct IsReadOnlyMultiTrajectory;
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 template <typename derived_t>
0141 class MultiTrajectory {
0142 public:
0143
0144 using Derived = derived_t;
0145
0146
0147 static constexpr bool ReadOnly = IsReadOnlyMultiTrajectory<Derived>::value;
0148
0149
0150
0151 static constexpr unsigned int MeasurementSizeMax = kMeasurementSizeMax;
0152
0153 friend class TrackStateProxy<Derived, MeasurementSizeMax, true>;
0154 friend class TrackStateProxy<Derived, MeasurementSizeMax, false>;
0155 template <bool R>
0156 friend class AnyTrackStateProxy;
0157 template <typename T, bool R>
0158 friend class detail_anytstate::TrackStateHandler;
0159 template <typename T>
0160 friend class MultiTrajectory;
0161
0162
0163
0164 using ConstTrackStateProxy =
0165 Acts::TrackStateProxy<Derived, MeasurementSizeMax, true>;
0166
0167
0168
0169 using TrackStateProxy =
0170 Acts::TrackStateProxy<Derived, MeasurementSizeMax, false>;
0171
0172
0173 using IndexType = TrackIndexType;
0174
0175
0176 static constexpr IndexType kInvalid = kTrackIndexInvalid;
0177
0178 protected:
0179 MultiTrajectory() = default;
0180
0181 private:
0182
0183 constexpr Derived& self() { return static_cast<Derived&>(*this); }
0184
0185 constexpr const Derived& self() const {
0186 return static_cast<const Derived&>(*this);
0187 }
0188
0189
0190
0191 bool checkOptional(HashedString key, IndexType istate) const {
0192 using namespace Acts::HashedStringLiteral;
0193 switch (key) {
0194 case "predicted"_hash:
0195 case "filtered"_hash:
0196 case "smoothed"_hash:
0197 case "calibrated"_hash:
0198 case "jacobian"_hash:
0199 case "projector"_hash:
0200 return self().has_impl(key, istate);
0201 default:
0202 return true;
0203 }
0204 }
0205
0206 public:
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 ConstTrackStateProxy getTrackState(IndexType istate) const {
0220 return {*this, istate};
0221 }
0222
0223
0224
0225
0226
0227 TrackStateProxy getTrackState(IndexType istate)
0228 requires(!ReadOnly)
0229 {
0230 return {*this, istate};
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240 IndexType addTrackState(TrackStatePropMask mask = TrackStatePropMask::All,
0241 IndexType iprevious = kInvalid)
0242 requires(!ReadOnly)
0243 {
0244 return self().addTrackState_impl(mask, iprevious);
0245 }
0246
0247
0248
0249
0250
0251
0252
0253 TrackStateProxy makeTrackState(
0254 TrackStatePropMask mask = TrackStatePropMask::All,
0255 IndexType iprevious = kInvalid)
0256 requires(!ReadOnly)
0257 {
0258 return getTrackState(addTrackState(mask, iprevious));
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 template <typename F>
0272 void visitBackwards(IndexType iendpoint, F&& callable) const
0273 requires detail_lt::VisitorConcept<F, ConstTrackStateProxy>;
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 template <typename F>
0284 void applyBackwards(IndexType iendpoint, F&& callable)
0285 requires(!ReadOnly) && detail_lt::VisitorConcept<F, TrackStateProxy>
0286 {
0287 if (iendpoint == kInvalid) {
0288 throw std::runtime_error(
0289 "Cannot apply backwards with kInvalid as endpoint");
0290 }
0291
0292 while (true) {
0293 auto ts = getTrackState(iendpoint);
0294 if constexpr (std::is_same_v<std::invoke_result_t<F, TrackStateProxy>,
0295 bool>) {
0296 bool proceed = callable(ts);
0297
0298
0299 if (!proceed || !ts.hasPrevious()) {
0300 break;
0301 }
0302 } else {
0303 callable(ts);
0304
0305 if (!ts.hasPrevious()) {
0306 break;
0307 }
0308 }
0309 iendpoint = ts.previous();
0310 }
0311 }
0312
0313
0314
0315
0316
0317 auto reverseTrackStateRange(IndexType iendpoint) const {
0318 using range_t =
0319 detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, true>;
0320 if (iendpoint == kInvalid) {
0321 return range_t{};
0322 }
0323
0324 return range_t{getTrackState(iendpoint)};
0325 }
0326
0327
0328
0329
0330
0331
0332
0333 auto reverseTrackStateRange(IndexType iendpoint)
0334 requires(!ReadOnly)
0335 {
0336 using range_t =
0337 detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, false>;
0338 if (iendpoint == kInvalid) {
0339 return range_t{};
0340 }
0341
0342 return range_t{getTrackState(iendpoint)};
0343 }
0344
0345
0346
0347
0348
0349
0350
0351 auto forwardTrackStateRange(IndexType istartpoint) const {
0352 using range_t =
0353 detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, true>;
0354 if (istartpoint == kInvalid) {
0355 return range_t{};
0356 }
0357
0358 return range_t{getTrackState(istartpoint)};
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 auto forwardTrackStateRange(IndexType istartpoint)
0368 requires(!ReadOnly)
0369 {
0370 using range_t =
0371 detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, false>;
0372 if (istartpoint == kInvalid) {
0373 return range_t{};
0374 }
0375
0376 return range_t{getTrackState(istartpoint)};
0377 }
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394 template <typename T>
0395 void addColumn(std::string_view key)
0396 requires(!ReadOnly)
0397 {
0398 self().template addColumn_impl<T>(key);
0399 }
0400
0401
0402
0403
0404 bool hasColumn(HashedString key) const { return self().hasColumn_impl(key); }
0405
0406
0407
0408
0409
0410 void clear()
0411 requires(!ReadOnly)
0412 {
0413 self().clear_impl();
0414 }
0415
0416
0417
0418 IndexType size() const { return self().size_impl(); }
0419
0420 protected:
0421
0422
0423
0424
0425
0426
0427 bool has(HashedString key, IndexType istate) const {
0428 return self().has_impl(key, istate);
0429 }
0430
0431
0432
0433
0434
0435 template <HashedString key>
0436 bool has(IndexType istate) const {
0437 return self().has_impl(key, istate);
0438 }
0439
0440
0441
0442
0443 typename TrackStateProxy::Parameters parameters(IndexType parIdx)
0444 requires(!ReadOnly)
0445 {
0446 return self().parameters_impl(parIdx);
0447 }
0448
0449
0450
0451
0452 typename ConstTrackStateProxy::ConstParameters parameters(
0453 IndexType parIdx) const {
0454 return self().parameters_impl(parIdx);
0455 }
0456
0457
0458
0459
0460 typename TrackStateProxy::Covariance covariance(IndexType covIdx)
0461 requires(!ReadOnly)
0462 {
0463 return self().covariance_impl(covIdx);
0464 }
0465
0466
0467
0468
0469 typename ConstTrackStateProxy::ConstCovariance covariance(
0470 IndexType covIdx) const {
0471 return self().covariance_impl(covIdx);
0472 }
0473
0474
0475
0476
0477 typename TrackStateProxy::Jacobian jacobian(IndexType istate)
0478 requires(!ReadOnly)
0479 {
0480 return self().jacobian_impl(istate);
0481 }
0482
0483
0484
0485
0486 typename ConstTrackStateProxy::ConstJacobian jacobian(
0487 IndexType istate) const {
0488 return self().jacobian_impl(istate);
0489 }
0490
0491
0492
0493
0494
0495
0496 template <std::size_t measdim>
0497 typename TrackStateProxy::template Calibrated<measdim> calibrated(
0498 IndexType istate)
0499 requires(!ReadOnly)
0500 {
0501 return self().template calibrated_impl<measdim>(istate);
0502 }
0503
0504
0505
0506
0507
0508
0509 template <std::size_t measdim>
0510 typename ConstTrackStateProxy::template ConstCalibrated<measdim> calibrated(
0511 IndexType istate) const {
0512 return self().template calibrated_impl<measdim>(istate);
0513 }
0514
0515
0516
0517
0518
0519
0520 template <std::size_t measdim>
0521 typename TrackStateProxy::template CalibratedCovariance<measdim>
0522 calibratedCovariance(IndexType istate)
0523 requires(!ReadOnly)
0524 {
0525 return self().template calibratedCovariance_impl<measdim>(istate);
0526 }
0527
0528
0529
0530
0531
0532 typename TrackStateProxy::EffectiveCalibrated effectiveCalibrated(
0533 IndexType istate)
0534 requires(!ReadOnly)
0535 {
0536
0537
0538
0539 return typename TrackStateProxy::EffectiveCalibrated{
0540 calibrated<eBoundSize>(istate).data(), calibratedSize(istate)};
0541 }
0542
0543
0544
0545
0546
0547 typename ConstTrackStateProxy::EffectiveCalibrated effectiveCalibrated(
0548 IndexType istate) const {
0549
0550
0551
0552 return typename ConstTrackStateProxy::EffectiveCalibrated{
0553 calibrated<eBoundSize>(istate).data(), calibratedSize(istate)};
0554 }
0555
0556
0557
0558
0559
0560 typename TrackStateProxy::EffectiveCalibratedCovariance
0561 effectiveCalibratedCovariance(IndexType istate)
0562 requires(!ReadOnly)
0563 {
0564
0565
0566
0567 return typename TrackStateProxy::EffectiveCalibratedCovariance{
0568 calibratedCovariance<eBoundSize>(istate).data(), calibratedSize(istate),
0569 calibratedSize(istate)};
0570 }
0571
0572
0573
0574
0575
0576 typename ConstTrackStateProxy::EffectiveCalibratedCovariance
0577 effectiveCalibratedCovariance(IndexType istate) const {
0578
0579
0580
0581 return typename ConstTrackStateProxy::EffectiveCalibratedCovariance{
0582 calibratedCovariance<eBoundSize>(istate).data(), calibratedSize(istate),
0583 calibratedSize(istate)};
0584 }
0585
0586
0587
0588
0589
0590 template <std::size_t measdim>
0591 typename ConstTrackStateProxy::template ConstCalibratedCovariance<measdim>
0592 calibratedCovariance(IndexType istate) const {
0593 return self().template calibratedCovariance_impl<measdim>(istate);
0594 }
0595
0596
0597
0598
0599 IndexType calibratedSize(IndexType istate) const {
0600 return self().calibratedSize_impl(istate);
0601 }
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613 void shareFrom(IndexType iself, IndexType iother,
0614 TrackStatePropMask shareSource, TrackStatePropMask shareTarget)
0615 requires(!ReadOnly)
0616 {
0617 self().shareFrom_impl(iself, iother, shareSource, shareTarget);
0618 }
0619
0620
0621
0622
0623 void unset(TrackStatePropMask target, IndexType istate)
0624 requires(!ReadOnly)
0625 {
0626 self().unset_impl(target, istate);
0627 }
0628
0629
0630
0631
0632
0633 void addTrackStateComponents(IndexType istate, TrackStatePropMask mask)
0634 requires(!ReadOnly)
0635 {
0636 self().addTrackStateComponents_impl(istate, mask);
0637 }
0638
0639
0640
0641
0642
0643
0644 template <typename T, HashedString key>
0645 T& component(IndexType istate)
0646 requires(!ReadOnly)
0647 {
0648 assert(checkOptional(key, istate));
0649 return *std::any_cast<T*>(self().component_impl(key, istate));
0650 }
0651
0652
0653
0654
0655
0656
0657 template <typename T>
0658 T& component(HashedString key, IndexType istate)
0659 requires(!ReadOnly)
0660 {
0661 assert(checkOptional(key, istate));
0662 return *std::any_cast<T*>(self().component_impl(key, istate));
0663 }
0664
0665
0666
0667
0668
0669
0670 template <typename T, HashedString key>
0671 const T& component(IndexType istate) const {
0672 assert(checkOptional(key, istate));
0673 return *std::any_cast<const T*>(self().component_impl(key, istate));
0674 }
0675
0676
0677
0678
0679
0680
0681 template <typename T>
0682 const T& component(HashedString key, IndexType istate) const {
0683 assert(checkOptional(key, istate));
0684 return *std::any_cast<const T*>(self().component_impl(key, istate));
0685 }
0686
0687
0688
0689
0690
0691
0692 void allocateCalibrated(IndexType istate, std::size_t measdim) {
0693 throw_assert(measdim > 0 && measdim <= eBoundSize,
0694 "Invalid measurement dimension detected");
0695
0696 visit_measurement(measdim, [this, istate]<std::size_t DIM>(
0697 std::integral_constant<std::size_t, DIM>) {
0698 self().allocateCalibrated_impl(
0699 istate, Vector<DIM>{Vector<DIM>::Zero()},
0700 SquareMatrix<DIM>{SquareMatrix<DIM>::Zero()});
0701 });
0702 }
0703
0704
0705
0706
0707
0708
0709
0710
0711 template <std::size_t measdim, typename val_t, typename cov_t>
0712 void allocateCalibrated(IndexType istate, const Eigen::DenseBase<val_t>& val,
0713 const Eigen::DenseBase<cov_t>& cov) {
0714 self().allocateCalibrated_impl(istate, val, cov);
0715 }
0716
0717
0718
0719
0720 void setUncalibratedSourceLink(IndexType istate, SourceLink&& sourceLink)
0721 requires(!ReadOnly)
0722 {
0723 self().setUncalibratedSourceLink_impl(istate, std::move(sourceLink));
0724 }
0725
0726
0727
0728
0729 SourceLink getUncalibratedSourceLink(IndexType istate) const {
0730 return self().getUncalibratedSourceLink_impl(istate);
0731 }
0732
0733
0734
0735
0736 const Surface* referenceSurface(IndexType istate) const {
0737 return self().referenceSurface_impl(istate);
0738 }
0739
0740
0741
0742
0743 void setReferenceSurface(IndexType istate,
0744 std::shared_ptr<const Surface> surface)
0745 requires(!ReadOnly)
0746 {
0747 self().setReferenceSurface_impl(istate, std::move(surface));
0748 }
0749
0750 private:
0751 template <typename T>
0752 void copyDynamicFrom(IndexType dstIdx, const T& src, IndexType srcIdx)
0753 requires(!ReadOnly)
0754 {
0755 const auto& dynamicKeys = src.self().dynamicKeys_impl();
0756 for (const auto key : dynamicKeys) {
0757 std::any srcPtr = src.self().component_impl(key, srcIdx);
0758 self().copyDynamicFrom_impl(dstIdx, key, srcPtr);
0759 }
0760 }
0761 };
0762
0763 }
0764
0765 #include "Acts/EventData/MultiTrajectory.ipp"