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_passname_ =
76 parameters.
get<std::string>(
"sim_particles_passname");
77 tagger_trks_event_collection_passname_ =
78 parameters.
get<std::string>(
"tagger_trks_event_collection_passname");
79 sim_particles_event_passname_ =
80 parameters.
get<std::string>(
"sim_particles_event_passname");
88 auto start = std::chrono::high_resolution_clock::now();
89 ldmx::Tracks seed_tracks;
94 std::map<int, ldmx::SimParticle> particle_map;
96 const std::vector<ldmx::Measurement> measurements =
100 std::vector<ldmx::Track> tagger_tracks;
102 tagger_trks_event_collection_passname_)) {
108 std::shared_ptr<Acts::Surface> tgt_surf =
109 tracking::sim::utils::unboundSurface(0.);
113 ldmx::Measurements target_pseudo_meas;
115 for (
auto tagtrk : tagger_tracks) {
116 auto ts = tagtrk.getTrackState(ldmx::TrackStateType::AtTarget);
122 if (ts.has_value()) {
123 auto track_state = ts.value();
125 Acts::BoundSquareMatrix cov =
126 tracking::sim::utils::unpackCov(track_state.cov_);
127 double locu = track_state.params_[0];
128 double locv = track_state.params_[1];
130 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
132 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
136 Acts::Vector3 dummy{0., 0., 0.};
137 Acts::Vector2 local_pos{locu, locv};
138 Acts::Vector3 global_pos =
139 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
146 target_pseudo_meas.push_back(pseudo_meas);
150 if (event.
exists(
"SimParticles", sim_particles_event_passname_)) {
152 "SimParticles", sim_particles_passname_);
153 truth_matching_tool_->setup(particle_map, measurements);
156 ldmx_log(debug) <<
"Preparing the strategies";
163 std::vector<int> strategy = {0, 1, 2, 3, 4};
164 bool success = groupStrips(measurements, strategy);
165 if (success) findSeedsFromMap(seed_tracks, target_pseudo_meas);
179 ntracks_ += seed_tracks.size();
182 auto end = std::chrono::high_resolution_clock::now();
187 auto diff = end - start;
188 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
225 const ldmx::Measurements& vmeas,
double xOrigin,
226 const Acts::Vector3& perigee_location,
227 const ldmx::Measurements& pmeas_tgt) {
236 Acts::ActsMatrix<5, 5> a = Acts::ActsMatrix<5, 5>::Zero();
237 Acts::ActsVector<5> y = Acts::ActsVector<5>::Zero();
239 for (
auto meas : vmeas) {
240 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
243 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
246 auto rot = hit_surface->transform(geometryContext()).rotation();
247 auto tr = hit_surface->transform(geometryContext()).translation();
249 auto rotl2g = rot.transpose();
252 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
254 xhit_.push_back(xmeas);
255 yhit_.push_back(meas.getGlobalPosition()[1]);
256 zhit_.push_back(meas.getGlobalPosition()[2]);
258 Acts::ActsMatrix<2, 5> a_i;
260 a_i(0, 0) = rotl2g(0, 1);
261 a_i(0, 1) = rotl2g(0, 1) * xmeas;
262 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
263 a_i(0, 3) = rotl2g(0, 2);
264 a_i(0, 4) = rotl2g(0, 2) * xmeas;
266 a_i(1, 0) = rotl2g(1, 1);
267 a_i(1, 1) = rotl2g(1, 1) * xmeas;
268 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
269 a_i(1, 3) = rotl2g(1, 2);
270 a_i(1, 4) = rotl2g(1, 2) * xmeas;
273 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
274 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
276 loc(0) = meas.getLocalPosition()[0];
279 Acts::ActsMatrix<2, 2> w_i = Acts::ActsMatrix<2, 2>::Zero();
284 Acts::Vector2 yprime_i = loc + offset - xoffset;
285 y += (a_i.transpose()) * w_i * yprime_i;
287 Acts::ActsMatrix<2, 5> wa_i = (w_i * a_i);
288 a += a_i.transpose() * wa_i;
291 Acts::ActsVector<5> b;
301 Acts::ActsVector<3> ref{0., 0., 0.};
303 double relative_perigee_x = perigee_location(0) - xOrigin;
305 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
306 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
307 relative_perigee_x, perigee_location(1), perigee_location(2)));
310 Acts::Vector3 seed_pos{relative_perigee_x,
311 b(0) + b(1) * relative_perigee_x +
312 b(2) * relative_perigee_x * relative_perigee_x,
313 b(3) + b(4) * relative_perigee_x};
314 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
319 double p = 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
323 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
325 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
341 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
343 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
344 intersection.intersections()[0].position(), seed_mom, q);
346 auto bound_params = Acts::transformFreeToBoundParameters(
347 seed_free, *seed_perigee, geometryContext())
350 ldmx_log(trace) <<
"bound parameters at perigee location" << bound_params;
352 Acts::BoundVector stddev;
354 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
355 stddev[Acts::eBoundLoc0] =
356 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
357 stddev[Acts::eBoundLoc1] =
358 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
359 stddev[Acts::eBoundPhi] =
360 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
361 stddev[Acts::eBoundTheta] =
362 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
363 stddev[Acts::eBoundQOverP] =
364 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
365 stddev[Acts::eBoundTime] =
366 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
369 <<
"Making covariance matrix as diagonal matrix with inflated terms";
370 Acts::BoundSquareMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
372 ldmx_log(debug) <<
"...now putting together the seed track ...";
375 trk.setPerigeeLocation(perigee_location(0), perigee_location(1),
376 perigee_location(2));
380 trk.setNsharedHits(0);
381 std::vector<double> v_seed_params(
382 (bound_params).data(),
383 bound_params.data() + bound_params.rows() * bound_params.cols());
384 std::vector<double> v_seed_cov;
385 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
387 trk.setPerigeeCov(v_seed_cov);
392 trk.setPosition(seed_free[Acts::eFreePos0], seed_free[Acts::eFreePos1],
393 seed_free[Acts::eFreePos2]);
394 trk.setMomentum(seed_free[Acts::eFreeDir0], seed_free[Acts::eFreeDir1],
395 seed_free[Acts::eFreeDir2]);
398 <<
"...making the ParticleHypothesis ...assume electron for now";
399 auto part_hypo{Acts::SinglyChargedParticleHypothesis::electron()};
401 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
402 Acts::BoundTrackParameters seed_parameters(
403 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
405 ldmx_log(debug) <<
"Returning seed track";
413 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
414 << processing_time_ / nevents_ <<
" ms";
415 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
416 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
418 ldmx_log(info) <<
"not enough seed points " << nmissing_;
419 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
420 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
421 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
422 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
423 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
424 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
425 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
432bool SeedFinderProcessor::groupStrips(
433 const std::vector<ldmx::Measurement>& measurements,
434 const std::vector<int> strategy) {
441 for (
auto& meas : measurements) {
442 ldmx_log(trace) << meas;
444 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
446 ldmx_log(debug) <<
"Adding measurement from layer_ = " << meas.getLayer();
447 groups_map_[meas.getLayer()].push_back(&meas);
452 if (groups_map_.size() < 5)
462void SeedFinderProcessor::findSeedsFromMap(ldmx::Tracks& seeds,
463 const ldmx::Measurements& pmeas) {
464 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
467 constexpr size_t k = 5;
468 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
471 unsigned int ikey = 0;
472 for (
auto& key : groups_map_) {
473 it[ikey] = key.second.begin();
480 while (it[0] != groups_iter->second.end()) {
492 std::vector<ldmx::Measurement> meas_for_seeds;
493 meas_for_seeds.reserve(5);
495 ldmx_log(debug) <<
" Grouping ";
497 for (
int j = 0; j < k; j++) {
499 meas_for_seeds.push_back(*meas);
502 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
504 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
507 if (meas_for_seeds.size() < 5) {
512 ldmx_log(debug) <<
"making seedTrack";
518 seedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
524 if (1. / abs(seed_track.getQoP()) <
pmin_) {
527 }
else if (1. / abs(seed_track.getQoP()) >
pmax_) {
535 else if (abs(seed_track.getZ0()) >
z0max_) {
538 }
else if (seed_track.getD0() <
d0min_) {
541 }
else if (seed_track.getD0() >
d0max_) {
544 }
else if (abs(seed_track.getPhi()) >
phicut_) {
547 }
else if (abs(seed_track.getTheta() - piover2_) >
thetacut_) {
558 if (pmeas.size() > 0) {
565 for (
auto tgt_pseudomeas : pmeas) {
569 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
571 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
573 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
582 if (truth_matching_tool_->configured()) {
583 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
584 seed_track.setTrackID(truth_info.track_id_);
585 seed_track.setPdgID(truth_info.pdg_id_);
586 seed_track.setTruthProb(truth_info.truth_prob_);
589 seeds.push_back(seed_track);
601 ldmx_log(debug) <<
"Go to the next combination";
605 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
606 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.
void setPerigeeParameters(const std::vector< double > &par)
d_0 z_0 phi_0 theta q/p t
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...