LDMX Software
Public Member Functions | Private Attributes | List of all members
trigscint::EventReadoutProducer Class Reference

Linearizes ADC info to charge, calculates channel pedestal and noise levels (in charge) More...

#include <EventReadoutProducer.h>

Public Member Functions

 EventReadoutProducer (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &parameters) override
 Callback for the processor to configure itself from the given set of parameters.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void beforeNewRun (ldmx::RunHeader &header)
 Handle allowing producers to modify run headers before the run begins.
 
- Public Member Functions inherited from framework::EventProcessor
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()
 Class destructor.
 
virtual void onNewRun (const ldmx::RunHeader &runHeader)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &eventFile)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &eventFile)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
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

bool verbose_ {false}
 Class to set the verbosity level.
 
std::string inputCollection_
 Name of the input collection containing the sim hits.
 
std::string inputPassName_
 Name of the pass that the input collection is on (empty string means take any pass)
 
std::string outputCollection_
 Name of the output collection that will be used to stored the digitized trigger scintillator hits.
 
int nPedSamples_ {5}
 Number of initial time samples averaged over in the pedestal calculation.
 
int timeShift_ {5}
 Number of time samples to shift readout by, to align fibers if there is an offset.
 
int fiberToShift_ {1}
 Which of the fibers to set the time shift for (0 or 1)
 

Additional Inherited Members

- Static Public Member Functions inherited from framework::EventProcessor
static void declare (const std::string &classname, int classtype, EventProcessorMaker *)
 Internal function which is part of the PluginFactory machinery.
 
- Static Public Attributes inherited from framework::Producer
static const int CLASSTYPE {1}
 Constant used to track EventProcessor types by the PluginFactory.
 
- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramHelper histograms_
 Interface class for making and filling histograms.
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger theLog_
 The logger for this EventProcessor.
 

Detailed Description

Linearizes ADC info to charge, calculates channel pedestal and noise levels (in charge)

Definition at line 34 of file EventReadoutProducer.h.

Constructor & Destructor Documentation

◆ EventReadoutProducer()

trigscint::EventReadoutProducer::EventReadoutProducer ( const std::string &  name,
framework::Process process 
)

Definition at line 9 of file EventReadoutProducer.cxx.

11 : Producer(name, process) {}
Producer(const std::string &name, Process &process)
Class constructor.

Member Function Documentation

◆ configure()

void trigscint::EventReadoutProducer::configure ( framework::config::Parameters parameters)
overridevirtual

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

Parameters
parametersParameterSet for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 13 of file EventReadoutProducer.cxx.

14 {
15 // Configure this instance of the producer
16 inputCollection_ = parameters.getParameter<std::string>("input_collection");
17 inputPassName_ = parameters.getParameter<std::string>("input_pass_name");
18 outputCollection_ = parameters.getParameter<std::string>("output_collection");
19 nPedSamples_ = parameters.getParameter<int>("number_pedestal_samples");
20 timeShift_ = parameters.getParameter<int>("time_shift");
21 fiberToShift_ = parameters.getParameter<int>("fiber_to_shift");
22 verbose_ = parameters.getParameter<bool>("verbose");
23
24 ldmx_log(debug) << "In configure, got parameters:"
25 << "\noutput_collection = " << outputCollection_
26 << "\ninput_collection = " << inputCollection_
27 << "\ninput_pass_name = " << inputPassName_
28 << "\nnumber_pedestal_samples = " << nPedSamples_
29 << "\ntime_shift = " << timeShift_
30 << "\nfiber_to_shift = " << fiberToShift_
31 << "\nverbose = " << verbose_;
32}
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
int fiberToShift_
Which of the fibers to set the time shift for (0 or 1)
bool verbose_
Class to set the verbosity level.
std::string outputCollection_
Name of the output collection that will be used to stored the digitized trigger scintillator hits.
int nPedSamples_
Number of initial time samples averaged over in the pedestal calculation.
std::string inputCollection_
Name of the input collection containing the sim hits.
int timeShift_
Number of time samples to shift readout by, to align fibers if there is an offset.
std::string inputPassName_
Name of the pass that the input collection is on (empty string means take any pass)

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

