File indexing completed on 2025-08-06 08:10:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/MultiTrajectory.hpp"
0013 #include "Acts/EventData/ParticleHypothesis.hpp"
0014 #include "Acts/EventData/TrackContainerBackendConcept.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/EventData/TrackStatePropMask.hpp"
0017 #include "Acts/Utilities/Concepts.hpp"
0018 #include "Acts/Utilities/HashedString.hpp"
0019 #include "Acts/Utilities/UnitVectors.hpp"
0020
0021 #include <iterator>
0022 #include <type_traits>
0023
0024 namespace Acts {
0025
0026 template <ACTS_CONCEPT(Acts::TrackContainerBackend) track_container_t,
0027 typename traj_t, template <typename> class holder_t>
0028 class TrackContainer;
0029
0030 namespace detail_tc {
0031 template <typename T, bool select>
0032 using ConstIf = std::conditional_t<select, const T, T>;
0033
0034
0035 template <typename container_t, typename proxy_t, bool ReadOnly>
0036 class TrackProxyIterator {
0037 using ProxyType = proxy_t;
0038 using IndexType = typename ProxyType::IndexType;
0039 using ContainerType = container_t;
0040
0041 public:
0042 using iterator_category = std::random_access_iterator_tag;
0043 using value_type = ProxyType;
0044 using difference_type = std::ptrdiff_t;
0045 using pointer = void;
0046 using reference = void;
0047
0048 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0049 TrackProxyIterator(container_t& container, IndexType itrack)
0050 : m_container(&container), m_itrack(itrack) {}
0051
0052 template <bool RO = ReadOnly, typename = std::enable_if_t<RO>>
0053 TrackProxyIterator(const container_t& container, IndexType itrack)
0054 : m_container(&container), m_itrack(itrack) {}
0055
0056 TrackProxyIterator& operator++() {
0057 m_itrack++;
0058 return *this;
0059 }
0060 TrackProxyIterator& operator--() {
0061 m_itrack--;
0062 return *this;
0063 }
0064
0065 bool operator==(const TrackProxyIterator& other) const {
0066 return m_container == other.m_container && m_itrack == other.m_itrack;
0067 }
0068
0069 bool operator!=(const TrackProxyIterator& other) const {
0070 return !(*this == other);
0071 }
0072
0073 bool operator<(const TrackProxyIterator& other) const {
0074 return m_itrack < other.m_itrack;
0075 }
0076
0077 bool operator>(const TrackProxyIterator& other) const {
0078 return m_itrack > other.m_itrack;
0079 }
0080
0081 bool operator<=(const TrackProxyIterator& other) const {
0082 return m_itrack <= other.m_itrack;
0083 }
0084
0085 bool operator>=(const TrackProxyIterator& other) const {
0086 return m_itrack >= other.m_itrack;
0087 }
0088
0089 ProxyType operator*() const { return m_container->getTrack(m_itrack); }
0090
0091 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0092 ProxyType operator*() {
0093 return m_container->getTrack(m_itrack);
0094 }
0095
0096 TrackProxyIterator operator[](difference_type n) const {
0097 TrackProxyIterator copy = *this;
0098 copy += n;
0099 return copy;
0100 };
0101
0102 TrackProxyIterator& operator+=(difference_type n) {
0103 m_itrack += n;
0104 return *this;
0105 }
0106
0107 TrackProxyIterator operator-=(difference_type n) {
0108 m_itrack -= n;
0109 return *this;
0110 }
0111
0112 friend difference_type operator-(const TrackProxyIterator& lhs,
0113 const TrackProxyIterator& rhs) {
0114 return lhs.m_itrack - rhs.m_itrack;
0115 }
0116
0117 friend TrackProxyIterator operator+(const TrackProxyIterator& lhs,
0118 difference_type rhs) {
0119 TrackProxyIterator copy = lhs;
0120 copy += rhs;
0121 return copy;
0122 }
0123
0124 friend TrackProxyIterator operator+(difference_type lhs,
0125 const TrackProxyIterator& rhs) {
0126 return rhs + lhs;
0127 }
0128
0129 friend TrackProxyIterator operator-(const TrackProxyIterator& lhs,
0130 difference_type rhs) {
0131 return lhs + (-rhs);
0132 }
0133
0134 friend TrackProxyIterator operator-(difference_type lhs,
0135 const TrackProxyIterator& rhs) {
0136 return rhs + (-lhs);
0137 }
0138
0139 private:
0140 detail_lt::TransitiveConstPointer<ConstIf<ContainerType, ReadOnly>>
0141 m_container;
0142 IndexType m_itrack;
0143 };
0144
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template <typename track_container_t, typename trajectory_t,
0158 template <typename> class holder_t, bool read_only = true>
0159 class TrackProxy {
0160 public:
0161
0162 static constexpr bool ReadOnly = read_only;
0163
0164
0165 using Container = track_container_t;
0166
0167
0168 using Trajectory = trajectory_t;
0169
0170
0171 using IndexType = typename Container::IndexType;
0172
0173
0174 static constexpr IndexType kInvalid = Container::kInvalid;
0175
0176
0177 using MutableTrackProxy =
0178 TrackProxy<track_container_t, trajectory_t, holder_t, false>;
0179
0180
0181 using ConstTrackProxy =
0182 TrackProxy<track_container_t, trajectory_t, holder_t, true>;
0183
0184
0185 using ConstProxyType = ConstTrackProxy;
0186
0187
0188 using TrackStateProxy = typename Trajectory::TrackStateProxy;
0189
0190
0191 using ConstTrackStateProxy = typename Trajectory::ConstTrackStateProxy;
0192
0193
0194
0195 using Parameters =
0196 typename detail_lt::Types<eBoundSize, false>::CoefficientsMap;
0197
0198
0199 using ConstParameters =
0200 typename detail_lt::Types<eBoundSize, true>::CoefficientsMap;
0201
0202
0203
0204 using Covariance =
0205 typename detail_lt::Types<eBoundSize, false>::CovarianceMap;
0206
0207
0208 using ConstCovariance =
0209 typename detail_lt::Types<eBoundSize, true>::CovarianceMap;
0210
0211 #ifndef DOXYGEN
0212 friend TrackContainer<Container, Trajectory, holder_t>;
0213 friend MutableTrackProxy;
0214 friend ConstTrackProxy;
0215
0216 template <typename A, typename B, template <typename> class H, bool R>
0217 friend class TrackProxy;
0218 #endif
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 TrackProxy(const MutableTrackProxy& other)
0233 : m_container{other.m_container}, m_index{other.m_index} {}
0234
0235
0236
0237
0238 TrackProxy& operator=(const MutableTrackProxy& other) {
0239 m_container = other.m_container;
0240 m_index = other.m_index;
0241 return *this;
0242 }
0243
0244
0245
0246
0247
0248
0249 bool operator==(const TrackProxy& other) const {
0250 return &(*m_container) == &(*other.m_container) && m_index == other.m_index;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 IndexType tipIndex() const {
0268 return component<IndexType>(hashString("tipIndex"));
0269 }
0270
0271
0272
0273
0274
0275 IndexType stemIndex() const {
0276 return component<IndexType>(hashString("stemIndex"));
0277 }
0278
0279
0280
0281
0282
0283 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0284 IndexType& tipIndex() {
0285 return component<IndexType>(hashString("tipIndex"));
0286 }
0287
0288
0289
0290
0291
0292
0293 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0294 IndexType& stemIndex() {
0295 return component<IndexType>(hashString("stemIndex"));
0296 }
0297
0298
0299
0300 const Surface& referenceSurface() const {
0301 return *m_container->container().referenceSurface_impl(m_index);
0302 }
0303
0304
0305
0306
0307
0308 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0309 void setReferenceSurface(std::shared_ptr<const Surface> srf) {
0310 m_container->container().setReferenceSurface_impl(m_index, std::move(srf));
0311 }
0312
0313
0314
0315
0316 bool hasReferenceSurface() const {
0317
0318 return m_container->container().referenceSurface_impl(m_index) != nullptr;
0319 }
0320
0321
0322
0323
0324 ConstParameters parameters() const {
0325 return m_container->parameters(m_index);
0326 }
0327
0328
0329
0330
0331 ConstCovariance covariance() const {
0332 return m_container->covariance(m_index);
0333 }
0334
0335
0336
0337
0338
0339 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0340 Parameters parameters() {
0341 return m_container->parameters(m_index);
0342 }
0343
0344
0345
0346
0347
0348 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0349 Covariance covariance() {
0350 return m_container->covariance(m_index);
0351 }
0352
0353
0354
0355 ActsScalar theta() const {
0356 return parameters()[eBoundTheta];
0357 }
0358
0359
0360
0361 ActsScalar phi() const {
0362 return parameters()[eBoundPhi];
0363 }
0364
0365
0366
0367 ActsScalar loc0() const {
0368 return parameters()[eBoundLoc0];
0369 }
0370
0371
0372
0373 ActsScalar loc1() const {
0374 return parameters()[eBoundLoc1];
0375 }
0376
0377
0378
0379 ActsScalar time() const {
0380 return parameters()[eBoundTime];
0381 }
0382
0383
0384
0385 ActsScalar qOverP() const {
0386 return parameters()[eBoundQOverP];
0387 }
0388
0389
0390
0391 ParticleHypothesis particleHypothesis() const {
0392 return m_container->container().particleHypothesis_impl(m_index);
0393 }
0394
0395
0396
0397
0398 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0399 void setParticleHypothesis(const ParticleHypothesis& particleHypothesis) {
0400 m_container->container().setParticleHypothesis_impl(m_index,
0401 particleHypothesis);
0402 }
0403
0404
0405
0406
0407 ActsScalar charge() const {
0408 return particleHypothesis().qFromQOP(qOverP());
0409 }
0410
0411
0412
0413 ActsScalar absoluteMomentum() const {
0414 return particleHypothesis().extractMomentum(qOverP());
0415 }
0416
0417
0418
0419 ActsScalar transverseMomentum() const {
0420 return std::sin(theta()) * absoluteMomentum();
0421 }
0422
0423
0424
0425 Vector3 direction() const {
0426 return makeDirectionFromPhiTheta(phi(), theta());
0427 }
0428
0429
0430
0431 Vector3 momentum() const {
0432 return absoluteMomentum() * direction();
0433 }
0434
0435
0436
0437
0438
0439
0440 unsigned int nTrackStates() const {
0441
0442
0443 if (tipIndex() == kInvalid) {
0444
0445 return 0;
0446 }
0447 auto tsRange = trackStatesReversed();
0448 return std::distance(tsRange.begin(), tsRange.end());
0449 }
0450
0451
0452
0453
0454 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0455 unsigned int& nMeasurements() {
0456 return component<unsigned int, hashString("nMeasurements")>();
0457 }
0458
0459
0460
0461
0462 unsigned int nMeasurements() const {
0463 return component<unsigned int, hashString("nMeasurements")>();
0464 }
0465
0466
0467
0468
0469
0470 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0471 unsigned int& nHoles() {
0472 return component<unsigned int, hashString("nHoles")>();
0473 }
0474
0475
0476
0477 unsigned int nHoles() const {
0478 return component<unsigned int, hashString("nHoles")>();
0479 }
0480
0481
0482
0483
0484
0485 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0486 unsigned int& nOutliers() {
0487 return component<unsigned int, hashString("nOutliers")>();
0488 }
0489
0490
0491
0492 unsigned int nOutliers() const {
0493 return component<unsigned int, hashString("nOutliers")>();
0494 }
0495
0496
0497
0498
0499
0500 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0501 unsigned int& nSharedHits() {
0502 return component<unsigned int, hashString("nSharedHits")>();
0503 }
0504
0505
0506
0507 unsigned int nSharedHits() const {
0508 return component<unsigned int, hashString("nSharedHits")>();
0509 }
0510
0511
0512
0513
0514
0515 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0516 float& chi2() {
0517 return component<float, hashString("chi2")>();
0518 }
0519
0520
0521
0522 float chi2() const {
0523 return component<float, hashString("chi2")>();
0524 }
0525
0526
0527
0528
0529
0530 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0531 unsigned int& nDoF() {
0532 return component<unsigned int, hashString("ndf")>();
0533 }
0534
0535
0536
0537 unsigned int nDoF() const {
0538 return component<unsigned int, hashString("ndf")>();
0539 }
0540
0541
0542
0543
0544 IndexType index() const {
0545 return m_index;
0546 }
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558 auto innermostTrackState() const {
0559 using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0560 std::declval<IndexType>()));
0561
0562 IndexType stem = component<IndexType, hashString("stemIndex")>();
0563 if (stem == kInvalid) {
0564 return std::optional<proxy_t>{};
0565 } else {
0566 return std::optional<proxy_t>{
0567 m_container->trackStateContainer().getTrackState(stem)};
0568 }
0569 }
0570
0571
0572
0573
0574
0575 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0576 auto innermostTrackState() {
0577 using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
0578 std::declval<IndexType>()));
0579
0580 IndexType stem = component<IndexType>(hashString("stemIndex"));
0581 if (stem == kInvalid) {
0582 return std::optional<proxy_t>{};
0583 } else {
0584 return std::optional<proxy_t>{
0585 m_container->trackStateContainer().getTrackState(stem)};
0586 }
0587 }
0588
0589
0590
0591
0592
0593 auto trackStatesReversed() const {
0594 return m_container->reverseTrackStateRange(m_index);
0595 }
0596
0597
0598
0599
0600
0601
0602 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0603 auto trackStatesReversed() {
0604 return m_container->reverseTrackStateRange(m_index);
0605 }
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 auto trackStates() const {
0616 return m_container->forwardTrackStateRange(m_index);
0617 }
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0629 auto trackStates() {
0630 return m_container->forwardTrackStateRange(m_index);
0631 }
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0644 void linkForward() {
0645 IndexType last = kInvalid;
0646 for (auto ts : trackStatesReversed()) {
0647 ts.template component<IndexType>(hashString("next")) = last;
0648 last = ts.index();
0649 }
0650 stemIndex() = last;
0651 }
0652
0653
0654
0655
0656
0657
0658
0659 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0660 auto appendTrackState(TrackStatePropMask mask = TrackStatePropMask::All) {
0661 auto& tsc = m_container->trackStateContainer();
0662 auto ts = tsc.makeTrackState(mask, tipIndex());
0663 tipIndex() = ts.index();
0664 return ts;
0665 }
0666
0667
0668
0669
0670
0671
0672 template <typename track_proxy_t, bool RO = ReadOnly,
0673 typename = std::enable_if_t<!RO>>
0674 void copyFrom(const track_proxy_t& other, bool copyTrackStates = true) {
0675
0676
0677
0678 if (copyTrackStates) {
0679
0680 for (const auto& srcTrackState : other.trackStatesReversed()) {
0681 auto destTrackState = appendTrackState(srcTrackState.getMask());
0682 if (srcTrackState.hasCalibrated()) {
0683 destTrackState.allocateCalibrated(srcTrackState.calibratedSize());
0684 }
0685 destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All,
0686 true);
0687 }
0688
0689
0690 reverseTrackStates();
0691 }
0692
0693 parameters() = other.parameters();
0694 covariance() = other.covariance();
0695 setParticleHypothesis(other.particleHypothesis());
0696 if (other.hasReferenceSurface()) {
0697 setReferenceSurface(other.referenceSurface().getSharedPtr());
0698 }
0699 nMeasurements() = other.nMeasurements();
0700 nHoles() = other.nHoles();
0701 nOutliers() = other.nOutliers();
0702 nSharedHits() = other.nSharedHits();
0703 chi2() = other.chi2();
0704 nDoF() = other.nDoF();
0705
0706 m_container->copyDynamicFrom(m_index, other.m_container->container(),
0707 other.m_index);
0708 }
0709
0710
0711
0712
0713
0714
0715
0716
0717 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0718 void reverseTrackStates(bool invertJacobians = false) {
0719 IndexType current = tipIndex();
0720 IndexType next = kInvalid;
0721 IndexType prev = kInvalid;
0722
0723 stemIndex() = tipIndex();
0724
0725
0726 BoundMatrix nextJacobian;
0727
0728 while (current != kInvalid) {
0729 auto ts = m_container->trackStateContainer().getTrackState(current);
0730 prev = ts.previous();
0731 ts.template component<IndexType>(hashString("next")) = prev;
0732 ts.previous() = next;
0733 if (invertJacobians) {
0734 if (next != kInvalid) {
0735 BoundMatrix curJacobian = ts.jacobian();
0736 ts.jacobian() = nextJacobian.inverse();
0737 nextJacobian = curJacobian;
0738 } else {
0739 nextJacobian = ts.jacobian();
0740 ts.jacobian().setZero();
0741 }
0742 }
0743 next = current;
0744 tipIndex() = current;
0745 current = prev;
0746 }
0747 }
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770 template <typename T, HashedString key, bool RO = ReadOnly,
0771 typename = std::enable_if_t<!RO>>
0772 constexpr T& component() {
0773 return m_container->template component<T, key>(m_index);
0774 }
0775
0776
0777
0778
0779
0780 template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0781 constexpr T& component(HashedString key) {
0782 return m_container->template component<T>(key, m_index);
0783 }
0784
0785
0786
0787
0788
0789
0790 template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0791 constexpr T& component(std::string_view key) {
0792 return m_container->template component<T>(hashString(key), m_index);
0793 }
0794
0795
0796
0797
0798
0799 template <typename T, HashedString key>
0800 constexpr const T& component() const {
0801 return m_container->template component<T, key>(m_index);
0802 }
0803
0804
0805
0806
0807
0808 template <typename T>
0809 constexpr const T& component(HashedString key) const {
0810 return m_container->template component<T>(key, m_index);
0811 }
0812
0813
0814
0815
0816
0817
0818 template <typename T>
0819 constexpr const T& component(std::string_view key) const {
0820 return m_container->template component<T>(hashString(key), m_index);
0821 }
0822
0823
0824
0825
0826
0827
0828 BoundTrackParameters createParametersAtReference() const {
0829 return BoundTrackParameters(referenceSurface().getSharedPtr(), parameters(),
0830 covariance(), particleHypothesis());
0831 }
0832
0833
0834
0835
0836 BoundTrackParameters createParametersFromState(
0837 const ConstTrackStateProxy& trackState) const {
0838 return BoundTrackParameters(trackState.referenceSurface().getSharedPtr(),
0839 trackState.parameters(),
0840 trackState.covariance(), particleHypothesis());
0841 }
0842
0843
0844
0845
0846 template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
0847 auto& container() {
0848 return *m_container;
0849 }
0850
0851
0852
0853 const auto& container() const {
0854 return *m_container;
0855 }
0856
0857 private:
0858 TrackProxy(detail_tc::ConstIf<TrackContainer<Container, Trajectory, holder_t>,
0859 ReadOnly>& container,
0860 IndexType itrack)
0861 : m_container{&container}, m_index{itrack} {}
0862
0863 detail_lt::TransitiveConstPointer<detail_tc::ConstIf<
0864 TrackContainer<Container, Trajectory, holder_t>, ReadOnly>>
0865 m_container;
0866 IndexType m_index;
0867 };
0868 }