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