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