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>
25#include <Math/Vector3D.h>
47 m_aDigiHit(
"CsiDigiHits"),
48 m_calibConstants(16, 5),
49 m_noiseLevels(16, 0.25e-3),
74 B2DEBUG(100,
"Initializing ");
85 for (uint i = 0; i !=
m_LY.size(); ++i) {
95 for (
int i = 8; i < 16; i++) {
109 int m_currentEventNumber = eventMetaDataPtr->getEvent();
111 B2DEBUG(80,
"Digitingevent " << m_currentEventNumber);
120 for (
int i = 0 ; i < 16 ; i++) {
126 B2DEBUG(150,
"Looping over CsISimHits");
127 for (
int i = 0; i < hitNum; i++) {
136 ROOT::Math::XYZVector hitPos = aCsISimHit->
getPosition();
137 ROOT::Math::XYZVector cellPos = csip->
GetPosition(m_cellID);
140 double localPos = (15. - (hitPos - cellPos).Dot(
145 (0.0600 * localPos + (tof / CLHEP::ns)) * 1
E-9;
164 for (
int iCh = 0; iCh < 16; iCh++) {
170 B2DEBUG(140,
"Generating Time signal");
175 B2DEBUG(140,
"Launching Charge integration");
176 bool recordWaveform =
false;
179 recordWaveform =
true;
180 B2DEBUG(80,
"Recording WF");
214 uint32_t* _t, vector<uint16_t>* _Waveform,
215 vector<uint8_t>* _DPPCIBits,
int _Treshold,
216 double _TriggerHoldoff,
double _GateWidth,
217 double _GateOffset,
bool _recordTraces)
220 B2DEBUG(80,
"Arguments: " << &_u <<
", " << _NsamBL <<
", " << _BSL <<
", " << _Q <<
", " << _t
221 <<
", " << _Waveform <<
", " << _Treshold <<
", " << _TriggerHoldoff <<
", " << _GateWidth
222 <<
", " << _GateOffset <<
", " << _recordTraces);
228 TH1I h_trigger(
"h_trigger",
"Trigger", nSam, 0, nSam - 1);
229 TH1I h_gate(
"h_gate",
"Gate", nSam, 0, nSam - 1);
230 TH1I h_holdoff(
"h_holdoff",
"Holdoff", nSam, 0, nSam - 1);
231 TH1I h_baseline(
"h_baseline",
"Baseline", nSam, 0, nSam - 1);
232 TH1I h_charge(
"h_charge",
"Charge", nSam, 0, nSam - 1);
233 TH1F h_signal(
"h_signal",
"Continuous signal", nSam, 0, nSam - 1);
234 TH1I h_digsig(
"h_digsig",
"Digital signal", nSam, 0, nSam - 1);
237 int max_gated = (int) floor(_GateWidth /
m_dt);
238 int gate_offset = (int) floor(_GateOffset /
m_dt);
239 int max_holdoff = (int) floor(_TriggerHoldoff /
m_dt);
247 bool holdoff =
false;
249 bool trigger =
false;
253 int iFirstTrigger = 0;
254 list<int> baselineBuffer;
255 vector<int>::iterator it;
259 const double invMaxNavgBL = 1.0 / _NsamBL;
262 _Waveform->resize(nSam, 0);
263 _DPPCIBits->resize(nSam, 0);
265 B2DEBUG(140,
"Scanning vector: all should have nSam=" << nSam);
269 for (it = x.begin(); (it != x.end()); ++it, ++i) {
274 _Waveform->at(i) = *it;
275 _DPPCIBits->at(i) = trigger + (gate << 1) + (holdoff << 2) + (stop << 3);
279 h_trigger.Fill(i, (
int) trigger) ;
280 h_gate.Fill(i, (
int) gate) ;
281 h_holdoff.Fill(i, (
int) holdoff) ;
282 h_baseline.Fill(i, baseline) ;
283 h_charge.Fill(i, charge) ;
284 h_digsig.Fill(i, *it) ;
285 h_signal.Fill(i, _u.at(i)) ;
288 if (!gate && !holdoff) {
290 baselineBuffer.push_back(*it);
293 if ((i + 1) > _NsamBL) {
294 baselineBuffer.pop_front();
295 invNavgBL = invMaxNavgBL;
297 invNavgBL = (1.0 / i);
301 for (list<int>::iterator itbl = baselineBuffer.begin(); itbl != baselineBuffer.end(); ++itbl)
302 tempBaseline += (
float) * itbl;
304 tempBaseline *= invNavgBL;
306 baseline = (int) round(tempBaseline);
308 trigger = (*it - baseline) > _Treshold;
311 if (trigger && !iFirstTrigger)
317 charge += (*(it - gate_offset) - baseline);
329 holdoff = trigger || (holdoff && (n_holdoff < max_holdoff));
330 gate = trigger || (gate && (n_gated < max_gated));
332 stop = iFirstTrigger && !gate && !holdoff;
337 *_t = (uint)(iFirstTrigger + 2.0 * (gRandom->Rndm() - 0.5));
339 if (not(_recordTraces)) {
349 vector<int> output(_v.size(), 0);
350 double invLSB = 1.0 / _LSB;
353 for (Signal::iterator it = _v.begin() ; it != _v.end(); ++it, ++i) {
354 output.at(i) = (int) round(*it * invLSB);
364 double invdt = 1.0 / _dt;
368 double sumEnergies = 0.0;
370 for (Signal::iterator it = _times.begin() ; it != _times.end(); ++it) {
378 Signal edepos(_nsam, 0.0);
381 int ioffset = floor(_nsam * 0.25);
382 B2DEBUG(150,
"Filling edepos vector. Container length is " << _nsam);
384 for (Signal::iterator it = _times.begin() ; it != _times.end(); ++it, ++i) {
385 sumEnergies += _energies.at(i);
387 int timeIndex = ((int)(*it - t0) * invdt + ioffset);
388 if ((timeIndex - 1) > (int) edepos.size()) {
389 B2WARNING(
" genTimeSignal: TimeIndex greater than length of signal container. Skipping deposit of " << _energies.at(i) <<
"GeV");
391 edepos.at(timeIndex) += _energies.at(i);
395 B2DEBUG(80,
"Generating time responses for channel " << _iChannel);
396 B2DEBUG(80,
" Fast time constant " <<
m_tFast[_iChannel]);
397 B2DEBUG(80,
" Slow time constant " <<
m_tSlow[_iChannel]);
412 for (Signal::iterator it = Qcathode.begin() ; it != Qcathode.end(); ++it, ++j)
413 *it += QcathodeF.at(j);
418 B2DEBUG(150,
"Adding noise. Container length is " << Vanode.size());
425 for (i = 1; i < _nsam; i++)
426 t.at(i) = t.at(i - 1) + _dt;
428 TGraph gPlot1(_nsam, &t[0], &edepos[0]);
429 gPlot1.SaveAs(
"EdeposOut.root");
431 TGraph gPlot2(_nsam, &t[0], &Qcathode[0]);
432 gPlot2.SaveAs(
"QOut.root");
434 TGraph gPlot3(_nsam, &t[0], &Vanode[0]);
435 gPlot3.SaveAs(
"VOut.root");
446 for (Signal::iterator it = y->begin() ; it != y->end(); ++it)
447 *it += _offset + gRandom->Gaus(0, _rms);
473 B2DEBUG(80,
"Generating 1st order response with arguments");
474 B2DEBUG(80,
" _gain: " << _gain);
475 B2DEBUG(80,
" length(_u): " << _u.size());
476 B2DEBUG(80,
" _y0: " << _y0);
477 B2DEBUG(80,
" _dt: " << _dt);
478 B2DEBUG(80,
" _tau: " << _tau);
479 B2DEBUG(80,
" _delay: " << _delay);
490 static const double invSix = 1.0 / 6.0;
491 double invtau = 1.0 / _tau;
495 int n_delay = (int) round(_delay / _dt);
496 Signal::iterator it = _u.begin();
497 double _u_0 = _u.front();
498 _u.insert(it, n_delay, _u_0);
502 for (
int i = 0, j = 0; i < (n - 1); i++) {
504 k[0] =
f(i, _u[i], _u[j], y[i], invtau);
505 k[1] =
f(i + 0.5, _u[i], _u[j], y[i] + 0.5 * _dt * k[0], invtau);
506 k[2] =
f(i + 0.5, _u[i], _u[j], y[i] + 0.5 * _dt * k[1], invtau);
507 k[3] =
f(j, _u[i], _u[j], y[i] + _dt * k[2], invtau);
509 y.push_back(y[i] + _dt * invSix * (k[0] + 2 * k[1] + 2 * k[2] + k[3]));
515 for (Signal::iterator it2 = y.begin() ; it2 != y.end(); ++it2)
526 double u = u_i * (fi - floor(fi)) + u_j * (ceil(fi) - fi);
528 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.
ROOT::Math::XYZVector 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)
CsIDigitizerModule()
Constructor: Sets the description, the properties and the parameters of the module.
uint32_t m_Charge
Integrated Charge.
std::vector< double > m_tFast
Fast time constant for each channel (ns)
The Class for CSI Geometry Parameters.
ROOT::Math::XYZVector GetOrientation(int cid)
Get the orientation of the crystal.
void Print(const int cid, int debuglevel=80)
Print crystal information.
ROOT::Math::XYZVector GetPosition(int cid)
Get the position of the crystal.
static CsiGeometryPar * Instance()
Static method to get a reference to the CsiGeometryPar instance.
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.