Skip to content

Commit

Permalink
feat: Add (optional) Jacobian reversal to Track (#2571)
Browse files Browse the repository at this point in the history
`TrackProxy::reverseTrackStates` can now optionally invert its jacobians, and move them to the correct corresponding track state.
  • Loading branch information
paulgessinger committed Oct 25, 2023
1 parent f84610d commit 6df0704
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 33 deletions.
16 changes: 15 additions & 1 deletion Core/include/Acts/EventData/TrackProxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,19 +673,33 @@ class TrackProxy {
/// "innermost" track state
/// @note This is dangerous with branching track state sequences, as it will break them
/// @note This also automatically forward-links the track!
/// @param invertJacobians Whether to invert the Jacobians of the track states
template <bool RO = ReadOnly, typename = std::enable_if_t<!RO>>
void reverseTrackStates() {
void reverseTrackStates(bool invertJacobians = false) {
IndexType current = tipIndex();
IndexType next = kInvalid;
IndexType prev = kInvalid;

stemIndex() = tipIndex();

// @TODO: Maybe refactor to not need this variable if invertJacobians == false
BoundMatrix nextJacobian;

while (current != kInvalid) {
auto ts = m_container->trackStateContainer().getTrackState(current);
prev = ts.previous();
ts.template component<IndexType>(hashString("next")) = prev;
ts.previous() = next;
if (invertJacobians) {
if (next != kInvalid) {
BoundMatrix curJacobian = ts.jacobian();
ts.jacobian() = nextJacobian.inverse();
nextJacobian = curJacobian;
} else {
nextJacobian = ts.jacobian();
ts.jacobian().setZero();
}
}
next = current;
tipIndex() = current;
current = prev;
Expand Down
32 changes: 0 additions & 32 deletions Tests/UnitTests/Core/EventData/TrackTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,38 +537,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(DynamicColumns, factory_t, holder_types) {
BOOST_CHECK_EQUAL((t.template component<float, "col_a"_hash>()), 5.6f);
}

BOOST_AUTO_TEST_CASE(ReverseTrackStates) {
VectorTrackContainer vtc{};
VectorMultiTrajectory mtj{};
TrackContainer tc{vtc, mtj};

auto t = tc.getTrack(tc.addTrack());

for (size_t i = 0; i < 10; i++) {
t.appendTrackState();
}

std::vector<IndexType> exp;
exp.resize(t.nTrackStates());
std::iota(exp.rbegin(), exp.rend(), 0);
std::vector<IndexType> act;
std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
std::back_inserter(act),
[](const auto& ts) { return ts.index(); });

BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());

// reverse!
t.reverseTrackStates();

std::iota(exp.begin(), exp.end(), 0);
act.clear();
std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
std::back_inserter(act),
[](const auto& ts) { return ts.index(); });
BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());
}

BOOST_AUTO_TEST_CASE(EnsureDynamicColumns) {
TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
tc.addColumn<size_t>("counter");
Expand Down
83 changes: 83 additions & 0 deletions Tests/UnitTests/Core/EventData/TrackTestsExtra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
#include "Acts/EventData/VectorTrackContainer.hpp"
#include "Acts/Utilities/Zip.hpp"

#include <numeric>

using namespace Acts;
using namespace Acts::HashedStringLiteral;
using MultiTrajectoryTraits::IndexType;

BOOST_AUTO_TEST_SUITE(EventDataTrack)

Expand Down Expand Up @@ -99,4 +103,83 @@ BOOST_AUTO_TEST_CASE(CopyTracksIncludingDynamicColumns) {
t5.template component<bool>("odd"));
}
}

BOOST_AUTO_TEST_CASE(ReverseTrackStates) {
VectorTrackContainer vtc{};
VectorMultiTrajectory mtj{};
TrackContainer tc{vtc, mtj};

auto t = tc.getTrack(tc.addTrack());

for (size_t i = 0; i < 4; i++) {
auto ts = t.appendTrackState();
ts.jacobian() = Acts::BoundMatrix::Identity() * i;
}

std::vector<IndexType> exp;
exp.resize(t.nTrackStates());
std::iota(exp.rbegin(), exp.rend(), 0);
std::vector<IndexType> act;
std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
std::back_inserter(act),
[](const auto& ts) { return ts.index(); });

// jacobians count up
for (const auto [e, ts] : zip(exp, t.trackStatesReversed())) {
BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
}

BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());

// reverse!
t.reverseTrackStates();

std::iota(exp.begin(), exp.end(), 0);
act.clear();
std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
std::back_inserter(act),
[](const auto& ts) { return ts.index(); });
BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());

// jacobians stay with their track states
for (const auto [e, ts] : zip(exp, t.trackStatesReversed())) {
BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
}

// back to original!
t.reverseTrackStates();

// jacobians stay with their track states
for (const auto [e, ts] : zip(exp, t.trackStates())) {
BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
}

// reverse with jacobians
t.reverseTrackStates(true);

std::reverse(exp.begin(), exp.end());
std::rotate(exp.rbegin(), std::next(exp.rbegin()), exp.rend());

for (const auto [e, ts] : zip(exp, t.trackStates())) {
Acts::BoundMatrix expJac;
if (e == 0) {
expJac = Acts::BoundMatrix::Zero();
} else {
expJac = (Acts::BoundMatrix::Identity() * e).inverse();
}

BOOST_CHECK_EQUAL(ts.jacobian(), expJac);
}

// now back to original order, revert jacobians again
t.reverseTrackStates(true);

// reset exp to range(0, N)
std::iota(exp.begin(), exp.end(), 0);

for (const auto [e, ts] : zip(exp, t.trackStates())) {
BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
}
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 6df0704

Please sign in to comment.