TDCRPy 2.4.0__py3-none-any.whl → 2.15.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tdcrpy/TDCRPy.py +12 -11
- tdcrpy/TDCR_model_lib.py +260 -145
- tdcrpy/config.toml +10 -0
- tdcrpy/decayData/All-nuclides_BetaShape.zip +0 -0
- tdcrpy/decayData/All-nuclides_Ensdf.zip +0 -0
- tdcrpy/decayData/All-nuclides_PenNuc.zip +0 -0
- tdcrpy/test_randomGen.py +62 -0
- {tdcrpy-2.4.0.dist-info → tdcrpy-2.15.8.dist-info}/METADATA +4 -3
- {tdcrpy-2.4.0.dist-info → tdcrpy-2.15.8.dist-info}/RECORD +12 -11
- {tdcrpy-2.4.0.dist-info → tdcrpy-2.15.8.dist-info}/WHEEL +1 -1
- {tdcrpy-2.4.0.dist-info → tdcrpy-2.15.8.dist-info}/licenses/LICENCE.md +0 -0
- {tdcrpy-2.4.0.dist-info → tdcrpy-2.15.8.dist-info}/top_level.txt +0 -0
tdcrpy/TDCRPy.py
CHANGED
|
@@ -289,6 +289,7 @@ def TDCRPy(L, Rad, pmf_1, N, kB, V, mode="eff", Display=False, barp=False, Smode
|
|
|
289
289
|
efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2 = tl.detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime)
|
|
290
290
|
else:
|
|
291
291
|
efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2 = tl.detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime)
|
|
292
|
+
|
|
292
293
|
efficiency_S.append(efficiency0_S)
|
|
293
294
|
efficiency_T.append(efficiency0_T)
|
|
294
295
|
efficiency_D.append(efficiency0_D)
|
|
@@ -1038,7 +1039,7 @@ def objectFct(L, TD, Rad, pmf_1, N, kB, V):
|
|
|
1038
1039
|
|
|
1039
1040
|
return res
|
|
1040
1041
|
|
|
1041
|
-
def eff(TD, Rad, pmf_1, kB, V, N=10000, L=1, maxiter=20, xatol=1e-7, disp=False):
|
|
1042
|
+
def eff(TD, Rad, pmf_1, kB, V, N=10000, L=1, maxiter=20, xatol=1e-7, disp=False, Lbounds=[0.1, 10]):
|
|
1042
1043
|
"""
|
|
1043
1044
|
Caclulation of the efficiency of a TDCR system based on the model TDCRPy.
|
|
1044
1045
|
This function includes optimization procedures from scipy.
|
|
@@ -1107,8 +1108,8 @@ def eff(TD, Rad, pmf_1, kB, V, N=10000, L=1, maxiter=20, xatol=1e-7, disp=False)
|
|
|
1107
1108
|
|
|
1108
1109
|
TDCRPy(L, Rad, pmf_1, N, kB, V, record = True)
|
|
1109
1110
|
|
|
1110
|
-
if symm: r=opt.minimize_scalar(objectFct, args=(TD, Rad, pmf_1, N, kB, V), method='bounded', bounds = (0
|
|
1111
|
-
else: r=opt.minimize_scalar(objectFct, args=(TD[0], Rad, pmf_1, N, kB, V), method='bounded', bounds = (0
|
|
1111
|
+
if symm: r=opt.minimize_scalar(objectFct, args=(TD, Rad, pmf_1, N, kB, V), method='bounded', bounds = (Lbounds[0], Lbounds[1]), options={'disp': disp, 'maxiter':maxiter})
|
|
1112
|
+
else: r=opt.minimize_scalar(objectFct, args=(TD[0], Rad, pmf_1, N, kB, V), method='bounded', bounds = (Lbounds[0], Lbounds[1]), options={'disp': disp, 'maxiter':maxiter})
|
|
1112
1113
|
L0=r.x
|
|
1113
1114
|
L=(L0, L0, L0)
|
|
1114
1115
|
print(f"global free parameter = {L0} keV-1")
|
|
@@ -1138,7 +1139,7 @@ def eff(TD, Rad, pmf_1, kB, V, N=10000, L=1, maxiter=20, xatol=1e-7, disp=False)
|
|
|
1138
1139
|
return L0, L, eff_S, u_eff_S, eff_D, u_eff_D, eff_T, u_eff_T, eff_AB, u_eff_AB, eff_BC, u_eff_BC, eff_AC, u_eff_AC, eff_D2, u_eff_D2
|
|
1139
1140
|
|
|
1140
1141
|
|
|
1141
|
-
def effA(TD, Rad, pmf_1, kB, V, L=1, maxiter=20, xatol=1e-7, disp=False):
|
|
1142
|
+
def effA(TD, Rad, pmf_1, kB, V, L=1, maxiter=20, xatol=1e-7, disp=False, Lbounds=[0.1, 10]):
|
|
1142
1143
|
"""
|
|
1143
1144
|
Caclulation of the efficiency of a TDCR system based on the model TDCRPy (analytical model).
|
|
1144
1145
|
This function includes optimization procedures from scipy.
|
|
@@ -1203,8 +1204,8 @@ def effA(TD, Rad, pmf_1, kB, V, L=1, maxiter=20, xatol=1e-7, disp=False):
|
|
|
1203
1204
|
else:
|
|
1204
1205
|
symm = True
|
|
1205
1206
|
|
|
1206
|
-
if symm: r=opt.minimize_scalar(tl.modelAnalytical, args=(TD, TD, TD, TD, Rad, kB, V, "res", 1e3), method='bounded', bounds = (0
|
|
1207
|
-
else: r=opt.minimize_scalar(tl.modelAnalytical, args=(TD[0], TD[1], TD[2], TD[3], Rad, kB, V, "res", 1e3), method='bounded', bounds = (0
|
|
1207
|
+
if symm: r=opt.minimize_scalar(tl.modelAnalytical, args=(TD, TD, TD, TD, Rad, kB, V, "res", 1e3), method='bounded', bounds = (Lbounds[0], Lbounds[1]), options={'disp': disp, 'maxiter':maxiter})
|
|
1208
|
+
else: r=opt.minimize_scalar(tl.modelAnalytical, args=(TD[0], TD[1], TD[2], TD[3], Rad, kB, V, "res", 1e3), method='bounded', bounds = (Lbounds[0], Lbounds[1]), options={'disp': disp, 'maxiter':maxiter})
|
|
1208
1209
|
L0=r.x
|
|
1209
1210
|
L=(L0, L0, L0)
|
|
1210
1211
|
print(f"global free parameter = {L0} keV-1")
|
|
@@ -1236,20 +1237,20 @@ def effA(TD, Rad, pmf_1, kB, V, L=1, maxiter=20, xatol=1e-7, disp=False):
|
|
|
1236
1237
|
|
|
1237
1238
|
|
|
1238
1239
|
# mode = "eff" # ask for efficiency calculation
|
|
1239
|
-
# Rad="
|
|
1240
|
+
# Rad="Fe-55" # radionuclides
|
|
1240
1241
|
# pmf_1="1" # relatives fractions of the radionulides
|
|
1241
1242
|
# N = 1000 # number of Monte Carlo trials
|
|
1242
1243
|
# kB =1.0e-5 # Birks constant in cm keV-1
|
|
1243
1244
|
# V = 10 # volume of scintillator in mL
|
|
1244
|
-
# L=np.logspace(-
|
|
1245
|
+
# L=np.logspace(-1,2,num=100) # free parameter in keV-1
|
|
1245
1246
|
|
|
1246
|
-
# # TDCRPy(1, Rad, pmf_1, 10, kB, V, mode, Display= True, barp=False, record=True)
|
|
1247
1247
|
# # Record decay histories in temporary files
|
|
1248
|
-
# TDCRPy(L[0], Rad, pmf_1, N, kB, V, mode, barp=False, record=True)
|
|
1248
|
+
# TDCRPy(L[0], Rad, pmf_1, N, kB, V, mode, barp=False, record=True, fullMC=False)
|
|
1249
|
+
# # TDCRPy(100, Rad, pmf_1, N, kB, V, mode, barp=False, record=True, fullMC=True)
|
|
1249
1250
|
|
|
1250
1251
|
# effS, u_effS, effD, u_effD, effT, u_effT, effD2, u_effD2 = [], [],[], [],[], [], [], []
|
|
1251
1252
|
# for l in tqdm(L, desc="free parameters ", unit=" iterations"):
|
|
1252
|
-
# out = TDCRPy(l, Rad, pmf_1, N, kB, V, mode, readRecHist=True)
|
|
1253
|
+
# out = TDCRPy(l, Rad, pmf_1, N, kB, V, mode, readRecHist=True, fullMC=False)
|
|
1253
1254
|
# effS.append(out[2])
|
|
1254
1255
|
# u_effS.append(out[3])
|
|
1255
1256
|
# effD.append(out[2])
|
tdcrpy/TDCR_model_lib.py
CHANGED
|
@@ -11,7 +11,6 @@ Bureau International des Poids et Mesures
|
|
|
11
11
|
"""
|
|
12
12
|
======= Import Python Module =======
|
|
13
13
|
"""
|
|
14
|
-
|
|
15
14
|
import importlib.resources
|
|
16
15
|
from importlib.resources import files
|
|
17
16
|
import pkg_resources
|
|
@@ -24,6 +23,7 @@ import scipy.interpolate as interp
|
|
|
24
23
|
import matplotlib.pyplot as plt
|
|
25
24
|
from tqdm import tqdm
|
|
26
25
|
import tempfile
|
|
26
|
+
import math
|
|
27
27
|
|
|
28
28
|
"""
|
|
29
29
|
======= Import ressource data =======
|
|
@@ -32,6 +32,16 @@ import tempfile
|
|
|
32
32
|
# import advanced configuration data
|
|
33
33
|
config = configparser.ConfigParser()
|
|
34
34
|
|
|
35
|
+
def readEffQ0():
|
|
36
|
+
global config, file_conf
|
|
37
|
+
config = configparser.ConfigParser()
|
|
38
|
+
with importlib.resources.as_file(files('tdcrpy').joinpath('config.toml')) as data_path:
|
|
39
|
+
file_conf = data_path
|
|
40
|
+
config.read(file_conf)
|
|
41
|
+
|
|
42
|
+
effQuantic0 = config["Inputs"].get("effQuantum")
|
|
43
|
+
return effQuantic0
|
|
44
|
+
|
|
35
45
|
def readParameters(disp=False):
|
|
36
46
|
global config, file_conf
|
|
37
47
|
config = configparser.ConfigParser()
|
|
@@ -60,6 +70,15 @@ def readParameters(disp=False):
|
|
|
60
70
|
diam_micelle = config["Inputs"].getfloat("diam_micelle")
|
|
61
71
|
fAq = config["Inputs"].getfloat("fAq")
|
|
62
72
|
micCorr = config["Inputs"].getboolean("micCorr")
|
|
73
|
+
# alphaDir = config["Inputs"].getfloat("alphaDir")
|
|
74
|
+
effQuantic0 = config["Inputs"].get("effQuantum")
|
|
75
|
+
effQuantic = effQuantic0.split(',')
|
|
76
|
+
for i, iS in enumerate(effQuantic):
|
|
77
|
+
iS=iS.replace(" ","")
|
|
78
|
+
if iS != 'None': effQuantic[i]=float(iS)
|
|
79
|
+
optionModel = config["Inputs"].get("optionModel")
|
|
80
|
+
diffP = config["Inputs"].getfloat("diffP")
|
|
81
|
+
PMTspace = config["Inputs"].getfloat("PMTspace")
|
|
63
82
|
|
|
64
83
|
if disp:
|
|
65
84
|
print(f"number of integration bins for electrons = {nE_electron}")
|
|
@@ -76,13 +95,18 @@ def readParameters(disp=False):
|
|
|
76
95
|
print(f"activation of the micelle correction = {micCorr}")
|
|
77
96
|
print(f"diameter of micelle = {diam_micelle} nm")
|
|
78
97
|
print(f"acqueous fraction = {fAq}")
|
|
98
|
+
# print(f"alpha parameter of the hidden Dirichlet process = {alphaDir}")
|
|
99
|
+
print(f"quantum efficiency of the photocathodes = {effQuantic}")
|
|
100
|
+
print(f"Monte Carlo model of the optics = {optionModel}")
|
|
101
|
+
print(f"fraction of diffused scintillation photons = {diffP*100:.1f} %")
|
|
102
|
+
print(f"relative distance from vials border to PMT entrance = {PMTspace*100:.1f} %")
|
|
79
103
|
print(f"coincidence resolving time = {tau} ns")
|
|
80
104
|
print(f"extended dead time = {extDT} µs")
|
|
81
105
|
print(f"measurement time = {measTime} min")
|
|
82
106
|
|
|
83
|
-
return nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, pH,pC,pN,pO,pP,pCl
|
|
107
|
+
return nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, effQuantic, optionModel, diffP, PMTspace, pH,pC,pN,pO,pP,pCl
|
|
84
108
|
|
|
85
|
-
nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, pH,pC,pN,pO,pP,pCl = readParameters()
|
|
109
|
+
nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, effQuantic, optionModel, diffP, PMTspace, pH,pC,pN,pO,pP,pCl = readParameters()
|
|
86
110
|
|
|
87
111
|
p_atom = np.array([pH,pC,pN,pO,pP,pCl]) # atom abondance in the scintillator
|
|
88
112
|
p_atom /= sum(p_atom)
|
|
@@ -96,7 +120,7 @@ def readConfigAsstr():
|
|
|
96
120
|
def writeConfifAsstr(data):
|
|
97
121
|
path2config = str(config.read(file_conf)[0])
|
|
98
122
|
with open(path2config, 'w') as file:
|
|
99
|
-
file.write(data)
|
|
123
|
+
file.write(data)
|
|
100
124
|
|
|
101
125
|
def modifynE_electron(x):
|
|
102
126
|
data0 = readConfigAsstr()
|
|
@@ -190,7 +214,38 @@ def modifyMeasTime(x):
|
|
|
190
214
|
def modifyMicCorr(x):
|
|
191
215
|
data0 = readConfigAsstr()
|
|
192
216
|
x0 = readParameters()[13]
|
|
193
|
-
data1 = data0.replace(f"micCorr = {x0}",f"micCorr= {x}")
|
|
217
|
+
data1 = data0.replace(f"micCorr = {x0}",f"micCorr = {x}")
|
|
218
|
+
writeConfifAsstr(data1)
|
|
219
|
+
|
|
220
|
+
# def modifyAlphaDir(x):
|
|
221
|
+
# data0 = readConfigAsstr()
|
|
222
|
+
# x0 = readParameters()[14]
|
|
223
|
+
# data1 = data0.replace(f"alphaDir = {x0}",f"alphaDir = {x}")
|
|
224
|
+
# writeConfifAsstr(data1)
|
|
225
|
+
|
|
226
|
+
def modifyEffQ(x):
|
|
227
|
+
data0 = readConfigAsstr()
|
|
228
|
+
# x0 = readParameters()[14]
|
|
229
|
+
x0 = readEffQ0()
|
|
230
|
+
data1 = data0.replace(f"effQuantum = {x0}",f"effQuantum = {x}")
|
|
231
|
+
writeConfifAsstr(data1)
|
|
232
|
+
|
|
233
|
+
def modifyOptModel(x):
|
|
234
|
+
data0 = readConfigAsstr()
|
|
235
|
+
x0 = readParameters()[15]
|
|
236
|
+
data1 = data0.replace(f"optionModel = {x0}",f"optionModel = {x}")
|
|
237
|
+
writeConfifAsstr(data1)
|
|
238
|
+
|
|
239
|
+
def modifyDiffP(x):
|
|
240
|
+
data0 = readConfigAsstr()
|
|
241
|
+
x0 = readParameters()[16]
|
|
242
|
+
data1 = data0.replace(f"diffP = {x0:.1f}",f"diffP = {x:.1f}")
|
|
243
|
+
writeConfifAsstr(data1)
|
|
244
|
+
|
|
245
|
+
def modifyPMTspace(x):
|
|
246
|
+
data0 = readConfigAsstr()
|
|
247
|
+
x0 = readParameters()[17]
|
|
248
|
+
data1 = data0.replace(f"PMTspace = {x0:.1f}",f"PMTspace = {x:.1f}")
|
|
194
249
|
writeConfifAsstr(data1)
|
|
195
250
|
|
|
196
251
|
def read_temp_files(copy=False, path="C:"):
|
|
@@ -2851,7 +2906,7 @@ def buildBetaSpectra(rad, V, N, prt=False):
|
|
|
2851
2906
|
else: file.write(f"{b}\t{p2[i]}\n")
|
|
2852
2907
|
print("file written in local")
|
|
2853
2908
|
|
|
2854
|
-
def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime):
|
|
2909
|
+
def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime, effQuantic = effQuantic):
|
|
2855
2910
|
"""
|
|
2856
2911
|
Calculate detection probabilities for LS counting systems - see Broda, R., Cassette, P., Kossert, K., 2007. Radionuclide metrology using liquid scintillation counting. Metrologia 44. https://doi.org/10.1088/0026-1394/44/4/S06
|
|
2857
2912
|
|
|
@@ -2892,17 +2947,20 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2892
2947
|
"""
|
|
2893
2948
|
if isinstance(L, (tuple, list)):
|
|
2894
2949
|
symm = False
|
|
2950
|
+
mu = effQuantic
|
|
2895
2951
|
else:
|
|
2896
2952
|
symm = True
|
|
2953
|
+
mu = np.mean(effQuantic)
|
|
2897
2954
|
|
|
2955
|
+
|
|
2898
2956
|
|
|
2899
2957
|
if symm:
|
|
2900
|
-
|
|
2958
|
+
|
|
2901
2959
|
if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
|
|
2902
2960
|
# TDCR
|
|
2903
|
-
p_nosingle = np.exp(-L*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2961
|
+
p_nosingle = np.exp(-L*mu*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2904
2962
|
p_single = 1-p_nosingle # probability to have at least 1 electrons in a PMT
|
|
2905
|
-
p_nosingle2 = np.exp(-L*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
2963
|
+
p_nosingle2 = np.exp(-L*mu*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
2906
2964
|
p_single2 = 1-p_nosingle2
|
|
2907
2965
|
efficiency0_S = 1-p_nosingle**3+1-p_nosingle2**3
|
|
2908
2966
|
efficiency0_T = p_single**3+p_single2**3
|
|
@@ -2912,16 +2970,16 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2912
2970
|
efficiency0_AC = efficiency0_AB
|
|
2913
2971
|
|
|
2914
2972
|
# CN
|
|
2915
|
-
p_nosingle = np.exp(-L*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2973
|
+
p_nosingle = np.exp(-L*mu*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2916
2974
|
p_single = 1-p_nosingle # probability to have at least 1 electrons in a PMT
|
|
2917
|
-
p_nosingle2 = np.exp(-L*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
2975
|
+
p_nosingle2 = np.exp(-L*mu*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
2918
2976
|
p_single2 = 1-p_nosingle2
|
|
2919
2977
|
efficiency0_A2 = p_single+p_single2
|
|
2920
2978
|
efficiency0_B2 = efficiency0_A2
|
|
2921
2979
|
efficiency0_D2 = p_single**2+p_single2**2
|
|
2922
2980
|
else:
|
|
2923
2981
|
# TDCR
|
|
2924
|
-
p_nosingle = np.exp(-L*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2982
|
+
p_nosingle = np.exp(-L*mu*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2925
2983
|
p_single = 1-p_nosingle # probability to have at least 1 electrons in a PMT
|
|
2926
2984
|
efficiency0_S = 1-p_nosingle**3
|
|
2927
2985
|
efficiency0_T = p_single**3
|
|
@@ -2931,7 +2989,7 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2931
2989
|
efficiency0_AC = efficiency0_AB
|
|
2932
2990
|
|
|
2933
2991
|
# CN
|
|
2934
|
-
p_nosingle = np.exp(-L*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2992
|
+
p_nosingle = np.exp(-L*mu*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2935
2993
|
p_single = 1-p_nosingle # probability to have at least 1 electrons in a PMT
|
|
2936
2994
|
efficiency0_A2 = p_single
|
|
2937
2995
|
efficiency0_B2 = efficiency0_A2
|
|
@@ -2939,18 +2997,18 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2939
2997
|
else:
|
|
2940
2998
|
if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
|
|
2941
2999
|
# TDCR
|
|
2942
|
-
pA_nosingle = np.exp(-L[0]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3000
|
+
pA_nosingle = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2943
3001
|
pA_single = 1-pA_nosingle # probability to have at least 1 electrons in a PMT
|
|
2944
|
-
pB_nosingle = np.exp(-L[1]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3002
|
+
pB_nosingle = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2945
3003
|
pB_single = 1-pB_nosingle # probability to have at least 1 electrons in a PMT
|
|
2946
|
-
pC_nosingle = np.exp(-L[2]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3004
|
+
pC_nosingle = np.exp(-L[2]*mu[2]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2947
3005
|
pC_single = 1-pC_nosingle # probability to have at least 1 electrons in a PMT
|
|
2948
3006
|
|
|
2949
|
-
pA_nosingle2 = np.exp(-L[0]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
3007
|
+
pA_nosingle2 = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
2950
3008
|
pA_single2 = 1-pA_nosingle2 # probability to have at least 1 electrons in a PMT
|
|
2951
|
-
pB_nosingle2 = np.exp(-L[1]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
3009
|
+
pB_nosingle2 = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
2952
3010
|
pB_single2 = 1-pB_nosingle2 # probability to have at least 1 electrons in a PMT
|
|
2953
|
-
pC_nosingle2 = np.exp(-L[2]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
3011
|
+
pC_nosingle2 = np.exp(-L[2]*mu[2]*np.sum(np.asarray(e_quenching2))/3) # probability to have 0 electrons in a PMT
|
|
2954
3012
|
pC_single2 = 1-pC_nosingle2 # probability to have at least 1 electrons in a PMT
|
|
2955
3013
|
|
|
2956
3014
|
efficiency0_A2 = pA_single+pA_single2
|
|
@@ -2965,24 +3023,24 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2965
3023
|
|
|
2966
3024
|
|
|
2967
3025
|
# CN
|
|
2968
|
-
pA_nosingle = np.exp(-L[0]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
3026
|
+
pA_nosingle = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2969
3027
|
pA_single = 1-pA_nosingle # probability to have at least 1 electrons in a PMT
|
|
2970
|
-
pB_nosingle = np.exp(-L[1]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
3028
|
+
pB_nosingle = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2971
3029
|
pB_single = 1-pB_nosingle # probability to have at least 1 electrons in a PMT
|
|
2972
3030
|
|
|
2973
|
-
pA_nosingle2 = np.exp(-L[0]*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
3031
|
+
pA_nosingle2 = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
2974
3032
|
pA_single2 = 1-pA_nosingle2 # probability to have at least 1 electrons in a PMT
|
|
2975
|
-
pB_nosingle2 = np.exp(-L[1]*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
3033
|
+
pB_nosingle2 = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching2))/2) # probability to have 0 electrons in a PMT
|
|
2976
3034
|
pB_single2 = 1-pB_nosingle2 # probability to have at least 1 electrons in a PMT
|
|
2977
3035
|
|
|
2978
3036
|
efficiency0_D2 = pA_single*pB_single+pA_single2*pB_single2
|
|
2979
3037
|
else:
|
|
2980
3038
|
# TDCR
|
|
2981
|
-
pA_nosingle = np.exp(-L[0]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3039
|
+
pA_nosingle = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2982
3040
|
pA_single = 1-pA_nosingle # probability to have at least 1 electrons in a PMT
|
|
2983
|
-
pB_nosingle = np.exp(-L[1]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3041
|
+
pB_nosingle = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2984
3042
|
pB_single = 1-pB_nosingle # probability to have at least 1 electrons in a PMT
|
|
2985
|
-
pC_nosingle = np.exp(-L[2]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
3043
|
+
pC_nosingle = np.exp(-L[2]*mu[2]*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
|
|
2986
3044
|
pC_single = 1-pC_nosingle # probability to have at least 1 electrons in a PMT
|
|
2987
3045
|
|
|
2988
3046
|
efficiency0_A2 = pA_single
|
|
@@ -2995,16 +3053,114 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
|
|
|
2995
3053
|
efficiency0_S = 1-pA_nosingle*pB_nosingle*pC_nosingle
|
|
2996
3054
|
|
|
2997
3055
|
# CN
|
|
2998
|
-
pA_nosingle = np.exp(-L[0]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
3056
|
+
pA_nosingle = np.exp(-L[0]*mu[0]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
2999
3057
|
pA_single = 1-pA_nosingle # probability to have at least 1 electrons in a PMT
|
|
3000
|
-
pB_nosingle = np.exp(-L[1]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
3058
|
+
pB_nosingle = np.exp(-L[1]*mu[1]*np.sum(np.asarray(e_quenching))/2) # probability to have 0 electrons in a PMT
|
|
3001
3059
|
pB_single = 1-pB_nosingle # probability to have at least 1 electrons in a PMT
|
|
3002
3060
|
efficiency0_D2 = pA_single*pB_single
|
|
3003
3061
|
|
|
3004
3062
|
return efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2
|
|
3005
3063
|
|
|
3006
3064
|
|
|
3007
|
-
def
|
|
3065
|
+
def stochasticDepTD(diffP, PMTspace):
|
|
3066
|
+
"""
|
|
3067
|
+
Generate the probability
|
|
3068
|
+
|
|
3069
|
+
Parameters
|
|
3070
|
+
----------
|
|
3071
|
+
diffP : TYPE
|
|
3072
|
+
DESCRIPTION.
|
|
3073
|
+
PMTspace : TYPE
|
|
3074
|
+
DESCRIPTION.
|
|
3075
|
+
|
|
3076
|
+
Returns
|
|
3077
|
+
-------
|
|
3078
|
+
TYPE
|
|
3079
|
+
DESCRIPTION.
|
|
3080
|
+
|
|
3081
|
+
"""
|
|
3082
|
+
detA = np.array([[2*(1+PMTspace), 0], [-(1+PMTspace), np.sqrt(3)*(1+PMTspace)]])
|
|
3083
|
+
detB = np.array([[-(1+PMTspace), np.sqrt(3)*(1+PMTspace)], [-(1+PMTspace), -np.sqrt(3)*(1+PMTspace)]])
|
|
3084
|
+
detC = np.array([[-(1+PMTspace), -np.sqrt(3)*(1+PMTspace)], [2*(1+PMTspace), 0]])
|
|
3085
|
+
|
|
3086
|
+
def simulate_photon_groups():
|
|
3087
|
+
rho = 1 * np.sqrt(np.random.uniform(0, 1, 1)) # Radial distance
|
|
3088
|
+
theta = np.random.uniform(0, 2 * np.pi, 1) # Angular position
|
|
3089
|
+
x = rho * np.cos(theta)
|
|
3090
|
+
y = rho * np.sin(theta)
|
|
3091
|
+
return x, y
|
|
3092
|
+
|
|
3093
|
+
def calculate_angle(O, det):
|
|
3094
|
+
A=det[0]
|
|
3095
|
+
B=det[1]
|
|
3096
|
+
OA = (A[0] - O[0], A[1] - O[1]) # Vecteurs OA et OB
|
|
3097
|
+
OB = (B[0] - O[0], B[1] - O[1])
|
|
3098
|
+
dot_product = OA[0] * OB[0] + OA[1] * OB[1] # Produit scalaire OA . OB
|
|
3099
|
+
norm_OA = math.sqrt((OA[0]**2 + OA[1]**2)[0]) # Normes des vecteurs OA et OB
|
|
3100
|
+
norm_OB = math.sqrt((OB[0]**2 + OB[1]**2)[0])
|
|
3101
|
+
cos_angle = dot_product / (norm_OA * norm_OB) # Cosinus de l'angle
|
|
3102
|
+
angle_rad = math.acos(cos_angle[0]) # Angle en radians
|
|
3103
|
+
angle_deg = math.degrees(angle_rad) # Convertir en degrés
|
|
3104
|
+
return angle_deg
|
|
3105
|
+
|
|
3106
|
+
x, y = simulate_photon_groups()
|
|
3107
|
+
|
|
3108
|
+
pa=(1-diffP)*calculate_angle([x, y], detA)/360+diffP/3
|
|
3109
|
+
pb=(1-diffP)*calculate_angle([x, y], detB)/360+diffP/3
|
|
3110
|
+
pc=(1-diffP)*calculate_angle([x, y], detC)/360+diffP/3
|
|
3111
|
+
|
|
3112
|
+
return pa, pb, pc
|
|
3113
|
+
|
|
3114
|
+
# Di = []; Ti = []
|
|
3115
|
+
# n=1000000
|
|
3116
|
+
# for i in range(n):
|
|
3117
|
+
# A = stochasticDepTD(1, 0)
|
|
3118
|
+
# B = np.random.poisson(2)
|
|
3119
|
+
# n_phPMT = np.random.multinomial(B, A) # sample the number of photons in each PMTs (TDCR configuration)
|
|
3120
|
+
# nA=np.random.binomial(n_phPMT[0],0.25) # sample the conversion to photoelectrons PMT A
|
|
3121
|
+
# nB=np.random.binomial(n_phPMT[1],0.25) # sample the conversion to photoelectrons PMT B
|
|
3122
|
+
# nC=np.random.binomial(n_phPMT[2],0.25) # sample the conversion to photoelectrons PMT C
|
|
3123
|
+
# Di.append(sum([nA>0, nB>0, nC>0])>1)
|
|
3124
|
+
# Ti.append(sum([nA>0, nB>0, nC>0])>2)
|
|
3125
|
+
# D = sum(Di)/n
|
|
3126
|
+
# uD = D/np.sqrt(sum(Di))#np.sqrt(n)
|
|
3127
|
+
# T = sum(Ti)/n
|
|
3128
|
+
# uT = T/np.sqrt(sum(Ti))#/np.sqrt(n)
|
|
3129
|
+
# print(D, uD)
|
|
3130
|
+
# print(T, uT)
|
|
3131
|
+
|
|
3132
|
+
def stochasticDepCN(diffP, PMTspace):
|
|
3133
|
+
def simulate_photon_groups():
|
|
3134
|
+
rho = 1 * np.sqrt(np.random.uniform(0, 1, 1)) # Radial distance
|
|
3135
|
+
theta = np.random.uniform(0, 2 * np.pi, 1) # Angular position
|
|
3136
|
+
x = rho * np.cos(theta)
|
|
3137
|
+
y = rho * np.sin(theta)
|
|
3138
|
+
return x, y
|
|
3139
|
+
|
|
3140
|
+
def calculate_angle(O):
|
|
3141
|
+
OA = (-1-PMTspace - O[0], 0 - O[1]) # Vecteurs OA et OB
|
|
3142
|
+
OB = (1+PMTspace - O[0], 0 - O[1])
|
|
3143
|
+
dot_product = OA[0] * OB[0] + OA[1] * OB[1] # Produit scalaire OA . OB
|
|
3144
|
+
norm_OA = math.sqrt((OA[0]**2 + OA[1]**2)[0]) # Normes des vecteurs OA et OB
|
|
3145
|
+
norm_OB = math.sqrt((OB[0]**2 + OB[1]**2)[0])
|
|
3146
|
+
cos_angle = dot_product / (norm_OA * norm_OB) # Cosinus de l'angle
|
|
3147
|
+
angle_rad = math.acos(cos_angle[0]) # Angle en radians
|
|
3148
|
+
angle_deg = math.degrees(angle_rad) # Convertir en degrés
|
|
3149
|
+
return angle_deg
|
|
3150
|
+
|
|
3151
|
+
x, y = simulate_photon_groups()
|
|
3152
|
+
|
|
3153
|
+
if np.random.randint(0, high=2)==0:
|
|
3154
|
+
pa=(1-diffP)*calculate_angle([x, y])/360+diffP/2
|
|
3155
|
+
pb=1-pa
|
|
3156
|
+
else:
|
|
3157
|
+
pb=(1-diffP)*calculate_angle([x, y])/360+diffP/2
|
|
3158
|
+
pa=1-pb
|
|
3159
|
+
|
|
3160
|
+
return pa, pb
|
|
3161
|
+
|
|
3162
|
+
|
|
3163
|
+
def detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime, effQuantic = effQuantic, optionModel=optionModel, diffP = diffP, PMTspace = PMTspace, dispParam=False):
|
|
3008
3164
|
"""
|
|
3009
3165
|
Calculate detection probabilities for LS counting systems - see Broda, R., Cassette, P., Kossert, K., 2007. Radionuclide metrology using liquid scintillation counting. Metrologia 44. https://doi.org/10.1088/0026-1394/44/4/S06
|
|
3010
3166
|
|
|
@@ -3043,123 +3199,79 @@ def detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, me
|
|
|
3043
3199
|
detection probability of coincidences in a C/N system.
|
|
3044
3200
|
|
|
3045
3201
|
"""
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3202
|
+
mu = effQuantic
|
|
3203
|
+
|
|
3204
|
+
if type(L) == float:
|
|
3205
|
+
L = [L, L, L]
|
|
3050
3206
|
|
|
3051
|
-
if
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
efficiency0_T = n_T/m
|
|
3120
|
-
efficiency0_D = n_D/m
|
|
3121
|
-
efficiency0_AB = n_AB/m
|
|
3122
|
-
efficiency0_BC = n_BC/m
|
|
3123
|
-
efficiency0_AC = n_AC/m
|
|
3124
|
-
for j in n_ph:
|
|
3125
|
-
n_phPMT = np.random.multinomial(j, [L[0]/(2*Lm), L[1]/(2*Lm)])
|
|
3126
|
-
if sum(n_phPMT>1)>1: n_D2 +=1
|
|
3127
|
-
if n_phPMT[0]>1: n_A2 +=1
|
|
3128
|
-
if n_phPMT[1]>1: n_B2 +=1
|
|
3129
|
-
# efficiency0_A2 = n_A2/m
|
|
3130
|
-
# efficiency0_B2 = n_B2/m
|
|
3131
|
-
efficiency0_D2 = n_D2/m
|
|
3132
|
-
else: # asym and no sum of delayed events
|
|
3133
|
-
m = len(e_quenching)
|
|
3134
|
-
Lm = np.mean(L)
|
|
3135
|
-
n_ph = np.random.poisson(np.asarray((e_quenching+e_quenching2)*Lm))
|
|
3136
|
-
n_S = 0; n_D = 0; n_T = 0; n_AB = 0; n_BC = 0; n_AC = 0; n_D2 = 0; n_A2 = 0; n_B2 = 0;
|
|
3137
|
-
for j in n_ph:
|
|
3138
|
-
n_phPMT = np.random.multinomial(j, [L[0]/(3*Lm), L[1]/(3*Lm), L[2]/(3*Lm)])
|
|
3139
|
-
if sum(n_phPMT>1)>0: n_S +=1
|
|
3140
|
-
if sum(n_phPMT>1)>1: n_D +=1
|
|
3141
|
-
if sum(n_phPMT>1)>2: n_T +=1
|
|
3142
|
-
if n_phPMT[0]>1 and n_phPMT[1]>1: n_AB +=1
|
|
3143
|
-
if n_phPMT[1]>1 and n_phPMT[2]>1: n_BC +=1
|
|
3144
|
-
if n_phPMT[0]>1 and n_phPMT[2]>1: n_AC +=1
|
|
3145
|
-
efficiency0_S = n_S/m
|
|
3146
|
-
efficiency0_T = n_T/m
|
|
3147
|
-
efficiency0_D = n_D/m
|
|
3148
|
-
efficiency0_AB = n_AB/m
|
|
3149
|
-
efficiency0_BC = n_BC/m
|
|
3150
|
-
efficiency0_AC = n_AC/m
|
|
3151
|
-
for j in n_ph:
|
|
3152
|
-
n_phPMT = np.random.multinomial(j, [L[0]/(2*Lm), L[1]/(2*Lm)])
|
|
3153
|
-
if sum(n_phPMT>1)>1: n_D2 +=1
|
|
3154
|
-
if n_phPMT[0]>1: n_A2 +=1
|
|
3155
|
-
if n_phPMT[1]>1: n_B2 +=1
|
|
3156
|
-
# efficiency0_A2 = n_A2/m
|
|
3157
|
-
# efficiency0_B2 = n_B2/m
|
|
3158
|
-
efficiency0_D2 = n_D2/m
|
|
3159
|
-
return efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3207
|
+
if dispParam: print(f"EffQ = {mu} - model = {optionModel} - diffP = {diffP} - PMTspace = {PMTspace}")
|
|
3208
|
+
|
|
3209
|
+
def stochasOpticModel(e_q, L, mu):
|
|
3210
|
+
n_e=np.zeros(3); n_eCN=np.zeros(2) # initilize the number of photoelectrons
|
|
3211
|
+
|
|
3212
|
+
n_ph = np.random.poisson(sum(np.asarray(e_q))*np.mean(L)) # sample the number of scintillation photons
|
|
3213
|
+
|
|
3214
|
+
pTD = stochasticDepTD(diffP, PMTspace) # probabilities for photons to move towards the different PMTs (TDCR configuration)
|
|
3215
|
+
n_phPMT = np.random.multinomial(n_ph, pTD) # sample the number of photons in each PMTs (TDCR configuration)
|
|
3216
|
+
n_e[0]=np.random.binomial(n_phPMT[0],mu[0]) # sample the conversion to photoelectrons PMT A
|
|
3217
|
+
n_e[1]=np.random.binomial(n_phPMT[1],mu[1]) # sample the conversion to photoelectrons PMT B
|
|
3218
|
+
n_e[2]=np.random.binomial(n_phPMT[2],mu[2]) # sample the conversion to photoelectrons PMT C
|
|
3219
|
+
|
|
3220
|
+
pCN = stochasticDepCN(diffP, PMTspace) # probabilities for photons to move towards the different PMTs (C/N configuration)
|
|
3221
|
+
n_phPMTCN = np.random.multinomial(n_ph, pCN) # sample the number of photons in each PMTs (C/N configuration)
|
|
3222
|
+
n_eCN[0]=np.random.binomial(n_phPMTCN[0],mu[0]) # sample the conversion to photoelectrons PMT A
|
|
3223
|
+
n_eCN[1]=np.random.binomial(n_phPMTCN[1],mu[1]) # sample the conversion to photoelectrons PMT B
|
|
3224
|
+
|
|
3225
|
+
return n_e, n_eCN
|
|
3226
|
+
|
|
3227
|
+
def Pmodel(e_q, pTD_ideal, pCN_ideal, L, mu):
|
|
3228
|
+
n_e=np.zeros(3); n_eCN=np.zeros(2) # initilize the number of photoelectrons
|
|
3229
|
+
|
|
3230
|
+
n_e[0] = np.random.poisson(sum(np.asarray(e_q))*L[0]*mu[0]*pTD_ideal[0]) # sample the conversion to photoelectrons PMT A
|
|
3231
|
+
n_e[1] = np.random.poisson(sum(np.asarray(e_q))*L[1]*mu[1]*pTD_ideal[1]) # sample the conversion to photoelectrons PMT B
|
|
3232
|
+
n_e[2] = np.random.poisson(sum(np.asarray(e_q))*L[2]*mu[2]*pTD_ideal[2]) # sample the conversion to photoelectrons PMT C
|
|
3233
|
+
n_eCN[0] = np.random.poisson(sum(np.asarray(e_q))*L[0]*mu[0]*pCN_ideal[0]) # sample the conversion to photoelectrons PMT A
|
|
3234
|
+
n_eCN[1] = np.random.poisson(sum(np.asarray(e_q))*L[1]*mu[1]*pCN_ideal[1]) # sample the conversion to photoelectrons PMT B
|
|
3235
|
+
|
|
3236
|
+
return n_e, n_eCN
|
|
3237
|
+
|
|
3238
|
+
|
|
3239
|
+
efficiency0_S = 0; efficiency0_T = 0; efficiency0_D = 0
|
|
3240
|
+
efficiency0_AB = 0; efficiency0_BC = 0; efficiency0_AC = 0
|
|
3241
|
+
efficiency0_D2 = 0;
|
|
3242
|
+
# n_e = np.zeros(3); n_eCN = np.zeros(2); n_e2 = np.zeros(3); n_e2CN = np.zeros(2)
|
|
3243
|
+
if optionModel == "stochastic-dependence":
|
|
3244
|
+
n_e, n_eCN = stochasOpticModel(e_quenching, L, mu)
|
|
3245
|
+
elif optionModel == "poisson":
|
|
3246
|
+
n_e, n_eCN = Pmodel(e_quenching, [1/3, 1/3, 1/3], [1/2, 1/2], L, mu)
|
|
3247
|
+
else:
|
|
3248
|
+
print("unknown model")
|
|
3249
|
+
|
|
3250
|
+
if sum(n_e>0)>0: efficiency0_S =1
|
|
3251
|
+
if sum(n_e>0)>1: efficiency0_D =1
|
|
3252
|
+
if sum(n_e>0)>2: efficiency0_T =1
|
|
3253
|
+
if n_e[0]>0 and n_e[1]>0: efficiency0_AB =1
|
|
3254
|
+
if n_e[1]>0 and n_e[2]>0: efficiency0_BC =1
|
|
3255
|
+
if n_e[0]>0 and n_e[2]>0: efficiency0_AC =1
|
|
3256
|
+
if sum(n_eCN>1)>1: efficiency0_D2 =1
|
|
3257
|
+
|
|
3258
|
+
if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
|
|
3259
|
+
if optionModel == "stochastic-dependence":
|
|
3260
|
+
n_e2, n_e2CN = stochasOpticModel(e_quenching2, L, mu)
|
|
3261
|
+
elif optionModel == "poisson":
|
|
3262
|
+
n_e2, n_e2CN = Pmodel(e_quenching2, [1/3, 1/3, 1/3], [1/2, 1/2], L, mu)
|
|
3263
|
+
else:
|
|
3264
|
+
print("unknown model")
|
|
3265
|
+
|
|
3266
|
+
if sum(n_e2>0)>0: efficiency0_S +=1
|
|
3267
|
+
if sum(n_e2>0)>1: efficiency0_D +=1
|
|
3268
|
+
if sum(n_e2>0)>2: efficiency0_T +=1
|
|
3269
|
+
if n_e2[0]>0 and n_e2[1]>0: efficiency0_AB +=1
|
|
3270
|
+
if n_e2[1]>0 and n_e2[2]>0: efficiency0_BC +=1
|
|
3271
|
+
if n_e2[0]>0 and n_e2[2]>0: efficiency0_AC +=1
|
|
3272
|
+
if sum(n_e2CN>1)>1: efficiency0_D2 +=1
|
|
3273
|
+
|
|
3274
|
+
return efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2
|
|
3163
3275
|
|
|
3164
3276
|
|
|
3165
3277
|
def efficienciesEstimates(efficiency_S, efficiency_D, efficiency_T, efficiency_AB, efficiency_BC, efficiency_AC, efficiency_D2, N):
|
|
@@ -3271,6 +3383,9 @@ def readRecQuenchedEnergies():
|
|
|
3271
3383
|
e_quenching.append(energy)
|
|
3272
3384
|
return Epromt, Edelayed
|
|
3273
3385
|
|
|
3386
|
+
|
|
3387
|
+
|
|
3388
|
+
|
|
3274
3389
|
# N = 1e7
|
|
3275
3390
|
# buildBetaSpectra('H-3', 16, N, prt=True); print('H-3 - done')
|
|
3276
3391
|
# buildBetaSpectra('C-14', 16, N, prt=True); print('C-14 - done')
|
tdcrpy/config.toml
CHANGED
|
@@ -31,6 +31,16 @@ diam_micelle = 2
|
|
|
31
31
|
# acqueous fraction of the scintillator
|
|
32
32
|
fAq = 0.1
|
|
33
33
|
|
|
34
|
+
## OPTICAL PROPERTIES
|
|
35
|
+
# Quantum efficiency
|
|
36
|
+
effQuantum = 0.25, 0.25, 0.25
|
|
37
|
+
# Optical MC model
|
|
38
|
+
optionModel = stochastic-dependence
|
|
39
|
+
# fraction of diffused scintillation photons
|
|
40
|
+
diffP = 1.0
|
|
41
|
+
# relative distance from vials border to PMT entrance
|
|
42
|
+
PMTspace = 0.1
|
|
43
|
+
|
|
34
44
|
## PROPERTIES OF THE COUNTER
|
|
35
45
|
# Coincidence resolving time (ns)
|
|
36
46
|
tau = 50
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
tdcrpy/test_randomGen.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Wed May 14 16:17:16 2025
|
|
4
|
+
|
|
5
|
+
@author: romain.coulon
|
|
6
|
+
"""
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
# m = 0.1
|
|
10
|
+
# N = 1000000
|
|
11
|
+
|
|
12
|
+
# ps0 = 1-np.exp(-m)
|
|
13
|
+
|
|
14
|
+
# psi=np.random.poisson(m,N)
|
|
15
|
+
# ps1 = sum(psi>0)/N
|
|
16
|
+
# ups1 = np.sqrt(sum(psi>0))/N
|
|
17
|
+
|
|
18
|
+
# print(ps0,ps1,ups1)
|
|
19
|
+
# print(ps0-ps1,ups1)
|
|
20
|
+
# print(abs(ps0-ps1)<2*ups1)
|
|
21
|
+
|
|
22
|
+
import importlib
|
|
23
|
+
import tdcrpy
|
|
24
|
+
tdcrpy.TDCR_model_lib.modifyEffQ("0.1, 0.1, 0.1")
|
|
25
|
+
# tdcrpy.TDCR_model_lib.modifyOptModel("stochastic-dependence")
|
|
26
|
+
tdcrpy.TDCR_model_lib.modifyOptModel("poisson")
|
|
27
|
+
L = [1.0, 1.0, 1.0]
|
|
28
|
+
e_q = [100]
|
|
29
|
+
diffP = 1
|
|
30
|
+
importlib.reload(tdcrpy.TDCR_model_lib)
|
|
31
|
+
|
|
32
|
+
Q = tdcrpy.TDCR_model_lib.readEffQ0()
|
|
33
|
+
Q = Q.split(",")
|
|
34
|
+
Q = [float(i) for i in Q]
|
|
35
|
+
QL = [float(Qi)*L[i] for i, Qi in enumerate(Q)]
|
|
36
|
+
|
|
37
|
+
e_q2 = [0]; t1 = 0; evenement = 1; extDT = 50; measTime = 60000
|
|
38
|
+
|
|
39
|
+
S,D,T,_,_,_,_ = tdcrpy.TDCR_model_lib.detectProbabilities(QL, e_q, e_q2, t1, evenement, extDT, measTime)
|
|
40
|
+
SmcI=[];DmcI=[];TmcI=[]
|
|
41
|
+
nIter=100000
|
|
42
|
+
for i in range(nIter):
|
|
43
|
+
Smc,Dmc,Tmc,_,_,_,_ = tdcrpy.TDCR_model_lib.detectProbabilitiesMC(L, e_q, e_q2, t1, evenement, extDT, measTime, dispParam=True)
|
|
44
|
+
SmcI.append(Smc); DmcI.append(Dmc); TmcI.append(Tmc)
|
|
45
|
+
|
|
46
|
+
print('\n')
|
|
47
|
+
tdcrpy.TDCR_model_lib.readParameters(disp=True)
|
|
48
|
+
|
|
49
|
+
print("\nEffQ = ", Q, "\tEffQ*L = ", QL, "\n")
|
|
50
|
+
|
|
51
|
+
print("\nEFF, EFFmc, +/-")
|
|
52
|
+
print("single eff = ",round(S,4),round(np.mean(SmcI),4),round(np.std(SmcI)/np.sqrt(nIter),4))
|
|
53
|
+
print("double eff = ",round(D,4),round(np.mean(DmcI),4),round(np.std(DmcI)/np.sqrt(nIter),4))
|
|
54
|
+
print("triple eff = ",round(T,4),round(np.mean(TmcI),4),round(np.std(TmcI)/np.sqrt(nIter),4))
|
|
55
|
+
print('\nDEVIATION < 2 sigma')
|
|
56
|
+
print("single eff = ",abs(round(S,4)-round(np.mean(SmcI),4))<2*round(np.std(SmcI)/np.sqrt(nIter),4))
|
|
57
|
+
print("double eff = ",abs(round(D,4)-round(np.mean(DmcI),4))<2*round(np.std(DmcI)/np.sqrt(nIter),4))
|
|
58
|
+
print("triple eff = ",abs(round(T,4)-round(np.mean(TmcI),4))<2*round(np.std(TmcI)/np.sqrt(nIter),4))
|
|
59
|
+
print('\nPRECISION')
|
|
60
|
+
print("single eff = ",round(100*np.std(SmcI)/(np.sqrt(nIter)*round(np.mean(SmcI),4)),4)," %")
|
|
61
|
+
print("double eff = ",round(100*np.std(DmcI)/(np.sqrt(nIter)*round(np.mean(DmcI),4)),4)," %")
|
|
62
|
+
print("triple eff = ",round(100*np.std(TmcI)/(np.sqrt(nIter)*round(np.mean(TmcI),4)),4)," %")
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TDCRPy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.15.8
|
|
4
4
|
Summary: TDCR model
|
|
5
5
|
Home-page: https://pypi.org/project/TDCRPy/
|
|
6
6
|
Author: RomainCoulon (Romain Coulon)
|
|
7
7
|
Author-email: <romain.coulon@bipm.org>
|
|
8
8
|
Project-URL: Documentation, https://github.com/RomainCoulon/TDCRPy/
|
|
9
9
|
Keywords: Python,TDCR,Monte-Carlo,radionuclide,scintillation,counting
|
|
10
|
-
Classifier: Development Status ::
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Intended Audience :: Science/Research
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Natural Language :: English
|
|
@@ -49,7 +49,8 @@ The code is developped and maintained by the BIPM (MIT license).
|
|
|
49
49
|
|
|
50
50
|
Technical details can be found in
|
|
51
51
|
|
|
52
|
-
http://dx.doi.org/10.13140/RG.2.2.15682.80321
|
|
52
|
+
* http://dx.doi.org/10.13140/RG.2.2.15682.80321
|
|
53
|
+
* https://doi.org/10.1016/j.apradiso.2024.111518
|
|
53
54
|
|
|
54
55
|
## 1.1 Installation
|
|
55
56
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
tdcrpy/TDCRPy.py,sha256=
|
|
1
|
+
tdcrpy/TDCRPy.py,sha256=3puNWaySzWsCg08OYzI89rWRy5f2CV2aa5HuC0tVCFM,67965
|
|
2
2
|
tdcrpy/TDCRPy1.py,sha256=QTBZh5B5JWnGB0BQfD-cFmwA9W080OD4sG-aj50-ejo,38106
|
|
3
|
-
tdcrpy/TDCR_model_lib.py,sha256=
|
|
3
|
+
tdcrpy/TDCR_model_lib.py,sha256=aaQfweMgml6_yzvEAMmVC0zXcYd2WBxqY-os-nzmktA,138157
|
|
4
4
|
tdcrpy/TDCRoptimize.py,sha256=c2XIGveeLdVYYek4Rg6dygMvVA2xIrIkMb3L-_jUucM,6496
|
|
5
5
|
tdcrpy/__init__.py,sha256=9Djir8dPNchcJVQvhl-oRHEOsoDkiZlkOhWT-eHR7wQ,95
|
|
6
|
-
tdcrpy/config.toml,sha256=
|
|
6
|
+
tdcrpy/config.toml,sha256=UvIV6oUFjkk96c0Z053l14vekVc0eZ2-C0xy8MTs2zQ,1725
|
|
7
7
|
tdcrpy/test2.py,sha256=poLLXJyIaCeqh1VSkwgbi-udvY7lQjxz_YStKjJXGhU,501
|
|
8
|
+
tdcrpy/test_randomGen.py,sha256=CWN8jWJ3VAu6WhkRIR9BHv-e4V4hGx5jSfWBqGE0TT4,2195
|
|
8
9
|
tdcrpy/MCNP-MATRIX/Spectra_for_analytical_model/dep_spectrum_C-14.txt,sha256=Eh3KaNbfYHakk_uStLu8K1aFciO6_i_rS2yKxGGppDE,8416
|
|
9
10
|
tdcrpy/MCNP-MATRIX/Spectra_for_analytical_model/dep_spectrum_Ca-45.txt,sha256=TymodcK4ttoO1duZuW3RGOwHFwPPzw2ESPc_H_QQN8k,8830
|
|
10
11
|
tdcrpy/MCNP-MATRIX/Spectra_for_analytical_model/dep_spectrum_Co-60.txt,sha256=kxD5E7tk_Gc1Ylg8qCG1r3oB21m7wUT4zBWsmbseiMU,40203
|
|
@@ -62,9 +63,9 @@ tdcrpy/Quenching/TandataUG.txt,sha256=AkUGz2dAZ6g3bQIIacR5f92aa8gmiklgRbN4Dyz-12
|
|
|
62
63
|
tdcrpy/Quenching/alpha_toulene.txt,sha256=rJB9xCLM3GLg91EKfhu8sGwro281ySq6R0G5mXMt3f8,1553
|
|
63
64
|
tdcrpy/Quenching/inputVecteurAlpha.txt,sha256=ee4emplX51vhomC7cGNP_eE5eqS9By5PaSSaa4hh1eg,178652
|
|
64
65
|
tdcrpy/Quenching/inputVecteurElectron.txt,sha256=5NBRBaiB7op1SJ6v952w9gFKqh0x83pn8zYcoUpy33Y,181498
|
|
65
|
-
tdcrpy/decayData/All-nuclides_BetaShape.zip,sha256=
|
|
66
|
-
tdcrpy/decayData/All-nuclides_Ensdf.zip,sha256=
|
|
67
|
-
tdcrpy/decayData/All-nuclides_PenNuc.zip,sha256=
|
|
66
|
+
tdcrpy/decayData/All-nuclides_BetaShape.zip,sha256=k-UOym1MPPzGrOwal2mrlcXi3NSR1vAqzO15qTsW25c,8000329
|
|
67
|
+
tdcrpy/decayData/All-nuclides_Ensdf.zip,sha256=J7m6Uq9UqEvBgazuu31NPDO-43xMh3Ktq6w6yMEWBF0,453398
|
|
68
|
+
tdcrpy/decayData/All-nuclides_PenNuc.zip,sha256=o2DftXAJW6-zpBpi_ozHZiDIzl3XcEcAjFJZWAeHbI8,410519
|
|
68
69
|
tdcrpy/decayData/atom-ENDF-VII0.zip,sha256=oP4Z7qWweWF4j12QAIfvLFLlqeY1RomXwXD2iFgQCqo,1624444
|
|
69
70
|
tdcrpy/decayData/photo-ENDF.zip,sha256=eOiVUt6OKGl0a3pErfaibZzF_yoSzswdUCTbnGNlu7g,249674
|
|
70
71
|
tdcrpy/docs/_build/html/genindex.html,sha256=FopjoEyhTbeh7qOem-A7er-6yCIfdhv1BIzs9dJocCc,2522
|
|
@@ -74,8 +75,8 @@ tdcrpy/docs/_build/html/source/modules.html,sha256=Jf-qxVBId0UgpwyvYuyjtMNG-ezPO
|
|
|
74
75
|
tdcrpy/docs/_build/html/source/tdcrpy.html,sha256=-38lHMNFB22p1tWJEeN3yDqfDiCYE304vxDamO1-iRc,3779
|
|
75
76
|
tdcrpy/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
77
|
tdcrpy/test/test_tdcrpy.py,sha256=JINqSEMFoNpptE4f3h6ZzTYW1rBx90KkaoQzltSg-No,4692
|
|
77
|
-
tdcrpy-2.
|
|
78
|
-
tdcrpy-2.
|
|
79
|
-
tdcrpy-2.
|
|
80
|
-
tdcrpy-2.
|
|
81
|
-
tdcrpy-2.
|
|
78
|
+
tdcrpy-2.15.8.dist-info/licenses/LICENCE.md,sha256=ZTpWyGU3qv_iwEpgvCijoCuCYpOPpyzJCgOk46WpUKU,1066
|
|
79
|
+
tdcrpy-2.15.8.dist-info/METADATA,sha256=G68HRdhNUqMMynusKChlR44rsKGNXoD7qFWHo-qisY8,45363
|
|
80
|
+
tdcrpy-2.15.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
81
|
+
tdcrpy-2.15.8.dist-info/top_level.txt,sha256=f4vzFFcKSEnonAACs0ZXuRczmroLLqtPTqXFymU_VU0,14
|
|
82
|
+
tdcrpy-2.15.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|