LDMX Software
ecal::EcalTrackFinderProcessor Class Reference

Uses ACTS framework to fit tracks through ECAL hits with zero B-field. More...

#include <EcalTrackFinderProcessor.h>

Public Member Functions

 EcalTrackFinderProcessor (const std::string &name, framework::Process &process)
 Constructor.
 
virtual ~EcalTrackFinderProcessor ()=default
 Destructor.
 
void configure (framework::config::Parameters &parameters) override
 Configure the processor.
 
void onNewRun (const ldmx::RunHeader &) override
 Initialize ACTS tracking objects once the detector geometry is known.
 
void produce (framework::Event &event) override
 Process event to find ECAL tracks.
 
void onProcessEnd () override
 Print statistics.
 
- 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 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.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
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.
 

Private Types

using EcalPropagator
 
using TrackContainer
 

Private Member Functions

std::vector< ldmx::Measurement > createMeasurements (const std::vector< ldmx::EcalHit > &hits, std::vector< double > &energies)
 Create ACTS measurement objects from ECAL hits.
 
void createEcalSurfaces ()
 Create unbounded plane surfaces at each ECAL layer.
 
std::vector< ldmx::Track > findSeeds (const std::vector< ldmx::Measurement > &measurements)
 Find seed tracks via straight-line fitting.
 
std::tuple< Acts::Vector3, Acts::Vector3, double > fitStraightLine (const std::vector< Acts::Vector3 > &points)
 Fit straight line through 3D points Returns: (position, direction, RMS residual)
 
std::unordered_multimap< Acts::GeometryIdentifier, acts_examples::IndexSourceLink > makeGeoIdSourceLinkMap (const std::vector< ldmx::Measurement > &measurements)
 Create geometry ID to source link map for CKF.
 

Private Attributes

std::unique_ptr< const EcalPropagator > propagator_
 
std::unique_ptr< const Acts::CombinatorialKalmanFilter< EcalPropagator, TrackContainer > > ckf_
 
std::map< int, std::shared_ptr< Acts::Surface > > layer_surfaces_
 
std::map< int, Acts::GeometryIdentifier > layer_geo_ids_
 
std::shared_ptr< Acts::Surface > reference_surface_
 
std::shared_ptr< const Acts::TrackingGeometry > tracking_geometry_
 
Acts::RotationMatrix3 surf_rotation_
 
std::string rec_coll_name_ {"EcalRecHits"}
 
std::string rec_pass_name_ {""}
 
std::string out_track_collection_ {"EcalTracks"}
 
int min_hits_ {3}
 
double max_chi2_ {10.0}
 
double cell_resolution_ {1.5}
 
bool debug_ {false}
 
double max_seed_rms_ {10.0}
 
double min_momentum_ {50.0}
 
double max_momentum_ {10000.0}
 
bool use_roc_energy_ {true}
 
std::string roc_file_name_
 
std::vector< std::vector< float > > roc_range_values_
 
const ldmx::EcalGeometry * geometry_ {nullptr}
 
int nevents_ {0}
 
int ntracks_ {0}
 
int nseeds_ {0}
 
double processing_time_ {0.0}
 

Additional Inherited Members

- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- 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.
 

Detailed Description

Uses ACTS framework to fit tracks through ECAL hits with zero B-field.

This processor:

  1. Converts ECAL RecHits to ldmx::Measurement objects
  2. Creates unbounded plane surfaces at each ECAL layer
  3. Finds straight-line seed tracks through hits
  4. Runs ACTS Combinatorial Kalman Filter with zero magnetic field
  5. Outputs fitted ldmx::Track objects

Definition at line 52 of file EcalTrackFinderProcessor.h.

Member Typedef Documentation

◆ EcalPropagator

using ecal::EcalTrackFinderProcessor::EcalPropagator
private
Initial value:
Acts::Propagator<Acts::EigenStepper<>, Acts::Navigator>

Definition at line 118 of file EcalTrackFinderProcessor.h.

◆ TrackContainer

using ecal::EcalTrackFinderProcessor::TrackContainer
private
Initial value:
Acts::TrackContainer<Acts::VectorTrackContainer,
Acts::VectorMultiTrajectory>

Definition at line 120 of file EcalTrackFinderProcessor.h.

Constructor & Destructor Documentation

◆ EcalTrackFinderProcessor()

ecal::EcalTrackFinderProcessor::EcalTrackFinderProcessor ( const std::string & name,
framework::Process & process )

Constructor.

Definition at line 45 of file EcalTrackFinderProcessor.cxx.

47 : Producer(name, process) {
48 // Setup surface rotation: u=+Y, v=+Z, w=+X (beam direction)
49 surf_rotation_ = Acts::RotationMatrix3::Zero();
50 surf_rotation_(1, 0) = 1; // u along Y
51 surf_rotation_(2, 1) = 1; // v along Z
52 surf_rotation_(0, 2) = 1; // w along X (beam/normal)
53}
Producer(const std::string &name, Process &process)
Class constructor.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ configure()

void ecal::EcalTrackFinderProcessor::configure ( framework::config::Parameters & parameters)
overridevirtual

Configure the processor.

Reimplemented from framework::EventProcessor.

Definition at line 55 of file EcalTrackFinderProcessor.cxx.

56 {
57 rec_coll_name_ = parameters.get<std::string>("rec_coll_name");
58 rec_pass_name_ = parameters.get<std::string>("rec_pass_name");
59 out_track_collection_ = parameters.get<std::string>("out_track_collection");
60
61 min_hits_ = parameters.get<int>("min_hits");
62 max_chi2_ = parameters.get<double>("max_chi2");
63 cell_resolution_ = parameters.get<double>("cell_resolution");
64 debug_ = parameters.get<bool>("debug");
65
66 max_seed_rms_ = parameters.get<double>("max_seed_rms");
67 min_momentum_ = parameters.get<double>("min_momentum");
68 max_momentum_ = parameters.get<double>("max_momentum");
69
70 use_roc_energy_ = parameters.get<bool>("use_roc_energy");
71 if (use_roc_energy_) {
72 roc_file_name_ = parameters.get<std::string>("roc_file");
73 std::ifstream rocfile(roc_file_name_);
74 if (!rocfile.good()) {
75 EXCEPTION_RAISE("EcalTrackFinderProcessor",
76 "ROC file '" + roc_file_name_ + "' does not exist!");
77 }
78 std::string line, value;
79 // Skip header line
80 std::getline(rocfile, line);
81 while (std::getline(rocfile, line)) {
82 std::stringstream ss(line);
83 std::vector<float> values;
84 while (std::getline(ss, value, ',')) {
85 values.push_back(value.empty() ? -1.0f : std::stof(value));
86 }
87 roc_range_values_.push_back(values);
88 }
89 ldmx_log(info) << "Loaded ROC file with " << roc_range_values_.size()
90 << " bins";
91 }
92}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75

