Skip to content
Snippets Groups Projects
Commit 0f3a73cf authored by Jack Christopher Hutchinson Rolph's avatar Jack Christopher Hutchinson Rolph
Browse files

Initial Commit

parents
No related branches found
No related tags found
No related merge requests found
import numpy as np
from scipy.stats import rv_discrete, rv_continuous, uniform
import scipy.special as sc
import matplotlib.pyplot as plt
from scipy.stats._distn_infrastructure import (
rv_discrete, _ncx2_pdf, _ncx2_cdf, get_distribution_names)
class gpd_gen(rv_discrete):
def _argcheck(self, mu, lbda):
return mu >= 0.0 and lbda >= 0.0 and lbda <= 1.0
def _rvs(self, mu, lbda):
population = np.asarray(
self._random_state.poisson(mu, self._size)
)
if population.shape == ():
population = population.reshape(-1)
offspring = population.copy()
while np.any(offspring > 0):
# probability dists are NOT ufuncs
# print("offspring", offspring)
offspring[:] = [
self._random_state.poisson(m)
for m in lbda*offspring
]
population += offspring
return population
def _pmf(self, k, mu, lbda):
return np.exp(self._logpmf(k, mu, lbda))
def _logpmf(self, k, mu, lbda):
mu_pls_klmb = mu + lbda*k
return np.log(mu) + sc.xlogy(k-1, mu_pls_klmb) - mu_pls_klmb - sc.gammaln(k+1)
def _munp(self, n, mu, lbda):
if n == 1:
return mu/(1-lbda)
elif n == 2:
return (mu/(1-lbda))**2+mu/(1-lbda)**3
gpoisson = gpd_gen(name='gpoisson')
class borel_gen(rv_discrete):
def _argcheck(self, mu):
return ((mu > 0) & (mu<1))
def _logpmf(self, k, mu):
n = k+1
Pk = sc.xlogy(n-1, mu*n) - sc.gammaln(n + 1) - mu*n
return Pk
def _pmf(self, k, mu):
return np.exp(self._logpmf(k, mu))
# def _rvs(self, mu, size=None, random_state=None):
# u = uniform.rvs(loc=0, scale = 1, size=size)
# cum = np.cumsum([self._pmf(_k, mu) for _k in range(0, 100)])
# print(cum)
# rnd = [ np.argmax( cum>=_u ) for _u in u ]
# return rnd
def _rvs(self, mu, size=None, random_state=None, epsilon=1e-4):
_u = uniform.rvs(loc=0, scale = 1-epsilon, size=size)
_sum = 0
_k=0
_elem = []
_max_u = np.max(_u)
while(_sum<_max_u):
_pmf = self._pmf(_k, mu)
_elem.append(_pmf)
_sum+=_pmf
_k+=1
_cum = np.cumsum(_elem)
_rnd = [ np.argmax( _cum>=__u ) for __u in _u ]
return _rnd
def _stats(self, mu):
_mu = 1/(1-mu)
_var = mu/(1-mu)**3
tmp = np.asarray(mu)
mu_nonzero = ((tmp > 0) & (tmp<1))
#g1 and g2: Lagrangian Probability Distributions, 978-0-8176-4365-2, page 159
g1 = scipy._lib._util._lazywhere(mu_nonzero, (tmp,), lambda x: (1+2*x)/scipy.sqrt(x*(1-x)), np.inf)
g2 = scipy._lib._util._lazywhere(mu_nonzero, (tmp,), lambda x: 3 + (1 + 8*x+6*x**2)/(x*(1-x)), np.inf)
return _mu, _var, g1, g2
borel= borel_gen(name='borel')
class erlang_gen(rv_discrete):
def _pdf(self, x, a):
# gamma.pdf(x, a) = x**(a-1) * exp(-x) / gamma(a)
return np.exp(self._logpdf(x, a))
def _logpdf(self, k, mu, nu):
return sc.xlogy(a-1.0, x) - x - sc.gammaln(a)
# def _rvs(self, mu, nu, size=None, random_state=None):
# u = scipy.stats.uniform.rvs(loc=0, scale = 1, size=size)
# cum = np.cumsum([self._pmf(_k, mu, nu) for _k in range(0, 100)])
# rnd = [ np.argmax( cum>=_u ) for _u in u ]
# return rnd
pairs = list(globals().items())
_distn_names, _distn_gen_names = get_distribution_names(pairs, rv_discrete)
__all__ = _distn_names + _distn_gen_names
Example.png

25.3 KiB

