LDMX Software
tracking::reco::LinearSeedFinder Class Reference

Public Member Functions

 LinearSeedFinder (const std::string &name, framework::Process &process)
 Constructor.
 
virtual ~LinearSeedFinder ()=default
 Destructor.
 
void onProcessStart () override
 Setup the truth matching.
 
void onProcessEnd () override
 Output event statistics.
 
void configure (framework::config::Parameters &parameters) override
 Configure the processor using the given user specified parameters.
 
void produce (framework::Event &event) override
 Run the processor and create a collection of results which indicate if a charge particle can be found by the recoil tracker.
 
- Public Member Functions inherited from tracking::reco::TrackingGeometryUser
 TrackingGeometryUser (const std::string &name, framework::Process &p)
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
virtual void onNewRun (const ldmx::RunHeader &run_header)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Protected Member Functions

ldmx::StraightTrack seedTracker (const std::tuple< std::array< double, 3 >, ldmx::Measurement, std::optional< ldmx::Measurement > > recoil_one, const std::tuple< std::array< double, 3 >, ldmx::Measurement, std::optional< ldmx::Measurement > > recoil_two, const std::array< double, 3 > ecal_one)
 
std::tuple< double, double, double, double, std::vector< double > > fit3DLine (const std::array< double, 3 > &first_recoil, const std::array< double, 3 > &second_recoil, const std::array< double, 3 > &ecal)
 
double calculateDistance (const std::array< double, 3 > &point1, const std::array< double, 3 > &point2)
 
Acts::Vector3 simple3DHitV2 (const ldmx::Measurement &axial, const Acts::Surface &axial_surface, const ldmx::Measurement &stereo, const Acts::Surface &stereo_surface, const ldmx::SimTrackerHit &hitOnTarget, std::vector< ldmx::SimTrackerHit > pair_sim_hits)
 
std::vector< std::tuple< std::array< double, 3 >, std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit >, std::optional< std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit > > > > processMeasurements (const std::vector< std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit > > &measurements, const geo::TrackersTrackingGeometry &tg)
 
double globalChiSquare (const std::array< double, 3 > &first_sensor, const std::array< double, 3 > &second_sensor, const std::array< double, 3 > &ecal_hit, double a_x, double a_y, double b_x, double b_y)
 
int uniqueLayersHit (const std::vector< ldmx::Measurement > &digi_points)
 
std::array< double, 3 > convertToLdmxStdArray (const Acts::Vector3 &vec)
 
std::tuple< Acts::Vector3, Acts::Vector3, Acts::Vector3 > getSurfaceVectors (const Acts::Surface &surface)
 
double dotProduct (const Acts::Vector3 &v1, const Acts::Vector3 &v2)
 
std::array< double, 3 > getPointAtZ (std::array< double, 3 > target, std::array< double, 3 > measurement, double z_target)
 
- Protected Member Functions inherited from tracking::reco::TrackingGeometryUser
const Acts::GeometryContext & geometryContext ()
 
const Acts::MagneticFieldContext & magneticFieldContext ()
 
const Acts::CalibrationContext & calibrationContext ()
 
const geo::TrackersTrackingGeometry & geometry ()
 
void loadBField (const std::string &path, const BFieldDistortion &distortion={})
 Load the interpolated B-field map from path and cache it.
 
void loadBField (const BFieldDistortion &distortion={})
 Load B-field from the path recorded in the detector GDML.
 
std::shared_ptr< Acts::MagneticFieldProvider > bField () const
 Return the loaded B-field provider.
 
- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 

Protected Attributes

double processing_time_ {0.}
 
long n_events_ {0}
 
unsigned int n_seeds_ {0}
 
std::string out_seed_collection_ {"LinearRecoilSeedTracks"}
 The name of the output collection of seeds to be stored.
 
std::string input_hits_collection_ {"DigiRecoilSimHits"}
 The name of the input hits collection to use in finding seeds..
 
std::string input_rec_hits_collection_ {"EcalRecHits"}
 The name of the tagger Tracks (only for Recoil Seeding)
 
std::string input_pass_name_ {""}
 
double ecal_uncertainty_ {3.87}
 
double ecal_distance_threshold_ {10.0}
 
double layer12_midpoint_ {12.5}
 
double layer23_midpoint_ {20.0}
 
double layer34_midpoint_ {27.5}
 
double ecal_first_layer_z_threshold_ {250.0}
 
std::vector< double > recoil_uncertainty_ {0.006, 0.085}
 
long n_missing_ {0}
 
std::shared_ptr< tracking::sim::TruthMatchingTool > truth_matching_tool_
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManager & ntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Private Attributes

std::string next_event_passname_
 
std::string sim_particles_passname_
 
std::string sim_particles_events_passname_
 

Additional Inherited Members

- Static Protected Member Functions inherited from tracking::reco::TrackingGeometryUser
static BFieldDistortion bFieldDistortion (const framework::config::Parameters &parameters)
 Build a BFieldDistortion from processor configuration.
 

Detailed Description

Definition at line 22 of file LinearSeedFinder.h.

Constructor & Destructor Documentation

◆ LinearSeedFinder()

tracking::reco::LinearSeedFinder::LinearSeedFinder ( const std::string & name,
framework::Process & process )