References framework::config::Parameters::get().

◆ createEcalSurfaces()

void ecal::EcalTrackFinderProcessor::createEcalSurfaces ( )
private

Create unbounded plane surfaces at each ECAL layer.

Definition at line 232 of file EcalTrackFinderProcessor.cxx.

232 {
233 int n_layers = geometry_->getNumLayers();
234
235 for (int layer = 0; layer < n_layers; ++layer) {
236 // Get z position of this layer
237 double z_pos = geometry_->getZPosition(layer);
238
239 // Create plane surface at this z position
240 // Position in ACTS frame (x=z_ldmx, y=x_ldmx, z=y_ldmx)
241 Acts::Vector3 acts_pos =
242 tracking::sim::utils::ldmx2Acts(Acts::Vector3(0.0, 0.0, z_pos));
243
244 Acts::Translation3 translation(acts_pos);
245 Acts::Transform3 transform(translation * surf_rotation_);
246
247 // Create bounded plane surface (500mm x 500mm, covers full ECAL)
248 auto bounds = std::make_shared<Acts::RectangleBounds>(500.0, 500.0);
249 auto surface =
250 Acts::Surface::makeShared<Acts::PlaneSurface>(transform, bounds);
251
252 // Mark as sensitive so the CKF actor creates track states here.
253 // PlaneSurfaces default to isSensitive()=false; without this flag the CKF
254 // treats them as passive material surfaces and creates no track states.
255 surface->assignIsSensitive(true);
256
257 // Assign a geometry ID (use layer as volume, 0 as layer in ACTS sense)
258 Acts::GeometryIdentifier geo_id =
259 Acts::GeometryIdentifier().withVolume(layer).withLayer(0);
260 surface->assignGeometryId(geo_id);
261
262 layer_surfaces_[layer] = surface;
263 }
264
265 // Create reference surface at ECAL front face
266 double ecal_front_z = geometry_->getEcalFrontZ();
267 Acts::Vector3 ref_pos =
268 tracking::sim::utils::ldmx2Acts(Acts::Vector3(0.0, 0.0, ecal_front_z));
269 Acts::Translation3 ref_translation(ref_pos);
270 Acts::Transform3 ref_transform(ref_translation * surf_rotation_);
271 reference_surface_ =
272 Acts::Surface::makeShared<Acts::PlaneSurface>(ref_transform);
273}
double getEcalFrontZ() const
Get the z-coordinate of the Ecal face.
int getNumLayers() const
Get the number of layers in the Ecal Geometry.
double getZPosition(int layer) const
Get the z-coordinate given the layer id.

References ldmx::EcalGeometry::getEcalFrontZ(), ldmx::EcalGeometry::getNumLayers(), and ldmx::EcalGeometry::getZPosition().

Referenced by onNewRun().

◆ createMeasurements()

std::vector< ldmx::Measurement > ecal::EcalTrackFinderProcessor::createMeasurements ( const std::vector< ldmx::EcalHit > & hits,
std::vector< double > & energies )
private

Create ACTS measurement objects from ECAL hits.

Definition at line 275 of file EcalTrackFinderProcessor.cxx.

276 {
277 std::vector<ldmx::Measurement> measurements;
278 measurements.reserve(hits.size());
279 energies.clear();
280 energies.reserve(hits.size());
281
282 for (const auto& hit : hits) {
283 // Skip noise hits
284 if (hit.isNoise()) continue;
285
286 // Get EcalID
287 ldmx::EcalID ecal_id(hit.getID());
288 int layer = ecal_id.layer();
289
290 // Get position from geometry
291 auto [x, y, z] = geometry_->getPosition(ecal_id);
292
293 // Create measurement
295 meas.setGlobalPosition(x, y, z);
296 meas.setLayerID(layer);
297 meas.setTime(hit.getTime());
298
299 // Local coordinates: use x, y as local u, v in the layer plane
300 meas.setLocalPosition(x, y);
301
302 // Covariance: use cell resolution
303 double cov = cell_resolution_ * cell_resolution_;
304 meas.setLocalCovariance(cov, cov);
305
306 measurements.push_back(meas);
307 energies.push_back(hit.getEnergy());
308 }
309
310 return measurements;
311}
std::tuple< double, double, double > getPosition(EcalID id) const
Get a cell's position from its ID number.
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Definition EcalID.h:20
void setLocalPosition(const float &meas_u, const float &meas_v)
Set the local position i.e.
Definition Measurement.h:61
void setLayerID(const int &layer_id)
Set the layer ID of the sensor where this measurement took place.
void setGlobalPosition(const float &meas_x, const float &meas_y, const float &meas_z)
Set the global position i.e.
Definition Measurement.h:42
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
Definition Measurement.h:77
void setTime(const float &meas_t)
Set the measurement time in ns.
Definition Measurement.h:93

References ldmx::EcalGeometry::getPosition(), ldmx::EcalID::layer(), ldmx::Measurement::setGlobalPosition(), ldmx::Measurement::setLayerID(), ldmx::Measurement::setLocalCovariance(), ldmx::Measurement::setLocalPosition(), and ldmx::Measurement::setTime().

Referenced by produce().

◆ findSeeds()

std::vector< ldmx::Track > ecal::EcalTrackFinderProcessor::findSeeds ( const std::vector< ldmx::Measurement > & measurements)
private

Find seed tracks via straight-line fitting.

Definition at line 358 of file EcalTrackFinderProcessor.cxx.

