LDMX Software
SiStripWaveformBuilder.cxx
1#include "Tracking/Reco/SiStripWaveformBuilder.h"
2
3#include <algorithm>
4#include <map>
5
6#include "Tracking/Event/RawSiStripHit.h"
7#include "Tracking/Reco/SiStripChannelMap.h"
8#include "Tracking/Reco/TrackerPedestals.h"
9
10namespace tracking::reco {
11
13 input_collection_ =
14 ps.get<std::string>("input_collection", input_collection_);
15 input_pass_name_ = ps.get<std::string>("input_pass_name", input_pass_name_);
16 output_collection_ =
17 ps.get<std::string>("output_collection", output_collection_);
18 high_threshold_ = ps.get<double>("high_threshold", high_threshold_);
19 min_high_samples_ = ps.get<int>("min_high_samples", min_high_samples_);
20 low_threshold_ = ps.get<double>("low_threshold", low_threshold_);
22 ps.get<int>("min_consecutive_low", min_consecutive_low_);
23 n_triggers_ = ps.get<int>("n_triggers", n_triggers_);
24}
25
27 const auto& peds =
29
30 const auto& hits = event.getCollection<ldmx::RawSiStripHit>(input_collection_,
31 input_pass_name_);
32
33 // Key: encodes (feb, hybrid, pchannel) uniquely.
34 // Value: vector of (apv_trigger, samples) pairs.
35 struct TriggerSamples {
36 uint16_t apv_trigger_;
37 std::vector<short> samples_;
38 };
39 struct ChannelInfo {
40 float noise_{0};
41 uint8_t hybrid_id_{0};
42 uint8_t feb_id_{0};
43 std::vector<TriggerSamples> triggers_;
44 };
45
46 // Use a map keyed by (feb, hybrid, pchannel) for grouping.
47 std::map<uint32_t, ChannelInfo> channel_map;
48
49 for (const auto& hit : hits) {
50 const float noise = peds.noise(hit.getFebId(), hit.getHybridId(),
51 hit.getApvId(), hit.getChannel());
52 if (noise <= 0) continue;
53
54 const int16_t pchannel =
55 channelmap::pchannel(hit.getApvId(), hit.getChannel());
56 uint32_t key =
57 channelmap::groupKey(hit.getFebId(), hit.getHybridId(), pchannel);
58
59 auto& ch = channel_map[key];
60 ch.noise_ = noise;
61 ch.hybrid_id_ = hit.getHybridId();
62 ch.feb_id_ = hit.getFebId();
63 ch.triggers_.push_back({hit.getApvTrigger(), hit.getSamples()});
64 }
65
66 std::vector<ldmx::SiStripWaveform> waveforms;
67
68 for (auto& [key, ch] : channel_map) {
69 // Sort triggers by apv_trigger index.
70 std::sort(ch.triggers_.begin(), ch.triggers_.end(),
71 [](const TriggerSamples& a, const TriggerSamples& b) {
72 return a.apv_trigger_ < b.apv_trigger_;
73 });
74
75 // Assemble full waveform: [s0_t0, s1_t0, s2_t0, s0_t1, ...].
76 std::vector<short> samples;
77 samples.reserve(ch.triggers_.size() *
79 for (const auto& trig : ch.triggers_) {
80 for (short s : trig.samples_) samples.push_back(s);
81 }
82
83 if (samples.empty()) continue;
84
85 // Condition 1: at least min_high_samples_ samples exceed high_threshold_.
86 int n_high = 0;
87 for (short s : samples)
88 if (static_cast<float>(s) / ch.noise_ > high_threshold_) ++n_high;
89 if (n_high < min_high_samples_) continue;
90
91 // Condition 2: at least min_consecutive_low_ consecutive samples exceed
92 // low_threshold_.
93 int max_streak = 0, cur_streak = 0;
94 for (short s : samples) {
95 if (static_cast<float>(s) / ch.noise_ > low_threshold_) {
96 max_streak = std::max(max_streak, ++cur_streak);
97 } else {
98 cur_streak = 0;
99 }
100 }
101 if (max_streak < min_consecutive_low_) continue;
102
103 int16_t pchannel = channelmap::pchannelFromGroupKey(key);
104 uint8_t n_trig = static_cast<uint8_t>(
105 std::min(static_cast<int>(ch.triggers_.size()), 255));
106
107 waveforms.emplace_back(std::move(samples), pchannel, ch.hybrid_id_,
108 ch.feb_id_, n_trig);
109 }
110
111 ldmx_log(debug) << "Built " << waveforms.size()
112 << " waveforms (>=" << min_high_samples_ << " samples @"
113 << high_threshold_ << "s, streak>=" << min_consecutive_low_
114 << " @" << low_threshold_ << "s) from " << hits.size()
115 << " hits";
116
117 for (const auto& wf : waveforms) {
118 ldmx_log(trace) << wf;
119 }
120
121 event.add(output_collection_, waveforms);
122}
123
124} // namespace tracking::reco
125
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Implements an event buffer system for storing event data.
Definition Event.h:42
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
Implementation of a raw digitized hit from a silicon strip detector.
Assemble per-trigger pedestal-subtracted hits into full per-channel waveforms.
double high_threshold_
per-sample significance for high-threshold cut
int min_consecutive_low_
min consecutive samples exceeding low_threshold
void configure(framework::config::Parameters &ps) override
Callback for the EventProcessor to configure itself from the given set of parameters.
int n_triggers_
expected APV triggers per RoR
int min_high_samples_
min samples exceeding high_threshold
double low_threshold_
per-sample significance for consecutive-streak cut
void produce(framework::Event &event) override
Process the event and put new data products into it.
static const std::string CONDITIONS_NAME
Name of the conditions object (must match the python registration).
constexpr int K_SAMPLES_PER_APV_TRIGGER
Number of ADC samples the APV25 reads out per channel per trigger.
constexpr int16_t pchannelFromGroupKey(uint32_t key)
Extract the pchannel back out of a key produced by groupKey().
constexpr uint32_t groupKey(uint8_t feb, uint8_t hybrid, int16_t pchannel)
Pack (feb, hybrid, pchannel) into a single 32-bit waveform-grouping key.
constexpr int16_t pchannel(uint8_t apv_id, uint8_t channel)
Convert an (APV id, APV channel) pair into the physical strip number (pchannel) within a hybrid,...