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::MeasurementcreateMeasurements (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::TrackfindSeeds (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::IndexSourceLinkmakeGeoIdSourceLinkMap (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::EcalGeometrygeometry_ {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
 
NtupleManagerntuple_ {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 61 of file EcalTrackFinderProcessor.h.

Member Typedef Documentation

◆ EcalPropagator

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

Definition at line 127 of file EcalTrackFinderProcessor.h.

◆ TrackContainer

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

Definition at line 129 of file EcalTrackFinderProcessor.h.

Constructor & Destructor Documentation

◆ EcalTrackFinderProcessor()

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

Constructor.

Definition at line 44 of file EcalTrackFinderProcessor.cxx.

46 : Producer(name, process) {
47 // Setup surface rotation: u=+Y, v=+Z, w=+X (beam direction)
48 surf_rotation_ = Acts::RotationMatrix3::Zero();
49 surf_rotation_(1, 0) = 1; // u along Y
50 surf_rotation_(2, 1) = 1; // v along Z
51 surf_rotation_(0, 2) = 1; // w along X (beam/normal)
52}
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 54 of file EcalTrackFinderProcessor.cxx.

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

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:60
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:41
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
Definition Measurement.h:76
void setTime(const float &meas_t)
Set the measurement time in ns.
Definition Measurement.h:92

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 = Acts::transformFreeToBoundParameters(
443 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:53
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 93 of file EcalTrackFinderProcessor.cxx.

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

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

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

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

◆ ckf_

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

Definition at line 136 of file EcalTrackFinderProcessor.h.

◆ debug_

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

Definition at line 162 of file EcalTrackFinderProcessor.h.

162{false}; // ACTS debug logging

◆ geometry_

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

Definition at line 175 of file EcalTrackFinderProcessor.h.

175{nullptr};

◆ layer_geo_ids_

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

Definition at line 144 of file EcalTrackFinderProcessor.h.

◆ layer_surfaces_

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

Definition at line 139 of file EcalTrackFinderProcessor.h.

◆ max_chi2_

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

Definition at line 160 of file EcalTrackFinderProcessor.h.

160{10.0}; // Outlier chi2 cut

◆ max_momentum_

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

Definition at line 167 of file EcalTrackFinderProcessor.h.

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

◆ max_seed_rms_

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

Definition at line 165 of file EcalTrackFinderProcessor.h.

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

◆ min_hits_

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

Definition at line 159 of file EcalTrackFinderProcessor.h.

159{3}; // Minimum hits per track

◆ min_momentum_

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

Definition at line 166 of file EcalTrackFinderProcessor.h.

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

◆ nevents_

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

Definition at line 178 of file EcalTrackFinderProcessor.h.

178{0};

◆ nseeds_

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

Definition at line 180 of file EcalTrackFinderProcessor.h.

180{0};

◆ ntracks_

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

Definition at line 179 of file EcalTrackFinderProcessor.h.

179{0};

◆ out_track_collection_

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

Definition at line 158 of file EcalTrackFinderProcessor.h.

158{"EcalTracks"};

◆ processing_time_

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

Definition at line 181 of file EcalTrackFinderProcessor.h.

181{0.0};

◆ propagator_

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

Definition at line 133 of file EcalTrackFinderProcessor.h.

◆ rec_coll_name_

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

Definition at line 156 of file EcalTrackFinderProcessor.h.

156{"EcalRecHits"};

◆ rec_pass_name_

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

Definition at line 157 of file EcalTrackFinderProcessor.h.

157{""};

◆ reference_surface_

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

Definition at line 147 of file EcalTrackFinderProcessor.h.

◆ roc_file_name_

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

Definition at line 171 of file EcalTrackFinderProcessor.h.

◆ roc_range_values_

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

Definition at line 172 of file EcalTrackFinderProcessor.h.

◆ surf_rotation_

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

Definition at line 153 of file EcalTrackFinderProcessor.h.

◆ tracking_geometry_

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

Definition at line 150 of file EcalTrackFinderProcessor.h.

◆ use_roc_energy_

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

Definition at line 170 of file EcalTrackFinderProcessor.h.

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

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