359 {
360 std::vector<ldmx::Track> seeds;
361
362 if (measurements.size() < static_cast<size_t>(min_hits_)) {
363 ldmx_log(debug) << "Too few measurements for seed: " << measurements.size()
364 << " < " << min_hits_;
365 return seeds;
366 }
367
368 // Group measurements by layer
369 std::map<int, std::vector<const ldmx::Measurement*>> layer_map;
370 for (const auto& meas : measurements) {
371 layer_map[meas.getLayerID()].push_back(&meas);
372 }
373
374 ldmx_log(debug) << "Measurements span " << layer_map.size() << " layers";
375
376 // Simple strategy: use all hits for a single seed (can be extended later)
377 std::vector<Acts::Vector3> points;
378 std::vector<ldmx::Measurement> seed_measurements;
379
380 for (const auto& [layer, meas_vec] : layer_map) {
381 // For now, just take first hit in each layer
382 if (!meas_vec.empty()) {
383 const auto* meas = meas_vec[0];
384 auto gpos = meas->getGlobalPosition();
385
386 // Convert to ACTS frame
387 Acts::Vector3 pos_acts = tracking::sim::utils::ldmx2Acts(
388 Acts::Vector3(gpos[0], gpos[1], gpos[2]));
389 points.push_back(pos_acts);
390 seed_measurements.push_back(*meas);
391 }
392 }
393
394 if (points.size() < static_cast<size_t>(min_hits_)) {
395 ldmx_log(debug) << "Too few layers hit for seed: " << points.size() << " < "
396 << min_hits_;
397 return seeds;
398 }
399
400 // Fit straight line
401 auto [position, direction, rms] = fitStraightLine(points);
402
403 ldmx_log(debug) << "Seed line fit: rms=" << rms << " dir=(" << direction.x()
404 << "," << direction.y() << "," << direction.z() << ")";
405
406 if (rms > max_seed_rms_) {
407 ldmx_log(debug) << "Seed RMS too large: " << rms << " > " << max_seed_rms_
408 << " mm";
409 return seeds;
410 }
411
412 // Create seed track at the FIRST ECAL layer surface (layer 0).
413 // Using a surface that IS in the tracking geometry (has associatedLayer set)
414 // ensures the ACTS Navigator can use the fast initialization path and find
415 // all sensitive surfaces during CKF propagation.
418 .get();
419
420 auto& seed_surface = layer_surfaces_.begin()->second;
421
422 // For a plane surface, normal is the third column of rotation
423 Acts::Vector3 ref_normal =
424 seed_surface->localToGlobalTransform(gctx).rotation().col(2);
425 Acts::Vector3 ref_center = seed_surface->center(gctx);
426
427 double t =
428 (ref_center - position).dot(ref_normal) / direction.dot(ref_normal);
429 Acts::Vector3 seed_pos = position + t * direction;
430
431 // Estimate momentum (assume MIP ~200 MeV for now)
432 double p_estimate = 200.0; // MeV
433 Acts::Vector3 seed_mom = p_estimate * direction;
434
435 // Charge (assume positive)
436 double q = Acts::UnitConstants::e;
437
438 // Convert to bound parameters at the first layer surface
439 Acts::FreeVector seed_free =
440 tracking::sim::utils::toFreeParameters(seed_pos, seed_mom, q);
441
442 auto bound_params_result =
443 Acts::transformFreeToBoundParameters(seed_free, *seed_surface, gctx);
444
445 if (!bound_params_result.ok()) {
446 ldmx_log(warn) << "Failed to create bound parameters for seed";
447 return seeds;
448 }
449
450 Acts::BoundVector bound_params = bound_params_result.value();
451
452 // Create inflated covariance
453 Acts::BoundVector stddev;
454 stddev[Acts::eBoundLoc0] = 10.0 * Acts::UnitConstants::mm;
455 stddev[Acts::eBoundLoc1] = 10.0 * Acts::UnitConstants::mm;
456 stddev[Acts::eBoundPhi] = 0.1 * Acts::UnitConstants::rad;
457 stddev[Acts::eBoundTheta] = 0.1 * Acts::UnitConstants::rad;
458 stddev[Acts::eBoundQOverP] = 0.5 / p_estimate; // 50% uncertainty
459 stddev[Acts::eBoundTime] = 10.0 * Acts::UnitConstants::ns;
460
461 Acts::BoundMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
462
463 // Create ldmx::Track seed
464 ldmx::Track seed;
465
466 // Convert layer 0 surface position to LDMX frame
467 Acts::Vector3 ref_ldmx = tracking::sim::utils::acts2Ldmx(ref_center);
468 seed.setPerigeeLocation(ref_ldmx[0], ref_ldmx[1], ref_ldmx[2]);
469
470 seed.setChi2(0.0);
471 seed.setNhits(seed_measurements.size());
472 seed.setNdf(0);
473 seed.setNsharedHits(0);
474 seed.setCharge(q > 0 ? 1 : -1);
475
476 // Convert to std::vector for storage
477 std::vector<double> v_seed_params(bound_params.data(),
478 bound_params.data() + bound_params.size());
479 std::vector<double> v_seed_cov;
480 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
481
482 seed.setPerigeeParameters(v_seed_params);
483 seed.setPerigeeCov(v_seed_cov);
484
485 seeds.push_back(seed);
486 return seeds;
487}
std::tuple< Acts::Vector3, Acts::Vector3, double > fitStraightLine(const std::vector< Acts::Vector3 > &points)
Fit straight line through 3D points Returns: (position, direction, RMS residual)
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Implementation of a track object.
Definition Track.h:54
static const std::string NAME
Conditions object name.

References fitStraightLine(), framework::EventProcessor::getCondition(), and tracking::geo::GeometryContext::NAME.

Referenced by produce().

◆ fitStraightLine()

std::tuple< Acts::Vector3, Acts::Vector3, double > ecal::EcalTrackFinderProcessor::fitStraightLine ( const std::vector< Acts::Vector3 > & points)
private

Fit straight line through 3D points Returns: (position, direction, RMS residual)

Definition at line 314 of file EcalTrackFinderProcessor.cxx.

315 {
316 if (points.size() < 2) {
317 return {Acts::Vector3::Zero(), Acts::Vector3::Zero(), 1e6};
318 }
319
320 // Calculate centroid
321 Acts::Vector3 centroid = Acts::Vector3::Zero();
322 for (const auto& p : points) {
323 centroid += p;
324 }
325 centroid /= points.size();
326
327 // Build covariance matrix
328 Eigen::Matrix3d cov = Eigen::Matrix3d::Zero();
329 for (const auto& p : points) {
330 Acts::Vector3 dp = p - centroid;
331 cov += dp * dp.transpose();
332 }
333 cov /= points.size();
334
335 // Find principal direction (eigenvector with largest eigenvalue)
336 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver(cov);
337 Acts::Vector3 direction = solver.eigenvectors().col(2); // Largest eigenvalue
338 direction.normalize();
339
340 // Eigenvector has sign ambiguity — ensure it points forward along the beam.
341 // In ACTS coords, beam direction is +X (LDMX Z -> ACTS X).
342 if (direction.x() < 0) {
343 direction = -direction;
344 }
345
346 // Calculate RMS residual
347 double rms = 0.0;
348 for (const auto& p : points) {
349 Acts::Vector3 dp = p - centroid;
350 double residual = (dp - (dp.dot(direction)) * direction).norm();
351 rms += residual * residual;
352 }
353 rms = std::sqrt(rms / points.size());
354
355 return {centroid, direction, rms};
356}

