Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackProxy.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrackProxy.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
18 
19 #include <iterator>
20 #include <type_traits>
21 
22 namespace Acts {
23 
24 template <ACTS_CONCEPT(Acts::TrackContainerBackend) track_container_t,
25  typename traj_t, template <typename> class holder_t>
26 class TrackContainer;
27 
28 namespace detail_tc {
29 template <typename T, bool select>
30 using ConstIf = std::conditional_t<select, const T, T>;
31 
33 template <typename container_t, typename proxy_t, bool ReadOnly>
35  using ProxyType = proxy_t;
36  using IndexType = typename ProxyType::IndexType;
38 
39  public:
40  using iterator_category = std::random_access_iterator_tag;
42  using difference_type = std::ptrdiff_t;
43  using pointer = void;
44  using reference = void;
45 
46  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
48  : m_container(&container), m_itrack(itrack) {}
49 
50  template <bool RO = ReadOnly, typename = std::enable_if_t<RO>>
52  : m_container(&container), m_itrack(itrack) {}
53 
55  m_itrack++;
56  return *this;
57  }
59  m_itrack--;
60  return *this;
61  }
62 
63  bool operator==(const TrackProxyIterator& other) const {
64  return m_container == other.m_container && m_itrack == other.m_itrack;
65  }
66 
67  bool operator!=(const TrackProxyIterator& other) const {
68  return !(*this == other);
69  }
70 
71  bool operator<(const TrackProxyIterator& other) const {
72  return m_itrack < other.m_itrack;
73  }
74 
75  bool operator>(const TrackProxyIterator& other) const {
76  return m_itrack > other.m_itrack;
77  }
78 
79  bool operator<=(const TrackProxyIterator& other) const {
80  return m_itrack <= other.m_itrack;
81  }
82 
83  bool operator>=(const TrackProxyIterator& other) const {
84  return m_itrack >= other.m_itrack;
85  }
86 
87  ProxyType operator*() const { return m_container->getTrack(m_itrack); }
88 
89  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
91  return m_container->getTrack(m_itrack);
92  }
93 
95  TrackProxyIterator copy = *this;
96  copy += n;
97  return copy;
98  };
99 
101  m_itrack += n;
102  return *this;
103  }
104 
106  m_itrack -= n;
107  return *this;
108  }
109 
111  const TrackProxyIterator& rhs) {
112  return lhs.m_itrack - rhs.m_itrack;
113  }
114 
117  TrackProxyIterator copy = lhs;
118  copy += rhs;
119  return copy;
120  }
121 
123  const TrackProxyIterator& rhs) {
124  return rhs + lhs;
125  }
126 
129  return lhs + (-rhs);
130  }
131 
133  const TrackProxyIterator& rhs) {
134  return rhs + (-lhs);
135  }
136 
137  private:
141 };
142 
143 } // namespace detail_tc
144 
150 template <typename track_container_t, typename trajectory_t,
151  template <typename> class holder_t, bool read_only = true>
152 class TrackProxy {
153  public:
154  static constexpr bool ReadOnly = read_only;
155  using Container = track_container_t;
156  using Trajectory = trajectory_t;
157 
158  using MutableTrackProxy =
160  using ConstTrackProxy =
162 
163  using TrackStateProxy = typename Trajectory::TrackStateProxy;
164  using ConstTrackStateProxy = typename Trajectory::ConstTrackStateProxy;
165 
166  using Parameters =
168  using ConstParameters =
170 
171  using Covariance =
173  using ConstCovariance =
175 
176  using IndexType = typename Container::IndexType;
178 
179 #ifndef DOXYGEN
183 #endif
184 
189  : m_container{other.m_container}, m_index{other.m_index} {}
190 
194  TrackProxy& operator=(const MutableTrackProxy& other) {
195  m_container = other.m_container;
196  m_index = other.m_index;
197  return *this;
198  }
199 
204  template <typename T, HashedString key, bool RO = ReadOnly,
205  typename = std::enable_if_t<!RO>>
206  constexpr T& component() {
207  return m_container->template component<T, key>(m_index);
208  }
209 
214  template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
215  constexpr T& component(HashedString key) {
216  return m_container->template component<T>(key, m_index);
217  }
218 
224  template <typename T, bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
225  constexpr T& component(std::string_view key) {
226  return m_container->template component<T>(hashString(key), m_index);
227  }
228 
233  template <typename T, HashedString key>
234  constexpr const T& component() const {
235  return m_container->template component<T, key>(m_index);
236  }
237 
242  template <typename T>
243  constexpr const T& component(HashedString key) const {
244  return m_container->template component<T>(key, m_index);
245  }
246 
252  template <typename T>
253  constexpr const T& component(std::string_view key) const {
254  return m_container->template component<T>(hashString(key), m_index);
255  }
256 
259  IndexType tipIndex() const {
260  return component<IndexType>(hashString("tipIndex"));
261  }
262 
267  IndexType stemIndex() const {
268  return component<IndexType>(hashString("stemIndex"));
269  }
270 
274  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
275  IndexType& tipIndex() {
276  return component<IndexType>(hashString("tipIndex"));
277  }
278 
283  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
284  IndexType& stemIndex() {
285  return component<IndexType>(hashString("stemIndex"));
286  }
287 
291  auto innermostTrackState() const {
292  using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
293  std::declval<IndexType>()));
294 
295  IndexType stem = component<IndexType>(hashString("stemIndex"));
296  if (stem == kInvalid) {
297  return std::optional<proxy_t>{};
298  } else {
299  return std::optional<proxy_t>{
300  m_container->trackStateContainer().getTrackState(stem)};
301  }
302  }
303 
307  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
308  auto innermostTrackState() {
309  using proxy_t = decltype(m_container->trackStateContainer().getTrackState(
310  std::declval<IndexType>()));
311 
312  IndexType stem = component<IndexType>(hashString("stemIndex"));
313  if (stem == kInvalid) {
314  return std::optional<proxy_t>{};
315  } else {
316  return std::optional<proxy_t>{
317  m_container->trackStateContainer().getTrackState(stem)};
318  }
319  }
320 
323  const Surface& referenceSurface() const {
324  return *m_container->container().referenceSurface_impl(m_index);
325  }
326 
327  // NOLINTBEGIN(performance-unnecessary-value-param)
328  // looks like a false-positive. clang-tidy believes `srf` is not movable.
331  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
332  void setReferenceSurface(std::shared_ptr<const Surface> srf) {
333  m_container->container().setReferenceSurface_impl(m_index, std::move(srf));
334  }
335  // NOLINTEND(performance-unnecessary-value-param)
336 
339  bool hasReferenceSurface() const {
340  // @TODO: This could be more efficient
341  return m_container->container().referenceSurface_impl(m_index) != nullptr;
342  }
343 
347  ConstParameters parameters() const {
348  return m_container->parameters(m_index);
349  }
350 
354  ConstCovariance covariance() const {
355  return m_container->covariance(m_index);
356  }
357 
361  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
363  return m_container->parameters(m_index);
364  }
365 
369  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
371  return m_container->covariance(m_index);
372  }
373 
376  ActsScalar theta() const {
377  return parameters()[eBoundTheta];
378  }
379 
382  ActsScalar phi() const {
383  return parameters()[eBoundPhi];
384  }
385 
388  ActsScalar loc0() const {
389  return parameters()[eBoundLoc0];
390  }
391 
394  ActsScalar loc1() const {
395  return parameters()[eBoundLoc1];
396  }
397 
400  ActsScalar time() const {
401  return parameters()[eBoundTime];
402  }
403 
406  ActsScalar qOverP() const {
407  return parameters()[eBoundQOverP];
408  }
409 
412  ParticleHypothesis particleHypothesis() const {
413  return component<ParticleHypothesis, hashString("particleHypothesis")>();
414  }
415 
418  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
419  void setParticleHypothesis(const ParticleHypothesis& particleHypothesis) {
420  m_container->container().setParticleHypothesis_impl(m_index,
421  particleHypothesis);
422  }
423 
427  ActsScalar charge() const {
428  return particleHypothesis().qFromQOP(qOverP());
429  }
430 
433  ActsScalar absoluteMomentum() const {
434  return particleHypothesis().extractMomentum(qOverP());
435  }
436 
439  ActsScalar transverseMomentum() const {
440  return std::sin(theta()) * absoluteMomentum();
441  }
442 
445  Vector3 direction() const {
446  return makeDirectionFromPhiTheta(phi(), theta());
447  }
448 
451  Vector3 momentum() const {
452  return absoluteMomentum() * direction();
453  }
454 
459  auto trackStatesReversed() const {
460  return m_container->reverseTrackStateRange(m_index);
461  }
462 
467  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
468  auto trackStatesReversed() {
469  return m_container->reverseTrackStateRange(m_index);
470  }
471 
476  auto trackStates() const {
477  return m_container->forwardTrackStateRange(m_index);
478  }
479 
484  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
485  auto trackStates() {
486  return m_container->forwardTrackStateRange(m_index);
487  }
488 
491  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
492  void linkForward() {
493  IndexType last = kInvalid;
494  for (auto ts : trackStatesReversed()) {
495  ts.template component<IndexType>(hashString("next")) = last;
496  last = ts.index();
497  }
498  stemIndex() = last;
499  }
500 
506  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
507  auto appendTrackState(TrackStatePropMask mask = TrackStatePropMask::All) {
508  auto& tsc = m_container->trackStateContainer();
509  auto ts = tsc.getTrackState(tsc.addTrackState(mask, tipIndex()));
510  tipIndex() = ts.index();
511  return ts;
512  }
513 
519  unsigned int nTrackStates() const {
520  // @TODO: This should probably be cached, distance is expensive
521  // without random access
522  if (tipIndex() == kInvalid) {
523  // no tip index -> no track states
524  return 0;
525  }
526  auto tsRange = trackStatesReversed();
527  return std::distance(tsRange.begin(), tsRange.end());
528  }
529 
532  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
533  unsigned int& nMeasurements() {
534  return component<unsigned int>(hashString("nMeasurements"));
535  }
536 
540  unsigned int nMeasurements() const {
541  return component<unsigned int>(hashString("nMeasurements"));
542  }
543 
547  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
548  unsigned int& nHoles() {
549  return component<unsigned int>(hashString("nHoles"));
550  }
551 
554  unsigned int nHoles() const {
555  return component<unsigned int>(hashString("nHoles"));
556  }
557 
561  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
562  unsigned int& nOutliers() {
563  return component<unsigned int>(hashString("nOutliers"));
564  }
565 
568  unsigned int nOutliers() const {
569  return component<unsigned int>(hashString("nOutliers"));
570  }
571 
575  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
576  unsigned int& nSharedHits() {
577  return component<unsigned int>(hashString("nSharedHits"));
578  }
579 
582  unsigned int nSharedHits() const {
583  return component<unsigned int>(hashString("nSharedHits"));
584  }
585 
589  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
590  float& chi2() {
591  return component<float>(hashString("chi2"));
592  }
593 
596  float chi2() const {
597  return component<float>(hashString("chi2"));
598  }
599 
603  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
604  unsigned int& nDoF() {
605  return component<unsigned int>(hashString("ndf"));
606  }
607 
610  unsigned int nDoF() const {
611  return component<unsigned int>(hashString("ndf"));
612  }
613 
617  IndexType index() const {
618  return m_index;
619  }
620 
623  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
624  auto& container() {
625  return *m_container;
626  }
627 
632  template <typename track_proxy_t, bool RO = ReadOnly,
633  typename = std::enable_if_t<!RO>>
634  void copyFrom(const track_proxy_t& other, bool copyTrackStates = true) {
635  // @TODO: Add constraint on which track proxies are allowed,
636  // this is only implicit right now
637 
638  if (copyTrackStates) {
639  // append track states (cheap), but they're in the wrong order
640  for (const auto& srcTrackState : other.trackStatesReversed()) {
641  auto destTrackState = appendTrackState(srcTrackState.getMask());
642  if (srcTrackState.hasCalibrated()) {
643  destTrackState.allocateCalibrated(srcTrackState.calibratedSize());
644  }
645  destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All,
646  true);
647  }
648 
649  // reverse using standard linked list reversal algorithm
650  reverseTrackStates();
651  }
652 
653  parameters() = other.parameters();
654  covariance() = other.covariance();
655  setParticleHypothesis(other.particleHypothesis());
656  if (other.hasReferenceSurface()) {
657  setReferenceSurface(other.referenceSurface().getSharedPtr());
658  }
659  nMeasurements() = other.nMeasurements();
660  nHoles() = other.nHoles();
661  nOutliers() = other.nOutliers();
662  nSharedHits() = other.nSharedHits();
663  chi2() = other.chi2();
664  nDoF() = other.nDoF();
665 
666  // This will only be valid if the backends match and support this operation
667  m_container->copyDynamicFrom(m_index, other.m_container->container(),
668  other.m_index);
669  }
670 
677  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
678  void reverseTrackStates(bool invertJacobians = false) {
679  IndexType current = tipIndex();
681  IndexType prev = kInvalid;
682 
683  stemIndex() = tipIndex();
684 
685  // @TODO: Maybe refactor to not need this variable if invertJacobians == false
686  BoundMatrix nextJacobian;
687 
688  while (current != kInvalid) {
689  auto ts = m_container->trackStateContainer().getTrackState(current);
690  prev = ts.previous();
691  ts.template component<IndexType>(hashString("next")) = prev;
692  ts.previous() = next;
693  if (invertJacobians) {
694  if (next != kInvalid) {
695  BoundMatrix curJacobian = ts.jacobian();
696  ts.jacobian() = nextJacobian.inverse();
697  nextJacobian = curJacobian;
698  } else {
699  nextJacobian = ts.jacobian();
700  ts.jacobian().setZero();
701  }
702  }
703  next = current;
704  tipIndex() = current;
705  current = prev;
706  }
707  }
708 
711  const auto& container() const {
712  return *m_container;
713  }
714 
718  bool operator==(const TrackProxy& other) const {
719  return &(*m_container) == &(*other.m_container) && m_index == other.m_index;
720  }
721 
722  // Track proxies are friends, not food!
723  template <typename A, typename B, template <typename> class H, bool R>
724  friend class TrackProxy;
725 
726  private:
729  IndexType itrack)
730  : m_container{&container}, m_index{itrack} {}
731 
732  detail_lt::TransitiveConstPointer<detail_tc::ConstIf<
734  m_container;
736 };
737 } // namespace Acts