Skip to content

Commit

Permalink
feat!: MultiTrajectory backends (#1262)
Browse files Browse the repository at this point in the history
This PR decouples the interface of `MultiTrajectory` from the storage backend. The default storage backend is practically identical to the previous implementation, but it's now behind the interface. This change is intended to allow seamless integration with experiment specific EDM backends, like ATLAS' xAOD.

See [these slides](https://indico.cern.ch/event/1145372/contributions/4892312/attachments/2450169/4198806/2022-05-24_tracking-edm-update_v2.pdf) for some more information.

BREAKING CHANGE: The template parameters of `CombinatorialKalmanFilter`, `KalmanFitter` and `GaussianSumFitter` changes to 
```cpp
template <typename propagator_t, typename traj_t>
class CombinatorialKalmanFilter;
template <typename propagator_t, typename traj_t>
class KalmanFitter;
template <typename propagator_t, typename traj_t,
          typename bethe_heitler_approx_t = detail::BetheHeitlerApprox<6, 5>>
struct GaussianSumFitter;
```

Related classes (options, extensions, result) also change, gaining a `traj_t` template parameter. This parameter is the type of the memory backend.
  • Loading branch information
paulgessinger committed Aug 3, 2022
1 parent e72db5d commit 5cbcbf0
Show file tree
Hide file tree
Showing 55 changed files with 2,447 additions and 1,215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ void resetAlignmentDerivative(Acts::AlignmentToBoundMatrix& alignToBound,
///
/// @return The track alignment state containing fundamental alignment
/// ingredients
template <typename parameters_t = BoundTrackParameters>
template <typename traj_t, typename parameters_t = BoundTrackParameters>
TrackAlignmentState trackAlignmentState(
const GeometryContext& gctx, const Acts::MultiTrajectory& multiTraj,
const GeometryContext& gctx, const Acts::MultiTrajectory<traj_t>& multiTraj,
const size_t& entryIndex,
const std::pair<ActsDynamicMatrix, std::unordered_map<size_t, size_t>>&
globalTrackParamsCov,
Expand Down
820 changes: 545 additions & 275 deletions Core/include/Acts/EventData/MultiTrajectory.hpp

Large diffs are not rendered by default.

244 changes: 97 additions & 147 deletions Core/include/Acts/EventData/MultiTrajectory.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@

namespace Acts {
namespace detail_lt {
template <size_t M, bool ReadOnly>
inline TrackStateProxy<M, ReadOnly>::TrackStateProxy(
ConstIf<MultiTrajectory, ReadOnly>& trajectory, size_t istate)
template <typename D, size_t M, bool ReadOnly>
inline TrackStateProxy<D, M, ReadOnly>::TrackStateProxy(
ConstIf<MultiTrajectory<D>, ReadOnly>& trajectory, IndexType istate)
: m_traj(&trajectory), m_istate(istate) {}

template <size_t M, bool ReadOnly>
TrackStatePropMask TrackStateProxy<M, ReadOnly>::getMask() const {
template <typename D, size_t M, bool ReadOnly>
TrackStatePropMask TrackStateProxy<D, M, ReadOnly>::getMask() const {
using PM = TrackStatePropMask;

PM mask = PM::None;
Expand All @@ -40,233 +40,183 @@ TrackStatePropMask TrackStateProxy<M, ReadOnly>::getMask() const {
if (hasJacobian()) {
mask |= PM::Jacobian;
}
if (hasUncalibrated()) {
mask |= PM::Uncalibrated;
}
if (hasCalibrated()) {
mask |= PM::Calibrated;
}
return mask;
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::parameters() const -> Parameters {
IndexData::IndexType idx;
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::parameters() const -> Parameters {
if (hasSmoothed()) {
idx = data().ismoothed;
return smoothed();
} else if (hasFiltered()) {
idx = data().ifiltered;
return filtered();
} else {
idx = data().ipredicted;
return predicted();
}

return Parameters(m_traj->m_params.col(idx).data());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::covariance() const -> Covariance {
IndexData::IndexType idx;
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::covariance() const -> Covariance {
if (hasSmoothed()) {
idx = data().ismoothed;
return smoothedCovariance();
} else if (hasFiltered()) {
idx = data().ifiltered;
return filteredCovariance();
} else {
idx = data().ipredicted;
return predictedCovariance();
}
return Covariance(m_traj->m_cov.col(idx).data());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::predicted() const -> Parameters {
assert(data().ipredicted != IndexData::kInvalid);
return Parameters(m_traj->m_params.col(data().ipredicted).data());
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::predicted() const -> Parameters {
assert(has<hashString("predicted")>());
return m_traj->self().parameters(
component<IndexType, hashString("predicted")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::predictedCovariance() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::predictedCovariance() const
-> Covariance {
assert(data().ipredicted != IndexData::kInvalid);
return Covariance(m_traj->m_cov.col(data().ipredicted).data());
assert(has<hashString("predicted")>());
return m_traj->self().covariance(
component<IndexType, hashString("predicted")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::filtered() const -> Parameters {
assert(data().ifiltered != IndexData::kInvalid);
return Parameters(m_traj->m_params.col(data().ifiltered).data());
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::filtered() const -> Parameters {
assert(has<hashString("filtered")>());
return m_traj->self().parameters(
component<IndexType, hashString("filtered")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::filteredCovariance() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::filteredCovariance() const
-> Covariance {
assert(data().ifiltered != IndexData::kInvalid);
return Covariance(m_traj->m_cov.col(data().ifiltered).data());
assert(has<hashString("filtered")>());
return m_traj->self().covariance(
component<IndexType, hashString("filtered")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::smoothed() const -> Parameters {
assert(data().ismoothed != IndexData::kInvalid);
return Parameters(m_traj->m_params.col(data().ismoothed).data());
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::smoothed() const -> Parameters {
assert(has<hashString("smoothed")>());
return m_traj->self().parameters(
component<IndexType, hashString("smoothed")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::smoothedCovariance() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::smoothedCovariance() const
-> Covariance {
assert(data().ismoothed != IndexData::kInvalid);
return Covariance(m_traj->m_cov.col(data().ismoothed).data());
assert(has<hashString("smoothed")>());
return m_traj->self().covariance(
component<IndexType, hashString("smoothed")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::jacobian() const -> Covariance {
assert(data().ijacobian != IndexData::kInvalid);
return Covariance(m_traj->m_jac.col(data().ijacobian).data());
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::jacobian() const -> Covariance {
assert(has<hashString("jacobian")>());
return m_traj->self().jacobian(
component<IndexType, hashString("jacobian")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::projector() const -> Projector {
assert(data().iprojector != IndexData::kInvalid);
return bitsetToMatrix<Projector>(m_traj->m_projectors[data().iprojector]);
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::projector() const -> Projector {
assert(has<hashString("projector")>());
return bitsetToMatrix<Projector>(
component<ProjectorBitset, hashString("projector")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::uncalibrated() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::uncalibrated() const
-> const SourceLink& {
assert(data().iuncalibrated != IndexData::kInvalid);
assert(m_traj->m_sourceLinks[data().iuncalibrated] != nullptr);
return *m_traj->m_sourceLinks[data().iuncalibrated];
assert(has<hashString("uncalibrated")>());
using T = const SourceLink*;
const T& sl = component<const SourceLink*, hashString("uncalibrated")>();
assert(sl != nullptr);
return *sl;
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::calibrated() const -> Measurement {
assert(data().icalibrated != IndexData::kInvalid);
return Measurement(m_traj->m_meas.col(data().icalibrated).data());
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::calibrated() const -> Measurement {
assert(has<hashString("calibrated")>());
return m_traj->self().measurement(
component<IndexType, hashString("calibrated")>());
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::calibratedSourceLink() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::calibratedSourceLink() const
-> const SourceLink& {
assert(data().icalibratedsourcelink != IndexData::kInvalid);
assert(m_traj->m_sourceLinks[data().icalibratedsourcelink] != nullptr);
return *m_traj->m_sourceLinks[data().icalibratedsourcelink];
assert(has<hashString("calibratedSourceLink")>());
using T = const SourceLink*;
const T& sl =
component<const SourceLink*, hashString("calibratedSourceLink")>();
assert(sl != nullptr);
return *sl;
}

template <size_t M, bool ReadOnly>
inline auto TrackStateProxy<M, ReadOnly>::calibratedCovariance() const
template <typename D, size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::calibratedCovariance() const
-> MeasurementCovariance {
assert(data().icalibrated != IndexData::kInvalid);
return MeasurementCovariance(
m_traj->m_measCov.col(data().icalibrated).data());
assert(has<hashString("calibrated")>());
return m_traj->self().measurementCovariance(
component<IndexType, hashString("calibrated")>());
}

} // namespace detail_lt

inline size_t MultiTrajectory::addTrackState(TrackStatePropMask mask,
size_t iprevious) {
using PropMask = TrackStatePropMask;

m_index.emplace_back();
detail_lt::IndexData& p = m_index.back();
size_t index = m_index.size() - 1;

if (iprevious != SIZE_MAX) {
p.iprevious = static_cast<uint16_t>(iprevious);
}

// always set, but can be null
m_referenceSurfaces.emplace_back(nullptr);
p.irefsurface = m_referenceSurfaces.size() - 1;

if (ACTS_CHECK_BIT(mask, PropMask::Predicted)) {
m_params.addCol();
m_cov.addCol();
p.ipredicted = m_params.size() - 1;
}

if (ACTS_CHECK_BIT(mask, PropMask::Filtered)) {
m_params.addCol();
m_cov.addCol();
p.ifiltered = m_params.size() - 1;
}

if (ACTS_CHECK_BIT(mask, PropMask::Smoothed)) {
m_params.addCol();
m_cov.addCol();
p.ismoothed = m_params.size() - 1;
}

if (ACTS_CHECK_BIT(mask, PropMask::Jacobian)) {
m_jac.addCol();
p.ijacobian = m_jac.size() - 1;
}

if (ACTS_CHECK_BIT(mask, PropMask::Uncalibrated)) {
m_sourceLinks.emplace_back();
p.iuncalibrated = m_sourceLinks.size() - 1;
}

if (ACTS_CHECK_BIT(mask, PropMask::Calibrated)) {
m_meas.addCol();
m_measCov.addCol();
p.icalibrated = m_meas.size() - 1;

m_sourceLinks.emplace_back();
p.icalibratedsourcelink = m_sourceLinks.size() - 1;

m_projectors.emplace_back();
p.iprojector = m_projectors.size() - 1;
}

return index;
}

template <typename D>
template <typename F>
void MultiTrajectory::visitBackwards(size_t iendpoint, F&& callable) const {
void MultiTrajectory<D>::visitBackwards(IndexType iendpoint,
F&& callable) const {
static_assert(detail_lt::VisitorConcept<F, ConstTrackStateProxy>,
"Callable needs to satisfy VisitorConcept");

while (true) {
auto ts = getTrackState(iendpoint);
if constexpr (std::is_same_v<std::invoke_result_t<F, ConstTrackStateProxy>,
bool>) {
bool proceed = callable(getTrackState(iendpoint));
bool proceed = callable(ts);
// this point has no parent and ends the trajectory, or a break was
// requested
if (m_index[iendpoint].iprevious == detail_lt::IndexData::kInvalid ||
!proceed) {
if (!proceed || !ts.hasPrevious()) {
break;
}
} else {
callable(getTrackState(iendpoint));
callable(ts);
// this point has no parent and ends the trajectory
if (m_index[iendpoint].iprevious == detail_lt::IndexData::kInvalid) {
if (!ts.hasPrevious()) {
break;
}
}
iendpoint = m_index[iendpoint].iprevious;
iendpoint = ts.previous();
}
}

template <typename D>
template <typename F>
void MultiTrajectory::applyBackwards(size_t iendpoint, F&& callable) {
void MultiTrajectory<D>::applyBackwards(IndexType iendpoint, F&& callable) {
static_assert(detail_lt::VisitorConcept<F, TrackStateProxy>,
"Callable needs to satisfy VisitorConcept");

while (true) {
auto ts = getTrackState(iendpoint);
if constexpr (std::is_same_v<std::invoke_result_t<F, TrackStateProxy>,
bool>) {
bool proceed = callable(getTrackState(iendpoint));
bool proceed = callable(ts);
// this point has no parent and ends the trajectory, or a break was
// requested
if (m_index[iendpoint].iprevious == detail_lt::IndexData::kInvalid ||
!proceed) {
if (!proceed || !ts.hasPrevious()) {
break;
}
} else {
callable(getTrackState(iendpoint));
callable(ts);
// this point has no parent and ends the trajectory
if (m_index[iendpoint].iprevious == detail_lt::IndexData::kInvalid) {
if (!ts.hasPrevious()) {
break;
}
}
iendpoint = m_index[iendpoint].iprevious;
iendpoint = ts.previous();
}
}
} // namespace Acts
10 changes: 6 additions & 4 deletions Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ using VolumeTrajectoryStateContainer =
/// @param entryIndex The entry index of trajectory to investigate
///
/// @return The trajectory summary info
inline TrajectoryState trajectoryState(const Acts::MultiTrajectory& multiTraj,
const size_t& entryIndex) {
template <typename traj_t>
TrajectoryState trajectoryState(const Acts::MultiTrajectory<traj_t>& multiTraj,
const size_t& entryIndex) {
TrajectoryState trajState;
multiTraj.visitBackwards(entryIndex, [&](const auto& state) {
// Get the volume Id of this surface
Expand Down Expand Up @@ -93,8 +94,9 @@ inline TrajectoryState trajectoryState(const Acts::MultiTrajectory& multiTraj,
///
/// @return The trajectory summary info at different sub-detectors (i.e.
/// different volumes)
inline VolumeTrajectoryStateContainer trajectoryState(
const Acts::MultiTrajectory& multiTraj, const size_t& entryIndex,
template <typename traj_t>
VolumeTrajectoryStateContainer trajectoryState(
const Acts::MultiTrajectory<traj_t>& multiTraj, const size_t& entryIndex,
const std::vector<GeometryIdentifier::Value>& volumeIds) {
VolumeTrajectoryStateContainer trajStateContainer;
multiTraj.visitBackwards(entryIndex, [&](const auto& state) {
Expand Down
3 changes: 1 addition & 2 deletions Core/include/Acts/EventData/TrackStatePropMask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ enum struct TrackStatePropMask : uint8_t {
Smoothed = 1 << 2,
Jacobian = 1 << 3,

Uncalibrated = 1 << 4,
Calibrated = 1 << 5,
Calibrated = 1 << 4,

All = std::numeric_limits<uint8_t>::max(), // should be all ones
};
Expand Down

0 comments on commit 5cbcbf0

Please sign in to comment.