Referenced by findSeeds().

◆ makeGeoIdSourceLinkMap()

std::unordered_multimap< Acts::GeometryIdentifier, acts_examples::IndexSourceLink > ecal::EcalTrackFinderProcessor::makeGeoIdSourceLinkMap ( const std::vector< ldmx::Measurement > & measurements)
private

Create geometry ID to source link map for CKF.

Definition at line 491 of file EcalTrackFinderProcessor.cxx.

492 {
493 std::unordered_multimap<Acts::GeometryIdentifier,
495 geo_id_sl_map;
496
497 for (size_t i = 0; i < measurements.size(); ++i) {
498 const auto& meas = measurements[i];
499 int layer = meas.getLayerID();
500
501 // Use the builder-assigned geometry ID for this layer (not the manually
502 // assigned one). This ensures the CKF Navigator's surface.geometryId()
503 // matches our source link map keys.
504 auto it = layer_geo_ids_.find(layer);
505 if (it == layer_geo_ids_.end()) {
506 ldmx_log(warn) << "No builder geometry ID for layer " << layer;
507 continue;
508 }
509
510 Acts::GeometryIdentifier geo_id = it->second;
511 acts_examples::IndexSourceLink idx_sl(geo_id, i);
512 geo_id_sl_map.insert(std::make_pair(geo_id, idx_sl));
513 }
514
515 ldmx_log(debug) << "Source link map has " << geo_id_sl_map.size()
516 << " entries from " << measurements.size() << " measurements";
517
518 return geo_id_sl_map;
519}

Referenced by produce().

◆ onNewRun()

void ecal::EcalTrackFinderProcessor::onNewRun ( const ldmx::RunHeader & )
overridevirtual

Initialize ACTS tracking objects once the detector geometry is known.

Reimplemented from framework::EventProcessor.

Definition at line 94 of file EcalTrackFinderProcessor.cxx.

94 {
95 // Geometry is available here: EcalGeometryProvider::onNewRun has already
96 // populated detector_geometry_ before processors receive onNewRun.
98 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
99
100 // Create ECAL layer surfaces
101 layer_surfaces_.clear();
103
104 // Setup zero magnetic field
105 Acts::Vector3 b_field(0., 0., 0.);
106 auto zero_b_field = std::make_shared<Acts::ConstantBField>(b_field);
107
108 // Build ACTS tracking geometry for the ECAL using CuboidVolumeBuilder
109 // Each ECAL layer becomes a sensitive layer in the tracking geometry
110
113 .get();
114
115 // Get ECAL extent in ACTS coordinates
116 double ecal_front_z = geometry_->getEcalFrontZ();
117 double ecal_back_z =
118 geometry_->getZPosition(geometry_->getNumLayers() - 1) + 50.0;
119 Acts::Vector3 front_acts =
120 tracking::sim::utils::ldmx2Acts(Acts::Vector3(0.0, 0.0, ecal_front_z));
121 Acts::Vector3 back_acts =
122 tracking::sim::utils::ldmx2Acts(Acts::Vector3(0.0, 0.0, ecal_back_z));
123
124 // Create layer configurations - one per ECAL layer.
125 // IMPORTANT: layer_configs must be in ascending x-order so LayerArrayCreator
126 // gets a monotone sequence for BinningType::arbitrary along AxisX.
127 std::vector<Acts::CuboidVolumeBuilder::LayerConfig> layer_configs;
128 double clearance = 1.0; // mm envelope around each layer surface
129
130 for (auto& [layer, surface] : layer_surfaces_) {
131 Acts::CuboidVolumeBuilder::LayerConfig lcfg;
132 lcfg.surfaces = {surface};
133 lcfg.envelopeX = std::array<double, 2>{clearance, clearance};
134 lcfg.active = true;
135 layer_configs.push_back(lcfg);
136 }
137
138 // Volume config
139 Acts::Vector3 volume_center = 0.5 * (front_acts + back_acts);
140 double x_length = std::abs(back_acts.x() - front_acts.x()) + 20.0;
141
142 Acts::CuboidVolumeBuilder::VolumeConfig ecal_vol_cfg;
143 ecal_vol_cfg.position = volume_center;
144 ecal_vol_cfg.length = {x_length, 1000.0, 1000.0}; // generous transverse size
145 ecal_vol_cfg.name = "EcalVolume";
146 ecal_vol_cfg.layerCfg = layer_configs;
147 ecal_vol_cfg.volumeMaterial =
148 std::make_shared<Acts::HomogeneousVolumeMaterial>(
149 Acts::Material::Vacuum());
150
151 // Build the tracking geometry
152 Acts::CuboidVolumeBuilder cvb;
153 Acts::CuboidVolumeBuilder::Config cvb_cfg;
154 cvb_cfg.position = volume_center;
155 cvb_cfg.length = {x_length + 20.0, 1020.0, 1020.0};
156 cvb_cfg.volumeCfg = {ecal_vol_cfg};
157 cvb.setConfig(cvb_cfg);
158
159 Acts::TrackingGeometryBuilder::Config tgb_cfg;
160 tgb_cfg.trackingVolumeBuilders.push_back(
161 [=](const auto& cxt, const auto& inner, const auto&) {
162 return cvb.trackingVolume(cxt, inner, nullptr);
163 });
164
165 Acts::TrackingGeometryBuilder tgb(tgb_cfg);
166 tracking_geometry_ = tgb.trackingGeometry(gctx);
167
168 // Extract the geometry IDs that the builder assigned to our surfaces.
169 // CuboidVolumeBuilder/TrackingGeometryBuilder reassign GeometryIdentifiers
170 // based on the volume/layer/sensitive hierarchy, overwriting our manual IDs.
171 // We must use these builder-assigned IDs when creating the source link map,
172 // because the CKF Navigator will see these IDs when it reaches a surface.
173 layer_geo_ids_.clear();
174 tracking_geometry_->visitSurfaces([&](const Acts::Surface* surface) {
175 if (!surface) return;
176 // Only care about sensitive surfaces (those with a sensitive ID)
177 if (surface->geometryId().sensitive() == 0) return;
178
179 // CuboidVolumeBuilder creates new PlaneSurface objects inside the geometry
180 // rather than using our originals. Mark them sensitive here so the CKF
181 // actor doesn't skip them as passive surfaces.
182 const_cast<Acts::Surface*>(surface)->assignIsSensitive(true);
183
184 // Match to ECAL layer by z position (LDMX frame)
185 Acts::Vector3 center_ldmx =
186 tracking::sim::utils::acts2Ldmx(surface->center(gctx));
187 double z_ldmx = center_ldmx[2];
188
189 for (int layer = 0; layer < geometry_->getNumLayers(); ++layer) {
190 double layer_z = geometry_->getZPosition(layer);
191 if (std::abs(z_ldmx - layer_z) < 0.1) { // 0.1 mm tolerance
192 layer_geo_ids_[layer] = surface->geometryId();
193 ldmx_log(debug) << "ECAL layer " << layer << " -> builder geo_id: vol="
194 << surface->geometryId().volume()
195 << " lay=" << surface->geometryId().layer()
196 << " sen=" << surface->geometryId().sensitive();
197 break;
198 }
199 }
200 });
201
202 ldmx_log(info) << "Mapped " << layer_geo_ids_.size()
203 << " ECAL layers to builder-assigned geometry IDs";
204
205 // Setup stepper with zero B-field
206 const auto stepper = Acts::EigenStepper<>{zero_b_field};
207
208 auto acts_logging_level =
209 debug_ ? Acts::Logging::VERBOSE : Acts::Logging::FATAL;
210
211 // Setup navigator with tracking geometry
212 Acts::Navigator::Config nav_cfg{tracking_geometry_};
213 nav_cfg.resolveSensitive = true;
214 nav_cfg.resolvePassive = false;
215 nav_cfg.resolveMaterial = false;
216 const Acts::Navigator navigator(
217 nav_cfg, Acts::getDefaultLogger("ECAL_NAV", acts_logging_level));
218
219 // Create propagator
220 propagator_ = std::make_unique<EcalPropagator>(
221 stepper, navigator,
222 Acts::getDefaultLogger("ECAL_PROP", acts_logging_level));
223
224 // Create CKF
225 ckf_ = std::make_unique<std::decay_t<decltype(*ckf_)>>(
226 *propagator_, Acts::getDefaultLogger("ECAL_CKF", acts_logging_level));
227
228 ldmx_log(info) << "EcalTrackFinderProcessor initialized with "
229 << layer_surfaces_.size() << " ECAL layer surfaces";
230}
void createEcalSurfaces()
Create unbounded plane surfaces at each ECAL layer.

