File indexing completed on 2026-05-21 07:46:23
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
0130
0131
0132
0133 namespace MultiTrajectoryTraits {
0134
0135
0136
0137 [[deprecated("Use Acts::kMeasurementSizeMax instead.")]]
0138 constexpr unsigned int MeasurementSizeMax = kMeasurementSizeMax;
0139
0140
0141
0142 using IndexType [[deprecated("Use Acts::TrackIndexType instead.")]] =
0143 TrackIndexType;
0144
0145
0146
0147 [[deprecated("Use Acts::kTrackIndexInvalid instead.")]]
0148 constexpr IndexType kInvalid = kTrackIndexInvalid;
0149
0150 }
0151
0152 template <typename T>
0153 struct IsReadOnlyMultiTrajectory;
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 template <typename derived_t>
0164 class MultiTrajectory {
0165 public:
0166
0167 using Derived = derived_t;
0168
0169
0170 static constexpr bool ReadOnly = IsReadOnlyMultiTrajectory<Derived>::value;
0171
0172
0173
0174 static constexpr unsigned int MeasurementSizeMax = kMeasurementSizeMax;
0175
0176 friend class TrackStateProxy<Derived, MeasurementSizeMax, true>;
0177 friend class TrackStateProxy<Derived, MeasurementSizeMax, false>;
0178 template <bool R>
0179 friend class AnyTrackStateProxy;
0180 template <typename T, bool R>
0181 friend class detail_anytstate::TrackStateHandler;
0182 template <typename T>
0183 friend class MultiTrajectory;
0184
0185
0186
0187 using ConstTrackStateProxy =
0188 Acts::TrackStateProxy<Derived, MeasurementSizeMax, true>;
0189
0190
0191
0192 using TrackStateProxy =
0193 Acts::TrackStateProxy<Derived, MeasurementSizeMax, false>;
0194
0195
0196 using IndexType = TrackIndexType;
0197
0198
0199 static constexpr IndexType kInvalid = kTrackIndexInvalid;
0200
0201 protected:
0202 MultiTrajectory() = default;
0203
0204 private:
0205
0206 constexpr Derived& self() { return static_cast<Derived&>(*this); }
0207
0208 constexpr const Derived& self() const {
0209 return static_cast<const Derived&>(*this);
0210 }
0211
0212
0213
0214 bool checkOptional(HashedString key, IndexType istate) const {
0215 using namespace Acts::HashedStringLiteral;
0216 switch (key) {
0217 case "predicted"_hash:
0218 case "filtered"_hash:
0219 case "smoothed"_hash:
0220 case "calibrated"_hash:
0221 case "jacobian"_hash:
0222 case "projector"_hash:
0223 return self().has_impl(key, istate);
0224 default:
0225 return true;
0226 }
0227 }
0228
0229 public:
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 ConstTrackStateProxy getTrackState(IndexType istate) const {
0243 return {*this, istate};
0244 }
0245
0246
0247
0248
0249
0250 TrackStateProxy getTrackState(IndexType istate)
0251 requires(!ReadOnly)
0252 {
0253 return {*this, istate};
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263 IndexType addTrackState(TrackStatePropMask mask = TrackStatePropMask::All,
0264 IndexType iprevious = kInvalid)
0265 requires(!ReadOnly)
0266 {
0267 return self().addTrackState_impl(mask, iprevious);
0268 }
0269
0270
0271
0272
0273
0274
0275
0276 TrackStateProxy makeTrackState(
0277 TrackStatePropMask mask = TrackStatePropMask::All,
0278 IndexType iprevious = kInvalid)
0279 requires(!ReadOnly)
0280 {
0281 return getTrackState(addTrackState(mask, iprevious));
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294 template <typename F>
0295 void visitBackwards(IndexType iendpoint, F&& callable) const
0296 requires detail_lt::VisitorConcept<F, ConstTrackStateProxy>;
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 template <typename F>
0307 void applyBackwards(IndexType iendpoint, F&& callable)
0308 requires(!ReadOnly) && detail_lt::VisitorConcept<F, TrackStateProxy>
0309 {
0310 if (iendpoint == kInvalid) {
0311 throw std::runtime_error(
0312 "Cannot apply backwards with kInvalid as endpoint");
0313 }
0314
0315 while (true) {
0316 auto ts = getTrackState(iendpoint);
0317 if constexpr (std::is_same_v<std::invoke_result_t<F, TrackStateProxy>,
0318 bool>) {
0319 bool proceed = callable(ts);
0320
0321
0322 if (!proceed || !ts.hasPrevious()) {
0323 break;
0324 }
0325 } else {
0326 callable(ts);
0327
0328 if (!ts.hasPrevious()) {
0329 break;
0330 }
0331 }
0332 iendpoint = ts.previous();
0333 }
0334 }
0335
0336
0337
0338
0339
0340 auto reverseTrackStateRange(IndexType iendpoint) const {
0341 using range_t =
0342 detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, true>;
0343 if (iendpoint == kInvalid) {
0344 return range_t{};
0345 }
0346
0347 return range_t{getTrackState(iendpoint)};
0348 }
0349
0350
0351
0352
0353
0354
0355
0356 auto reverseTrackStateRange(IndexType iendpoint)
0357 requires(!ReadOnly)
0358 {
0359 using range_t =
0360 detail_lt::TrackStateRange<true, Derived, MeasurementSizeMax, false>;
0361 if (iendpoint == kInvalid) {
0362 return range_t{};
0363 }
0364
0365 return range_t{getTrackState(iendpoint)};
0366 }
0367
0368
0369
0370
0371
0372
0373
0374 auto forwardTrackStateRange(IndexType istartpoint) const {
0375 using range_t =
0376 detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, true>;
0377 if (istartpoint == kInvalid) {
0378 return range_t{};
0379 }
0380
0381 return range_t{getTrackState(istartpoint)};
0382 }
0383
0384
0385
0386
0387
0388
0389
0390 auto forwardTrackStateRange(IndexType istartpoint)
0391 requires(!ReadOnly)
0392 {
0393 using range_t =
0394 detail_lt::TrackStateRange<false, Derived, MeasurementSizeMax, false>;
0395 if (istartpoint == kInvalid) {
0396 return range_t{};
0397 }
0398
0399 return range_t{getTrackState(istartpoint)};
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 template <typename T>
0418 void addColumn(std::string_view key)
0419 requires(!ReadOnly)
0420 {
0421 self().template addColumn_impl<T>(key);
0422 }
0423
0424
0425
0426
0427 bool hasColumn(HashedString key) const { return self().hasColumn_impl(key); }
0428
0429
0430
0431
0432
0433 void clear()
0434 requires(!ReadOnly)
0435 {
0436 self().clear_impl();
0437 }
0438
0439
0440
0441 IndexType size() const { return self().size_impl(); }
0442
0443 protected:
0444
0445
0446
0447
0448
0449
0450 bool has(HashedString key, IndexType istate) const {
0451 return self().has_impl(key, istate);
0452 }
0453
0454
0455
0456
0457
0458 template <HashedString key>
0459 bool has(IndexType istate) const {
0460 return self().has_impl(key, istate);
0461 }
0462
0463
0464
0465
0466 typename TrackStateProxy::Parameters parameters(IndexType parIdx)
0467 requires(!ReadOnly)
0468 {
0469 return self().parameters_impl(parIdx);
0470 }
0471
0472
0473
0474
0475 typename ConstTrackStateProxy::ConstParameters parameters(
0476 IndexType parIdx) const {
0477 return self().parameters_impl(parIdx);
0478 }
0479
0480
0481
0482
0483 typename TrackStateProxy::Covariance covariance(IndexType covIdx)
0484 requires(!ReadOnly)
0485 {
0486 return self().covariance_impl(covIdx);
0487 }
0488
0489
0490
0491
0492 typename ConstTrackStateProxy::ConstCovariance covariance(
0493 IndexType covIdx) const {
0494 return self().covariance_impl(covIdx);
0495 }
0496
0497
0498
0499
0500 typename TrackStateProxy::Jacobian jacobian(IndexType istate)
0501 requires(!ReadOnly)
0502 {
0503 return self().jacobian_impl(istate);
0504 }
0505
0506
0507
0508
0509 typename ConstTrackStateProxy::ConstJacobian jacobian(
0510 IndexType istate) const {
0511 return self().jacobian_impl(istate);
0512 }
0513
0514
0515
0516
0517
0518
0519 template <std::size_t measdim>
0520 typename TrackStateProxy::template Calibrated<measdim> calibrated(
0521 IndexType istate)
0522 requires(!ReadOnly)
0523 {
0524 return self().template calibrated_impl<measdim>(istate);
0525 }
0526
0527
0528
0529
0530
0531
0532 template <std::size_t measdim>
0533 typename ConstTrackStateProxy::template ConstCalibrated<measdim> calibrated(
0534 IndexType istate) const {
0535 return self().template calibrated_impl<measdim>(istate);
0536 }
0537
0538
0539
0540
0541
0542
0543 template <std::size_t measdim>
0544 typename TrackStateProxy::template CalibratedCovariance<measdim>
0545 calibratedCovariance(IndexType istate)
0546 requires(!ReadOnly)
0547 {
0548 return self().template calibratedCovariance_impl<measdim>(istate);
0549 }
0550
0551
0552
0553
0554
0555 typename TrackStateProxy::EffectiveCalibrated effectiveCalibrated(
0556 IndexType istate)
0557 requires(!ReadOnly)
0558 {
0559
0560
0561
0562 return typename TrackStateProxy::EffectiveCalibrated{
0563 calibrated<eBoundSize>(istate).data(), calibratedSize(istate)};
0564 }
0565
0566
0567
0568
0569
0570 typename ConstTrackStateProxy::EffectiveCalibrated effectiveCalibrated(
0571 IndexType istate) const {
0572
0573
0574
0575 return typename ConstTrackStateProxy::EffectiveCalibrated{
0576 calibrated<eBoundSize>(istate).data(), calibratedSize(istate)};
0577 }
0578
0579
0580
0581
0582
0583 typename TrackStateProxy::EffectiveCalibratedCovariance
0584 effectiveCalibratedCovariance(IndexType istate)
0585 requires(!ReadOnly)
0586 {
0587
0588
0589
0590 return typename TrackStateProxy::EffectiveCalibratedCovariance{
0591 calibratedCovariance<eBoundSize>(istate).data(), calibratedSize(istate),
0592 calibratedSize(istate)};
0593 }
0594
0595
0596
0597
0598
0599 typename ConstTrackStateProxy::EffectiveCalibratedCovariance
0600 effectiveCalibratedCovariance(IndexType istate) const {
0601
0602
0603
0604 return typename ConstTrackStateProxy::EffectiveCalibratedCovariance{
0605 calibratedCovariance<eBoundSize>(istate).data(), calibratedSize(istate),
0606 calibratedSize(istate)};
0607 }
0608
0609
0610
0611
0612
0613 template <std::size_t measdim>
0614 typename ConstTrackStateProxy::template ConstCalibratedCovariance<measdim>
0615 calibratedCovariance(IndexType istate) const {
0616 return self().template calibratedCovariance_impl<measdim>(istate);
0617 }
0618
0619
0620
0621
0622 IndexType calibratedSize(IndexType istate) const {
0623 return self().calibratedSize_impl(istate);
0624 }
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 void shareFrom(IndexType iself, IndexType iother,
0637 TrackStatePropMask shareSource, TrackStatePropMask shareTarget)
0638 requires(!ReadOnly)
0639 {
0640 self().shareFrom_impl(iself, iother, shareSource, shareTarget);
0641 }
0642
0643
0644
0645
0646 void unset(TrackStatePropMask target, IndexType istate)
0647 requires(!ReadOnly)
0648 {
0649 self().unset_impl(target, istate);
0650 }
0651
0652
0653
0654
0655
0656 void addTrackStateComponents(IndexType istate, TrackStatePropMask mask)
0657 requires(!ReadOnly)
0658 {
0659 self().addTrackStateComponents_impl(istate, mask);
0660 }
0661
0662
0663
0664
0665
0666
0667 template <typename T, HashedString key>
0668 T& component(IndexType istate)
0669 requires(!ReadOnly)
0670 {
0671 assert(checkOptional(key, istate));
0672 return *std::any_cast<T*>(self().component_impl(key, istate));
0673 }
0674
0675
0676
0677
0678
0679
0680 template <typename T>
0681 T& component(HashedString key, IndexType istate)
0682 requires(!ReadOnly)
0683 {
0684 assert(checkOptional(key, istate));
0685 return *std::any_cast<T*>(self().component_impl(key, istate));
0686 }
0687
0688
0689
0690
0691
0692
0693 template <typename T, HashedString key>
0694 const T& component(IndexType istate) const {
0695 assert(checkOptional(key, istate));
0696 return *std::any_cast<const T*>(self().component_impl(key, istate));
0697 }
0698
0699
0700
0701
0702
0703
0704 template <typename T>
0705 const T& component(HashedString key, IndexType istate) const {
0706 assert(checkOptional(key, istate));
0707 return *std::any_cast<const T*>(self().component_impl(key, istate));
0708 }
0709
0710
0711
0712
0713
0714
0715 void allocateCalibrated(IndexType istate, std::size_t measdim) {
0716 throw_assert(measdim > 0 && measdim <= eBoundSize,
0717 "Invalid measurement dimension detected");
0718
0719 visit_measurement(measdim, [this, istate]<std::size_t DIM>(
0720 std::integral_constant<std::size_t, DIM>) {
0721 self().allocateCalibrated_impl(
0722 istate, Vector<DIM>{Vector<DIM>::Zero()},
0723 SquareMatrix<DIM>{SquareMatrix<DIM>::Zero()});
0724 });
0725 }
0726
0727
0728
0729
0730
0731
0732
0733
0734 template <std::size_t measdim, typename val_t, typename cov_t>
0735 void allocateCalibrated(IndexType istate, const Eigen::DenseBase<val_t>& val,
0736 const Eigen::DenseBase<cov_t>& cov) {
0737 self().allocateCalibrated_impl(istate, val, cov);
0738 }
0739
0740
0741
0742
0743 void setUncalibratedSourceLink(IndexType istate, SourceLink&& sourceLink)
0744 requires(!ReadOnly)
0745 {
0746 self().setUncalibratedSourceLink_impl(istate, std::move(sourceLink));
0747 }
0748
0749
0750
0751
0752 SourceLink getUncalibratedSourceLink(IndexType istate) const {
0753 return self().getUncalibratedSourceLink_impl(istate);
0754 }
0755
0756
0757
0758
0759 const Surface* referenceSurface(IndexType istate) const {
0760 return self().referenceSurface_impl(istate);
0761 }
0762
0763
0764
0765
0766 void setReferenceSurface(IndexType istate,
0767 std::shared_ptr<const Surface> surface)
0768 requires(!ReadOnly)
0769 {
0770 self().setReferenceSurface_impl(istate, std::move(surface));
0771 }
0772
0773 private:
0774 template <typename T>
0775 void copyDynamicFrom(IndexType dstIdx, const T& src, IndexType srcIdx)
0776 requires(!ReadOnly)
0777 {
0778 const auto& dynamicKeys = src.self().dynamicKeys_impl();
0779 for (const auto key : dynamicKeys) {
0780 std::any srcPtr = src.self().component_impl(key, srcIdx);
0781 self().copyDynamicFrom_impl(dstIdx, key, srcPtr);
0782 }
0783 }
0784 };
0785
0786 }
0787
0788 #include "Acts/EventData/MultiTrajectory.ipp"