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;
101 std::vector<ldmx::Track> tagger_tracks;
103 tagger_trks_event_collection_passname_)) {
109 std::shared_ptr<Acts::Surface> tgt_surf =
110 tracking::sim::utils::unboundSurface(0.);
114 ldmx::Measurements target_pseudo_meas;
116 for (
auto tagtrk : tagger_tracks) {
126 const auto& perigee_cov = tagtrk.getPerigeeCov();
127 if (!perigee_cov.empty()) {
128 Acts::BoundSquareMatrix cov =
129 tracking::sim::utils::unpackCov(perigee_cov);
130 double locu = tagtrk.getD0();
131 double locv = tagtrk.getZ0();
133 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
135 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
139 Acts::Vector3 dummy{0., 0., 0.};
140 Acts::Vector2 local_pos{locu, locv};
141 Acts::Vector3 global_pos =
142 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
149 target_pseudo_meas.push_back(pseudo_meas);
153 if (event.
exists(sim_particles_coll_name_, sim_particles_event_passname_)) {
155 sim_particles_coll_name_, sim_particles_passname_);
156 truth_matching_tool_->setup(particle_map, measurements);
159 ldmx_log(debug) <<
"Preparing the strategies";
166 std::vector<int> strategy = {0, 1, 2, 3, 4};
167 bool success = groupStrips(measurements, strategy);
168 if (success) findSeedsFromMap(seed_tracks, target_pseudo_meas);
182 ntracks_ += seed_tracks.size();
185 auto end = std::chrono::high_resolution_clock::now();
190 auto diff = end - start;
191 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
228 const ldmx::Measurements& vmeas,
double xOrigin,
229 const Acts::Vector3& perigee_location,
230 const ldmx::Measurements& pmeas_tgt) {
239 Acts::ActsMatrix<5, 5> a = Acts::ActsMatrix<5, 5>::Zero();
240 Acts::ActsVector<5> y = Acts::ActsVector<5>::Zero();
242 for (
auto meas : vmeas) {
243 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
246 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
249 auto rot = hit_surface->transform(geometryContext()).rotation();
250 auto tr = hit_surface->transform(geometryContext()).translation();
252 auto rotl2g = rot.transpose();
255 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
257 xhit_.push_back(xmeas);
258 yhit_.push_back(meas.getGlobalPosition()[1]);
259 zhit_.push_back(meas.getGlobalPosition()[2]);
261 Acts::ActsMatrix<2, 5> a_i;
263 a_i(0, 0) = rotl2g(0, 1);
264 a_i(0, 1) = rotl2g(0, 1) * xmeas;
265 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
266 a_i(0, 3) = rotl2g(0, 2);
267 a_i(0, 4) = rotl2g(0, 2) * xmeas;
269 a_i(1, 0) = rotl2g(1, 1);
270 a_i(1, 1) = rotl2g(1, 1) * xmeas;
271 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
272 a_i(1, 3) = rotl2g(1, 2);
273 a_i(1, 4) = rotl2g(1, 2) * xmeas;
276 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
277 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
279 loc(0) = meas.getLocalPosition()[0];
282 Acts::ActsMatrix<2, 2> w_i = Acts::ActsMatrix<2, 2>::Zero();
287 Acts::Vector2 yprime_i = loc + offset - xoffset;
288 y += (a_i.transpose()) * w_i * yprime_i;
290 Acts::ActsMatrix<2, 5> wa_i = (w_i * a_i);
291 a += a_i.transpose() * wa_i;
294 Acts::ActsVector<5> b;
304 Acts::ActsVector<3> ref{0., 0., 0.};
306 double relative_perigee_x = perigee_location(0) - xOrigin;
308 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
309 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
310 relative_perigee_x, perigee_location(1), perigee_location(2)));
313 Acts::Vector3 seed_pos{relative_perigee_x,
314 b(0) + b(1) * relative_perigee_x +
315 b(2) * relative_perigee_x * relative_perigee_x,
316 b(3) + b(4) * relative_perigee_x};
317 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
322 double p = 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
326 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
328 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
344 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
346 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
347 intersection.intersections()[0].position(), seed_mom, q);
349 auto bound_params = Acts::transformFreeToBoundParameters(
350 seed_free, *seed_perigee, geometryContext())
353 ldmx_log(trace) <<
"bound parameters at perigee location" << bound_params;
355 Acts::BoundVector stddev;
357 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
358 stddev[Acts::eBoundLoc0] =
359 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
360 stddev[Acts::eBoundLoc1] =
361 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
362 stddev[Acts::eBoundPhi] =
363 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
364 stddev[Acts::eBoundTheta] =
365 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
366 stddev[Acts::eBoundQOverP] =
367 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
368 stddev[Acts::eBoundTime] =
369 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
372 <<
"Making covariance matrix as diagonal matrix with inflated terms";
373 Acts::BoundSquareMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
375 ldmx_log(debug) <<
"...now putting together the seed track ...";
378 Acts::Vector3 perigee_ldmx =
379 tracking::sim::utils::acts2Ldmx(perigee_location);
380 trk.setPerigeeLocation(perigee_ldmx(0), perigee_ldmx(1), perigee_ldmx(2));
384 trk.setNsharedHits(0);
385 trk.setCharge(q < 0 ? -1 : 1);
386 std::vector<double> v_seed_params(
387 (bound_params).data(),
388 bound_params.data() + bound_params.rows() * bound_params.cols());
389 std::vector<double> v_seed_cov;
390 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
391 trk.setPerigeeParameters(v_seed_params);
392 trk.setPerigeeCov(v_seed_cov);
395 <<
"...making the ParticleHypothesis ...assume electron for now";
396 auto part_hypo{Acts::SinglyChargedParticleHypothesis::electron()};
398 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
399 Acts::BoundTrackParameters seed_parameters(
400 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
402 ldmx_log(debug) <<
"Returning seed track";
410 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
411 << processing_time_ / nevents_ <<
" ms";
412 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
413 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
415 ldmx_log(info) <<
"not enough seed points " << nmissing_;
416 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
417 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
418 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
419 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
420 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
421 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
422 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
429bool SeedFinderProcessor::groupStrips(
430 const std::vector<ldmx::Measurement>& measurements,
431 const std::vector<int> strategy) {
438 for (
auto& meas : measurements) {
439 ldmx_log(trace) << meas;
441 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
443 ldmx_log(debug) <<
"Adding measurement from layer_ = " << meas.getLayer();
444 groups_map_[meas.getLayer()].push_back(&meas);
449 if (groups_map_.size() < 5)
459void SeedFinderProcessor::findSeedsFromMap(std::vector<ldmx::Track>& seeds,
460 const ldmx::Measurements& pmeas) {
461 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
464 constexpr size_t k = 5;
465 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
468 unsigned int ikey = 0;
469 for (
auto& key : groups_map_) {
470 it[ikey] = key.second.begin();
477 while (it[0] != groups_iter->second.end()) {
489 std::vector<ldmx::Measurement> meas_for_seeds;
490 meas_for_seeds.reserve(5);
492 ldmx_log(debug) <<
" Grouping ";
494 for (
int j = 0; j < k; j++) {
496 meas_for_seeds.push_back(*meas);
499 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
501 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
504 if (meas_for_seeds.size() < 5) {
509 ldmx_log(debug) <<
"making seedTrack";
515 seedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
521 if (1. / abs(seed_track.getQoP()) <
pmin_) {
524 }
else if (1. / abs(seed_track.getQoP()) >
pmax_) {
532 else if (abs(seed_track.getZ0()) >
z0max_) {
535 }
else if (seed_track.getD0() <
d0min_) {
538 }
else if (seed_track.getD0() >
d0max_) {
541 }
else if (abs(seed_track.getPhi()) >
phicut_) {
544 }
else if (abs(seed_track.getTheta() - piover2_) >
thetacut_) {
555 if (pmeas.size() > 0) {
562 for (
auto tgt_pseudomeas : pmeas) {
566 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
568 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
570 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
579 if (truth_matching_tool_->configured()) {
580 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
581 seed_track.setTrackID(truth_info.track_id_);
582 seed_track.setPdgID(truth_info.pdg_id_);
583 seed_track.setTruthProb(truth_info.truth_prob_);
586 seeds.push_back(seed_track);
598 ldmx_log(debug) <<
"Go to the next combination";
602 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
603 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...