117 auto t_start = std::chrono::high_resolution_clock::now();
131 const auto& measurements =
137 Acts::GainMatrixUpdater updater;
138 Acts::GsfExtensions<Acts::VectorMultiTrajectory> gsf_extensions;
139 gsf_extensions.updater.connect<
140 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
142 gsf_extensions.calibrator
144 Acts::VectorMultiTrajectory>>(&calibrator);
147 struct SurfaceAccessor {
148 const Acts::TrackingGeometry* tracking_geometry_;
150 const Acts::Surface* operator()(
const Acts::SourceLink& sourceLink)
const {
151 const auto& index_source_link =
153 return tracking_geometry_->findSurface(index_source_link.geometryId());
157 SurfaceAccessor m_sl_surface_accessor{tg.getTG().get()};
159 gsf_extensions.surfaceAccessor.connect<&SurfaceAccessor::operator()>(
160 &m_sl_surface_accessor);
161 gsf_extensions.mixtureReducer.connect<&Acts::reduceMixtureLargestWeights>();
166 Acts::PropagatorOptions<Acts::StepperPlainOptions,
167 Acts::NavigatorPlainOptions, ActionList>
168 propagator_options(geometryContext(), magneticFieldContext());
170 propagator_options.pathLimit = std::numeric_limits<double>::max();
173 propagator_options.loopProtection =
false;
178 propagator_options.actorList.get<Acts::MaterialInteractor>();
179 m_interactor.multipleScattering =
true;
180 m_interactor.energyLoss =
true;
181 m_interactor.recordInteractions =
false;
185 propagator_options.actorList.get<Acts::detail::SteppingLogger>();
186 s_logger.sterile =
true;
188 propagator_options.stepping.maxStepSize =
196 std::shared_ptr<const Acts::Surface> gsf_ref_surface;
197 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsf_options{
198 geometryContext(), magneticFieldContext(), calibrationContext()};
199 gsf_options.extensions = gsf_extensions;
200 gsf_options.propagatorPlainOptions =
201 static_cast<Acts::PropagatorPlainOptions
>(propagator_options);
208 std::vector<ldmx::Track> out_tracks;
210 Acts::VectorTrackContainer vtc;
211 Acts::VectorMultiTrajectory mtj;
212 Acts::TrackContainer tc{vtc, mtj};
215 n_input_tracks_ +=
static_cast<int>(tracks.size());
217 unsigned int itrk = 0;
218 int n_gsf_ok_evt = 0;
219 int n_tgt_fail_evt = 0;
220 ldmx_log(debug) <<
"Starting GSF processing of " << tracks.size()
223 for (
auto& track : tracks) {
224 ldmx_log(debug) <<
"Processing track " << itrk <<
" with "
225 << track.getMeasurementsIdxs().size() <<
" measurements";
227 std::vector<ldmx::Measurement> meas_on_track;
230 std::vector<Acts::SourceLink> fit_track_source_links;
232 for (
auto imeas : track.getMeasurementsIdxs()) {
233 auto meas = measurements.at(imeas);
234 meas_on_track.push_back(meas);
238 const Acts::Surface* hit_surface =
239 tg.geo::TrackingGeometry::getSurface(meas.getLayerID());
243 fit_track_source_links.push_back(Acts::SourceLink(idx_sl));
247 std::reverse(meas_on_track.begin(), meas_on_track.end());
248 std::reverse(fit_track_source_links.begin(), fit_track_source_links.end());
250 for (
auto m : meas_on_track) {
251 ldmx_log(trace) <<
" Measurement:\n" << m <<
"\n";
254 ldmx_log(debug) <<
" Track bound track parameters preparation:";
259 Acts::Vector3 perigee_acts = tracking::sim::utils::ldmx2Acts(Acts::Vector3(
260 track.getPerigeeX(), track.getPerigeeY(), track.getPerigeeZ()));
261 std::shared_ptr<Acts::PerigeeSurface> perigee =
262 Acts::Surface::makeShared<Acts::PerigeeSurface>(perigee_acts);
264 Acts::BoundTrackParameters trk_btp =
265 tracking::sim::utils::boundTrackParameters(track, perigee);
267 Acts::BoundTrackParameters trk_btp_fit_start = trk_btp;
274 if (tagger_tracking_) {
275 auto opt_tagger_start =
277 if (!opt_tagger_start) {
279 <<
" Failed pre-fit extrapolation to tagger start surface (itrk="
284 trk_btp_fit_start = *opt_tagger_start;
287 ldmx_log(debug) <<
" Perigee surface (acts): (" << track.getPerigeeX()
288 <<
", " << track.getPerigeeY() <<
", "
289 << track.getPerigeeZ() <<
")";
291 const Acts::BoundVector& trkpars = trk_btp.parameters();
292 ldmx_log(debug) <<
" Perigee parameters (d0, z0, phi, theta, q/p)= ("
293 << trkpars[Acts::eBoundLoc0] <<
", "
294 << trkpars[Acts::eBoundLoc1] <<
", "
295 << trkpars[Acts::eBoundPhi] <<
", "
296 << trkpars[Acts::eBoundTheta] <<
", "
297 << trkpars[Acts::eBoundQOverP] <<
")";
299 const Acts::BoundVector& fit_start_pars = trk_btp_fit_start.parameters();
300 ldmx_log(debug) <<
" GSF start parameters (d0, z0, phi, theta, q/p)= ("
301 << fit_start_pars[Acts::eBoundLoc0] <<
", "
302 << fit_start_pars[Acts::eBoundLoc1] <<
", "
303 << fit_start_pars[Acts::eBoundPhi] <<
", "
304 << fit_start_pars[Acts::eBoundTheta] <<
", "
305 << fit_start_pars[Acts::eBoundQOverP] <<
")";
307 ldmx_log(debug) <<
" About to run GSF fit with "
308 << fit_track_source_links.size() <<
" source links";
312 if (tagger_tracking_) {
317 gsf_options.referenceSurface = &(*gsf_ref_surface);
319 auto gsf_refit_result =
320 gsf_->fit(fit_track_source_links.begin(), fit_track_source_links.end(),
321 trk_btp_fit_start, gsf_options, tc);
323 if (!gsf_refit_result.ok()) {
324 ldmx_log(debug) <<
" GSF re-fit failed (itrk=" << itrk
325 <<
"): " << gsf_refit_result.error().message();
326 if (n_gsf_failed_ < 5)
327 ldmx_log(info) <<
" [GSF dbg] fit failed (first few): "
328 << gsf_refit_result.error().message();
334 ldmx_log(debug) <<
" GSF fit succeeded (itrk=" << itrk
335 <<
"), tc.size()=" << tc.size();
337 auto gsftrk = gsf_refit_result.value();
340 const Acts::BoundVector& perigee_pars = gsftrk.parameters();
341 const Acts::BoundMatrix& trk_cov = gsftrk.covariance();
342 const Acts::Surface& perigee_surface = gsftrk.referenceSurface();
344 ldmx_log(debug) <<
" Reference Surface (acts-x, acts-y, acts-z) = ("
345 << perigee_surface.localToGlobalTransform(geometryContext())
348 << perigee_surface.localToGlobalTransform(geometryContext())
351 << perigee_surface.localToGlobalTransform(geometryContext())
355 ldmx_log(debug) <<
" nTrackStates=" << gsftrk.nTrackStates()
356 <<
" nMeasurements=" << gsftrk.nMeasurements()
357 <<
" chi2=" << gsftrk.chi2();
358 if (gsftrk.nTrackStates() == 0)
359 ldmx_log(info) <<
" [GSF dbg] track has 0 states after fit (itrk="
362 ldmx_log(debug) <<
" Track parameters (d0, z0, phi, theta, q/p)= ("
363 << perigee_pars[Acts::eBoundLoc0] <<
", "
364 << perigee_pars[Acts::eBoundLoc1] <<
", "
365 << perigee_pars[Acts::eBoundPhi] <<
", "
366 << perigee_pars[Acts::eBoundTheta] <<
", "
367 << perigee_pars[Acts::eBoundQOverP] <<
") ";
374 ldmx_log(debug) <<
" Extrapolating to target (itrk=" << itrk <<
")";
376 ldmx_log(debug) <<
" GSF target extrapolation succeeded";
377 auto ts_at_target = tracking::sim::utils::makeTrackState(
378 geometryContext(), *opt_target, ldmx::AtTarget);
379 trk.addTrackState(ts_at_target);
381 trk.setPerigeeParameters(tracking::sim::utils::convertActsToLdmxPars(
382 opt_target->parameters()));
383 if (opt_target->covariance()) {
384 std::vector<double> cov_vec;
385 tracking::sim::utils::flatCov(*(opt_target->covariance()), cov_vec);
386 trk.setPerigeeCov(cov_vec);
388 Acts::Vector3 target_loc_ldmx = tracking::sim::utils::acts2Ldmx(
391 trk.setPerigeeLocation(target_loc_ldmx[0], target_loc_ldmx[1],
395 <<
" GSF target parameters (d0, z0, phi, theta, q/p)= ("
396 << opt_target->parameters()[Acts::eBoundLoc0] <<
", "
397 << opt_target->parameters()[Acts::eBoundLoc1] <<
", "
398 << opt_target->parameters()[Acts::eBoundPhi] <<
", "
399 << opt_target->parameters()[Acts::eBoundTheta] <<
", "
400 << opt_target->parameters()[Acts::eBoundQOverP] <<
")";
402 ++n_target_extrap_failed_;
404 ldmx_log(debug) <<
" GSF target extrapolation failed (itrk=" << itrk
405 <<
"), using GSF fit parameters at reference surface";
406 trk.setPerigeeParameters(
407 tracking::sim::utils::convertActsToLdmxPars(perigee_pars));
408 std::vector<double> v_trk_cov;
409 tracking::sim::utils::flatCov(trk_cov, v_trk_cov);
410 trk.setPerigeeCov(v_trk_cov);
414 if (tagger_tracking_) {
415 auto opt_beam_origin =
418 trk.addTrackState(tracking::sim::utils::makeTrackState(
419 geometryContext(), *opt_beam_origin, ldmx::AtBeamOrigin));
421 ldmx_log(debug) <<
" ECAL extrapolation";
422 auto opt_ecal = trk_extrap_->extrapolate(gsftrk,
ecal_surface_);
424 trk.addTrackState(tracking::sim::utils::makeTrackState(
425 geometryContext(), *opt_ecal, ldmx::AtECAL));
427 ++n_ecal_extrap_failed_;
430 trk.setChi2(gsftrk.chi2());
431 trk.setNhits(gsftrk.nMeasurements());
432 trk.setNdf(gsftrk.nMeasurements() - 5);
433 trk.setCharge(perigee_pars[Acts::eBoundQOverP] > 0 ? 1 : -1);
436 trk.setTrackID(track.getTrackID());
437 trk.setPdgID(track.getPdgID());
438 trk.setTruthProb(track.getTruthProb());
442 ldmx_log(debug) <<
" Added track to output, total tracks = "
443 << (out_tracks.size() + 1);
445 out_tracks.push_back(trk);
449 ldmx_log(debug) <<
"[GSF evt " << nevents_ <<
"] in=" << tracks.size()
450 <<
" gsf_ok=" << n_gsf_ok_evt
451 <<
" tgt_fail=" << n_tgt_fail_evt
452 <<
" out=" << out_tracks.size();
454 n_output_tracks_ +=
static_cast<int>(out_tracks.size());
457 auto t_end = std::chrono::high_resolution_clock::now();
459 std::chrono::duration<double, std::milli>(t_end - t_start).count();