Constructor.

Parameters
nameThe name of the instance of this object.
processThe process running this producer.

Definition at line 11 of file LinearSeedFinder.cxx.

13 : TrackingGeometryUser(name, process) {}
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ calculateDistance()

double tracking::reco::LinearSeedFinder::calculateDistance ( const std::array< double, 3 > & point1,
const std::array< double, 3 > & point2 )
protected

Definition at line 592 of file LinearSeedFinder.cxx.

593 {
594 return sqrt(pow(point1[1] - point2[1], 2) + pow(point1[2] - point2[2], 2));
595} // calculateDistance in xy

◆ configure()

void tracking::reco::LinearSeedFinder::configure ( framework::config::Parameters & parameters)
overridevirtual

Configure the processor using the given user specified parameters.

Parameters
parametersSet of parameters used to configure this processor.

Reimplemented from framework::EventProcessor.

Definition at line 19 of file LinearSeedFinder.cxx.

19 {
20 // Output seed name
21 out_seed_collection_ = parameters.get<std::string>(
22 "out_seed_collection", getName() + "LinearRecoilSeedTracks");
23
24 // Input strip hits_
26 parameters.get<std::string>("input_hits_collection", "DigiRecoilSimHits");
28 parameters.get<std::string>("input_rec_hits_collection", "EcalRecHits");
29
30 input_pass_name_ = parameters.get<std::string>("input_pass_name", "");
31
32 sim_particles_passname_ =
33 parameters.get<std::string>("sim_particles_passname");
34
35 sim_particles_events_passname_ =
36 parameters.get<std::string>("sim_particles_events_passname");
37
38 // the uncertainty is sigma_x = 6 microns and sigma_y = 20./sqrt(12)
39 recoil_uncertainty_ =
40 parameters.get<std::vector<double>>("recoil_uncertainty", {0.006, 0.085});
41 ecal_uncertainty_ = parameters.get<double>("ecal_uncertainty", {3.87});
42 ecal_distance_threshold_ = parameters.get<double>("ecal_distance_threshold");
43 ecal_first_layer_z_threshold_ =
44 parameters.get<double>("ecal_first_layer_z_threshold");
45
46 layer12_midpoint_ = parameters.get<double>("layer12_midpoint");
47 layer23_midpoint_ = parameters.get<double>("layer23_midpoint");
48 layer34_midpoint_ = parameters.get<double>("layer34_midpoint");
49}
std::string getName() const
Get the processor name.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
std::string out_seed_collection_
The name of the output collection of seeds to be stored.
std::string input_hits_collection_
The name of the input hits collection to use in finding seeds..
std::string input_rec_hits_collection_
The name of the tagger Tracks (only for Recoil Seeding)

References framework::config::Parameters::get(), framework::EventProcessor::getName(), input_hits_collection_, input_rec_hits_collection_, and out_seed_collection_.

◆ convertToLdmxStdArray()

std::array< double, 3 > tracking::reco::LinearSeedFinder::convertToLdmxStdArray ( const Acts::Vector3 & vec)
protected

Definition at line 431 of file LinearSeedFinder.cxx.

432 {
433 return {vec.x(), vec.y(), vec.z()};
434}

◆ dotProduct()

double tracking::reco::LinearSeedFinder::dotProduct ( const Acts::Vector3 & v1,
const Acts::Vector3 & v2 )
protected

Definition at line 539 of file LinearSeedFinder.cxx.

540 {
541 return v1.dot(v2);
542}

◆ fit3DLine()

std::tuple< double, double, double, double, std::vector< double > > tracking::reco::LinearSeedFinder::fit3DLine ( const std::array< double, 3 > & first_recoil,
const std::array< double, 3 > & second_recoil,
const std::array< double, 3 > & ecal )
protected

Definition at line 545 of file LinearSeedFinder.cxx.

547 {
548 double z_pos1 = first_recoil[0], x_pos1 = first_recoil[1],
549 y_pos1 = first_recoil[2];
550 double z_pos2 = second_recoil[0], x_pos2 = second_recoil[1],
551 y_pos2 = second_recoil[2];
552 double z_pos3 = ecal[0], x_pos3 = ecal[1], y_pos3 = ecal[2];
553
554 std::array<double, 6> weights = {
555 1 / pow(recoil_uncertainty_[0], 2), 1 / pow(recoil_uncertainty_[1], 2),
556 1 / pow(recoil_uncertainty_[0], 2), 1 / pow(recoil_uncertainty_[1], 2),
557 1 / pow(ecal_uncertainty_, 2), 1 / pow(ecal_uncertainty_, 2)};
558
559 Eigen::Matrix<double, 6, 4> a_mat;
560 Eigen::Matrix<double, 6, 1> d_vec, w_vec;
561
562 // Fill the A matrix (z, 1, 0, 0) for x and (0, 0, z, 1) for y
563 a_mat << z_pos1, 1, 0, 0, 0, 0, z_pos1, 1, z_pos2, 1, 0, 0, 0, 0, z_pos2, 1,
564 z_pos3, 1, 0, 0, 0, 0, z_pos3, 1;
565
566 // Fill the d vector with x and y values
567 d_vec << x_pos1, y_pos1, x_pos2, y_pos2, x_pos3, y_pos3;
568
569 // Fill the weights vector
570 w_vec = Eigen::Matrix<double, 6, 1>(weights.data());
571
572 // Solve the weighted least squares system
573 Eigen::MatrixXd at_w_a = a_mat.transpose() * w_vec.asDiagonal() * a_mat;
574 Eigen::MatrixXd at_w_d = a_mat.transpose() * w_vec.asDiagonal() * d_vec;
575 Eigen::VectorXd param_vec = at_w_a.ldlt().solve(at_w_d);
576
577 Eigen::Matrix4d covariance_matrix = at_w_a.inverse();
578
579 // Store only the upper triangular part of the covariance matrix since it is
580 // symmetric
581 std::vector<double> covariance_vector = {
582 covariance_matrix(0, 0), covariance_matrix(0, 1), covariance_matrix(0, 2),
583 covariance_matrix(0, 3), covariance_matrix(1, 1), covariance_matrix(1, 2),
584 covariance_matrix(1, 3), covariance_matrix(2, 2), covariance_matrix(2, 3),
585 covariance_matrix(3, 3)};
586
587 // return {slope_x, intercept_x, slope_y, intercept_y, covariance}
588 return {param_vec(0), param_vec(1), param_vec(2), param_vec(3),
589 covariance_vector};
590} // fit3DLine

