LDMX Software
TrigScintRecHitProducer.cxx
2
3#include <algorithm>
4#include <fstream>
5#include <stdexcept>
6
7#include "Framework/Exception/Exception.h"
9
10namespace trigscint {
11
12TrigScintRecHitProducer::TrigScintRecHitProducer(const std::string &name,
13 framework::Process &process)
14 : Producer(name, process) {}
15
16TrigScintRecHitProducer::~TrigScintRecHitProducer() {}
17
18void TrigScintRecHitProducer::configure(framework::config::Parameters &parameters) {
19 pedestal_ = parameters.get<double>("pedestal");
20 gain_ = parameters.get<double>("gain");
21 mev_per_mip_ = parameters.get<double>("mev_per_mip");
22 pe_per_mip_ = parameters.get<double>("pe_per_mip");
23 input_collection_ = parameters.get<std::string>("input_collection");
24 input_pass_name_ = parameters.get<std::string>("input_pass_name");
25 output_collection_ = parameters.get<std::string>("output_collection");
26 sample_of_interest_ = parameters.get<int>("sample_of_interest");
27
28 use_calib_file_ = parameters.get<bool>("use_calib_file", false);
29 calib_file_ = parameters.get<std::string>("calib_file", std::string{""});
30
31 // If > 0: integrate [sample_of_interest, sample_of_interest + integration_window)
32 // If <= 0: integrate all samples (default)
33 integration_window_ = parameters.get<int>("integration_window", 0);
34
35 if (use_calib_file_) {
36 if (calib_file_.empty()) {
37 throw std::runtime_error(
38 "TrigScintRecHitProducer: use_calib_file=true but calib_file is empty.");
39 }
40 readCalib(calib_file_, &gains_, &pedestals_);
41 }
42}
43
44void TrigScintRecHitProducer::produce(framework::Event &event) {
45 SimQIE qie;
46
47 const auto digis{event.getCollection<trigscint::TrigScintQIEDigis>(
48 input_collection_, input_pass_name_)};
49
50 std::vector<ldmx::TrigScintHit> trig_scint_hits;
51 trig_scint_hits.reserve(digis.size());
52
53 for (const auto &digi : digis) {
55 auto adc{digi.getADC()};
56 auto tdc{digi.getTDC()};
57
58 hit.setModuleID(0);
59 hit.setBarID(digi.getChanID());
60 // sim truth from the digi; -1 for data
61 hit.setBeamEfrac(digi.getBeamEfrac());
62
63 const int soi = sample_of_interest_;
64 if (soi < 0 || soi >= int(adc.size()) || soi >= int(tdc.size())) {
65 continue;
66 }
67 if (soi + 1 < int(adc.size())) {
68 hit.setAmplitude(qie.adc2Q(adc[soi]) + qie.adc2Q(adc[soi + 1]));
69 } else {
70 hit.setAmplitude(qie.adc2Q(adc[soi]));
71 }
72 if (tdc[soi] > 49)
73 hit.setTime(-999.);
74 else
75 hit.setTime(tdc[soi] * 0.5);
76
77 int start = soi;
78 int end = int(adc.size());
79 if (integration_window_ > 0) {
80 end = std::min(start + integration_window_, int(adc.size()));
81 }
82 const int n_samp = std::max(0, end - start);
83
84 float integrated_charge = 0.f;
85 for (int i = start; i < end; ++i) {
86 integrated_charge += qie.adc2Q(adc[i]);
87 }
88
89 double ped = pedestal_;
90 double gain = gain_;
91
92 if (use_calib_file_) {
93 const int ch = digi.getChanID();
94 if (ch >= 0 && ch < int(pedestals_.size())) ped = pedestals_[ch];
95 if (ch >= 0 && ch < int(gains_.size())) gain = gains_[ch];
96 }
97
98 const float ped_subtr_q = integrated_charge - float(n_samp) * float(ped);
99
100 hit.setEnergy(ped_subtr_q * 6250.f / float(gain) * float(mev_per_mip_) /
101 float(pe_per_mip_)); // MeV
102 hit.setPE(ped_subtr_q * 6250.f / float(gain));
103
104 trig_scint_hits.push_back(hit);
105 }
106 event.add(output_collection_, trig_scint_hits);
107}
108
109void TrigScintRecHitProducer::readCalib(const std::string &filename,
110 std::vector<double> *gains,
111 std::vector<double> *pedestals) {
112 std::ifstream infile(filename);
113 if (!infile) {
114 throw std::runtime_error(
115 "TrigScintRecHitProducer: Could not open calibration file: " + filename);
116 }
117
118 double ch = 0.;
119 double gain = 0.;
120 double ped = 0.;
121
122 while (infile >> ch >> gain >> ped) {
123 const int bar_id = int(ch);
124 if (bar_id < 0) continue;
125 if (bar_id >= int(gains->size())) {
126 gains->resize(bar_id + 1, 0.0);
127 pedestals->resize(bar_id + 1, 0.0);
128 }
129 (*gains)[bar_id] = gain;
130 (*pedestals)[bar_id] = ped;
131 }
132}
133
134}
135
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Conditions object for random number seeds.
Class that builds recHits.
Implements an event buffer system for storing event data.
Definition Event.h:42
Class which represents the process under execution.
Definition Process.h:37
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
void setTime(float time)
Set the time of the hit [ns].
void setAmplitude(float amplitude)
Set the amplitude of the hit, which is proportional to the signal in the calorimeter cell without sam...
void setEnergy(float energy)
Set the calorimetric energy of the hit, corrected for sampling factors [MeV].
void setPE(const float PE)
Set hit pe.
void setBarID(const int barID)
Set hit bar ID.
void setBeamEfrac(const float beamEfrac)
Set beam energy fraction of hit.
void setModuleID(const int moduleID)
Set hit module ID.
class for simulating QIE chip output
Definition SimQIE.h:17
float adc2Q(int ADC)
Converting ADC back to charge.
Definition SimQIE.cxx:52
class for storing QIE output
Organizes digis into TrigScintHits, linearizes TDC and ADC info, and converts amplitudes to PEs.