TDCRPy 2.9.0__py3-none-any.whl → 2.12.13__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.

Potentially problematic release.


This version of TDCRPy might be problematic. Click here for more details.

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)
tdcrpy/TDCR_model_lib.py CHANGED
@@ -24,6 +24,7 @@ import scipy.interpolate as interp
24
24
  import matplotlib.pyplot as plt
25
25
  from tqdm import tqdm
26
26
  import tempfile
27
+ import math
27
28
 
28
29
  """
29
30
  ======= Import ressource data =======
@@ -32,6 +33,16 @@ import tempfile
32
33
  # import advanced configuration data
33
34
  config = configparser.ConfigParser()
34
35
 
36
+ def readEffQ0():
37
+ global config, file_conf
38
+ config = configparser.ConfigParser()
39
+ with importlib.resources.as_file(files('tdcrpy').joinpath('config.toml')) as data_path:
40
+ file_conf = data_path
41
+ config.read(file_conf)
42
+
43
+ effQuantic0 = config["Inputs"].get("effQuantum")
44
+ return effQuantic0
45
+
35
46
  def readParameters(disp=False):
36
47
  global config, file_conf
37
48
  config = configparser.ConfigParser()
@@ -60,9 +71,15 @@ def readParameters(disp=False):
60
71
  diam_micelle = config["Inputs"].getfloat("diam_micelle")
61
72
  fAq = config["Inputs"].getfloat("fAq")
62
73
  micCorr = config["Inputs"].getboolean("micCorr")
63
- alphaDir = config["Inputs"].getfloat("alphaDir")
64
- effQuantic = config["Inputs"].getfloat("effQuantum")
74
+ # alphaDir = config["Inputs"].getfloat("alphaDir")
75
+ effQuantic0 = config["Inputs"].get("effQuantum")
76
+ effQuantic = effQuantic0.split(',')
77
+ for i, iS in enumerate(effQuantic):
78
+ iS=iS.replace(" ","")
79
+ if iS != 'None': effQuantic[i]=float(iS)
65
80
  optionModel = config["Inputs"].get("optionModel")
81
+ diffP = config["Inputs"].getfloat("diffP")
82
+ PMTspace = config["Inputs"].getfloat("PMTspace")
66
83
 
67
84
  if disp:
68
85
  print(f"number of integration bins for electrons = {nE_electron}")
@@ -79,16 +96,18 @@ def readParameters(disp=False):
79
96
  print(f"activation of the micelle correction = {micCorr}")
80
97
  print(f"diameter of micelle = {diam_micelle} nm")
81
98
  print(f"acqueous fraction = {fAq}")
82
- print(f"alpha parameter of the hidden Dirichlet process = {alphaDir}")
99
+ # print(f"alpha parameter of the hidden Dirichlet process = {alphaDir}")
83
100
  print(f"quantum efficiency of the photocathodes = {effQuantic}")
84
101
  print(f"Monte Carlo model of the optics = {optionModel}")
102
+ print(f"fraction of diffused scintillation photons = {diffP*100:.1f} %")
103
+ print(f"relative distance from vials border to PMT entrance = {PMTspace*100:.1f} %")
85
104
  print(f"coincidence resolving time = {tau} ns")
86
105
  print(f"extended dead time = {extDT} µs")
87
106
  print(f"measurement time = {measTime} min")
88
107
 
89
- return nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, alphaDir, effQuantic, optionModel, pH,pC,pN,pO,pP,pCl
108
+ 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
90
109
 
91
- nE_electron, nE_alpha, RHO, Z, A, depthSpline, Einterp_a, Einterp_e, diam_micelle, fAq, tau, extDT, measTime, micCorr, alphaDir, effQuantic, optionModel, pH,pC,pN,pO,pP,pCl = readParameters()
110
+ 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()
92
111
 
93
112
  p_atom = np.array([pH,pC,pN,pO,pP,pCl]) # atom abondance in the scintillator
94
113
  p_atom /= sum(p_atom)
@@ -199,24 +218,37 @@ def modifyMicCorr(x):
199
218
  data1 = data0.replace(f"micCorr = {x0}",f"micCorr= {x}")
200
219
  writeConfifAsstr(data1)
201
220
 
202
- def modifyAlphaDir(x):
203
- data0 = readConfigAsstr()
204
- x0 = readParameters()[14]
205
- data1 = data0.replace(f"alphaDir = {x0}",f"alphaDir = {x}")
206
- writeConfifAsstr(data1)
221
+ # def modifyAlphaDir(x):
222
+ # data0 = readConfigAsstr()
223
+ # x0 = readParameters()[14]
224
+ # data1 = data0.replace(f"alphaDir = {x0}",f"alphaDir = {x}")
225
+ # writeConfifAsstr(data1)
207
226
 
208
227
  def modifyEffQ(x):
209
228
  data0 = readConfigAsstr()
210
- x0 = readParameters()[15]
229
+ # x0 = readParameters()[14]
230
+ x0 = readEffQ0()
211
231
  data1 = data0.replace(f"effQuantum = {x0}",f"effQuantum = {x}")
212
232
  writeConfifAsstr(data1)
213
233
 
214
234
  def modifyOptModel(x):
215
235
  data0 = readConfigAsstr()
216
- x0 = readParameters()[16]
236
+ x0 = readParameters()[15]
217
237
  data1 = data0.replace(f"optionModel = {x0}",f"optionModel = {x}")
218
238
  writeConfifAsstr(data1)
219
239
 
240
+ def modifyDiffP(x):
241
+ data0 = readConfigAsstr()
242
+ x0 = readParameters()[16]
243
+ data1 = data0.replace(f"diffP = {x0:.1f}",f"diffP = {x:.1f}")
244
+ writeConfifAsstr(data1)
245
+
246
+ def modifyPMTspace(x):
247
+ data0 = readConfigAsstr()
248
+ x0 = readParameters()[17]
249
+ data1 = data0.replace(f"PMTspace = {x0:.1f}",f"PMTspace = {x:.1f}")
250
+ writeConfifAsstr(data1)
251
+
220
252
  def read_temp_files(copy=False, path="C:"):
221
253
 
222
254
  temp_dir = tempfile.gettempdir()
@@ -2921,7 +2953,7 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
2921
2953
 
2922
2954
 
2923
2955
  if symm:
2924
- # print(evenement !=1, t1 > extDT*1e-6, t1 < measTime*60)
2956
+
2925
2957
  if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
2926
2958
  # TDCR
2927
2959
  p_nosingle = np.exp(-L*np.sum(np.asarray(e_quenching))/3) # probability to have 0 electrons in a PMT
@@ -3028,7 +3060,105 @@ def detectProbabilities(L, e_quenching, e_quenching2, t1, evenement, extDT, meas
3028
3060
  return efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2
3029
3061
 
3030
3062
 
3031
- def detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime, dir_param = alphaDir, effQuantic = effQuantic, optionModel=optionModel):
3063
+ def stochasticDepTD(diffP, PMTspace):
3064
+ """
3065
+ Generate the probability
3066
+
3067
+ Parameters
3068
+ ----------
3069
+ diffP : TYPE
3070
+ DESCRIPTION.
3071
+ PMTspace : TYPE
3072
+ DESCRIPTION.
3073
+
3074
+ Returns
3075
+ -------
3076
+ TYPE
3077
+ DESCRIPTION.
3078
+
3079
+ """
3080
+ detA = np.array([[2*(1+PMTspace), 0], [-(1+PMTspace), np.sqrt(3)*(1+PMTspace)]])
3081
+ detB = np.array([[-(1+PMTspace), np.sqrt(3)*(1+PMTspace)], [-(1+PMTspace), -np.sqrt(3)*(1+PMTspace)]])
3082
+ detC = np.array([[-(1+PMTspace), -np.sqrt(3)*(1+PMTspace)], [2*(1+PMTspace), 0]])
3083
+
3084
+ def simulate_photon_groups():
3085
+ rho = 1 * np.sqrt(np.random.uniform(0, 1, 1)) # Radial distance
3086
+ theta = np.random.uniform(0, 2 * np.pi, 1) # Angular position
3087
+ x = rho * np.cos(theta)
3088
+ y = rho * np.sin(theta)
3089
+ return x, y
3090
+
3091
+ def calculate_angle(O, det):
3092
+ A=det[0]
3093
+ B=det[1]
3094
+ OA = (A[0] - O[0], A[1] - O[1]) # Vecteurs OA et OB
3095
+ OB = (B[0] - O[0], B[1] - O[1])
3096
+ dot_product = OA[0] * OB[0] + OA[1] * OB[1] # Produit scalaire OA . OB
3097
+ norm_OA = math.sqrt((OA[0]**2 + OA[1]**2)[0]) # Normes des vecteurs OA et OB
3098
+ norm_OB = math.sqrt((OB[0]**2 + OB[1]**2)[0])
3099
+ cos_angle = dot_product / (norm_OA * norm_OB) # Cosinus de l'angle
3100
+ angle_rad = math.acos(cos_angle[0]) # Angle en radians
3101
+ angle_deg = math.degrees(angle_rad) # Convertir en degrés
3102
+ return angle_deg
3103
+
3104
+ x, y = simulate_photon_groups()
3105
+
3106
+ pa=(1-diffP)*calculate_angle([x, y], detA)/360+diffP/3
3107
+ pb=(1-diffP)*calculate_angle([x, y], detB)/360+diffP/3
3108
+ pc=(1-diffP)*calculate_angle([x, y], detC)/360+diffP/3
3109
+
3110
+ return pa, pb, pc
3111
+
3112
+ # Di = []; Ti = []
3113
+ # n=1000000
3114
+ # for i in range(n):
3115
+ # A = stochasticDepTD(1, 0)
3116
+ # B = np.random.poisson(2)
3117
+ # n_phPMT = np.random.multinomial(B, A) # sample the number of photons in each PMTs (TDCR configuration)
3118
+ # nA=np.random.binomial(n_phPMT[0],0.25) # sample the conversion to photoelectrons PMT A
3119
+ # nB=np.random.binomial(n_phPMT[1],0.25) # sample the conversion to photoelectrons PMT B
3120
+ # nC=np.random.binomial(n_phPMT[2],0.25) # sample the conversion to photoelectrons PMT C
3121
+ # Di.append(sum([nA>0, nB>0, nC>0])>1)
3122
+ # Ti.append(sum([nA>0, nB>0, nC>0])>2)
3123
+ # D = sum(Di)/n
3124
+ # uD = D/np.sqrt(sum(Di))#np.sqrt(n)
3125
+ # T = sum(Ti)/n
3126
+ # uT = T/np.sqrt(sum(Ti))#/np.sqrt(n)
3127
+ # print(D, uD)
3128
+ # print(T, uT)
3129
+
3130
+ def stochasticDepCN(diffP, PMTspace):
3131
+ def simulate_photon_groups():
3132
+ rho = 1 * np.sqrt(np.random.uniform(0, 1, 1)) # Radial distance
3133
+ theta = np.random.uniform(0, 2 * np.pi, 1) # Angular position
3134
+ x = rho * np.cos(theta)
3135
+ y = rho * np.sin(theta)
3136
+ return x, y
3137
+
3138
+ def calculate_angle(O):
3139
+ OA = (-1-PMTspace - O[0], 0 - O[1]) # Vecteurs OA et OB
3140
+ OB = (1+PMTspace - O[0], 0 - O[1])
3141
+ dot_product = OA[0] * OB[0] + OA[1] * OB[1] # Produit scalaire OA . OB
3142
+ norm_OA = math.sqrt((OA[0]**2 + OA[1]**2)[0]) # Normes des vecteurs OA et OB
3143
+ norm_OB = math.sqrt((OB[0]**2 + OB[1]**2)[0])
3144
+ cos_angle = dot_product / (norm_OA * norm_OB) # Cosinus de l'angle
3145
+ angle_rad = math.acos(cos_angle[0]) # Angle en radians
3146
+ angle_deg = math.degrees(angle_rad) # Convertir en degrés
3147
+ return angle_deg
3148
+
3149
+ x, y = simulate_photon_groups()
3150
+
3151
+ if np.random.randint(0, high=2)==0:
3152
+ pa=(1-diffP)*calculate_angle([x, y])/360+diffP/2
3153
+ pb=1-pa
3154
+ else:
3155
+ pb=(1-diffP)*calculate_angle([x, y])/360+diffP/2
3156
+ pa=1-pb
3157
+
3158
+ return pa, pb
3159
+
3160
+
3161
+ def detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, measTime, effQuantic = effQuantic, optionModel=optionModel, diffP = diffP, PMTspace = PMTspace, dispParam=False):
3032
3162
  """