◆ getPointAtZ()

std::array< double, 3 > tracking::reco::LinearSeedFinder::getPointAtZ ( std::array< double, 3 > target,
std::array< double, 3 > measurement,
double z_target )
protected

Definition at line 327 of file LinearSeedFinder.cxx.

329 {
330 double slope_x = (measurement[1] - target[0]) / (measurement[0] - target[2]);
331 double slope_y = (measurement[2] - target[1]) / (measurement[0] - target[2]);
332
333 double intercept_x = target[0] - slope_x * target[2];
334 double intercept_y = target[1] - slope_y * target[2];
335
336 double x_target = slope_x * z_target + intercept_x;
337 double y_target = slope_y * z_target + intercept_y;
338
339 return {z_target, x_target, y_target};
340}

◆ getSurfaceVectors()

std::tuple< Acts::Vector3, Acts::Vector3, Acts::Vector3 > tracking::reco::LinearSeedFinder::getSurfaceVectors ( const Acts::Surface & surface)
protected

Definition at line 439 of file LinearSeedFinder.cxx.

439 {
440 Acts::Vector3 dummy{0., 0., 0.};
441 Acts::Vector3 u =
442 surface.localToGlobal(geometryContext(), Acts::Vector2(1, 0), dummy) -
443 surface.center(geometryContext());
444 Acts::Vector3 v =
445 surface.localToGlobal(geometryContext(), Acts::Vector2(0, 1), dummy) -
446 surface.center(geometryContext());
447 Acts::Vector3 w = u.cross(v).normalized();
448 return {u.normalized(), v.normalized(), w};
449}

◆ globalChiSquare()

double tracking::reco::LinearSeedFinder::globalChiSquare ( const std::array< double, 3 > & first_sensor,
const std::array< double, 3 > & second_sensor,
const std::array< double, 3 > & ecal_hit,
double a_x,
double a_y,
double b_x,
double b_y )
protected

Definition at line 597 of file LinearSeedFinder.cxx.

601 {
602 double chi2_x = 0, chi2_y = 0;
603 chi2_x += pow(
604 (m_x * first_sensor[0] + b_x - first_sensor[1]) / recoil_uncertainty_[0],
605 2);
606 chi2_y += pow(
607 (m_y * first_sensor[0] + b_y - first_sensor[2]) / recoil_uncertainty_[1],
608 2);
609
610 chi2_x += pow((m_x * second_sensor[0] + b_x - second_sensor[1]) /
611 recoil_uncertainty_[0],
612 2);
613 chi2_y += pow((m_y * second_sensor[0] + b_y - second_sensor[2]) /
614 recoil_uncertainty_[1],
615 2);
616
617 chi2_x += pow((m_x * ecal_hit[0] + b_x - ecal_hit[1]) / ecal_uncertainty_, 2);
618 chi2_y += pow((m_y * ecal_hit[0] + b_y - ecal_hit[2]) / ecal_uncertainty_, 2);
619
620 return chi2_x + chi2_y;
621} // globalChiSquare

◆ onProcessEnd()

void tracking::reco::LinearSeedFinder::onProcessEnd ( )
overridevirtual

Output event statistics.

Reimplemented from framework::EventProcessor.

Definition at line 319 of file LinearSeedFinder.cxx.

319 {
320 ldmx_log(info) << "AVG Time/Event: " << std::fixed << std::setprecision(1)
321 << processing_time_ / n_events_ << " ms";
322 ldmx_log(info) << "Total Seeds/Events: " << n_seeds_ << "/" << n_events_;
323 ldmx_log(info) << "not enough seed points " << n_missing_;
324
325} // onProcessEnd

◆ onProcessStart()

void tracking::reco::LinearSeedFinder::onProcessStart ( )
overridevirtual

Setup the truth matching.

Reimplemented from framework::EventProcessor.

Definition at line 15 of file LinearSeedFinder.cxx.