from LightSimtastic import SiPMSimulation
import matplotlib.pyplot as plt
#################################
# THE SIMULATION TOOL TAKES A DICTIONARY AS AN INPUT, WITH EACH OF THE VARIABLES AS KEYS.
# FOR EACH ELEMENT YOU ADD TO THE LISTS, ANOTHER SIMULATION WILL BE PERFORMED.
# THIS ALLOWS SCANS THROUGH PARAMETERS.
#################################
variables={
"Name_Sim":[0], #THIS CAN BE ANYTHING YOU LIKE
"mu":[7], # MEAN NUMBER OF GEIGER DISCHARGES
"ppXT":[0.0], # PROBABILITY OF PROMPT CROSS-TALK
"pdXT":[0.2], #PROBABILITY OF DELAYED CROSS-TALK
"taudXT":[25], #TIME CONSTANT FOR DELAYED CROSS-TALK (NS)
"rdXT":[0.5], #FRACTION OF DELAYED CROSS-TALK FROM ADJACENT CELLS
"pAp":[0.15], #PROBABILITY OF AFTERPULSE
"tauAp":[7.5], #TIME CONSTANT OF AFTERPULSE
"taur":[20], # SIPM RECOVERY TIME CONSTANT
"Sig0":[0.075], #WIDTH OF PEDESTAL [NORMALISED ADC]
"Sig1":[0.02], # INCREASE IN PEAK WIDTH PER ADDITIONAL DISCHARGE [NORMALISED ADC]
"DCR":[0.0], # DARK COUNT RATE [GHZ]
"Sigt":[0.02], # ELECTRONICS NOISE FOR CURRENT TRANSIENT (FOR TRANSIENT)
"GSig":[0.75], # WIDTH OF ELECTRONICS NOISE TRANSFER FUNCTION (FOR TRANSIENT)
"tslow":[20], # TIME CONSTANT FOR SLOW PART OF PULSE
"tfast":[1.5], # TIME CONSTANT FOR FAST PART OF PULSE
"rfast":[0.2], # PROPORTION OF SLOW/FAST
"start_tgate":[-5], # GATE START TIME [NS]
"len_tgate":[100], # LENGTH OF GATE
"t0":[100,], # STARTING POINT OF GATE
"tl0":[0], #GAUSSIAN MEAN OF PRIMARY GEIGER DICHARGE TIME DISTRIBUTION
"tl1":[0.1], #GAUSSIAN WIDTH OF PRIMARY GEIGER DICHARGE TIME DISTRIBUTION
"tl2":[0], #FREE PARAMETER
"Gen_mu":["Poisson"], # NUMBER PRIMARY GEIGER DISCHARGE PDF
"Gen_tmu":["Gauss"], # TIME OF PRIMARY GEIGER DISCHARGE PDF
"Gen_gain":["Gauss"], # GAIN PDF (FOR TRANSIENT)
"Gen_npXT":["Binomial"], #NUMBER PROMPT X-TALK DISCHARGE DISTRIBUTION
"Gen_ndXT":["Binomial"], #NUMBER PROMPT X-TALK DISCHARGE DISTRIBUTION
"Gen_tdXT":["Exp"], #TIME DELAYED X-TALK DISTRIBUTION
"Gen_nAP":["Binom"], #NUMBER AFTER DISTRIBUTION
"Gen_tAP":["Exp"], #AFTERPULSE TIME DISTRIBUTION
"Gen_noise":["Gauss"] #ELECTRONIC NOISE DISTRIBUTION (FOR TRANSIENT)
}
#################################
# CREATE A SIPM SIMULATION CLASS OBJECT
#################################
s = SiPMSimulation()
#################################
# ADD VARIABLES
#################################
s.AddVariables(variables)
n_events = int(1e5)
#################################
# SIMULATE
#################################
s.Simulate(n_events, transients=False)
#################################
# EXTRACT SIMULATION DATAFRAME
#################################
df = s.pars
#################################
# EXTRACT CHARGE SPECTRUM
#################################
Qs = df.iloc[0]["ChargeSpectrum"]
#################################
# PLOT
#################################
plt.figure(figsize=(15.5,10.5))
plt.hist(Qs, label="Simulated Charge Spectrum", bins=1000)
plt.yscale("log")
plt.xticks(fontsize=25)
plt.yticks(fontsize=25)
plt.xlabel("# GD", fontsize=25),
plt.savefig("./Example.png")
plt.legend(fontsize=25)
This diff is collapsed.
File added
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment