LDMX Software
tracking::reco::SiStripWaveformFitProcessor Class Reference

Fit a pulse shape to each SiStripWaveform and produce FittedSiStripHits. More...

#include <SiStripWaveformFitProcessor.h>

Public Member Functions

 SiStripWaveformFitProcessor (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &ps) override
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
void onProcessStart () override
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
void onProcessEnd () override
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
virtual void onNewRun (const ldmx::RunHeader &run_header)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Private Attributes

std::string input_collection_ {"TrackerWaveforms"}
 
std::string input_pass_name_ {""}
 
std::string output_collection_ {"FittedSiStripHits"}
 
std::string daq_map_file_ {""}
 
double t_scan_min_ns_ {-50.0}
 
double t_scan_max_ns_ {-1.0}
 
double t_scan_step_ns_ {1.0}
 
double max_chi2_ndf_ {-1.0}
 
TrackerDaqMap daq_map_
 
std::unique_ptr< tracking::digitization::PulseShapepulse_shape_
 Pulse shape shared by every per-channel fitter (built in onProcessStart).
 
long n_waveforms_ {0}
 waveforms seen
 
long n_unmapped_ {0}
 skipped: (feb, hybrid) absent from the DAQ map
 
long n_out_of_range_ {0}
 skipped: strip_id outside the sensor
 
long n_fit_attempted_ {0}
 waveforms passed to the fitter
 
long n_unconverged_ {0}
 skipped because the pulse fit did not converge
 
long n_bad_chi2_ {0}
 skipped by the chi2/ndf cut
 
long n_hits_ {0}
 emitted FittedSiStripHits
 
std::map< uint16_t, long > unmapped_sensors_
 (feb, hybrid) pairs already warned about, so each is reported only once.
 

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

Fit a pulse shape to each SiStripWaveform and produce FittedSiStripHits.

This is the real-data counterpart of StripFitProcessor, and the bridge into the geometry-aware reconstruction.

Input : collection of ldmx::SiStripWaveform (pedestal-subtracted samples) Output : collection of ldmx::FittedSiStripHit

Configuration parameters

input_collection SiStripWaveform input collection. input_pass_name Pass name for the input collection. output_collection FittedSiStripHit output collection. daq_map_file Path to the DAQ map JSON (required). t_scan_min_ns Lower bound of the hit-time scan [ns] (default -50). t_scan_max_ns Upper bound of the hit-time scan [ns]; <= 0 means auto, i.e. n_samples * sampling interval (default -1). t_scan_step_ns Step size of the coarse scan [ns] (default 1). max_chi2_ndf If > 0, discard fits with chi2/ndf above this value (default -1 = off).

Definition at line 35 of file SiStripWaveformFitProcessor.h.

Constructor & Destructor Documentation

◆ SiStripWaveformFitProcessor()

tracking::reco::SiStripWaveformFitProcessor::SiStripWaveformFitProcessor ( const std::string & name,
framework::Process & process )
inline

Definition at line 37 of file SiStripWaveformFitProcessor.h.

Base class for a module which produces a data product.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ configure()

void tracking::reco::SiStripWaveformFitProcessor::configure ( framework::config::Parameters & parameters)
overridevirtual

Callback for the EventProcessor to configure itself from the given set of parameters.

The parameters a processor has access to are the member variables of the python class in the sequence that has class_name equal to the EventProcessor class name.

For an example, look at MyProcessor.

Parameters
parametersParameters for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 13 of file SiStripWaveformFitProcessor.cxx.

13 {
14 input_collection_ =
15 ps.get<std::string>("input_collection", input_collection_);
16 input_pass_name_ = ps.get<std::string>("input_pass_name", input_pass_name_);
17 output_collection_ =
18 ps.get<std::string>("output_collection", output_collection_);
19 daq_map_file_ = ps.get<std::string>("daq_map_file", daq_map_file_);
20
21 t_scan_min_ns_ = ps.get<double>("t_scan_min_ns", t_scan_min_ns_);
22 t_scan_max_ns_ = ps.get<double>("t_scan_max_ns", t_scan_max_ns_);
23 t_scan_step_ns_ = ps.get<double>("t_scan_step_ns", t_scan_step_ns_);
24 max_chi2_ndf_ = ps.get<double>("max_chi2_ndf", max_chi2_ndf_);
25}

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

◆ onProcessEnd()

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

Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.

Reimplemented from framework::EventProcessor.

Definition at line 157 of file SiStripWaveformFitProcessor.cxx.

