Skip to content

Commit

Permalink
refactor!: Clean track EDM projector (#3605)
Browse files Browse the repository at this point in the history
Clean deprecated projector functions from `TrackStateProxy` and rename the new methods to something recognizable. Also deals with the ACTS internal downstream changes.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Enhanced handling of projector subspace indices across various components for improved accuracy in alignment and calibration processes.

- **Bug Fixes**
	- Updated method calls to ensure consistent use of `setProjectorSubspaceIndices`, enhancing the clarity and functionality of the track state management.

- **Documentation**
	- Minor adjustments to comments for better clarity on the changes related to projector handling.

- **Tests**
	- Updated test cases to reflect changes in method names and ensure proper validation of projector subspace indices.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
andiwand authored Nov 29, 2024
1 parent e10cd54 commit 2eee794
Show file tree
Hide file tree
Showing 27 changed files with 127 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ TrackAlignmentState trackAlignmentState(
measdim) = measCovariance;

// (b) Get and fill the bound parameters to measurement projection matrix
const ActsDynamicMatrix H = state.effectiveProjector();
const ActsDynamicMatrix H =
state.projectorSubspaceHelper().fullProjector().topLeftCorner(
measdim, eBoundSize);
alignState.projectionMatrix.block(iMeasurement, iParams, measdim,
eBoundSize) = H;
// (c) Get and fill the residual
Expand Down
30 changes: 15 additions & 15 deletions Core/include/Acts/EventData/SubspaceHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
#include "Acts/Utilities/AlgebraHelpers.hpp"
#include "Acts/Utilities/Enumerate.hpp"

#include <bitset>
#include <span>
#include <ranges>

#include <boost/container/static_vector.hpp>

Expand All @@ -25,30 +24,30 @@ namespace Acts {
///
/// Indices must be unique and within the full size of the subspace
///
/// @tparam Container type of the container
/// @tparam index_range_t the type of the container of indices
///
/// @param container the container of indices
/// @param indexRange the range of indices
/// @param fullSize the full size of the subspace
/// @param subspaceSize the size of the subspace
///
/// @return true if the indices are consistent
template <typename Container>
inline static bool checkSubspaceIndices(const Container& container,
template <std::ranges::sized_range index_range_t>
inline static bool checkSubspaceIndices(const index_range_t& indexRange,
std::size_t fullSize,
std::size_t subspaceSize) {
if (subspaceSize > fullSize) {
return false;
}
if (static_cast<std::size_t>(container.size()) != subspaceSize) {
if (static_cast<std::size_t>(indexRange.size()) != subspaceSize) {
return false;
}
for (auto it = container.begin(); it != container.end();) {
for (auto it = indexRange.begin(); it != indexRange.end();) {
auto index = *it;
if (index >= fullSize) {
return false;
}
++it;
if (std::find(it, container.end(), index) != container.end()) {
if (std::find(it, indexRange.end(), index) != indexRange.end()) {
return false;
}
}
Expand All @@ -69,7 +68,8 @@ inline static SerializedSubspaceIndices serializeSubspaceIndices(
{
SerializedSubspaceIndices result = 0;
for (std::size_t i = 0; i < FullSize; ++i) {
result |= static_cast<SerializedSubspaceIndices>(indices[i]) << (i * 8);
result |= static_cast<SerializedSubspaceIndices>(indices[i] & 0xFF)
<< (i * 8);
}
return result;
}
Expand All @@ -88,7 +88,7 @@ inline static SubspaceIndices<FullSize> deserializeSubspaceIndices(
{
SubspaceIndices<FullSize> result;
for (std::size_t i = 0; i < FullSize; ++i) {
result[i] = static_cast<std::uint8_t>(serialized >> (i * 8));
result[i] = static_cast<std::uint8_t>((serialized >> (i * 8)) & 0xFF);
}
return result;
}
Expand Down Expand Up @@ -187,8 +187,8 @@ class VariableSubspaceHelper
using IndexType = index_t;
using Container = boost::container::static_vector<IndexType, FullSize>;

template <typename OtherContainer>
explicit VariableSubspaceHelper(const OtherContainer& indices) {
template <std::ranges::sized_range other_index_range_t>
explicit VariableSubspaceHelper(const other_index_range_t& indices) {
assert(checkSubspaceIndices(indices, kFullSize, indices.size()) &&
"Invalid indices");
m_indices.resize(indices.size());
Expand Down Expand Up @@ -236,8 +236,8 @@ class FixedSubspaceHelper
using IndexType = index_t;
using Container = std::array<IndexType, kSubspaceSize>;

template <typename OtherContainer>
explicit FixedSubspaceHelper(const OtherContainer& indices) {
template <std::ranges::sized_range other_index_range_t>
explicit FixedSubspaceHelper(const other_index_range_t& indices) {
assert(checkSubspaceIndices(indices, kFullSize, kSubspaceSize) &&
"Invalid indices");
std::transform(indices.begin(), indices.end(), m_indices.begin(),
Expand Down
171 changes: 35 additions & 136 deletions Core/include/Acts/EventData/TrackStateProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/TrackParametrization.hpp"
#include "Acts/EventData/SourceLink.hpp"
#include "Acts/EventData/SubspaceHelpers.hpp"
Expand All @@ -17,11 +16,11 @@
#include "Acts/EventData/TrackStateType.hpp"
#include "Acts/EventData/Types.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Utilities/AlgebraHelpers.hpp"
#include "Acts/Utilities/HashedString.hpp"
#include "Acts/Utilities/Helpers.hpp"

#include <cstddef>
#include <ranges>
#include <span>

#include <Eigen/Core>
Expand Down Expand Up @@ -127,11 +126,6 @@ struct TrackStateTraits {
typename detail_lt::DynamicSizeTypes<ReadOnly>::CoefficientsMap;
using EffectiveCalibratedCovariance =
typename detail_lt::DynamicSizeTypes<ReadOnly>::CovarianceMap;

constexpr static auto ProjectorFlags = Eigen::RowMajor | Eigen::AutoAlign;
using Projector = Eigen::Matrix<double, M, eBoundSize, ProjectorFlags>;
using EffectiveProjector = Eigen::Matrix<double, Eigen::Dynamic, eBoundSize,
ProjectorFlags, M, eBoundSize>;
};

/// Proxy object to access a single point on the trajectory.
Expand Down Expand Up @@ -207,17 +201,6 @@ class TrackStateProxy {
/// Sentinel value that indicates an invalid index
static constexpr IndexType kInvalid = kTrackIndexInvalid;

/// Matrix representing the projector (measurement mapping function) for a
/// measurement. This is not a map type, but an actual matrix. This matrix
/// is always \f$M \times M\f$, even if the local measurement dimension is lower.
/// The actual \f$N\times M\f$ projector is given by the top \f$N\f$ rows.
using Projector = typename TrackStateTraits<M, ReadOnly>::Projector;

/// Dynamic variant of the projector matrix
/// @warning Using this type is discouraged, as it has a runtime overhead
using EffectiveProjector =
typename TrackStateTraits<M, ReadOnly>::EffectiveProjector;

/// The track state container backend given as a template parameter
using Trajectory = trajectory_t;

Expand Down Expand Up @@ -615,145 +598,61 @@ class TrackStateProxy {
///
/// @{

/// Returns the projector (measurement mapping function) for this track
/// state. It is derived from the uncalibrated measurement
/// @note This function returns the overallocated projector. This means it
/// is of dimension MxM, where M is the maximum number of measurement
/// dimensions. The NxM submatrix, where N is the actual dimension of the
/// measurement, is located in the top left corner, everything else is zero.
/// @return The overallocated projector
Projector projector() const;

/// Returns whether a projector is set
/// @return Whether it is set
bool hasProjector() const { return has<hashString("projector")>(); }

/// Returns the projector (measurement mapping function) for this track
/// state. It is derived from the uncalibrated measurement
/// @warning This function returns the effective projector. This means it
/// is of dimension \f$N\times M\f$, where \f$N\f$ is the actual dimension of the
/// measurement.
/// @return The effective projector
EffectiveProjector effectiveProjector() const {
return projector().topLeftCorner(calibratedSize(), M);
}

/// Set the projector on this track state
/// This will convert the projector to a more compact bitset representation
/// and store it.
/// @param projector The projector in the form of a dense matrix
/// @note @p projector is assumed to only have 0s or 1s as components.
template <typename Derived>
[[deprecated("use setProjector(span) instead")]] void setProjector(
const Eigen::MatrixBase<Derived>& projector)
requires(!ReadOnly)
/// Set the projector subspace indices
/// @param subspaceIndices The projector subspace indices to set
template <std::ranges::sized_range index_range_t>
void setProjectorSubspaceIndices(const index_range_t& subspaceIndices)
requires(!ReadOnly &&
std::convertible_to<std::ranges::range_value_t<index_range_t>,
std::uint8_t>)
{
constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
constexpr int cols = Eigen::MatrixBase<Derived>::ColsAtCompileTime;

static_assert(rows != -1 && cols != -1,
"Assignment of dynamic matrices is currently not supported.");

assert(has<hashString("projector")>());

static_assert(rows <= M, "Given projector has too many rows");
static_assert(cols <= eBoundSize, "Given projector has too many columns");

// set up full size projector with only zeros
typename TrackStateProxy::Projector fullProjector =
decltype(fullProjector)::Zero();

// assign (potentially) smaller actual projector to matrix, preserving
// zeroes outside of smaller matrix block.
fullProjector.template topLeftCorner<rows, cols>() = projector;

// convert to bitset before storing
ProjectorBitset projectorBitset = matrixToBitset(fullProjector).to_ulong();
setProjectorBitset(projectorBitset);
}

/// Directly get the projector bitset, a compressed form of a projection
/// matrix
/// @note This is mainly to copy explicitly a projector from one state
/// to another. Use the `projector` or `effectiveProjector` method if
/// you want to access the matrix.
/// @return The projector bitset
[[deprecated("use projector() instead")]] ProjectorBitset projectorBitset()
const {
return variableBoundSubspaceHelper().projectorBitset();
assert(subspaceIndices.size() <= eBoundSize);
BoundSubspaceIndices boundSubspace{};
std::transform(subspaceIndices.begin(), subspaceIndices.end(),
boundSubspace.begin(),
[](auto i) { return static_cast<std::uint8_t>(i); });
component<SerializedSubspaceIndices, hashString("projector")>() =
serializeSubspaceIndices(boundSubspace);
}

/// Set the projector bitset, a compressed form of a projection matrix
/// @param proj The projector bitset
///
/// @note This is mainly to copy explicitly a projector from one state
/// to another. If you have a projection matrix, set it with
/// `setProjector`.
[[deprecated("use setProjector(span) instead")]] void setProjectorBitset(
ProjectorBitset proj)
requires(!ReadOnly)
{
BoundMatrix projMatrix = bitsetToMatrix<BoundMatrix>(proj);
BoundSubspaceIndices boundSubspace =
projectorToSubspaceIndices<eBoundSize>(projMatrix);
setBoundSubspaceIndices(boundSubspace);
}
/// Returns whether a projector is set
/// @return Whether it is set
bool hasProjector() const { return has<hashString("projector")>(); }

BoundSubspaceIndices boundSubspaceIndices() const {
/// Returns the projector subspace indices
/// @return The projector subspace indices
BoundSubspaceIndices projectorSubspaceIndices() const {
assert(has<hashString("projector")>());
return deserializeSubspaceIndices<eBoundSize>(
component<SerializedSubspaceIndices, hashString("projector")>());
}

/// Returns the projector subspace indices
/// @return The projector subspace indices
template <std::size_t measdim>
SubspaceIndices<measdim> subspaceIndices() const {
BoundSubspaceIndices boundSubspace = BoundSubspaceIndices();
SubspaceIndices<measdim> projectorSubspaceIndices() const {
BoundSubspaceIndices boundSubspace = projectorSubspaceIndices();
SubspaceIndices<measdim> subspace;
std::copy(boundSubspace.begin(), boundSubspace.begin() + measdim,
subspace.begin());
return subspace;
}

void setBoundSubspaceIndices(BoundSubspaceIndices boundSubspace)
requires(!ReadOnly)
{
assert(has<hashString("projector")>());
component<SerializedSubspaceIndices, hashString("projector")>() =
serializeSubspaceIndices(boundSubspace);
}

template <std::size_t measdim>
void setSubspaceIndices(SubspaceIndices<measdim> subspace)
requires(!ReadOnly && measdim <= eBoundSize)
{
assert(has<hashString("projector")>());
BoundSubspaceIndices boundSubspace{};
std::copy(subspace.begin(), subspace.end(), boundSubspace.begin());
setBoundSubspaceIndices(boundSubspace);
}

template <std::size_t measdim, typename index_t>
void setSubspaceIndices(std::array<index_t, measdim> subspaceIndices)
requires(!ReadOnly && measdim <= eBoundSize)
{
assert(has<hashString("projector")>());
BoundSubspaceIndices boundSubspace{};
std::transform(subspaceIndices.begin(), subspaceIndices.end(),
boundSubspace.begin(),
[](index_t i) { return static_cast<std::uint8_t>(i); });
setBoundSubspaceIndices(boundSubspace);
}

VariableBoundSubspaceHelper variableBoundSubspaceHelper() const {
BoundSubspaceIndices boundSubspace = boundSubspaceIndices();
/// Creates a variable size subspace helper
/// @return The subspace helper
VariableBoundSubspaceHelper projectorSubspaceHelper() const {
BoundSubspaceIndices boundSubspace = projectorSubspaceIndices();
std::span<std::uint8_t> validSubspaceIndices(
boundSubspace.begin(), boundSubspace.begin() + calibratedSize());
return VariableBoundSubspaceHelper(validSubspaceIndices);
}

/// Creates a fixed size subspace helper
/// @return The subspace helper
template <std::size_t measdim>
FixedBoundSubspaceHelper<measdim> fixedBoundSubspaceHelper() const {
SubspaceIndices<measdim> subspace = subspaceIndices<measdim>();
FixedBoundSubspaceHelper<measdim> projectorSubspaceHelper() const {
SubspaceIndices<measdim> subspace = projectorSubspaceIndices<measdim>();
return FixedBoundSubspaceHelper<measdim>(subspace);
}

Expand Down Expand Up @@ -1028,7 +927,7 @@ class TrackStateProxy {
other.template calibratedCovariance<measdim>().eval());
});

setBoundSubspaceIndices(other.boundSubspaceIndices());
setProjectorSubspaceIndices(other.projectorSubspaceIndices());
}
} else {
if (ACTS_CHECK_BIT(mask, PM::Predicted) &&
Expand Down Expand Up @@ -1073,7 +972,7 @@ class TrackStateProxy {
other.template calibratedCovariance<measdim>().eval());
});

setBoundSubspaceIndices(other.boundSubspaceIndices());
setProjectorSubspaceIndices(other.projectorSubspaceIndices());
}
}

Expand Down
5 changes: 0 additions & 5 deletions Core/include/Acts/EventData/TrackStateProxy.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ inline auto TrackStateProxy<D, M, ReadOnly>::covariance() const
}
}

template <typename D, std::size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::projector() const -> Projector {
return variableBoundSubspaceHelper().fullProjector();
}

template <typename D, std::size_t M, bool ReadOnly>
inline auto TrackStateProxy<D, M, ReadOnly>::getUncalibratedSourceLink() const
-> SourceLink {
Expand Down
6 changes: 0 additions & 6 deletions Core/include/Acts/EventData/TrackStateProxyConcept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,6 @@ concept TrackStateProxyConcept =
{ cv.hasProjector() } -> std::same_as<bool>;
{ v.hasProjector() } -> std::same_as<bool>;

{ cv.effectiveProjector() } -> std::same_as<detail::EffectiveProjector>;
{ v.effectiveProjector() } -> std::same_as<detail::EffectiveProjector>;

{ cv.projectorBitset() } -> std::same_as<ProjectorBitset>;
{ v.projectorBitset() } -> std::same_as<ProjectorBitset>;

{ cv.getUncalibratedSourceLink() } -> std::same_as<SourceLink>;
{ v.getUncalibratedSourceLink() } -> std::same_as<SourceLink>;

Expand Down
Loading

0 comments on commit 2eee794

Please sign in to comment.