1#include "Tracking/Reco/SeedFinderProcessor.h"
3#include "Acts/Definitions/TrackParametrization.hpp"
4#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
6#include "Tracking/Sim/TrackingUtils.h"
44 truthMatchingTool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
50 "out_seed_collection",
getName() +
"SeedTracks");
54 "input_hits_collection",
"TaggerSimHits");
58 "tagger_trks_collection",
"TaggerTracks");
61 "perigee_location", {-700, 0., 0.});
63 parameters.
getParameter<
double>(
"pmin", 0.05 * Acts::UnitConstants::GeV);
66 parameters.
getParameter<
double>(
"d0max", -15. * Acts::UnitConstants::mm);
68 parameters.
getParameter<
double>(
"d0min", -45. * Acts::UnitConstants::mm);
70 parameters.
getParameter<
double>(
"z0max", 60. * Acts::UnitConstants::mm);
76 loc1cut_ = parameters.
getParameter<
double>(
"loc1cut", 0.3);
79 "strategies", {
"0,1,2,3,4"});
81 inflate_factors_ = parameters.
getParameter<std::vector<double>>(
82 "inflate_factors", {10., 10., 10., 10., 10., 10.});
84 bfield_ = parameters.
getParameter<
double>(
"bfield", 1.5);
90 auto start = std::chrono::high_resolution_clock::now();
91 ldmx::Tracks seed_tracks;
96 std::map<int, ldmx::SimParticle> particleMap;
98 const std::vector<ldmx::Measurement> measurements =
101 std::vector<ldmx::Track> tagger_tracks;
107 std::shared_ptr<Acts::Surface> tgt_surf =
108 tracking::sim::utils::unboundSurface(0.);
112 ldmx::Measurements target_pseudo_meas;
114 for (
auto tagtrk : tagger_tracks) {
115 auto ts = tagtrk.getTrackState(ldmx::TrackStateType::AtTarget);
121 if (ts.has_value()) {
122 auto trackState = ts.value();
124 Acts::BoundSquareMatrix cov =
125 tracking::sim::utils::unpackCov(trackState.cov);
126 double locu = trackState.params[0];
127 double locv = trackState.params[1];
129 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
131 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
135 Acts::Vector3 dummy{0., 0., 0.};
136 Acts::Vector2 local_pos{locu, locv};
137 Acts::Vector3 global_pos =
138 tgt_surf->localToGlobal(geometry_context(), local_pos, dummy);
145 target_pseudo_meas.push_back(pseudo_meas);
149 if (event.
exists(
"SimParticles")) {
151 truthMatchingTool_->setup(particleMap, measurements);
154 ldmx_log(debug) <<
"Preparing the strategies";
161 std::vector<int> strategy = {0, 1, 2, 3, 4};
162 bool success = GroupStrips(measurements, strategy);
163 if (success) FindSeedsFromMap(seed_tracks, target_pseudo_meas);
177 ntracks_ += seed_tracks.size();
180 auto end = std::chrono::high_resolution_clock::now();
185 auto diff = end - start;
186 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
222 const ldmx::Measurements& vmeas,
double xOrigin,
223 const Acts::Vector3& perigee_location,
224 const ldmx::Measurements& pmeas_tgt) {
233 Acts::ActsMatrix<5, 5> A = Acts::ActsMatrix<5, 5>::Zero();
234 Acts::ActsVector<5> Y = Acts::ActsVector<5>::Zero();
236 for (
auto meas : vmeas) {
237 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
240 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
243 auto rot = hit_surface->transform(geometry_context()).rotation();
244 auto tr = hit_surface->transform(geometry_context()).translation();
246 auto rotl2g = rot.transpose();
249 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
251 xhit_.push_back(xmeas);
252 yhit_.push_back(meas.getGlobalPosition()[1]);
253 zhit_.push_back(meas.getGlobalPosition()[2]);
255 Acts::ActsMatrix<2, 5> A_i;
257 A_i(0, 0) = rotl2g(0, 1);
258 A_i(0, 1) = rotl2g(0, 1) * xmeas;
259 A_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
260 A_i(0, 3) = rotl2g(0, 2);
261 A_i(0, 4) = rotl2g(0, 2) * xmeas;
263 A_i(1, 0) = rotl2g(1, 1);
264 A_i(1, 1) = rotl2g(1, 1) * xmeas;
265 A_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
266 A_i(1, 3) = rotl2g(1, 2);
267 A_i(1, 4) = rotl2g(1, 2) * xmeas;
270 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
271 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
273 loc(0) = meas.getLocalPosition()[0];
275 double uError = sqrt(vmeas[0].getLocalCovariance()[0]);
278 double vError = 40. / sqrt(12);
280 Acts::ActsMatrix<2, 2> W_i =
281 Acts::ActsMatrix<2, 2>::Zero();
283 W_i(0, 0) = 1. / (uError * uError);
284 W_i(1, 1) = 1. / (vError * vError);
286 Acts::Vector2 Yprime_i = loc + offset - xoffset;
287 Y += (A_i.transpose()) * W_i * Yprime_i;
289 Acts::ActsMatrix<2, 5> WA_i = (W_i * A_i);
290 A += A_i.transpose() * WA_i;
293 Acts::ActsVector<5> B;
303 Acts::ActsVector<3> ref{0., 0., 0.};
305 double relativePerigeeX = perigee_location(0) - xOrigin;
307 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
308 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
309 relativePerigeeX, perigee_location(1), perigee_location(2)));
312 Acts::Vector3 seed_pos{relativePerigeeX,
313 B(0) + B(1) * relativePerigeeX +
314 B(2) * relativePerigeeX * relativePerigeeX,
315 B(3) + B(4) * relativePerigeeX};
316 Acts::Vector3 dir{1, B(1) + 2 * B(2) * relativePerigeeX, B(4)};
321 0.3 * bfield_ * (1. / (2. * abs(B(2)))) * 0.001;
325 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
327 B(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
343 (*seed_perigee).intersect(geometry_context(), seed_pos, dir);
345 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
346 intersection.intersections()[0].position(), seed_mom, q);
348 auto bound_params = Acts::transformFreeToBoundParameters(
349 seed_free, *seed_perigee, geometry_context())
352 ldmx_log(debug) <<
"bound parameters at perigee location" << std::endl
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 trk.setPerigeeLocation(perigee_location(0), perigee_location(1),
379 perigee_location(2));
383 trk.setNsharedHits(0);
384 std::vector<double> v_seed_params(
385 (bound_params).data(),
386 bound_params.data() + bound_params.rows() * bound_params.cols());
387 std::vector<double> v_seed_cov;
388 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
390 trk.setPerigeeCov(v_seed_cov);
395 trk.setPosition(seed_free[Acts::eFreePos0], seed_free[Acts::eFreePos1],
396 seed_free[Acts::eFreePos2]);
397 trk.setMomentum(seed_free[Acts::eFreeDir0], seed_free[Acts::eFreeDir1],
398 seed_free[Acts::eFreeDir2]);
401 <<
"...making the ParticleHypothesis ...assume electron for now";
402 auto partHypo{Acts::SinglyChargedParticleHypothesis::electron()};
404 ldmx_log(debug) <<
"Making BoundTrackParameters seedParameters";
405 Acts::BoundTrackParameters seedParameters(
406 seed_perigee, std::move(bound_params), bound_cov, partHypo);
408 ldmx_log(debug) <<
"Returning seed track";
416 ldmx_log(info) <<
"AVG Time/Event: " << std::fixed << std::setprecision(1)
417 << processing_time_ / nevents_ <<
" ms";
418 ldmx_log(info) <<
"Total Seeds/Events: " << ntracks_ <<
"/" << nevents_;
419 ldmx_log(info) <<
"Seeds discarded due to multiple hits on layers "
421 ldmx_log(info) <<
"not enough seed points " << nmissing_;
422 ldmx_log(info) <<
" nfailpmin=" << nfailpmin_;
423 ldmx_log(info) <<
" nfailpmax=" << nfailpmax_;
424 ldmx_log(info) <<
" nfaild0max=" << nfaild0max_;
425 ldmx_log(info) <<
" nfaild0min=" << nfaild0min_;
426 ldmx_log(info) <<
" nfailphicut=" << nfailphi_;
427 ldmx_log(info) <<
" nfailthetacut=" << nfailtheta_;
428 ldmx_log(info) <<
" nfailz0max=" << nfailz0max_;
435bool SeedFinderProcessor::GroupStrips(
436 const std::vector<ldmx::Measurement>& measurements,
437 const std::vector<int> strategy) {
444 for (
auto& meas : measurements) {
445 ldmx_log(debug) << meas;
447 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
449 ldmx_log(debug) <<
"Adding measurement from layer = " << meas.getLayer();
450 groups_map[meas.getLayer()].push_back(&meas);
455 if (groups_map.size() < 5)
465void SeedFinderProcessor::FindSeedsFromMap(ldmx::Tracks& seeds,
466 const ldmx::Measurements& pmeas) {
467 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
470 constexpr size_t K = 5;
471 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
474 unsigned int ikey = 0;
475 for (
auto& key : groups_map) {
476 it[ikey] = key.second.begin();
482 while (it[0] != groups_iter->second.end()) {
494 std::vector<ldmx::Measurement> meas_for_seeds;
495 meas_for_seeds.reserve(5);
497 ldmx_log(debug) <<
" Grouping ";
499 for (
int j = 0; j < K; j++) {
501 meas_for_seeds.push_back(*meas);
504 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
506 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
509 if (meas_for_seeds.size() < 5) {
514 ldmx_log(debug) <<
"making seedTrack";
520 SeedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
526 if (1. / abs(seedTrack.getQoP()) <
pmin_) {
529 }
else if (1. / abs(seedTrack.getQoP()) >
pmax_) {
537 else if (abs(seedTrack.getZ0()) >
z0max_) {
540 }
else if (seedTrack.getD0() <
d0min_) {
543 }
else if (seedTrack.getD0() >
d0max_) {
546 }
else if (abs(seedTrack.getPhi()) >
phicut_) {
549 }
else if (abs(seedTrack.getTheta() - piover2_) >
thetacut_) {
560 if (pmeas.size() > 0) {
567 for (
auto tgt_pseudomeas : pmeas) {
571 seedTrack.getD0() - tgt_pseudomeas.getLocalPosition()[0];
573 seedTrack.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
575 if (abs(delta_loc0) <
loc0cut_ && abs(delta_loc1) < loc1cut_) {
584 if (truthMatchingTool_->configured()) {
585 auto truthInfo = truthMatchingTool_->TruthMatch(meas_for_seeds);
586 seedTrack.setTrackID(truthInfo.trackID);
587 seedTrack.setPdgID(truthInfo.pdgID);
588 seedTrack.setTruthProb(truthInfo.truthProb);
591 seeds.push_back(seedTrack);
603 ldmx_log(debug) <<
"Go to the next combination";
607 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
608 it[i] = std::next(groups_iter, i)->second.begin();
#define DECLARE_PRODUCER_NS(NS, 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.
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
void setTime(const float &t)
Set the measurement time in ns.
void setGlobalPosition(const float &x, const float &y, const float &z)
Set the global position i.e.
void setLocalPosition(const float &u, const float &v)
Set the local position i.e.
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
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.
~SeedFinderProcessor()
Destructor.
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...