1#include "Tracking/Reco/SeedFinderProcessor.h"
6#include "Acts/Definitions/TrackParametrization.hpp"
7#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
9#include "Tracking/Sim/TrackingUtils.h"
45 truth_matching_tool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
55 parameters.
get<std::string>(
"input_hits_collection",
"TaggerSimHits");
59 parameters.
get<std::string>(
"tagger_trks_collection",
"TaggerTracks");
62 parameters.
get<std::vector<double>>(
"perigee_location", {-700, 0., 0.});
63 pmin_ = parameters.
get<
double>(
"pmin", 0.05 * Acts::UnitConstants::GeV);
64 pmax_ = parameters.
get<
double>(
"pmax", 8 * Acts::UnitConstants::GeV);
65 d0max_ = parameters.
get<
double>(
"d0max", -15. * Acts::UnitConstants::mm);
66 d0min_ = parameters.
get<
double>(
"d0min", -45. * Acts::UnitConstants::mm);
67 z0max_ = parameters.
get<
double>(
"z0max", 60. * Acts::UnitConstants::mm);
68 phicut_ = parameters.
get<
double>(
"phicut", 0.1);
71 loc1cut_ = parameters.
get<
double>(
"loc1cut", 0.3);
73 parameters.
get<std::vector<std::string>>(
"strategies", {
"0,1,2,3,4"});
78 std::vector<int> layers;
79 std::stringstream ss(strategy);
81 while (std::getline(ss, token,
',')) {
82 if (!token.empty()) layers.push_back(std::stoi(token));
85 std::set<int> distinct(layers.begin(), layers.end());
86 if (distinct.size() < 5) {
87 EXCEPTION_RAISE(
"BadConf",
"Seeding strategy '" + strategy +
88 "' has fewer than 5 distinct layers");
92 inflate_factors_ = parameters.
get<std::vector<double>>(
93 "inflate_factors", {10., 10., 10., 10., 10., 10.});
94 bfield_ = parameters.
get<
double>(
"bfield", 1.5);
95 input_pass_name_ = parameters.
get<std::string>(
"input_pass_name");
96 sim_particles_coll_name_ =
97 parameters.
get<std::string>(
"sim_particles_coll_name");
98 sim_particles_passname_ =
99 parameters.
get<std::string>(
"sim_particles_passname");
100 tagger_trks_event_collection_passname_ =
101 parameters.
get<std::string>(
"tagger_trks_event_collection_passname");
102 sim_particles_event_passname_ =
103 parameters.
get<std::string>(
"sim_particles_event_passname");
111 auto start = std::chrono::high_resolution_clock::now();
112 std::vector<ldmx::Track> seed_tracks;
117 std::map<int, ldmx::SimParticle> particle_map;
122 std::vector<ldmx::Track> tagger_tracks;
124 tagger_trks_event_collection_passname_)) {
130 std::shared_ptr<Acts::Surface> tgt_surf =
131 tracking::sim::utils::unboundSurface(0.);
135 ldmx::Measurements target_pseudo_meas;
137 for (
auto tagtrk : tagger_tracks) {
147 const auto& perigee_cov = tagtrk.getPerigeeCov();
148 if (!perigee_cov.empty()) {
149 Acts::BoundMatrix cov = tracking::sim::utils::unpackCov(perigee_cov);
150 double locu = tagtrk.getD0();
151 double locv = tagtrk.getZ0();
153 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
155 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
159 Acts::Vector3 dummy{0., 0., 0.};
160 Acts::Vector2 local_pos{locu, locv};
161 Acts::Vector3 global_pos =
162 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
169 target_pseudo_meas.push_back(pseudo_meas);
173 if (event.
exists(sim_particles_coll_name_, sim_particles_event_passname_)) {
175 sim_particles_coll_name_, sim_particles_passname_);
176 truth_matching_tool_->setup(particle_map, measurements);
179 ldmx_log(debug) <<
"Preparing the strategies";
185 if (groupStrips(measurements, strategy))
186 findSeedsFromMap(seed_tracks, target_pseudo_meas);
191 ntracks_ += seed_tracks.size();
194 auto end = std::chrono::high_resolution_clock::now();
199 auto diff = end - start;
200 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
237 const ldmx::Measurements& vmeas,
double xOrigin,
238 const Acts::Vector3& perigee_location,
239 const ldmx::Measurements& pmeas_tgt) {
248 Acts::Matrix<5, 5> a = Acts::Matrix<5, 5>::Zero();
249 Acts::Vector<5> y = Acts::Vector<5>::Zero();
251 for (
auto meas : vmeas) {
252 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
255 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
259 hit_surface->localToGlobalTransform(geometryContext()).rotation();
261 hit_surface->localToGlobalTransform(geometryContext()).translation();
263 auto rotl2g = rot.transpose();
266 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
268 xhit_.push_back(xmeas);
269 yhit_.push_back(meas.getGlobalPosition()[1]);
270 zhit_.push_back(meas.getGlobalPosition()[2]);
272 Acts::Matrix<2, 5> a_i;
274 a_i(0, 0) = rotl2g(0, 1);
275 a_i(0, 1) = rotl2g(0, 1) * xmeas;
276 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
277 a_i(0, 3) = rotl2g(0, 2);
278 a_i(0, 4) = rotl2g(0, 2) * xmeas;
280 a_i(1, 0) = rotl2g(1, 1);
281 a_i(1, 1) = rotl2g(1, 1) * xmeas;
282 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
283 a_i(1, 3) = rotl2g(1, 2);
284 a_i(1, 4) = rotl2g(1, 2) * xmeas;
287 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
288 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
290 loc(0) = meas.getLocalPosition()[0];
293 Acts::Matrix<2, 2> w_i = Acts::Matrix<2, 2>::Zero();
298 Acts::Vector2 yprime_i = loc + offset - xoffset;
299 y += (a_i.transpose()) * w_i * yprime_i;
301 Acts::Matrix<2, 5> wa_i = (w_i * a_i);
302 a += a_i.transpose() * wa_i;
315 Acts::Vector<3> ref{0., 0., 0.};
321 double relative_perigee_x = perigee_location(0) - xOrigin;
323 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
324 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
325 perigee_location(0), perigee_location(1), perigee_location(2)));
329 Acts::Vector3 seed_pos{perigee_location(0),
330 b(0) + b(1) * relative_perigee_x +
331 b(2) * relative_perigee_x * relative_perigee_x,
332 b(3) + b(4) * relative_perigee_x};
333 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
338 double p = 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
342 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
344 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
360 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
362 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
363 intersection[0].position(), seed_mom, q);
365 auto bound_params = Acts::transformFreeToBoundParameters(
366 seed_free, *seed_perigee, geometryContext())
369 ldmx_log(trace) <<
"bound parameters at perigee location" << bound_params;
371 Acts::BoundVector stddev;
373 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
374 stddev[Acts::eBoundLoc0] =
375 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
376 stddev[Acts::eBoundLoc1] =
377 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
378 stddev[Acts::eBoundPhi] =
379 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
380 stddev[Acts::eBoundTheta] =
381 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
382 stddev[Acts::eBoundQOverP] =
383 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
384 stddev[Acts::eBoundTime] =
385 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
388 <<
"Making covariance matrix as diagonal matrix with inflated terms";
389 Acts::BoundMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
391 ldmx_log(debug) <<
"...now putting together the seed track ...";
396 Acts::Vector3 perigee_ldmx =
397 tracking::sim::utils::acts2Ldmx(perigee_location);
398 trk.setPerigeeLocation(perigee_ldmx(0), perigee_ldmx(1), perigee_ldmx(2));
402 trk.setNsharedHits(0);
403 trk.setCharge(q < 0 ? -1 : 1);
404 std::vector<double> v_seed_params(
405 (bound_params).data(),
406 bound_params.data() + bound_params.rows() * bound_params.cols());
407 std::vector<double> v_seed_cov;
408 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
409 trk.setPerigeeParameters(v_seed_params);
410 trk.setPerigeeCov(v_seed_cov);
413 <<
"...making the ParticleHypothesis ...assume electron for now";
414 auto part_hypo{Acts::ParticleHypothesis::electron()};
416 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
417 Acts::BoundTrackParameters seed_parameters(
418 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
420 ldmx_log(debug) <<
"Returning seed track";
428 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
429 << processing_time_ / nevents_ <<
" ms";
430 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
431 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
433 ldmx_log(info) <<
"not enough seed points " << nmissing_;
434 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
435 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
436 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
437 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
438 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
439 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
440 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
447bool SeedFinderProcessor::groupStrips(
448 const std::vector<ldmx::Measurement>& measurements,
449 const std::vector<int> strategy) {
456 for (
auto& meas : measurements) {
457 ldmx_log(trace) << meas;
459 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
461 ldmx_log(debug) <<
"Adding measurement from layer_ = " << meas.getLayer();
462 groups_map_[meas.getLayer()].push_back(&meas);
467 if (groups_map_.size() < strategy.size())
477void SeedFinderProcessor::findSeedsFromMap(std::vector<ldmx::Track>& seeds,
478 const ldmx::Measurements& pmeas) {
479 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
482 const int k = groups_map_.size();
484 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
487 unsigned int ikey = 0;
488 for (
auto& key : groups_map_) {
489 it[ikey] = key.second.begin();
496 while (it[0] != groups_iter->second.end()) {
508 std::vector<ldmx::Measurement> meas_for_seeds;
509 meas_for_seeds.reserve(k);
511 ldmx_log(debug) <<
" Grouping ";
513 for (
int j = 0; j < k; j++) {
515 meas_for_seeds.push_back(*meas);
518 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
520 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
523 if (meas_for_seeds.size() < k) {
528 ldmx_log(debug) <<
"making seedTrack";
534 meas_for_seeds, meas_for_seeds.at(k / 2).getGlobalPosition()[0],
540 if (1. / abs(seed_track.getQoP()) <
pmin_) {
543 }
else if (1. / abs(seed_track.getQoP()) >
pmax_) {
551 else if (abs(seed_track.getZ0()) >
z0max_) {
554 }
else if (seed_track.getD0() <
d0min_) {
557 }
else if (seed_track.getD0() >
d0max_) {
560 }
else if (abs(seed_track.getPhi()) >
phicut_) {
563 }
else if (abs(seed_track.getTheta() - piover2_) >
thetacut_) {
574 if (pmeas.size() > 0) {
581 for (
auto tgt_pseudomeas : pmeas) {
585 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
587 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
589 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
598 if (truth_matching_tool_->configured()) {
599 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
600 seed_track.setTrackID(truth_info.track_id_);
601 seed_track.setPdgID(truth_info.pdg_id_);
602 seed_track.setTruthProb(truth_info.truth_prob_);
605 seeds.push_back(seed_track);
617 ldmx_log(debug) <<
"Go to the next combination";
621 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
622 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.
std::vector< std::vector< int > > strategy_layers_
Layer lists parsed from strategies_, one per strategy.
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...