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);
66 phicut_ = parameters.
get<
double>(
"phicut", 0.1);
70 loc1cut_ = parameters.
get<
double>(
"loc1cut", 0.3);
73 parameters.
get<std::vector<std::string>>(
"strategies", {
"0,1,2,3,4"});
75 inflate_factors_ = parameters.
get<std::vector<double>>(
76 "inflate_factors", {10., 10., 10., 10., 10., 10.});
78 bfield_ = parameters.
get<
double>(
"bfield", 1.5);
80 input_pass_name_ = parameters.
get<std::string>(
"input_pass_name");
82 sim_particles_passname_ =
83 parameters.
get<std::string>(
"sim_particles_passname");
84 tagger_trks_event_collection_passname_ =
85 parameters.
get<std::string>(
"tagger_trks_event_collection_passname");
86 sim_particles_event_passname_ =
87 parameters.
get<std::string>(
"sim_particles_event_passname");
93 auto start = std::chrono::high_resolution_clock::now();
94 ldmx::Tracks seed_tracks;
99 std::map<int, ldmx::SimParticle> particle_map;
101 const std::vector<ldmx::Measurement> measurements =
105 std::vector<ldmx::Track> tagger_tracks;
107 tagger_trks_event_collection_passname_)) {
113 std::shared_ptr<Acts::Surface> tgt_surf =
114 tracking::sim::utils::unboundSurface(0.);
118 ldmx::Measurements target_pseudo_meas;
120 for (
auto tagtrk : tagger_tracks) {
121 auto ts = tagtrk.getTrackState(ldmx::TrackStateType::AtTarget);
127 if (ts.has_value()) {
128 auto track_state = ts.value();
130 Acts::BoundSquareMatrix cov =
131 tracking::sim::utils::unpackCov(track_state.cov_);
132 double locu = track_state.params_[0];
133 double locv = track_state.params_[1];
135 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
137 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
141 Acts::Vector3 dummy{0., 0., 0.};
142 Acts::Vector2 local_pos{locu, locv};
143 Acts::Vector3 global_pos =
144 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
151 target_pseudo_meas.push_back(pseudo_meas);
155 if (event.
exists(
"SimParticles", sim_particles_event_passname_)) {
157 "SimParticles", sim_particles_passname_);
158 truth_matching_tool_->setup(particle_map, measurements);
161 ldmx_log(debug) <<
"Preparing the strategies";
168 std::vector<int> strategy = {0, 1, 2, 3, 4};
169 bool success = groupStrips(measurements, strategy);
170 if (success) findSeedsFromMap(seed_tracks, target_pseudo_meas);
184 ntracks_ += seed_tracks.size();
187 auto end = std::chrono::high_resolution_clock::now();
192 auto diff = end - start;
193 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
230 const ldmx::Measurements& vmeas,
double xOrigin,
231 const Acts::Vector3& perigee_location,
232 const ldmx::Measurements& pmeas_tgt) {
241 Acts::ActsMatrix<5, 5> a = Acts::ActsMatrix<5, 5>::Zero();
242 Acts::ActsVector<5> y = Acts::ActsVector<5>::Zero();
244 for (
auto meas : vmeas) {
245 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
248 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
251 auto rot = hit_surface->transform(geometryContext()).rotation();
252 auto tr = hit_surface->transform(geometryContext()).translation();
254 auto rotl2g = rot.transpose();
257 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
259 xhit_.push_back(xmeas);
260 yhit_.push_back(meas.getGlobalPosition()[1]);
261 zhit_.push_back(meas.getGlobalPosition()[2]);
263 Acts::ActsMatrix<2, 5> a_i;
265 a_i(0, 0) = rotl2g(0, 1);
266 a_i(0, 1) = rotl2g(0, 1) * xmeas;
267 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
268 a_i(0, 3) = rotl2g(0, 2);
269 a_i(0, 4) = rotl2g(0, 2) * xmeas;
271 a_i(1, 0) = rotl2g(1, 1);
272 a_i(1, 1) = rotl2g(1, 1) * xmeas;
273 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
274 a_i(1, 3) = rotl2g(1, 2);
275 a_i(1, 4) = rotl2g(1, 2) * xmeas;
278 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
279 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
281 loc(0) = meas.getLocalPosition()[0];
283 double u_error = sqrt(vmeas[0].getLocalCovariance()[0]);
286 double v_error = 40. / sqrt(12);
288 Acts::ActsMatrix<2, 2> w_i =
289 Acts::ActsMatrix<2, 2>::Zero();
291 w_i(0, 0) = 1. / (u_error * u_error);
292 w_i(1, 1) = 1. / (v_error * v_error);
294 Acts::Vector2 yprime_i = loc + offset - xoffset;
295 y += (a_i.transpose()) * w_i * yprime_i;
297 Acts::ActsMatrix<2, 5> wa_i = (w_i * a_i);
298 a += a_i.transpose() * wa_i;
301 Acts::ActsVector<5> b;
311 Acts::ActsVector<3> ref{0., 0., 0.};
313 double relative_perigee_x = perigee_location(0) - xOrigin;
315 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
316 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
317 relative_perigee_x, perigee_location(1), perigee_location(2)));
320 Acts::Vector3 seed_pos{relative_perigee_x,
321 b(0) + b(1) * relative_perigee_x +
322 b(2) * relative_perigee_x * relative_perigee_x,
323 b(3) + b(4) * relative_perigee_x};
324 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
329 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
333 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
335 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
351 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
353 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
354 intersection.intersections()[0].position(), seed_mom, q);
356 auto bound_params = Acts::transformFreeToBoundParameters(
357 seed_free, *seed_perigee, geometryContext())
360 ldmx_log(trace) <<
"bound parameters at perigee location" << bound_params;
362 Acts::BoundVector stddev;
364 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
365 stddev[Acts::eBoundLoc0] =
366 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
367 stddev[Acts::eBoundLoc1] =
368 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
369 stddev[Acts::eBoundPhi] =
370 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
371 stddev[Acts::eBoundTheta] =
372 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
373 stddev[Acts::eBoundQOverP] =
374 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
375 stddev[Acts::eBoundTime] =
376 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
379 <<
"Making covariance matrix as diagonal matrix with inflated terms";
380 Acts::BoundSquareMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
382 ldmx_log(debug) <<
"...now putting together the seed track ...";
385 trk.setPerigeeLocation(perigee_location(0), perigee_location(1),
386 perigee_location(2));
390 trk.setNsharedHits(0);
391 std::vector<double> v_seed_params(
392 (bound_params).data(),
393 bound_params.data() + bound_params.rows() * bound_params.cols());
394 std::vector<double> v_seed_cov;
395 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
397 trk.setPerigeeCov(v_seed_cov);
402 trk.setPosition(seed_free[Acts::eFreePos0], seed_free[Acts::eFreePos1],
403 seed_free[Acts::eFreePos2]);
404 trk.setMomentum(seed_free[Acts::eFreeDir0], seed_free[Acts::eFreeDir1],
405 seed_free[Acts::eFreeDir2]);
408 <<
"...making the ParticleHypothesis ...assume electron for now";
409 auto part_hypo{Acts::SinglyChargedParticleHypothesis::electron()};
411 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
412 Acts::BoundTrackParameters seed_parameters(
413 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
415 ldmx_log(debug) <<
"Returning seed track";
423 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
424 << processing_time_ / nevents_ <<
" ms";
425 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
426 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
428 ldmx_log(info) <<
"not enough seed points " << nmissing_;
429 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
430 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
431 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
432 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
433 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
434 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
435 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
442bool SeedFinderProcessor::groupStrips(
443 const std::vector<ldmx::Measurement>& measurements,
444 const std::vector<int> strategy) {
451 for (
auto& meas : measurements) {
452 ldmx_log(trace) << meas;
454 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
456 ldmx_log(debug) <<
"Adding measurement from layer_ = " << meas.getLayer();
457 groups_map_[meas.getLayer()].push_back(&meas);
462 if (groups_map_.size() < 5)
472void SeedFinderProcessor::findSeedsFromMap(ldmx::Tracks& seeds,
473 const ldmx::Measurements& pmeas) {
474 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
477 constexpr size_t k = 5;
478 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
481 unsigned int ikey = 0;
482 for (
auto& key : groups_map_) {
483 it[ikey] = key.second.begin();
489 while (it[0] != groups_iter->second.end()) {
501 std::vector<ldmx::Measurement> meas_for_seeds;
502 meas_for_seeds.reserve(5);
504 ldmx_log(debug) <<
" Grouping ";
506 for (
int j = 0; j < k; j++) {
508 meas_for_seeds.push_back(*meas);
511 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
513 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
516 if (meas_for_seeds.size() < 5) {
521 ldmx_log(debug) <<
"making seedTrack";
527 seedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
533 if (1. / abs(seed_track.getQoP()) <
pmin_) {
536 }
else if (1. / abs(seed_track.getQoP()) >
pmax_) {
544 else if (abs(seed_track.getZ0()) >
z0max_) {
547 }
else if (seed_track.getD0() <
d0min_) {
550 }
else if (seed_track.getD0() >
d0max_) {
553 }
else if (abs(seed_track.getPhi()) >
phicut_) {
556 }
else if (abs(seed_track.getTheta() - piover2_) >
thetacut_) {
567 if (pmeas.size() > 0) {
574 for (
auto tgt_pseudomeas : pmeas) {
578 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
580 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
582 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
591 if (truth_matching_tool_->configured()) {
592 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
593 seed_track.setTrackID(truth_info.track_id_);
594 seed_track.setPdgID(truth_info.pdg_id_);
595 seed_track.setTruthProb(truth_info.truth_prob_);
598 seeds.push_back(seed_track);
610 ldmx_log(debug) <<
"Go to the next combination";
614 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
615 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...