Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VectorMultiTrajectory.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file VectorMultiTrajectory.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 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 
21 
22 #include <any>
23 #include <cassert>
24 #include <cstddef>
25 #include <iosfwd>
26 #include <memory>
27 #include <optional>
28 #include <stdexcept>
29 #include <string>
30 #include <type_traits>
31 #include <unordered_map>
32 #include <utility>
33 #include <vector>
34 
35 #include <boost/histogram.hpp>
36 
37 namespace Acts {
38 class Surface;
39 template <typename T>
41 
42 namespace detail_vmt {
43 
47 
49  public:
50  struct Statistics {
51  using axis_t = boost::histogram::axis::variant<
52  boost::histogram::axis::category<std::string>,
53  boost::histogram::axis::category<>>;
54 
55  using axes_t = std::vector<axis_t>;
56  using hist_t = boost::histogram::histogram<axes_t>;
57 
59 
60  void toStream(std::ostream& os, size_t n = 1);
61  };
62 
63  template <typename T>
64  Statistics statistics(T& instance) const {
65  using namespace boost::histogram;
66  using cat = axis::category<std::string>;
67 
68  Statistics::axes_t axes;
69  axes.emplace_back(cat({
70  "count",
71  "index",
72  "parPred",
73  "covPred",
74  "parFilt",
75  "covFilt",
76  "parSmth",
77  "covSmth",
78  "meas",
79  "measOffset",
80  "measCov",
81  "measCovOffset",
82  "jac",
83  "sourceLinks",
84  "projectors",
85  }));
86 
87  axes.emplace_back(axis::category<>({0, 1}));
88 
89  auto h = make_histogram(axes);
90 
91  for (IndexType i = 0; i < instance.size(); i++) {
92  auto ts = instance.getTrackState(i);
93 
94  bool isMeas = ts.typeFlags().test(TrackStateFlag::MeasurementFlag);
95 
96  h("count", isMeas);
97 
98  h("index", isMeas, weight(sizeof(IndexData)));
99 
100  using scalar = typename decltype(ts.predicted())::Scalar;
101  size_t par_size = eBoundSize * sizeof(scalar);
102  size_t cov_size = eBoundSize * eBoundSize * sizeof(scalar);
103 
104  const IndexData& index = m_index[i];
105  if (ts.hasPredicted() &&
106  ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Predicted)) {
107  h("parPred", isMeas, weight(par_size));
108  h("covPred", isMeas, weight(cov_size));
109  }
110  if (ts.hasFiltered() &&
111  ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Filtered)) {
112  h("parFilt", isMeas, weight(par_size));
113  h("covFilt", isMeas, weight(cov_size));
114  }
115  if (ts.hasSmoothed() &&
116  ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Smoothed)) {
117  h("parSmth", isMeas, weight(par_size));
118  h("covSmth", isMeas, weight(cov_size));
119  }
120  h("sourceLinks", isMeas, weight(sizeof(SourceLink)));
121  h("measOffset", isMeas,
122  weight(sizeof(decltype(m_measOffset)::value_type)));
123  h("measCovOffset", isMeas,
124  weight(sizeof(decltype(m_measCovOffset)::value_type)));
125  if (ts.hasCalibrated() &&
126  ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Calibrated)) {
127  size_t meas_size = ts.calibratedSize() * sizeof(scalar);
128  size_t meas_cov_size =
129  ts.calibratedSize() * ts.calibratedSize() * sizeof(scalar);
130 
131  h("meas", isMeas, weight(meas_size));
132  h("measCov", isMeas, weight(meas_cov_size));
133  h("sourceLinks", isMeas, weight(sizeof(const SourceLink)));
134  h("projectors", isMeas, weight(sizeof(ProjectorBitset)));
135  }
136 
137  if (ts.hasJacobian() &&
138  ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Jacobian)) {
139  h("jac", isMeas, weight(cov_size));
140  }
141  }
142 
143  return Statistics{h};
144  }
145 
146  protected:
147  struct IndexData {
153 
154  double chi2 = 0;
155  double pathLength = 0;
157 
161 
162  TrackStatePropMask allocMask = TrackStatePropMask::None;
163  };
164 
165  VectorMultiTrajectoryBase() = default;
166 
168  : m_index{other.m_index},
169  m_previous{other.m_previous},
170  m_next{other.m_next},
171  m_params{other.m_params},
172  m_cov{other.m_cov},
173  m_meas{other.m_meas},
174  m_measOffset{other.m_measOffset},
175  m_measCov{other.m_measCov},
176  m_measCovOffset{other.m_measCovOffset},
177  m_jac{other.m_jac},
178  m_sourceLinks{other.m_sourceLinks},
179  m_projectors{other.m_projectors},
180  m_referenceSurfaces{other.m_referenceSurfaces} {
181  for (const auto& [key, value] : other.m_dynamic) {
182  m_dynamic.insert({key, value->clone()});
183  }
184  };
185 
187 
188  // BEGIN INTERFACE HELPER
189  template <typename T>
190  static constexpr bool has_impl(T& instance, HashedString key,
191  IndexType istate) {
192  using namespace Acts::HashedStringLiteral;
193  switch (key) {
194  case "predicted"_hash:
195  return instance.m_index[istate].ipredicted != kInvalid;
196  case "filtered"_hash:
197  return instance.m_index[istate].ifiltered != kInvalid;
198  case "smoothed"_hash:
199  return instance.m_index[istate].ismoothed != kInvalid;
200  case "calibrated"_hash:
201  return instance.m_measOffset[istate] != kInvalid;
202  case "calibratedCov"_hash:
203  return instance.m_measCovOffset[istate] != kInvalid;
204  case "jacobian"_hash:
205  return instance.m_index[istate].ijacobian != kInvalid;
206  case "projector"_hash:
207  return instance.m_index[istate].iprojector != kInvalid;
208  case "uncalibratedSourceLink"_hash:
209  return instance.m_sourceLinks[instance.m_index[istate].iuncalibrated]
210  .has_value();
211  case "previous"_hash:
212  case "next"_hash:
213  case "referenceSurface"_hash:
214  case "measdim"_hash:
215  case "chi2"_hash:
216  case "pathLength"_hash:
217  case "typeFlags"_hash:
218  return true;
219  default:
220  return instance.m_dynamic.find(key) != instance.m_dynamic.end();
221  }
222  }
223 
224  template <bool EnsureConst, typename T>
225  static std::any component_impl(T& instance, HashedString key,
226  IndexType istate) {
227  if constexpr (EnsureConst) {
228  static_assert(std::is_const_v<std::remove_reference_t<T>>,
229  "Is not const");
230  }
231  using namespace Acts::HashedStringLiteral;
232  switch (key) {
233  case "previous"_hash:
234  return &instance.m_previous[istate];
235  case "next"_hash:
236  return &instance.m_next[istate];
237  case "predicted"_hash:
238  return &instance.m_index[istate].ipredicted;
239  case "filtered"_hash:
240  return &instance.m_index[istate].ifiltered;
241  case "smoothed"_hash:
242  return &instance.m_index[istate].ismoothed;
243  case "projector"_hash:
244  return &instance.m_projectors[instance.m_index[istate].iprojector];
245  case "measdim"_hash:
246  return &instance.m_index[istate].measdim;
247  case "chi2"_hash:
248  return &instance.m_index[istate].chi2;
249  case "pathLength"_hash:
250  return &instance.m_index[istate].pathLength;
251  case "typeFlags"_hash:
252  return &instance.m_index[istate].typeFlags;
253  default:
254  auto it = instance.m_dynamic.find(key);
255  if (it == instance.m_dynamic.end()) {
256  throw std::runtime_error("Unable to handle this component");
257  }
258  std::conditional_t<EnsureConst, const detail::DynamicColumnBase*,
259  detail::DynamicColumnBase*>
260  col = it->second.get();
261  assert(col && "Dynamic column is null");
262  return col->get(istate);
263  }
264  }
265 
266  template <typename T>
267  static constexpr bool hasColumn_impl(T& instance, HashedString key) {
268  using namespace Acts::HashedStringLiteral;
269  switch (key) {
270  case "predicted"_hash:
271  case "filtered"_hash:
272  case "smoothed"_hash:
273  case "calibrated"_hash:
274  case "calibratedCov"_hash:
275  case "jacobian"_hash:
276  case "projector"_hash:
277  case "previous"_hash:
278  case "next"_hash:
279  case "uncalibratedSourceLink"_hash:
280  case "referenceSurface"_hash:
281  case "measdim"_hash:
282  case "chi2"_hash:
283  case "pathLength"_hash:
284  case "typeFlags"_hash:
285  return true;
286  default:
287  return instance.m_dynamic.find(key) != instance.m_dynamic.end();
288  }
289  }
290 
291  // END INTERFACE HELPER
292 
293  public:
295  return m_index[istate].measdim;
296  }
297 
299  return m_sourceLinks[m_index[istate].iuncalibrated].value();
300  }
301 
302  const Surface* referenceSurface_impl(IndexType istate) const {
303  return m_referenceSurfaces[istate].get();
304  }
305 
306  protected:
308  std::vector<IndexData> m_index;
309  std::vector<IndexType> m_previous;
310  std::vector<IndexType> m_next;
311  std::vector<typename detail_lt::Types<eBoundSize>::Coefficients> m_params;
313 
314  std::vector<double> m_meas;
315  std::vector<MultiTrajectoryTraits::IndexType> m_measOffset;
316  std::vector<double> m_measCov;
317  std::vector<MultiTrajectoryTraits::IndexType> m_measCovOffset;
318 
320  std::vector<std::optional<SourceLink>> m_sourceLinks;
321  std::vector<ProjectorBitset> m_projectors;
322 
323  // owning vector of shared pointers to surfaces
324  //
325  // This might be problematic when appending a large number of surfaces
326  // trackstates, because vector has to reallocated and thus copy. This might
327  // be handled in a smart way by moving but not sure.
328  std::vector<std::shared_ptr<const Surface>> m_referenceSurfaces;
329 
330  std::unordered_map<HashedString, std::unique_ptr<detail::DynamicColumnBase>>
332 };
333 
334 } // namespace detail_vmt
335 
337 
338 template <>
340 
343  public MultiTrajectory<VectorMultiTrajectory> {
344 #ifndef DOXYGEN
346 #endif
347 
348  public:
349  VectorMultiTrajectory() = default;
351  : VectorMultiTrajectoryBase{other} {}
352 
353  VectorMultiTrajectory(VectorMultiTrajectory&& other)
355 
356  Statistics statistics() const {
358  }
359 
360  // BEGIN INTERFACE
361  TrackStateProxy::Parameters parameters_impl(IndexType parIdx) {
362  return TrackStateProxy::Parameters{m_params[parIdx].data()};
363  }
364 
365  ConstTrackStateProxy::Parameters parameters_impl(IndexType parIdx) const {
366  return ConstTrackStateProxy::Parameters{m_params[parIdx].data()};
367  }
368 
369  TrackStateProxy::Covariance covariance_impl(IndexType parIdx) {
370  return TrackStateProxy::Covariance{m_cov[parIdx].data()};
371  }
372 
373  ConstTrackStateProxy::Covariance covariance_impl(IndexType parIdx) const {
374  return ConstTrackStateProxy::Covariance{m_cov[parIdx].data()};
375  }
376 
377  TrackStateProxy::Covariance jacobian_impl(IndexType istate) {
378  IndexType jacIdx = m_index[istate].ijacobian;
379  return TrackStateProxy::Covariance{m_jac[jacIdx].data()};
380  }
381 
382  ConstTrackStateProxy::Covariance jacobian_impl(IndexType istate) const {
383  IndexType jacIdx = m_index[istate].ijacobian;
384  return ConstTrackStateProxy::Covariance{m_jac[jacIdx].data()};
385  }
386 
387  template <size_t measdim>
388  TrackStateProxy::Measurement<measdim> measurement_impl(IndexType istate) {
389  IndexType offset = m_measOffset[istate];
390  return TrackStateProxy::Measurement<measdim>{&m_meas[offset]};
391  }
392 
393  template <size_t measdim>
394  ConstTrackStateProxy::Measurement<measdim> measurement_impl(
395  IndexType istate) const {
396  IndexType offset = m_measOffset[istate];
397  return ConstTrackStateProxy::Measurement<measdim>{&m_meas[offset]};
398  }
399 
400  template <size_t measdim>
401  TrackStateProxy::MeasurementCovariance<measdim> measurementCovariance_impl(
402  IndexType istate) {
403  IndexType offset = m_measCovOffset[istate];
404  return TrackStateProxy::MeasurementCovariance<measdim>{&m_measCov[offset]};
405  }
406 
407  template <size_t measdim>
408  ConstTrackStateProxy::MeasurementCovariance<measdim>
409  measurementCovariance_impl(IndexType istate) const {
410  IndexType offset = m_measCovOffset[istate];
411  return ConstTrackStateProxy::MeasurementCovariance<measdim>{
412  &m_measCov[offset]};
413  }
414 
415  IndexType addTrackState_impl(
416  TrackStatePropMask mask = TrackStatePropMask::All,
417  IndexType iprevious = kInvalid);
418 
419  void reserve(std::size_t n);
420 
421  void shareFrom_impl(IndexType iself, IndexType iother,
422  TrackStatePropMask shareSource,
423  TrackStatePropMask shareTarget);
424 
425  void unset_impl(TrackStatePropMask target, IndexType istate);
426 
427  constexpr bool has_impl(HashedString key, IndexType istate) const {
428  return detail_vmt::VectorMultiTrajectoryBase::has_impl(*this, key, istate);
429  }
430 
432  return m_index.size();
433  }
434 
435  void clear_impl();
436 
437  std::any component_impl(HashedString key, IndexType istate) {
438  return detail_vmt::VectorMultiTrajectoryBase::component_impl<false>(
439  *this, key, istate);
440  }
441 
442  std::any component_impl(HashedString key, IndexType istate) const {
443  return detail_vmt::VectorMultiTrajectoryBase::component_impl<true>(
444  *this, key, istate);
445  }
446 
447  template <typename T>
448  constexpr void addColumn_impl(const std::string& key) {
449  m_dynamic.insert(
450  {hashString(key), std::make_unique<detail::DynamicColumn<T>>()});
451  }
452 
453  constexpr bool hasColumn_impl(HashedString key) const {
455  }
456 
457  void allocateCalibrated_impl(IndexType istate, size_t measdim) {
458  throw_assert(measdim > 0 && measdim <= eBoundSize,
459  "Invalid measurement dimension detected");
460 
461  if (m_measOffset[istate] != kInvalid &&
462  m_measCovOffset[istate] != kInvalid &&
463  m_index[istate].measdim == measdim) {
464  return;
465  }
466 
467  m_index[istate].measdim = measdim;
468 
469  m_measOffset[istate] = static_cast<IndexType>(m_meas.size());
470  m_meas.resize(m_meas.size() + measdim);
471 
472  m_measCovOffset[istate] = static_cast<IndexType>(m_measCov.size());
473  m_measCov.resize(m_measCov.size() + measdim * measdim);
474  }
475 
477  m_sourceLinks[m_index[istate].iuncalibrated] = std::move(sourceLink);
478  }
479 
480  void setReferenceSurface_impl(IndexType istate,
481  std::shared_ptr<const Surface> surface) {
482  m_referenceSurfaces[istate] = std::move(surface);
483  }
484 
485  // END INTERFACE
486 };
487 
488 ACTS_STATIC_CHECK_CONCEPT(MutableMultiTrajectoryBackend, VectorMultiTrajectory);
489 
490 class ConstVectorMultiTrajectory;
491 
492 template <>
494 };
495 
498  public MultiTrajectory<ConstVectorMultiTrajectory> {
499 #ifndef DOXYGEN
501 #endif
502 
503  public:
504  ConstVectorMultiTrajectory() = default;
505 
507  : VectorMultiTrajectoryBase{other} {}
508 
509  ConstVectorMultiTrajectory(const VectorMultiTrajectory& other)
510  : VectorMultiTrajectoryBase{other} {}
511 
512  ConstVectorMultiTrajectory(VectorMultiTrajectory&& other)
514 
515  ConstVectorMultiTrajectory(ConstVectorMultiTrajectory&&) = default;
516 
519  }
520 
521  // BEGIN INTERFACE
522 
524  return ConstTrackStateProxy::Parameters{m_params[parIdx].data()};
525  }
526 
528  return ConstTrackStateProxy::Covariance{m_cov[parIdx].data()};
529  }
530 
532  IndexType jacIdx = m_index[istate].ijacobian;
533  return ConstTrackStateProxy::Covariance{m_jac[jacIdx].data()};
534  }
535 
536  template <size_t measdim>
538  IndexType istate) const {
539  IndexType offset = m_measOffset[istate];
541  }
542 
543  template <size_t measdim>
544  ConstTrackStateProxy::MeasurementCovariance<measdim>
546  IndexType offset = m_measCovOffset[istate];
548  &m_measCov[offset]};
549  }
550 
551  constexpr bool has_impl(HashedString key, IndexType istate) const {
552  return detail_vmt::VectorMultiTrajectoryBase::has_impl(*this, key, istate);
553  }
554 
556  return m_index.size();
557  }
558 
559  std::any component_impl(HashedString key, IndexType istate) const {
560  return detail_vmt::VectorMultiTrajectoryBase::component_impl<true>(
561  *this, key, istate);
562  }
563 
564  constexpr bool hasColumn_impl(HashedString key) const {
566  }
567 
568  // END INTERFACE
569 };
570 
571 ACTS_STATIC_CHECK_CONCEPT(ConstMultiTrajectoryBackend,
572  ConstVectorMultiTrajectory);
573 
574 } // namespace Acts