15 {
16 truth_matching_tool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
17}

◆ processMeasurements()

std::vector< std::tuple< std::array< double, 3 >, std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit >, std::optional< std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit > > > > tracking::reco::LinearSeedFinder::processMeasurements ( const std::vector< std::tuple< ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit > > & measurements,
const geo::TrackersTrackingGeometry & tg )
protected

Definition at line 347 of file LinearSeedFinder.cxx.

350 {
351 std::vector<
352 std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>>
353 axial_measurements;
354 std::vector<
355 std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>>
356 stereo_measurements;
357 std::vector<std::tuple<
358 std::array<double, 3>,
359 std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>,
360 std::optional<std::tuple<ldmx::Measurement, ldmx::SimTrackerHit,
362 points_with_measurement;
363 Acts::Vector3 dummy{0., 0., 0.};
364
365 // Separate measurements into axial and stereo based on layerID
366 for (const auto& [measurement, sim_hit, scoring_hit] : measurements) {
367 if (measurement.getLayerID() % 2 == 0) {
368 axial_measurements.emplace_back(measurement, sim_hit, scoring_hit);
369 } else {
370 stereo_measurements.emplace_back(measurement, sim_hit, scoring_hit);
371 }
372 }
373
374 // If there are measurements in both axial and stereo layer_:
375 // Iterate over axial and stereo measurements to compute 3D points
376 if (!axial_measurements.empty() && !stereo_measurements.empty()) {
377 for (const auto& axial : axial_measurements) {
378 const auto& [axial_meas, axial_hit, axial_sp] = axial;
379
380 for (const auto& stereo : stereo_measurements) {
381 const auto& [stereo_meas, stereo_hit, stereo_sp] = stereo;
382
383 const Acts::Surface* axial_surface =
384 tg.getSurface(axial_meas.getLayerID());
385 const Acts::Surface* stereo_surface =
386 tg.getSurface(stereo_meas.getLayerID());
387
388 if (!axial_surface || !stereo_surface) continue;
389
390 std::vector<ldmx::SimTrackerHit> sim_hits = {axial_hit, stereo_hit};
391 Acts::Vector3 space_point =
392 simple3DHitV2(axial_meas, *axial_surface, stereo_meas,
393 *stereo_surface, axial_sp, sim_hits);
394
395 points_with_measurement.push_back(
396 {convertToLdmxStdArray(space_point), axial, stereo});
397 }
398 }
399 } else if (!axial_measurements.empty()) {
400 // if there are only axial measurements, take them to be our sensor points
401 for (const auto& axial : axial_measurements) {
402 const auto& [axial_meas, axial_hit, axial_sp] = axial;
403 const Acts::Surface* axial_surface =
404 tg.getSurface(axial_meas.getLayerID());
405
406 Acts::Vector3 axial_meas_hit = axial_surface->localToGlobal(
407 geometryContext(),
408 Acts::Vector2(axial_meas.getLocalPosition()[0], 0.0), dummy);
409
410 points_with_measurement.push_back(
411 {convertToLdmxStdArray(axial_meas_hit), axial, std::nullopt});
412 }
413 } else if (!stereo_measurements.empty()) {
414 for (const auto& stereo : stereo_measurements) {
415 const auto& [stereo_meas, stereo_hit, stereo_sp] = stereo;
416 const Acts::Surface* stereo_surface =
417 tg.getSurface(stereo_meas.getLayerID());
418
419 Acts::Vector3 stereo_meas_hit = stereo_surface->localToGlobal(
420 geometryContext(),
421 Acts::Vector2(stereo_meas.getLocalPosition()[0], 0.0), dummy);
422
423 points_with_measurement.push_back(
424 {convertToLdmxStdArray(stereo_meas_hit), stereo, std::nullopt});
425 }
426 }
427 return points_with_measurement;
428}
Represents a simulated tracker hit in the simulation.

◆ produce()

void tracking::reco::LinearSeedFinder::produce ( framework::Event & event)
overridevirtual

Run the processor and create a collection of results which indicate if a charge particle can be found by the recoil tracker.

Parameters
eventThe event to process.

Implements framework::Producer.

Definition at line 51 of file LinearSeedFinder.cxx.

