Skip to content

Commit

Permalink
feat: Add measurement emplace functions (#3627)
Browse files Browse the repository at this point in the history
Recently, the measurement EDM was replaced by a memory-optimal bulk storage, but this makes it a bit harder to add new measurements to a collection. This commit adds two new emplace functions which variadically allow users to add measurements, similar to how they might use `std::vector::emplace_back`.
  • Loading branch information
stephenswat authored Sep 26, 2024
1 parent 0bf2465 commit a129eeb
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 16 deletions.
8 changes: 1 addition & 7 deletions Examples/Algorithms/Digitization/src/MeasurementCreation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ ActsExamples::VariableBoundMeasurementProxy ActsExamples::createMeasurement(
return Acts::visit_measurement(
dParams.indices.size(), [&](auto dim) -> VariableBoundMeasurementProxy {
auto [indices, par, cov] = measurementConstituents<dim>(dParams);
FixedBoundMeasurementProxy<dim> measurement =
container.makeMeasurement<dim>();
measurement.setSourceLink(sl);
measurement.setSubspaceIndices(indices);
measurement.parameters() = par;
measurement.covariance() = cov;
return measurement;
return container.emplaceMeasurement<dim>(sl, indices, par, cov);
});
}
68 changes: 61 additions & 7 deletions Examples/Framework/include/ActsExamples/EventData/Measurement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
#include "Acts/EventData/detail/CalculateResiduals.hpp"
#include "Acts/EventData/detail/ParameterTraits.hpp"
#include "Acts/EventData/detail/PrintParameters.hpp"
#include "ActsExamples/EventData/MeasurementConcept.hpp"

#include <array>
#include <concepts>
#include <cstddef>
#include <iosfwd>
#include <type_traits>
Expand Down Expand Up @@ -117,6 +119,12 @@ class MeasurementContainer {
return getMeasurement<Size>(addMeasurement(Size));
}

template <typename... Args>
VariableProxy emplaceMeasurement(std::uint8_t size, Args&&... args);

template <std::size_t Size, typename... Args>
FixedProxy<Size> emplaceMeasurement(Args&&... args);

template <bool Const>
class IteratorImpl {
public:
Expand Down Expand Up @@ -263,7 +271,7 @@ class MeasurementProxyBase {
void setSubspaceIndices(const IndexContainer& indices)
requires(!ReadOnly)
{
assert(checkSubspaceIndices(indices, FullSize, size()) &&
assert(Acts::checkSubspaceIndices(indices, FullSize, size()) &&
"Invalid indices");
std::transform(indices.begin(), indices.end(),
self().subspaceIndexVector().begin(),
Expand All @@ -282,19 +290,45 @@ class MeasurementProxyBase {
return self().subspaceHelper().expandMatrix(self().covariance());
}

/// @brief Construct the measurement from a sourcelink, subspace vector,
/// parameters, and covariance.
///
template <typename Subspace, typename ParameterDerived,
typename CovarianceDerived>
void fill(const Acts::SourceLink& source_link, Subspace&& subspace,
const Eigen::DenseBase<ParameterDerived>& parameters,
const Eigen::DenseBase<CovarianceDerived>& covariance)
requires(!ReadOnly)
{
setSourceLink(source_link);
self().setSubspaceIndices(std::forward<Subspace>(subspace));
self().parameters() = parameters;
self().covariance() = covariance;
}

/// @brief Construct the measurement from a sourcelink, subspace vector,
/// parameters, and covariance.
///
template <MeasurementConcept OtherDerived>
void fill(const OtherDerived& other)
requires(!ReadOnly)
{
assert(size() == other.size() && "Size mismatch");
fill(other.sourceLink(), other.subspaceIndexVector(), other.parameters(),
other.covariance());
}

/// @brief Copy the data from another measurement
/// @tparam OtherDerived The derived measurement proxy class of the other
/// measurement
/// @param other The other measurement proxy
template <typename OtherDerived>
void copyFrom(const OtherDerived& other)
requires(!ReadOnly)
requires(!ReadOnly) && requires {
{ this->fill(other) };
}
{
assert(size() == other.size() && "Size mismatch");
setSourceLink(other.sourceLink());
self().subspaceIndexVector() = other.subspaceIndexVector();
self().parameters() = other.parameters();
self().covariance() = other.covariance();
fill(other);
}

protected:
Expand Down Expand Up @@ -485,4 +519,24 @@ class VariableMeasurementProxy
}
};

template <typename... Args>
MeasurementContainer::VariableProxy MeasurementContainer::emplaceMeasurement(
std::uint8_t size, Args&&... args) {
VariableProxy meas = makeMeasurement(size);

meas.fill(std::forward<Args>(args)...);

return meas;
}

template <std::size_t Size, typename... Args>
MeasurementContainer::FixedProxy<Size> MeasurementContainer::emplaceMeasurement(
Args&&... args) {
FixedProxy<Size> meas = makeMeasurement<Size>();

meas.fill(std::forward<Args>(args)...);

return meas;
}

} // namespace ActsExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/EventData/SourceLink.hpp"

#include <concepts>

namespace ActsExamples {

template <typename T>
concept MeasurementConcept = requires(const T& m) {
{ m.size() } -> std::integral;
{ m.sourceLink() } -> Acts::Concepts::decayed_same_as<Acts::SourceLink>;
{ m.subspaceIndexVector() };
{ m.parameters() };
{ m.covariance() };
};
} // namespace ActsExamples
3 changes: 1 addition & 2 deletions Examples/Io/Csv/src/CsvMeasurementReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,7 @@ ActsExamples::ProcessCode ActsExamples::CsvMeasurementReader::read(

MeasurementContainer measurements;
for (auto& [_, meas] : orderedMeasurements) {
auto measurement = measurements.makeMeasurement(meas.size());
measurement.copyFrom(meas);
measurements.emplaceMeasurement(meas.size(), meas);
}

// Generate measurement-particles-map
Expand Down
39 changes: 39 additions & 0 deletions Tests/UnitTests/Examples/EventData/MeasurementTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ BOOST_DATA_TEST_CASE(VariableBoundOne, bd::make(boundIndices), index) {
sourceOrig);
}

BOOST_DATA_TEST_CASE(VariableBoundOneEmplace, bd::make(boundIndices), index) {
MeasurementContainer container;

auto [params, cov] = generateParametersCovariance<ActsScalar, 1u>(rng);

FixedBoundMeasurementProxy<1> meas =
container.emplaceMeasurement<1>(source, std::array{index}, params, cov);

BOOST_CHECK_EQUAL(meas.size(), 1);
for (auto i : boundIndices) {
BOOST_CHECK_EQUAL(meas.contains(i), i == index);
}
BOOST_CHECK_EQUAL(meas.parameters(), params);
BOOST_CHECK_EQUAL(meas.covariance(), cov);
BOOST_CHECK_EQUAL(meas.sourceLink().template get<TestSourceLink>(),
sourceOrig);
}

BOOST_AUTO_TEST_CASE(VariableBoundAll) {
MeasurementContainer container;

Expand All @@ -92,6 +110,27 @@ BOOST_AUTO_TEST_CASE(VariableBoundAll) {
BOOST_CHECK_EQUAL(meas.sourceLink().get<TestSourceLink>(), sourceOrig);
}

BOOST_AUTO_TEST_CASE(VariableBoundAllEmplace) {
MeasurementContainer container;

auto [params, cov] = generateBoundParametersCovariance(rng);

FixedBoundMeasurementProxy<eBoundSize> meas =
container.emplaceMeasurement<eBoundSize>(
source,
std::array{eBoundLoc0, eBoundLoc1, eBoundTime, eBoundPhi, eBoundTheta,
eBoundQOverP},
params, cov);

BOOST_CHECK_EQUAL(meas.size(), eBoundSize);
for (auto i : boundIndices) {
BOOST_CHECK(meas.contains(i));
}
BOOST_CHECK_EQUAL(meas.parameters(), params);
BOOST_CHECK_EQUAL(meas.covariance(), cov);
BOOST_CHECK_EQUAL(meas.sourceLink().get<TestSourceLink>(), sourceOrig);
}

BOOST_AUTO_TEST_CASE(VariableBoundReassign) {
MeasurementContainer container;

Expand Down

0 comments on commit a129eeb

Please sign in to comment.