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