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