36 profiling_map_[
"setup"] = 0.;
37 profiling_map_[
"hits"] = 0.;
38 profiling_map_[
"seeds"] = 0.;
39 profiling_map_[
"ckf_setup"] = 0.;
40 profiling_map_[
"ckf_run"] = 0.;
41 profiling_map_[
"result_loop"] = 0.;
49 Acts::Vector3 b_field(0., 0., bfield_ * Acts::UnitConstants::T);
52 const auto const_b_field = std::make_shared<Acts::ConstantBField>(b_field);
60 surf_rotation_ = Acts::RotationMatrix3::Zero();
62 surf_rotation_(1, 0) = 1;
64 surf_rotation_(2, 1) = 1;
66 surf_rotation_(0, 2) = 1;
68 Acts::Vector3 target_pos(0., 0., 0.);
69 Acts::Translation3 target_translation(target_pos);
70 Acts::Transform3 target_transform(target_translation * surf_rotation_);
74 Acts::Surface::makeShared<Acts::PlaneSurface>(target_transform);
77 if (field_map_.empty())
82 std::static_pointer_cast<InterpolatedMagneticField3>(
bField());
84 auto acts_logging_level = Acts::Logging::FATAL;
85 if (debug_acts_) acts_logging_level = Acts::Logging::VERBOSE;
89 std::shared_ptr<const Acts::MagneticFieldProvider> field = map;
90 if (field_zero_outside_) {
91 field = std::make_shared<tracking::sim::ZeroOutsideBField>(map);
93 const auto stepper = Acts::EigenStepper<>{field};
94 const auto const_stepper = Acts::EigenStepper<>{const_b_field};
95 const auto multi_stepper = Acts::MultiEigenStepperLoop{map};
98 Acts::Navigator::Config nav_cfg{geometry().getTG()};
99 nav_cfg.resolveMaterial =
true;
100 nav_cfg.resolvePassive =
true;
101 nav_cfg.resolveSensitive =
true;
102 const Acts::Navigator navigator(nav_cfg);
104 propagator_ = std::make_unique<CkfPropagator>(
106 Acts::getDefaultLogger(
"CKF_PROP", acts_logging_level));
109 ckf_ = std::make_unique<std::decay_t<
decltype(*ckf_)>>(
110 *propagator_, Acts::getDefaultLogger(
"CKF", acts_logging_level));
114 propagator_extrap_ = std::make_unique<ExtrapPropagator>(
115 Acts::EigenStepper<>{field}, Acts::VoidNavigator{});
116 trk_extrap_ = std::make_shared<std::decay_t<
decltype(*trk_extrap_)>>(
117 *propagator_extrap_, geometryContext(), magneticFieldContext());
120 Acts::ConstantBField zero_b_field(Acts::Vector3(0., 0., 0.));
121 const auto zero_b_stepper = Acts::EigenStepper<>{
122 std::make_shared<Acts::ConstantBField>(zero_b_field)};
124 std::make_unique<CkfPropagator>(zero_b_stepper, navigator);
125 ckf_zero_b_ = std::make_unique<std::decay_t<
decltype(*ckf_zero_b_)>>(
127 Acts::getDefaultLogger(
"CKF_ZERO_B", acts_logging_level));
128 propagator_extrap_zero_b_ = std::make_unique<ExtrapPropagator>(
129 Acts::EigenStepper<>{
130 std::make_shared<Acts::ConstantBField>(zero_b_field)},
131 Acts::VoidNavigator{});
133 std::make_shared<std::decay_t<
decltype(*trk_extrap_zero_b_)>>(
134 *propagator_extrap_zero_b_, geometryContext(),
135 magneticFieldContext());
138 propagator_const_b_ =
139 std::make_unique<CkfPropagator>(const_stepper, navigator);
140 ckf_const_b_ = std::make_unique<std::decay_t<
decltype(*ckf_const_b_)>>(
141 *propagator_const_b_,
142 Acts::getDefaultLogger(
"CKF_CONST_B", acts_logging_level));
143 propagator_extrap_const_b_ = std::make_unique<ExtrapPropagator>(
144 Acts::EigenStepper<>{const_b_field}, Acts::VoidNavigator{});
145 trk_extrap_const_b_ =
146 std::make_shared<std::decay_t<
decltype(*trk_extrap_const_b_)>>(
147 *propagator_extrap_const_b_, geometryContext(),
148 magneticFieldContext());
158 std::vector<ldmx::Track> tracks;
160 auto start = std::chrono::high_resolution_clock::now();
164 ACTS_LOCAL_LOGGER(Acts::getDefaultLogger(
"LDMX Tracking Geometry Maker",
165 Acts::Logging::DEBUG));
168 Acts::PropagatorOptions<Acts::StepperPlainOptions,
169 Acts::NavigatorPlainOptions, ActionList>
170 propagator_options(geometryContext(), magneticFieldContext());
172 propagator_options.pathLimit = std::numeric_limits<double>::max();
174 propagator_options.loopProtection =
false;
179 propagator_options.actorList.get<Acts::MaterialInteractor>();
180 m_interactor.multipleScattering =
true;
181 m_interactor.energyLoss =
true;
182 m_interactor.recordInteractions =
false;
186 propagator_options.actorList.get<Acts::detail::SteppingLogger>();
187 s_logger.sterile =
true;
189 propagator_options.stepping.maxStepSize =
190 propagator_step_size_ * Acts::UnitConstants::mm;
191 propagator_options.maxSteps = propagator_max_steps_;
201 auto setup = std::chrono::high_resolution_clock::now();
202 profiling_map_[
"setup"] +=
203 std::chrono::duration<double, std::milli>(setup - start).count();
206 measurement_collection_, input_pass_name_);
209 std::shared_ptr<tracking::sim::TruthMatchingTool> truth_matching_tool =
211 std::map<int, ldmx::SimParticle> particle_map;
213 if (event.
exists(sim_particles_coll_name_, sim_particles_event_passname_)) {
214 ldmx_log(debug) <<
"Setting up track truth matching tool";
216 sim_particles_coll_name_, sim_particles_event_passname_);
217 truth_matching_tool = std::make_shared<tracking::sim::TruthMatchingTool>(
218 particle_map, measurements);
222 std::vector<TargetPoint> target_points;
223 if (!tagger_tracking_ && use_target_constraint_) {
229 const auto geo_id_sl_map = makeGeoIdSourceLinkMap(tg, measurements);
231 auto hits = std::chrono::high_resolution_clock::now();
232 profiling_map_[
"hits"] +=
233 std::chrono::duration<double, std::milli>(hits - setup).count();
238 const auto& seed_tracks =
239 event.getCollection<
ldmx::Track>(seed_coll_name_, input_pass_name_);
241 ldmx_log(info) <<
"Number of " << seed_coll_name_
242 <<
" seed tracks = " << seed_tracks.size();
244 if (seed_tracks.empty()) {
245 std::vector<ldmx::Track> empty;
246 ldmx_log(warn) <<
"No seed tracks, returning...";
247 event.add(out_trk_collection_, empty);
252 std::vector<Acts::BoundTrackParameters> start_parameters;
254 ldmx_log(debug) <<
"Transform the seed track to bound parameters";
255 int seed_track_index{0};
256 for (
auto& seed : seed_tracks) {
260 Acts::Vector3 perigee_acts = tracking::sim::utils::ldmx2Acts(Acts::Vector3(
261 seed.getPerigeeX(), seed.getPerigeeY(), seed.getPerigeeZ()));
262 std::shared_ptr<Acts::PerigeeSurface> perigee_surface =
263 Acts::Surface::makeShared<Acts::PerigeeSurface>(perigee_acts);
265 Acts::BoundVector param_vec;
266 param_vec << seed.getD0(), seed.getZ0(), seed.getPhi(), seed.getTheta(),
267 seed.getQoP(), seed.getT();
269 Acts::BoundMatrix cov_mat =
270 tracking::sim::utils::unpackCov(seed.getPerigeeCov());
272 ldmx_log(debug) <<
" For seed index_ = " << seed_track_index
273 <<
": Perigee X / Y / Z = " << seed.getPerigeeX() <<
" / "
274 << seed.getPerigeeY() <<
" / " << seed.getPerigeeZ()
275 <<
", D0 = " << param_vec[0] <<
", Z0 = " << param_vec[1]
276 <<
", Phi = " << param_vec[2]
277 <<
", Theta = " << param_vec[3]
278 <<
", QoP = " << param_vec[4]
279 <<
", Time = " << param_vec[5];
281 ldmx_log(debug) <<
" Cov matrix diagonal (" << cov_mat(0, 0) <<
", "
282 << cov_mat(1, 1) <<
", " << cov_mat(2, 2) <<
")";
285 auto part_hypo{Acts::ParticleHypothesis::electron()};
286 start_parameters.push_back(Acts::BoundTrackParameters(
287 perigee_surface, param_vec, cov_mat, part_hypo));
295 auto seeds = std::chrono::high_resolution_clock::now();
296 profiling_map_[
"seeds"] +=
297 std::chrono::duration<double, std::milli>(seeds - hits).count();
299 Acts::GainMatrixUpdater kf_updater;
304 Acts::MeasurementSelector::Config measurement_selector_cfg = {
306 {Acts::GeometryIdentifier(), {{}, {outlier_pval_}, {1u}}},
309 Acts::MeasurementSelector meas_sel{measurement_selector_cfg};
314 struct SourceLinkAccIt {
315 using BaseIt =
decltype(geo_id_sl_map.begin());
318#pragma GCC diagnostic push
319#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
321 using difference_type =
typename BaseIt::difference_type;
322 using iterator_category =
typename BaseIt::iterator_category;
323 using value_type = Acts::SourceLink;
324 using pointer =
typename BaseIt::pointer;
325 using reference = value_type&;
326#pragma GCC diagnostic pop
328 SourceLinkAccIt& operator++() {
332 bool operator==(
const SourceLinkAccIt& other)
const {
333 return it_ == other.it_;
335 bool operator!=(
const SourceLinkAccIt& other)
const {
336 return !(*
this == other);
338 value_type operator*()
const {
return value_type{it_->second}; }
341 auto source_link_accessor = [&](
const Acts::Surface& surface)
342 -> std::pair<SourceLinkAccIt, SourceLinkAccIt> {
343 auto [begin, end] = geo_id_sl_map.equal_range(surface.geometryId());
344 return {SourceLinkAccIt{begin}, SourceLinkAccIt{end}};
348 Acts::TrackStateCreator<SourceLinkAccIt, TrackContainer> track_state_creator;
349 track_state_creator.sourceLinkAccessor
350 .connect<&
decltype(source_link_accessor)::operator(),
351 decltype(source_link_accessor)>(&source_link_accessor);
352 if (use1_dmeasurements_) {
353 track_state_creator.calibrator
355 Acts::VectorMultiTrajectory>>(&calibrator);
357 track_state_creator.calibrator
359 Acts::VectorMultiTrajectory>>(&calibrator);
361 track_state_creator.measurementSelector
362 .connect<&Acts::MeasurementSelector::select<Acts::VectorMultiTrajectory>>(
365 Acts::CombinatorialKalmanFilterExtensions<TrackContainer> ckf_extensions;
366 ckf_extensions.updater.connect<
367 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
369 ckf_extensions.createTrackStates.connect<&Acts::TrackStateCreator<
370 SourceLinkAccIt, TrackContainer>::createTrackStates>(
371 &track_state_creator);
373 ldmx_log(debug) <<
"Setting up surfaces...";
375 std::shared_ptr<const Acts::PerigeeSurface> origin_surface =
376 Acts::Surface::makeShared<Acts::PerigeeSurface>(
377 Acts::Vector3(0., 0., 0.));
379 ldmx_log(debug) <<
"About to run CKF...";
382 auto ckf_setup = std::chrono::high_resolution_clock::now();
383 profiling_map_[
"ckf_setup"] +=
384 std::chrono::duration<double, std::milli>(ckf_setup - seeds).count();
386 Acts::VectorTrackContainer vtc;
387 Acts::VectorMultiTrajectory mtj;
388 Acts::TrackContainer tc{vtc, mtj};
392 ldmx_log(debug) <<
"Loop on the track candidates";
393 for (
size_t track_id = 0u; track_id < start_parameters.size(); ++track_id) {
394 ldmx_log(debug) <<
"---------------------------";
395 ldmx_log(debug) <<
"Candidate Track ID = " << track_id;
397 const Acts::CombinatorialKalmanFilterOptions<TrackContainer> ckf_options(
398 TrackingGeometryUser::geometryContext(),
399 TrackingGeometryUser::magneticFieldContext(),
400 TrackingGeometryUser::calibrationContext(), ckf_extensions,
401 static_cast<Acts::PropagatorPlainOptions
>(propagator_options),
404 ldmx_log(debug) <<
" Checking options: multiple scattering = "
405 << ckf_options.multipleScattering
406 <<
" energy loss = " << ckf_options.energyLoss;
410 ckf_->findTracks(start_parameters.at(track_id), ckf_options, tc);
412 auto start_params = start_parameters.at(track_id).parameters().transpose();
416 ckf_errors_[results.error().message()]++;
417 if (!tagger_tracking_) {
419 n_fieldmap_ckf_failed_recoil_++;
421 <<
" Field-map CKF failed, trying zero-B CKF fallback";
422 results = ckf_zero_b_->findTracks(start_parameters.at(track_id),
425 n_zerob_ckf_recovered_recoil_++;
426 ldmx_log(debug) <<
" Yay! Zero-B CKF succeeded as fallback!";
428 ldmx_log(debug) <<
" Zero-B CKF also failed!";
432 n_fieldmap_ckf_failed_tagger_++;
434 <<
" Field-map CKF failed, trying const-B (1.5T) CKF fallback";
435 results = ckf_const_b_->findTracks(start_parameters.at(track_id),
438 n_constb_ckf_recovered_tagger_++;
439 ldmx_log(debug) <<
" Yay! Const-B CKF succeeded as fallback!";
441 ldmx_log(debug) <<
" Const-B CKF also failed!";
447 <<
" Checking CKF success for track candidate with params: "
448 <<
" D0 = " << start_params[0] <<
" Z0 = " << start_params[1]
449 <<
", Phi = " << start_params[2] <<
" Theta = " << start_params[3]
450 <<
", QoP = " << start_params[4] <<
" Time = " << start_params[5];
451 if (not results.ok()) {
452 ldmx_log(debug) <<
" CKF failed!";
455 ldmx_log(debug) <<
" CKF succeded!";
458 auto& tracks_from_seed = results.value();
459 if (tracks_from_seed.size() != 1) {
460 ldmx_log(info) <<
" tracksFromSeed.size = " << tracks_from_seed.size();
463 for (
auto& track : tracks_from_seed) {
465 auto smooth_result = Acts::smoothTrack(geometryContext(), track);
466 if (!smooth_result.ok()) {
467 ldmx_log(warn) <<
"smoothTrack failed: "
468 << smooth_result.error().message();
474 auto opt_target = trk_extrap_->extrapolate(track, target_surface_);
477 if (tagger_tracking_) {
478 n_fieldmap_target_extrap_failed_tagger_++;
479 ldmx_log(debug) <<
" Field-map target extrapolation failed, "
480 "trying const-B (1.5T) fallback";
481 opt_target = trk_extrap_const_b_->extrapolate(track, target_surface_);
483 n_constb_target_extrap_recovered_tagger_++;
485 ldmx_log(debug) <<
" Both field-map and Const-B target "
486 "extrapolation failed!";
488 n_fieldmap_target_extrap_failed_recoil_++;
489 ldmx_log(debug) <<
" Field-map target extrapolation failed, "
490 "trying zero-B fallback";
491 opt_target = trk_extrap_zero_b_->extrapolate(track, target_surface_);
493 n_zerob_target_extrap_recovered_recoil_++;
496 <<
" Both field-map and Zero-B target extrapolation failed!";
501 ldmx_log(debug) <<
" Could not extrapolate to target! nhits = "
502 << track.nMeasurements() <<
" Printing track states:";
503 for (
const auto ts : track.trackStatesReversed()) {
504 if (ts.hasSmoothed())
505 ldmx_log(debug) <<
" Parameters: " << ts.smoothed().transpose();
507 ldmx_log(debug) <<
" Track state not smoothed!";
509 ldmx_log(debug) <<
" ...skipping this track candidate...";
513 ldmx_log(debug) <<
" Successfully obtained TrackState at target";
521 const bool short_enough = target_constraint_max_hits_ < 0 ||
522 static_cast<int>(track.nMeasurements()) <=
523 target_constraint_max_hits_;
524 if (!target_points.empty() && short_enough) {
525 if (opt_target->covariance()) {
526 const Acts::BoundVector x = opt_target->parameters();
527 const Acts::BoundMatrix c = *opt_target->covariance();
528 Acts::Matrix<2, 6> h = Acts::Matrix<2, 6>::Zero();
529 h(0, Acts::eBoundLoc0) = 1.;
530 h(1, Acts::eBoundLoc1) = 1.;
532 double best_chi2{std::numeric_limits<double>::infinity()};
533 Acts::Vector2 best_r{Acts::Vector2::Zero()};
534 Acts::Matrix<2, 2> best_s_inv{Acts::Matrix<2, 2>::Identity()};
535 Acts::Matrix<2, 2> best_v{Acts::Matrix<2, 2>::Zero()};
538 const double p_gev = 1. / std::abs(x[Acts::eBoundQOverP]);
540 const double phi = x[Acts::eBoundPhi];
541 const double slope[2] = {
543 1. / std::tan(x[Acts::eBoundTheta]) / std::cos(phi)};
544 Acts::Matrix<2, 2> extra = Acts::Matrix<2, 2>::Zero();
545 for (
int d = 0; d < 2; ++d) {
546 extra(d, d) = target_sigma_extra_[d] * target_sigma_extra_[d] +
547 std::pow(target_thickness_ * slope[d], 2) / 12. +
548 std::pow(target_sigma_extra_ms_[d] / p_gev, 2);
550 for (
const auto& tp : target_points) {
551 const Acts::Vector2 r = tp.loc_ - h * x;
552 const Acts::Matrix<2, 2> s_inv =
553 (h * c * h.transpose() + tp.cov_ + extra).inverse();
554 const double chi2 = r.transpose() * s_inv * r;
555 if (chi2 < best_chi2) {
559 best_v = tp.cov_ + extra;
562 const Acts::Matrix<6, 2> k = c * h.transpose() * best_s_inv;
563 const Acts::BoundVector x_new = x + k * best_r;
565 const Acts::BoundMatrix i_kh = Acts::BoundMatrix::Identity() - k * h;
566 const Acts::BoundMatrix c_new =
567 i_kh * c * i_kh.transpose() + k * best_v * k.transpose();
568 opt_target = Acts::BoundTrackParameters(
569 target_surface_, x_new, c_new, opt_target->particleHypothesis());
570 chi2_tgt = best_chi2;
579 auto ts_at_target = tracking::sim::utils::makeTrackState(
580 geometryContext(), *opt_target, ldmx::AtTarget);
581 trk.addTrackState(ts_at_target);
583 ldmx_log(debug) <<
" Position at target (LDMX): ("
584 << ts_at_target.pos_[0] <<
", " << ts_at_target.pos_[1]
585 <<
", " << ts_at_target.pos_[2] <<
") mm"
586 <<
" Momentum: (" << ts_at_target.mom_[0] <<
", "
587 << ts_at_target.mom_[1] <<
", " << ts_at_target.mom_[2]
591 track.setReferenceSurface(target_surface_);
592 track.parameters() = opt_target->parameters();
595 trk.setPerigeeParameters(tracking::sim::utils::convertActsToLdmxPars(
596 opt_target->parameters()));
597 if (opt_target->covariance()) {
598 std::vector<double> cov_vec;
599 tracking::sim::utils::flatCov(*(opt_target->covariance()), cov_vec);
600 trk.setPerigeeCov(cov_vec);
603 Acts::Vector3 target_loc_ldmx = tracking::sim::utils::acts2Ldmx(
604 target_surface_->localToGlobalTransform(geometryContext())
606 trk.setPerigeeLocation(target_loc_ldmx[0], target_loc_ldmx[1],
609 trk.setChi2(track.chi2() + chi2_tgt);
610 trk.setNhits(track.nMeasurements());
611 trk.setNdf(track.nMeasurements() - 5 + ndf_tgt);
612 trk.setNsharedHits(track.nSharedHits());
613 trk.setCharge(opt_target->parameters()[Acts::eBoundQOverP] > 0 ? 1 : -1);
616 if ((trk.getNhits() <= min_hits_) ||
617 (std::abs(1. / trk.getQoP()) <= 0.05)) {
619 <<
" > Track candidate did NOT meet the requirements: Nhits = "
620 << trk.getNhits() <<
" and p = " << std::abs(1. / trk.getQoP())
626 ldmx_log(debug) <<
" Add measurements to the final track from "
627 << track.nTrackStates() <<
" TrackStates with "
628 << track.nMeasurements() <<
" measurements";
630 int trk_state_index{0};
631 for (
const auto ts : track.trackStatesReversed()) {
633 ldmx_log(debug) <<
" Checking Track State index_ = "
634 << trk_state_index <<
" at location "
635 << ts.referenceSurface()
636 .localToGlobalTransform(geometryContext())
640 if (ts.hasSmoothed()) {
641 ldmx_log(debug) <<
" Smoothed track parameters: "
642 << ts.smoothed().transpose();
648 auto type_flags = ts.typeFlags();
650 if (type_flags.isMeasurement() && ts.hasUncalibratedSourceLink()) {
651 Acts::SourceLink usl = ts.getUncalibratedSourceLink();
656 ldmx_log(debug) <<
" Adding measurement to ldmx::track with "
657 "source link index_ = "
659 ldmx_log(trace) <<
" Measurement:\n" << ldmx_meas;
660 trk.addMeasurementIndex(sl.
index());
668 if (ts.hasSmoothed()) {
670 static_cast<float>(ts.smoothed()[Acts::eBoundLoc0]),
671 static_cast<float>(ts.smoothedCovariance()(Acts::eBoundLoc0,
676 if (ts.hasSmoothed()) {
677 const auto& meas_surface = ts.referenceSurface();
678 const auto& smoothed_params = ts.smoothed();
683 float p_inv = smoothed_params[Acts::eBoundQOverP];
684 float p = 1.0f / std::abs(p_inv);
685 float theta = smoothed_params[Acts::eBoundTheta];
686 float phi = smoothed_params[Acts::eBoundPhi];
688 Acts::Vector3 global_momentum(p * std::sin(theta) * std::cos(phi),
689 p * std::sin(theta) * std::sin(phi),
690 p * std::cos(theta));
693 auto local_frame_transform =
694 meas_surface.localToGlobalTransform(geometryContext());
695 Acts::Vector3 local_momentum =
696 local_frame_transform.rotation().transpose() * global_momentum;
699 float phi_u = (local_momentum.z() != 0)
700 ? local_momentum.x() / local_momentum.z()
702 float phi_v = (local_momentum.z() != 0)
703 ? local_momentum.y() / local_momentum.z()
710 float sensor_thickness = 0.0f;
711 if (
const auto* placement = meas_surface.surfacePlacement()) {
712 sensor_thickness =
static_cast<float>(
716 ldmx_log(warn) <<
"No detector element for measurement surface"
717 <<
" — skipping dE/dx for this hit";
720 float tan_angle_sq = phi_u * phi_u + phi_v * phi_v;
721 float cos_angle = 1.0f / std::sqrt(1.0f + tan_angle_sq);
722 float path_length = sensor_thickness / cos_angle;
724 ldmx_log(debug) <<
" Local angles: phi_u = " << phi_u
725 <<
", phi_v = " << phi_v
726 <<
"; Path length = " << path_length <<
" mm";
729 float edep = ldmx_meas.getEdep();
730 float dedx = edep / path_length;
731 trk.addDedxMeasurement(dedx);
733 ldmx_log(debug) <<
" Edep = " << edep
734 <<
" MeV, dE/dx = " << dedx <<
" MeV/mm";
737 ldmx_log(debug) <<
" This TrackState is not a measurement";
742 ldmx_log(debug) <<
" Starting extrapolations";
745 const double ecal_scoring_plane = 240.5;
746 Acts::Vector3 pos(ecal_scoring_plane, 0., 0.);
747 Acts::Translation3 surf_translation(pos);
748 Acts::Transform3 surf_transform(surf_translation * surf_rotation_);
749 const std::shared_ptr<Acts::PlaneSurface> ecal_surface =
750 Acts::Surface::makeShared<Acts::PlaneSurface>(surf_transform);
753 const std::shared_ptr<Acts::Surface> beam_origin_surface =
754 tracking::sim::utils::unboundSurface(-700);
756 if (tagger_tracking_) {
757 ldmx_log(debug) <<
" Beam Origin Extrapolation";
758 auto opt_beam_origin =
759 trk_extrap_->extrapolate(track, beam_origin_surface);
760 if (opt_beam_origin) {
761 trk.addTrackState(tracking::sim::utils::makeTrackState(
762 geometryContext(), *opt_beam_origin, ldmx::AtBeamOrigin));
764 <<
" Successfully obtained TrackState at beam origin";
769 if (!tagger_tracking_) {
770 ldmx_log(debug) <<
" Ecal Extrapolation";
771 auto opt_ecal = trk_extrap_->extrapolate(track, ecal_surface);
774 n_fieldmap_ecal_extrap_failed_recoil_++;
775 ldmx_log(debug) <<
" Field-map ECAL extrapolation failed, trying "
777 opt_ecal = trk_extrap_zero_b_->extrapolate(track, ecal_surface);
779 n_zerob_ecal_extrap_recovered_recoil_++;
782 <<
" Both field-map and Zero-B ECAL extrapolation failed!";
786 auto ts_at_ecal = tracking::sim::utils::makeTrackState(
787 geometryContext(), *opt_ecal, ldmx::AtECAL);
788 trk.addTrackState(ts_at_ecal);
789 ldmx_log(debug) <<
" Successfully obtained TrackState at ECAL";
790 ldmx_log(debug) <<
" Position at ECAL (LDMX): ("
791 << ts_at_ecal.pos_[0] <<
", " << ts_at_ecal.pos_[1]
792 <<
", " << ts_at_ecal.pos_[2] <<
") mm";
797 if (truth_matching_tool) {
798 auto truth_info = truth_matching_tool->truthMatch(trk);
799 trk.setTrackID(truth_info.track_id_);
800 trk.setPdgID(truth_info.pdg_id_);
801 trk.setTruthProb(truth_info.truth_prob_);
806 <<
" > Adding the track candidate to the track collection";
807 tracks.push_back(trk);
812 ldmx_log(info) <<
"Number of CKF tracks " << tracks.size();
814 auto ckf_run = std::chrono::high_resolution_clock::now();
815 profiling_map_[
"ckf_run"] +=
816 std::chrono::duration<double, std::milli>(ckf_run - ckf_setup).count();
819 auto shared_hits = computeSharedHits(
820 tracks, measurements, tg, tracking::sim::utils::sourceLinkHash,
821 tracking::sim::utils::sourceLinkEquality);
822 for (std::size_t i_track = 0; i_track < shared_hits.size(); ++i_track) {
823 tracks[i_track].setNsharedHits(shared_hits[i_track].size());
824 for (
auto idx : shared_hits[i_track]) {
825 tracks[i_track].addSharedIndex(idx);
829 auto result_loop = std::chrono::high_resolution_clock::now();
830 profiling_map_[
"result_loop"] +=
831 std::chrono::duration<double, std::milli>(result_loop - ckf_run).count();
834 event.add(out_trk_collection_, tracks);
836 auto end = std::chrono::high_resolution_clock::now();
839 auto diff = end - start;
840 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();