10 #include <beast/csi/modules/CsIDigitizerModule.h>
13 #include <beast/csi/geometry/CsiGeometryPar.h>
16 #include <framework/core/RandomNumbers.h>
17 #include <framework/dataobjects/EventMetaData.h>
18 #include <framework/datastore/StoreObjPtr.h>
43 CsIDigitizerModule::CsIDigitizerModule() :
Module(), m_hitNum(0),
46 m_aDigiHit(
"CsiDigiHits"),
47 m_calibConstants(16, 5),
48 m_noiseLevels(16, 0.25e-3),
73 B2DEBUG(100,
"Initializing ");
84 for (uint i = 0; i !=
m_LY.size(); ++i) {
94 for (
int i = 8; i < 16; i++) {
108 int m_currentEventNumber = eventMetaDataPtr->getEvent();
110 B2DEBUG(80,
"Digitingevent " << m_currentEventNumber);
119 for (
int i = 0 ; i < 16 ; i++) {
125 B2DEBUG(150,
"Looping over CsISimHits");
126 for (
int i = 0; i < hitNum; i++) {
139 double localPos = (15. - (hitPos - cellPos) *
144 (0.0600 * localPos + (tof / CLHEP::ns)) * 1
E-9;
163 for (
int iCh = 0; iCh < 16; iCh++) {
169 B2DEBUG(140,
"Generating Time signal");
174 B2DEBUG(140,
"Launching Charge integration");
175 bool recordWaveform =
false;
178 recordWaveform =
true;
179 B2DEBUG(80,
"Recording WF");
213 uint32_t* _t, vector<uint16_t>* _Waveform,
214 vector<uint8_t>* _DPPCIBits,
int _Treshold,
215 double _TriggerHoldoff,
double _GateWidth,
216 double _GateOffset,
bool _recordTraces)
219 B2DEBUG(80,
"Arguments: " << &_u <<
", " << _NsamBL <<
", " << _BSL <<
", " << _Q <<
", " << _t
220 <<
", " << _Waveform <<
", " << _Treshold <<
", " << _TriggerHoldoff <<
", " << _GateWidth
221 <<
", " << _GateOffset <<
", " << _recordTraces);
227 TH1I h_trigger(
"h_trigger",
"Trigger", nSam, 0, nSam - 1);
228 TH1I h_gate(
"h_gate",
"Gate", nSam, 0, nSam - 1);
229 TH1I h_holdoff(
"h_holdoff",
"Holdoff", nSam, 0, nSam - 1);
230 TH1I h_baseline(
"h_baseline",
"Baseline", nSam, 0, nSam - 1);
231 TH1I h_charge(
"h_charge",
"Charge", nSam, 0, nSam - 1);
232 TH1F h_signal(
"h_signal",
"Continuous signal", nSam, 0, nSam - 1);
233 TH1I h_digsig(
"h_digsig",
"Digital signal", nSam, 0, nSam - 1);
236 int max_gated = (int) floor(_GateWidth /
m_dt);
237 int gate_offset = (int) floor(_GateOffset /
m_dt);
238 int max_holdoff = (int) floor(_TriggerHoldoff /
m_dt);
246 bool holdoff =
false;
248 bool trigger =
false;
252 int iFirstTrigger = 0;
253 list<int> baselineBuffer;
254 vector<int>::iterator it;
258 const double invMaxNavgBL = 1.0 / _NsamBL;
261 _Waveform->resize(nSam, 0);
262 _DPPCIBits->resize(nSam, 0);
264 B2DEBUG(140,
"Scanning vector: all should have nSam=" << nSam);
268 for (it = x.begin(); (it != x.end()); ++it, ++i) {
273 _Waveform->at(i) = *it;
274 _DPPCIBits->at(i) = trigger + (gate << 1) + (holdoff << 2) + (stop << 3);
278 h_trigger.Fill(i, (
int) trigger) ;
279 h_gate.Fill(i, (
int) gate) ;
280 h_holdoff.Fill(i, (
int) holdoff) ;
281 h_baseline.Fill(i, baseline) ;
282 h_charge.Fill(i, charge) ;
283 h_digsig.Fill(i, *it) ;
284 h_signal.Fill(i, _u.at(i)) ;
287 if (!gate && !holdoff) {
289 baselineBuffer.push_back(*it);
292 if ((i + 1) > _NsamBL) {
293 baselineBuffer.pop_front();
294 invNavgBL = invMaxNavgBL;
296 invNavgBL = (1.0 / i);
300 for (list<int>::iterator itbl = baselineBuffer.begin(); itbl != baselineBuffer.end(); ++itbl)
301 tempBaseline += (
float) * itbl;
303 tempBaseline *= invNavgBL;
305 baseline = (int) round(tempBaseline);
307 trigger = (*it - baseline) > _Treshold;
310 if (trigger && !iFirstTrigger)
316 charge += (*(it - gate_offset) - baseline);
328 holdoff = trigger || (holdoff && (n_holdoff < max_holdoff));
329 gate = trigger || (gate && (n_gated < max_gated));
331 stop = iFirstTrigger && !gate && !holdoff;
336 *_t = (uint)(iFirstTrigger + 2.0 * (gRandom->Rndm() - 0.5));
338 if (not(_recordTraces)) {
348 vector<int> output(_v.size(), 0);
349 double invLSB = 1.0 / _LSB;
352 for (Signal::iterator it = _v.begin() ; it != _v.end(); ++it, ++i) {
353 output.at(i) = (int) round(*it * invLSB);
363 double invdt = 1.0 / _dt;
367 double sumEnergies = 0.0;
369 for (Signal::iterator it = _times.begin() ; it != _times.end(); ++it) {
377 Signal edepos(_nsam, 0.0);
380 int ioffset = floor(_nsam * 0.25);
381 B2DEBUG(150,
"Filling edepos vector. Container length is " << _nsam);
383 for (Signal::iterator it = _times.begin() ; it != _times.end(); ++it, ++i) {
384 sumEnergies += _energies.at(i);
386 int timeIndex = ((int)(*it - t0) * invdt + ioffset);
387 if ((timeIndex - 1) > (int) edepos.size()) {
388 B2WARNING(
" genTimeSignal: TimeIndex greater than length of signal container. Skipping deposit of " << _energies.at(i) <<
"GeV");
390 edepos.at(timeIndex) += _energies.at(i);
394 B2DEBUG(80,
"Generating time responses for channel " << _iChannel);
395 B2DEBUG(80,
" Fast time constant " <<
m_tFast[_iChannel]);
396 B2DEBUG(80,
" Slow time constant " <<
m_tSlow[_iChannel]);
411 for (Signal::iterator it = Qcathode.begin() ; it != Qcathode.end(); ++it, ++j)
412 *it += QcathodeF.at(j);
417 B2DEBUG(150,
"Adding noise. Container length is " << Vanode.size());
424 for (i = 1; i < _nsam; i++)
425 t.at(i) = t.at(i - 1) + _dt;
427 TGraph gPlot1(_nsam, &t[0], &edepos[0]);
428 gPlot1.SaveAs(
"EdeposOut.root");
430 TGraph gPlot2(_nsam, &t[0], &Qcathode[0]);
431 gPlot2.SaveAs(
"QOut.root");
433 TGraph gPlot3(_nsam, &t[0], &Vanode[0]);
434 gPlot3.SaveAs(
"VOut.root");
445 for (Signal::iterator it = y->begin() ; it != y->end(); ++it)
446 *it += _offset + gRandom->Gaus(0, _rms);
472 B2DEBUG(80,
"Generating 1st order response with arguments");
473 B2DEBUG(80,
" _gain: " << _gain);
474 B2DEBUG(80,
" length(_u): " << _u.size());
475 B2DEBUG(80,
" _y0: " << _y0);
476 B2DEBUG(80,
" _dt: " << _dt);
477 B2DEBUG(80,
" _tau: " << _tau);
478 B2DEBUG(80,
" _delay: " << _delay);
489 static const double invSix = 1.0 / 6.0;
490 double invtau = 1.0 / _tau;
494 int n_delay = (int) round(_delay / _dt);
495 Signal::iterator it = _u.begin();
496 double _u_0 = _u.front();
497 _u.insert(it, n_delay, _u_0);
501 for (
int i = 0, j = 0; i < (n - 1); i++) {
503 k[0] =
f(i, _u[i], _u[j], y[i], invtau);
504 k[1] =
f(i + 0.5, _u[i], _u[j], y[i] + 0.5 * _dt * k[0], invtau);
505 k[2] =
f(i + 0.5, _u[i], _u[j], y[i] + 0.5 * _dt * k[1], invtau);
506 k[3] =
f(j, _u[i], _u[j], y[i] + _dt * k[2], invtau);
508 y.push_back(y[i] + _dt * invSix * (k[0] + 2 * k[1] + 2 * k[2] + k[3]));
514 for (Signal::iterator it2 = y.begin() ; it2 != y.end(); ++it2)
525 double u = u_i * (fi - floor(fi)) + u_j * (ceil(fi) - fi);
527 return u - invtau * y;
ClassCsiSimHit - Geant4 simulated hits in CsI crystals in BEAST.
int getCellId() const
Get Cell ID.
double getFlightTime() const
Get Flight time from IP.
double getEnergyDep() const
Get Deposit energy.
TVector3 getPosition() const
Get Position.
void setDescription(const std::string &description)
Sets the description of the module.
Type-safe access to single objects in the data store.
uint16_t m_Baseline
Baseline (pedestal) frozen during charge integration.
int addNoise(Signal *y, double _rms, double _offset)
Adds noise to the signal.
Signal m_SimHitEdeps[16]
Array of signals (each corresponding to one channel)
double m_Resolution
Parameter: Resolution (in mV) of the ACD.
DigitalSignal doDigitization(Signal _v, double _LSB)
Digitizes the signal the signal.
double m_TrueEdep
Sum of the MC (true) deposited energies in the event-channel.
std::vector< double > m_noiseLevels
Noise level for each channel (in V)
std::vector< uint16_t > m_Waveform
Saved waveform.
virtual void initialize() override
Register input and output data.
double f(double fi, double u_i, double u_j, double y, double invtau)
This returns the RHS of first order differential equation.
const double m_Zl
Line impedance of the analog chain (to get voltage from anode current)
int m_hitNum
index of csiHit
virtual void event() override
Each event This is where the actual digitization is done, and the hits are written to the DataStore.
Signal firstOrderResponse(double _gain, Signal _u, double _y0, double _dt, double _tSlow, double _delay)
Calculates the time response of a first order system (such as crystal, PMT, etc)
virtual void endRun() override
Clean up.
Signal genTimeSignal(double _energy, double _timeAvg, double _timeRMS, int iChannel, bool _save=0)
Generates a time signal for a mean energy deposit The energy deposit is modelled at a Gaussian whose ...
StoreArray< CsiSimHit > m_aSimHit
Each simulated particle in the crystal.
int m_nWFcounter
Counter for the number of waveforms to save.
virtual void terminate() override
Final clean up.
double m_dt
Time interval (in ns) (calculated from m_SampleRate.
std::vector< double > m_LCE
Light collection efficiency for each channel.
void setnSamples(int nsamples)
Sets the number of points in the waveforms arrays.
const double m_tTransitPMT
48Mean transit time of the PMT signal (in ns)
std::vector< double > m_LY
Light yield for each channel (gamma per GeV)
uint32_t m_Time
Trigger Time.
int m_nSamples
Number of points requested in the waveform arrays.
virtual ~CsIDigitizerModule()
Default destructor.
virtual void beginRun() override
To do before each runs.
std::vector< double > m_PmtGain
PMT gain for each channel.
std::vector< double > m_PmtQE
PMT quantum efficiency for each channel.
std::vector< uint8_t > m_DPPCIBits
status of the DPP-CI
const double m_tRisePMT
2.6 Rise time of the PMT signal (in ns)
std::vector< double > m_tSlow
Slow time constant for each channel (ns)
std::vector< double > m_tRatio
Ratio fast light / slow light for each channel.
StoreArray< CsiDigiHit > m_aDigiHit
Output: a digitized hit.
uint16_t doChargeIntegration(Signal _u, int _NsamBL, uint16_t *BSL, uint32_t *Q, uint32_t *t, std::vector< uint16_t > *_Waveform, std::vector< uint8_t > *_DPPCIBits, int _Treshold, double _TriggerHoldoff=0.0, double _GateWidth=320.0, double _GateOffset=40.0, bool _recordTraces=false)
Realizes the charge integration of the input signal.
double m_SampleRate
Parameter: Sample rate (in samples/sec) of the ADC.
int m_nWaveforms
Number of waveforms to save.
Signal m_SimHitTimes[16]
Array of signals (each corresponding to one channel)
uint32_t m_Charge
Integrated Charge.
std::vector< double > m_tFast
Fast time constant for each channel (ns)
The Class for CSI Geometry Parameters.
void Print(const int cid, int debuglevel=80)
Print crystal information.
TVector3 GetOrientationTV3(int cid)
Get the orientation of the crystal in a root TVector3.
static CsiGeometryPar * Instance()
Static method to get a reference to the CsiGeometryPar instance.
TVector3 GetPositionTV3(int cid)
Get the position of the crystal in a root TVector3.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
std::vector< double > Signal
Designed to hold a "continuous" (in time and amplitude) signal
Abstract base class for different kinds of events.