LDMX Software
TestBeamHitProducer.cxx
Go to the documentation of this file.
1
9
10namespace trigscint {
11
12TestBeamHitProducer::TestBeamHitProducer(const std::string& name,
13 framework::Process& process)
14 : Producer(name, process) {}
15
16void TestBeamHitProducer::configure(framework::config::Parameters& parameters) {
17 input_col_ = parameters.get<std::string>("inputCollection");
18 output_collection_ = parameters.get<std::string>("outputCollection");
19 input_pass_name_ = parameters.get<std::string>("inputPassName");
20 mip_response_ = parameters.get<std::vector<double> >("MIPresponse");
21 peds_ = parameters.get<std::vector<double> >("pedestals");
22 gain_ = parameters.get<std::vector<double> >("gain");
23
24 start_sample_ = parameters.get<int>("startSample");
25 pulse_width_ = parameters.get<int>("pulseWidth");
26 pulse_width_lyso_ = parameters.get<int>("pulseWidthLYSO");
27 n_instrumented_channels_ = parameters.get<int>("nInstrumentedChannels");
28 do_clean_hits_ = parameters.get<bool>("doCleanHits");
29
30 std::cout << " [ TestBeamHitProducer ] In configure(), got parameters "
31 << "\n\t inputCollection = " << input_col_
32 << "\n\t inputPassName = " << input_pass_name_
33 << "\n\t outputCollection = " << output_collection_
34 << "\n\t startSample = " << start_sample_
35 << "\n\t pulseWidth = " << pulse_width_
36 << "\n\t pulseWidthLYSO = " << pulse_width_lyso_
37 << "\n\t gain[0] = " << gain_[0]
38 << "\n\t nInstrumentedChannels = " << n_instrumented_channels_
39 << "\n\t doCleanHits = " << do_clean_hits_
40 << "\n\t pedestals[0] = " << peds_[0]
41 << "\n\t MIPresponse[0] = " << mip_response_[0] << "\t."
42 << std::endl;
43
44 return;
45}
46
47void TestBeamHitProducer::produce(framework::Event& event) {
48 /*
49 hit producer.
50 sum up all charge within a certain time window. could work two ways:
51 - find a time sample above a threshold or where TDC is 0-50 (0-2)
52 * this could allow for finding several pulses per event, just
53 keep sliding along in time
54 -- in that case, record nPulses, startsample, pulsewidth
55 for each hit
56 - use a fixed start sample, and keep summing from there until
57 nSamples is reached or all time samples used
58
59 specifics:
60 - each channel has its own pedestal to subtract. also try using the
61 first 5 samples to establish a threshold in the event. store both
62 - store hit Q and hit PE conversion
63 - for now use the same reconstruction paradigm for LYSO and plastic.
64 two notes though
65 1. LYSO pulse looks wider, and might need wider window. plastic is
66 fine with 5. start by 8 for LYSO (even if for large pulses, sometimes 10
67 seem to be needed). could probe this by correlating plastic and LYSO, and
68 checking if at some amplitude (in plastic), we start cutting off charge in
69 LYSO
70 2. there is a time offset between fibers. need to have a
71 parameter fiber2offset to use for elecID >= 8
72 -- added this as a variable in EventReadout, along with fiber
73 number. so this class doesn't need any detailed knowledge
74
75 variables to write out:
76 - start sample
77 - pulse width
78 - n samples above threshold
79 - nPulses
80 - early pedestal (from first 5)
81 - assumed/average channel pedestal
82 - total Q
83 - ped subtracted total Q
84 - PE value
85 - max amplitude in pulse
86 - store material assumption? isLYSO?
87 */
88
89 float mev_per_mip = 0.3;
90 float pe_per_mip = 100;
91
92 const auto channels{event.getCollection<trigscint::EventReadout>(
93 input_col_, input_pass_name_)};
94
95 int ev_nb = event.getEventNumber();
96 std::vector<trigscint::TestBeamHit> hits;
97 for (auto chan : channels) {
99 int bar = chan.getChanID();
100 // don't run hit reconstruction on junk signal
101 if (bar >= n_instrumented_channels_) continue;
102 int width = pulse_width_;
103 if (bar % 2 == 0) { // LYSO channel: allow for wider pulses
104 width = pulse_width_lyso_; // avoid hardwiring
105 }
106 hit.setPulseWidth(width);
107 hit.setStartSample(start_sample_);
108 float ped = peds_.at(bar); // chan.getPedestal() ;
109 float early_ped = chan.getEarlyPedestal();
110 hit.setPedestal(ped);
111 hit.setEarlyPedestal(early_ped);
112 int is_clean = 0; // false;
113 float threshold = fabs(ped); // 2*fabs(peds_[ bar ]); // or sth
114 if (do_clean_hits_) threshold = 7 * fabs(ped); // stricter cut
115
116 int start_t = start_sample_ + chan.getTimeOffset();
117 float max_q = -999.;
118 int n_samp_above_ped = 0;
119 int n_samp_above_thr = 0;
120 float tot_subtr_q = 0;
121 std::vector<float> q = chan.getQ();
122 // go to the start sample defined for this channel.
123 for (int i_t = start_t; i_t < q.size(); i_t++) {
124 ldmx_log(debug) << "in event " << ev_nb << "; channel " << bar
125 << ", got charge[" << i_t << "] = " << q.at(i_t);
126 // for the defined number of samples, subtract pedestal. if > 0, increment
127 // sample counter.
128 float sub_q = q.at(i_t) -
129 ped; // this might be addition, if ped is negative. should
130 // see this as channel dependence in nSampAbove
131 // once beyond nSamples, want to see how long positive threshold
132 // subtracted tail is --> increment sample counter in any case.
133 if (sub_q > 0) n_samp_above_ped++;
134 if (sub_q > threshold) n_samp_above_thr++;
135 if (i_t - start_t < width) { // we're in the pulse integration window
136 if (sub_q > max_q) // keep track of max Q. this is the pulse amplitude
137 max_q = sub_q; // q.at(iT);
138 if (sub_q > 0)
139 tot_subtr_q +=
140 sub_q; // add positive subtracted Q to total pulse charge.
141 } else if (sub_q < 0 ||
142 q.at(i_t) < 0) // if after the full pulse width, subQ <
143 // pedestal, break. special case to break at
144 // q=0 for cases where ped < 0
145 break;
146 // done
147 } // over time samples
148
149 // first check that hit passes any quality cuts
150 uint flag = chan.getQualityFlag();
151 if (do_clean_hits_) {
152 // int isLongPulse=(nSampAboveThr < 2 || nSampAboveThr >
153 // width + 2);
154 int is_long_pulse =
155 (n_samp_above_thr >
156 width); // the short ones we'll have to single out otherwise (like
157 // spike flag or low Q) or live with
158 flag += 4 * is_long_pulse;
159 if (max_q > 2e5 && n_samp_above_thr < 3 &&
160 flag % 2 == 0) // this was not flagged as a spike but is eerily
161 // narrow and with high Q; flag it as a spike.
162 flag += 1;
163 if (flag == 0) is_clean = 1;
164 }
165
166 float pe = tot_subtr_q * 6250. / gain_[bar];
167 if (pe > 20) // dont't want to intercalibrate the shot noise
168 pe *= mip_response_[bar];
169
170 // set pulse properties like PE and amplitude
171 hit.setSampAbovePed(n_samp_above_ped);
172 hit.setSampAboveThr(n_samp_above_thr);
173 hit.setQ(tot_subtr_q);
174 hit.setAmplitude(max_q);
175 hit.setPE(pe);
176 hit.setHitQuality(is_clean);
177 hit.setQualityFlag(flag);
178 // set bar id. set moduleNB = 0
179 hit.setBarID(bar);
180 hit.setModuleID(0); // test beam
181 // the rest are a little ill-defined for now (PE-energy conversion not
182 // known/different between LYSO and plastic)
183 hit.setTime(-999); // maybe?
184 hit.setBeamEfrac(-1.);
185 hit.setEnergy(hit.getPE() * mev_per_mip / pe_per_mip);
186
187 // add hit
188 hits.push_back(hit);
189 } // over channels
190
191 // at end of event, write the collection of trigger scintillator hits.
192 event.add(output_collection_, hits);
193
194 return;
195}
196
197} // namespace trigscint
198
#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:42
Class which represents the process under execution.
Definition Process.h:36
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.
float getPE() const
Get the hit pe.
void setModuleID(const int moduleID)
Set hit module ID.
This class represents the linearised QIE output from the trigger scintillator, in charge (fC).
Organizes digis into TrigScintHits, based on linearized full event readout from test beam/test stand.
This class represents the linearised QIE output from the trigger scintillator, in charge (fC).
Definition TestBeamHit.h:24
void setQualityFlag(const uint flag)
Set hit data quality flag.
void setHitQuality(const int isClean)
Set whether hit has been checked for and passed quality criteria.
void setSampAbovePed(const int sampAbovePed)
Set number of samples above pedestal in pulse/hit.
void setQ(const float q)
Store total charge.
Definition TestBeamHit.h:73
void setSampAboveThr(const int sampAboveThr)
Set number of samples above threshold in pulse/hit.
void setPulseWidth(const int pulseWidth)
Set width used to integrate pulse/hit (in time samples)
void setPedestal(const float pedestal)
Set channel (linearized.
Definition TestBeamHit.h:51
void setEarlyPedestal(const float earlyPed)
Set channel (linearized.
Definition TestBeamHit.h:63
void setStartSample(const int startSample)
Store total charge.
Definition TestBeamHit.h:96