157 {
158 const long n_converged = n_fit_attempted_ - n_unconverged_;
159 const double fail_pct =
161 ? 100.0 * static_cast<double>(n_unconverged_) / n_fit_attempted_
162 : 0.0;
163 ldmx_log(info) << "Fit summary: " << n_fit_attempted_ << " attempted, "
164 << n_converged << " converged, " << n_unconverged_
165 << " failed (" << fail_pct << "%)";
166 ldmx_log(info) << "SiStripWaveformFitProcessor summary: " << n_waveforms_
167 << " waveforms -> " << n_hits_ << " hits (" << n_unmapped_
168 << " unmapped, " << n_out_of_range_ << " out-of-range, "
169 << n_unconverged_ << " unconverged, " << n_bad_chi2_
170 << " bad chi2/ndf)";
171 for (const auto& [k, n] : unmapped_sensors_) {
172 ldmx_log(warn) << " unmapped feb=" << (k >> 8) << " hybrid=" << (k & 0xFF)
173 << ": " << n << " waveforms dropped";
174 }
175}
std::map< uint16_t, long > unmapped_sensors_
(feb, hybrid) pairs already warned about, so each is reported only once.
long n_unmapped_
skipped: (feb, hybrid) absent from the DAQ map
long n_fit_attempted_
waveforms passed to the fitter
long n_out_of_range_
skipped: strip_id outside the sensor
long n_unconverged_
skipped because the pulse fit did not converge

References n_bad_chi2_, n_fit_attempted_, n_hits_, n_out_of_range_, n_unconverged_, n_unmapped_, n_waveforms_, and unmapped_sensors_.

◆ onProcessStart()

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

Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.

Reimplemented from framework::EventProcessor.

Definition at line 27 of file SiStripWaveformFitProcessor.cxx.

27 {
28 using namespace tracking::digitization;
29
30 if (daq_map_file_.empty()) {
31 EXCEPTION_RAISE("BadConfig",
32 "SiStripWaveformFitProcessor requires a daq_map_file.");
33 }
34 // Loads eagerly so a missing/malformed map fails here, at start-up, with the
35 // path in the message -- never as a silently empty event stream.
36 daq_map_ = TrackerDaqMap::fromJsonFile(daq_map_file_);
37
38 pulse_shape_ = PulseShape::make(std::string(PULSE_SHAPE_NAME),
39 PEAKING_TIME_NS, SECOND_TIME_CONST_NS);
40
41 ldmx_log(info) << "SiStripWaveformFitProcessor configured:"
42 << " daq_map='" << daq_map_file_ << "' (" << daq_map_.size()
43 << " sensors)" << " shape=" << PULSE_SHAPE_NAME
44 << " tp=" << PEAKING_TIME_NS << " ns" << " T scan ["
45 << t_scan_min_ns_ << ", "
46 << (t_scan_max_ns_ > 0.0 ? std::to_string(t_scan_max_ns_)
47 : std::string("auto"))
48 << "] ns" << " step=" << t_scan_step_ns_ << " ns";
49}
std::unique_ptr< tracking::digitization::PulseShape > pulse_shape_
Pulse shape shared by every per-channel fitter (built in onProcessStart).
std::size_t size() const
Number of sensors in the map.
static TrackerDaqMap fromJsonFile(const std::string &path)
Load a DAQ map from a JSON file.

References tracking::reco::TrackerDaqMap::fromJsonFile(), pulse_shape_, and tracking::reco::TrackerDaqMap::size().

◆ produce()

void tracking::reco::SiStripWaveformFitProcessor::produce ( framework::Event & event)
overridevirtual

Process the event and put new data products into it.

Parameters
eventThe Event to process.

Implements framework::Producer.

Definition at line 51 of file SiStripWaveformFitProcessor.cxx.

51 {
52 using namespace tracking::digitization;
53
54 const auto& peds =
56
57 const auto& waveforms = event.getCollection<ldmx::SiStripWaveform>(
58 input_collection_, input_pass_name_);
59
60 std::vector<ldmx::FittedSiStripHit> hits;
61 hits.reserve(waveforms.size());
62
63 for (const auto& wf : waveforms) {
65
66 // -----------------------------------------------------------------------
67 // Address first: an unmapped hybrid or an unbonded channel is dropped
68 // before paying for the fit.
69 // -----------------------------------------------------------------------
70 const uint8_t feb = wf.getFebId();
71 const uint8_t hybrid = wf.getHybridId();
72
73 if (!daq_map_.has(feb, hybrid)) {
75 const uint16_t k =
76 static_cast<uint16_t>((static_cast<uint16_t>(feb) << 8) | hybrid);
77 if (unmapped_sensors_[k]++ == 0) {
78 ldmx_log(warn) << "No DAQ-map entry for feb=" << static_cast<int>(feb)
79 << " hybrid=" << static_cast<int>(hybrid)
80 << " -- dropping its waveforms (reported once)";
81 }
82 continue;
83 }
84
85 const auto& sensor = daq_map_.at(feb, hybrid);
86 const int16_t pchannel = wf.getPchannel();
87 const int strip_id = channelmap::stripId(
88 pchannel, sensor.n_strips_, sensor.first_strip_, sensor.reversed_);
89
90 // Reject channels that fall outside the bonded strip range (e.g. a read-out
91 // but unbonded APV). Counted so an unexpected layout shows up loudly.
92 if (strip_id < sensor.first_strip_ ||
93 strip_id >= sensor.first_strip_ + sensor.n_strips_) {
95 continue;
96 }
97
98 // -----------------------------------------------------------------------
99 // Fit. The noise enters the chi2, so the fitter is per channel; it is a
100 // cheap value type over a shared pulse shape.
101 // -----------------------------------------------------------------------
102 uint8_t apv_id, channel;
103 channelmap::apvChannelFromPchannel(pchannel, apv_id, channel);
104 const float noise = peds.noise(feb, hybrid, apv_id, channel);
105
106 const auto& samples = wf.getSamples();
107 const int n_samples = static_cast<int>(samples.size());
108 // Samples are pedestal-subtracted and lie on a uniform grid measured from
109 // sample 0, so T may peak anywhere from before sample 0 to the last sample.
110 const double t_scan_max = (t_scan_max_ns_ > 0.0)
111 ? t_scan_max_ns_
112 : n_samples * SAMPLING_INTERVAL_NS;
113
115 /*t0_offset_ns=*/0.0, SAMPLING_INTERVAL_NS,
116 /*pedestal_adc=*/0.0,
117 /*noise_sigma_adc=*/noise, t_scan_min_ns_,
118 t_scan_max, t_scan_step_ns_);
119 const auto fit = fitter.fit(samples);
121
122 ldmx_log(trace) << "fit feb=" << static_cast<int>(feb)
123 << " hyb=" << static_cast<int>(hybrid)
124 << " pch=" << pchannel << " nsamp=" << n_samples
125 << " noise=" << noise
126 << " -> converged=" << (fit.converged ? "yes" : "no")
127 << " amp=" << fit.amplitude << " t0=" << fit.t0 << "ns"
128 << " chi2/ndf=" << fit.chi2 << "/" << fit.ndf << " ("
129 << (fit.ndf > 0 ? fit.chi2 / fit.ndf : 0.0) << ")";
130
131 if (!fit.converged) {
133 continue;
134 }
135
136 if (max_chi2_ndf_ > 0.0 && fit.ndf > 0) {
137 if (fit.chi2 / fit.ndf > max_chi2_ndf_) {
138 ++n_bad_chi2_;
139 continue;
140 }
141 }
142
143 hits.emplace_back(
144 sensor.layer_id_, strip_id, static_cast<float>(fit.amplitude),
145 static_cast<float>(fit.t0), static_cast<float>(fit.chi2), fit.ndf,
146 /*track_id=*/-1, /*pdg_id=*/0, /*sim_hit_id=*/-1,
147 /*edep=*/0.f, noise);
148 ++n_hits_;
149 }
150
151 ldmx_log(debug) << "Produced " << hits.size() << " FittedSiStripHits from "
152 << waveforms.size() << " waveforms";
153
154 event.add(output_collection_, hits);
155}
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Full multi-trigger waveform for one silicon strip channel.
Fits a pulse shape to the ADC samples of a single silicon-strip readout channel to extract hit amplit...
const SensorInfo & at(uint8_t feb, uint8_t hybrid) const
Look up the sensor read by (feb, hybrid).
bool has(uint8_t feb, uint8_t hybrid) const
True if the map has an entry for this electronics sensor.
static const std::string CONDITIONS_NAME
Name of the conditions object (must match the python registration).
constexpr int stripId(int16_t pchannel, int n_strips, int first_strip, bool reversed)
Map a physical strip number (pchannel) onto a sensor strip index using a DAQ-map transform: an option...
constexpr void apvChannelFromPchannel(int16_t pchannel, uint8_t &apv_id, uint8_t &channel)
Inverse of pchannel(): recover the (APV id, APV channel) pair from a physical strip number.
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,...

References tracking::reco::channelmap::apvChannelFromPchannel(), tracking::reco::TrackerDaqMap::at(), tracking::reco::TrackerPedestals::CONDITIONS_NAME, tracking::digitization::StripPulseFitter::fit(), framework::EventProcessor::getCondition(), tracking::reco::TrackerDaqMap::has(), n_bad_chi2_, n_fit_attempted_, n_hits_, n_out_of_range_, n_unconverged_, n_unmapped_, n_waveforms_, pulse_shape_, tracking::reco::channelmap::stripId(), and unmapped_sensors_.

Member Data Documentation

◆ daq_map_

TrackerDaqMap tracking::reco::SiStripWaveformFitProcessor::daq_map_
private

Definition at line 62 of file SiStripWaveformFitProcessor.h.

◆ daq_map_file_

std::string tracking::reco::SiStripWaveformFitProcessor::daq_map_file_ {""}
private

Definition at line 50 of file SiStripWaveformFitProcessor.h.

50{""};

◆ input_collection_

std::string tracking::reco::SiStripWaveformFitProcessor::input_collection_ {"TrackerWaveforms"}
private

Definition at line 47 of file SiStripWaveformFitProcessor.h.

47{"TrackerWaveforms"};

◆ input_pass_name_

std::string tracking::reco::SiStripWaveformFitProcessor::input_pass_name_ {""}
private

Definition at line 48 of file SiStripWaveformFitProcessor.h.

48{""};

◆ max_chi2_ndf_

double tracking::reco::SiStripWaveformFitProcessor::max_chi2_ndf_ {-1.0}
private

Definition at line 60 of file SiStripWaveformFitProcessor.h.

60{-1.0};

◆ n_bad_chi2_

long tracking::reco::SiStripWaveformFitProcessor::n_bad_chi2_ {0}
private

skipped by the chi2/ndf cut

Definition at line 73 of file SiStripWaveformFitProcessor.h.

73{0};

Referenced by onProcessEnd(), and produce().

◆ n_fit_attempted_

long tracking::reco::SiStripWaveformFitProcessor::n_fit_attempted_ {0}
private

waveforms passed to the fitter

Definition at line 71 of file SiStripWaveformFitProcessor.h.

71{0};

Referenced by onProcessEnd(), and produce().

◆ n_hits_

long tracking::reco::SiStripWaveformFitProcessor::n_hits_ {0}
private

emitted FittedSiStripHits

Definition at line 74 of file SiStripWaveformFitProcessor.h.

74{0};

Referenced by onProcessEnd(), and produce().

◆ n_out_of_range_

long tracking::reco::SiStripWaveformFitProcessor::n_out_of_range_ {0}
private

skipped: strip_id outside the sensor

Definition at line 70 of file SiStripWaveformFitProcessor.h.

70{0};

Referenced by onProcessEnd(), and produce().

◆ n_unconverged_

long tracking::reco::SiStripWaveformFitProcessor::n_unconverged_ {0}
private

skipped because the pulse fit did not converge

Definition at line 72 of file SiStripWaveformFitProcessor.h.

72{0};

Referenced by onProcessEnd(), and produce().

◆ n_unmapped_

long tracking::reco::SiStripWaveformFitProcessor::n_unmapped_ {0}
private

skipped: (feb, hybrid) absent from the DAQ map

Definition at line 69 of file SiStripWaveformFitProcessor.h.

69{0};

Referenced by onProcessEnd(), and produce().

◆ n_waveforms_

long tracking::reco::SiStripWaveformFitProcessor::n_waveforms_ {0}
private

waveforms seen

Definition at line 68 of file SiStripWaveformFitProcessor.h.

68{0};

Referenced by onProcessEnd(), and produce().

◆ output_collection_

std::string tracking::reco::SiStripWaveformFitProcessor::output_collection_ {"FittedSiStripHits"}
private

Definition at line 49 of file SiStripWaveformFitProcessor.h.

49{"FittedSiStripHits"};

◆ pulse_shape_

std::unique_ptr<tracking::digitization::PulseShape> tracking::reco::SiStripWaveformFitProcessor::pulse_shape_
private

Pulse shape shared by every per-channel fitter (built in onProcessStart).

Definition at line 65 of file SiStripWaveformFitProcessor.h.

Referenced by onProcessStart(), and produce().

◆ t_scan_max_ns_

double tracking::reco::SiStripWaveformFitProcessor::t_scan_max_ns_ {-1.0}
private

Definition at line 56 of file SiStripWaveformFitProcessor.h.

56{-1.0};

◆ t_scan_min_ns_

double tracking::reco::SiStripWaveformFitProcessor::t_scan_min_ns_ {-50.0}
private

Definition at line 55 of file SiStripWaveformFitProcessor.h.

55{-50.0};

◆ t_scan_step_ns_

double tracking::reco::SiStripWaveformFitProcessor::t_scan_step_ns_ {1.0}
private

Definition at line 57 of file SiStripWaveformFitProcessor.h.

57{1.0};

◆ unmapped_sensors_

std::map<uint16_t, long> tracking::reco::SiStripWaveformFitProcessor::unmapped_sensors_
private

(feb, hybrid) pairs already warned about, so each is reported only once.

Definition at line 76 of file SiStripWaveformFitProcessor.h.

Referenced by onProcessEnd(), and produce().


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