51 {
52 auto start = std::chrono::high_resolution_clock::now();
53 std::vector<ldmx::StraightTrack> straight_seed_tracks;
54 n_events_++;
55 auto tg{geometry()};
56
57 const auto& recoil_hits = event.getCollection<ldmx::Measurement>(
58 input_hits_collection_, input_pass_name_);
59 const auto& ecal_rec_hit = event.getCollection<ldmx::EcalHit>(
60 input_rec_hits_collection_, input_pass_name_);
61
62 std::vector<std::array<double, 3>> first_layer_ecal_rec_hits;
63
64 // Find RecHits at first layer_ of ECal
65 for (const auto& x_ecal : ecal_rec_hit) {
66 if (x_ecal.getZPos() < ecal_first_layer_z_threshold_) {
67 first_layer_ecal_rec_hits.push_back(
68 {x_ecal.getZPos(), x_ecal.getXPos(), x_ecal.getYPos()});
69 } // if first layer_ of Ecal
70 } // for positions in ecalRecHit
71
72 // Check if we would fit empty seeds, if so: end tracking
73 if ((recoil_hits.size() < 2) || (first_layer_ecal_rec_hits.empty()) ||
74 (uniqueLayersHit(recoil_hits) < 2)) {
75 n_missing_++;
76 n_seeds_ += straight_seed_tracks.size();
77 event.add(out_seed_collection_, straight_seed_tracks);
78 return;
79 }
80
81 // Setup truth map
82 std::map<int, ldmx::SimParticle> particle_map;
83 if (event.exists("SimParticles", sim_particles_events_passname_)) {
84 particle_map = event.getMap<int, ldmx::SimParticle>(
85 "SimParticles", sim_particles_passname_);
86 truth_matching_tool_->setup(particle_map, recoil_hits);
87 }
88
89 std::vector<
90 std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>>
91 first_two_layers;
92 std::vector<
93 std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>>
94 second_two_layers;
95
96 const auto& recoil_sim_hits = event.getCollection<ldmx::SimTrackerHit>(
97 "RecoilSimHits", input_pass_name_);
98 const auto& scoring_hits = event.getCollection<ldmx::SimTrackerHit>(
99 "TargetScoringPlaneHits", input_pass_name_);
100
101 // Index all sim hits_ by track ID
102 std::unordered_map<int, std::vector<const ldmx::SimTrackerHit*>>
103 sim_hits_by_track_id;
104 for (const auto& hit : recoil_sim_hits) {
105 sim_hits_by_track_id[hit.getTrackID()].push_back(&hit);
106 } // for sim hits_
107
108 // Index scoring hits_ by track ID (one positive scoring plane hit / ID)
109 std::unordered_map<int, const ldmx::SimTrackerHit*> scoring_hit_map;
110 for (const auto& sp_hit : scoring_hits) {
111 if (sp_hit.getPosition()[2] > 0)
112 scoring_hit_map[sp_hit.getTrackID()] = &sp_hit;
113 } // for sp hits_
114
115 for (const auto& point : recoil_hits) {
116 // x is in tracking coordinates, z is in ldmx coordinates
117 float x = point.getGlobalPosition()[0];
118 // need to do a size check here since getTrackIds is a std::vector
119 // which could be empty
120 auto track_ids = point.getTrackIds();
121 int track_id = (track_ids.size() > 0) ? track_ids.at(0) : -1;
122
123 // get the key value = track_id
124 auto sim_range_it = sim_hits_by_track_id.find(track_id);
125 if (sim_range_it == sim_hits_by_track_id.end()) continue;
126
127 // access map value at track_id
128 const auto& sim_hits = sim_range_it->second;
129
130 for (const auto* sim_hit : sim_hits) {
131 float z = sim_hit->getPosition()[2];
132
133 if (x < layer12_midpoint_) {
134 if (z < layer12_midpoint_) {
135 auto sp_it = scoring_hit_map.find(track_id);
136 if (sp_it != scoring_hit_map.end()) {
137 first_two_layers.emplace_back(point, *sim_hit, *sp_it->second);
138 break;
139 } // add the associated scoring plane hit (will be needed for 3D
140 // reconstruction)
141 } // associate 1st layer_ sim hit
142 } // check if recoil hit is 1st layer_
143 else if (x < layer23_midpoint_) {
144 if (z > layer12_midpoint_ && z < layer23_midpoint_) {
145 first_two_layers.emplace_back(point, *sim_hit, ldmx::SimTrackerHit());
146 break;
147 } // associate 2nd layer_ sim hit
148 } // check if recoil hit is 2nd layer_
149 else if (x < layer34_midpoint_) {
150 if (z > layer23_midpoint_ && z < layer34_midpoint_) {
151 auto sp_it = scoring_hit_map.find(track_id);
152 if (sp_it != scoring_hit_map.end()) {
153 second_two_layers.emplace_back(point, *sim_hit, *sp_it->second);
154 break;
155 } // add the associated scoring plane hit (will be needed for 3D
156 // reconstruction)
157 } // associate 3rd layer_ sim hits_
158 } // check if recoil hit is 3rd layer_
159 else {
160 if (z > layer34_midpoint_) {
161 second_two_layers.emplace_back(point, *sim_hit,
163 break;
164 } // associate 4th layer_ sim hits_
165 } // check if recoil hits_ is 4th layer_
166
167 } // loop through simhits
168 } // loop through recoil hits_
169
170 // Reconstruct 3D sensor points on which to do fitting
171 auto first_sensor_combos = processMeasurements(first_two_layers, tg);
172 auto second_sensor_combos = processMeasurements(second_two_layers, tg);
173
174 for (const auto& [first_combo_3d_point, first_layer_one, first_layer_two] :
175 first_sensor_combos) {
176 std::tuple<std::array<double, 3>, ldmx::Measurement,
177 std::optional<ldmx::Measurement>>
178 first_sensor_point;
179
180 if (first_layer_two.has_value()) {
181 first_sensor_point = {first_combo_3d_point,
182 std::get<ldmx::Measurement>(first_layer_one),
183 std::get<ldmx::Measurement>(*first_layer_two)};
184 } // check whether we did reconstruction or...
185 else {
186 first_sensor_point = {first_combo_3d_point,
187 std::get<ldmx::Measurement>(first_layer_one),
188 std::nullopt};
189 } //...we are taking only one layer_ as the measurement (axial or stereo)
190
191 for (const auto& [second_combo_3d_point, second_layer_one,
192 second_layer_two] : second_sensor_combos) {
193 std::tuple<std::array<double, 3>, ldmx::Measurement,
194 std::optional<ldmx::Measurement>>
195 second_sensor_point;
196 if (second_layer_two.has_value()) {
197 second_sensor_point = {second_combo_3d_point,
198 std::get<ldmx::Measurement>(second_layer_one),
199 std::get<ldmx::Measurement>(*second_layer_two)};
200 } // check whether we did reconstruction or...
201 else {
202 second_sensor_point = {second_combo_3d_point,
203 std::get<ldmx::Measurement>(second_layer_one),
204 std::nullopt};
205 } //...we are taking only one layer_ as the measurement (axial or stereo)
206
207 for (const auto& rec_hit : first_layer_ecal_rec_hits) {
208 // Do fitting on 2 sensor + 1 recHit combinations = 1 degree of freedom
209 // for linear fit
210 ldmx::StraightTrack seed_track =
211 seedTracker(first_sensor_point, second_sensor_point, rec_hit);
212
213 // Seed passed RecHit distance check, add it
214 if (seed_track.getChi2() > 0.0) {
215 straight_seed_tracks.push_back(seed_track);
216 } // if chi2 > 0
217 } // for rec_hits
218 } // for second recoil tracker
219 } // for first recoil tracker
220
221 n_seeds_ += straight_seed_tracks.size();
222 event.add(out_seed_collection_, straight_seed_tracks);
223
224 auto end = std::chrono::high_resolution_clock::now();
225
226 auto diff = end - start;
227 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
228
229 first_layer_ecal_rec_hits.clear();
230 straight_seed_tracks.clear();
231
232} // produce
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.
Definition Event.cxx:107
Stores reconstructed hit information from the ECAL.
Definition EcalHit.h:19
Class representing a simulated particle.
Definition SimParticle.h:25

References framework::Event::exists(), input_hits_collection_, input_rec_hits_collection_, and out_seed_collection_.

◆ seedTracker()

ldmx::StraightTrack tracking::reco::LinearSeedFinder::seedTracker ( const std::tuple< std::array< double, 3 >, ldmx::Measurement, std::optional< ldmx::Measurement > > recoil_one,
const std::tuple< std::array< double, 3 >, ldmx::Measurement, std::optional< ldmx::Measurement > > recoil_two,
const std::array< double, 3 > ecal_one )
protected

Definition at line 234 of file LinearSeedFinder.cxx.

241 {
242 auto [sensor1, layer1, layer2] = recoil_one;
243 auto [sensor2, layer3, layer4] = recoil_two;
244 std::vector<ldmx::Measurement> all_points;
245
246 // TODO: in the case where we don't have all 4 hits_, we will be fitting a
247 // sensor (weighted average of two layers) + single layer_
248 // TODO: or fitting two single layers. Currently, the single layer_ point has
249 // the uncertainty of a sensor assigned to it,
250 // TODO: but this is not a realistic uncertainty for a single layer_...
251 // IF all layers are well-defined, this sequence will add layer1, 2, 3, 4 to
252 // the allPoints vector
253 all_points.push_back(layer1);
254
255 // if layer2 doesn't exist (has_value == False), then the layer1 we added
256 // is either layer1 or 2, depending on which one has_value
257 if (layer2.has_value()) {
258 all_points.push_back(*layer2);
259 }
260
261 all_points.push_back(layer3);
262
263 // if layer4 doesn't exist (has_value == False), then the layer3 we added
264 // is either layer3 or 4, depending on which one has_value
265 if (layer4.has_value()) {
266 all_points.push_back(*layer4);
267 }
268
269 // Fit the 3 points to a 3D straight line, find track location at first layer_
270 // of Ecal, check distance to recHit used in fitting
271 // m = slope ; b = intercept
272 auto [m_x, b_x, m_y, b_y, seed_cov] = fit3DLine(sensor1, sensor2, ecal_one);
273 std::array<double, 3> temp_extrapolated_point = {
274 ecal_one[0], m_x * ecal_one[0] + b_x, m_y * ecal_one[0] + b_y};
275 double temp_distance = calculateDistance(temp_extrapolated_point, ecal_one);
276
278
279 if (temp_distance < ecal_distance_threshold_) {
280 trk.setSlopeX(m_x);
281 trk.setInterceptX(b_x);
282 trk.setSlopeY(m_y);
283 trk.setInterceptY(b_y);
284 trk.setTheta(std::atan2(m_y, std::sqrt(1 + m_x * m_x)));
285 trk.setPhi(std::atan2(m_x, 1.0));
286
287 trk.setAllSensorPoints(all_points);
288 trk.setFirstSensorPosition(sensor1);
289 trk.setSecondSensorPosition(sensor2);
290 trk.setFirstLayerEcalRecHit(ecal_one);
291 trk.setDistancetoRecHit(temp_distance);
292
293 trk.setTargetLocation(0.0, b_x, b_y);
294 trk.setEcalLayer1Location(temp_extrapolated_point);
295 trk.setChi2(
296 globalChiSquare(sensor1, sensor2, ecal_one, m_x, m_y, b_x, b_y));
297 trk.setNhits(3);
298 trk.setNdf(1);
299
300 trk.setCov(seed_cov);
301
302 // truth matching
303 if (truth_matching_tool_->configured()) {
304 auto truth_info = truth_matching_tool_->truthMatch(all_points);
305 trk.setTrackID(truth_info.track_id_);
306 trk.setPdgID(truth_info.pdg_id_);
307 trk.setTruthProb(truth_info.truth_prob_);
308 }
309
310 return trk;
311
312 } // if (track is close enough to EcalRecHit)
313 else {
314 trk.setChi2(-1);
315 return trk;
316 } // else (does not pass the threshold)
317} // SeedTracker

◆ simple3DHitV2()

Acts::Vector3 tracking::reco::LinearSeedFinder::simple3DHitV2 ( const ldmx::Measurement & axial,
const Acts::Surface & axial_surface,
const ldmx::Measurement & stereo,
const Acts::Surface & stereo_surface,
const ldmx::SimTrackerHit & hitOnTarget,
std::vector< ldmx::SimTrackerHit > pair_sim_hits )
protected

Definition at line 460 of file LinearSeedFinder.cxx.

464 {
465 Acts::Vector3 dummy{0., 0., 0.};
466 Acts::Vector3 hit_on_target{target_sp.getPosition()[0],
467 target_sp.getPosition()[1],
468 target_sp.getPosition()[2]}; // x,y,z
469
470 Acts::Vector3 axial_true_global{pair_sim_hits[0].getPosition()[0],
471 pair_sim_hits[0].getPosition()[1],
472 pair_sim_hits[0].getPosition()[2]};
473 // stereo_true_global is unused
474 Acts::Vector3 stereo_true_global{pair_sim_hits[1].getPosition()[0],
475 pair_sim_hits[1].getPosition()[1],
476 pair_sim_hits[1].getPosition()[2]};
477
478 Acts::Vector3 simpart_path = axial_true_global - hit_on_target;
479 Acts::Vector3 simpart_unit = simpart_path.normalized();
480
481 // Get global positions for strip origins .... actually these are in
482 // tracking coordinates!
483 Acts::Vector3 axial_origin = axial_surface.center(geometryContext());
484 Acts::Vector3 stereo_origin = stereo_surface.center(geometryContext());
485
486 // the tracking-global vector difference between stereo and axial sensor
487 // centers
488 Acts::Vector3 delta_sensors = stereo_origin - axial_origin;
489
490 // calculate the displacement in tracking global x (need to generalize) by
491 // going from tracking x=axial to x=stereo
492 double dx_proj = (simpart_unit[0] / simpart_unit[2]) *
493 delta_sensors[0]; // this looks weird because simpart_unit
494 // is in global-global and delta sensors
495 // is in tracking-global
496
497 // Compute unit vectors for both hits_
498 auto [axial_u, axial_v, axial_w] = getSurfaceVectors(axial_surface);
499 auto [stereo_u, stereo_v, stereo_w] = getSurfaceVectors(stereo_surface);
500 double salpha = dotProduct(axial_v, stereo_u);
501 double cosalpha = dotProduct(axial_u, stereo_u);
502
503 // Get sensor local measured coordinates
504 // Get local position components
505 auto [axial_u_value, axial_v_value] = axial.getLocalPosition();
506 auto [stereo_u_value, stereo_v_value] = stereo.getLocalPosition();
507
508 // Manual correction, since v should always be 0 (insensitive direction)
509 axial_v_value = 0.0;
510 stereo_v_value = 0.0;
511
512 // use the dx_proj as the displacement in u of the axial measurement
513 // it's axial_u_value - dx_proj because u is in the -x direction
514 // this calculation is in the axial frame
515 double v_intercept_useproj =
516 (stereo_u_value - (axial_u_value - dx_proj) * cosalpha) / salpha;
517 double u_intercept_useproj = axial_u_value - dx_proj;
518
519 // convert to tracking global
520 Acts::Vector3 axst_global_useproj = axial_surface.localToGlobal(
521 geometryContext(),
522 Acts::Vector2(u_intercept_useproj, v_intercept_useproj), dummy);
523 Acts::Vector3 dummy_stereo_proj = stereo_surface.localToGlobal(
524 geometryContext(),
525 Acts::Vector2(u_intercept_useproj, v_intercept_useproj), dummy);
526
527 // we want the reconstructed hit to be at the z of the stereo layer
528 Acts::Vector3 reconstructed_hit{dummy_stereo_proj[0], axst_global_useproj[1],
529 axst_global_useproj[2]};
530
531 ldmx_log(debug) << "The particle projected axst measured position is "
532 "(compare with stereo sim position): "
533 << reconstructed_hit[0] << ", " << reconstructed_hit[1]
534 << ", " << reconstructed_hit[2] << "\n";
535
536 return reconstructed_hit;
537}
std::array< float, 2 > getLocalPosition() const
Definition Measurement.h:67

◆ uniqueLayersHit()

int tracking::reco::LinearSeedFinder::uniqueLayersHit ( const std::vector< ldmx::Measurement > & digi_points)
protected

Definition at line 623 of file LinearSeedFinder.cxx.

624 {
625 std::vector<ldmx::Measurement> sorted_points = digi_points;
626
627 // Sort by z position in the Recoil
628 std::sort(sorted_points.begin(), sorted_points.end(),
629 [](const ldmx::Measurement& meas1, const ldmx::Measurement& meas2) {
630 return meas1.getGlobalPosition()[0] <
631 meas2.getGlobalPosition()[0];
632 });
633
634 // Remove duplicates to ensure we only keep unique z positions
635 auto last = std::unique(
636 sorted_points.begin(), sorted_points.end(),
637 [](const ldmx::Measurement& meas1, const ldmx::Measurement& meas2) {
638 return meas1.getGlobalPosition()[0] == meas2.getGlobalPosition()[0];
639 });
640
641 // return the number of unique layer_ hits_
642 return std::distance(sorted_points.begin(), last);
643} // uniqueLayersHit

Member Data Documentation

◆ ecal_distance_threshold_

double tracking::reco::LinearSeedFinder::ecal_distance_threshold_ {10.0}
protected

Definition at line 132 of file LinearSeedFinder.h.

132{10.0};

◆ ecal_first_layer_z_threshold_

double tracking::reco::LinearSeedFinder::ecal_first_layer_z_threshold_ {250.0}
protected

Definition at line 138 of file LinearSeedFinder.h.

138{250.0};

◆ ecal_uncertainty_

double tracking::reco::LinearSeedFinder::ecal_uncertainty_ {3.87}
protected

Definition at line 130 of file LinearSeedFinder.h.

130{3.87};

◆ input_hits_collection_

std::string tracking::reco::LinearSeedFinder::input_hits_collection_ {"DigiRecoilSimHits"}
protected

The name of the input hits collection to use in finding seeds..

Definition at line 125 of file LinearSeedFinder.h.

125{"DigiRecoilSimHits"};

Referenced by configure(), and produce().

◆ input_pass_name_

std::string tracking::reco::LinearSeedFinder::input_pass_name_ {""}
protected

Definition at line 128 of file LinearSeedFinder.h.

128{""};

◆ input_rec_hits_collection_

std::string tracking::reco::LinearSeedFinder::input_rec_hits_collection_ {"EcalRecHits"}
protected

The name of the tagger Tracks (only for Recoil Seeding)

Definition at line 127 of file LinearSeedFinder.h.

127{"EcalRecHits"};

Referenced by configure(), and produce().

◆ layer12_midpoint_

double tracking::reco::LinearSeedFinder::layer12_midpoint_ {12.5}
protected

Definition at line 135 of file LinearSeedFinder.h.

135{12.5};

◆ layer23_midpoint_

double tracking::reco::LinearSeedFinder::layer23_midpoint_ {20.0}
protected

Definition at line 136 of file LinearSeedFinder.h.

136{20.0};

◆ layer34_midpoint_

double tracking::reco::LinearSeedFinder::layer34_midpoint_ {27.5}
protected

Definition at line 137 of file LinearSeedFinder.h.

137{27.5};

◆ n_events_

long tracking::reco::LinearSeedFinder::n_events_ {0}
protected

Definition at line 119 of file LinearSeedFinder.h.

119{0};

◆ n_missing_

long tracking::reco::LinearSeedFinder::n_missing_ {0}
protected

Definition at line 143 of file LinearSeedFinder.h.

143{0};

◆ n_seeds_

unsigned int tracking::reco::LinearSeedFinder::n_seeds_ {0}
protected

Definition at line 120 of file LinearSeedFinder.h.

120{0};

◆ next_event_passname_

std::string tracking::reco::LinearSeedFinder::next_event_passname_
private

Definition at line 150 of file LinearSeedFinder.h.

◆ out_seed_collection_

std::string tracking::reco::LinearSeedFinder::out_seed_collection_ {"LinearRecoilSeedTracks"}
protected

The name of the output collection of seeds to be stored.

Definition at line 123 of file LinearSeedFinder.h.

123{"LinearRecoilSeedTracks"};

Referenced by configure(), and produce().

◆ processing_time_

double tracking::reco::LinearSeedFinder::processing_time_ {0.}
protected

Definition at line 118 of file LinearSeedFinder.h.

118{0.};

◆ recoil_uncertainty_

std::vector<double> tracking::reco::LinearSeedFinder::recoil_uncertainty_ {0.006, 0.085}
protected

Definition at line 140 of file LinearSeedFinder.h.

140{0.006, 0.085};

◆ sim_particles_events_passname_

std::string tracking::reco::LinearSeedFinder::sim_particles_events_passname_
private

Definition at line 152 of file LinearSeedFinder.h.

◆ sim_particles_passname_

std::string tracking::reco::LinearSeedFinder::sim_particles_passname_
private

Definition at line 151 of file LinearSeedFinder.h.

◆ truth_matching_tool_

std::shared_ptr<tracking::sim::TruthMatchingTool> tracking::reco::LinearSeedFinder::truth_matching_tool_
protected
Initial value:
=
nullptr

Definition at line 146 of file LinearSeedFinder.h.


The documentation for this class was generated from the following files: