LDMX Software
TrackExtrapolatorTool.h
1#pragma once
2
3#include <iostream>
4#include <iterator>
5#include <optional>
6
7#include "Acts/Definitions/TrackParametrization.hpp"
8#include "Acts/EventData/ParticleHypothesis.hpp"
9#include "Acts/EventData/TrackContainer.hpp"
10#include "Acts/EventData/TrackProxy.hpp"
11#include "Acts/Geometry/GeometryContext.hpp"
12#include "Acts/MagneticField/MagneticFieldContext.hpp"
13#include "Acts/Propagator/ActorList.hpp"
14#include "Acts/Propagator/MaterialInteractor.hpp"
15#include "Acts/Propagator/Propagator.hpp"
16#include "Acts/Propagator/detail/SteppingLogger.hpp"
17#include "Acts/Utilities/TrackHelpers.hpp"
18#include "Tracking/Event/Track.h"
19#include "Tracking/Sim/TrackingUtils.h"
20
21using ActionList =
22 Acts::ActorList<Acts::detail::SteppingLogger, Acts::MaterialInteractor,
23 Acts::EndOfWorldReached>;
24
25namespace tracking {
26namespace reco {
27
28template <class propagator_t>
30 public:
31 // The geometry context should be already in the propagator options...
32 TrackExtrapolatorTool(propagator_t propagator,
33 const Acts::GeometryContext& gctx,
34 const Acts::MagneticFieldContext& mctx)
35 : propagator_(std::move(propagator)), gctx_(gctx), mctx_(mctx) {}
36
42 void setDebug(bool debug) { debug_ = debug; }
43 void setMaxStepSize(double step) { max_step_size_ = step; }
44 void setPathLimit(double limit) { path_limit_ = limit; }
45
54 using PropagatorOptions = typename propagator_t::template Options<ActionList>;
55
56 std::optional<Acts::BoundTrackParameters> extrapolate(
57 const Acts::BoundTrackParameters pars,
58 const std::shared_ptr<Acts::Surface>& target_surface) {
59 auto intersection = target_surface->intersect(gctx_, pars.position(gctx_),
60 pars.direction());
61
62 PropagatorOptions p_options(gctx_, mctx_);
63 if (max_step_size_ > 0) p_options.stepping.maxStepSize = max_step_size_;
64 if (path_limit_ > 0) p_options.pathLimit = path_limit_;
65
66 p_options.direction = intersection[0].pathLength() >= 0
67 ? Acts::Direction::Forward()
68 : Acts::Direction::Backward();
69
70 auto result = propagator_.propagate(pars, *target_surface, p_options);
71
72 // CHECK THE EXTRAPOLATION COVARIANCE MATRIX
73
74 if (debug_) {
75 if (result.ok()) {
76 std::cout << "INITIAL COV MATRIX\n";
77 std::cout << (*(pars.covariance())) << std::endl;
78
79 std::cout << "FINAL COV MATRIX\n";
80 auto opt_pars = *result->endParameters;
81 std::cout << *(opt_pars.covariance()) << std::endl;
82 }
83 }
84
85 if (result.ok())
86 return *result->endParameters;
87 else
88 return std::nullopt;
89 } // end of extrapolate()
90
101 template <class track_t>
102 std::optional<Acts::BoundTrackParameters> extrapolate(
103 track_t track, const std::shared_ptr<Acts::Surface>& target_surface) {
104 if (debug_) {
105 std::cout << "[TrackExtrapolatorTool] extrapolate START\n";
106 std::cout << "[TrackExtrapolatorTool] track.nTrackStates() = "
107 << track.nTrackStates() << std::endl;
108 std::cout << "[TrackExtrapolatorTool] target_surface = "
109 << target_surface.get() << std::endl;
110 }
111
112 if (track.nTrackStates() == 0) {
113 return std::nullopt;
114 }
115
116 // Use ACTS's built-in helper to find the measurement track state
117 // (first or last) that is closest to the target surface. This correctly
118 // handles holes and material-only states which lack filtered parameters.
119 auto state_result = Acts::findTrackStateForExtrapolation(
120 gctx_, track, *target_surface,
121 Acts::TrackExtrapolationStrategy::firstOrLast);
122
123 if (!state_result.ok()) {
124 return std::nullopt;
125 }
126
127 const auto& ts = state_result->first;
128 const auto& surface = ts.referenceSurface();
129
130 Acts::BoundVector params;
131 Acts::BoundMatrix cov;
132
133 if (ts.hasSmoothed()) {
134 if (debug_)
135 std::cout << "[TrackExtrapolatorTool] Using smoothed parameters\n";
136 params = ts.smoothed();
137 cov = ts.smoothedCovariance();
138 } else if (ts.hasFiltered()) {
139 if (debug_)
140 std::cout << "[TrackExtrapolatorTool] Using filtered parameters\n";
141 params = ts.filtered();
142 cov = ts.filteredCovariance();
143 } else {
144 return std::nullopt;
145 }
146
147 if (debug_) {
148 std::cout << "Surface::"
149 << surface.localToGlobalTransform(gctx_).translation()
150 << std::endl;
151 std::cout << "HasSmoothed::" << ts.hasSmoothed() << std::endl;
152 std::cout << "Parameters::" << params.transpose() << std::endl;
153 }
154
155 auto part_hypo{Acts::ParticleHypothesis::electron()};
156 Acts::BoundTrackParameters sp(surface.getSharedPtr(), params, cov,
157 part_hypo);
158 if (debug_)
159 std::cout << "[TrackExtrapolatorTool] calling extrapolate(BTP)...\n";
160 auto result = extrapolate(sp, target_surface);
161 if (debug_) std::cout << "[TrackExtrapolatorTool] extrapolate DONE\n";
162 return result;
163 }
164
174 template <class track_t>
175 std::optional<Acts::BoundTrackParameters> extrapolateToEcal(
176 track_t track, const std::shared_ptr<Acts::Surface>& target_surface) {
177 // get last track state on the track.
178 // Now.. I'm taking whatever it is. I'm not checking here if it is a
179 // measurement.
180
181 auto& tsc = track.container().trackStateContainer();
182 auto begin = track.trackStates().begin();
183 auto ts_last = *begin;
184 const auto& surface = (ts_last).referenceSurface();
185 const auto& smoothed = (ts_last).smoothed();
186 const auto& cov = (ts_last).smoothedCovariance();
187
188 // Get the BoundTrackStateParameters
189 // assume electron for now
190 auto part_hypo{Acts::ParticleHypothesis::electron()};
191
192 Acts::BoundTrackParameters state_parameters(surface.getSharedPtr(),
193 smoothed, cov, part_hypo);
194
195 // One can also use directly the extrapolate method
196 PropagatorOptions p_options(gctx_, mctx_);
197 auto result =
198 propagator_.propagate(state_parameters, *target_surface, p_options);
199
200 if (result.ok())
201 return *result->endParameters;
202 else
203 return std::nullopt;
204 }
205
216 template <class track_t>
217 bool trackStateAtSurface(track_t track,
218 const std::shared_ptr<Acts::Surface>& target_surface,
220 ldmx::TrackStateType type) {
221 if (debug_) {
222 std::cout << "[TrackExtrapolatorTool] trackStateAtSurface START\n";
223 std::cout << "[TrackExtrapolatorTool] target_surface = "
224 << target_surface.get() << std::endl;
225 std::cout << "[TrackExtrapolatorTool] track.nTrackStates() = "
226 << track.nTrackStates() << std::endl;
227 std::cout << "[TrackExtrapolatorTool] TrackStateType = "
228 << static_cast<int>(type) << std::endl;
229 std::cout << "[TrackExtrapolatorTool] About to call extrapolate...\n";
230 }
231
232 auto opt_pars = extrapolate(track, target_surface);
233
234 if (debug_) {
235 std::cout << "[TrackExtrapolatorTool] extrapolate returned, "
236 "opt_pars.has_value() = "
237 << opt_pars.has_value() << std::endl;
238 }
239
240 if (opt_pars) {
241 if (debug_) {
242 Acts::Vector3 surf_loc =
243 target_surface->localToGlobalTransform(gctx_).translation();
244 std::cout << "[TrackExtrapolatorTool] Surface location: ("
245 << surf_loc(0) << ", " << surf_loc(1) << ", " << surf_loc(2)
246 << ")\n";
247 }
248
249 ts = tracking::sim::utils::makeTrackState(gctx_, *opt_pars, type);
250 if (debug_)
251 std::cout << "[TrackExtrapolatorTool] trackStateAtSurface SUCCESS\n";
252 return true;
253 } else {
254 if (debug_)
255 std::cout << "[TrackExtrapolatorTool] trackStateAtSurface FAILED - "
256 "opt_pars is empty\n";
257 return false;
258 }
259 }
260
261 private:
262 propagator_t propagator_;
263 Acts::GeometryContext gctx_;
264 Acts::MagneticFieldContext mctx_;
265 bool debug_{false};
266 double max_step_size_{-1};
267 double path_limit_{-1};
268};
269
270} // namespace reco
271} // namespace tracking
std::optional< Acts::BoundTrackParameters > extrapolate(track_t track, const std::shared_ptr< Acts::Surface > &target_surface)
Method to extrapolate to a target surface given a track The method computes which track state is clos...
std::optional< Acts::BoundTrackParameters > extrapolateToEcal(track_t track, const std::shared_ptr< Acts::Surface > &target_surface)
Create an ldmx::TrackState to the extrapolated position.
typename propagator_t::template Options< ActionList > PropagatorOptions
Method to extrapolate to a target surface given a set of BoundTrackParameters.
bool trackStateAtSurface(track_t track, const std::shared_ptr< Acts::Surface > &target_surface, ldmx::Track::TrackState &ts, ldmx::TrackStateType type)
Create an ldmx::TrackState to the extrapolated position.
void setDebug(bool debug)
Turn on/off internal debug flag.
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...