3033
3163
  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
3034
3164
 
@@ -3067,149 +3197,81 @@ def detectProbabilitiesMC(L, e_quenching, e_quenching2, t1, evenement, extDT, me
3067
3197
  detection probability of coincidences in a C/N system.
3068
3198
 
3069
3199
  """
3070
- if isinstance(L, (tuple, list)):
3071
- symm = False
3072
- else:
3073
- symm = True
3074
-
3075
3200
  mu = effQuantic
3201
+
3202
+ if type(L) == float:
3203
+ L = [L, L, L]
3076
3204
 
3077
- if dir_param < 1000:
3078
- dirichTD = np.random.dirichlet([dir_param, dir_param, dir_param])
3079
- dirichCN = np.random.dirichlet([dir_param, dir_param])
3080
- else:
3081
- dirichTD = [1/3, 1/3, 1/3]
3082
- dirichCN = [1/2, 1/2]
3205
+ if dispParam: print(f"EffQ = {mu} - model = {optionModel} - diffP = {diffP} - PMTspace = {PMTspace}")
3206
+
3207
+ def stochasOpticModel(e_q, L, mu):
3208
+ n_e=np.zeros(3); n_eCN=np.zeros(2) # initilize the number of photoelectrons
3209
+
3210
+ n_ph = np.random.poisson(sum(np.asarray(e_q))*np.mean(L)/np.mean(mu)) # sample the number of scintillation photons
3211
+
3212
+ pTD = stochasticDepTD(diffP, PMTspace) # probabilities for photons to move towards the different PMTs (TDCR configuration)
3213
+ n_phPMT = np.random.multinomial(n_ph, pTD) # sample the number of photons in each PMTs (TDCR configuration)
3214
+ n_e[0]=np.random.binomial(n_phPMT[0],mu[0]) # sample the conversion to photoelectrons PMT A
3215
+ n_e[1]=np.random.binomial(n_phPMT[1],mu[1]) # sample the conversion to photoelectrons PMT B
3216
+ n_e[2]=np.random.binomial(n_phPMT[2],mu[2]) # sample the conversion to photoelectrons PMT C
3217
+
3218
+ pCN = stochasticDepCN(diffP, PMTspace) # probabilities for photons to move towards the different PMTs (C/N configuration)
3219
+ n_phPMTCN = np.random.multinomial(n_ph, pCN) # sample the number of photons in each PMTs (C/N configuration)
3220
+ n_eCN[0]=np.random.binomial(n_phPMTCN[0],mu[0]) # sample the conversion to photoelectrons PMT A
3221
+ n_eCN[1]=np.random.binomial(n_phPMTCN[1],mu[1]) # sample the conversion to photoelectrons PMT B
3222
+
3223
+ return n_e, n_eCN
3224
+
3225
+ def Pmodel(e_q, pTD_ideal, pCN_ideal, L, mu):
3226
+ n_e=np.zeros(3); n_eCN=np.zeros(2) # initilize the number of photoelectrons
3227
+
3228
+ 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
3229
+ 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
3230
+ 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
3231
+ 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
3232
+ 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
3233
+
3234
+ return n_e, n_eCN
3235
+
3083
3236
 
3084
3237
  efficiency0_S = 0; efficiency0_T = 0; efficiency0_D = 0
3085
3238
  efficiency0_AB = 0; efficiency0_BC = 0; efficiency0_AC = 0
3086
3239
  efficiency0_D2 = 0;
3087
- n_e = np.zeros(3); n_eCN = np.zeros(2); n_e2 = np.zeros(3); n_e2CN = np.zeros(2)
3088
-
3089
- if symm:
3090
- if optionModel == "poisson-multinomial-binomial":
3091
- n_ph = np.random.poisson(sum(np.asarray(e_quenching))*L/mu)
3092
- # TDCR
3093
- n_phPMT = np.random.multinomial(n_ph, dirichTD)
3094
- n_e[0]=np.random.binomial(n_phPMT[0],mu)
3095
- n_e[1]=np.random.binomial(n_phPMT[1],mu)
3096
- n_e[2]=np.random.binomial(n_phPMT[2],mu)
3097
- # C/N
3098
- n_phPMTCN = np.random.multinomial(n_ph, dirichCN)
3099
- n_eCN[0]=np.random.binomial(n_phPMTCN[0],mu)
3100
- n_eCN[1]=np.random.binomial(n_phPMTCN[1],mu)
3101
- elif optionModel == "poisson":
3102
- n_e[0] = np.random.poisson(sum(np.asarray(e_quenching))*L*mu*dirichTD[0])
3103
- n_e[1] = np.random.poisson(sum(np.asarray(e_quenching))*L*mu*dirichTD[1])
3104
- n_e[2] = np.random.poisson(sum(np.asarray(e_quenching))*L*mu*dirichTD[2])
3105
- n_eCN[0] = np.random.poisson(sum(np.asarray(e_quenching))*L*mu*dirichCN[0])
3106
- n_eCN[1] = np.random.poisson(sum(np.asarray(e_quenching))*L*mu*dirichCN[1])
3107
- else:
3108
- print("unknown model")
3109
-
3110
- if sum(n_e>1)>0: efficiency0_S =1
3111
- if sum(n_e>1)>1: efficiency0_D =1
3112
- if sum(n_e>1)>2: efficiency0_T =1
3113
- if n_e[0]>1 and n_e[1]>1: efficiency0_AB =1
3114
- if n_e[1]>1 and n_e[2]>1: efficiency0_BC =1
3115
- if n_e[0]>1 and n_e[2]>1: efficiency0_AC =1
3116
- if sum(n_eCN>1)>1: efficiency0_D2 =1
3117
-
3118
- if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
3119
- if optionModel == "poisson-multinomial-binomial":
3120
- n_ph2 = np.random.poisson(sum(np.asarray(e_quenching2))*L/mu)
3121
- # TDCR
3122
- n_phPMT2 = np.random.multinomial(n_ph2, dirichTD)
3123
- n_e2[0]=np.random.binomial(n_phPMT2[0],mu)
3124
- n_e2[1]=np.random.binomial(n_phPMT2[1],mu)
3125
- n_e2[2]=np.random.binomial(n_phPMT2[2],mu)
3126
- # C/N
3127
- n_phPMT2CN = np.random.multinomial(n_ph2, dirichCN)
3128
- n_e2CN[0]=np.random.binomial(n_phPMT2CN[0],mu)
3129
- n_e2CN[1]=np.random.binomial(n_phPMT2CN[1],mu)
3130
- elif optionModel == "poisson":
3131
- n_e2[0] = np.random.poisson(sum(np.asarray(e_quenching2))*L*mu*dirichTD[0])
3132
- n_e2[1] = np.random.poisson(sum(np.asarray(e_quenching2))*L*mu*dirichTD[1])
3133
- n_e2[2] = np.random.poisson(sum(np.asarray(e_quenching2))*L*mu*dirichTD[2])
3134
- n_e2CN[0] = np.random.poisson(sum(np.asarray(e_quenching2))*L*mu*dirichCN[0])
3135
- n_e2CN[1] = np.random.poisson(sum(np.asarray(e_quenching2))*L*mu*dirichCN[1])
3136
- else:
3137
- print("unknown model")
3138
-
3139
-
3140
- if sum(n_e2>1)>0: efficiency0_S +=1
3141
- if sum(n_e2>1)>1: efficiency0_D +=1
3142
- if sum(n_e2>1)>2: efficiency0_T +=1
3143
- if n_e2[0]>1 and n_e2[1]>1: efficiency0_AB +=1
3144
- if n_e2[1]>1 and n_e2[2]>1: efficiency0_BC +=1
3145
- if n_e2[0]>1 and n_e2[2]>1: efficiency0_AC +=1
3146
- if sum(n_e2CN>1)>1: efficiency0_D2 +=1
3240
+ # n_e = np.zeros(3); n_eCN = np.zeros(2); n_e2 = np.zeros(3); n_e2CN = np.zeros(2)
3241
+ if optionModel == "stochastic-dependence":
3242
+ n_e, n_eCN = stochasOpticModel(e_quenching, L, mu)
3243
+ elif optionModel == "poisson":
3244
+ n_e, n_eCN = Pmodel(e_quenching, [1/3, 1/3, 1/3], [1/2, 1/2], L, mu)
3245
+ else:
3246
+ print("unknown model")
3147
3247
 
3148
- else: # asym
3149
- if optionModel == "poisson-multinomial-binomial":
3150
- Lm = np.mean(L)
3151
- n_ph = np.random.poisson(sum(np.asarray((e_quenching))*Lm/mu))
3152
- # TDCR
3153
- n_phPMT = np.random.multinomial(n_ph, [L[0]*dirichTD[0]/Lm, L[1]*dirichTD[1]/Lm, L[2]*dirichTD[2]/Lm])
3154
- n_e[0]=np.random.binomial(n_phPMT[0],mu)
3155
- n_e[1]=np.random.binomial(n_phPMT[1],mu)
3156
- n_e[2]=np.random.binomial(n_phPMT[2],mu)
3157
- # C/N
3158
- n_phPMTCN = np.random.multinomial(n_ph, [L[0]/(2*Lm), L[1]/(2*Lm)])
3159
- n_eCN[0]=np.random.binomial(n_phPMTCN[0],mu)
3160
- n_eCN[1]=np.random.binomial(n_phPMTCN[1],mu)
3248
+ if sum(n_e>0)>0: efficiency0_S =1
3249
+ if sum(n_e>0)>1: efficiency0_D =1
3250
+ if sum(n_e>0)>2: efficiency0_T =1
3251
+ if n_e[0]>0 and n_e[1]>0: efficiency0_AB =1
3252
+ if n_e[1]>0 and n_e[2]>0: efficiency0_BC =1
3253
+ if n_e[0]>0 and n_e[2]>0: efficiency0_AC =1
3254
+ if sum(n_eCN>1)>1: efficiency0_D2 =1
3255
+
3256
+ if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
3257
+ if optionModel == "stochastic-dependence":
3258
+ n_e2, n_e2CN = stochasOpticModel(e_quenching2, L, mu)
3161
3259
  elif optionModel == "poisson":
3162
- n_e[0] = np.random.poisson(sum(np.asarray(e_quenching))*L[0]*mu*dirichTD[0])
3163
- n_e[1] = np.random.poisson(sum(np.asarray(e_quenching))*L[1]*mu*dirichTD[1])
3164
- n_e[2] = np.random.poisson(sum(np.asarray(e_quenching))*L[2]*mu*dirichTD[2])
3165
- n_eCN[0] = np.random.poisson(sum(np.asarray(e_quenching))*L[0]*mu*dirichCN[0])
3166
- n_eCN[1] = np.random.poisson(sum(np.asarray(e_quenching))*L[1]*mu*dirichCN[1])
3260
+ n_e2, n_e2CN = Pmodel(e_quenching2, [1/3, 1/3, 1/3], [1/2, 1/2], L, mu)
3167
3261
  else:
3168
3262
  print("unknown model")
3169
-
3170
- if sum(n_e>1)>0: efficiency0_S =1
3171
- if sum(n_e>1)>1: efficiency0_D =1
3172
- if sum(n_e>1)>2: efficiency0_T =1
3173
- if n_e[0]>1 and n_e[1]>1: efficiency0_AB =1
3174
- if n_e[1]>1 and n_e[2]>1: efficiency0_BC =1
3175
- if n_e[0]>1 and n_e[2]>1: efficiency0_AC =1
3176
- if sum(n_eCN>1)>1: efficiency0_D2 =1
3177
-
3178
- if evenement !=1 and t1 > extDT*1e-6 and t1 < measTime*60:
3179
- if optionModel == "poisson-multinomial-binomial":
3180
- n_ph2 = np.random.poisson(sum(np.asarray(e_quenching2))*Lm/mu)
3181
- # TDCR
3182
- n_phPMT2 = np.random.multinomial(n_ph2, [L[0]*dirichCN[0]/Lm, L[1]*dirichCN[1]/Lm, L[2]*dirichCN[2]/Lm])
3183
- n_e2[0]=np.random.binomial(n_phPMT2[0],mu)
3184
- n_e2[1]=np.random.binomial(n_phPMT2[1],mu)
3185
- n_e2[2]=np.random.binomial(n_phPMT2[2],mu)
3186
- # C/N
3187
- n_phPMT2CN = np.random.multinomial(n_ph2, [L[0]/(2*Lm), L[1]/(2*Lm)])
3188
- n_e2CN[0]=np.random.binomial(n_phPMT2CN[0],mu)
3189
- n_e2CN[1]=np.random.binomial(n_phPMT2CN[1],mu)
3190
- elif optionModel == "poisson":
3191
- n_e2[0] = np.random.poisson(sum(np.asarray(e_quenching2))*L[0]*mu*dirichTD[0])
3192
- n_e2[1] = np.random.poisson(sum(np.asarray(e_quenching2))*L[1]*mu*dirichTD[1])
3193
- n_e2[2] = np.random.poisson(sum(np.asarray(e_quenching2))*L[2]*mu*dirichTD[2])
3194
- n_e2CN[0] = np.random.poisson(sum(np.asarray(e_quenching2))*L[0]*mu*dirichCN[0])
3195
- n_e2CN[1] = np.random.poisson(sum(np.asarray(e_quenching2))*L[1]*mu*dirichCN[1])
3196
- else:
3197
- print("unknown model")
3198
-
3199
- if sum(n_e2>1)>0: efficiency0_S +=1
3200
- if sum(n_e2>1)>1: efficiency0_D +=1
3201
- if sum(n_e2>1)>2: efficiency0_T +=1
3202
- if n_e2[0]>1 and n_e2[1]>1: efficiency0_AB +=1
3203
- if n_e2[1]>1 and n_e2[2]>1: efficiency0_BC +=1
3204
- if n_e2[0]>1 and n_e2[2]>1: efficiency0_AC +=1
3205
- if sum(n_e2CN>1)>1: efficiency0_D2 +=1
3206
3263
 
3264
+ if sum(n_e2>0)>0: efficiency0_S +=1
3265
+ if sum(n_e2>0)>1: efficiency0_D +=1
3266
+ if sum(n_e2>0)>2: efficiency0_T +=1
3267
+ if n_e2[0]>0 and n_e2[1]>0: efficiency0_AB +=1
3268
+ if n_e2[1]>0 and n_e2[2]>0: efficiency0_BC +=1
3269
+ if n_e2[0]>0 and n_e2[2]>0: efficiency0_AC +=1
3270
+ if sum(n_e2CN>1)>1: efficiency0_D2 +=1
3271
+
3207
3272
  return efficiency0_S, efficiency0_D, efficiency0_T, efficiency0_AB, efficiency0_BC, efficiency0_AC, efficiency0_D2
3208
3273
 
3209
3274
 
3210
-
3211
-
3212
-
3213
3275
  def efficienciesEstimates(efficiency_S, efficiency_D, efficiency_T, efficiency_AB, efficiency_BC, efficiency_AC, efficiency_D2, N):
3214
3276
  """
3215
3277
  Calculate detection efficiencies from list of detection probabilities per decays.
@@ -3319,6 +3381,9 @@ def readRecQuenchedEnergies():
3319
3381
  e_quenching.append(energy)
3320
3382
  return Epromt, Edelayed
3321
3383
 
3384
+
3385
+
3386
+
3322
3387
  # N = 1e7
3323
3388
  # buildBetaSpectra('H-3', 16, N, prt=True); print('H-3 - done')
3324
3389
  # buildBetaSpectra('C-14', 16, N, prt=True); print('C-14 - done')
tdcrpy/config.toml CHANGED
@@ -32,12 +32,14 @@ diam_micelle = 2
32
32
  fAq = 0.1
33
33
 
34
34
  ## OPTICAL PROPERTIES
35
- # Dirichlet parameter
36
- alphaDir = 100000
37
35
  # Quantum efficiency
38
- effQuantum = 0.25
36
+ effQuantum = 0.25, 0.25, 0.25
39
37
  # Optical MC model
40
- optionModel = poisson-multinomial-binomial
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
41
43
 
42
44
  ## PROPERTIES OF THE COUNTER
43
45
  # Coincidence resolving time (ns)
@@ -0,0 +1,66 @@
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
+
23
+ import tdcrpy
24
+ tdcrpy.TDCR_model_lib.modifyEffQ("0.2, 0.2, 0.2")
25
+ # tdcrpy.TDCR_model_lib.modifyOptModel("stochastic-dependence")
26
+ tdcrpy.TDCR_model_lib.modifyOptModel("poisson")
27
+ L = [9.0, 9.0, 9.0]
28
+ e_q = [0.5]
29
+ tdcrpy.TDCR_model_lib.readParameters(disp=True)
30
+
31
+ import tdcrpy
32
+ diffP = 1
33
+
34
+
35
+ Q = tdcrpy.TDCR_model_lib.readEffQ0()
36
+ Q = Q.split(",")
37
+ Q = [float(i) for i in Q]
38
+ QL = [float(Qi)*L[i] for i, Qi in enumerate(Q)]
39
+ print("EffQ = ", Q)
40
+ print("EffQ*L = ", QL)
41
+
42
+ e_q2 = [0]; t1 = 0; evenement = 1; extDT = 50; measTime = 60000
43
+
44
+ # S,D,T,_,_,_,_ = detectProbabilities(QL, e_q, e_q2, t1, evenement, extDT, measTime)
45
+ S,D,T,_,_,_,_ = tdcrpy.TDCR_model_lib.detectProbabilities(QL, e_q, e_q2, t1, evenement, extDT, measTime)
46
+ SmcI=[];DmcI=[];TmcI=[]
47
+ nIter=100000
48
+ for i in range(nIter):
49
+ Smc,Dmc,Tmc,_,_,_,_ = tdcrpy.TDCR_model_lib.detectProbabilitiesMC(L, e_q, e_q2, t1, evenement, extDT, measTime,
50
+ PMTspace=0, diffP=diffP, effQuantic = Q)
51
+ # Smc,Dmc,Tmc,_,_,_,_ = detectProbabilitiesMC(L, e_q, e_q2, t1, evenement, extDT, measTime,
52
+ # PMTspace=0,diffP=diffP)
53
+ SmcI.append(Smc); DmcI.append(Dmc); TmcI.append(Tmc)
54
+
55
+ print("\nEFF, EFFmc, +/-")
56
+ print("single eff = ",round(S,4),round(np.mean(SmcI),4),round(np.std(SmcI)/np.sqrt(nIter),4))
57
+ print("double eff = ",round(D,4),round(np.mean(DmcI),4),round(np.std(DmcI)/np.sqrt(nIter),4))
58
+ print("triple eff = ",round(T,4),round(np.mean(TmcI),4),round(np.std(TmcI)/np.sqrt(nIter),4))
59
+ print('\nDEVIATION < 2 sigma')
60
+ print("single eff = ",abs(round(S,4)-round(np.mean(SmcI),4))<2*round(np.std(SmcI)/np.sqrt(nIter),4))
61
+ print("double eff = ",abs(round(D,4)-round(np.mean(DmcI),4))<2*round(np.std(DmcI)/np.sqrt(nIter),4))
62
+ print("triple eff = ",abs(round(T,4)-round(np.mean(TmcI),4))<2*round(np.std(TmcI)/np.sqrt(nIter),4))
63
+ print('\nPRECISION')
64
+ print("single eff = ",round(100*np.std(SmcI)/(np.sqrt(nIter)*round(np.mean(SmcI),4)),4)," %")
65
+ print("double eff = ",round(100*np.std(DmcI)/(np.sqrt(nIter)*round(np.mean(DmcI),4)),4)," %")
66
+ print("triple eff = ",round(100*np.std(TmcI)/(np.sqrt(nIter)*round(np.mean(TmcI),4)),4)," %")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TDCRPy
3
- Version: 2.9.0
3
+ Version: 2.12.13
4
4
  Summary: TDCR model
5
5
  Home-page: https://pypi.org/project/TDCRPy/
6
6
  Author: RomainCoulon (Romain Coulon)
@@ -1,10 +1,11 @@
1
- tdcrpy/TDCRPy.py,sha256=VIwZJHtpjBt5e87KUqatCC6eTMr2sFVRl52LAc3PZq8,67850
1
+ tdcrpy/TDCRPy.py,sha256=vr3adVMfSRW6bNXZXJnvjwhhuql39nCAHEFFi_1S2Mo,67863
2
2
  tdcrpy/TDCRPy1.py,sha256=QTBZh5B5JWnGB0BQfD-cFmwA9W080OD4sG-aj50-ejo,38106
3
- tdcrpy/TDCR_model_lib.py,sha256=vsfDZheX_jE9oS5mgAobJGBMwkra_uJvQhqZOaZDdWI,136498
3
+ tdcrpy/TDCR_model_lib.py,sha256=pjoPKHMRmFlJJiw06bYf5WLm70vPWsKvuR5-RI2e-m4,137978
4
4
  tdcrpy/TDCRoptimize.py,sha256=c2XIGveeLdVYYek4Rg6dygMvVA2xIrIkMb3L-_jUucM,6496
5
5
  tdcrpy/__init__.py,sha256=9Djir8dPNchcJVQvhl-oRHEOsoDkiZlkOhWT-eHR7wQ,95
6
- tdcrpy/config.toml,sha256=Yg-MBlzxOYiovgVFWq6VtivPkzwyNeWBzwNTc7ADYkU,1634
6
+ tdcrpy/config.toml,sha256=UvIV6oUFjkk96c0Z053l14vekVc0eZ2-C0xy8MTs2zQ,1725
7
7
  tdcrpy/test2.py,sha256=poLLXJyIaCeqh1VSkwgbi-udvY7lQjxz_YStKjJXGhU,501
8
+ tdcrpy/test_randomGen.py,sha256=dhKjtjguGWd9OWl0ZcrfXHiDJUi_XJ1IY3t9qvPowf8,2457
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
@@ -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.9.0.dist-info/licenses/LICENCE.md,sha256=ZTpWyGU3qv_iwEpgvCijoCuCYpOPpyzJCgOk46WpUKU,1066
78
- tdcrpy-2.9.0.dist-info/METADATA,sha256=7kUyXyp5Dao5UqiWM5Miob1qX9FjygQCNnKZI1jWwEE,45298
79
- tdcrpy-2.9.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
80
- tdcrpy-2.9.0.dist-info/top_level.txt,sha256=f4vzFFcKSEnonAACs0ZXuRczmroLLqtPTqXFymU_VU0,14
81
- tdcrpy-2.9.0.dist-info/RECORD,,
78
+ tdcrpy-2.12.13.dist-info/licenses/LICENCE.md,sha256=ZTpWyGU3qv_iwEpgvCijoCuCYpOPpyzJCgOk46WpUKU,1066
79
+ tdcrpy-2.12.13.dist-info/METADATA,sha256=NQQG95cOfBPp_1BMGGR6PZyt2WQy1qGtX-hJrcPF-kU,45300
80
+ tdcrpy-2.12.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
81
+ tdcrpy-2.12.13.dist-info/top_level.txt,sha256=f4vzFFcKSEnonAACs0ZXuRczmroLLqtPTqXFymU_VU0,14
82
+ tdcrpy-2.12.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5