References createEcalSurfaces(), framework::EventProcessor::getCondition(), ldmx::EcalGeometry::getEcalFrontZ(), ldmx::EcalGeometry::getNumLayers(), ldmx::EcalGeometry::getZPosition(), and tracking::geo::GeometryContext::NAME.

◆ onProcessEnd()

void ecal::EcalTrackFinderProcessor::onProcessEnd ( )
overridevirtual

Print statistics.

Reimplemented from framework::EventProcessor.

Definition at line 905 of file EcalTrackFinderProcessor.cxx.

905 {
906 ldmx_log(info) << "EcalTrackFinderProcessor Statistics:";
907 ldmx_log(info) << " Events processed: " << nevents_;
908 ldmx_log(info) << " Total seeds: " << nseeds_;
909 ldmx_log(info) << " Total tracks: " << ntracks_;
910 ldmx_log(info) << " Avg tracks/event: "
911 << (nevents_ > 0 ? (double)ntracks_ / nevents_ : 0);
912 ldmx_log(info) << " Avg time/event: "
913 << (nevents_ > 0 ? processing_time_ / nevents_ : 0) << " ms";
914}

◆ produce()

void ecal::EcalTrackFinderProcessor::produce ( framework::Event & event)
overridevirtual

Process event to find ECAL tracks.

Implements framework::Producer.

Definition at line 521 of file EcalTrackFinderProcessor.cxx.

