21void StripClusterProcessor::configure(
24 parameters.
get<std::string>(
"in_collection",
"FittedSiStripHits");
25 in_pass_ = parameters.
get<std::string>(
"in_pass",
"");
27 parameters.
get<std::string>(
"out_collection",
"StripMeasurements");
29 seed_threshold_ = parameters.
get<
double>(
"seed_threshold", 4.0);
30 neighbor_threshold_ = parameters.
get<
double>(
"neighbor_threshold", 3.0);
31 cluster_threshold_ = parameters.
get<
double>(
"cluster_threshold", 4.0);
32 mean_time_ns_ = parameters.
get<
double>(
"mean_time_ns", 0.0);
33 time_window_ns_ = parameters.
get<
double>(
"time_window_ns", -1.0);
34 neighbor_delta_t_ns_ = parameters.
get<
double>(
"neighbor_delta_t_ns", -1.0);
35 max_chi2_ndf_ = parameters.
get<
double>(
"max_chi2_ndf", -1.0);
40void StripClusterProcessor::onProcessStart() {
41 using namespace tracking::digitization;
43 clusterer_ = std::make_unique<tracking::digitization::StripClusterer>(
44 seed_threshold_, neighbor_threshold_, cluster_threshold_, NOISE_SIGMA_ADC,
45 mean_time_ns_, time_window_ns_, neighbor_delta_t_ns_, max_chi2_ndf_);
47 ldmx_log(info) <<
"StripClusterProcessor configured:" <<
" seed_thr="
48 << seed_threshold_ <<
" nbr_thr=" << neighbor_threshold_
49 <<
" cls_thr=" << cluster_threshold_
50 <<
" noise=" << NOISE_SIGMA_ADC <<
" ADC"
51 <<
" pitch=" << READOUT_PITCH_MM <<
" mm"
52 <<
" sigma_v=" << SIGMA_V_MM <<
" mm";
58 const auto& fitted_hits =
61 ldmx_log(debug) <<
"Clustering " << fitted_hits.size()
62 <<
" FittedSiStripHits";
67 std::map<int, std::vector<ldmx::FittedSiStripHit>> hits_by_layer;
68 for (
const auto& h : fitted_hits) {
69 hits_by_layer[h.getLayerID()].push_back(h);
75 std::vector<ldmx::Measurement> measurements;
77 for (
const auto& [layer_id, layer_hits] : hits_by_layer) {
78 auto hit_surface = geometry().getSurface(layer_id);
80 ldmx_log(warn) <<
"No surface found for layer_id=" << layer_id
81 <<
" — skipping " << layer_hits.size() <<
" hits";
86 std::map<int, const ldmx::FittedSiStripHit*> strip_hit_map;
87 for (
const auto& h : layer_hits) {
88 strip_hit_map[h.getStripID()] = &h;
91 const auto clusters = clusterer_->findClusters(layer_hits);
92 ldmx_log(debug) <<
" layer " << layer_id <<
": " << layer_hits.size()
93 <<
" hits → " << clusters.size() <<
" clusters";
95 for (
const auto& cl : clusters) {
104 using namespace tracking::digitization;
105 const int n_int_ = N_READOUT_STRIPS / 2;
106 const double offset_ =
static_cast<double>(n_int_);
107 const double local_u = (cl.centroid_strip - offset_) * READOUT_PITCH_MM;
113 switch (cl.n_strips) {
115 sigma_u = SENSE_PITCH_MM / std::sqrt(12.0);
118 sigma_u = SENSE_PITCH_MM / 5.0;
121 sigma_u = SENSE_PITCH_MM / 3.0;
124 sigma_u = SENSE_PITCH_MM / 2.0;
127 sigma_u = SENSE_PITCH_MM;
130 constexpr double local_v = 0.0;
135 Acts::Vector3 dummy_momentum;
136 const Acts::Vector3 global_pos = hit_surface->localToGlobal(
137 geometryContext(), Acts::Vector2(local_u, local_v), dummy_momentum);
145 static_cast<float>(local_v));
147 static_cast<float>(sigma_u * sigma_u),
148 static_cast<float>(tracking::digitization::SIGMA_V_MM *
149 tracking::digitization::SIGMA_V_MM));
151 static_cast<float>(global_pos[1]),
152 static_cast<float>(global_pos[2]));
153 meas.
setTime(
static_cast<float>(cl.time_ns));
163 const float reco_edep =
static_cast<float>(
164 cl.total_amplitude * ADC_ELECTRONS_PER_COUNT * ENERGY_PER_EHP_MEV);
170 std::unordered_set<int> seen_track_ids;
171 for (
const int strip : cl.strip_ids) {
172 auto it = strip_hit_map.find(strip);
173 if (it != strip_hit_map.end()) {
174 const int tid = it->second->getTrackID();
175 if (tid >= 0 && seen_track_ids.insert(tid).second) {
181 ldmx_log(trace) <<
" cluster: layer=" << layer_id
182 <<
" strips=" << cl.n_strips <<
" u=" << local_u <<
" mm"
183 <<
" sigma_u=" << sigma_u <<
" mm" <<
" t=" << cl.time_ns
184 <<
" ns" <<
" amp=" << cl.total_amplitude <<
" ADC"
185 <<
" n_track_ids=" << seen_track_ids.size();
187 measurements.push_back(meas);
191 ldmx_log(debug) <<
"Produced " << measurements.size() <<
" Measurements";
192 event.add(out_collection_, measurements);