EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultiTrajectory.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MultiTrajectory.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
16 
17 #include <bitset>
18 #include <cstdint>
19 #include <type_traits>
20 #include <vector>
21 
22 #include <Eigen/Core>
23 
24 namespace Acts {
25 
33  HoleFlag = 3,
36 };
37 
38 using TrackStateType = std::bitset<TrackStateFlag::NumTrackStateFlags>;
39 
40 // forward declarations
41 template <typename source_link_t>
43 class Surface;
44 
45 namespace detail_lt {
47 template <typename T, bool select>
48 using ConstIf = std::conditional_t<select, const T, T>;
52 template <typename Storage, size_t kSizeIncrement>
59  auto addCol(size_t n = 1) {
60  size_t index = m_size + (n - 1);
61  while (capacity() <= index) {
62  data.conservativeResize(Eigen::NoChange, data.cols() + kSizeIncrement);
63  }
64  m_size = index + 1;
65 
66  // @TODO: do this or not? If we assume this happens only when something is
67  // written, the expectation is that everything is zero
68  data.col(index).setZero();
69 
70  return data.col(index);
71  }
72 
74  auto col(size_t index) { return data.col(index); }
75 
77  auto col(size_t index) const { return data.col(index); }
78 
80  size_t capacity() const { return static_cast<size_t>(data.cols()); }
81 
82  size_t size() const { return m_size; }
83 
84  private:
85  Storage data;
86  size_t m_size{0};
87 };
88 
90 template <size_t Size, bool ReadOnlyMaps = true>
91 struct Types {
92  enum {
93  Flags = Eigen::ColMajor | Eigen::AutoAlign,
95  };
96  using Scalar = double;
97  // single items
98  using Coefficients = Eigen::Matrix<Scalar, Size, 1, Flags>;
99  using Covariance = Eigen::Matrix<Scalar, Size, Size, Flags>;
100  using CoefficientsMap = Eigen::Map<ConstIf<Coefficients, ReadOnlyMaps>>;
101  using CovarianceMap = Eigen::Map<ConstIf<Covariance, ReadOnlyMaps>>;
102  // storage of multiple items in flat arrays
103  using StorageCoefficients =
106  using StorageCovariance =
109 };
110 
111 struct IndexData {
113 
114  static constexpr IndexType kInvalid = UINT16_MAX;
115 
123 
124  double chi2;
125  double pathLength;
127 
132 };
133 
139 template <typename source_link_t, size_t M, bool ReadOnly = true>
141  public:
142  using SourceLink = source_link_t;
147 
148  // as opposed to the types above, this is an actual Matrix (rather than a
149  // map)
150  // @TODO: Does not copy flags, because this fails: can't have col major row
151  // vector, but that's required for 1xN projection matrices below.
152  constexpr static auto ProjectorFlags = Eigen::RowMajor | Eigen::AutoAlign;
153  using Projector =
154  Eigen::Matrix<typename Covariance::Scalar, M, eBoundSize, ProjectorFlags>;
155  using EffectiveProjector =
156  Eigen::Matrix<typename Projector::Scalar, Eigen::Dynamic, Eigen::Dynamic,
158 
161  size_t index() const { return m_istate; }
162 
165  size_t previous() const { return data().iprevious; }
166 
170  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
172  return m_traj->m_index[m_istate];
173  }
174 
178  TrackStatePropMask getMask() const;
179 
187  template <bool RO = ReadOnly, bool ReadOnlyOther,
188  typename = std::enable_if<!RO>>
190  TrackStatePropMask mask = TrackStatePropMask::All) {
191  using PM = TrackStatePropMask;
192  auto dest = getMask();
193  auto src = other.getMask() &
194  mask; // combine what we have with what we want to copy
195  if (static_cast<std::underlying_type_t<TrackStatePropMask>>((src ^ dest) &
196  src) != 0) {
197  throw std::runtime_error(
198  "Attempt track state copy with incompatible allocations");
199  }
200 
201  // we're sure now this has correct allocations, so just copy
202  if (ACTS_CHECK_BIT(src, PM::Predicted)) {
203  predicted() = other.predicted();
205  }
206 
207  if (ACTS_CHECK_BIT(src, PM::Filtered)) {
208  filtered() = other.filtered();
210  }
211 
212  if (ACTS_CHECK_BIT(src, PM::Smoothed)) {
213  smoothed() = other.smoothed();
215  }
216 
217  if (ACTS_CHECK_BIT(src, PM::Uncalibrated)) {
218  uncalibrated() = other.uncalibrated();
219  }
220 
221  if (ACTS_CHECK_BIT(src, PM::Jacobian)) {
222  jacobian() = other.jacobian();
223  }
224 
225  if (ACTS_CHECK_BIT(src, PM::Calibrated)) {
227  calibrated() = other.calibrated();
229  data().measdim = other.data().measdim;
231  }
232 
233  chi2() = other.chi2();
234  pathLength() = other.pathLength();
235  typeFlags() = other.typeFlags();
236 
237  // can be nullptr, but we just take that
239  }
240 
243  const IndexData& data() const { return m_traj->m_index[m_istate]; }
244 
247  const Surface& referenceSurface() const {
248  assert(data().irefsurface != IndexData::kInvalid);
249  return *m_traj->m_referenceSurfaces[data().irefsurface];
250  }
251 
255  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
256  void setReferenceSurface(std::shared_ptr<const Surface> srf) {
257  m_traj->m_referenceSurfaces[data().irefsurface] = std::move(srf);
258  }
259 
264  Parameters parameters() const;
265 
271  Covariance covariance() const;
272 
275  Parameters predicted() const;
276 
280 
283  bool hasPredicted() const { return data().ipredicted != IndexData::kInvalid; }
284 
287  Parameters filtered() const;
288 
292 
295  bool hasFiltered() const { return data().ifiltered != IndexData::kInvalid; }
296 
299  Parameters smoothed() const;
300 
304 
307  bool hasSmoothed() const { return data().ismoothed != IndexData::kInvalid; }
308 
311  Covariance jacobian() const;
312 
315  bool hasJacobian() const { return data().ijacobian != IndexData::kInvalid; }
316 
324  Projector projector() const;
325 
328  bool hasProjector() const { return data().iprojector != IndexData::kInvalid; }
329 
337  return projector().topLeftCorner(data().measdim, M);
338  }
339 
345  template <typename Derived, bool RO = ReadOnly,
346  typename = std::enable_if_t<!RO>>
347  void setProjector(const Eigen::MatrixBase<Derived>& projector) {
348  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
349  constexpr int cols = Eigen::MatrixBase<Derived>::ColsAtCompileTime;
350 
351  static_assert(rows != -1 && cols != -1,
352  "Assignment of dynamic matrices is currently not supported.");
353 
354  IndexData& dataref = data();
355  assert(dataref.iprojector != IndexData::kInvalid);
356 
357  static_assert(rows <= M, "Given projector has too many rows");
358  static_assert(cols <= eBoundSize, "Given projector has too many columns");
359 
360  // set up full size projector with only zeros
361  typename TrackStateProxy::Projector fullProjector =
362  decltype(fullProjector)::Zero();
363 
364  // assign (potentially) smaller actual projector to matrix, preserving
365  // zeroes outside of smaller matrix block.
366  fullProjector.template topLeftCorner<rows, cols>() = projector;
367 
368  // convert to bitset before storing
369  m_traj->m_projectors[dataref.iprojector] = matrixToBitset(fullProjector);
370  }
371 
374  bool hasUncalibrated() const {
376  }
377 
380  const SourceLink& uncalibrated() const;
381 
385  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
387  assert(data().iuncalibrated != IndexData::kInvalid);
388  return m_traj->m_sourceLinks[data().iuncalibrated];
389  }
390 
393  bool hasCalibrated() const {
395  }
396 
400  const SourceLink& calibratedSourceLink() const;
401 
406  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
408  assert(data().icalibratedsourcelink != IndexData::kInvalid);
409  return m_traj->m_sourceLinks[data().icalibratedsourcelink];
410  }
411 
415  Measurement calibrated() const;
416 
421 
424  auto effectiveCalibrated() const { return calibrated().head(data().measdim); }
425 
429  return calibratedCovariance().topLeftCorner(data().measdim, data().measdim);
430  }
431 
436  size_t calibratedSize() const { return data().measdim; }
437 
445  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>,
446  BoundIndices... params>
449  IndexData& dataref = data();
450  constexpr size_t measdim =
452 
453  dataref.measdim = measdim;
454 
455  assert(hasCalibrated());
456  calibrated().setZero();
457  calibrated().template head<measdim>() = meas.parameters();
458 
459  calibratedCovariance().setZero();
460  calibratedCovariance().template topLeftCorner<measdim, measdim>() =
461  meas.covariance();
462 
463  setProjector(meas.projector());
464 
465  // this shouldn't change
466  assert(data().irefsurface != IndexData::kInvalid);
467  std::shared_ptr<const Surface>& refSrf =
468  m_traj->m_referenceSurfaces[dataref.irefsurface];
469  // either unset, or the same, otherwise this is inconsistent assignment
470  assert(!refSrf || refSrf.get() == &meas.referenceObject());
471  if (!refSrf) {
472  // ref surface is not set, set it now
473  refSrf = meas.referenceObject().getSharedPtr();
474  }
475 
476  assert(dataref.icalibratedsourcelink != IndexData::kInvalid);
477  calibratedSourceLink() = meas.sourceLink();
478  }
479 
486  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>,
487  BoundIndices... params>
490  IndexData& dataref = data();
491  auto& traj = *m_traj;
492  // force reallocate, whether currently invalid or shared index
493  traj.m_meas.addCol();
494  traj.m_measCov.addCol();
495  // shared index between meas par
496  // and cov
497  dataref.icalibrated = traj.m_meas.size() - 1;
498 
499  traj.m_sourceLinks.emplace_back();
500  dataref.icalibratedsourcelink = traj.m_sourceLinks.size() - 1;
501 
502  traj.m_projectors.emplace_back();
503  dataref.iprojector = traj.m_projectors.size() - 1;
504 
505  // now actually assign to the allocated entries
506  setCalibrated(meas);
507  }
508 
514  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
515  double& chi2() {
516  return data().chi2;
517  }
518 
523  double chi2() const { return data().chi2; }
524 
529  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
530  double& pathLength() {
531  return data().pathLength;
532  }
533 
536  double pathLength() const { return data().pathLength; }
537 
542  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
544  return data().typeFlags;
545  }
546 
549  TrackStateType typeFlags() const { return data().typeFlags; }
550 
551  private:
552  // Private since it can only be created by the trajectory.
553  TrackStateProxy(ConstIf<MultiTrajectory<SourceLink>, ReadOnly>& trajectory,
554  size_t istate);
555 
556  const std::shared_ptr<const Surface>& referenceSurfacePointer() const {
557  assert(data().irefsurface != IndexData::kInvalid);
558  return m_traj->m_referenceSurfaces[data().irefsurface];
559  }
560 
562  const {
563  assert(data().iprojector != IndexData::kInvalid);
564  return m_traj->m_projectors[data().iprojector];
565  }
566 
567  template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
570  assert(data().iprojector != IndexData::kInvalid);
571  m_traj->m_projectors[data().iprojector] = proj;
572  }
573 
575  size_t m_istate;
576 
578 };
579 
580 // implement track state visitor concept
581 template <typename T, typename TS>
582 using call_operator_t = decltype(std::declval<T>()(std::declval<TS>()));
583 
584 template <typename T, typename TS>
586  Concepts ::either<Concepts ::identical_to<bool, call_operator_t, T, TS>,
587  Concepts ::identical_to<void, call_operator_t, T, TS>>>;
588 
589 } // namespace detail_lt
590 
600 template <typename source_link_t>
602  public:
603  enum {
605  };
606  using SourceLink = source_link_t;
607  using ConstTrackStateProxy =
609  using TrackStateProxy =
611 
612  using ProjectorBitset = std::bitset<eBoundSize * MeasurementSizeMax>;
613 
615  MultiTrajectory() = default;
616 
623  size_t addTrackState(TrackStatePropMask mask = TrackStatePropMask::All,
624  size_t iprevious = SIZE_MAX);
625 
629  ConstTrackStateProxy getTrackState(size_t istate) const {
630  return {*this, istate};
631  }
632 
636  TrackStateProxy getTrackState(size_t istate) { return {*this, istate}; }
637 
642  template <typename F>
643  void visitBackwards(size_t iendpoint, F&& callable) const;
644 
652  template <typename F>
653  void applyBackwards(size_t iendpoint, F&& callable);
654 
655  private:
657  std::vector<detail_lt::IndexData> m_index;
663  std::vector<SourceLink> m_sourceLinks;
664  std::vector<ProjectorBitset> m_projectors;
665 
666  // owning vector of shared pointers to surfaces
667  // @TODO: This might be problematic when appending a large number of surfaces
668  // trackstates, because vector has to reallocated and thus copy. This might
669  // be handled in a smart way by moving but not sure.
670  std::vector<std::shared_ptr<const Surface>> m_referenceSurfaces;
671 
675 };
676 
677 } // namespace Acts
678