521 {
522 auto start = std::chrono::high_resolution_clock::now();
523 nevents_++;
524
525 std::vector<ldmx::Track> tracks;
526
527 // Get ECAL RecHits
528 if (!event.exists(rec_coll_name_, rec_pass_name_)) {
529 ldmx_log(debug) << "No ECAL RecHits collection found";
530 event.add(out_track_collection_, tracks);
531 return;
532 }
533
534 const std::vector<ldmx::EcalHit> ecal_hits =
535 event.getCollection<ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
536
537 ldmx_log(debug) << "Processing " << ecal_hits.size() << " ECAL hits";
538
539 // Convert hits to measurements (with parallel energy vector)
540 std::vector<double> measurement_energies;
541 auto measurements = createMeasurements(ecal_hits, measurement_energies);
542 ldmx_log(debug) << "Created " << measurements.size() << " measurements";
543
544 if (measurements.empty()) {
545 event.add(out_track_collection_, tracks);
546 return;
547 }
548
549 // Create source link map
550 auto geo_id_sl_map = makeGeoIdSourceLinkMap(measurements);
551 ldmx_log(info) << "Source link map: " << geo_id_sl_map.size()
552 << " entries from " << measurements.size() << " measurements";
553
554 // Find seed tracks
555 auto seed_tracks = findSeeds(measurements);
556 ldmx_log(info) << "Found " << seed_tracks.size() << " seed tracks";
557 nseeds_ += seed_tracks.size();
558
559 if (seed_tracks.empty()) {
560 event.add(out_track_collection_, tracks);
561 return;
562 }
563
564 // Get ACTS contexts
567 .get();
570 .get();
573 .get();
574
575 // Setup propagator options
576 Acts::PropagatorPlainOptions propagator_options(gctx, mctx);
577 propagator_options.pathLimit = std::numeric_limits<double>::max();
578 propagator_options.maxSteps = 1000;
579 propagator_options.stepping.maxStepSize = 100.0 * Acts::UnitConstants::mm;
580
581 // Setup CKF extensions
582 Acts::GainMatrixUpdater kf_updater;
583 Acts::MeasurementSelector::Config meas_sel_cfg = {
584 {Acts::GeometryIdentifier(), {{}, {max_chi2_}, {1u}}}};
585 Acts::MeasurementSelector meas_sel{meas_sel_cfg};
586
587 tracking::sim::LdmxMeasurementCalibrator calibrator{measurements};
588
589 // Setup source link accessor iterator type and lambda
590 struct SourceLinkAccIt {
591 using BaseIt = decltype(geo_id_sl_map.begin());
592 BaseIt it_;
593
594#pragma GCC diagnostic push
595#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
596
597 using difference_type = typename BaseIt::difference_type;
598 using iterator_category = std::input_iterator_tag;
599 using value_type = Acts::SourceLink;
600 using pointer = value_type*;
601 using reference = value_type&;
602#pragma GCC diagnostic pop
603
604 SourceLinkAccIt& operator++() {
605 ++it_;
606 return *this;
607 }
608 bool operator==(const SourceLinkAccIt& other) const {
609 return it_ == other.it_;
610 }
611 bool operator!=(const SourceLinkAccIt& other) const {
612 return !(*this == other);
613 }
614 value_type operator*() const { return value_type{it_->second}; }
615 };
616
617 auto source_link_accessor = [&](const Acts::Surface& surface)
618 -> std::pair<SourceLinkAccIt, SourceLinkAccIt> {
619 auto [begin, end] = geo_id_sl_map.equal_range(surface.geometryId());
620 return {SourceLinkAccIt{begin}, SourceLinkAccIt{end}};
621 };
622
623 // v46: calibrator and measurementSelector moved to TrackStateCreator
624 Acts::TrackStateCreator<SourceLinkAccIt, TrackContainer> track_state_creator;
625 track_state_creator.sourceLinkAccessor
626 .connect<&decltype(source_link_accessor)::operator(),
627 decltype(source_link_accessor)>(&source_link_accessor);
628 track_state_creator.calibrator
630 Acts::VectorMultiTrajectory>>(&calibrator);
631 track_state_creator.measurementSelector
632 .connect<&Acts::MeasurementSelector::select<Acts::VectorMultiTrajectory>>(
633 &meas_sel);
634
635 Acts::CombinatorialKalmanFilterExtensions<TrackContainer> ckf_extensions;
636 ckf_extensions.updater.connect<
637 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
638 &kf_updater);
639 ckf_extensions.createTrackStates.connect<&Acts::TrackStateCreator<
640 SourceLinkAccIt, TrackContainer>::createTrackStates>(
641 &track_state_creator);
642
643 // Create track container
644 Acts::VectorTrackContainer vtc;
645 Acts::VectorMultiTrajectory mtj;
646 Acts::TrackContainer tc{vtc, mtj};
647
648 // Process each seed
649 for (size_t seed_idx = 0; seed_idx < seed_tracks.size(); ++seed_idx) {
650 const auto& seed = seed_tracks[seed_idx];
651
652 // Convert seed to BoundTrackParameters.
653 // Start from layer_surfaces_[0] which is part of the tracking geometry and
654 // has associatedLayer() set — this lets the Navigator use the fast
655 // initialization path and correctly traverse all 32 ECAL layers.
656 Acts::BoundVector param_vec;
657 param_vec << seed.getD0(), seed.getZ0(), seed.getPhi(), seed.getTheta(),
658 seed.getQoP(), seed.getT();
659
660 ldmx_log(debug) << "Seed " << seed_idx << ": loc0=" << param_vec[0]
661 << " loc1=" << param_vec[1] << " phi=" << param_vec[2]
662 << " theta=" << param_vec[3] << " qop=" << param_vec[4];
663
664 Acts::BoundMatrix cov_mat =
665 tracking::sim::utils::unpackCov(seed.getPerigeeCov());
666
667 auto part_hypo{Acts::ParticleHypothesis::electron()};
668 auto& layer0_surface = layer_surfaces_.begin()->second;
669 Acts::BoundTrackParameters start_params(layer0_surface, param_vec, cov_mat,
670 part_hypo);
671
672 // Setup CKF options
673 const Acts::CombinatorialKalmanFilterOptions<TrackContainer> ckf_options(
674 gctx, mctx, cctx, ckf_extensions, propagator_options);
675
676 // Run CKF
677 auto results = ckf_->findTracks(start_params, ckf_options, tc);
678
679 if (!results.ok()) {
680 ldmx_log(debug) << "CKF failed for seed " << seed_idx << ": "
681 << results.error().message();
682 continue;
683 }
684
685 auto& tracks_from_seed = results.value();
686 ldmx_log(info) << "CKF returned " << tracks_from_seed.size()
687 << " tracks from seed " << seed_idx;
688 for (auto& track : tracks_from_seed) {
689 // Count track state types before smoothing
690 int n_meas = 0, n_holes = 0, n_outliers = 0, n_total = 0;
691 for (const auto& ts : track.trackStatesReversed()) {
692 ++n_total;
693 if (ts.typeFlags().isMeasurement()) ++n_meas;
694 if (ts.typeFlags().isHole()) ++n_holes;
695 if (ts.typeFlags().isOutlier()) ++n_outliers;
696 }
697 ldmx_log(info) << "Track states: total=" << n_total << " meas=" << n_meas
698 << " holes=" << n_holes << " outliers=" << n_outliers;
699
700 // Smooth the track
701 auto smooth_result = Acts::smoothTrack(gctx, track);
702 if (!smooth_result.ok()) {
703 ldmx_log(warn) << "smoothTrack failed: "
704 << smooth_result.error().message();
705 continue;
706 }
707
708 // Create output track
709 ldmx::Track trk;
710
711 // Get parameters from first smoothed state
712 // (setReferenceSurface doesn't actually transform params, need actual
713 // state)
714 Acts::BoundVector smoothed_params;
715 std::shared_ptr<const Acts::Surface> smoothed_surface;
716 bool found_smoothed = false;
717
718 for (const auto& ts : track.trackStatesReversed()) {
719 if (ts.hasSmoothed()) {
720 smoothed_params = ts.smoothed();
721 smoothed_surface = ts.referenceSurface().getSharedPtr();
722 found_smoothed = true;
723 break;
724 }
725 }
726
727 if (!found_smoothed) {
728 ldmx_log(warn) << "No smoothed track state found after smoothing";
729 continue;
730 }
731
732 ldmx_log(debug) << "Smoothed params: loc0=" << smoothed_params[0]
733 << " loc1=" << smoothed_params[1]
734 << " phi=" << smoothed_params[2]
735 << " theta=" << smoothed_params[3]
736 << " qop=" << smoothed_params[4];
737
738 // Convert to free parameters (in ACTS global coords)
739 Acts::FreeVector free_params = Acts::transformBoundToFreeParameters(
740 *smoothed_surface, gctx, smoothed_params);
741
742 // Convert ACTS position and momentum to LDMX coordinates
743 Acts::Vector3 pos_acts(free_params[Acts::eFreePos0],
744 free_params[Acts::eFreePos1],
745 free_params[Acts::eFreePos2]);
746 Acts::Vector3 mom_acts(free_params[Acts::eFreeDir0],
747 free_params[Acts::eFreeDir1],
748 free_params[Acts::eFreeDir2]);
749
750 Acts::Vector3 pos_ldmx = tracking::sim::utils::acts2Ldmx(pos_acts);
751 Acts::Vector3 mom_ldmx = tracking::sim::utils::acts2Ldmx(mom_acts);
752
753 double x = pos_ldmx[0];
754 double y = pos_ldmx[1];
755 double z = pos_ldmx[2];
756 double px = mom_ldmx[0];
757 double py = mom_ldmx[1];
758 double pz = mom_ldmx[2];
759
760 ldmx_log(debug) << "LDMX momentum: px=" << px << " py=" << py
761 << " pz=" << pz;
762
763 // Compute theta and phi same way as SP electron (atan2(pt, pz))
764 double pt = std::sqrt(px * px + py * py);
765 double theta = std::atan2(pt, pz);
766 double phi = std::atan2(py, px);
767 if (phi < 0)
768 phi += 2.0 * M_PI; // Shift to [0, 2π] to avoid boundary artifacts
769 double qop = free_params[Acts::eFreeQOverP];
770
771 // Compute perigee parameters from smoothed track state position.
772 // PCA-based z0 is ill-defined for forward tracks (pz >> pt), so
773 // we just use the z of the smoothed state directly.
774 double d0 = -(x * std::sin(phi) - y * std::cos(phi));
775 double z0 = z;
776 double time = free_params[Acts::eFreeTime];
777
778 Acts::BoundVector perigee_params;
779 perigee_params << d0, z0, phi, theta, qop, time;
780
781 ldmx_log(debug) << "Perigee params: d0=" << d0 << " z0=" << z0
782 << " phi=" << phi << " theta=" << theta;
783
784 // Store perigee parameters
785 trk.setPerigeeParameters(
786 tracking::sim::utils::convertActsToLdmxPars(perigee_params));
787
788 // Covariance is always available for TrackProxy
789 std::vector<double> cov_vec;
790 tracking::sim::utils::flatCov(track.covariance(), cov_vec);
791 trk.setPerigeeCov(cov_vec);
792
793 Acts::Vector3 ref_loc_ldmx = tracking::sim::utils::acts2Ldmx(
794 layer_surfaces_.begin()->second->center(gctx));
795 trk.setPerigeeLocation(ref_loc_ldmx[0], ref_loc_ldmx[1], ref_loc_ldmx[2]);
796
797 trk.setChi2(track.chi2());
798 trk.setNhits(track.nMeasurements());
799 trk.setNdf(track.nMeasurements() - 5);
800 trk.setNsharedHits(0);
801 trk.setCharge(qop > 0 ? 1 : -1);
802
803 // Add measurement indices
804 for (const auto ts : track.trackStatesReversed()) {
805 if (ts.typeFlags().isMeasurement() && ts.hasUncalibratedSourceLink()) {
806 Acts::SourceLink usl = ts.getUncalibratedSourceLink();
809 trk.addMeasurementIndex(sl.index());
810 }
811 }
812
813 // Compute track energy from RecHits
814 double track_energy = 0.0;
815
816 if (use_roc_energy_ && !roc_range_values_.empty()) {
817 // Use 68% containment cone: project track through each layer,
818 // sum energies of all RecHits within the ROC radius
819
820 // Track momentum magnitude and angle for ROC bin selection
821 double trk_p_mag = 1.0 / std::abs(smoothed_params[Acts::eBoundQOverP]);
822 double trk_theta_deg = theta * 180.0 / M_PI;
823
824 // Select ROC bin based on momentum and angle
825 std::vector<float> ele_radii(roc_range_values_[0].begin() + 4,
826 roc_range_values_[0].end());
827 for (const auto& row : roc_range_values_) {
828 float theta_min = row[0], theta_max = row[1];
829 float p_min = row[2], p_max = row[3];
830 bool inrange = true;
831 if (theta_min != -1.0f)
832 inrange = inrange && (trk_theta_deg >= theta_min);
833 if (theta_max != -1.0f)
834 inrange = inrange && (trk_theta_deg < theta_max);
835 if (p_min != -1.0f) inrange = inrange && (trk_p_mag >= p_min);
836 if (p_max != -1.0f) inrange = inrange && (trk_p_mag < p_max);
837 if (inrange) {
838 ele_radii.assign(row.begin() + 4, row.end());
839 }
840 }
841
842 // Project track through each ECAL layer (straight line in LDMX coords)
843 // Track at (x, y, z) with direction (px, py, pz) normalized
844 for (const auto& hit : ecal_hits) {
845 if (hit.isNoise()) continue;
846 ldmx::EcalID ecal_id(hit.getID());
847 int layer = ecal_id.layer();
848 if (layer < 0 || layer >= static_cast<int>(ele_radii.size()))
849 continue;
850
851 auto [hx, hy, hz] = geometry_->getPosition(ecal_id);
852
853 // Project track to this layer's z
854 double dz = hz - z;
855 double proj_x = x + (px / pz) * dz;
856 double proj_y = y + (py / pz) * dz;
857
858 // Distance from projected track to hit
859 double dx = hx - proj_x;
860 double dy = hy - proj_y;
861 double dist = std::sqrt(dx * dx + dy * dy);
862
863 if (dist < ele_radii[layer]) {
864 track_energy += hit.getEnergy();
865 }
866 }
867 } else {
868 // Fallback: sum on-track hit energies only
869 for (const auto ts : track.trackStatesReversed()) {
870 if (ts.typeFlags().isMeasurement() &&
871 ts.hasUncalibratedSourceLink()) {
872 Acts::SourceLink usl = ts.getUncalibratedSourceLink();
875 track_energy += measurement_energies[sl.index()];
876 }
877 }
878 }
879
880 // Use energy as track momentum (E ≈ p for relativistic electrons)
881 double track_p = track_energy;
882 qop = (track_p > 0) ? -1.0 / track_p : 0.0;
883 perigee_params[Acts::eBoundQOverP] = qop;
884 trk.setPerigeeParameters(
885 tracking::sim::utils::convertActsToLdmxPars(perigee_params));
886
887 ldmx_log(debug) << "Track energy from RecHits: " << track_energy
888 << " MeV, q/p=" << qop;
889
890 tracks.push_back(trk);
891 ntracks_++;
892 }
893 }
894
895 ldmx_log(info) << "Found " << tracks.size() << " fitted tracks";
896
897 // Add to event
898 event.add(out_track_collection_, tracks);
899
900 auto end = std::chrono::high_resolution_clock::now();
901 auto diff = end - start;
902 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
903}
std::vector< ldmx::Measurement > createMeasurements(const std::vector< ldmx::EcalHit > &hits, std::vector< double > &energies)
Create ACTS measurement objects from ECAL hits.
std::unordered_multimap< Acts::GeometryIdentifier, acts_examples::IndexSourceLink > makeGeoIdSourceLinkMap(const std::vector< ldmx::Measurement > &measurements)
Create geometry ID to source link map for CKF.
std::vector< ldmx::Track > findSeeds(const std::vector< ldmx::Measurement > &measurements)
Find seed tracks via straight-line fitting.
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
static const std::string NAME
Conditions object name.
static const std::string NAME
Conditions object name.
void calibrate(const Acts::GeometryContext &, const Acts::CalibrationContext &, const Acts::SourceLink &genericSourceLink, typename traj_t::TrackStateProxy trackState) const
Find the measurement corresponding to the source link.

