upgrade ACTS from v36 to v47 - #2101
Conversation
Fix tagger GSF producing 0 output tracks: the beam origin surface at x=-700mm (ACTS) is outside the tagger geometry volume (-618mm to +250mm), causing the v46 Navigator to fail with "No start volume could be resolved". Replace beam_origin_surface_ with tagger_start_surface_ at x=-617mm (1mm inside the tagger volume outer boundary, 1.5mm upstream of L1). For tagger tracks the GSF now backward-extrapolates from the CKF perigee at the target (x=0mm) to x=-617mm via VoidNavigator, then fits forward through L1-L7. Also add per-run summary counters to GSFProcessor and GreedyAmbiguitySolver, remove leftover diagnostic std::cout from TrackExtrapolatorTool, and set use_truth_smearing=True as the default in full_tracking_sequence.py. Generated with AI Co-Authored-By: SLAC AI
Bump FetchContent URL and MD5 hash in CMakeLists.txt. The only code change needed is renaming AtlasBetheHeitlerApprox to PolynomialBetheHeitlerApprox in GSFProcessor; AtlasBetheHeitlerApprox is a deprecated typedef alias in v47 and will be removed in a future release. All other v47 breaking changes (deprecated API removals, seeding renames, navigation policy factory refactor) do not affect ldmx-sw as the relevant APIs were already migrated during the v36->v46 upgrade. Generated with AI Co-Authored-By: SLAC AI
…his is weird because I have not touched this file in this branch
tomeichlersmith
left a comment
There was a problem hiding this comment.
For LDMX, where the GSF drives electron momentum measurement, this is the
highest-risk area for physics-level differences vs. trunk.
Do you plan to do an initial study of these differences and post them here before the PR is merged? Or do you think it is too detailed (and the differences are likely improvements) so it will wait for future work?
| # Find or fetch ACTS - must be at top level so both Ecal and Tracking can use it | ||
| find_package(Acts 47.0.0 QUIET) | ||
| if (NOT Acts_FOUND) | ||
| message(STATUS "Did not find Acts >= 47.0.0, downloading and compiling v47.0.0") |
There was a problem hiding this comment.
While I like this fallback in order to support older versions of the image, I think this PR should have a companion PR where the development image is updated to Acts v47. Is it backwards compatible? Could Acts v47 be used to compile what's on trunk right now?
There was a problem hiding this comment.
(These questions will just motivate how we document the development image and not necessarily whether we update the Acts within it.)
There was a problem hiding this comment.
I've just been looking at the validation plots (and really just the signal sample). The biggest differences I see:
-
tagger: the uncertainties for d0/z0/phi are smaller with v47, residuals the same, so the pulls are also broader. I don't think this is real...it's probably due to the change in the "origin" point which was moved closer so that it is in tracker volume. The pulls at the target X/Y pass the KS tests (though X vs n_hits fails but for some reason this plot only goes up to 12 hits, which must just be a bug).
-
recoil: we get KS failurs for some dup and fake plots and this is expected (though honestly they look ok to me). Also see failures for target position X (both truth and reco?) but they are pretty close by eye. The locations projected to the ecal fail and look bad (even the gold plots look bad, now they look worse). We will have to figure this out.
-
GSF: apart from the changes that feed down from the CKF tracks, the q/p error is much larger than before which effects the pulls (I think making them better).
-
ECal Tracking! I forget to look at these earlier! There are quite a few failures in EcalSPTrackCompare (particularly the deltas) and EcalTrackAnalyzer. Most of the plots fail actually.
There was a problem hiding this comment.
On your question on the image, no trunk as of now will not compile with v47...interface and class-name changes. What is the right thing to do here? I can't remember what we did when we updated to v36....
There was a problem hiding this comment.
It will just be nice to document it. If the answer is that the developer needs to either (a) merge their updates with the updated trunk or (b) pin their environment on an old image, that's okay I just wanted to know.
Validation ResultsSome validation samples failed! ❌
|
…; add assignIsSensitive(true) in visitSurfaces method; ECal tracking should be working as of this commit

Upgrade ACTS versions for 36-->47. Closes #2100
Algorithm changes that may effect tracks:
CKF branch handling
The CKF received improvements to outlier rejection and branch pruning
across these 11 major versions. This can shift the
efficiency/fake-rate tradeoff even with identical inputs.
GainMatrixSmoother → smoothTrack()
The Kalman backward (RTS) smoother was rewritten as a free function.
The math is identical in principle, but the implementation details
(handling of degenerate states, track-end boundary conditions, numerical
precision) may differ. Most likely source of small systematic shifts in
momentum resolution or pull distributions.
EigenStepper / RKN propagator
Step-size control and Jacobian transport have had stability improvements.
Effects appear mainly in track-to-truth residuals for long extrapolations
(e.g., tagger perigee → ECAL scoring plane).
GSF Bethe-Heitler handling
AtlasBetheHeitlerApprox was renamed PolynomialBetheHeitlerApprox — the
polynomial coefficients are the same. However, the GSF received active
development between v36 and v47 in component reduction strategies, weight
re-normalization, and handling of near-degenerate Gaussian mixtures. For
LDMX, where the GSF drives electron momentum measurement, this is the
highest-risk area for physics-level differences vs. trunk.
Interface changes etc:
In v46, the calibrator and measurementSelector
delegates moved out of CombinatorialKalmanFilterExtensions into a new
Acts::TrackStateCreator object. The SourceLinkAccessorDelegate also moved there.
DetectorElementBase -> Acts::SurfacePlacementBase.
transform() override -> localToGlobalTransform() (matches new base class).
surface->assignDetectorElement() -> surface->assignSurfacePlacement().
thickness() is no longer a pure virtual in the base; override removed.
isSensitive() added as a required override (returns true for sensor elements).
Acts::ViewConfig now uses C++ designated initializers: {.color = {r, g, b}}.
Added tagger_start_surface_ at ACTS x=-617mm (1mm inside the tagger
volume outer boundary at x=-618mm, 1.5mm upstream of the L1 doublet at
x=-615.5mm).
Recoil tracking volume extended upstream so its low-x edge is at x=-1mm,
placing the target plane (x=0) clearly inside the volume for the CKF Navigator
(previously the target was on or outside the volume boundary, causing Navigator
failures for recoil tracks).
BetheHeitlerApprox changed from a local stack object to a shared_ptr:
Old: BetheHeitlerApprox bh = Acts::makeDefaultBetheHeitlerApprox();
New: auto bh = std::make_sharedActs::AtlasBetheHeitlerApprox(
Acts::makeDefaultBetheHeitlerApprox());
GsfOptions.propagatorPlainOptions now requires an explicit cast:
gsf_options.propagatorPlainOptions =
static_castActs::PropagatorPlainOptions(propagator_options);
A separate GsfExtrapPropagator (EigenStepper + VoidNavigator) was added for
post-fit track extrapolations (to target, ECAL). VoidNavigator is required
because the ECAL scoring plane is outside the tracking geometry volume and the
standard Navigator would stop propagation at the volume boundary.
GainMatrixSmoother removed; Acts::smoothTrack() used instead, with its return
value checked.
Acts::FreeSquareMatrix renamed (TrackingUtils.cxx)
Old: Acts::FreeSquareMatrix
New: Acts::FreeMatrix
(defined in Acts/Definitions/TrackParametrization.hpp, same as before)
Acts::GeometryContext default constructor made private
The no-arg Acts::GeometryContext() constructor is private in v47. Code that
held Acts::GeometryContext as a member and relied on implicit default
initialization would fail to compile.