◆ produce()

void trigscint::EventReadoutProducer::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 34 of file EventReadoutProducer.cxx.

34 {
35 // initialize QIE object for linearizing ADCs
36 SimQIE qie;
37
38 const auto digis{event.getCollection<trigscint::TrigScintQIEDigis>(
40
41 std::vector<trigscint::EventReadout> channelReadoutEvents;
42 for (const auto &digi : digis) {
44 auto adc{digi.getADC()};
45 auto tdc{digi.getTDC()};
46
47 // copy over from qie digi for convenience
48 outEvent.setChanID(digi.getChanID());
49 outEvent.setElecID(digi.getElecID());
50 outEvent.setTimeSinceSpill(digi.getTimeSinceSpill());
51 // elecID increases monotonically with 8 channels per fiber
52 outEvent.setFiberNb(digi.getElecID() / 8);
53 if (outEvent.getFiberNb() == fiberToShift_)
54 outEvent.setTimeOffset(timeShift_);
55
56 outEvent.setADC(adc);
57 outEvent.setTDC(tdc);
58 std::vector<float> charge;
59 std::vector<float> chargeErr;
60
61 float avgQ = 0;
62 float totPosQ = 0;
63 int iS = 0;
64 int nPos = 0;
65 float earlyPed = 0;
66 for (auto &val : adc) {
67 float Q = qie.ADC2Q(val);
68 charge.push_back(Q);
69 chargeErr.push_back(qie.QErr(Q));
70 avgQ += Q; // charge.back();
71 if (Q > 0) {
72 totPosQ += Q;
73 nPos++;
74 }
75 if (verbose_)
76 ldmx_log(debug) << "got adc value " << val << " and charge "
77 << Q; // qie.ADC2Q(val);
78 if (iS < nPedSamples_) earlyPed += Q;
79 iS++;
80 }
81 outEvent.setQ(charge); // set in proper order before sorting
82 outEvent.setQError(chargeErr); // set in proper order before sorting
83 earlyPed /= nPedSamples_;
84 outEvent.setEarlyPedestal(earlyPed);
85
86 // oscillation check. for this the pulse charge needs to be in order, so set
87 // this up now the period is 4. ansatz: an oscillation is a repeated shape.
88 // normalize to maxq=1, in every interval of 4 samples if after
89 // normalization the same numbers are repeated, it's an oscillation edge
90 // case: multiple single PE peaks with that repetition. we probably don't
91 // need to keep those anyway
92 if (verbose_) ldmx_log(debug) << "going into oscillations check ";
93 std::vector<float> chargeCheck = {NULL};
94 float minCharge =
95 10; // no point in looking at oscillations just around the pedestal.
96 // nearest edge is 10.35 fC //ADC=0 corresponds to -16 fC.
97 for (int i = 3; i < charge.size() - 4; i++) {
98 float maxSamp = minCharge;
99 for (int iQ = 0; iQ < 4; iQ++) { // find the local max in the 4 samples
100 // ldmx_log(debug) << "got charge " << charge[i+iQ];
101 if (charge[i + iQ] > maxSamp) maxSamp = charge[i + iQ];
102 }
103 if (verbose_) ldmx_log(debug) << "got max charge " << maxSamp;
104 for (int iQ = 0; iQ < 4;
105 iQ++) // store the locally normalized numbers. even if the period is
106 // 5 this should work for a while
107 chargeCheck.push_back(charge[i + iQ] / maxSamp);
108 i += 3; // to increment by 4, do 3 here and 1 in the loop
109 }
110
111 // now calculate the pedestal as the average of the middle half of the
112 // sorted vector
113 float ped = 0;
114 std::sort(charge.begin(), charge.end());
115 int pedLength = (int)charge.size() /
116 5; // actually pulse can be up to 12 samples = 2/5*30
117 int pedOffset = 2; // but still skip the lowest (and highest) few
118 // for (int i = pedLength; i < 3*pedLength ; i++) { //use 2nd and third 5th
119 for (int i = pedOffset; i < 2 * pedLength + pedOffset;
120 i++) { // use 1st and 2nd 5th
121 ped += charge[i];
122 }
123 ped /= 2 * pedLength;
124 // median: technically only true for odd number of elements but good enough
125 float medQ = charge[(int)charge.size() / 2];
126 float minQ = charge[0];
127 float maxQ = charge[charge.size() - 1];
128
129 outEvent.setTotQ(totPosQ); //-nPos*ped); //store (event) ped subtracted
130 // total charge, before dividing by N -->
131 // actually, ped subtraction makes it confusing
132 // outEvent.setTotQ(totPosQ-adc.size()*ped); //store (event) ped subtracted
133 // total charge, before dividing by N
134 // outEvent.setTotQ(avgQ-adc.size()*ped);
136 avgQ /= adc.size();
137 outEvent.setPedestal(ped);
138 outEvent.setAvgQ(avgQ);
139 outEvent.setMedQ(medQ);
140 outEvent.setMinQ(minQ);
141 outEvent.setMaxQ(maxQ);
142
143 // and the noise as the RMSE of that, same interval as pedestal
144 float diffSq = 0;
145 // for (int i = pedLength; i < 3*pedLength ; i++) {
146 for (int i = pedOffset; i < 2 * pedLength + pedOffset; i++) {
147 diffSq += (charge[i] - ped) * (charge[i] - ped);
148 }
149 diffSq /= 2 * pedLength; // adc.size();
150 outEvent.setNoise(sqrt(diffSq));
151
152 // oscillation check
153 uint flagOscillation = 0;
154 // no need to run tedious oscillation check for all-neg channels
155 if (maxQ > minCharge) {
156 int maxID = 0;
157 // find the first occurence of a local max
158 for (int i = 0; i < chargeCheck.size() - 4; i++) {
159 if (chargeCheck[i] ==
160 1) { // an actual local max has been normalised by its own value
161 maxID = i;
162 // ldmx_log(debug) << "storing max index " <<maxID <<"
163 // and size of vector is " << chargeCheck.size()-4;
164 break;
165 }
166 }
167 int lastMatchSample = 0;
168 // start from local max
169 bool doBreak = false;
170 for (int i = maxID; i < chargeCheck.size() - 4; i++) {
171 if (verbose_)
172 ldmx_log(debug) << "Checking how many matching groups of four we can "
173 "find, starting at index "
174 << i;
175
176 for (int iQ = 0; iQ < 4; iQ++) { // check if they are consistently
177 // close
178 if (verbose_)
179 ldmx_log(debug)
180 << "Comparing " << chargeCheck[i + iQ] << " (sample " << i + iQ
181 << ") to " << chargeCheck[i + 4 + iQ] << " (sample "
182 << i + 4 + iQ << "), ratio is "
183 << chargeCheck[i + iQ] / chargeCheck[i + 4 + iQ];
184 // we can be generous in these crietira since we will require an
185 // unbroken suite of 8 matches to call it oscillation
186 if (fabs(chargeCheck[i + iQ] / chargeCheck[i + 4 + iQ] - 1) <
187 0.5 || // need this tolerance to be kind of large, most
188 // actual peaks won't pass it by far anyway.
189 (chargeCheck[i + 4 + iQ] < 0.01 &&
190 fabs(chargeCheck[i + iQ] / chargeCheck[i + 4 + iQ]) <
191 5)) // for very small numbers, one ADC difference can be a
192 // factor 3 so add some margin
193 lastMatchSample = i + iQ;
194 else {
195 if (verbose_)
196 ldmx_log(debug)
197 << "Oscillation check for channel " << digi.getChanID()
198 << " breaking at time sample " << i + iQ;
199 doBreak = true; // break outer loop
200 break; // break this loop
201 }
202 }
203 if (doBreak) {
204 break;
205 }
206 if (verbose_)
207 ldmx_log(debug) << "Current lastMatchSample " << lastMatchSample;
208 if (lastMatchSample - maxID >=
209 2 * 4) { // we had at least a couple of oscillations (2nd period
210 // was fully matched by third)
211 flagOscillation = 1; // there is another check possible later too,
212 // commented for now
213 break; // we've seen what we need to see
214 }
215 i += 3;
216 }
217 } // if positive maxQ
218
219 // //use the top and bottom ends of the sorted q as another oscillation
220 // catcher: we don't expect that the top values will be high and basically
221 // identical unless they are from an oscillation
222 int nHigh = 0;
223 int quartLength = (int)charge.size() / 4;
224 for (int i = 4 * quartLength - 2; i >= 3 * quartLength;
225 i--) { // maxQ is already at last index
226 if (charge[i] / maxQ > 0.66) nHigh++;
227 }
228
229 /* used to be: >0.9, > 0.25. But this really killed MC pulses which
230 all end up in 0.90-0.94, and somewhere >0.05 (at least >0.15)
231 */
232 uint flagSpike = (maxQ / outEvent.getTotQ() > 0.95) ||
233 (charge[charge.size() - 2] / maxQ <
234 0.05); // skip "unnaturally" narrow hits (all charge in
235 // one sample or huge drop to second highest)
236 uint flagPlateau =
237 (ped > 15 || nHigh >= 5); //( fabs(ped) > 15 ); //threshold // //skip
238 // events that have strange plateaus
239 uint flagLongPulse =
240 0; // easier to deal with in hit reconstruction directly. copy channel
241 // flags to hit flags and add this one there
242 uint flagNoise =
243 (outEvent.getNoise() > 3.5 ||
244 outEvent.getNoise() == 0); // =0 is typically from funky events but
245 // could be too harsh maybe
246 /* //let this wait for now
247 //if we have many high counts, a small event pedestal (where they weren't
248 included), and an avgQ ~ maxQ/nHigh, then this is an oscillation if (
249 (quartLength-nHigh<2 && ped<10) || fabs( maxQ/(avgQ*nHigh)-1 ) <0.1 )
250 flagOscillation=1;
251 */
252
253 /* //this seems to not catch what we want it to
254if ( fabs(chan.getPedestal()) < 15 //threshold // //skip events that have
255strange plateaus
256 // && (chan.getAvgQ()/chan.getPedestal()<0.8) //skip
257events that have strange oscillations
258 && 1 < nSampAboveThr && nSampAboveThr < 10 ) // skip one-time sample
259flips and long weird pulses
260 */
261 uint flag = flagSpike + 2 * flagPlateau + 4 * flagLongPulse +
262 8 * flagOscillation + 16 * flagNoise;
263 ldmx_log(debug)
264 << "Got quality flag " << flag
265 << " made up of (spike/plateau/long pulse/oscillation/noise) "
266 << flagSpike << "+" << flagPlateau << "+" << flagLongPulse << "+"
267 << flagOscillation << "+" << flagNoise;
268 outEvent.setQualityFlag(flag);
269
270 // if (ped > 15 )
271 // continue;
272 ldmx_log(debug) << "In event " << event.getEventHeader().getEventNumber()
273 << ", set pedestal = " << outEvent.getPedestal()
274 << // ped <<
275 " fC, noise = " << outEvent.getNoise() << " fC for channel "
276 << outEvent.getChanID();
277
278 channelReadoutEvents.push_back(outEvent);
279 }
280 // Create the container to hold the
281 // digitized trigger scintillator hits.
282
283 event.add(outputCollection_, channelReadoutEvents);
284 ldmx_log(debug) << "\n";
285}
This class represents the linearised QIE output from the trigger scintillator, in charge (fC).
void setMedQ(const float medQ)
Set channel (linearized, charge-equiv) median charge.
void setFiberNb(const int fiberNb)
Set channel readout fiber number.
void setTimeOffset(const int timeOffset)
Set channel readout itme offset (in units of samples)
float getPedestal() const
Get the pedestal.
void setMinQ(const float minQ)
Set channel (linearized, charge-equiv) minimum charge.
void setQError(const std::vector< float > qErr)
Store charge quantization errors of all time samples.
void setNoise(const float noise)
Set channel (linearized, charge-equiv) noise.
float getNoise() const
Get the channel noise.
void setTotQ(const float totQ)
Set channel (linearized, charge-equiv) average charge.
float getTotQ() const
Get the channel totQ.
void setQualityFlag(const uint flag)
Set channel data quality flag.
void setPedestal(const float pedestal)
Set channel (linearized.
void setAvgQ(const float avgQ)
Set channel (linearized, charge-equiv) average charge.
void setMaxQ(const float maxQ)
Set channel (linearized, charge-equiv) maximum charge.
int getFiberNb() const
Get the channel fiberNb.
void setQ(const std::vector< float > q)
Store charges of all time samples.
void setEarlyPedestal(const float earlyPed)
Set channel (linearized.
class for storing QIE output
std::vector< int > getADC() const
Get ADCs of all time samples.
void setTDC(const std::vector< int > tdc)
Store tdcs of all time samples.
void setChanID(const int chanid)
Store the channel ID.
void setTimeSinceSpill(const uint32_t timeSpill)
Store the event time since spill counter.
int getChanID() const
Get channel ID.
void setElecID(const int elecid)
Store the electronics ID.
void setADC(const std::vector< int > adc)
Store adcs of all time samples.

References trigscint::SimQIE::ADC2Q(), trigscint::TrigScintQIEDigis::getADC(), trigscint::TrigScintQIEDigis::getChanID(), trigscint::EventReadout::getFiberNb(), trigscint::EventReadout::getNoise(), trigscint::EventReadout::getPedestal(), trigscint::EventReadout::getTotQ(), trigscint::SimQIE::QErr(), trigscint::TrigScintQIEDigis::setADC(), trigscint::EventReadout::setAvgQ(), trigscint::TrigScintQIEDigis::setChanID(), trigscint::EventReadout::setEarlyPedestal(), trigscint::TrigScintQIEDigis::setElecID(), trigscint::EventReadout::setFiberNb(), trigscint::EventReadout::setMaxQ(), trigscint::EventReadout::setMedQ(), trigscint::EventReadout::setMinQ(), trigscint::EventReadout::setNoise(), trigscint::EventReadout::setPedestal(), trigscint::EventReadout::setQ(), trigscint::EventReadout::setQError(), trigscint::EventReadout::setQualityFlag(), trigscint::TrigScintQIEDigis::setTDC(), trigscint::EventReadout::setTimeOffset(), trigscint::TrigScintQIEDigis::setTimeSinceSpill(), and trigscint::EventReadout::setTotQ().

Member Data Documentation

◆ fiberToShift_

int trigscint::EventReadoutProducer::fiberToShift_ {1}
private

Which of the fibers to set the time shift for (0 or 1)

Definition at line 74 of file EventReadoutProducer.h.

74{1};

◆ inputCollection_

std::string trigscint::EventReadoutProducer::inputCollection_
private

Name of the input collection containing the sim hits.

Definition at line 56 of file EventReadoutProducer.h.

◆ inputPassName_

std::string trigscint::EventReadoutProducer::inputPassName_
private

Name of the pass that the input collection is on (empty string means take any pass)

Definition at line 60 of file EventReadoutProducer.h.

◆ nPedSamples_

int trigscint::EventReadoutProducer::nPedSamples_ {5}
private

Number of initial time samples averaged over in the pedestal calculation.

Definition at line 67 of file EventReadoutProducer.h.

67{5};

◆ outputCollection_

std::string trigscint::EventReadoutProducer::outputCollection_
private

Name of the output collection that will be used to stored the digitized trigger scintillator hits.

Definition at line 64 of file EventReadoutProducer.h.

◆ timeShift_

int trigscint::EventReadoutProducer::timeShift_ {5}
private

Number of time samples to shift readout by, to align fibers if there is an offset.

Definition at line 71 of file EventReadoutProducer.h.

71{5};

◆ verbose_

bool trigscint::EventReadoutProducer::verbose_ {false}
private

Class to set the verbosity level.

Definition at line 53 of file EventReadoutProducer.h.

53{false};

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