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