References tracking::sim::LdmxMeasurementCalibrator::calibrate(), createMeasurements(), framework::Event::exists(), findSeeds(), framework::EventProcessor::getCondition(), ldmx::EcalGeometry::getPosition(), acts_examples::IndexSourceLink::index(), ldmx::EcalID::layer(), makeGeoIdSourceLinkMap(), tracking::geo::CalibrationContext::NAME, tracking::geo::GeometryContext::NAME, and tracking::geo::MagneticFieldContext::NAME.

Member Data Documentation

◆ cell_resolution_

double ecal::EcalTrackFinderProcessor::cell_resolution_ {1.5}
private

Definition at line 152 of file EcalTrackFinderProcessor.h.

152{1.5}; // ECAL cell resolution [mm]

◆ ckf_

std::unique_ptr< const Acts::CombinatorialKalmanFilter<EcalPropagator, TrackContainer> > ecal::EcalTrackFinderProcessor::ckf_
private

Definition at line 127 of file EcalTrackFinderProcessor.h.

◆ debug_

bool ecal::EcalTrackFinderProcessor::debug_ {false}
private

Definition at line 153 of file EcalTrackFinderProcessor.h.

153{false}; // ACTS debug logging

◆ geometry_

const ldmx::EcalGeometry* ecal::EcalTrackFinderProcessor::geometry_ {nullptr}
private

