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::TrackersTrackingGeometrygeometry ()
 
void loadBField (const std::string &path, const std::vector< double > &map_offset={0., 0., 0.})
 Load the interpolated B-field map from path and cache it.
 
void loadBField (const std::vector< double > &map_offset={0., 0., 0.})
 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::TruthMatchingTooltruth_matching_tool_
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManagerntuple_ {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_
 

Detailed Description

Definition at line 26 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 8 of file LinearSeedFinder.cxx.

10 : 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 589 of file LinearSeedFinder.cxx.

590 {
591 return sqrt(pow(point1[1] - point2[1], 2) + pow(point1[2] - point2[2], 2));
592} // 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 16 of file LinearSeedFinder.cxx.

16 {
17 // Output seed name
18 out_seed_collection_ = parameters.get<std::string>(
19 "out_seed_collection", getName() + "LinearRecoilSeedTracks");
20
21 // Input strip hits_
23 parameters.get<std::string>("input_hits_collection", "DigiRecoilSimHits");
25 parameters.get<std::string>("input_rec_hits_collection", "EcalRecHits");
26
27 input_pass_name_ = parameters.get<std::string>("input_pass_name", "");
28
29 sim_particles_passname_ =
30 parameters.get<std::string>("sim_particles_passname");
31
32 sim_particles_events_passname_ =
33 parameters.get<std::string>("sim_particles_events_passname");
34
35 // the uncertainty is sigma_x = 6 microns and sigma_y = 20./sqrt(12)
36 recoil_uncertainty_ =
37 parameters.get<std::vector<double>>("recoil_uncertainty", {0.006, 0.085});
38 ecal_uncertainty_ = parameters.get<double>("ecal_uncertainty", {3.87});
39 ecal_distance_threshold_ = parameters.get<double>("ecal_distance_threshold");
40 ecal_first_layer_z_threshold_ =
41 parameters.get<double>("ecal_first_layer_z_threshold");
42
43 layer12_midpoint_ = parameters.get<double>("layer12_midpoint");
44 layer23_midpoint_ = parameters.get<double>("layer23_midpoint");
45 layer34_midpoint_ = parameters.get<double>("layer34_midpoint");
46}
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:78
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 428 of file LinearSeedFinder.cxx.

429 {
430 return {vec.x(), vec.y(), vec.z()};
431}

◆ dotProduct()

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

Definition at line 536 of file LinearSeedFinder.cxx.

537 {
538 return v1.dot(v2);
539}

◆ 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 542 of file LinearSeedFinder.cxx.

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

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

◆ getSurfaceVectors()

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

Definition at line 436 of file LinearSeedFinder.cxx.

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

◆ 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 594 of file LinearSeedFinder.cxx.

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

◆ onProcessEnd()

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

Output event statistics.

Reimplemented from framework::EventProcessor.

Definition at line 316 of file LinearSeedFinder.cxx.

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

◆ onProcessStart()

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

Setup the truth matching.

Reimplemented from framework::EventProcessor.

Definition at line 12 of file LinearSeedFinder.cxx.

12 {
13 truth_matching_tool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
14}

◆ 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 344 of file LinearSeedFinder.cxx.

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

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

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 231 of file LinearSeedFinder.cxx.

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

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

◆ uniqueLayersHit()

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

Definition at line 620 of file LinearSeedFinder.cxx.

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

Member Data Documentation

◆ ecal_distance_threshold_

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

Definition at line 136 of file LinearSeedFinder.h.

136{10.0};

◆ ecal_first_layer_z_threshold_

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

Definition at line 142 of file LinearSeedFinder.h.

142{250.0};

◆ ecal_uncertainty_

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

Definition at line 134 of file LinearSeedFinder.h.

134{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 129 of file LinearSeedFinder.h.

129{"DigiRecoilSimHits"};

Referenced by configure(), and produce().

◆ input_pass_name_

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

Definition at line 132 of file LinearSeedFinder.h.

132{""};

◆ 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 131 of file LinearSeedFinder.h.

131{"EcalRecHits"};

Referenced by configure(), and produce().

◆ layer12_midpoint_

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

Definition at line 139 of file LinearSeedFinder.h.

139{12.5};

◆ layer23_midpoint_

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

Definition at line 140 of file LinearSeedFinder.h.

140{20.0};

◆ layer34_midpoint_

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

Definition at line 141 of file LinearSeedFinder.h.

141{27.5};

◆ n_events_

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

Definition at line 123 of file LinearSeedFinder.h.

123{0};

◆ n_missing_

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

Definition at line 147 of file LinearSeedFinder.h.

147{0};

◆ n_seeds_

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

Definition at line 124 of file LinearSeedFinder.h.

124{0};

◆ next_event_passname_

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

Definition at line 154 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 127 of file LinearSeedFinder.h.

127{"LinearRecoilSeedTracks"};

Referenced by configure(), and produce().

◆ processing_time_

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

Definition at line 122 of file LinearSeedFinder.h.

122{0.};

◆ recoil_uncertainty_

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

Definition at line 144 of file LinearSeedFinder.h.

144{0.006, 0.085};

◆ sim_particles_events_passname_

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

Definition at line 156 of file LinearSeedFinder.h.

◆ sim_particles_passname_

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

Definition at line 155 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 150 of file LinearSeedFinder.h.


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