diff --git a/Core/include/Acts/EventData/MultiTrajectory.hpp b/Core/include/Acts/EventData/MultiTrajectory.hpp index 1c065fd7e12..e293c6c9c5f 100644 --- a/Core/include/Acts/EventData/MultiTrajectory.hpp +++ b/Core/include/Acts/EventData/MultiTrajectory.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/MeasurementHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" @@ -687,13 +688,24 @@ class MultiTrajectory { /// Allocate storage for a calibrated measurement of specified dimension /// @param istate The track state to store for /// @param measdim the dimension of the measurement to store - /// @note Is a noop if the track state already has an allocation - /// an the dimension is the same. + /// @note In case an allocation is already present, no additional allocation + /// will be performed, but the existing allocation will be zeroed. void allocateCalibrated(IndexType istate, std::size_t measdim) { throw_assert(measdim > 0 && measdim <= eBoundSize, "Invalid measurement dimension detected"); - self().allocateCalibrated_impl(istate, measdim); + visit_measurement(measdim, [this, istate]( + std::integral_constant) { + self().template allocateCalibrated_impl( + istate, ActsVector{ActsVector::Zero()}, + ActsSquareMatrix{ActsSquareMatrix::Zero()}); + }); + } + + template + void allocateCalibrated(IndexType istate, const Eigen::DenseBase& val, + const Eigen::DenseBase& cov) { + self().template allocateCalibrated_impl(istate, val, cov); } void setUncalibratedSourceLink(IndexType istate, SourceLink&& sourceLink) diff --git a/Core/include/Acts/EventData/MultiTrajectoryBackendConcept.hpp b/Core/include/Acts/EventData/MultiTrajectoryBackendConcept.hpp index 92ae47270bc..83f2593d647 100644 --- a/Core/include/Acts/EventData/MultiTrajectoryBackendConcept.hpp +++ b/Core/include/Acts/EventData/MultiTrajectoryBackendConcept.hpp @@ -130,7 +130,15 @@ concept MutableMultiTrajectoryBackend = { v.template addColumn_impl(col) }; { v.template addColumn_impl(col) }; - { v.allocateCalibrated_impl(istate, dim) }; + { + v.template allocateCalibrated_impl(istate, ActsVector<1>{}, + ActsSquareMatrix<1>{}) + }; + // Assuming intermediate values also work + { + v.template allocateCalibrated_impl(istate, ActsVector{}, + ActsSquareMatrix{}) + }; { v.setUncalibratedSourceLink_impl(istate, std::move(sl)) }; diff --git a/Core/include/Acts/EventData/TrackProxy.hpp b/Core/include/Acts/EventData/TrackProxy.hpp index 077ee8340b0..7e62eea943d 100644 --- a/Core/include/Acts/EventData/TrackProxy.hpp +++ b/Core/include/Acts/EventData/TrackProxy.hpp @@ -577,9 +577,6 @@ class TrackProxy { // append track states (cheap), but they're in the wrong order for (const auto& srcTrackState : other.trackStatesReversed()) { auto destTrackState = appendTrackState(srcTrackState.getMask()); - if (srcTrackState.hasCalibrated()) { - destTrackState.allocateCalibrated(srcTrackState.calibratedSize()); - } destTrackState.copyFrom(srcTrackState, Acts::TrackStatePropMask::All, true); } diff --git a/Core/include/Acts/EventData/TrackStateProxy.hpp b/Core/include/Acts/EventData/TrackStateProxy.hpp index b7b991fa2ee..3f7ddf1a028 100644 --- a/Core/include/Acts/EventData/TrackStateProxy.hpp +++ b/Core/include/Acts/EventData/TrackStateProxy.hpp @@ -865,10 +865,35 @@ class TrackStateProxy { /// Allocate storage to be able to store a measurement of size @p measdim. /// This must be called **before** setting the measurement content. + /// @note This does not allocate if an allocation of the same size already exists + /// @note This will zero-initialize the allocated storage + /// @note This is an error if an existing allocation has different size void allocateCalibrated(std::size_t measdim) { m_traj->allocateCalibrated(m_istate, measdim); } + /// Allocate storage and assign the given vector and covariance to it. + /// The dimension is inferred from the given vector and matrix. + /// @tparam val_t Type of the vector + /// @tparam cov_t Type of the covariance matrix + /// @param val The measurement vector + /// @param cov The covariance matrix + /// @note This does not allocate if an allocation of the same size already exists + /// @note This throws an exception if an existing allocation has different size + template + void allocateCalibrated(const Eigen::DenseBase& val, + const Eigen::DenseBase& cov) + requires(Eigen::PlainObjectBase::RowsAtCompileTime > 0 && + Eigen::PlainObjectBase::RowsAtCompileTime <= eBoundSize && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::RowsAtCompileTime && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::ColsAtCompileTime) + { + m_traj->template allocateCalibrated< + Eigen::PlainObjectBase::RowsAtCompileTime>(m_istate, val, cov); + } + /// @} /// @anchor track_state_share_copy @@ -993,17 +1018,14 @@ class TrackStateProxy { } if (ACTS_CHECK_BIT(src, PM::Calibrated)) { - 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(); + self->allocateCalibrated( + other.template calibrated().eval(), + other.template calibratedCovariance().eval()); }); setBoundSubspaceIndices(other.boundSubspaceIndices()); @@ -1041,17 +1063,14 @@ class TrackStateProxy { // may be not yet allocated if (ACTS_CHECK_BIT(mask, PM::Calibrated) && other.template has()) { - 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(); + self->allocateCalibrated( + other.template calibrated().eval(), + other.template calibratedCovariance().eval()); }); setBoundSubspaceIndices(other.boundSubspaceIndices()); diff --git a/Core/include/Acts/EventData/TrackStateProxyConcept.hpp b/Core/include/Acts/EventData/TrackStateProxyConcept.hpp index d148d3c4940..61e98adbc48 100644 --- a/Core/include/Acts/EventData/TrackStateProxyConcept.hpp +++ b/Core/include/Acts/EventData/TrackStateProxyConcept.hpp @@ -248,6 +248,13 @@ concept MutableTrackStateProxyConcept = { v.allocateCalibrated(measdim) }; + { v.allocateCalibrated(ActsVector<1>{}, ActsSquareMatrix<1>{}) }; + // Assuming intermediate values are also allowed + { + v.allocateCalibrated(ActsVector{}, + ActsSquareMatrix{}) + }; + { v.chi2() } -> std::same_as; { v.pathLength() } -> std::same_as; diff --git a/Core/include/Acts/EventData/VectorMultiTrajectory.hpp b/Core/include/Acts/EventData/VectorMultiTrajectory.hpp index 3859239ae69..e13498cea2c 100644 --- a/Core/include/Acts/EventData/VectorMultiTrajectory.hpp +++ b/Core/include/Acts/EventData/VectorMultiTrajectory.hpp @@ -47,6 +47,33 @@ using MultiTrajectoryTraits::IndexType; constexpr auto kInvalid = MultiTrajectoryTraits::kInvalid; constexpr auto MeasurementSizeMax = MultiTrajectoryTraits::MeasurementSizeMax; +template +struct NonInitializingAllocator { + using value_type = T; + + NonInitializingAllocator() noexcept = default; + + template + explicit NonInitializingAllocator( + const NonInitializingAllocator& /*other*/) noexcept {} + + template + bool operator==(const NonInitializingAllocator& /*other*/) const noexcept { + return true; + } + + T* allocate(std::size_t n) const { return std::allocator{}.allocate(n); } + + void deallocate(T* const p, std::size_t n) const noexcept { + std::allocator{}.deallocate(p, n); + } + + void construct(T* /*p*/) const { + // This construct function intentionally does not initialize the object! + // Be very careful when using this allocator. + } +}; + class VectorMultiTrajectoryBase { public: struct Statistics { @@ -320,9 +347,9 @@ class VectorMultiTrajectoryBase { m_params; std::vector::Covariance> m_cov; - std::vector m_meas; + std::vector> m_meas; std::vector m_measOffset; - std::vector m_measCov; + std::vector> m_measCov; std::vector m_measCovOffset; std::vector::Covariance> m_jac; @@ -464,23 +491,44 @@ class VectorMultiTrajectory final return detail_vmt::VectorMultiTrajectoryBase::hasColumn_impl(*this, key); } - void allocateCalibrated_impl(IndexType istate, std::size_t measdim) { - throw_assert(measdim > 0 && measdim <= eBoundSize, - "Invalid measurement dimension detected"); + template + void allocateCalibrated_impl(IndexType istate, + const Eigen::DenseBase& val, + const Eigen::DenseBase& cov) + + requires(Eigen::PlainObjectBase::RowsAtCompileTime > 0 && + Eigen::PlainObjectBase::RowsAtCompileTime <= eBoundSize && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::RowsAtCompileTime && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::ColsAtCompileTime) + { + constexpr std::size_t measdim = val_t::RowsAtCompileTime; + + if (m_index[istate].measdim != kInvalid && + m_index[istate].measdim != measdim) { + throw std::invalid_argument{ + "Measurement dimension does not match the allocated dimension"}; + } + + if (m_measOffset[istate] == kInvalid || + m_measCovOffset[istate] == kInvalid) { + m_measOffset[istate] = static_cast(m_meas.size()); + m_meas.resize(m_meas.size() + measdim); - if (m_measOffset[istate] != kInvalid && - m_measCovOffset[istate] != kInvalid && - m_index[istate].measdim == measdim) { - return; + m_measCovOffset[istate] = static_cast(m_measCov.size()); + m_measCov.resize(m_measCov.size() + measdim * measdim); } m_index[istate].measdim = measdim; - m_measOffset[istate] = static_cast(m_meas.size()); - m_meas.resize(m_meas.size() + measdim); + double* measPtr = &m_meas[m_measOffset[istate]]; + Eigen::Map> valMap(measPtr); + valMap = val; - m_measCovOffset[istate] = static_cast(m_measCov.size()); - m_measCov.resize(m_measCov.size() + measdim * measdim); + double* covPtr = &m_measCov[m_measCovOffset[istate]]; + Eigen::Map> covMap(covPtr); + covMap = cov; } void setUncalibratedSourceLink_impl(IndexType istate, diff --git a/Core/include/Acts/EventData/VectorTrackContainer.hpp b/Core/include/Acts/EventData/VectorTrackContainer.hpp index 8734f69eb4c..d0ce9cf402d 100644 --- a/Core/include/Acts/EventData/VectorTrackContainer.hpp +++ b/Core/include/Acts/EventData/VectorTrackContainer.hpp @@ -253,6 +253,7 @@ class VectorTrackContainer final : public detail_vtc::VectorTrackContainerBase { void reserve(IndexType size); void clear(); + std::size_t size() const; void setReferenceSurface_impl(IndexType itrack, std::shared_ptr surface) { diff --git a/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp b/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp index a2e374c0cc2..422dc58e053 100644 --- a/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp +++ b/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp @@ -10,6 +10,7 @@ #include +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" @@ -20,6 +21,7 @@ #include "Acts/Utilities/HashedString.hpp" #include +#include namespace Acts::detail::Test { @@ -196,6 +198,9 @@ class MultiTrajectoryTestsCommon { alwaysPresent(ts); ts.allocateCalibrated(5); BOOST_CHECK(ts.hasCalibrated()); + BOOST_CHECK_EQUAL(ts.template calibrated<5>(), ActsVector<5>::Zero()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<5>(), + ActsSquareMatrix<5>::Zero()); ts = t.getTrackState(t.addTrackState(PM::None)); BOOST_CHECK(!ts.hasPredicted()); @@ -242,6 +247,9 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK(!ts.hasJacobian()); ts.allocateCalibrated(5); BOOST_CHECK(ts.hasCalibrated()); + BOOST_CHECK_EQUAL(ts.template calibrated<5>(), ActsVector<5>::Zero()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<5>(), + ActsSquareMatrix<5>::Zero()); ts = t.getTrackState(t.addTrackState(PM::Jacobian)); BOOST_CHECK(!ts.hasPredicted()); @@ -300,6 +308,9 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK(ts.hasSmoothed()); BOOST_CHECK(ts.hasCalibrated()); BOOST_CHECK(!ts.hasJacobian()); + BOOST_CHECK_EQUAL(ts.template calibrated<5>(), ActsVector<5>::Zero()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<5>(), + ActsSquareMatrix<5>::Zero()); ts.addComponents(PM::Jacobian); BOOST_CHECK(ts.hasPredicted()); @@ -378,7 +389,13 @@ class MultiTrajectoryTestsCommon { { // reset measurements w/ full parameters auto [measPar, measCov] = generateBoundParametersCovariance(rng, {}); + // Explicitly unset to avoid error below + tsb.unset(TrackStatePropMask::Calibrated); tsb.allocateCalibrated(eBoundSize); + BOOST_CHECK_EQUAL(tsb.template calibrated(), + BoundVector::Zero()); + BOOST_CHECK_EQUAL(tsb.template calibratedCovariance(), + BoundMatrix::Zero()); tsb.template calibrated() = measPar; tsb.template calibratedCovariance() = measCov; BOOST_CHECK_EQUAL(tsa.template calibrated(), measPar); @@ -394,7 +411,15 @@ class MultiTrajectoryTestsCommon { std::size_t nMeasurements = tsb.effectiveCalibrated().rows(); auto effPar = measPar.head(nMeasurements); auto effCov = measCov.topLeftCorner(nMeasurements, nMeasurements); - tsb.allocateCalibrated(eBoundSize); + tsb.allocateCalibrated( + eBoundSize); // no allocation, but we expect it to be reset to zero + // with this overload + BOOST_CHECK_EQUAL(tsa.effectiveCalibrated(), BoundVector::Zero()); + BOOST_CHECK_EQUAL(tsa.effectiveCalibratedCovariance(), + BoundMatrix::Zero()); + BOOST_CHECK_EQUAL(tsa.effectiveCalibrated(), BoundVector::Zero()); + BOOST_CHECK_EQUAL(tsa.effectiveCalibratedCovariance(), + BoundMatrix::Zero()); tsb.effectiveCalibrated() = effPar; tsb.effectiveCalibratedCovariance() = effCov; BOOST_CHECK_EQUAL(tsa.effectiveCalibrated(), effPar); @@ -444,6 +469,8 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK_EQUAL( ts.getUncalibratedSourceLink().template get().sourceId, pc.sourceLink.sourceId); + // Explicitly unset to avoid error below + ts.unset(TrackStatePropMask::Calibrated); testSourceLinkCalibratorReturn( gctx, cctx, SourceLink{ttsb.sourceLink}, ts); BOOST_CHECK_EQUAL( @@ -762,6 +789,8 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK_NE(ts1.pathLength(), ts2.pathLength()); BOOST_CHECK_NE(&ts1.referenceSurface(), &ts2.referenceSurface()); + // Explicitly unset to avoid error below + ts1.unset(TrackStatePropMask::Calibrated); ts1.copyFrom(ts2); BOOST_CHECK_EQUAL(ts1.predicted(), ts2.predicted()); @@ -795,6 +824,8 @@ class MultiTrajectoryTestsCommon { ts2 = mkts(PM::Predicted | PM::Jacobian | PM::Calibrated); ts2.copyFrom(ots2, PM::Predicted | PM::Jacobian | PM::Calibrated); // copy into empty ts, only copy some + // explicitly unset to avoid error below + ts1.unset(TrackStatePropMask::Calibrated); ts1.copyFrom(ots1); // reset to original // is different again BOOST_CHECK_NE(ts1.predicted(), ts2.predicted()); @@ -816,6 +847,8 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK_NE(ts1.pathLength(), ts2.pathLength()); BOOST_CHECK_NE(&ts1.referenceSurface(), &ts2.referenceSurface()); + // Explicitly unset to avoid error below + ts1.unset(TrackStatePropMask::Calibrated); ts1.copyFrom(ts2); // some components are same now @@ -1193,5 +1226,41 @@ class MultiTrajectoryTestsCommon { // runTest([](const std::string& c) { return c; }); // runTest([](std::string_view c) { return c; }); } + + void testMultiTrajectoryAllocateCalibratedInit( + std::default_random_engine& rng) { + trajectory_t traj = m_factory.create(); + auto ts = traj.makeTrackState(TrackStatePropMask::All); + + BOOST_CHECK_EQUAL(ts.calibratedSize(), MultiTrajectoryTraits::kInvalid); + + auto [par, cov] = generateBoundParametersCovariance(rng, {}); + + ts.template allocateCalibrated(par.head<3>(), cov.topLeftCorner<3, 3>()); + + BOOST_CHECK_EQUAL(ts.calibratedSize(), 3); + BOOST_CHECK_EQUAL(ts.template calibrated<3>(), par.head<3>()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<3>(), + (cov.topLeftCorner<3, 3>())); + + auto [par2, cov2] = generateBoundParametersCovariance(rng, {}); + + ts.allocateCalibrated(3); + BOOST_CHECK_EQUAL(ts.template calibrated<3>(), ActsVector<3>::Zero()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<3>(), + ActsSquareMatrix<3>::Zero()); + + ts.template allocateCalibrated(par2.head<3>(), cov2.topLeftCorner<3, 3>()); + BOOST_CHECK_EQUAL(ts.calibratedSize(), 3); + // The values are re-assigned + BOOST_CHECK_EQUAL(ts.template calibrated<3>(), par2.head<3>()); + BOOST_CHECK_EQUAL(ts.template calibratedCovariance<3>(), + (cov2.topLeftCorner<3, 3>())); + + // Re-allocation with a different measurement dimension is an error + BOOST_CHECK_THROW(ts.template allocateCalibrated( + par2.head<4>(), cov2.topLeftCorner<4, 4>()), + std::invalid_argument); + } }; } // namespace Acts::detail::Test diff --git a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp index 315dd2379b0..0bc2e5680cc 100644 --- a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp +++ b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp @@ -464,7 +464,6 @@ 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/src/EventData/VectorMultiTrajectory.cpp b/Core/src/EventData/VectorMultiTrajectory.cpp index 66629d65f12..f25d64db4c5 100644 --- a/Core/src/EventData/VectorMultiTrajectory.cpp +++ b/Core/src/EventData/VectorMultiTrajectory.cpp @@ -212,6 +212,7 @@ void VectorMultiTrajectory::unset_impl(TrackStatePropMask target, case PM::Calibrated: m_measOffset[istate] = kInvalid; m_measCovOffset[istate] = kInvalid; + m_index[istate].measdim = kInvalid; break; default: throw std::domain_error{"Unable to unset this component"}; diff --git a/Core/src/EventData/VectorTrackContainer.cpp b/Core/src/EventData/VectorTrackContainer.cpp index dc7cca761d1..5be40fae6c8 100644 --- a/Core/src/EventData/VectorTrackContainer.cpp +++ b/Core/src/EventData/VectorTrackContainer.cpp @@ -167,4 +167,8 @@ void VectorTrackContainer::clear() { } } +std::size_t VectorTrackContainer::size() const { + return m_tipIndex.size(); +} + } // namespace Acts diff --git a/Examples/Algorithms/TrackFitting/src/RefittingCalibrator.cpp b/Examples/Algorithms/TrackFitting/src/RefittingCalibrator.cpp index b54efd0dcb4..eaf2f74bffa 100644 --- a/Examples/Algorithms/TrackFitting/src/RefittingCalibrator.cpp +++ b/Examples/Algorithms/TrackFitting/src/RefittingCalibrator.cpp @@ -30,11 +30,9 @@ void RefittingCalibrator::calibrate(const Acts::GeometryContext& /*gctx*/, using namespace Acts; constexpr int Size = decltype(N)::value; - trackState.allocateCalibrated(Size); - trackState.template calibrated() = - sl.state.template calibrated(); - trackState.template calibratedCovariance() = - sl.state.template calibratedCovariance(); + trackState.allocateCalibrated( + sl.state.template calibrated().eval(), + sl.state.template calibratedCovariance().eval()); }); trackState.setBoundSubspaceIndices(sl.state.boundSubspaceIndices()); diff --git a/Examples/Framework/ML/src/NeuralCalibrator.cpp b/Examples/Framework/ML/src/NeuralCalibrator.cpp index 67c6e76db57..83e4d11354e 100644 --- a/Examples/Framework/ML/src/NeuralCalibrator.cpp +++ b/Examples/Framework/ML/src/NeuralCalibrator.cpp @@ -189,9 +189,7 @@ void ActsExamples::NeuralCalibrator::calibrate( calibratedCovariance(boundLoc0, boundLoc0) = output[iVar0]; calibratedCovariance(boundLoc1, boundLoc1) = output[iVar0 + 1]; - trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = calibratedParameters; - trackState.calibratedCovariance() = calibratedCovariance; + trackState.allocateCalibrated(calibratedParameters, calibratedCovariance); trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Examples/Framework/src/EventData/MeasurementCalibration.cpp b/Examples/Framework/src/EventData/MeasurementCalibration.cpp index b4764844770..190d37153bb 100644 --- a/Examples/Framework/src/EventData/MeasurementCalibration.cpp +++ b/Examples/Framework/src/EventData/MeasurementCalibration.cpp @@ -41,10 +41,8 @@ void ActsExamples::PassThroughCalibrator::calibrate( static_cast>( measurement); - trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = fixedMeasurement.parameters(); - trackState.calibratedCovariance() = - fixedMeasurement.covariance(); + trackState.allocateCalibrated(fixedMeasurement.parameters().eval(), + fixedMeasurement.covariance().eval()); trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Examples/Framework/src/EventData/ScalingCalibrator.cpp b/Examples/Framework/src/EventData/ScalingCalibrator.cpp index ae5c1eca4fe..2a956902513 100644 --- a/Examples/Framework/src/EventData/ScalingCalibrator.cpp +++ b/Examples/Framework/src/EventData/ScalingCalibrator.cpp @@ -178,9 +178,7 @@ void ActsExamples::ScalingCalibrator::calibrate( calibratedCovariance(boundLoc0, boundLoc0) *= ct.x_scale; calibratedCovariance(boundLoc1, boundLoc1) *= ct.y_scale; - trackState.allocateCalibrated(kMeasurementSize); - trackState.calibrated() = calibratedParameters; - trackState.calibratedCovariance() = calibratedCovariance; + trackState.allocateCalibrated(calibratedParameters, calibratedCovariance); trackState.setSubspaceIndices(fixedMeasurement.subspaceIndices()); }); } diff --git a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackStateContainer.hpp b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackStateContainer.hpp index e503f3ca2f3..53eebf0e9b4 100644 --- a/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackStateContainer.hpp +++ b/Plugins/Podio/include/Acts/Plugins/Podio/PodioTrackStateContainer.hpp @@ -70,9 +70,9 @@ class PodioTrackStateContainerBase { case "smoothed"_hash: return data.ismoothed != kInvalid; case "calibrated"_hash: - return data.measdim != 0; + return data.measdim != kInvalid; case "calibratedCov"_hash: - return data.measdim != 0; + return data.measdim != kInvalid; case "jacobian"_hash: return data.ijacobian != kInvalid; case "projector"_hash: @@ -472,7 +472,7 @@ class MutablePodioTrackStateContainer final m_jacs->create(); data.ijacobian = m_jacs->size() - 1; } - data.measdim = 0; + data.measdim = kInvalid; data.hasProjector = false; if (ACTS_CHECK_BIT(mask, TrackStatePropMask::Calibrated)) { data.hasProjector = true; @@ -592,7 +592,7 @@ class MutablePodioTrackStateContainer final data.ijacobian = kInvalid; break; case TrackStatePropMask::Calibrated: - data.measdim = 0; + data.measdim = kInvalid; break; default: throw std::domain_error{"Unable to unset this component"}; @@ -615,10 +615,35 @@ class MutablePodioTrackStateContainer final {hashedKey, std::make_unique>(key)}); } - void allocateCalibrated_impl(IndexType istate, std::size_t measdim) { - assert(measdim > 0 && "Zero measdim not supported"); + template + void allocateCalibrated_impl(IndexType istate, + const Eigen::DenseBase& val, + const Eigen::DenseBase& cov) + + requires(Eigen::PlainObjectBase::RowsAtCompileTime > 0 && + Eigen::PlainObjectBase::RowsAtCompileTime <= eBoundSize && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::RowsAtCompileTime && + Eigen::PlainObjectBase::RowsAtCompileTime == + Eigen::PlainObjectBase::ColsAtCompileTime) + { + constexpr std::size_t measdim = val_t::RowsAtCompileTime; + auto& data = PodioUtil::getDataMutable(m_collection->at(istate)); + + if (data.measdim != kInvalid && data.measdim != measdim) { + throw std::invalid_argument{ + "Measurement dimension does not match the allocated dimension"}; + } + data.measdim = measdim; + + Eigen::Map> valMap(data.measurement.data()); + valMap = val; + + Eigen::Map> covMap( + data.measurementCovariance.data()); + covMap = cov; } void setUncalibratedSourceLink_impl(IndexType istate, diff --git a/Tests/Benchmarks/TrackEdmBenchmark.cpp b/Tests/Benchmarks/TrackEdmBenchmark.cpp index b063254e154..a85b0482be2 100644 --- a/Tests/Benchmarks/TrackEdmBenchmark.cpp +++ b/Tests/Benchmarks/TrackEdmBenchmark.cpp @@ -111,6 +111,8 @@ int main(int /*argc*/, char** /*argv[]*/) { << std::endl; for (std::size_t r = 0; r < runs; ++r) { tc.clear(); + output.clear(); + for (std::size_t i = 0; i < nTracks; ++i) { auto track = tc.makeTrack(); @@ -133,17 +135,17 @@ int main(int /*argc*/, char** /*argv[]*/) { trackState.typeFlags().set(TrackStateFlag::MaterialFlag); } else { BenchmarkSourceLink bsl{gid, 123}; - trackState.allocateCalibrated(measDimDist(rng)); + std::size_t measdim = measDimDist(rng); const auto& [predicted, covariance] = parameters(); trackState.predicted() = predicted; trackState.predictedCovariance() = covariance; visit_measurement( - trackState.calibratedSize(), + measdim, [&](std::integral_constant /*d*/) { - trackState.calibrated().setOnes(); - trackState.calibratedCovariance().setIdentity(); + trackState.allocateCalibrated(ActsVector::Ones(), + ActsSquareMatrix::Identity()); std::array indices{0}; std::iota(indices.begin(), indices.end(), 0); diff --git a/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp b/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp index 6a3c1aafc3e..421fcc3c62f 100644 --- a/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp +++ b/Tests/UnitTests/Core/EventData/MultiTrajectoryTests.cpp @@ -203,6 +203,11 @@ BOOST_AUTO_TEST_CASE(MultiTrajectoryExtraColumnsRuntime) { ct.testMultiTrajectoryExtraColumnsRuntime(); } +BOOST_AUTO_TEST_CASE(MultiTrajectoryAllocateCalibratedInit) { + CommonTests ct; + ct.testMultiTrajectoryAllocateCalibratedInit(rng); +} + BOOST_AUTO_TEST_CASE(MemoryStats) { using namespace boost::histogram; using cat = axis::category; diff --git a/Tests/UnitTests/Core/EventData/TrackTestsExtra.cpp b/Tests/UnitTests/Core/EventData/TrackTestsExtra.cpp index ca444466216..f2f27ed8522 100644 --- a/Tests/UnitTests/Core/EventData/TrackTestsExtra.cpp +++ b/Tests/UnitTests/Core/EventData/TrackTestsExtra.cpp @@ -457,8 +457,6 @@ BOOST_AUTO_TEST_CASE(CopyTrackProxyCalibrated) { auto track1 = tc.makeTrack(); auto ts = track1.appendTrackState(TrackStatePropMask::Calibrated); ts.allocateCalibrated(kMeasurementSize); - ts.calibrated() = Vector3::Ones(); - ts.calibratedCovariance() = SquareMatrix3::Identity(); ts.setSubspaceIndices(BoundSubspaceIndices{}); auto tsCopy = track1.appendTrackState(TrackStatePropMask::Calibrated); diff --git a/Tests/UnitTests/Plugins/Podio/PodioTrackStateContainerTest.cpp b/Tests/UnitTests/Plugins/Podio/PodioTrackStateContainerTest.cpp index 2be4cc1411a..9169568fd60 100644 --- a/Tests/UnitTests/Plugins/Podio/PodioTrackStateContainerTest.cpp +++ b/Tests/UnitTests/Plugins/Podio/PodioTrackStateContainerTest.cpp @@ -202,6 +202,11 @@ BOOST_AUTO_TEST_CASE(MultiTrajectoryExtraColumnsRuntime) { ct.testMultiTrajectoryExtraColumnsRuntime(); } +BOOST_AUTO_TEST_CASE(MultiTrajectoryAllocateCalibratedInit) { + CommonTests ct; + ct.testMultiTrajectoryAllocateCalibratedInit(rng); +} + BOOST_AUTO_TEST_CASE(WriteToPodioFrame) { using namespace HashedStringLiteral;