diff --git a/Core/include/Acts/EventData/MeasurementHelpers.hpp b/Core/include/Acts/EventData/MeasurementHelpers.hpp index 6f046da0bb3..14eec96155a 100644 --- a/Core/include/Acts/EventData/MeasurementHelpers.hpp +++ b/Core/include/Acts/EventData/MeasurementHelpers.hpp @@ -57,4 +57,16 @@ auto visit_measurement(A&& param, B&& cov, size_t dim, L&& lambda) { dim, param, cov, lambda); } +/// Dispatch a generic lambda on a measurement dimension. This overload doesn't +/// assume anything about what is needed inside the lambda, it communicates the +/// dimension via an integral constant type +/// @tparam L The generic lambda type to call +/// @param dim The runtime dimension of the measurement +/// @param lambda The generic lambda instance to call +/// @return Returns the lambda return value +template +auto visit_measurement(size_t dim, L&& lambda) { + return template_switch_lambda<1, eBoundSize>(dim, lambda); +} + } // namespace Acts diff --git a/Core/include/Acts/EventData/MultiTrajectory.hpp b/Core/include/Acts/EventData/MultiTrajectory.hpp index 022a562c4a6..e3d9f0cc5b1 100644 --- a/Core/include/Acts/EventData/MultiTrajectory.hpp +++ b/Core/include/Acts/EventData/MultiTrajectory.hpp @@ -10,6 +10,7 @@ #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/Measurement.hpp" +#include "Acts/EventData/MeasurementHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -67,6 +68,14 @@ struct Types { using Covariance = Eigen::Matrix; using CoefficientsMap = Eigen::Map>; using CovarianceMap = Eigen::Map>; + + using DynamicCoefficients = Eigen::Matrix; + using DynamicCovariance = + Eigen::Matrix; + using DynamicCoefficientsMap = + Eigen::Map>; + using DynamicCovarianceMap = + Eigen::Map>; }; } // namespace detail_lt @@ -101,9 +110,12 @@ class TrackStateProxy { public: using Parameters = typename TrackStateTraits::Parameters; using Covariance = typename TrackStateTraits::Covariance; - using Measurement = typename TrackStateTraits::Measurement; + + template + using Measurement = typename TrackStateTraits::Measurement; + template using MeasurementCovariance = - typename TrackStateTraits::MeasurementCovariance; + typename TrackStateTraits::MeasurementCovariance; using IndexType = typename TrackStateTraits::IndexType; static constexpr IndexType kInvalid = TrackStateTraits::kInvalid; @@ -223,8 +235,17 @@ class TrackStateProxy { auto dest = getMask(); auto src = other.getMask() & mask; // combine what we have with what we want to copy - if (static_cast>((src ^ dest) & - src) != 0) { + + if (ACTS_CHECK_BIT(src, PM::Calibrated)) { + // on-demand allocate calibrated + dest |= PM::Calibrated; + } + + if ((static_cast>( + (src ^ dest) & src) != 0 || + dest == TrackStatePropMask::None || + src == TrackStatePropMask::None) && + mask != TrackStatePropMask::None) { throw std::runtime_error( "Attempt track state copy with incompatible allocations"); } @@ -259,9 +280,19 @@ class TrackStateProxy { component() = other.template component(); - calibrated() = other.calibrated(); - calibratedCovariance() = other.calibratedCovariance(); - calibratedSize() = other.calibratedSize(); + allocateCalibrated(other.calibratedSize()); + + // workaround for gcc8 bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594 + auto* self = this; + visit_measurement(other.calibratedSize(), [&](auto N) { + constexpr int measdim = decltype(N)::value; + self->template calibrated() = + other.template calibrated(); + self->template calibratedCovariance() = + other.template calibratedCovariance(); + }); + setProjectorBitset(other.projectorBitset()); } } else { @@ -303,9 +334,20 @@ class TrackStateProxy { component() = other.template component(); - calibrated() = other.calibrated(); - calibratedCovariance() = other.calibratedCovariance(); - calibratedSize() = other.calibratedSize(); + + allocateCalibrated(other.calibratedSize()); + + // workaround for gcc8 bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594 + auto* self = this; + visit_measurement(other.calibratedSize(), [&](auto N) { + constexpr int measdim = decltype(N)::value; + self->template calibrated() = + other.template calibrated(); + self->template calibratedCovariance() = + other.template calibratedCovariance(); + }); + setProjectorBitset(other.projectorBitset()); } } @@ -578,24 +620,43 @@ class TrackStateProxy { /// Full calibrated measurement vector. Might contain additional zeroed /// dimensions. /// @return The measurement vector - Measurement calibrated() const; + template + Measurement calibrated() const; /// Full calibrated measurement covariance matrix. The effective covariance /// is located in the top left corner, everything else is zeroed. /// @return The measurement covariance matrix - MeasurementCovariance calibratedCovariance() const; + template + MeasurementCovariance calibratedCovariance() const; /// Dynamic measurement vector with only the valid dimensions. /// @return The effective calibrated measurement vector auto effectiveCalibrated() const { - return calibrated().head(calibratedSize()); + // repackage the data pointer to a dynamic map type + // workaround for gcc8 bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594 + auto* self = this; + return visit_measurement(calibratedSize(), [&](auto N) { + constexpr int kMeasurementSize = decltype(N)::value; + return typename Types::DynamicCoefficientsMap{ + self->template calibrated().data(), + kMeasurementSize}; + }); } /// Dynamic measurement covariance matrix with only the valid dimensions. /// @return The effective calibrated covariance matrix auto effectiveCalibratedCovariance() const { - const size_t measdim = calibratedSize(); - return calibratedCovariance().topLeftCorner(measdim, measdim); + // repackage the data pointer to a dynamic map type + // workaround for gcc8 bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86594 + auto* self = this; + return visit_measurement(calibratedSize(), [&](auto N) { + constexpr int kMeasurementSize = decltype(N)::value; + return typename Types::DynamicCovarianceMap{ + self->template calibratedCovariance().data(), + kMeasurementSize, kMeasurementSize}; + }); } /// Return the (dynamic) number of dimensions stored for this measurement. @@ -642,16 +703,24 @@ class TrackStateProxy { (component() != nullptr)); + allocateCalibrated(kMeasurementSize); assert(hasCalibrated()); - calibrated().setZero(); - calibrated().template head() = meas.parameters(); - calibratedCovariance().setZero(); - calibratedCovariance() + + calibrated().setZero(); + calibrated().template head() = + meas.parameters(); + calibratedCovariance().setZero(); + calibratedCovariance() .template topLeftCorner() = meas.covariance(); setProjector(meas.projector()); } + void allocateCalibrated(size_t measdim) { + m_traj->allocateCalibrated(m_istate, measdim); + calibratedSize() = measdim; + } + /// Getter/setter for chi2 value associated with the track state /// This overload returns a mutable reference, which allows setting a new /// value directly into the backing store. @@ -979,39 +1048,47 @@ class MultiTrajectory { } /// Retrieve a measurement proxy instance for a measurement at a given index + /// @tparam measdim the measurement dimension /// @param measIdx Index into the measurement column /// @return Mutable proxy - template > - constexpr typename TrackStateProxy::Measurement measurement( + template > + constexpr typename TrackStateProxy::template Measurement measurement( IndexType measIdx) { - return self().measurement_impl(measIdx); + return self().template measurement_impl(measIdx); } /// Retrieve a measurement proxy instance for a measurement at a given index + /// @tparam measdim the measurement dimension /// @param measIdx Index into the measurement column /// @return Const proxy - constexpr typename ConstTrackStateProxy::Measurement measurement( - IndexType measIdx) const { - return self().measurement_impl(measIdx); + template + constexpr typename ConstTrackStateProxy::template Measurement + measurement(IndexType measIdx) const { + return self().template measurement_impl(measIdx); } /// Retrieve a measurement covariance proxy instance for a measurement at a /// given index + /// @tparam measdim the measurement dimension /// @param covIdx Index into the measurement covariance column /// @return Mutable proxy - template > - constexpr typename TrackStateProxy::MeasurementCovariance + template > + constexpr typename TrackStateProxy::template MeasurementCovariance measurementCovariance(IndexType covIdx) { - return self().measurementCovariance_impl(covIdx); + return self().template measurementCovariance_impl(covIdx); } /// Retrieve a measurement covariance proxy instance for a measurement at a /// given index /// @param covIdx Index into the measurement covariance column /// @return Const proxy - constexpr typename ConstTrackStateProxy::MeasurementCovariance - measurementCovariance(IndexType covIdx) const { - return self().measurementCovariance_impl(covIdx); + template + constexpr + typename ConstTrackStateProxy::template MeasurementCovariance + measurementCovariance(IndexType covIdx) const { + return self().template measurementCovariance_impl(covIdx); } /// Share a shareable component from between track state. @@ -1084,6 +1161,10 @@ class MultiTrajectory { return *std::any_cast(self().component_impl(key, istate)); } + void allocateCalibrated(IndexType istate, size_t measdim) { + self().allocateCalibrated_impl(istate, measdim); + } + private: friend class detail_lt::TrackStateProxy; friend class detail_lt::TrackStateProxy; diff --git a/Core/include/Acts/EventData/MultiTrajectory.ipp b/Core/include/Acts/EventData/MultiTrajectory.ipp index c6b31c8c2ff..670ef375e56 100644 --- a/Core/include/Acts/EventData/MultiTrajectory.ipp +++ b/Core/include/Acts/EventData/MultiTrajectory.ipp @@ -138,9 +138,11 @@ inline auto TrackStateProxy::uncalibrated() const } template -inline auto TrackStateProxy::calibrated() const -> Measurement { +template +inline auto TrackStateProxy::calibrated() const + -> Measurement { assert(has()); - return m_traj->self().measurement( + return m_traj->self().template measurement( component()); } @@ -156,11 +158,12 @@ inline auto TrackStateProxy::calibratedSourceLink() const } template +template inline auto TrackStateProxy::calibratedCovariance() const - -> MeasurementCovariance { - assert(has()); - return m_traj->self().measurementCovariance( - component()); + -> MeasurementCovariance { + assert(has()); + return m_traj->self().template measurementCovariance( + component()); } } // namespace detail_lt diff --git a/Core/include/Acts/EventData/VectorMultiTrajectory.hpp b/Core/include/Acts/EventData/VectorMultiTrajectory.hpp index 0ad9db3b00a..7de4e72fc37 100644 --- a/Core/include/Acts/EventData/VectorMultiTrajectory.hpp +++ b/Core/include/Acts/EventData/VectorMultiTrajectory.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" @@ -54,7 +55,9 @@ class VectorMultiTrajectoryBase { "parSmth", "covSmth", "meas", + "measOffset", "measCov", + "measCovOffset", "jac", "sourceLinks", "projectors", @@ -93,13 +96,18 @@ class VectorMultiTrajectoryBase { h("parSmth", isMeas, weight(par_size)); h("covSmth", isMeas, weight(cov_size)); } - - size_t meas_size = eBoundSize * sizeof(scalar); - size_t meas_cov_size = eBoundSize * eBoundSize * sizeof(scalar); - h("sourceLinks", isMeas, weight(sizeof(const SourceLink*))); + h("measOffset", isMeas, + weight(sizeof(decltype(m_measOffset)::value_type))); + h("measCovOffset", isMeas, + weight(sizeof(decltype(m_measCovOffset)::value_type))); + if (ts.hasCalibrated() && ACTS_CHECK_BIT(index.allocMask, TrackStatePropMask::Calibrated)) { + size_t meas_size = ts.calibratedSize() * sizeof(scalar); + size_t meas_cov_size = + ts.calibratedSize() * ts.calibratedSize() * sizeof(scalar); + h("meas", isMeas, weight(meas_size)); h("measCov", isMeas, weight(meas_cov_size)); h("sourceLinks", isMeas, weight(sizeof(const SourceLink*))); @@ -129,7 +137,6 @@ class VectorMultiTrajectoryBase { TrackStateType typeFlags; IndexType iuncalibrated = kInvalid; - IndexType icalibrated = kInvalid; IndexType icalibratedsourcelink = kInvalid; IndexType measdim = 0; @@ -205,7 +212,9 @@ class VectorMultiTrajectoryBase { case "smoothed"_hash: return instance.m_index[istate].ismoothed != kInvalid; case "calibrated"_hash: - return instance.m_index[istate].icalibrated != kInvalid; + return instance.m_measOffset[istate] != kInvalid; + case "calibratedCov"_hash: + return instance.m_measCovOffset[istate] != kInvalid; case "jacobian"_hash: return instance.m_index[istate].ijacobian != kInvalid; case "projector"_hash: @@ -246,7 +255,9 @@ class VectorMultiTrajectoryBase { case "smoothed"_hash: return &instance.m_index[istate].ismoothed; case "calibrated"_hash: - return &instance.m_index[istate].icalibrated; + return &instance.m_measOffset[istate]; + case "calibratedCov"_hash: + return &instance.m_measCovOffset[istate]; case "jacobian"_hash: return &instance.m_index[istate].ijacobian; case "projector"_hash: @@ -285,6 +296,7 @@ class VectorMultiTrajectoryBase { case "filtered"_hash: case "smoothed"_hash: case "calibrated"_hash: + case "calibratedCov"_hash: case "jacobian"_hash: case "projector"_hash: case "previous"_hash: @@ -300,6 +312,7 @@ class VectorMultiTrajectoryBase { return instance.m_dynamic.find(key) != instance.m_dynamic.end(); } } + // END INTERFACE HELPER /// index to map track states to the corresponding @@ -307,10 +320,12 @@ class VectorMultiTrajectoryBase { std::vector m_previous; std::vector::Coefficients> m_params; std::vector::Covariance> m_cov; - std::vector::Coefficients> - m_meas; - std::vector::Covariance> - m_measCov; + + std::vector m_meas; + std::vector m_measOffset; + std::vector m_measCov; + std::vector m_measCovOffset; + std::vector::Covariance> m_jac; std::vector m_sourceLinks; std::vector m_projectors; @@ -377,23 +392,28 @@ class VectorMultiTrajectory final return ConstTrackStateProxy::Covariance{m_jac[parIdx].data()}; } - TrackStateProxy::Measurement measurement_impl(IndexType parIdx) { - return TrackStateProxy::Measurement{m_meas[parIdx].data()}; + template + TrackStateProxy::Measurement measurement_impl(IndexType offset) { + return TrackStateProxy::Measurement{&m_meas[offset]}; } - ConstTrackStateProxy::Measurement measurement_impl(IndexType parIdx) const { - return ConstTrackStateProxy::Measurement{m_meas[parIdx].data()}; + template + ConstTrackStateProxy::Measurement measurement_impl( + IndexType offset) const { + return ConstTrackStateProxy::Measurement{&m_meas[offset]}; } - TrackStateProxy::MeasurementCovariance measurementCovariance_impl( - IndexType parIdx) { - return TrackStateProxy::MeasurementCovariance{m_measCov[parIdx].data()}; + template + TrackStateProxy::MeasurementCovariance measurementCovariance_impl( + IndexType offset) { + return TrackStateProxy::MeasurementCovariance{&m_measCov[offset]}; } - ConstTrackStateProxy::MeasurementCovariance measurementCovariance_impl( - IndexType parIdx) const { - return ConstTrackStateProxy::MeasurementCovariance{ - m_measCov[parIdx].data()}; + template + ConstTrackStateProxy::MeasurementCovariance + measurementCovariance_impl(IndexType offset) const { + return ConstTrackStateProxy::MeasurementCovariance{ + &m_measCov[offset]}; } IndexType addTrackState_impl( @@ -433,6 +453,20 @@ class VectorMultiTrajectory final return detail_vmt::VectorMultiTrajectoryBase::hasColumn_impl(*this, key); } + void allocateCalibrated_impl(IndexType istate, size_t measdim) { + if (m_measOffset[istate] != kInvalid && + m_measCovOffset[istate] != kInvalid && + m_index[istate].measdim == measdim) { + return; + } + + m_measOffset[istate] = static_cast(m_meas.size()); + m_meas.resize(m_meas.size() + measdim); + + m_measCovOffset[istate] = static_cast(m_measCov.size()); + m_measCov.resize(m_measCov.size() + measdim * measdim); + } + // END INTERFACE }; @@ -481,14 +515,17 @@ class ConstVectorMultiTrajectory final return ConstTrackStateProxy::Covariance{m_jac[parIdx].data()}; } - ConstTrackStateProxy::Measurement measurement_impl(IndexType parIdx) const { - return ConstTrackStateProxy::Measurement{m_meas[parIdx].data()}; + template + ConstTrackStateProxy::Measurement measurement_impl( + IndexType offset) const { + return ConstTrackStateProxy::Measurement{&m_meas[offset]}; } - ConstTrackStateProxy::MeasurementCovariance measurementCovariance_impl( - IndexType parIdx) const { - return ConstTrackStateProxy::MeasurementCovariance{ - m_measCov[parIdx].data()}; + template + ConstTrackStateProxy::MeasurementCovariance + measurementCovariance_impl(IndexType offset) const { + return ConstTrackStateProxy::MeasurementCovariance{ + &m_measCov[offset]}; } constexpr bool has_impl(HashedString key, IndexType istate) const { diff --git a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp index e7486efe4be..af8f6dbac03 100644 --- a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp +++ b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp @@ -902,6 +902,7 @@ class CombinatorialKalmanFilter { } // either copy ALL or everything except for predicted and jacobian + trackState.allocateCalibrated(candidateTrackState.calibratedSize()); trackState.copyFrom(candidateTrackState, mask, false); auto& typeFlags = trackState.typeFlags(); diff --git a/Core/include/Acts/TrackFinding/MeasurementSelector.hpp b/Core/include/Acts/TrackFinding/MeasurementSelector.hpp index a18e2b44d90..3c62a0be659 100644 --- a/Core/include/Acts/TrackFinding/MeasurementSelector.hpp +++ b/Core/include/Acts/TrackFinding/MeasurementSelector.hpp @@ -115,7 +115,16 @@ class MeasurementSelector { // const auto predictedCovariance = trackState.predictedCovariance(); double chi2 = calculateChi2( - trackState.calibrated(), trackState.calibratedCovariance(), + // This abuses an incorrectly sized vector / matrix to access the + // data pointer! This works (don't use the matrix as is!), but be + // careful! + trackState + .template calibrated() + .data(), + trackState + .template calibratedCovariance< + MultiTrajectoryTraits::MeasurementSizeMax>() + .data(), trackState.predicted(), trackState.predictedCovariance(), trackState.projector(), trackState.calibratedSize()); @@ -211,10 +220,7 @@ class MeasurementSelector { } double calculateChi2( - TrackStateTraits::Measurement fullCalibrated, - TrackStateTraits::MeasurementCovariance fullCalibratedCovariance, + double* fullCalibrated, double* fullCalibratedCovariance, TrackStateTraits::Parameters predicted, TrackStateTraits::Parameters filtered; TrackStateTraits::Covariance filteredCovariance; - TrackStateTraits::Measurement calibrated; - TrackStateTraits::MeasurementCovariance calibratedCovariance; + // This is used to build a covariance matrix view in the .cpp file + double* calibrated; + double* calibratedCovariance; TrackStateTraits::Projector projector; unsigned int calibratedSize; @@ -81,8 +80,17 @@ class GainMatrixUpdater { trackState.predictedCovariance(), trackState.filtered(), trackState.filteredCovariance(), - trackState.calibrated(), - trackState.calibratedCovariance(), + // This abuses an incorrectly sized vector / matrix to access the + // data pointer! This works (don't use the matrix as is!), but be + // careful! + trackState + .template calibrated< + MultiTrajectoryTraits::MeasurementSizeMax>() + .data(), + trackState + .template calibratedCovariance< + MultiTrajectoryTraits::MeasurementSizeMax>() + .data(), trackState.projector(), trackState.calibratedSize(), }, diff --git a/Core/include/Acts/TrackFitting/detail/GsfUtils.hpp b/Core/include/Acts/TrackFitting/detail/GsfUtils.hpp index 51c91eaa8d4..51faa9f66d4 100644 --- a/Core/include/Acts/TrackFitting/detail/GsfUtils.hpp +++ b/Core/include/Acts/TrackFitting/detail/GsfUtils.hpp @@ -146,10 +146,7 @@ class ScopedGsfInfoPrinterAndChecker { }; ActsScalar calculateDeterminant( - TrackStateTraits::Measurement fullCalibrated, - TrackStateTraits::MeasurementCovariance fullCalibratedCovariance, + const double *fullCalibrated, const double *fullCalibratedCovariance, TrackStateTraits::Covariance predictedCovariance, TrackStateTraits::Projector @@ -182,7 +179,15 @@ void computePosteriorWeights( const auto state = mt.getTrackState(tip); const double chi2 = state.chi2() - minChi2; const double detR = calculateDeterminant( - state.calibrated(), state.calibratedCovariance(), + // This abuses an incorrectly sized vector / matrix to access the + // data pointer! This works (don't use the matrix as is!), but be + // careful! + state.template calibrated() + .data(), + state + .template calibratedCovariance< + MultiTrajectoryTraits::MeasurementSizeMax>() + .data(), state.predictedCovariance(), state.projector(), state.calibratedSize()); const auto factor = std::sqrt(1. / detR) * std::exp(-0.5 * chi2); diff --git a/Core/include/Acts/Utilities/Helpers.hpp b/Core/include/Acts/Utilities/Helpers.hpp index 1568ed7abc1..18dc359d7ba 100644 --- a/Core/include/Acts/Utilities/Helpers.hpp +++ b/Core/include/Acts/Utilities/Helpers.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #define ACTS_CHECK_BIT(value, mask) ((value & mask) == mask) @@ -387,6 +388,28 @@ auto template_switch(size_t v, Args&&... args) { std::abort(); } +/// Alternative version of @c template_switch which accepts a generic +/// lambda and communicates the dimension via an integral constant type +/// @tparam N Value from which to start the dispatch chain, i.e. 0 in most cases +/// @tparam NMAX Maximum value up to which to attempt a dispatch +/// @param v The runtime value to dispatch on +/// @param func The lambda to invoke +/// @param args Additional arguments passed to @p func +template +auto template_switch_lambda(size_t v, Lambda&& func, Args&&... args) { + if (v == N) { + return func(std::integral_constant{}, + std::forward(args)...); + } + if constexpr (N < NMAX) { + return template_switch_lambda(v, func, + std::forward(args)...); + } + std::cerr << "template_switch(v=" << v + << ") is not valid (v > NMAX)" << std::endl; + std::abort(); +} + /// Convert a bitset to a matrix of integers, with each element set to the bit /// value. /// @note How the bits are assigned to matrix elements depends on the storage diff --git a/Core/include/Acts/Visualization/EventDataView3D.hpp b/Core/include/Acts/Visualization/EventDataView3D.hpp index dfe3b73b91e..b9297e052d2 100644 --- a/Core/include/Acts/Visualization/EventDataView3D.hpp +++ b/Core/include/Acts/Visualization/EventDataView3D.hpp @@ -225,9 +225,8 @@ struct EventDataView3D { // @Todo: how to draw 1D measurement? if (measurementConfig.visible and state.hasCalibrated() and state.calibratedSize() == 2) { - const Vector2& lposition = state.calibrated().template head<2>(); - const SymMatrix2 covariance = - state.calibratedCovariance().template topLeftCorner<2, 2>(); + const Vector2& lposition = state.template calibrated<2>(); + const SymMatrix2 covariance = state.template calibratedCovariance<2>(); drawCovarianceCartesian(helper, lposition, covariance, state.referenceSurface().transform(gctx), locErrorScale, measurementConfig); diff --git a/Core/src/EventData/VectorMultiTrajectory.cpp b/Core/src/EventData/VectorMultiTrajectory.cpp index fc09d7f56d2..173a1b7e6df 100644 --- a/Core/src/EventData/VectorMultiTrajectory.cpp +++ b/Core/src/EventData/VectorMultiTrajectory.cpp @@ -73,11 +73,10 @@ auto VectorMultiTrajectory::addTrackState_impl(TrackStatePropMask mask, m_sourceLinks.push_back(nullptr); p.iuncalibrated = m_sourceLinks.size() - 1; - if (ACTS_CHECK_BIT(mask, PropMask::Calibrated)) { - m_meas.emplace_back(); - m_measCov.emplace_back(); - p.icalibrated = m_meas.size() - 1; + m_measOffset.push_back(kInvalid); + m_measCovOffset.push_back(kInvalid); + if (ACTS_CHECK_BIT(mask, PropMask::Calibrated)) { m_sourceLinks.push_back(nullptr); p.icalibratedsourcelink = m_sourceLinks.size() - 1; @@ -165,7 +164,8 @@ void VectorMultiTrajectory::unset_impl(TrackStatePropMask target, m_index[istate].ijacobian = kInvalid; break; case PM::Calibrated: - m_index[istate].icalibrated = kInvalid; + m_measOffset[istate] = kInvalid; + m_measCovOffset[istate] = kInvalid; break; default: throw std::domain_error{"Unable to unset this component"}; diff --git a/Core/src/TrackFinding/MeasurementSelector.cpp b/Core/src/TrackFinding/MeasurementSelector.cpp index 07df50d33f1..f45903862cd 100644 --- a/Core/src/TrackFinding/MeasurementSelector.cpp +++ b/Core/src/TrackFinding/MeasurementSelector.cpp @@ -11,10 +11,7 @@ namespace Acts { double MeasurementSelector::calculateChi2( - TrackStateTraits::Measurement fullCalibrated, - TrackStateTraits::MeasurementCovariance fullCalibratedCovariance, + double* fullCalibrated, double* fullCalibratedCovariance, TrackStateTraits::Parameters predicted, TrackStateTraits::Projector projector, unsigned int calibratedSize) const { - return visit_measurement( - fullCalibrated, fullCalibratedCovariance, calibratedSize, - [&](const auto calibrated, const auto calibratedCovariance) -> double { - constexpr size_t kMeasurementSize = - decltype(calibrated)::RowsAtCompileTime; - - using ParametersVector = ActsVector; - - // Take the projector (measurement mapping function) - const auto H = - projector.template topLeftCorner() - .eval(); - - // Get the residuals - ParametersVector res; - res = calibrated - H * predicted; - - // Get the chi2 - return (res.transpose() * - ((calibratedCovariance + - H * predictedCovariance * H.transpose())) - .inverse() * - res) - .eval()(0, 0); - }); + return visit_measurement(calibratedSize, [&](auto N) -> double { + constexpr size_t kMeasurementSize = decltype(N)::value; + + typename TrackStateTraits::Measurement calibrated{ + fullCalibrated}; + + typename TrackStateTraits::MeasurementCovariance + calibratedCovariance{fullCalibratedCovariance}; + + using ParametersVector = ActsVector; + + // Take the projector (measurement mapping function) + const auto H = + projector.template topLeftCorner().eval(); + + // Get the residuals + ParametersVector res; + res = calibrated - H * predicted; + + // Get the chi2 + return (res.transpose() * + ((calibratedCovariance + H * predictedCovariance * H.transpose())) + .inverse() * + res) + .eval()(0, 0); + }); } } // namespace Acts diff --git a/Core/src/TrackFitting/GainMatrixUpdater.cpp b/Core/src/TrackFitting/GainMatrixUpdater.cpp index bc046d035e7..8827c582de4 100644 --- a/Core/src/TrackFitting/GainMatrixUpdater.cpp +++ b/Core/src/TrackFitting/GainMatrixUpdater.cpp @@ -8,6 +8,9 @@ #include "Acts/TrackFitting/GainMatrixUpdater.hpp" +#include "Acts/EventData/MeasurementHelpers.hpp" +#include "Acts/Utilities/Helpers.hpp" + namespace Acts { std::tuple GainMatrixUpdater::visitMeasurement( @@ -16,71 +19,70 @@ std::tuple GainMatrixUpdater::visitMeasurement( // default-constructed error represents success, i.e. an invalid error code std::error_code error; double chi2 = 0; - visit_measurement( - trackState.calibrated, trackState.calibratedCovariance, - trackState.calibratedSize, - [&](const auto calibrated, const auto calibratedCovariance) { - constexpr size_t kMeasurementSize = - decltype(calibrated)::RowsAtCompileTime; - using ParametersVector = ActsVector; - using CovarianceMatrix = ActsSymMatrix; - - ACTS_VERBOSE("Measurement dimension: " << kMeasurementSize); - ACTS_VERBOSE("Calibrated measurement: " << calibrated.transpose()); - ACTS_VERBOSE("Calibrated measurement covariance:\n" - << calibratedCovariance); - - const auto H = - trackState.projector - .template topLeftCorner() - .eval(); - - ACTS_VERBOSE("Measurement projector H:\n" << H); - - const auto K = (trackState.predictedCovariance * H.transpose() * - (H * trackState.predictedCovariance * H.transpose() + - calibratedCovariance) - .inverse()) - .eval(); - - ACTS_VERBOSE("Gain Matrix K:\n" << K); - - if (K.hasNaN()) { - error = - (direction == NavigationDirection::Forward) + + visit_measurement(trackState.calibratedSize, [&](auto N) -> bool { + constexpr size_t kMeasurementSize = decltype(N)::value; + using ParametersVector = ActsVector; + using CovarianceMatrix = ActsSymMatrix; + + typename TrackStateTraits::Measurement calibrated{ + trackState.calibrated}; + typename TrackStateTraits::MeasurementCovariance + calibratedCovariance{trackState.calibratedCovariance}; + + ACTS_VERBOSE("Measurement dimension: " << kMeasurementSize); + ACTS_VERBOSE("Calibrated measurement: " << calibrated.transpose()); + ACTS_VERBOSE("Calibrated measurement covariance:\n" + << calibratedCovariance); + + const auto H = trackState.projector + .template topLeftCorner() + .eval(); + + ACTS_VERBOSE("Measurement projector H:\n" << H); + + const auto K = (trackState.predictedCovariance * H.transpose() * + (H * trackState.predictedCovariance * H.transpose() + + calibratedCovariance) + .inverse()) + .eval(); + + ACTS_VERBOSE("Gain Matrix K:\n" << K); + + if (K.hasNaN()) { + error = (direction == NavigationDirection::Forward) ? KalmanFitterError::ForwardUpdateFailed : KalmanFitterError::BackwardUpdateFailed; // set to error - return false; // abort execution - } - - trackState.filtered = - trackState.predicted + K * (calibrated - H * trackState.predicted); - trackState.filteredCovariance = (BoundSymMatrix::Identity() - K * H) * - trackState.predictedCovariance; - ACTS_VERBOSE( - "Filtered parameters: " << trackState.filtered.transpose()); - ACTS_VERBOSE("Filtered covariance:\n" << trackState.filteredCovariance); - - // calculate filtered residual - // - // FIXME: Without separate residual construction and assignment, we - // currently take a +0.7GB build memory consumption hit in the - // EventDataView unit tests. Revisit this once Measurement - // overhead problems (Acts issue #350) are sorted out. - // - ParametersVector residual; - residual = calibrated - H * trackState.filtered; - ACTS_VERBOSE("Residual: " << residual.transpose()); - - chi2 = (residual.transpose() * - ((CovarianceMatrix::Identity() - H * K) * calibratedCovariance) - .inverse() * - residual) - .value(); - - ACTS_VERBOSE("Chi2: " << chi2); - return true; // continue execution - }); + return false; // abort execution + } + + trackState.filtered = + trackState.predicted + K * (calibrated - H * trackState.predicted); + trackState.filteredCovariance = + (BoundSymMatrix::Identity() - K * H) * trackState.predictedCovariance; + ACTS_VERBOSE("Filtered parameters: " << trackState.filtered.transpose()); + ACTS_VERBOSE("Filtered covariance:\n" << trackState.filteredCovariance); + + // calculate filtered residual + // + // FIXME: Without separate residual construction and assignment, we + // currently take a +0.7GB build memory consumption hit in the + // EventDataView unit tests. Revisit this once Measurement + // overhead problems (Acts issue #350) are sorted out. + // + ParametersVector residual; + residual = calibrated - H * trackState.filtered; + ACTS_VERBOSE("Residual: " << residual.transpose()); + + chi2 = (residual.transpose() * + ((CovarianceMatrix::Identity() - H * K) * calibratedCovariance) + .inverse() * + residual) + .value(); + + ACTS_VERBOSE("Chi2: " << chi2); + return true; // continue execution + }); return {chi2, error}; } diff --git a/Core/src/TrackFitting/GsfUtils.cpp b/Core/src/TrackFitting/GsfUtils.cpp index 5b7c1071783..86bd11aad14 100644 --- a/Core/src/TrackFitting/GsfUtils.cpp +++ b/Core/src/TrackFitting/GsfUtils.cpp @@ -17,22 +17,25 @@ using TrackStateTraits = TrackStateTraits; ActsScalar calculateDeterminant( - TrackStateTraits::Measurement fullCalibrated, - TrackStateTraits::MeasurementCovariance fullCalibratedCovariance, + const double* fullCalibrated, const double* fullCalibratedCovariance, TrackStateTraits::Covariance predictedCovariance, TrackStateTraits::Projector projector, unsigned int calibratedSize) { - return visit_measurement( - fullCalibrated, fullCalibratedCovariance, calibratedSize, - [&](const auto calibrated, const auto calibratedCovariance) { - constexpr size_t kMeasurementSize = - decltype(calibrated)::RowsAtCompileTime; - const auto H = - projector.template topLeftCorner() - .eval(); - - return (H * predictedCovariance * H.transpose() + calibratedCovariance) - .determinant(); - }); + return visit_measurement(calibratedSize, [&](auto N) { + constexpr size_t kMeasurementSize = decltype(N)::value; + + typename Acts::TrackStateTraits::Measurement + calibrated{fullCalibrated}; + + typename Acts::TrackStateTraits< + kMeasurementSize, true>::MeasurementCovariance calibratedCovariance{ + fullCalibratedCovariance}; + + const auto H = + projector.template topLeftCorner().eval(); + + return (H * predictedCovariance * H.transpose() + calibratedCovariance) + .determinant(); + }); } } // namespace detail } // namespace Acts diff --git a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp index 1e60702f288..82804794373 100644 --- a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp @@ -53,7 +53,10 @@ class MeasurementCalibrator { assert((sourceLink.index() < m_measurements->size()) and "Source link index is outside the container bounds"); std::visit( - [&trackState](const auto& meas) { trackState.setCalibrated(meas); }, + [&trackState](const auto& meas) { + trackState.allocateCalibrated(meas.size()); + trackState.setCalibrated(meas); + }, (*m_measurements)[sourceLink.index()]); } diff --git a/Examples/Io/Root/src/RootTrajectoryStatesWriter.cpp b/Examples/Io/Root/src/RootTrajectoryStatesWriter.cpp index c5168fbc603..d806e31b86a 100644 --- a/Examples/Io/Root/src/RootTrajectoryStatesWriter.cpp +++ b/Examples/Io/Root/src/RootTrajectoryStatesWriter.cpp @@ -376,8 +376,8 @@ ActsExamples::ProcessCode ActsExamples::RootTrajectoryStatesWriter::writeT( m_pathLength.push_back(state.pathLength()); // expand the local measurements into the full bound space - Acts::BoundVector meas = - state.projector().transpose() * state.calibrated(); + Acts::BoundVector meas = state.effectiveProjector().transpose() * + state.effectiveCalibrated(); // extract local and global position Acts::Vector2 local(meas[Acts::eBoundLoc0], meas[Acts::eBoundLoc1]); Acts::Vector3 mom(1, 1, 1); diff --git a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/TestSourceLink.hpp b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/TestSourceLink.hpp index 20a847ac718..7d4d1d930cb 100644 --- a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/TestSourceLink.hpp +++ b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/TestSourceLink.hpp @@ -85,12 +85,14 @@ Acts::BoundVariantMeasurement testSourceLinkCalibratorReturn( (sl.indices[1] != Acts::eBoundSize)) { auto meas = makeMeasurement(sl, sl.parameters, sl.covariance, sl.indices[0], sl.indices[1]); + trackState.allocateCalibrated(2); trackState.setCalibrated(meas); return meas; } else if (sl.indices[0] != Acts::eBoundSize) { auto meas = makeMeasurement(sl, sl.parameters.head<1>(), sl.covariance.topLeftCorner<1, 1>(), sl.indices[0]); + trackState.allocateCalibrated(1); trackState.setCalibrated(meas); return meas; } else { diff --git a/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp b/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp index ab34783e473..1ceef4ecc21 100644 --- a/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp +++ b/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp @@ -7,9 +7,12 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include +#include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/Measurement.hpp" +#include "Acts/EventData/MeasurementHelpers.hpp" #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" @@ -367,10 +370,12 @@ BOOST_AUTO_TEST_CASE(AddTrackStateWithBitMask) { BOOST_CHECK(ts.hasPredicted()); BOOST_CHECK(ts.hasFiltered()); BOOST_CHECK(ts.hasSmoothed()); - BOOST_CHECK(ts.hasCalibrated()); + BOOST_CHECK(!ts.hasCalibrated()); BOOST_CHECK(ts.hasProjector()); BOOST_CHECK(ts.hasJacobian()); alwaysPresent(ts); + ts.allocateCalibrated(5); + BOOST_CHECK(ts.hasCalibrated()); ts = t.getTrackState(t.addTrackState(PM::None)); BOOST_CHECK(!ts.hasPredicted()); @@ -412,9 +417,11 @@ BOOST_AUTO_TEST_CASE(AddTrackStateWithBitMask) { BOOST_CHECK(!ts.hasPredicted()); BOOST_CHECK(!ts.hasFiltered()); BOOST_CHECK(!ts.hasSmoothed()); - BOOST_CHECK(ts.hasCalibrated()); + BOOST_CHECK(!ts.hasCalibrated()); BOOST_CHECK(ts.hasProjector()); BOOST_CHECK(!ts.hasJacobian()); + ts.allocateCalibrated(5); + BOOST_CHECK(ts.hasCalibrated()); ts = t.getTrackState(t.addTrackState(PM::Jacobian)); BOOST_CHECK(!ts.hasPredicted()); @@ -480,12 +487,13 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCrossTalk) { { // reset measurements w/ full parameters auto [measPar, measCov] = generateBoundParametersCovariance(rng); - tsb.calibrated() = measPar; - tsb.calibratedCovariance() = measCov; - BOOST_CHECK_EQUAL(tsa.calibrated(), measPar); - BOOST_CHECK_EQUAL(tsa.calibratedCovariance(), measCov); - BOOST_CHECK_EQUAL(tsb.calibrated(), measPar); - BOOST_CHECK_EQUAL(tsb.calibratedCovariance(), measCov); + tsb.allocateCalibrated(eBoundSize); + tsb.calibrated() = measPar; + tsb.calibratedCovariance() = measCov; + BOOST_CHECK_EQUAL(tsa.calibrated(), measPar); + BOOST_CHECK_EQUAL(tsa.calibratedCovariance(), measCov); + BOOST_CHECK_EQUAL(tsb.calibrated(), measPar); + BOOST_CHECK_EQUAL(tsb.calibratedCovariance(), measCov); } { // reset only the effective measurements @@ -493,6 +501,7 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCrossTalk) { size_t nMeasurements = tsb.effectiveCalibrated().rows(); auto effPar = measPar.head(nMeasurements); auto effCov = measCov.topLeftCorner(nMeasurements, nMeasurements); + tsb.allocateCalibrated(eBoundSize); tsb.effectiveCalibrated() = effPar; tsb.effectiveCalibratedCovariance() = effCov; BOOST_CHECK_EQUAL(tsa.effectiveCalibrated(), effPar); @@ -545,18 +554,6 @@ BOOST_AUTO_TEST_CASE(TrackStateReassignment) { BOOST_CHECK_EQUAL(ts.effectiveCalibrated(), m2.parameters()); BOOST_CHECK_EQUAL(ts.effectiveCalibratedCovariance(), m2.covariance()); BOOST_CHECK_EQUAL(ts.effectiveProjector(), m2.projector()); - - // check that the overallocated parts are zeroed - ParametersVector mParFull = ParametersVector::Zero(); - CovarianceMatrix mCovFull = CovarianceMatrix::Zero(); - ActsMatrix projFull; - mParFull.head<2>() = ts.effectiveCalibrated(); - mCovFull.topLeftCorner<2, 2>() = ts.effectiveCalibratedCovariance(); - projFull.setZero(); - projFull.topLeftCorner<2, eBoundSize>() = ts.effectiveProjector(); - BOOST_CHECK_EQUAL(ts.calibrated(), mParFull); - BOOST_CHECK_EQUAL(ts.calibratedCovariance(), mCovFull); - BOOST_CHECK_EQUAL(ts.projector(), projFull); } BOOST_DATA_TEST_CASE(TrackStateProxyStorage, bd::make({1u, 2u}), @@ -612,8 +609,16 @@ BOOST_DATA_TEST_CASE(TrackStateProxyStorage, bd::make({1u, 2u}), mParFull.head(nMeasurements) = pc.sourceLink.parameters.head(nMeasurements); mCovFull.topLeftCorner(nMeasurements, nMeasurements) = pc.sourceLink.covariance.topLeftCorner(nMeasurements, nMeasurements); - BOOST_CHECK_EQUAL(ts.calibrated(), mParFull); - BOOST_CHECK_EQUAL(ts.calibratedCovariance(), mCovFull); + + auto expMeas = pc.sourceLink.parameters.head(nMeasurements); + auto expCov = + pc.sourceLink.covariance.topLeftCorner(nMeasurements, nMeasurements); + + visit_measurement(ts.calibratedSize(), [&](auto N) { + constexpr size_t measdim = decltype(N)::value; + BOOST_CHECK_EQUAL(ts.calibrated(), expMeas); + BOOST_CHECK_EQUAL(ts.calibratedCovariance(), expCov); + }); } BOOST_CHECK(ts.hasProjector()); @@ -675,6 +680,8 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyAllocations) { BOOST_CHECK(tsall.has<"filtered"_hash>()); BOOST_CHECK(tsall.has<"smoothed"_hash>()); BOOST_CHECK(tsall.has<"jacobian"_hash>()); + BOOST_CHECK(!tsall.has<"calibrated"_hash>()); + tsall.allocateCalibrated(5); BOOST_CHECK(tsall.has<"calibrated"_hash>()); BOOST_CHECK(tsall.has<"projector"_hash>()); BOOST_CHECK(!tsall.has<"uncalibrated"_hash>()); // separate optional @@ -709,11 +716,17 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyGetMask) { VectorMultiTrajectory mj; { auto ts = mj.getTrackState(mj.addTrackState(PM::All)); - BOOST_CHECK(ts.getMask() == all); + // Calibrated is ignored because we haven't allocated yet + BOOST_CHECK_EQUAL(ts.getMask(), (all & ~PM::Calibrated)); + ts.allocateCalibrated(4); + BOOST_CHECK_EQUAL(ts.getMask(), all); } { auto ts = mj.getTrackState(mj.addTrackState(PM::Filtered | PM::Calibrated)); - BOOST_CHECK(ts.getMask() == (PM::Filtered | PM::Calibrated)); + // Calibrated is ignored because we haven't allocated yet + BOOST_CHECK_EQUAL(ts.getMask(), PM::Filtered); + ts.allocateCalibrated(4); + BOOST_CHECK_EQUAL(ts.getMask(), (PM::Filtered | PM::Calibrated)); } { auto ts = mj.getTrackState( @@ -723,7 +736,8 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyGetMask) { { for (PM mask : values) { auto ts = mj.getTrackState(mj.addTrackState(mask)); - BOOST_CHECK(ts.getMask() == mask); + // Calibrated is ignored because we haven't allocated yet + BOOST_CHECK_EQUAL(ts.getMask(), (mask & ~PM::Calibrated)); } } } @@ -731,11 +745,14 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyGetMask) { BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { using PM = TrackStatePropMask; - std::array values{PM::Predicted, PM::Filtered, PM::Smoothed, - PM::Jacobian, PM::Calibrated}; + std::array values{PM::Predicted, PM::Filtered, PM::Smoothed, + PM::Jacobian}; VectorMultiTrajectory mj; - auto mkts = [&](PM mask) { return mj.getTrackState(mj.addTrackState(mask)); }; + auto mkts = [&](PM mask) { + auto r = mj.getTrackState(mj.addTrackState(mask)); + return r; + }; // orthogonal ones for (PM a : values) { @@ -753,6 +770,26 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { } } + { + BOOST_TEST_CHECKPOINT("Calib auto alloc"); + auto tsa = mkts(PM::All); + auto tsb = mkts(PM::All); + tsb.allocateCalibrated(5); + tsb.calibrated<5>().setRandom(); + tsb.calibratedCovariance<5>().setRandom(); + tsa.copyFrom(tsb, PM::All); + BOOST_CHECK_EQUAL(tsa.calibrated<5>(), tsb.calibrated<5>()); + BOOST_CHECK_EQUAL(tsa.calibratedCovariance<5>(), + tsb.calibratedCovariance<5>()); + } + + { + BOOST_TEST_CHECKPOINT("Copy none"); + auto tsa = mkts(PM::All); + auto tsb = mkts(PM::All); + tsa.copyFrom(tsb, PM::None); + } + auto ts1 = mkts(PM::Filtered | PM::Predicted); // this has both ts1.filtered().setRandom(); ts1.filteredCovariance().setRandom(); @@ -803,8 +840,14 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { BOOST_CHECK_NE(&ts1.uncalibrated(), &ts2.uncalibrated()); BOOST_CHECK_NE(&ts1.calibratedSourceLink(), &ts2.calibratedSourceLink()); - BOOST_CHECK_NE(ts1.calibrated(), ts2.calibrated()); - BOOST_CHECK_NE(ts1.calibratedCovariance(), ts2.calibratedCovariance()); + + visit_measurement(ts1.calibratedSize(), [&](auto N) { + constexpr size_t measdim = decltype(N)::value; + BOOST_CHECK_NE(ts1.calibrated(), ts2.calibrated()); + BOOST_CHECK_NE(ts1.calibratedCovariance(), + ts2.calibratedCovariance()); + }); + BOOST_CHECK_NE(ts1.calibratedSize(), ts2.calibratedSize()); BOOST_CHECK_NE(ts1.projector(), ts2.projector()); @@ -825,8 +868,14 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { BOOST_CHECK_EQUAL(&ts1.uncalibrated(), &ts2.uncalibrated()); BOOST_CHECK_EQUAL(&ts1.calibratedSourceLink(), &ts2.calibratedSourceLink()); - BOOST_CHECK_EQUAL(ts1.calibrated(), ts2.calibrated()); - BOOST_CHECK_EQUAL(ts1.calibratedCovariance(), ts2.calibratedCovariance()); + + visit_measurement(ts1.calibratedSize(), [&](auto N) { + constexpr size_t measdim = decltype(N)::value; + BOOST_CHECK_EQUAL(ts1.calibrated(), ts2.calibrated()); + BOOST_CHECK_EQUAL(ts1.calibratedCovariance(), + ts2.calibratedCovariance()); + }); + BOOST_CHECK_EQUAL(ts1.calibratedSize(), ts2.calibratedSize()); BOOST_CHECK_EQUAL(ts1.projector(), ts2.projector()); @@ -845,8 +894,14 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { BOOST_CHECK_NE(ts1.predictedCovariance(), ts2.predictedCovariance()); BOOST_CHECK_NE(&ts1.calibratedSourceLink(), &ts2.calibratedSourceLink()); - BOOST_CHECK_NE(ts1.calibrated(), ts2.calibrated()); - BOOST_CHECK_NE(ts1.calibratedCovariance(), ts2.calibratedCovariance()); + + visit_measurement(ts1.calibratedSize(), [&](auto N) { + constexpr size_t measdim = decltype(N)::value; + BOOST_CHECK_NE(ts1.calibrated(), ts2.calibrated()); + BOOST_CHECK_NE(ts1.calibratedCovariance(), + ts2.calibratedCovariance()); + }); + BOOST_CHECK_NE(ts1.calibratedSize(), ts2.calibratedSize()); BOOST_CHECK_NE(ts1.projector(), ts2.projector()); @@ -862,8 +917,14 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { BOOST_CHECK_EQUAL(ts1.predictedCovariance(), ts2.predictedCovariance()); BOOST_CHECK_EQUAL(&ts1.calibratedSourceLink(), &ts2.calibratedSourceLink()); - BOOST_CHECK_EQUAL(ts1.calibrated(), ts2.calibrated()); - BOOST_CHECK_EQUAL(ts1.calibratedCovariance(), ts2.calibratedCovariance()); + + visit_measurement(ts1.calibratedSize(), [&](auto N) { + constexpr size_t measdim = decltype(N)::value; + BOOST_CHECK_EQUAL(ts1.calibrated(), ts2.calibrated()); + BOOST_CHECK_EQUAL(ts1.calibratedCovariance(), + ts2.calibratedCovariance()); + }); + BOOST_CHECK_EQUAL(ts1.calibratedSize(), ts2.calibratedSize()); BOOST_CHECK_EQUAL(ts1.projector(), ts2.projector()); @@ -877,14 +938,18 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopy) { BOOST_AUTO_TEST_CASE(TrackStateProxyCopyDiffMTJ) { using PM = TrackStatePropMask; - std::array values{PM::Predicted, PM::Filtered, PM::Smoothed, - PM::Jacobian, PM::Calibrated}; + std::array values{PM::Predicted, PM::Filtered, PM::Smoothed, + PM::Jacobian}; VectorMultiTrajectory mj; VectorMultiTrajectory mj2; - auto mkts = [&](PM mask) { return mj.getTrackState(mj.addTrackState(mask)); }; + auto mkts = [&](PM mask) { + auto r = mj.getTrackState(mj.addTrackState(mask)); + return r; + }; auto mkts2 = [&](PM mask) { - return mj2.getTrackState(mj2.addTrackState(mask)); + auto r = mj2.getTrackState(mj2.addTrackState(mask)); + return r; }; // orthogonal ones @@ -931,6 +996,26 @@ BOOST_AUTO_TEST_CASE(TrackStateProxyCopyDiffMTJ) { ts1.copyFrom(ts2); BOOST_CHECK(ts1.predicted() == ts2.predicted()); BOOST_CHECK(ts1.predictedCovariance() == ts2.predictedCovariance()); + + { + BOOST_TEST_CHECKPOINT("Calib auto alloc"); + auto tsa = mkts(PM::All); + auto tsb = mkts(PM::All); + tsb.allocateCalibrated(5); + tsb.calibrated<5>().setRandom(); + tsb.calibratedCovariance<5>().setRandom(); + tsa.copyFrom(tsb, PM::All); + BOOST_CHECK_EQUAL(tsa.calibrated<5>(), tsb.calibrated<5>()); + BOOST_CHECK_EQUAL(tsa.calibratedCovariance<5>(), + tsb.calibratedCovariance<5>()); + } + + { + BOOST_TEST_CHECKPOINT("Copy none"); + auto tsa = mkts(PM::All); + auto tsb = mkts(PM::All); + tsa.copyFrom(tsb, PM::None); + } } BOOST_AUTO_TEST_CASE(ProxyAssignment) { diff --git a/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp b/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp index 0a18d712ef1..226166e597a 100644 --- a/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp +++ b/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp @@ -48,7 +48,8 @@ struct TestOutlierFinder { if (not state.hasCalibrated() or not state.hasPredicted()) { return false; } - auto residuals = state.calibrated() - state.projector() * state.predicted(); + auto residuals = state.effectiveCalibrated() - + state.effectiveProjector() * state.predicted(); auto distance = residuals.norm(); return (distanceMax <= distance); }