56 parameters.
get<std::string>(
"scoring_hits_coll_name");
57 ecal_sp_coll_name_ = parameters.
get<std::string>(
"ecal_sp_coll_name");
58 sp_pass_name_ = parameters.
get<std::string>(
"sp_pass_name");
60 parameters.
get<std::string>(
"recoil_sim_hits_coll_name");
62 parameters.
get<std::string>(
"tagger_sim_hits_coll_name");
64 sim_particles_coll_name_ =
65 parameters.
get<std::string>(
"sim_particles_coll_name");
66 sim_particles_passname_ =
67 parameters.
get<std::string>(
"sim_particles_passname");
71 pdg_ids_ = parameters.
get<std::vector<int>>(
"pdg_ids", {11});
72 z_min_ = parameters.
get<
double>(
"z_min", -9999);
74 pz_cut_ = parameters.
get<
double>(
"pz_cut", -9999);
75 p_cut_ = parameters.
get<
double>(
"p_cut", 0.);
77 p_cut_ecal_ = parameters.
get<
double>(
"p_cut_ecal", -1.);
78 recoil_sp_ = parameters.
get<
double>(
"recoil_sp",
true);
79 target_sp_ = parameters.
get<
double>(
"tagger_sp",
true);
80 seed_smearing_ = parameters.
get<
bool>(
"seedSmearing",
false);
81 max_track_id_ = parameters.
get<
int>(
"max_track_id", 5);
83 ldmx_log(info) <<
"Seed Smearing is set to " << seed_smearing_;
85 d0smear_ = parameters.
get<std::vector<double>>(
"d0smear", {0.01, 0.01, 0.01});
86 z0smear_ = parameters.
get<std::vector<double>>(
"z0smear", {0.1, 0.1, 0.1});
87 phismear_ = parameters.
get<
double>(
"phismear", 0.001);
88 thetasmear_ = parameters.
get<
double>(
"thetasmear", 0.001);
89 relpsmear_ = parameters.
get<
double>(
"relpsmear", 0.1);
92 rel_smearfactors_ = parameters.
get<std::vector<double>>(
93 "rel_smearfactors", {0.1, 0.1, 0.1, 0.1, 0.1, 0.1});
94 inflate_factors_ = parameters.
get<std::vector<double>>(
95 "inflate_factors", {10., 10., 10., 10., 10., 10.});
103 beam_origin_ = parameters.
get<std::vector<double>>(
"beamOrigin",
104 {-883.0, -21.745876, 0.0});
107 skip_tagger_ = parameters.
get<
bool>(
"skip_tagger",
false);
108 skip_recoil_ = parameters.
get<
bool>(
"skip_recoil",
false);
109 particle_hypothesis_ = parameters.
get<
int>(
"particle_hypothesis");
111 beam_electrons_collection_ =
112 parameters.
get<std::string>(
"beam_electrons_collection");
113 tagger_truth_collection_ =
114 parameters.
get<std::string>(
"tagger_truth_collection");
115 recoil_truth_collection_ =
116 parameters.
get<std::string>(
"recoil_truth_collection");
117 tagger_seeds_collection_ =
118 parameters.
get<std::string>(
"tagger_seeds_collection");
119 recoil_seeds_collection_ =
120 parameters.
get<std::string>(
"recoil_seeds_collection");
148 const std::vector<double>& pos_vec,
const std::vector<double>& p_vec,
150 const std::shared_ptr<Acts::Surface>& target_surface) {
158 Acts::Vector3 pos{pos_vec[0], pos_vec[1], pos_vec[2]};
159 Acts::Vector3 mom{p_vec[0], p_vec[1], p_vec[2]};
162 pos = tracking::sim::utils::ldmx2Acts(pos);
163 mom = tracking::sim::utils::ldmx2Acts(mom);
167 double q{charge * Acts::UnitConstants::e};
176 auto free_params{tracking::sim::utils::toFreeParameters(pos, mom, q)};
181 auto gen_surface{Acts::Surface::makeShared<Acts::PerigeeSurface>(
182 Acts::Vector3(free_params[Acts::eFreePos0], free_params[Acts::eFreePos1],
183 free_params[Acts::eFreePos2]))};
190 Acts::transformFreeToBoundParameters(free_params, *gen_surface,
gctx_)
193 auto part{Acts::GenericParticleHypothesis(
194 Acts::ParticleHypothesis(Acts::PdgParticle(particle_hypothesis_)))};
195 Acts::BoundTrackParameters bound_trk_pars(gen_surface, bound_params,
198 auto prop_bound_state =
199 trk_extrap_->extrapolate(bound_trk_pars, target_surface);
201 if (!prop_bound_state) {
202 ldmx_log(warn) <<
"Propagation to target surface failed — "
203 <<
"track may have exited the B-field map.";
208 Acts::Vector3 ref = target_surface->center(geometryContext());
209 Acts::Vector3 ref_ldmx = tracking::sim::utils::acts2Ldmx(ref);
210 trk.setPerigeeLocation(ref_ldmx(0), ref_ldmx(1), ref_ldmx(2));
212 auto prop_bound_vec = prop_bound_state->parameters();
214 trk.setPerigeeParameters(
215 tracking::sim::utils::convertActsToLdmxPars(prop_bound_vec));
357 bool seed_smearing) {
359 seed.setPerigeeLocation(tt.getPerigeeLocation()[0],
360 tt.getPerigeeLocation()[1],
361 tt.getPerigeeLocation()[2]);
363 seed.setNhits(tt.getNhits());
365 seed.setNsharedHits(0);
366 seed.setTrackID(tt.getTrackID());
367 seed.setPdgID(tt.getPdgID());
368 seed.setTruthProb(1.);
370 Acts::BoundVector bound_params;
371 Acts::BoundVector stddev;
374 ldmx_log(debug) <<
"Smear track and inflate covariance";
386 double sigma_d0 = d0smear_[0];
387 double sigma_z0 = z0smear_[0];
388 double sigma_phi = phismear_;
389 double sigma_theta = thetasmear_;
390 double sigma_p = relpsmear_ * abs(1 / tt.getQoP());
391 double sigma_t = 1. * Acts::UnitConstants::ns;
393 double smear = (*normal_)(generator_);
394 double d0smear = tt.getD0() + smear * sigma_d0;
396 smear = (*normal_)(generator_);
397 double z0smear = tt.getZ0() + smear * sigma_z0;
399 smear = (*normal_)(generator_);
400 double phismear = tt.getPhi() + smear * sigma_phi;
402 smear = (*normal_)(generator_);
403 double thetasmear = tt.getTheta() + smear * sigma_theta;
405 double p = std::abs(1. / tt.getQoP());
406 smear = (*normal_)(generator_);
407 double psmear = p + smear * sigma_p;
409 double q = tt.getQoP() < 0 ? -1. : 1.;
410 double qo_psmear = q / psmear;
412 smear = (*normal_)(generator_);
413 double tsmear = tt.getT() + smear * sigma_t;
415 bound_params << d0smear, z0smear, phismear, thetasmear, qo_psmear, tsmear;
417 stddev[Acts::eBoundLoc0] =
418 inflate_factors_[Acts::eBoundLoc0] * sigma_d0 * Acts::UnitConstants::mm;
419 stddev[Acts::eBoundLoc1] =
420 inflate_factors_[Acts::eBoundLoc1] * sigma_z0 * Acts::UnitConstants::mm;
421 stddev[Acts::eBoundPhi] = inflate_factors_[Acts::eBoundPhi] * sigma_phi;
422 stddev[Acts::eBoundTheta] =
423 inflate_factors_[Acts::eBoundTheta] * sigma_theta;
424 stddev[Acts::eBoundQOverP] =
425 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
426 stddev[Acts::eBoundTime] =
427 inflate_factors_[Acts::eBoundTime] * sigma_t * Acts::UnitConstants::ns;
429 ldmx_log(debug) << stddev;
431 std::vector<double> v_seed_params(
432 (bound_params).data(),
433 bound_params.data() + bound_params.rows() * bound_params.cols());
435 Acts::BoundSquareMatrix bound_cov =
436 stddev.cwiseProduct(stddev).asDiagonal();
437 std::vector<double> v_seed_cov;
438 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
439 seed.setPerigeeParameters(v_seed_params);
440 seed.setPerigeeCov(v_seed_cov);
445 bound_params << tt.getD0(), tt.getZ0(), tt.getPhi(), tt.getTheta(),
446 tt.getQoP(), tt.getT();
448 std::vector<double> v_seed_params(
449 (bound_params).data(),
450 bound_params.data() + bound_params.rows() * bound_params.cols());
452 double p = std::abs(1. / tt.getQoP());
453 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
454 stddev[Acts::eBoundLoc0] = 2 * Acts::UnitConstants::mm;
455 stddev[Acts::eBoundLoc1] = 5 * Acts::UnitConstants::mm;
456 stddev[Acts::eBoundTime] = 1000 * Acts::UnitConstants::ns;
457 stddev[Acts::eBoundPhi] = 5 * Acts::UnitConstants::degree;
458 stddev[Acts::eBoundTheta] = 5 * Acts::UnitConstants::degree;
459 stddev[Acts::eBoundQOverP] = (1. / p) * (1. / p) * sigma_p;
461 Acts::BoundSquareMatrix bound_cov =
462 stddev.cwiseProduct(stddev).asDiagonal();
463 std::vector<double> v_seed_cov;
464 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
465 seed.setPerigeeParameters(v_seed_params);
466 seed.setPerigeeCov(v_seed_cov);
563 sim_particles_coll_name_, sim_particles_passname_)};
569 const std::vector<ldmx::SimTrackerHit> scoring_hits{
574 const std::vector<ldmx::SimTrackerHit> scoring_hits_ecal{
579 const std::vector<ldmx::SimTrackerHit> tagger_sim_hits =
584 const std::vector<ldmx::SimTrackerHit> recoil_sim_hits =
589 if (tagger_sim_hits.size() == 0 && !skip_tagger_) {
590 ldmx_log(error) <<
"Tagger sim hits collection empty for event ";
592 if (recoil_sim_hits.size() == 0 && !skip_recoil_) {
593 ldmx_log(error) <<
"Recoil sim hits collection empty for event ";
597 std::map<int, std::vector<int>> hit_count_map_recoil;
600 std::map<int, std::vector<int>> hit_count_map_tagger;
604 std::vector<int> recoil_sh_idxs;
605 std::unordered_map<int, std::vector<int>> recoil_sh_count_map;
607 std::vector<int> tagger_sh_idxs;
608 std::unordered_map<int, std::vector<int>> tagger_sh_count_map;
612 for (
unsigned int i_sh = 0; i_sh < scoring_hits.size(); i_sh++) {
618 double tagger_p_max = 0.;
624 if (p_vec(2) < 0. || p_vec.norm() <
p_cut_)
continue;
627 if (abs(particle_map[hit.
getTrackID()].getCharge()) < 1e-8)
continue;
629 if (p_vec.norm() > tagger_p_max) {
630 tagger_sh_count_map[hit.
getTrackID()].push_back(i_sh);
638 if (p_vec(2) < 0. || p_vec.norm() <
p_cut_)
continue;
641 if (abs(particle_map[hit.
getTrackID()].getCharge()) < 1e-8)
continue;
643 recoil_sh_count_map[hit.
getTrackID()].push_back(i_sh);
648 for (std::pair<
int, std::vector<int>> element : recoil_sh_count_map) {
650 element.second.begin(), element.second.end(),
651 [&](
const int idx1,
int idx2) ->
bool {
652 const ldmx::SimTrackerHit& hit1 = scoring_hits.at(idx1);
653 const ldmx::SimTrackerHit& hit2 = scoring_hits.at(idx2);
655 Acts::Vector3 phit1{hit1.getMomentum()[0], hit1.getMomentum()[1],
656 hit1.getMomentum()[2]};
657 Acts::Vector3 phit2{hit2.getMomentum()[0], hit2.getMomentum()[1],
658 hit2.getMomentum()[2]};
660 return phit1.norm() > phit2.norm();
665 for (
auto& [_track_id, hit_indices] : tagger_sh_count_map) {
667 hit_indices.begin(), hit_indices.end(),
668 [&](
const int idx1,
int idx2) ->
bool {
669 const ldmx::SimTrackerHit& hit1 = scoring_hits.at(idx1);
670 const ldmx::SimTrackerHit& hit2 = scoring_hits.at(idx2);
672 Acts::Vector3 phit1{hit1.getMomentum()[0], hit1.getMomentum()[1],
673 hit1.getMomentum()[2]};
674 Acts::Vector3 phit2{hit2.getMomentum()[0], hit2.getMomentum()[1],
675 hit2.getMomentum()[2]};
677 return phit1.norm() > phit2.norm();
684 std::vector<ldmx::Track> tagger_truth_tracks;
685 std::vector<ldmx::Track> tagger_truth_seeds;
686 std::vector<ldmx::Track> recoil_truth_tracks;
687 std::vector<ldmx::Track> recoil_truth_seeds;
688 std::vector<ldmx::Track> beam_electrons;
692 auto target_surface{Acts::Surface::makeShared<Acts::PerigeeSurface>(
693 Acts::Vector3(0., 0., 0.))};
696 auto target_unbound_surface = tracking::sim::utils::unboundSurface(0.);
699 auto ecal_surface = tracking::sim::utils::unboundSurface(240.5);
701 auto beam_origin_surface{Acts::Surface::makeShared<Acts::PerigeeSurface>(
702 Acts::Vector3(beam_origin_[0], beam_origin_[1], beam_origin_[2]))};
705 for (
const auto& [track_id, hit_indices] : tagger_sh_count_map) {
709 if (hit_count_map_tagger[hit.
getTrackID()].size() > n_min_hits_tagger_) {
711 createTruthTrack(phit, hit, truth_tagger_track, target_surface);
712 truth_tagger_track.setNhits(
713 hit_count_map_tagger[hit.
getTrackID()].size());
721 ts_target.ts_type_ = ldmx::AtTarget;
722 truth_tagger_track.addTrackState(ts_target);
723 tagger_truth_tracks.push_back(truth_tagger_track);
728 hit, hit_count_map_tagger, beam_origin_surface,
729 target_unbound_surface);
730 beam_electrons.push_back(beam_e_truth_seed);
737 std::vector<ldmx::SimTrackerHit> ecal_sp_hits =
741 std::vector<ldmx::SimTrackerHit> sel_ecal_sp_hits;
743 for (
auto sp_hit : ecal_sp_hits) {
744 if (sp_hit.getMomentum()[2] > 0 && ((sp_hit.getID() & 0xfff) == 31)) {
745 sel_ecal_sp_hits.push_back(sp_hit);
751 for (std::pair<
int, std::vector<int>> element : recoil_sh_count_map) {
758 bool found_ecal_hit =
false;
759 for (
auto ecal_sp_hit : sel_ecal_sp_hits) {
760 if (ecal_sp_hit.getTrackID() == hit.
getTrackID()) {
761 ecal_hit = ecal_sp_hit;
762 found_ecal_hit =
true;
770 if (hit_count_map_recoil[hit.
getTrackID()].size() > n_min_hits_recoil_ &&
771 found_ecal_hit && !skip_recoil_) {
773 createTruthTrack(phit, hit, truth_recoil_track, target_surface);
774 truth_recoil_track.setTrackID(hit.
getTrackID());
783 ts_target.ts_type_ = ldmx::AtTarget;
784 truth_recoil_track.addTrackState(ts_target);
793 ep = tracking::sim::utils::ldmx2Acts(ep);
794 em = tracking::sim::utils::ldmx2Acts(em);
798 if (std::abs(em[0]) > 0) {
799 double delta = 240.5 - ep[0];
800 ep[1] += delta * em[1] / em[0];
801 ep[2] += delta * em[2] / em[0];
804 double q_ecal = phit.
getCharge() * Acts::UnitConstants::e;
805 auto ecal_free = tracking::sim::utils::toFreeParameters(ep, em, q_ecal);
806 auto ecal_bound = Acts::transformFreeToBoundParameters(
807 ecal_free, *ecal_surface, gctx_);
808 if (ecal_bound.ok()) {
809 auto part{Acts::GenericParticleHypothesis(Acts::ParticleHypothesis(
810 Acts::PdgParticle(particle_hypothesis_)))};
811 Acts::BoundTrackParameters ecal_pars(
812 ecal_surface, ecal_bound.value(),
813 Acts::BoundSquareMatrix::Identity(), part);
814 truth_recoil_track.addTrackState(tracking::sim::utils::makeTrackState(
815 geometryContext(), ecal_pars, ldmx::AtECAL));
821 for (
auto sim_hit_idx : hit_count_map_recoil.at(hit.
getTrackID())) {
822 truth_recoil_track.addMeasurementIndex(sim_hit_idx);
825 truth_recoil_track.setNhits(nhits);
827 recoil_truth_tracks.push_back(truth_recoil_track);
848 for (
auto& tt : tagger_truth_tracks) {
849 ldmx::Track seed = seedFromTruth(tt, seed_smearing_);
851 tagger_truth_seeds.push_back(seed);
854 ldmx_log(debug) <<
"Forming seeds from truth";
855 for (
auto& tt : recoil_truth_tracks) {
856 ldmx_log(debug) <<
"Smearing truth track";
858 ldmx::Track seed = seedFromTruth(tt, seed_smearing_);
860 recoil_truth_seeds.push_back(seed);
865 event.add(beam_electrons_collection_, beam_electrons);
866 event.add(tagger_truth_collection_, tagger_truth_tracks);
867 event.add(recoil_truth_collection_, recoil_truth_tracks);
868 event.add(tagger_seeds_collection_, tagger_truth_seeds);
869 event.add(recoil_seeds_collection_, recoil_truth_seeds);