Definition at line 166 of file EcalTrackFinderProcessor.h.

166{nullptr};

◆ layer_geo_ids_

std::map<int, Acts::GeometryIdentifier> ecal::EcalTrackFinderProcessor::layer_geo_ids_
private

Definition at line 135 of file EcalTrackFinderProcessor.h.

◆ layer_surfaces_

std::map<int, std::shared_ptr<Acts::Surface> > ecal::EcalTrackFinderProcessor::layer_surfaces_
private

Definition at line 130 of file EcalTrackFinderProcessor.h.

◆ max_chi2_

double ecal::EcalTrackFinderProcessor::max_chi2_ {10.0}
private

Definition at line 151 of file EcalTrackFinderProcessor.h.

151{10.0}; // Outlier chi2 cut

◆ max_momentum_

double ecal::EcalTrackFinderProcessor::max_momentum_ {10000.0}
private

Definition at line 158 of file EcalTrackFinderProcessor.h.

158{10000.0}; // Max momentum estimate [MeV]

◆ max_seed_rms_

double ecal::EcalTrackFinderProcessor::max_seed_rms_ {10.0}
private

Definition at line 156 of file EcalTrackFinderProcessor.h.

156{10.0}; // Max RMS for seed fit [mm]

◆ min_hits_

int ecal::EcalTrackFinderProcessor::min_hits_ {3}
private

Definition at line 150 of file EcalTrackFinderProcessor.h.

150{3}; // Minimum hits per track

◆ min_momentum_

double ecal::EcalTrackFinderProcessor::min_momentum_ {50.0}
private

Definition at line 157 of file EcalTrackFinderProcessor.h.

157{50.0}; // Min momentum estimate [MeV]

◆ nevents_

int ecal::EcalTrackFinderProcessor::nevents_ {0}
private

Definition at line 169 of file EcalTrackFinderProcessor.h.

169{0};

◆ nseeds_

int ecal::EcalTrackFinderProcessor::nseeds_ {0}
private

Definition at line 171 of file EcalTrackFinderProcessor.h.

171{0};

◆ ntracks_

int ecal::EcalTrackFinderProcessor::ntracks_ {0}
private

Definition at line 170 of file EcalTrackFinderProcessor.h.

170{0};

◆ out_track_collection_

std::string ecal::EcalTrackFinderProcessor::out_track_collection_ {"EcalTracks"}
private

Definition at line 149 of file EcalTrackFinderProcessor.h.

149{"EcalTracks"};

◆ processing_time_

double ecal::EcalTrackFinderProcessor::processing_time_ {0.0}
private

Definition at line 172 of file EcalTrackFinderProcessor.h.

172{0.0};

◆ propagator_

std::unique_ptr<const EcalPropagator> ecal::EcalTrackFinderProcessor::propagator_
private

Definition at line 124 of file EcalTrackFinderProcessor.h.

◆ rec_coll_name_

std::string ecal::EcalTrackFinderProcessor::rec_coll_name_ {"EcalRecHits"}
private

Definition at line 147 of file EcalTrackFinderProcessor.h.

147{"EcalRecHits"};

◆ rec_pass_name_

std::string ecal::EcalTrackFinderProcessor::rec_pass_name_ {""}
private

Definition at line 148 of file EcalTrackFinderProcessor.h.

148{""};

◆ reference_surface_

std::shared_ptr<Acts::Surface> ecal::EcalTrackFinderProcessor::reference_surface_
private

Definition at line 138 of file EcalTrackFinderProcessor.h.

◆ roc_file_name_

std::string ecal::EcalTrackFinderProcessor::roc_file_name_
private

Definition at line 162 of file EcalTrackFinderProcessor.h.

◆ roc_range_values_

std::vector<std::vector<float> > ecal::EcalTrackFinderProcessor::roc_range_values_
private

Definition at line 163 of file EcalTrackFinderProcessor.h.

◆ surf_rotation_

Acts::RotationMatrix3 ecal::EcalTrackFinderProcessor::surf_rotation_
private

Definition at line 144 of file EcalTrackFinderProcessor.h.

◆ tracking_geometry_

std::shared_ptr<const Acts::TrackingGeometry> ecal::EcalTrackFinderProcessor::tracking_geometry_
private

Definition at line 141 of file EcalTrackFinderProcessor.h.

◆ use_roc_energy_

bool ecal::EcalTrackFinderProcessor::use_roc_energy_ {true}
private

Definition at line 161 of file EcalTrackFinderProcessor.h.

161{true}; // Use 68% containment cone for track energy

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