LDMX Software
GSFProcessor.cxx
1#include "Tracking/Reco/GSFProcessor.h"
2
3#include <algorithm>
4#include <chrono>
5#include <iomanip>
6#include <optional>
7#include <string>
8
9#include "Acts/Definitions/TrackParametrization.hpp"
10#include "Acts/Definitions/Units.hpp"
11#include "Acts/EventData/BoundTrackParameters.hpp"
12#include "Acts/EventData/SourceLink.hpp"
13#include "Acts/MagneticField/ConstantBField.hpp"
14#include "Acts/Surfaces/PerigeeSurface.hpp"
15#include "Acts/TrackFitting/BetheHeitlerApprox.hpp"
16#include "Acts/TrackFitting/GainMatrixUpdater.hpp"
17#include "Acts/TrackFitting/GsfMixtureReduction.hpp"
18#include "Acts/Utilities/Logger.hpp"
19#include "Tracking/Event/Measurement.h"
20#include "Tracking/Event/Track.h"
21#include "Tracking/Sim/IndexSourceLink.h"
22#include "Tracking/Sim/MeasurementCalibrator.h"
23#include "Tracking/Sim/TrackingUtils.h"
24
25namespace tracking {
26namespace reco {
27
28GSFProcessor::GSFProcessor(const std::string& name, framework::Process& process)
29 : TrackingGeometryUser(name, process) {}
30
32 beam_origin_surface_ = tracking::sim::utils::unboundSurface(-700);
33 // 1mm inside tagger ACTS volume outer boundary, upstream of L1
34 tagger_start_surface_ = tracking::sim::utils::unboundSurface(tagger_start_x_);
35 target_surface_ = tracking::sim::utils::unboundSurface(0.);
36 ecal_surface_ = tracking::sim::utils::unboundSurface(240.5);
37
38 // Setup a interpolated bfield map
39 if (field_map_.empty())
41 else
43 const auto map =
44 std::static_pointer_cast<InterpolatedMagneticField3>(bField());
45
46 auto acts_logging_level = Acts::Logging::FATAL;
47
48 if (debug_) acts_logging_level = Acts::Logging::VERBOSE;
49
50 // Setup the GSF Fitter
51
52 // Stepper
53 // Acts::MixtureReductionMethod finalReductionMethod;
54 // const auto multi_stepper = Acts::MultiEigenStepperLoop{map};
55
56 // Acts::ComponentMergeMethod reductionMethod =
57 // Acts::ComponentMergeMethod::eMaxWeight;
58 // Acts::MultiEigenStepperLoop multi_stepper(
59 // map, reductionMethod,
60 // Acts::getDefaultLogger("GSF_STEP", acts_loggingLevel));
61
62 Acts::MultiEigenStepperLoop multi_stepper(map);
63 // Detailed Stepper
64
65 // Acts::MultiEigenStepperLoop multi_stepper(map, finalReductionMethod);
66
67 // Navigator
68 Acts::Navigator::Config nav_cfg{geometry().getTG()};
69 nav_cfg.resolveMaterial = true;
70 nav_cfg.resolvePassive = false;
71 nav_cfg.resolveSensitive = true;
72 const Acts::Navigator navigator(nav_cfg);
73
74 auto gsf_propagator =
75 GsfPropagator(std::move(multi_stepper), std::move(navigator),
76 Acts::getDefaultLogger("GSF_PROP", acts_logging_level));
77
78 auto bethe_heitler = std::make_shared<Acts::PolynomialBetheHeitlerApprox>(
79 Acts::makeDefaultBetheHeitlerApprox());
80
81 gsf_ = std::make_unique<GsfFitter>(
82 std::move(gsf_propagator), bethe_heitler,
83 Acts::getDefaultLogger("GSF", acts_logging_level));
84
85 const auto stepper = Acts::EigenStepper<>{map};
86 propagator_ = std::make_unique<Propagator>(
87 stepper, navigator,
88 Acts::getDefaultLogger("GSF_EXTRAP", acts_logging_level));
89
90 propagator_extrap_ = std::make_unique<GsfExtrapPropagator>(
91 Acts::EigenStepper<>{map}, Acts::VoidNavigator{});
92 trk_extrap_ = std::make_shared<std::decay_t<decltype(*trk_extrap_)>>(
93 *propagator_extrap_, geometryContext(), magneticFieldContext());
94
95 // Constant-field fallbacks for tracks that leave the field map, as in the CKF
96 const auto zero_b_field =
97 std::make_shared<Acts::ConstantBField>(Acts::Vector3(0., 0., 0.));
98 const auto const_b_field = std::make_shared<Acts::ConstantBField>(
99 Acts::Vector3(0., 0., bfield_ * Acts::UnitConstants::T));
100
101 MultiStepper zero_b_multi_stepper(zero_b_field);
102 gsf_zero_b_ = std::make_unique<GsfFitter>(
103 GsfPropagator(
104 std::move(zero_b_multi_stepper), navigator,
105 Acts::getDefaultLogger("GSF_PROP_ZERO_B", acts_logging_level)),
106 bethe_heitler, Acts::getDefaultLogger("GSF_ZERO_B", acts_logging_level));
107
108 MultiStepper const_b_multi_stepper(const_b_field);
109 gsf_const_b_ = std::make_unique<GsfFitter>(
110 GsfPropagator(
111 std::move(const_b_multi_stepper), navigator,
112 Acts::getDefaultLogger("GSF_PROP_CONST_B", acts_logging_level)),
113 bethe_heitler, Acts::getDefaultLogger("GSF_CONST_B", acts_logging_level));
114
115 propagator_extrap_zero_b_ = std::make_unique<GsfExtrapPropagator>(
116 Acts::EigenStepper<>{zero_b_field}, Acts::VoidNavigator{});
117 trk_extrap_zero_b_ =
118 std::make_shared<std::decay_t<decltype(*trk_extrap_zero_b_)>>(
119 *propagator_extrap_zero_b_, geometryContext(),
120 magneticFieldContext());
121
122 propagator_extrap_const_b_ = std::make_unique<GsfExtrapPropagator>(
123 Acts::EigenStepper<>{const_b_field}, Acts::VoidNavigator{});
124 trk_extrap_const_b_ =
125 std::make_shared<std::decay_t<decltype(*trk_extrap_const_b_)>>(
126 *propagator_extrap_const_b_, geometryContext(),
127 magneticFieldContext());
128}
129
132 parameters.get<std::string>("out_trk_collection", "GSFTracks");
133
135 parameters.get<std::string>("track_collection", "TaggerTracks");
137 parameters.get<std::string>("meas_collection", "DigiTaggerSimHits");
138
139 track_passname_ = parameters.get<std::string>("track_passname");
140 meas_passname_ = parameters.get<std::string>("meas_passname");
142 parameters.get<std::string>("track_collection_event_passname");
144 parameters.get<std::string>("meas_collection_event_passname");
145
146 max_components_ = parameters.get<int>("max_components", 4);
147 abort_on_error_ = parameters.get<bool>("abort_on_error", false);
149 parameters.get<bool>("disable_all_material_handling", false);
150 weight_cutoff_ = parameters.get<double>("weight_cutoff_", 1.0e-4);
151
152 propagator_max_steps_ = parameters.get<int>("propagator_max_steps", 10000);
153 propagator_step_size_ = parameters.get<double>("propagator_step_size", 200.);
154 field_map_ = parameters.get<std::string>("field_map");
155 bfield_ = parameters.get<double>("bfield", -1.5);
157 use_perigee_ = parameters.get<bool>("usePerigee", false);
158
159 debug_ = parameters.get<bool>("debug", false);
160 tagger_tracking_ = parameters.get<bool>("tagger_tracking", true);
161 tagger_start_x_ = parameters.get<double>("tagger_start_x", -617.);
162
163 // final_reduction_method_ =
164 // parameters.get<double>("finalReductionMethod",);
165} // end of configure()
166
168 auto t_start = std::chrono::high_resolution_clock::now();
169
170 // General Setup
171
172 auto tg{geometry()};
173
174 // Retrieve the tracks
176 return;
177 const auto& tracks =
178 event.getCollection<ldmx::Track>(track_collection_, track_passname_);
179
180 // Retrieve the measurements
182 const auto& measurements =
184
185 tracking::sim::LdmxMeasurementCalibrator calibrator{measurements};
186
187 // GSF Setup
188 Acts::GainMatrixUpdater updater;
189 Acts::GsfExtensions<Acts::VectorMultiTrajectory> gsf_extensions;
190 gsf_extensions.updater.connect<
191 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
192 &updater);
193 gsf_extensions.calibrator
195 Acts::VectorMultiTrajectory>>(&calibrator);
196
197 // Surface Accessor
198 struct SurfaceAccessor {
199 const Acts::TrackingGeometry* tracking_geometry_;
200
201 const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const {
202 const auto& index_source_link =
203 sourceLink.get<acts_examples::IndexSourceLink>();
204 return tracking_geometry_->findSurface(index_source_link.geometryId());
205 }
206 };
207
208 SurfaceAccessor m_sl_surface_accessor{tg.getTG().get()};
209 // m_slSurfaceAccessor.trackingGeometry = tg.getTG();
210 gsf_extensions.surfaceAccessor.connect<&SurfaceAccessor::operator()>(
211 &m_sl_surface_accessor);
212 gsf_extensions.mixtureReducer.connect<&Acts::reduceMixtureLargestWeights>();
213
214 // Propagator Options
215
216 // Move this at the start of the producer
217 Acts::PropagatorOptions<Acts::StepperPlainOptions,
218 Acts::NavigatorPlainOptions, ActionList>
219 propagator_options(geometryContext(), magneticFieldContext());
220
221 propagator_options.pathLimit = std::numeric_limits<double>::max();
222
223 // Activate loop protection at some pt value
224 propagator_options.loopProtection = false;
225 //(startParameters.transverseMomentum() < cfg.ptLoopers);
226
227 // Switch the material interaction on/off & eventually into logging mode
228 auto& m_interactor =
229 propagator_options.actorList.get<Acts::MaterialInteractor>();
230 m_interactor.multipleScattering = true;
231 m_interactor.energyLoss = true;
232 m_interactor.recordInteractions = false;
233
234 // The logger can be switched to sterile, e.g. for timing logging
235 auto& s_logger =
236 propagator_options.actorList.get<Acts::detail::SteppingLogger>();
237 s_logger.sterile = true;
238 // Set a maximum step size
239 propagator_options.stepping.maxStepSize =
240 propagator_step_size_ * Acts::UnitConstants::mm;
241 propagator_options.maxSteps = propagator_max_steps_;
242
243 // Electron hypothesis
244 // propagator_options.mass = 0.511 * Acts::UnitConstants::MeV;
245
246 // GSF options will be configured per-track
247 std::shared_ptr<const Acts::Surface> gsf_ref_surface;
248 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsf_options{
249 geometryContext(), magneticFieldContext(), calibrationContext()};
250 gsf_options.extensions = gsf_extensions;
251 gsf_options.propagatorPlainOptions =
252 static_cast<Acts::PropagatorPlainOptions>(propagator_options);
253 gsf_options.maxComponents = max_components_;
254 gsf_options.weightCutoff = weight_cutoff_;
255 gsf_options.abortOnError = abort_on_error_;
256 gsf_options.disableAllMaterialHandling = disable_all_material_handling_;
257
258 // Output track container
259 std::vector<ldmx::Track> out_tracks;
260
261 Acts::VectorTrackContainer vtc;
262 Acts::VectorMultiTrajectory mtj;
263 Acts::TrackContainer tc{vtc, mtj};
264
265 // Loop on tracks
266 n_input_tracks_ += static_cast<int>(tracks.size());
267
268 unsigned int itrk = 0;
269 int n_gsf_ok_evt = 0;
270 int n_tgt_fail_evt = 0;
271 ldmx_log(debug) << "Starting GSF processing of " << tracks.size()
272 << " tracks";
273
274 // Fallback for this system
275 const GsfFitter& fallback_gsf =
276 tagger_tracking_ ? *gsf_const_b_ : *gsf_zero_b_;
277 auto& fallback_extrap =
278 tagger_tracking_ ? trk_extrap_const_b_ : trk_extrap_zero_b_;
279 const std::string fallback_name = tagger_tracking_ ? "const-B" : "zero-B";
280
281 for (auto& track : tracks) {
282 ldmx_log(debug) << "Processing track " << itrk << " with "
283 << track.getMeasurementsIdxs().size() << " measurements";
284 // Retrieve measurements on track
285 std::vector<ldmx::Measurement> meas_on_track;
286
287 // std::vector<ActsExamples::IndexSourceLink> fit_trackSourceLinks;
288 std::vector<Acts::SourceLink> fit_track_source_links;
289
290 for (auto imeas : track.getMeasurementsIdxs()) {
291 auto meas = measurements.at(imeas);
292 meas_on_track.push_back(meas);
293
294 // Retrieve the surface
295
296 const Acts::Surface* hit_surface =
297 tg.geo::TrackingGeometry::getSurface(meas.getLayerID());
298
299 // Store the index source link
300 acts_examples::IndexSourceLink idx_sl(hit_surface->geometryId(), imeas);
301 fit_track_source_links.push_back(Acts::SourceLink(idx_sl));
302 }
303
304 // Reverse the order of the vectors
305 std::reverse(meas_on_track.begin(), meas_on_track.end());
306 std::reverse(fit_track_source_links.begin(), fit_track_source_links.end());
307
308 for (auto m : meas_on_track) {
309 ldmx_log(trace) << " Measurement:\n" << m << "\n";
310 }
311
312 ldmx_log(debug) << " Track bound track parameters preparation:";
313
314 // Reconstruct BoundTrackParameters at perigee (target) from stored params.
315 // perigee_ is stored in LDMX frame; rotate to ACTS frame for surface
316 // creation.
317 Acts::Vector3 perigee_acts = tracking::sim::utils::ldmx2Acts(Acts::Vector3(
318 track.getPerigeeX(), track.getPerigeeY(), track.getPerigeeZ()));
319 std::shared_ptr<Acts::PerigeeSurface> perigee =
320 Acts::Surface::makeShared<Acts::PerigeeSurface>(perigee_acts);
321
322 Acts::BoundTrackParameters trk_btp =
323 tracking::sim::utils::boundTrackParameters(track, perigee);
324
325 Acts::BoundTrackParameters trk_btp_fit_start = trk_btp;
326
327 // For tagger: backward-extrapolate (via VoidNavigator) from the target
328 // perigee (x=0mm) to just inside the tagger outer boundary (x≈-650mm), then
329 // run the GSF forward (+x) through L1→L7. The CKF stores tagger track
330 // perigees at the target, so we must back-propagate before handing off to
331 // the GSF.
332 if (tagger_tracking_) {
333 auto opt_tagger_start =
334 trk_extrap_->extrapolate(trk_btp, tagger_start_surface_);
335 if (!opt_tagger_start) {
336 ++n_fieldmap_start_extrap_failed_;
337 ldmx_log(debug) << " Field-map pre-fit extrapolation to tagger start "
338 "surface failed, trying "
339 << fallback_name << " fallback (itrk=" << itrk << ")";
340 opt_tagger_start =
341 fallback_extrap->extrapolate(trk_btp, tagger_start_surface_);
342 if (opt_tagger_start) ++n_fallback_start_extrap_recovered_;
343 }
344 if (!opt_tagger_start) {
345 ldmx_log(debug)
346 << " Failed pre-fit extrapolation to tagger start surface (itrk="
347 << itrk << ")";
348 ++n_start_extrap_failed_;
349 continue;
350 }
351 trk_btp_fit_start = *opt_tagger_start;
352 }
353
354 ldmx_log(debug) << " Perigee surface (acts): (" << track.getPerigeeX()
355 << ", " << track.getPerigeeY() << ", "
356 << track.getPerigeeZ() << ")";
357
358 const Acts::BoundVector& trkpars = trk_btp.parameters();
359 ldmx_log(debug) << " Perigee parameters (d0, z0, phi, theta, q/p)= ("
360 << trkpars[Acts::eBoundLoc0] << ", "
361 << trkpars[Acts::eBoundLoc1] << ", "
362 << trkpars[Acts::eBoundPhi] << ", "
363 << trkpars[Acts::eBoundTheta] << ", "
364 << trkpars[Acts::eBoundQOverP] << ")";
365
366 const Acts::BoundVector& fit_start_pars = trk_btp_fit_start.parameters();
367 ldmx_log(debug) << " GSF start parameters (d0, z0, phi, theta, q/p)= ("
368 << fit_start_pars[Acts::eBoundLoc0] << ", "
369 << fit_start_pars[Acts::eBoundLoc1] << ", "
370 << fit_start_pars[Acts::eBoundPhi] << ", "
371 << fit_start_pars[Acts::eBoundTheta] << ", "
372 << fit_start_pars[Acts::eBoundQOverP] << ")";
373
374 ldmx_log(debug) << " About to run GSF fit with "
375 << fit_track_source_links.size() << " source links";
376
377 // GSF reference surface: for tagger use the start surface (x=-648mm, inside
378 // geometry), for recoil use the target (x=0mm).
379 if (tagger_tracking_) {
380 gsf_ref_surface = tagger_start_surface_;
381 } else {
382 gsf_ref_surface = target_surface_;
383 }
384 gsf_options.referenceSurface = &(*gsf_ref_surface);
385
386 // Index in tc of the successful fit
387 std::optional<Acts::TrackIndexType> fitted_index;
388
389 {
390 auto gsf_refit_result = gsf_->fit(fit_track_source_links.begin(),
391 fit_track_source_links.end(),
392 trk_btp_fit_start, gsf_options, tc);
393
394 if (gsf_refit_result.ok()) {
395 fitted_index = gsf_refit_result.value().index();
396 } else {
397 ++n_fieldmap_gsf_failed_;
398 ldmx_log(debug) << " Field-map GSF re-fit failed (itrk=" << itrk
399 << "): " << gsf_refit_result.error().message()
400 << ", trying " << fallback_name << " fallback";
401 if (n_fieldmap_gsf_failed_ <= 5)
402 ldmx_log(info) << " [GSF dbg] fit failed (first few): "
403 << gsf_refit_result.error().message();
404
405 auto fallback_result = fallback_gsf.fit(
406 fit_track_source_links.begin(), fit_track_source_links.end(),
407 trk_btp_fit_start, gsf_options, tc);
408
409 if (fallback_result.ok()) {
410 ++n_fallback_gsf_recovered_;
411 fitted_index = fallback_result.value().index();
412 ldmx_log(debug) << " Yay! " << fallback_name
413 << " GSF succeeded as fallback!";
414 } else {
415 ldmx_log(debug) << " " << fallback_name
416 << " GSF also failed (itrk=" << itrk
417 << "): " << fallback_result.error().message();
418 }
419 }
420 }
421
422 if (!fitted_index) {
423 ++n_gsf_failed_;
424 continue;
425 }
426
427 ++n_gsf_ok_evt;
428 ldmx_log(debug) << " GSF fit succeeded (itrk=" << itrk
429 << "), tc.size()=" << tc.size();
430
431 auto gsftrk = tc.getTrack(*fitted_index);
432 // calculateTrackQuantities(gsftrk);
433
434 const Acts::BoundVector& perigee_pars = gsftrk.parameters();
435 const Acts::BoundMatrix& trk_cov = gsftrk.covariance();
436 const Acts::Surface& perigee_surface = gsftrk.referenceSurface();
437
438 ldmx_log(debug) << " Reference Surface (acts-x, acts-y, acts-z) = ("
439 << perigee_surface.localToGlobalTransform(geometryContext())
440 .translation()(0)
441 << ", "
442 << perigee_surface.localToGlobalTransform(geometryContext())
443 .translation()(1)
444 << ", "
445 << perigee_surface.localToGlobalTransform(geometryContext())
446 .translation()(2)
447 << ")";
448
449 ldmx_log(debug) << " nTrackStates=" << gsftrk.nTrackStates()
450 << " nMeasurements=" << gsftrk.nMeasurements()
451 << " chi2=" << gsftrk.chi2();
452 if (gsftrk.nTrackStates() == 0)
453 ldmx_log(info) << " [GSF dbg] track has 0 states after fit (itrk="
454 << itrk << ");";
455
456 ldmx_log(debug) << " Track parameters (d0, z0, phi, theta, q/p)= ("
457 << perigee_pars[Acts::eBoundLoc0] << ", "
458 << perigee_pars[Acts::eBoundLoc1] << ", "
459 << perigee_pars[Acts::eBoundPhi] << ", "
460 << perigee_pars[Acts::eBoundTheta] << ", "
461 << perigee_pars[Acts::eBoundQOverP] << ") ";
462
463 ldmx::Track trk;
464
465 // Extrapolate GSF track to target surface to get perigee parameters
466 ldmx_log(debug) << " Extrapolating to target (itrk=" << itrk << ")";
467 auto opt_target = trk_extrap_->extrapolate(gsftrk, target_surface_);
468
469 if (!opt_target) {
470 ++n_fieldmap_target_extrap_failed_;
471 ldmx_log(debug) << " Field-map target extrapolation failed, trying "
472 << fallback_name << " fallback";
473 opt_target = fallback_extrap->extrapolate(gsftrk, target_surface_);
474 if (opt_target) ++n_fallback_target_extrap_recovered_;
475 }
476
477 if (opt_target) {
478 ldmx_log(debug) << " GSF target extrapolation succeeded";
479 auto ts_at_target = tracking::sim::utils::makeTrackState(
480 geometryContext(), *opt_target, ldmx::AtTarget);
481 trk.addTrackState(ts_at_target);
482
483 trk.setPerigeeParameters(tracking::sim::utils::convertActsToLdmxPars(
484 opt_target->parameters()));
485 if (opt_target->covariance()) {
486 std::vector<double> cov_vec;
487 tracking::sim::utils::flatCov(*(opt_target->covariance()), cov_vec);
488 trk.setPerigeeCov(cov_vec);
489 }
490 Acts::Vector3 target_loc_ldmx = tracking::sim::utils::acts2Ldmx(
491 target_surface_->localToGlobalTransform(geometryContext())
492 .translation());
493 trk.setPerigeeLocation(target_loc_ldmx[0], target_loc_ldmx[1],
494 target_loc_ldmx[2]);
495
496 ldmx_log(debug)
497 << " GSF target parameters (d0, z0, phi, theta, q/p)= ("
498 << opt_target->parameters()[Acts::eBoundLoc0] << ", "
499 << opt_target->parameters()[Acts::eBoundLoc1] << ", "
500 << opt_target->parameters()[Acts::eBoundPhi] << ", "
501 << opt_target->parameters()[Acts::eBoundTheta] << ", "
502 << opt_target->parameters()[Acts::eBoundQOverP] << ")";
503 } else {
504 ++n_target_extrap_failed_;
505 ++n_tgt_fail_evt;
506 ldmx_log(debug) << " GSF target extrapolation failed (itrk=" << itrk
507 << "), using GSF fit parameters at reference surface";
508 trk.setPerigeeParameters(
509 tracking::sim::utils::convertActsToLdmxPars(perigee_pars));
510 std::vector<double> v_trk_cov;
511 tracking::sim::utils::flatCov(trk_cov, v_trk_cov);
512 trk.setPerigeeCov(v_trk_cov);
513 }
514
515 // Tagger: also add beam-origin state; Recoil: add ECAL state
516 if (tagger_tracking_) {
517 auto opt_beam_origin =
518 trk_extrap_->extrapolate(gsftrk, beam_origin_surface_);
519 if (!opt_beam_origin)
520 opt_beam_origin =
521 fallback_extrap->extrapolate(gsftrk, beam_origin_surface_);
522 if (opt_beam_origin)
523 trk.addTrackState(tracking::sim::utils::makeTrackState(
524 geometryContext(), *opt_beam_origin, ldmx::AtBeamOrigin));
525 } else {
526 ldmx_log(debug) << " ECAL extrapolation";
527 auto opt_ecal = trk_extrap_->extrapolate(gsftrk, ecal_surface_);
528
529 if (!opt_ecal) {
530 ++n_fieldmap_ecal_extrap_failed_;
531 ldmx_log(debug) << " Field-map ECAL extrapolation failed, trying "
532 << fallback_name << " fallback";
533 opt_ecal = fallback_extrap->extrapolate(gsftrk, ecal_surface_);
534 if (opt_ecal) ++n_fallback_ecal_extrap_recovered_;
535 }
536
537 if (opt_ecal)
538 trk.addTrackState(tracking::sim::utils::makeTrackState(
539 geometryContext(), *opt_ecal, ldmx::AtECAL));
540 else
541 ++n_ecal_extrap_failed_;
542 }
543
544 trk.setChi2(gsftrk.chi2());
545 trk.setNhits(gsftrk.nMeasurements());
546 trk.setNdf(gsftrk.nMeasurements() - 5);
547 trk.setCharge(perigee_pars[Acts::eBoundQOverP] > 0 ? 1 : -1);
548
549 // Truth information carried over from input track
550 trk.setTrackID(track.getTrackID());
551 trk.setPdgID(track.getPdgID());
552 trk.setTruthProb(track.getTruthProb());
553
554 itrk++;
555
556 ldmx_log(debug) << " Added track to output, total tracks = "
557 << (out_tracks.size() + 1);
558
559 out_tracks.push_back(trk);
560
561 } // loop on tracks
562
563 ldmx_log(debug) << "[GSF evt " << nevents_ << "] in=" << tracks.size()
564 << " gsf_ok=" << n_gsf_ok_evt
565 << " tgt_fail=" << n_tgt_fail_evt
566 << " out=" << out_tracks.size();
567
568 n_output_tracks_ += static_cast<int>(out_tracks.size());
569 event.add(out_trk_collection_, out_tracks);
570
571 auto t_end = std::chrono::high_resolution_clock::now();
572 processing_time_ +=
573 std::chrono::duration<double, std::milli>(t_end - t_start).count();
574 ++nevents_;
575} // end of produce()
576
578
580 ldmx_log(info) << "--------------------------------- ";
581 ldmx_log(info) << "GSF: " << n_output_tracks_ << " output tracks / "
582 << n_input_tracks_ << " input tracks";
583 ldmx_log(info) << "AVG Time/Event: " << std::fixed << std::setprecision(1)
584 << processing_time_ / nevents_ << " ms";
585 ldmx_log(info) << "GSF Fit Failures: " << n_gsf_failed_;
586 ldmx_log(info) << "Extrapolation Failures::";
587 if (tagger_tracking_)
588 ldmx_log(info) << " Tagger start: " << n_start_extrap_failed_ << " times";
589 ldmx_log(info) << " Target: " << n_target_extrap_failed_ << " times";
590 if (!tagger_tracking_)
591 ldmx_log(info) << " ECAL: " << n_ecal_extrap_failed_ << " times";
592
593 const std::string fallback_name = tagger_tracking_ ? "const-B" : "zero-B";
594 auto recovery_fraction = [](int recovered, int failed) {
595 return failed > 0 ? 100.0 * recovered / failed : 0.0;
596 };
597
598 ldmx_log(info) << "GSF Fallback Statistics (" << fallback_name << ")::";
599 ldmx_log(info) << " Fit: field-map failed " << n_fieldmap_gsf_failed_
600 << " times, fallback recovered " << n_fallback_gsf_recovered_
601 << " ("
602 << recovery_fraction(n_fallback_gsf_recovered_,
603 n_fieldmap_gsf_failed_)
604 << "%)";
605 if (tagger_tracking_)
606 ldmx_log(info) << " Tagger start extrap: field-map failed "
607 << n_fieldmap_start_extrap_failed_
608 << " times, fallback recovered "
609 << n_fallback_start_extrap_recovered_ << " ("
610 << recovery_fraction(n_fallback_start_extrap_recovered_,
611 n_fieldmap_start_extrap_failed_)
612 << "%)";
613 ldmx_log(info) << " Target extrap: field-map failed "
614 << n_fieldmap_target_extrap_failed_
615 << " times, fallback recovered "
616 << n_fallback_target_extrap_recovered_ << " ("
617 << recovery_fraction(n_fallback_target_extrap_recovered_,
618 n_fieldmap_target_extrap_failed_)
619 << "%)";
620 if (!tagger_tracking_)
621 ldmx_log(info) << " ECAL extrap: field-map failed "
622 << n_fieldmap_ecal_extrap_failed_
623 << " times, fallback recovered "
624 << n_fallback_ecal_extrap_recovered_ << " ("
625 << recovery_fraction(n_fallback_ecal_extrap_recovered_,
626 n_fieldmap_ecal_extrap_failed_)
627 << "%)";
628}
629
630} // namespace reco
631} // namespace tracking
632
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Implements an event buffer system for storing event data.
Definition Event.h:40
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:107
Class which represents the process under execution.
Definition Process.h:34
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:68
Implementation of a track object.
Definition Track.h:54
bool disable_all_material_handling_
Disable all material interactions during propagation.
std::shared_ptr< Acts::Surface > target_surface_
Target surface at z=0 mm (recoil track initialization, perigee output)
std::unique_ptr< const GsfFitter > gsf_
Gaussian Sum Fitter instance for track refitting.
double bfield_
Bz of the tagger fallback field, in Tesla.
std::unique_ptr< const GsfFitter > gsf_zero_b_
Zero-field GSF, fallback for the recoil.
void produce(framework::Event &event) override
Run the processor.
BFieldDistortion bfield_distortion_
Mis-placement of the reconstruction field; must match the CKF's.
bool debug_
Enable verbose debug output logging.
std::string track_collection_
Collection name for input tracks to be refit.
size_t max_components_
Maximum number of mixture components in GSF fit.
std::string meas_collection_
Collection name for measurements associated with tracks.
bool abort_on_error_
Abort fit if any error occurs (strict error handling)
std::string meas_passname_
Pass name for measurement collection in event.
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
double weight_cutoff_
Weight threshold below which mixture components are dropped.
std::string field_map_
Path to magnetic field map file.
std::shared_ptr< Acts::Surface > tagger_start_surface_
Tagger GSF start surface at x=tagger_start_x_ in ACTS.
void configure(framework::config::Parameters &parameters) override
Configure the processor using the given user specified parameters.
int propagator_max_steps_
Maximum number of propagation steps before aborting.
bool use_perigee_
Use perigee parameterization for tracks.
GSFProcessor(const std::string &name, framework::Process &process)
Constructor.
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
void onNewRun(const ldmx::RunHeader &rh) override
onNewRun is the first function called for each processor after the conditions are fully configured an...
std::string track_collection_event_passname_
Pass name qualifier for track collection event key.
std::unique_ptr< const Propagator > propagator_
Propagator for track extrapolation using eigen stepper.
double propagator_step_size_
Step size for track propagation in mm.
std::shared_ptr< Acts::Surface > beam_origin_surface_
Beam origin surface at z=-700 mm (tagger post-fit extrapolation via VoidNavigator)
std::string track_passname_
Pass name for track collection in event.
std::shared_ptr< Acts::Surface > ecal_surface_
ECAL surface at z=240.5 mm (ECAL scoring plane for recoil tracking)
std::unique_ptr< const GsfFitter > gsf_const_b_
Constant-field (bfield_) GSF, fallback for the tagger.
std::string meas_collection_event_passname_
Pass name qualifier for measurement collection event key.
double tagger_start_x_
ACTS x of the tagger GSF start surface [mm].
std::string out_trk_collection_
Collection name for output GSF-refitted tracks.
a helper base class providing some methods to shorten access to common conditions used within the tra...
static BFieldDistortion bFieldDistortion(const framework::config::Parameters &parameters)
Build a BFieldDistortion from processor configuration.
void loadBField(const std::string &path, const BFieldDistortion &distortion={})
Load the interpolated B-field map from path and cache it.
std::shared_ptr< Acts::MagneticFieldProvider > bField() const
Return the loaded B-field provider.
void calibrate1d(const Acts::GeometryContext &, const Acts::CalibrationContext &, const Acts::SourceLink &genericSourceLink, typename traj_t::TrackStateProxy trackState) const
Find the measurement corresponding to the source link.
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...