Skip to content

Commit

Permalink
fix: Really handle holes after measurement selection in Core CKF (#3474)
Browse files Browse the repository at this point in the history
Looks like I lost the actual objective in #3413 which did not resolve the issue.

After the refactoring of the measurement selector it is possible that we end up with no measurements after selection. That case was not handled by the Core CKF yet.

#3413 was an attempt to fix the problem but the hole handling was shifted to the wrong place. We want to check for a hole after `trackStateCandidateCreator` and before `processNewTrackStates`.
  • Loading branch information
andiwand authored Aug 7, 2024
1 parent ca69799 commit 95da6aa
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 64 deletions.
119 changes: 60 additions & 59 deletions Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,6 @@ class CombinatorialKalmanFilter {
TrackIndexType prevTip = currentBranch.tipIndex();

// Create trackstates for all source links (will be filtered later)
// Results are stored in result => no return value
using TrackStatesResult =
Acts::Result<CkfTypes::BranchVector<TrackIndexType>>;
TrackStatesResult tsRes = trackStateCandidateCreator(
Expand All @@ -745,64 +744,23 @@ class CombinatorialKalmanFilter {
const CkfTypes::BranchVector<TrackIndexType>& newTrackStateList =
*tsRes;

Result<std::pair<unsigned int, unsigned int>> procRes =
processNewTrackStates(state.geoContext, newTrackStateList, result);
if (!procRes.ok()) {
ACTS_ERROR("Processing of selected track states failed: "
<< procRes.error());
return procRes.error();
}
auto [nNewBranchesOnSurface, nStoppedBranches] = *procRes;
nBranchesOnSurface = nNewBranchesOnSurface;

if (nStoppedBranches >= newTrackStateList.size()) {
// All branches on the surface have been stopped. Reset happens at the
// end of the function
ACTS_VERBOSE("All branches on surface " << surface->geometryId()
<< " have been stopped");
} else if (nBranchesOnSurface > 0) {
if (currentBranch.outermostTrackState().typeFlags().test(
TrackStateFlag::OutlierFlag)) {
// We don't need to update the stepper given an outlier state
ACTS_VERBOSE("Outlier state detected on surface "
<< surface->geometryId());
} else {
// If there are measurement track states on this surface
ACTS_VERBOSE("Filtering step successful with " << nBranchesOnSurface
<< " branches");
// Update stepping state using filtered parameters of last track
// state on this surface
auto ts = result.activeBranches.back().outermostTrackState();
stepper.update(state.stepping,
MultiTrajectoryHelpers::freeFiltered(
state.options.geoContext, ts),
ts.filtered(), ts.filteredCovariance(), *surface);
ACTS_VERBOSE("Stepping state is updated with filtered parameter:");
ACTS_VERBOSE("-> " << ts.filtered().transpose()
<< " of track state with tip = " << ts.index());
}
} else { // nBranchesOnSurface == 0
if (newTrackStateList.empty()) {
ACTS_VERBOSE("Detected hole after measurement selection on surface "
<< surface->geometryId());

// After `processNewTrackStates` `currentBranch` is invalidated
currentBranch = result.activeBranches.back();
prevTip = currentBranch.tipIndex();

// Setting the number of branches on the surface to 1 as the hole
// still counts as a branch
nBranchesOnSurface = 1;

auto stateMask = PM::Predicted | PM::Jacobian;

currentBranch.nHoles()++;

// Add a hole track state to the multitrajectory
TrackIndexType currentTip = addNonSourcelinkState(
stateMask, boundState, result, true, prevTip);
auto nonSourcelinkState =
result.trackStates->getTrackState(currentTip);
currentBranch.tipIndex() = currentTip;
currentBranch.nHoles()++;

BranchStopperResult branchStopperResult =
m_extensions.branchStopper(currentBranch, nonSourcelinkState);
Expand All @@ -819,6 +777,49 @@ class CombinatorialKalmanFilter {
// Remove the branch from list
result.activeBranches.pop_back();
}
} else {
Result<unsigned int> procRes = processNewTrackStates(
state.geoContext, newTrackStateList, result);
if (!procRes.ok()) {
ACTS_ERROR("Processing of selected track states failed: "
<< procRes.error());
return procRes.error();
}
nBranchesOnSurface = *procRes;

if (nBranchesOnSurface == 0) {
// All branches on the surface have been stopped. Reset happens at
// the end of the function
ACTS_VERBOSE("All branches on surface " << surface->geometryId()
<< " have been stopped");
} else {
// `currentBranch` is invalidated after `processNewTrackStates`
currentBranch = result.activeBranches.back();
prevTip = currentBranch.tipIndex();

if (currentBranch.outermostTrackState().typeFlags().test(
TrackStateFlag::OutlierFlag)) {
// We don't need to update the stepper given an outlier state
ACTS_VERBOSE("Outlier state detected on surface "
<< surface->geometryId());
} else {
// If there are measurement track states on this surface
ACTS_VERBOSE("Filtering step successful with "
<< nBranchesOnSurface << " branches");
// Update stepping state using filtered parameters of last track
// state on this surface
auto ts = result.activeBranches.back().outermostTrackState();
stepper.update(state.stepping,
MultiTrajectoryHelpers::freeFiltered(
state.options.geoContext, ts),
ts.filtered(), ts.filteredCovariance(), *surface);
ACTS_VERBOSE(
"Stepping state is updated with filtered parameter:");
ACTS_VERBOSE("-> "
<< ts.filtered().transpose()
<< " of track state with tip = " << ts.index());
}
}
}

// Update state and stepper with post material effects
Expand All @@ -845,11 +846,6 @@ class CombinatorialKalmanFilter {
// measurement and filtered parameter
auto stateMask = PM::Predicted | PM::Jacobian;

if (isSensitive) {
// Increment of number of holes
currentBranch.nHoles()++;
}

// Transport the covariance to a curvilinear surface
stepper.transportCovarianceToCurvilinear(state.stepping);

Expand All @@ -873,6 +869,9 @@ class CombinatorialKalmanFilter {
auto nonSourcelinkState =
result.trackStates->getTrackState(currentTip);
currentBranch.tipIndex() = currentTip;
if (isSensitive) {
currentBranch.nHoles()++;
}

BranchStopperResult branchStopperResult =
m_extensions.branchStopper(currentBranch, nonSourcelinkState);
Expand Down Expand Up @@ -927,23 +926,27 @@ class CombinatorialKalmanFilter {
/// @param gctx The geometry context for this track finding/fitting
/// @param newTrackStateList index list of new track states
/// @param result which contains among others the new states, and the list of active branches
/// @return the number of newly added branches and number of stopped branches or an error
Result<std::pair<unsigned int, unsigned int>> processNewTrackStates(
/// @return the number of newly added branches or an error
Result<unsigned int> processNewTrackStates(
const Acts::GeometryContext& gctx,
const CkfTypes::BranchVector<TrackIndexType>& newTrackStateList,
result_type& result) const {
using PM = TrackStatePropMask;

unsigned int nBranchesOnSurface = 0;
unsigned int nStoppedBranches = 0;

auto rootBranch = result.activeBranches.back();

// Build the new branches by forking the root branch
// Build the new branches by forking the root branch. Reverse the order to
// process the best candidate first
CkfTypes::BranchVector<TrackProxy> newBranches;
for (auto [i, tipIndex] : enumerate(newTrackStateList)) {
auto newBranch = (i == 0) ? rootBranch : rootBranch.shallowCopy();
newBranch.tipIndex() = tipIndex;
for (auto it = newTrackStateList.rbegin(); it != newTrackStateList.rend();
++it) {
// Keep the root branch as the first branch, make a copy for the others
auto newBranch = (it == newTrackStateList.rbegin())
? rootBranch
: rootBranch.shallowCopy();
newBranch.tipIndex() = *it;
newBranches.push_back(newBranch);
}

Expand Down Expand Up @@ -978,7 +981,6 @@ class CombinatorialKalmanFilter {
newBranch.nMeasurements()++;
} else {
ACTS_WARNING("Cannot handle this track state flags");
nStoppedBranches++;
continue;
}

Expand All @@ -993,7 +995,6 @@ class CombinatorialKalmanFilter {
nBranchesOnSurface++;
} else {
// Record the number of stopped branches
nStoppedBranches++;
if (branchStopperResult == BranchStopperResult::StopAndKeep) {
storeLastActiveBranch(result);
}
Expand All @@ -1002,7 +1003,7 @@ class CombinatorialKalmanFilter {
}
}

return std::pair{nBranchesOnSurface, nStoppedBranches};
return nBranchesOnSurface;
}

/// @brief CombinatorialKalmanFilter actor operation: add a hole or material track state
Expand Down
10 changes: 5 additions & 5 deletions Examples/Python/tests/root_file_hashes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ test_ckf_tracks_example[generic-full_seeding]__performance_seeding_trees.root: 0
test_ckf_tracks_example[generic-truth_estimated]__trackstates_ckf.root: 7679bbbdb47abcbee87048ce373966d5f58bab6b04312844ede351ea653a573f
test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 0df341fc0833c33474cd8835d2e3318b6bd492a07b3b4ae5aa74068593679854
test_ckf_tracks_example[generic-truth_estimated]__performance_seeding.root: 1facb05c066221f6361b61f015cdf0918e94d9f3fce2269ec7b6a4dffeb2bc7e
test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: b9fe81e4d9084ad91790de2106fe7cb94a5a5942fed3a7e34250ef667a72f39b
test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: a1b9f1bffff115e165f4a43de480931f6a7bd0fcbcd6c827b9baa339f8e823c9
test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: 25b985218418c91782696daab1b3fd3eaf7d15cd05681c7dfe2e4c3e44977e16
test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: be592112183bd6554ed5e00dcb62eb4a5a5f4a9bb7efa4b1e1ce699dec13157b
test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 935359233aa503a077faf2394ba988d0da97ea5db4f6d3294a95fb93c5625c68
test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: 59537c52d23a77dbed9230c7b92cf653f7592c72fb882e8a24a2b33f1d27019e
test_ckf_tracks_example[odd-full_seeding]__performance_seeding_trees.root: 43c58577aafe07645e5660c4f43904efadf91d8cda45c5c04c248bbe0f59814f
test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 4c80c03534ac82960808fad88d38c2d9f794320fbebd494e310208300def01e9
test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 89fad58add1ead7c0d38a952391d3c4a720feda6e37c37ed53f994a99fe15f57
test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 3a092423e717b1fe76f78f6b95eb6df67648a196e8c4da32158061d4bc490578
test_ckf_tracks_example[odd-truth_estimated]__performance_seeding.root: 1a36b7017e59f1c08602ef3c2cb0483c51df248f112e3780c66594110719c575
test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: c3e59a27c1ec5d2187b390373ff80e4f61cf2ead9916c1456ccb60ab4c52b4f6
test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: b92e4760aaa6e152116dae071f6c64efee20b8612188a173d88fc02c82ea85cf
test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 268357818ee53cc13b26aa23af06d7f839d112e9dc2eb3ac4c5b6e6eda48e6af
test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: 98c9e97240f541c22dd41d05c2114d7e9455b117162d64baad2c3ecb5b7d52f7
test_vertex_fitting_reading[Truth-False-100]__performance_vertexing.root: 76ef6084d758dfdfc0151ddec2170e12d73394424e3dac4ffe46f0f339ec8293
test_vertex_fitting_reading[Iterative-False-100]__performance_vertexing.root: 60372210c830a04f95ceb78c6c68a9b0de217746ff59e8e73053750c837b57eb
test_vertex_fitting_reading[Iterative-True-100]__performance_vertexing.root: e34f217d524a5051dbb04a811d3407df3ebe2cc4bb7f54f6bda0847dbd7b52c3
Expand Down

0 comments on commit 95da6aa

Please sign in to comment.