1#ifndef __JDETECTOR__JPMTANALOGUESIGNALPROCESSOR__
2#define __JDETECTOR__JPMTANALOGUESIGNALPROCESSOR__
77 x1(
std::numeric_limits<double>::max())
96 static const int N = 100;
97 static const double precision = 1.0e-4;
124 const double Q = b*b - 4.0*a*c;
144 x1 = std::numeric_limits<double>::max();
149 for (
int i = 0; i != N; ++i) {
151 const double x = 0.5 * (xmin + xmax);
154 if (fabs(1.0 - u) < precision) {
164 x1 = 0.5 * (xmin + xmax);
226 return exp(-0.5*x*x);
278 if (th > 0.0 && th < 1.0)
281 THROW(
JValueOutOfRange,
"JPMTAnalogueSignalProcessor::getMaximalRiseTime(): Invalid threshold " << th);
308 return std::numeric_limits<double>::max();
456 return gRandom->Rndm() <
QE;
473 return gRandom->Gaus(t_ns,
TTS_ns);
513 const double mu = NPE *
gain;
516 q = gRandom->Gaus(mu,sigma);
523 const double X = gRandom->Uniform();
528 for (; k <= NPE; ++k) {
531 if (sum_p > X) {
break; }
540 q = gRandom->Gaus(mu,sigma);
547 q = gRandom->Gaus(mu,sigma);
580 const double mu = NPE *
gain;
605 for (
int k = 0; k <= NPE; ++k) {
671 double minCharge = normTh;
674 if (minCharge < th) {minCharge = th;}
678 const double mu = NPE *
gain;
684 const double norm = 0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma);
688 }
else if (mu >= normTh) {
703 for (
int k = 0; k <= NPE; ++k) {
711 norm += weight * (0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma));
713 }
else if (mu >= normTh) {
736 const double norm = 0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma);
740 }
else if (mu >= normTh) {
775 if (zmin < th) { zmin = th; }
776 if (zmax < th) { zmax = th; }
780 const double mu = NPE *
gain;
785 const double cumulP = (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
786 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
787 const double norm = 0.5 * erfc((th - mu) / sqrt(2.0) / sigma);
789 return cumulP / norm;
791 }
else if ((mu >= zmin) && (mu <= zmax)) {
806 for (
int k = 0; k <= NPE; ++k) {
813 cumulP += weight * (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
814 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
815 norm += weight * (0.5 * erfc((th - mu) / sqrt(2.0) / sigma));
817 }
else if ((mu >= zmin) && (mu <= zmax)) {
830 return cumulP / norm;
839 const double cumulP = (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
840 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
841 const double norm = 0.5 * erfc((th - mu) / sqrt(2.0) / sigma);
843 return cumulP / norm;
845 }
else if ((mu >= zmin) && (mu <= zmax)) {
876 double minCharge = normTh;
879 if (minCharge < th) {minCharge = th;}
884 if (zmin < minCharge) { zmin = minCharge; }
885 if (zmax < minCharge) { zmax = minCharge; }
889 const double mu = NPE *
gain;
894 const double cumulP = (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
895 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
896 const double norm = 0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma);
898 return cumulP / norm;
900 }
else if ((mu >= zmin) && (mu <= zmax)) {
915 for (
int k = 0; k <= NPE; ++k) {
922 cumulP += weight * (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
923 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
924 norm += weight * (0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma));
926 }
else if ((mu >= zmin) && (mu <= zmax)) {
939 return cumulP / norm;
948 const double cumulP = (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma) -
949 0.5 * erfc((zmax - mu) / sqrt(2.0) / sigma));
950 const double norm = 0.5 * erfc((normTh - mu) / sqrt(2.0) / sigma);
952 return cumulP / norm;
954 }
else if ((mu >= zmin) && (mu <= zmax)) {
988 if (zmin < th) { zmin = th; }
992 const double mu = NPE *
gain;
997 const double cumulP = 0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma);
998 const double norm = 0.5 * erfc((th - mu) / sqrt(2.0) / sigma);
1000 return cumulP / norm;
1002 }
else if (mu >= zmin) {
1013 double cumulP = 0.0;
1017 for (
int k = 0; k <= NPE; ++k) {
1024 cumulP += weight * (0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma));
1025 norm += weight * (0.5 * erfc((th - mu) / sqrt(2.0) / sigma));
1027 }
else if (mu >= zmin) {
1040 return cumulP / norm;
1049 const double cumulP = 0.5 * erfc((zmin - mu) / sqrt(2.0) / sigma);
1050 const double norm = 0.5 * erfc((th - mu) / sqrt(2.0) / sigma);
1052 return cumulP / norm;
1054 }
else if (mu >= zmin) {
1182 THROW(
JValueOutOfRange,
"JPMTAnalogueSignalProcessor::getTimeOverThreshold: Invalid charge " << npe);
1216 y = npe / (2.0 * z);
1248 }
else if (
QE < 1.0) {
1252 for (
int i = 1; i <= NPE; ++i) {
1285 const double mu = NPE *
gain;
1290 const double Ptotal = 0.5 * erfc((0.0 - mu) / (sqrt(2.0) * sigma));
1293 return Pabove / Ptotal;
1306 double Ptotal = 0.0;
1307 double Pabove = 0.0;
1310 for (
int k = 0; k <= NPE; ++k) {
1317 Ptotal += weight * 0.5 * erfc((0.0 - mu) / (sqrt(2.0) * sigma));
1329 return Pabove / Ptotal;
1338 const double Ptotal = 0.5 * erfc((0.0 - mu) / (sqrt(2.0) * sigma));
1341 return Pabove / Ptotal;
1366 virtual double getNPE(
const double tot_ns)
const override
1369 return std::numeric_limits<double>::max();
1380 }
else if (tot <= TOT) {
1385 const double z = (-b + sqrt(b*b - 4*a*c)) / (2*a);
1408 const double npe =
getNPE(tot_ns);
1411 const double RaboveTh = PaboveTh * y * v;
1416 return RaboveTh + RthBand;
1447 return IaboveTh + IthBand;
1496 double getNormalisedGauss(
const double x,
const double x0,
const double sigma,
const double normXmin,
const double normXmax)
const
1499 const double norm = (0.5 * erfc((normXmin - x0) / sqrt(2.0) / sigma) -
1500 0.5 * erfc((normXmax - x0) / sqrt(2.0) / sigma));
1516 double getIntegralOfNormalisedGauss(
const double xmin,
const double xmax,
const double x0,
const double sigma,
const double normXmin,
const double normXmax)
const
1518 const double numerator = (0.5 * erfc((xmin - x0) / sqrt(2.0) /
sigma_ns) -
1519 0.5 * erfc((xmax - x0) / sqrt(2.0) /
sigma_ns));
1520 const double denominator = (0.5 * erfc((normXmin - x0) / sqrt(2.0) /
sigma_ns) -
1521 0.5 * erfc((normXmax - x0) / sqrt(2.0) /
sigma_ns));
1522 return numerator / denominator;
1539 const double precision = 1.0e-4)
1541 int i = (int) (NPE - 5.0 * sqrt(NPE));
1547 double p = NPE * exp(-NPE) / (double) 1;
1549 for (
int __i = 1; __i != i; ++__i) {
1555 for (
double p0 = 0.0; (p >= p0 || p > precision); ++i, p0 = p, p *= NPE / (double) i) {
1573 const double tot_ns,
1575 const double precision = 1.0e-4)
1577 int i = (int) (NPE - 5.0 * sqrt(NPE) - 0.5);
1578 int M = (int) (NPE + 5.0 * sqrt(NPE) + 0.5);
1580 if (i < 1) { i = 1; }
1581 if (M < i) { M = i; }
1583 double p = NPE * exp(-NPE) / (double) 1;
1585 for (
int __i = 1; __i != i; ++__i) {
1591 for (
double p0 = 0.0; (p >= p0 || p > precision) && i != M; ++i, p0 = p, p *= NPE / (double) i) {
Time calibration (including definition of sign of time offset).
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Auxiliary methods for mathematics.
Data structure for PMT parameters.
double sigma_ns
time-over-threshold standard deviation of threshold-band hits [ns]
double QE
relative quantum efficiency
int getType() const
Get type for for time-slewing correction.
double thresholdBand
threshold-band [npe]
double gainSpread
gain spread [unit]
JPMTParameters()
Default constructor.
double riseTime_ns
rise time of analogue pulse [ns]
double TTS_ns
transition time spread [ns]
double threshold
threshold [npe]
double mean_ns
mean time-over-threshold of threshold-band hits [ns]
void setPMTParameters(const JPMTParameters ¶meters)
Set PMT parameters.
double slope
slope [ns/npe]
double PunderAmplified
probability of underamplified hit
bool slewing
time slewing of analogue signal
double saturation
saturation [ns]
PMT signal processor interface.
virtual double getChargeProbability(const double npe, const int NPE) const
Get probability density for given charge.
Exception for accessing a value in a collection that is outside of its range.
file Auxiliary data structures and methods for detector calibration.
JDETECTOR::JTransitTimeGenerator_t getTransitTime
Function object to generate transit time.
const double TIME_OVER_THRESHOLD_NS
Specification for time-over-threshold corresponding to a one photo-electron pulse.
double getChargeProbability(const JPMTSignalProcessorInterface &pmt, const double npe, const double NPE, const double precision=1.0e-4)
Get charge probability convoluted with a Poisson distribution.
double getTimeOverThresholdProbability(const JPMTAnalogueSignalProcessor &pmt, const double tot_ns, const double NPE, const double precision=1.0e-4)
Get time-over-threshold probability convoluted with a Poisson distribution.
double Gauss(const double x, const double sigma)
Normalised Gauss function.
double binomial(const size_t n, const size_t k)
Binomial function.
PMT analogue signal processor.
double getUnderamplifiedGain() const
Get gain of underamplified pulses.
double getIntegralOfChargeProbability(const double xmin, const double xmax, const int NPE, const double normTh) const
Get integral of probability.
double getDecayTime() const
Get decay time.
friend std::istream & operator>>(std::istream &in, JPMTAnalogueSignalProcessor &object)
Read PMT signal from input.
virtual bool applyQE() const override
Apply relative QE.
virtual bool compare(const JPhotoElectron &first, const JPhotoElectron &second) const override
Compare arrival times of photo-electrons.
static double getMaximalRiseTime(const double th)
Get maximal rise time for given threshold.
double getT1() const
Get time at transition point from Gaussian to exponential.
double getUnderamplifiedGainSpread(int NPE) const
Get gain spread of underamplified pulses.
double getGainSpread(int NPE) const
Get gain spread for given number of photo-electrons.
double getIntegralOfChargeProbability(const JThresholdDomain domain, const int NPE) const
Get integral of probability in specific threshold domain.
double decayTime_ns
decay time [ns]
virtual double getRandomTime(const double t_ns) const override
Get randomised time according transit-time distribution.
virtual bool applyThreshold(const double npe) const override
Apply threshold.
virtual double getChargeProbability(const double npe, const int NPE) const override
Get probability density for given charge.
double y1
amplitude at match point [npe]
double getUnderamplifiedGainSpread() const
Get gain spread of underamplified pulses.
static double getTH1()
Get upper threshold for rise time evaluation.
virtual double getRiseTime(const double npe) const override
Get time to reach threshold.
virtual double getNPE(const double tot_ns) const override
Get number of photo-electrons.
double x1
Transition point from a logarithmic to a linear relation between time-over-threshold and number of ph...
double getTimeOverThresholdProbability(const double tot_ns, const int NPE) const
Get probability of having a pulse with specific time-over-threshold.
double getIntegralOfChargeProbability(const double xmin, const double xmax, const int NPE) const
Get integral of probability.
double getIntegralOfTimeOverThresholdProbability(const double Tmin, const double Tmax, const int NPE) const
Get cumulative probability of time-over-threshold distribution.
double getIntegralOfNormalisedGauss(const double xmin, const double xmax, const double x0, const double sigma, const double normXmin, const double normXmax) const
Integral of Gauss function normalised to a configurable domain.
double getChargeProbability(const double npe, const int NPE, const double normTh) const
Get probability density for given charge.
double getY1() const
Get amplitude at transition point from Gaussian to exponential.
JThresholdDomain getThresholdDomain(const double npe) const
Get threshold domain.
virtual double getThresholdProbability(const int NPE) const override
Probability that a hit survives the threshold of the PMT.
virtual double getRandomCharge(const int NPE) const override
Get randomised charge according to gain and gain spread.
JPMTAnalogueSignalProcessor(const JPMTParameters ¶meters=JPMTParameters())
Constructor.
double getDerivativeOfSaturation(const double tot_ns) const
Get derivative of saturation factor.
double applySaturation(const double tot_ns) const
Get time-over-threshold with saturation.
double getIntegralOfChargeProbability(const double xmin, const int NPE) const
Get integral of probability.
double getDecayTime(const double npe, const double th) const
Get time to pass from top of analogue pulse to threshold.
double removeSaturation(const double tot_ns) const
Get time-over-threshold without saturation.
double getRiseTime(const double npe, const double th) const
Get time to pass from threshold to top of analogue pulse.
double getAmplitude(const double t1_ns) const
Get amplitude at given time for a one photo-electron pulse.
static double getTH0()
Get lower threshold for rise time evaluation.
double getStartOfLinearisation() const
Get transition point from a model-dependent to linear relation between time-over-threshold and number...
JThresholdDomain
Threshold domain specifiers.
@ ABOVE_THRESHOLD
above threshold
@ BELOW_THRESHOLD
below threshold
@ THRESHOLDBAND
inside threshold band
void setPMTParameters(const JPMTParameters ¶meters)
Set PMT parameters.
void configure()
Configure internal parameters.
virtual double getSurvivalProbability(const int NPE) const override
Probability that a hit survives the simulation of the PMT.
virtual double getTimeOverThreshold(const double npe) const override
Get time-over-threshold (ToT).
double getGainSpread() const
Get gain spread for given number of photo-electrons.
virtual double getDerivative(const double npe) const override
Get derivative of number of photo-electrons to time-over-threshold.
double getUnderamplifiedGain(int NPE) const
Get gain of underamplified pulses.
double getNormalisedGauss(const double x, const double x0, const double sigma, const double normXmin, const double normXmax) const
Gauss function normalised to a configurable domain.
double t1
time at match point [ns]
Data structure for single photo-electron.