1#include "Tracking/Reco/SeedFinderProcessor.h"
3#include "Acts/Definitions/TrackParametrization.hpp"
4#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
6#include "Tracking/Sim/TrackingUtils.h"
42 truth_matching_tool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
52 parameters.
get<std::string>(
"input_hits_collection",
"TaggerSimHits");
56 parameters.
get<std::string>(
"tagger_trks_collection",
"TaggerTracks");
59 parameters.
get<std::vector<double>>(
"perigee_location", {-700, 0., 0.});
60 pmin_ = parameters.
get<
double>(
"pmin", 0.05 * Acts::UnitConstants::GeV);
61 pmax_ = parameters.
get<
double>(
"pmax", 8 * Acts::UnitConstants::GeV);
62 d0max_ = parameters.
get<
double>(
"d0max", -15. * Acts::UnitConstants::mm);
63 d0min_ = parameters.
get<
double>(
"d0min", -45. * Acts::UnitConstants::mm);
64 z0max_ = parameters.
get<
double>(
"z0max", 60. * Acts::UnitConstants::mm);
65 phicut_ = parameters.
get<
double>(
"phicut", 0.1);
68 loc1cut_ = parameters.
get<
double>(
"loc1cut", 0.3);
70 parameters.
get<std::vector<std::string>>(
"strategies", {
"0,1,2,3,4"});
71 inflate_factors_ = parameters.
get<std::vector<double>>(
72 "inflate_factors", {10., 10., 10., 10., 10., 10.});
73 bfield_ = parameters.
get<
double>(
"bfield", 1.5);
74 input_pass_name_ = parameters.
get<std::string>(
"input_pass_name");
75 sim_particles_coll_name_ =
76 parameters.
get<std::string>(
"sim_particles_coll_name");
77 sim_particles_passname_ =
78 parameters.
get<std::string>(
"sim_particles_passname");
79 tagger_trks_event_collection_passname_ =
80 parameters.
get<std::string>(
"tagger_trks_event_collection_passname");
81 sim_particles_event_passname_ =
82 parameters.
get<std::string>(
"sim_particles_event_passname");
90 auto start = std::chrono::high_resolution_clock::now();
91 std::vector<ldmx::Track> seed_tracks;
96 std::map<int, ldmx::SimParticle> particle_map;
98 const std::vector<ldmx::Measurement> measurements =
102 std::vector<ldmx::Track> tagger_tracks;
104 tagger_trks_event_collection_passname_)) {
110 std::shared_ptr<Acts::Surface> tgt_surf =
111 tracking::sim::utils::unboundSurface(0.);
115 ldmx::Measurements target_pseudo_meas;
117 for (
auto tagtrk : tagger_tracks) {
127 const auto& perigee_cov = tagtrk.getPerigeeCov();
128 if (!perigee_cov.empty()) {
129 Acts::BoundSquareMatrix cov =
130 tracking::sim::utils::unpackCov(perigee_cov);
131 double locu = tagtrk.getD0();
132 double locv = tagtrk.getZ0();
134 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
136 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
140 Acts::Vector3 dummy{0., 0., 0.};
141 Acts::Vector2 local_pos{locu, locv};
142 Acts::Vector3 global_pos =
143 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
150 target_pseudo_meas.push_back(pseudo_meas);
154 if (event.
exists(sim_particles_coll_name_, sim_particles_event_passname_)) {
156 sim_particles_coll_name_, sim_particles_passname_);
157 truth_matching_tool_->setup(particle_map, measurements);
160 ldmx_log(debug) <<
"Preparing the strategies";
167 std::vector<int> strategy = {0, 1, 2, 3, 4};
168 bool success = groupStrips(measurements, strategy);
169 if (success) findSeedsFromMap(seed_tracks, target_pseudo_meas);
183 ntracks_ += seed_tracks.size();
186 auto end = std::chrono::high_resolution_clock::now();
191 auto diff = end - start;
192 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
229 const ldmx::Measurements& vmeas,
double xOrigin,
230 const Acts::Vector3& perigee_location,
231 const ldmx::Measurements& pmeas_tgt) {
240 Acts::ActsMatrix<5, 5> a = Acts::ActsMatrix<5, 5>::Zero();
241 Acts::ActsVector<5> y = Acts::ActsVector<5>::Zero();
243 for (
auto meas : vmeas) {
244 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
247 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
250 auto rot = hit_surface->transform(geometryContext()).rotation();
251 auto tr = hit_surface->transform(geometryContext()).translation();
253 auto rotl2g = rot.transpose();
256 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
258 xhit_.push_back(xmeas);
259 yhit_.push_back(meas.getGlobalPosition()[1]);
260 zhit_.push_back(meas.getGlobalPosition()[2]);
262 Acts::ActsMatrix<2, 5> a_i;
264 a_i(0, 0) = rotl2g(0, 1);
265 a_i(0, 1) = rotl2g(0, 1) * xmeas;
266 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
267 a_i(0, 3) = rotl2g(0, 2);
268 a_i(0, 4) = rotl2g(0, 2) * xmeas;
270 a_i(1, 0) = rotl2g(1, 1);
271 a_i(1, 1) = rotl2g(1, 1) * xmeas;
272 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
273 a_i(1, 3) = rotl2g(1, 2);
274 a_i(1, 4) = rotl2g(1, 2) * xmeas;
277 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
278 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
280 loc(0) = meas.getLocalPosition()[0];
283 Acts::ActsMatrix<2, 2> w_i = Acts::ActsMatrix<2, 2>::Zero();
288 Acts::Vector2 yprime_i = loc + offset - xoffset;
289 y += (a_i.transpose()) * w_i * yprime_i;
291 Acts::ActsMatrix<2, 5> wa_i = (w_i * a_i);
292 a += a_i.transpose() * wa_i;
295 Acts::ActsVector<5> b;
305 Acts::ActsVector<3> ref{0., 0., 0.};
307 double relative_perigee_x = perigee_location(0) - xOrigin;
309 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
310 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
311 relative_perigee_x, perigee_location(1), perigee_location(2)));
314 Acts::Vector3 seed_pos{relative_perigee_x,
315 b(0) + b(1) * relative_perigee_x +
316 b(2) * relative_perigee_x * relative_perigee_x,
317 b(3) + b(4) * relative_perigee_x};
318 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
323 double p = 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
327 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
329 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
345 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
347 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
348 intersection.intersections()[0].position(), seed_mom, q);
350 auto bound_params = Acts::transformFreeToBoundParameters(
351 seed_free, *seed_perigee, geometryContext())
354 ldmx_log(trace) <<
"bound parameters at perigee location" << bound_params;
356 Acts::BoundVector stddev;
358 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
359 stddev[Acts::eBoundLoc0] =
360 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
361 stddev[Acts::eBoundLoc1] =
362 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
363 stddev[Acts::eBoundPhi] =
364 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
365 stddev[Acts::eBoundTheta] =
366 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
367 stddev[Acts::eBoundQOverP] =
368 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
369 stddev[Acts::eBoundTime] =
370 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
373 <<
"Making covariance matrix as diagonal matrix with inflated terms";
374 Acts::BoundSquareMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
376 ldmx_log(debug) <<
"...now putting together the seed track ...";
379 Acts::Vector3 perigee_ldmx =
380 tracking::sim::utils::acts2Ldmx(perigee_location);
381 trk.setPerigeeLocation(perigee_ldmx(0), perigee_ldmx(1), perigee_ldmx(2));
385 trk.setNsharedHits(0);
386 trk.setCharge(q < 0 ? -1 : 1);
387 std::vector<double> v_seed_params(
388 (bound_params).data(),
389 bound_params.data() + bound_params.rows() * bound_params.cols());
390 std::vector<double> v_seed_cov;
391 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
392 trk.setPerigeeParameters(v_seed_params);
393 trk.setPerigeeCov(v_seed_cov);
396 <<
"...making the ParticleHypothesis ...assume electron for now";
397 auto part_hypo{Acts::SinglyChargedParticleHypothesis::electron()};
399 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
400 Acts::BoundTrackParameters seed_parameters(
401 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
403 ldmx_log(debug) <<
"Returning seed track";
411 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
412 << processing_time_ / nevents_ <<
" ms";
413 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
414 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
416 ldmx_log(info) <<
"not enough seed points " << nmissing_;
417 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
418 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
419 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
420 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
421 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
422 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
423 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
430bool SeedFinderProcessor::groupStrips(
431 const std::vector<ldmx::Measurement>& measurements,
432 const std::vector<int> strategy) {
439 for (
auto& meas : measurements) {
440 ldmx_log(trace) << meas;
442 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
444 ldmx_log(debug) <<
"Adding measurement from layer_ = " << meas.getLayer();
445 groups_map_[meas.getLayer()].push_back(&meas);
450 if (groups_map_.size() < 5)
460void SeedFinderProcessor::findSeedsFromMap(std::vector<ldmx::Track>& seeds,
461 const ldmx::Measurements& pmeas) {
462 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
465 constexpr size_t k = 5;
466 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
469 unsigned int ikey = 0;
470 for (
auto& key : groups_map_) {
471 it[ikey] = key.second.begin();
478 while (it[0] != groups_iter->second.end()) {
490 std::vector<ldmx::Measurement> meas_for_seeds;
491 meas_for_seeds.reserve(5);
493 ldmx_log(debug) <<
" Grouping ";
495 for (
int j = 0; j < k; j++) {
497 meas_for_seeds.push_back(*meas);
500 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
502 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
505 if (meas_for_seeds.size() < 5) {
510 ldmx_log(debug) <<
"making seedTrack";
516 seedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
522 if (1. / abs(seed_track.getQoP()) <
pmin_) {
525 }
else if (1. / abs(seed_track.getQoP()) >
pmax_) {
533 else if (abs(seed_track.getZ0()) >
z0max_) {
536 }
else if (seed_track.getD0() <
d0min_) {
539 }
else if (seed_track.getD0() >
d0max_) {
542 }
else if (abs(seed_track.getPhi()) >
phicut_) {
545 }
else if (abs(seed_track.getTheta() - piover2_) >
thetacut_) {
556 if (pmeas.size() > 0) {
563 for (
auto tgt_pseudomeas : pmeas) {
567 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
569 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
571 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
580 if (truth_matching_tool_->configured()) {
581 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
582 seed_track.setTrackID(truth_info.track_id_);
583 seed_track.setPdgID(truth_info.pdg_id_);
584 seed_track.setTruthProb(truth_info.truth_prob_);
587 seeds.push_back(seed_track);
599 ldmx_log(debug) <<
"Go to the next combination";
603 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
604 it[i] = std::next(groups_iter, i)->second.begin();
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
std::string getName() const
Get the processor name.
Implements an event buffer system for storing event data.
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.
Class which represents the process under execution.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
void setLocalPosition(const float &meas_u, const float &meas_v)
Set the local position i.e.
void setGlobalPosition(const float &meas_x, const float &meas_y, const float &meas_z)
Set the global position i.e.
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
void setTime(const float &meas_t)
Set the measurement time in ns.
Class representing a simulated particle.
Implementation of a track object.
double thetacut_
ThetaRange.
double loc0cut_
loc0 / loc1 cuts
SeedFinderProcessor(const std::string &name, framework::Process &process)
Constructor.
std::string out_seed_collection_
The name of the output collection of seeds to be stored.
double pmax_
Maximum cut on the momentum of the seeds.
std::vector< std::string > strategies_
List of stragies for seed finding.
std::string input_hits_collection_
The name of the input hits collection to use in finding seeds..
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
void produce(framework::Event &event) override
Run the processor and create a collection of results which indicate if a charge particle can be found...
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
double pmin_
Minimum cut on the momentum of the seeds.
std::string tagger_trks_collection_
The name of the tagger Tracks (only for Recoil Seeding)
std::vector< double > perigee_location_
Location of the perigee for the helix track parameters.
double d0max_
Max d0 allowed for the seeds.
void configure(framework::config::Parameters ¶meters) override
Configure the processor using the given user specified parameters.
double d0min_
Min d0 allowed for the seeds.
double z0max_
Max z0 allowed for the seeds.
a helper base class providing some methods to shorten access to common conditions used within the tra...
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...