ararpy 0.1.199__py3-none-any.whl → 0.2.2__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.
- ararpy/Example - Check arr.py +52 -0
- ararpy/Example - Granite Cooling History.py +411 -0
- ararpy/Example - Plot temperature calibration.py +291 -0
- ararpy/Example - Show MDD results.py +561 -0
- ararpy/Example - Show all Kfs age spectra.py +344 -0
- ararpy/Example - Show random walk results.py +363 -0
- ararpy/Example - Tc calculation.py +437 -0
- ararpy/__init__.py +3 -4
- ararpy/calc/age.py +34 -36
- ararpy/calc/arr.py +0 -20
- ararpy/calc/basic.py +26 -3
- ararpy/calc/corr.py +131 -85
- ararpy/calc/jvalue.py +7 -5
- ararpy/calc/plot.py +1 -2
- ararpy/calc/raw_funcs.py +41 -2
- ararpy/calc/regression.py +224 -132
- ararpy/files/arr_file.py +2 -1
- ararpy/files/basic.py +0 -22
- ararpy/files/calc_file.py +107 -84
- ararpy/files/raw_file.py +242 -229
- ararpy/smp/basic.py +133 -34
- ararpy/smp/calculation.py +6 -6
- ararpy/smp/corr.py +339 -153
- ararpy/smp/diffusion_funcs.py +345 -36
- ararpy/smp/export.py +247 -129
- ararpy/smp/info.py +2 -2
- ararpy/smp/initial.py +93 -45
- ararpy/smp/json.py +2 -2
- ararpy/smp/plots.py +144 -164
- ararpy/smp/raw.py +11 -15
- ararpy/smp/sample.py +222 -181
- ararpy/smp/style.py +26 -7
- ararpy/smp/table.py +42 -33
- ararpy/thermo/atomic_level_random_walk.py +56 -48
- ararpy/thermo/basic.py +2 -2
- {ararpy-0.1.199.dist-info → ararpy-0.2.2.dist-info}/METADATA +10 -1
- ararpy-0.2.2.dist-info/RECORD +73 -0
- {ararpy-0.1.199.dist-info → ararpy-0.2.2.dist-info}/WHEEL +1 -1
- ararpy-0.1.199.dist-info/RECORD +0 -66
- {ararpy-0.1.199.dist-info → ararpy-0.2.2.dist-info}/licenses/LICENSE +0 -0
- {ararpy-0.1.199.dist-info → ararpy-0.2.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
# Copyright (C) 2024 Yang. - All Rights Reserved
|
|
2
|
+
"""
|
|
3
|
+
# ==========================================
|
|
4
|
+
# Copyright 2024 Yang
|
|
5
|
+
# ararpy - test.py
|
|
6
|
+
# ==========================================
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
#
|
|
10
|
+
"""
|
|
11
|
+
import ararpy as ap
|
|
12
|
+
import numpy as np
|
|
13
|
+
import pdf_maker as pm
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
import matplotlib
|
|
17
|
+
|
|
18
|
+
matplotlib.use('TkAgg')
|
|
19
|
+
import matplotlib.pyplot as plt
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def export_pdf(each_line, X, Y, x, y, Tc_list, sample_name):
|
|
23
|
+
|
|
24
|
+
example_dir = r"C:\Users\Young\OneDrive\00-Projects\【2】个人项目\2022-05论文课题\初稿\封闭温度计算"
|
|
25
|
+
|
|
26
|
+
# ------ 将以下五个样品的年龄谱图组合到一起 -------
|
|
27
|
+
arr_files = [
|
|
28
|
+
os.path.join(example_dir, r'22WHA0433.arr'),
|
|
29
|
+
os.path.join(example_dir, r'20WHA0103.age'),
|
|
30
|
+
]
|
|
31
|
+
colors = ['#1f3c40', '#e35000', '#e1ae0f', '#3d8ebf']
|
|
32
|
+
series = []
|
|
33
|
+
|
|
34
|
+
# ------ 构建数据 -------
|
|
35
|
+
for index, file in enumerate(arr_files):
|
|
36
|
+
smp = ap.from_arr(file_path=file) if file.endswith('.arr') else ap.from_age(file_path=file)
|
|
37
|
+
age = smp.ApparentAgeValues[2:4]
|
|
38
|
+
ar = smp.DegasValues[20]
|
|
39
|
+
data = ap.calc.spectra.get_data(*age, ar, cumulative=False)
|
|
40
|
+
series.append({
|
|
41
|
+
'type': 'series.line', 'id': f'line{index * 2 + 0}', 'name': f'line{index * 2 + 0}', 'color': colors[index],
|
|
42
|
+
'data': np.transpose([data[0], data[1]]).tolist(), 'line_caps': 'square',
|
|
43
|
+
})
|
|
44
|
+
series.append({
|
|
45
|
+
'type': 'series.line', 'id': f'line{index * 2 + 1}', 'name': f'line{index * 2 + 1}', 'color': colors[index],
|
|
46
|
+
'data': np.transpose([data[0], data[2]]).tolist(), 'line_caps': 'square',
|
|
47
|
+
})
|
|
48
|
+
series.append({
|
|
49
|
+
'type': 'text', 'id': f'text{index * 2 + 0}', 'name': f'text{index * 2 + 0}', 'color': colors[index],
|
|
50
|
+
'text': f'{smp.name()}<r>{round(smp.Info.results.age_plateau[0]["age"], 2)}',
|
|
51
|
+
'size': 10, 'data': [[index * 15 + 5, 23]],
|
|
52
|
+
})
|
|
53
|
+
data = {
|
|
54
|
+
"data": [
|
|
55
|
+
{
|
|
56
|
+
'xAxis': [{'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100],
|
|
57
|
+
'title': 'Cumulative <sup>39</sup>Ar Released (%)', 'nameLocation': 'middle', }],
|
|
58
|
+
'yAxis': [{'extent': [0, 250], 'interval': [0, 50, 100, 150, 200, 250],
|
|
59
|
+
'title': 'Apparent Age (Ma)', 'nameLocation': 'middle', }],
|
|
60
|
+
'series': series
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
'xAxis': [{'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100],
|
|
64
|
+
'title': 'Cumulative <sup>39</sup>Ar Released (%)', 'nameLocation': 'middle', }],
|
|
65
|
+
'yAxis': [{'extent': [0, 250], 'interval': [0, 50, 100, 150, 200, 250],
|
|
66
|
+
'title': 'Apparent Age (Ma)', 'nameLocation': 'middle', }],
|
|
67
|
+
'series': series
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"file_name": f"{sample_name}",
|
|
71
|
+
"plot_names": [f"{sample_name}"],
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# write pdf
|
|
75
|
+
file = pm.NewPDF(filepath=os.path.join(example_dir, f"{data['file_name']}.pdf"))
|
|
76
|
+
for index, each in enumerate(data['data']):
|
|
77
|
+
# rich text tags should follow this priority: color > script > break
|
|
78
|
+
file.text(page=index, x=50, y=780, line_space=1.2, size=12, base=0, h_align="left",
|
|
79
|
+
text=f"The PDF can be edited with Adobe Acrobat, Illustrator and CorelDRAW")
|
|
80
|
+
cv = ap.smp.export.export_chart_to_pdf(each)
|
|
81
|
+
file.canvas(page=index, base=0, margin_top=5, canvas=cv, unit="cm", h_align="middle")
|
|
82
|
+
if index + 1 < len(data['data']):
|
|
83
|
+
file.add_page()
|
|
84
|
+
|
|
85
|
+
# save pdf
|
|
86
|
+
file.save()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def read_sample(arr_file_path):
|
|
90
|
+
# 读取样品信息
|
|
91
|
+
if not arr_file_path.endswith('.arr'):
|
|
92
|
+
for root, dirs, files in os.walk(arr_file_path):
|
|
93
|
+
for file in files:
|
|
94
|
+
if file.endswith('.arr'):
|
|
95
|
+
arr_file_path = os.path.join(arr_file_path, file)
|
|
96
|
+
break
|
|
97
|
+
print(f"arr file: {arr_file_path}")
|
|
98
|
+
sample = ap.from_arr(file_path=arr_file_path)
|
|
99
|
+
name = sample.name()
|
|
100
|
+
sequence = sample.sequence()
|
|
101
|
+
nsteps = sequence.size
|
|
102
|
+
te = np.array(sample.TotalParam[124], dtype=np.float64)
|
|
103
|
+
ti = (np.array(sample.TotalParam[123], dtype=np.float64) / 60).round(2) # time in minute
|
|
104
|
+
nindex = {"40": 24, "39": 20, "38": 10, "37": 8, "36": 0}
|
|
105
|
+
argon = "39"
|
|
106
|
+
if argon in list(nindex.keys()):
|
|
107
|
+
ar = np.array(sample.DegasValues[nindex[argon]], dtype=np.float64) # 20-21 Argon
|
|
108
|
+
sar = np.array(sample.DegasValues[nindex[argon] + 1], dtype=np.float64)
|
|
109
|
+
elif argon == 'total':
|
|
110
|
+
all_ar = np.array(sample.CorrectedValues, dtype=np.float64) # 20-21 Argon
|
|
111
|
+
ar, sar = ap.calc.arr.add(*all_ar.reshape(5, 2, len(all_ar[0])))
|
|
112
|
+
ar = np.array(ar)
|
|
113
|
+
sar = np.array(sar)
|
|
114
|
+
else:
|
|
115
|
+
raise KeyError
|
|
116
|
+
age = np.array(sample.ApparentAgeValues[2], dtype=np.float64) # 2-3 age
|
|
117
|
+
sage = np.array(sample.ApparentAgeValues[3], dtype=np.float64)
|
|
118
|
+
f = np.cumsum(ar) / ar.sum()
|
|
119
|
+
|
|
120
|
+
# 组合data
|
|
121
|
+
dr2 = [1 for i in range(nsteps)]
|
|
122
|
+
ln_dr2 = [1 for i in range(nsteps)]
|
|
123
|
+
wt = [1 for i in range(nsteps)]
|
|
124
|
+
data = np.array([sequence.value, te, ti, age, sage, ar, sar, f, dr2, ln_dr2, wt]).tolist()
|
|
125
|
+
data.insert(0, (np.where(np.array(data[3]) > 0, True, False) & np.isfinite(data[3])).tolist())
|
|
126
|
+
data.insert(1, [1 for i in range(nsteps)])
|
|
127
|
+
for row in ap.calc.arr.transpose(data):
|
|
128
|
+
print(row)
|
|
129
|
+
return data, name
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def calculate_dr2(f, ti, ar, sar, use_ln=True, logdr2_method="plane"):
|
|
133
|
+
try:
|
|
134
|
+
if str(logdr2_method).lower().startswith('plane'.lower()):
|
|
135
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_plane(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
136
|
+
elif str(logdr2_method).lower() == 'yang':
|
|
137
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_yang(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
138
|
+
elif str(logdr2_method).lower().startswith('sphere'.lower()):
|
|
139
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_sphere(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
140
|
+
elif str(logdr2_method).lower().startswith('Thern'.lower()):
|
|
141
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_thern(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
142
|
+
elif str(logdr2_method).lower().startswith('cylinder'.lower()):
|
|
143
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_cylinder(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
144
|
+
elif str(logdr2_method).lower().startswith('cube'.lower()):
|
|
145
|
+
dr2, ln_dr2, wt = ap.smp.diffusion_funcs.dr2_cube(f, ti, ar=ar, sar=sar, ln=use_ln)
|
|
146
|
+
else:
|
|
147
|
+
raise KeyError(f"Geometric model not found: {str(logdr2_method).lower()}")
|
|
148
|
+
except (Exception, BaseException) as e:
|
|
149
|
+
raise ValueError
|
|
150
|
+
|
|
151
|
+
return dr2, ln_dr2, wt
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def calculate_tc(arr_file_path, logdr2_method='plane', A=55, cooling_rate=10, radius=100, use_ln=True, index=None):
|
|
155
|
+
base = np.e if use_ln else 10
|
|
156
|
+
# [A, cooling_rate, radius] = [55, 10, 100] # 55, 10°C/Ma, 100µm
|
|
157
|
+
|
|
158
|
+
# 读取样品信息
|
|
159
|
+
[_, _, seq_value, te, ti, age, sage, ar, sar, f, dr2, ln_dr2, wt], name = read_sample(arr_file_path=arr_file_path)
|
|
160
|
+
dr2, ln_dr2, wt = calculate_dr2(f, ti, ar, sar, use_ln=use_ln, logdr2_method=logdr2_method)
|
|
161
|
+
te = [i + 273.15 for i in te]
|
|
162
|
+
|
|
163
|
+
@np.vectorize
|
|
164
|
+
def get_da2_e_Tc(b, m):
|
|
165
|
+
k1 = base ** b * ap.thermo.basic.SEC2YEAR # k1: da2
|
|
166
|
+
k2 = -10 * m * ap.thermo.basic.GAS_CONSTANT * np.log(base) # activation energy, kJ
|
|
167
|
+
try:
|
|
168
|
+
# Closure temperature
|
|
169
|
+
k3, _ = ap.thermo.basic.get_tc(da2=k1, sda2=0, E=k2 * 1000, sE=0, pho=0,
|
|
170
|
+
cooling_rate=cooling_rate, A=A)
|
|
171
|
+
except ValueError as e:
|
|
172
|
+
# print(e.args)
|
|
173
|
+
k3 = 999
|
|
174
|
+
return k1, k2, k3 # da2, E, Tc
|
|
175
|
+
|
|
176
|
+
index = np.s_[index if index is not None else list(range(len(te)))]
|
|
177
|
+
each_line = [np.nan for i in range(17)] # [b, sb, a, sa, ..., energy, se, tc, stc]
|
|
178
|
+
temp_err = 5
|
|
179
|
+
X, Y, wtX, wtY = 10000 / np.array(te), np.array(ln_dr2), 10000 * temp_err / np.array(te) ** 2, np.array(wt)
|
|
180
|
+
x, y, wtx, wty = X[index,], Y[index,], wtX[index,], wtY[index]
|
|
181
|
+
Tc_list = []
|
|
182
|
+
|
|
183
|
+
if len(x) > 0:
|
|
184
|
+
|
|
185
|
+
for cooling_rate in np.linspace(start=0, stop=100, num=100):
|
|
186
|
+
# Arrhenius line regression
|
|
187
|
+
# each_line[0:6] = ap.thermo.basic.fit(x, y, wtx, wty) # intercept, slop, sa, sb, chi2, q
|
|
188
|
+
# b (intercept), sb, a (slope), sa, mswd, dF, Di, k, r2, chi_square, p_value, avg_err_s, cov
|
|
189
|
+
each_line[0:13] = ap.calc.regression.york2(x, wtx, y, wty, ri=np.zeros(len(x)))
|
|
190
|
+
each_line[1] = each_line[1] * 1 # 1 sigma
|
|
191
|
+
each_line[3] = each_line[3] * 1 # 1 sigma
|
|
192
|
+
|
|
193
|
+
# monte carlo simulation with 4000 trials
|
|
194
|
+
cov_matrix = np.array([[each_line[1] ** 2, each_line[12]], [each_line[12], each_line[3] ** 2]])
|
|
195
|
+
mean_vector = np.array([each_line[0], each_line[2]])
|
|
196
|
+
random_numbers = np.random.multivariate_normal(mean_vector, cov_matrix, 4000)
|
|
197
|
+
res, cov = ap.calc.basic.monte_carlo(get_da2_e_Tc, random_numbers, confidence_level=0.95)
|
|
198
|
+
da2, E, Tc = res[0:3, 0]
|
|
199
|
+
# sda2, sE, sTc = np.diff(res[0:3, [1, 2]], axis=1).flatten() / 2
|
|
200
|
+
sda2, sE, sTc = 2 * cov[0, 0] ** .5, 2 * cov[1, 1] ** .5, 2 * cov[2, 2] ** .5 # 95%
|
|
201
|
+
|
|
202
|
+
each_line[13:15] = [E, sE]
|
|
203
|
+
each_line[15:17] = [Tc, sTc]
|
|
204
|
+
|
|
205
|
+
Tc_list.append([cooling_rate, Tc, sTc])
|
|
206
|
+
|
|
207
|
+
Tc_list = np.transpose(Tc_list)
|
|
208
|
+
|
|
209
|
+
return each_line, X, Y, x, y, Tc_list, name
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def plot_Tc(file_path, index=None, radius=100, use_ln=True):
|
|
213
|
+
if index is None:
|
|
214
|
+
index = [1, 2, 3, 4, 5]
|
|
215
|
+
logdr2_methods = ['plane', 'cylinder', 'sphere']
|
|
216
|
+
As = [8.7, 27, 55]
|
|
217
|
+
|
|
218
|
+
x1_extent = [10, 0]
|
|
219
|
+
y1_extent = [-5, -10]
|
|
220
|
+
|
|
221
|
+
x2_extent = [0, 100]
|
|
222
|
+
y2_extent = [0, 450]
|
|
223
|
+
|
|
224
|
+
fig, axs = plt.subplots(len(logdr2_methods), 2, figsize=(12, 12))
|
|
225
|
+
for i in range(len(logdr2_methods)):
|
|
226
|
+
logdr2_method = logdr2_methods[i]
|
|
227
|
+
A = As[i]
|
|
228
|
+
each_line, X, Y, x, y, Tc_list, name = calculate_tc(file_path, logdr2_method=logdr2_method, A=A, radius=radius,
|
|
229
|
+
use_ln=use_ln, index=index, cooling_rate=10)
|
|
230
|
+
print(each_line)
|
|
231
|
+
[E, sE] = each_line[13:15]
|
|
232
|
+
axs[i, 0].scatter(X, Y, c='white', edgecolors='black')
|
|
233
|
+
axs[i, 0].scatter(x, y, c='red')
|
|
234
|
+
axs[i, 0].plot([min(x), max(x)], [i * each_line[2] + each_line[0] for i in [min(x), max(x)]], c='blue')
|
|
235
|
+
axs[i, 0].set_title(f'{name} - Arrhenius Plot - {logdr2_method}')
|
|
236
|
+
axs[i, 0].set_xlabel(f'10000 / T')
|
|
237
|
+
axs[i, 0].set_ylabel(f'ln(D/r2)' if use_ln else f'log(D/r2)')
|
|
238
|
+
axs[i, 0].text(axs[0, 0].get_xlim()[0], np.average(axs[0, 0].get_ylim()),
|
|
239
|
+
f'intercept = {each_line[0]:.6f} ± {each_line[1]:.6f}\n'
|
|
240
|
+
f'slope = {each_line[2]:.6f} ± {each_line[3]:.6f}\n'
|
|
241
|
+
f'E = {E / 4.184:.6f} ± {2 * sE / 4.184:.6f} kcal/mol (2sigma)\n'
|
|
242
|
+
f'log(D0/r2) = {each_line[0]:.6f} ± {2 * each_line[1]:.6f} /s (2sigma)\n'
|
|
243
|
+
f'A = {A}\n'
|
|
244
|
+
f'radius = {radius} µm')
|
|
245
|
+
|
|
246
|
+
for s in Tc_list[2]:
|
|
247
|
+
axs[i, 1].plot([Tc_list[0], Tc_list[0]], [Tc_list[1]-2*s, Tc_list[1]+2*s], c="#f0f0f0")
|
|
248
|
+
axs[i, 1].plot([Tc_list[0], Tc_list[0]], [Tc_list[1]-s, Tc_list[1]+s], c="#8e8e8e")
|
|
249
|
+
|
|
250
|
+
axs[i, 1].plot(Tc_list[0], Tc_list[1], c="black")
|
|
251
|
+
axs[i, 1].set_ylim(*[y2_extent])
|
|
252
|
+
axs[i, 1].set_xlim(*[x2_extent])
|
|
253
|
+
axs[i, 1].set_xlabel(f'Cooling Rate')
|
|
254
|
+
axs[i, 1].set_ylabel(f'Closure Temperature')
|
|
255
|
+
|
|
256
|
+
x1_extent = [min(axs[i, 0].get_xlim()[0], x1_extent[0]), max(axs[i, 0].get_xlim()[1], x1_extent[1])]
|
|
257
|
+
y1_extent = [min(axs[i, 0].get_ylim()[0], y1_extent[0]), max(axs[i, 0].get_ylim()[1], y1_extent[1])]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
for i in range(len(logdr2_methods)):
|
|
261
|
+
axs[i, 0].set_xlim(*[x1_extent])
|
|
262
|
+
axs[i, 0].set_ylim(*[y1_extent])
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
print(Tc_list[0])
|
|
266
|
+
fig.tight_layout()
|
|
267
|
+
plt.show()
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def export_ar_relase_curve():
|
|
271
|
+
|
|
272
|
+
plot_data = {
|
|
273
|
+
"data": [],
|
|
274
|
+
"file_name": f"-Tc",
|
|
275
|
+
"plot_names": [f"-Tc"],
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
plot_data['data'].append({
|
|
279
|
+
'xAxis': [{
|
|
280
|
+
'extent': [400, 1500], 'interval': [400, 600, 800, 1000, 1200, 1400, 1600],
|
|
281
|
+
'title': f'Temperature [°C]', 'nameLocation': 'middle',
|
|
282
|
+
'show_frame': True, 'label_size': 10, 'title_size': 10,
|
|
283
|
+
}],
|
|
284
|
+
'yAxis': [{
|
|
285
|
+
'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100],
|
|
286
|
+
# 'extent': [-25, 0], 'interval': [-30, -25, -20, -15, -10, -5, 0],
|
|
287
|
+
'title': f'Cumulative argon released [%]', 'nameLocation': 'middle',
|
|
288
|
+
'show_frame': True, 'label_size': 10, 'title_size': 10,
|
|
289
|
+
}],
|
|
290
|
+
'series': [
|
|
291
|
+
]
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
plot_data['data'].append({
|
|
295
|
+
'xAxis': [{
|
|
296
|
+
'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100],
|
|
297
|
+
'title': 'Cooling Rate [°C/Ma]', 'nameLocation': 'middle', 'show_frame': True,
|
|
298
|
+
'label_size': 10, 'title_size': 10,
|
|
299
|
+
}],
|
|
300
|
+
'yAxis': [{
|
|
301
|
+
'extent': [0, 850], 'interval': [0, 100, 200, 300, 400, 500, 600, 700, 800],
|
|
302
|
+
'title': 'Closure Temperature [°C]', 'nameLocation': 'middle', 'show_frame': True,
|
|
303
|
+
'label_size': 10, 'title_size': 10,
|
|
304
|
+
}],
|
|
305
|
+
'series': []
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
colors = {"bt": 'black', 'ms': 'red', 'tour': 'grey', 'amp': 'blue', 'pl': '#a4df82', 'kfs': '#a43c82'}
|
|
309
|
+
sample_types = [
|
|
310
|
+
r"bt",
|
|
311
|
+
r"ms",
|
|
312
|
+
r"bt",
|
|
313
|
+
r"bt",
|
|
314
|
+
r"ms",
|
|
315
|
+
r"ms",
|
|
316
|
+
r"bt",
|
|
317
|
+
r"ms",
|
|
318
|
+
r"kfs",
|
|
319
|
+
r"kfs",
|
|
320
|
+
r"kfs",
|
|
321
|
+
r"kfs",
|
|
322
|
+
r"kfs",
|
|
323
|
+
r"kfs",
|
|
324
|
+
r"kfs",
|
|
325
|
+
r"kfs",
|
|
326
|
+
r"kfs",
|
|
327
|
+
r"kfs",
|
|
328
|
+
r"tour",
|
|
329
|
+
r"tour",
|
|
330
|
+
r"tour",
|
|
331
|
+
r"tour",
|
|
332
|
+
r"tour",
|
|
333
|
+
r"tour",
|
|
334
|
+
r"amp",
|
|
335
|
+
r"amp",
|
|
336
|
+
r"amp",
|
|
337
|
+
r"amp",
|
|
338
|
+
r"amp",
|
|
339
|
+
]
|
|
340
|
+
files = [
|
|
341
|
+
r"D:\DjangoProjects\webarar\static\download\20241121_24FY01a.arr",
|
|
342
|
+
r"D:\DjangoProjects\webarar\static\download\20241123_24FY02a.arr",
|
|
343
|
+
r"D:\DjangoProjects\webarar\static\download\20241125_24FY03a.arr",
|
|
344
|
+
r"D:\DjangoProjects\webarar\static\download\20241129_24FY06a.arr",
|
|
345
|
+
r"D:\DjangoProjects\webarar\static\download\20241130_24FY07a.arr",
|
|
346
|
+
r"D:\DjangoProjects\webarar\private\upload\20241201_24FY08a.arr",
|
|
347
|
+
r"D:\DjangoProjects\webarar\static\download\20241202_24FY09a.arr",
|
|
348
|
+
r"D:\DjangoProjects\webarar\static\download\20241203_24FY10a.arr",
|
|
349
|
+
r"D:\DjangoProjects\webarar\private\upload\20240630_24FY49a.arr",
|
|
350
|
+
r"D:\DjangoProjects\webarar\private\upload\20240705_24FY50a.arr",
|
|
351
|
+
r"D:\DjangoProjects\webarar\private\upload\20240710_24FY51a.arr",
|
|
352
|
+
r"D:\DjangoProjects\webarar\private\upload\20240714_24FY52.arr",
|
|
353
|
+
r"D:\DjangoProjects\webarar\private\upload\20240728_24FY55a.arr",
|
|
354
|
+
r"D:\DjangoProjects\webarar\private\upload\20240801_24FY61.arr",
|
|
355
|
+
r"D:\DjangoProjects\webarar\private\upload\20241016_24FY66a.arr",
|
|
356
|
+
r"D:\DjangoProjects\webarar\private\upload\20240821_24FY67a.arr",
|
|
357
|
+
r"D:\DjangoProjects\webarar\private\upload\20240924_24FY70a.arr",
|
|
358
|
+
r"D:\DjangoProjects\webarar\private\upload\20240823_24FY71a.arr",
|
|
359
|
+
r"D:\DjangoProjects\webarar\private\upload\20241212_24FY80a.arr",
|
|
360
|
+
r"C:\Users\Young\OneDrive\00-Projects\【2】个人项目\2022-05论文课题\初稿\[01]ArAr\Gaowu\20241115_24FY81a.arr",
|
|
361
|
+
r"D:\DjangoProjects\webarar\static\download\20241210_24FY82a.arr",
|
|
362
|
+
r"D:\DjangoProjects\webarar\static\download\20241019_24FY83a.arr",
|
|
363
|
+
r"D:\DjangoProjects\webarar\private\upload\Table_M - BH04 diffusion experiment.arr",
|
|
364
|
+
r"D:\DjangoProjects\webarar\private\mdd\MA08-1\Table_K - MA08 diffusion experiment.arr",
|
|
365
|
+
r"D:\DjangoProjects\webarar\private\mdd\126KD57\126KD57-Dinh2023.arr",
|
|
366
|
+
r"D:\DjangoProjects\webarar\private\mdd\Growdon2013\CT0714-Growdon2013.arr",
|
|
367
|
+
r"D:\DjangoProjects\webarar\private\mdd\Growdon2013\CT0705A-Growdon2013.arr",
|
|
368
|
+
r"D:\DjangoProjects\webarar\private\mdd\Growdon2013\CT0712-Growdon2013.arr",
|
|
369
|
+
r"D:\DjangoProjects\webarar\private\mdd\Growdon2013\CT0726-Growdon2013.arr",
|
|
370
|
+
]
|
|
371
|
+
for arr_file, sample_type in zip(files, sample_types):
|
|
372
|
+
print(f"{sample_type = }, {arr_file = }")
|
|
373
|
+
sample = ap.from_arr(file_path=arr_file)
|
|
374
|
+
te = np.array(sample.TotalParam[124], dtype=np.float64)
|
|
375
|
+
ar = np.array(sample.DegasValues[20], dtype=np.float64) # 20-21 Argon 39
|
|
376
|
+
f = np.cumsum(ar) / ar.sum() * 100
|
|
377
|
+
|
|
378
|
+
plot_data['data'][-2]['series'].append(
|
|
379
|
+
{
|
|
380
|
+
'type': 'series.line', 'id': f'scatter_line', 'name': f'scatters_line',
|
|
381
|
+
'color': colors[sample_type], 'line_width': 1,
|
|
382
|
+
'data': np.transpose([te, f]).tolist(), 'line_caps': 'none',
|
|
383
|
+
},
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
params_list = {
|
|
387
|
+
"page_size": 'a4', "ppi": 72, "width": 9.5, "height": 7,
|
|
388
|
+
"pt_width": 0.8, "pt_height": 0.8, "pt_left": 0.16, "pt_bottom": 0.18,
|
|
389
|
+
"offset_top": 0, "offset_right": 0, "offset_bottom": 25, "offset_left": 35,
|
|
390
|
+
"plot_together": False, "show_frame": True,
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
filename = f"释放曲线"
|
|
394
|
+
filepath = os.path.join(r"C:\Users\Young\Downloads", f"{filename}.pdf")
|
|
395
|
+
cvs = [[ap.smp.export.get_cv_from_dict(plot, **params_list) for plot in plot_data['data']]]
|
|
396
|
+
filepath = ap.smp.export.export_chart_to_pdf(cvs, filename, filepath)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
if __name__ == "__main__":
|
|
401
|
+
file_path = r"D:\DjangoProjects\webarar\private\mdd\Y01\20241121_24FY01a-removeHT.arr"
|
|
402
|
+
index = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
403
|
+
|
|
404
|
+
# file_path = r"D:\DjangoProjects\webarar\private\mdd\MA08-2\Table_L - MA08 diffusion experiment.arr"
|
|
405
|
+
# index = [0, 1, 2, 3, 4, 5]
|
|
406
|
+
# # plot_Tc(file_path, index=index)
|
|
407
|
+
#
|
|
408
|
+
# file_path = r"D:\DjangoProjects\webarar\private\mdd\MA08-1\Table_K - MA08 diffusion experiment.arr"
|
|
409
|
+
# index = [4, 5, 6, 7, 8]
|
|
410
|
+
#
|
|
411
|
+
# file_path = r"D:\DjangoProjects\webarar\private\mdd\CR99NW\CR99NW Shi 2020.arr"
|
|
412
|
+
# index = list(range(10))
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
# file_path = r"D:\DjangoProjects\webarar\private\mdd\Y07"
|
|
416
|
+
# index = list(range(1, 9))
|
|
417
|
+
#
|
|
418
|
+
# plot_Tc(file_path, index=index, use_ln=True, radius=100)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
# for cr in [1, 10, 20, 40, 60, 80, 100]:
|
|
422
|
+
# tc, _ = ap.thermo.basic.get_tc(da2=0.077 / (0.0140 ** 2) * 3600 * 24 * 365.24, sda2=0, E=47*1000 * 4.184, sE=0, pho=0,
|
|
423
|
+
# cooling_rate=cr, A=55)
|
|
424
|
+
# print(f"cooling rate = {cr}, tc = {tc}")
|
|
425
|
+
#
|
|
426
|
+
# for cr in [1, 10, 20, 40, 60, 80, 100]:
|
|
427
|
+
# tc, _ = ap.thermo.basic.get_tc(da2=18 * 3600 * 24 * 365.24, sda2=0, E=87*1000 * 4.184, sE=0, pho=0,
|
|
428
|
+
# cooling_rate=cr, A=6)
|
|
429
|
+
# print(f"cooling rate = {cr}, tc = {tc}")
|
|
430
|
+
#
|
|
431
|
+
# for cr in [1, 10, 20, 40, 60, 80, 100]:
|
|
432
|
+
# tc, _ = ap.thermo.basic.get_tc(da2=10**9.05 * 3600 * 24 * 365.24, sda2=0, E=83.79*1000 * 4.184, sE=0, pho=0,
|
|
433
|
+
# cooling_rate=cr, A=55)
|
|
434
|
+
# print(f"cooling rate = {cr}, tc = {tc}")
|
|
435
|
+
|
|
436
|
+
export_ar_relase_curve()
|
|
437
|
+
|
ararpy/__init__.py
CHANGED
|
@@ -16,10 +16,10 @@ from . import calc, smp, files, thermo, test
|
|
|
16
16
|
""" Information """
|
|
17
17
|
|
|
18
18
|
name = 'ararpy'
|
|
19
|
-
version = '0.
|
|
19
|
+
version = '0.2.2'
|
|
20
20
|
__version__ = version
|
|
21
21
|
full_version = version
|
|
22
|
-
last_update = '
|
|
22
|
+
last_update = '2026-01-01'
|
|
23
23
|
|
|
24
24
|
""" ArArPy Functions """
|
|
25
25
|
|
|
@@ -62,7 +62,7 @@ Sample.results = lambda _smp: smp.basic.get_results(_smp)
|
|
|
62
62
|
Sample.sequence = lambda _smp: smp.basic.get_sequence(_smp)
|
|
63
63
|
|
|
64
64
|
Sample.initial = smp.initial.initial
|
|
65
|
-
Sample.set_selection = lambda _smp, _index, _mark: smp.
|
|
65
|
+
Sample.set_selection = lambda _smp, _index, _mark: smp.basic.set_selection(_smp, _index, _mark)
|
|
66
66
|
Sample.update_table = lambda _smp, _data, _id: smp.table.update_handsontable(_smp, _data, _id)
|
|
67
67
|
|
|
68
68
|
# Sample.unknown = lambda _smp: ArArData(name='unknown', data=_smp.SampleIntercept)
|
|
@@ -141,6 +141,5 @@ RawData.get_sequence = smp.raw.get_sequence
|
|
|
141
141
|
RawData.to_sample = smp.initial.from_raw_data
|
|
142
142
|
RawData.get_unknown = lambda _raw: smp.raw.get_sequence(_raw, True, 'is_unknown', unique=False)
|
|
143
143
|
RawData.get_blank = lambda _raw: smp.raw.get_sequence(_raw, True, 'is_blank', unique=False)
|
|
144
|
-
RawData.get_air = lambda _raw: smp.raw.get_sequence(_raw, True, 'is_air', unique=False)
|
|
145
144
|
Sequence.get_data_df = lambda _seq: pd.DataFrame(_seq.data)
|
|
146
145
|
Sequence.get_flag_df = lambda _seq: pd.DataFrame(_seq.flag)
|
ararpy/calc/age.py
CHANGED
|
@@ -41,11 +41,13 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
|
|
|
41
41
|
J = arr.array_as_float(kwargs.pop('J'))
|
|
42
42
|
sJ = arr.array_as_float(kwargs.pop('sJ') * J / 100)
|
|
43
43
|
A = arr.array_as_float(kwargs.pop('A'))
|
|
44
|
-
sA = arr.array_as_float(kwargs.pop('sA') * A / 100)
|
|
44
|
+
sA = arr.array_as_float(kwargs.pop('sA') * A / 100) # total A, A = Aec + (Ab+) + (Ab-). Ab- for Ca
|
|
45
45
|
Ae = arr.array_as_float(kwargs.pop('Ae'))
|
|
46
|
-
sAe = arr.array_as_float(kwargs.pop('sAe') * Ae / 100)
|
|
46
|
+
sAe = arr.array_as_float(kwargs.pop('sAe') * Ae / 100) # Aec
|
|
47
47
|
Ab = arr.array_as_float(kwargs.pop('Ab'))
|
|
48
|
-
sAb = arr.array_as_float(kwargs.pop('sAb') * Ab / 100)
|
|
48
|
+
sAb = arr.array_as_float(kwargs.pop('sAb') * Ab / 100) # Ab-
|
|
49
|
+
Abp = arr.array_as_float(kwargs.pop('Abp'))
|
|
50
|
+
sAbp = arr.array_as_float(kwargs.pop('sAbp') * Ab / 100) # Ab+
|
|
49
51
|
W = arr.array_as_float(kwargs.pop('W'))
|
|
50
52
|
sW = arr.array_as_float(kwargs.pop('sW') * W / 100)
|
|
51
53
|
Y = arr.array_as_float(kwargs.pop('Y'))
|
|
@@ -62,21 +64,21 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
|
|
|
62
64
|
sLb = arr.array_as_float(kwargs.pop('sLb') * Lb / 100)
|
|
63
65
|
t = arr.array_as_float(kwargs.pop('t'))
|
|
64
66
|
st = arr.array_as_float(kwargs.pop('st'))
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
Ap = arr.array_as_float(kwargs.pop('Ap'))
|
|
68
|
+
sAp = arr.array_as_float(kwargs.pop('sAp') * Ap / 100)
|
|
69
|
+
Kp = arr.array_as_float(kwargs.pop('Kp'))
|
|
70
|
+
sKp = arr.array_as_float(kwargs.pop('sKp') * Kp / 100)
|
|
69
71
|
|
|
70
|
-
#
|
|
72
|
+
# calculating using Min et al.(2000) equation
|
|
71
73
|
# lmd = A * W * Y / (f * No)
|
|
72
74
|
V = f * No / ((Ab + Ae) * W * Y)
|
|
73
|
-
sf = 0
|
|
74
75
|
sV = pow((V / f * sf) ** 2 + (V / No * sNo) ** 2 + (V / (Ab + Ae)) ** 2 * (sAb ** 2 + sAe ** 2) +
|
|
75
76
|
(V / W * sW) ** 2 + (V / Y * sY) ** 2, 0.5)
|
|
77
|
+
|
|
76
78
|
# standard age in year, change to Ma
|
|
77
79
|
t = t * 1000000
|
|
78
80
|
st = st * 1000000
|
|
79
|
-
# back-calculating Ar40/Ar39
|
|
81
|
+
# back-calculating Ar40/Ar39 of the standard
|
|
80
82
|
stdR = (np.exp(t * L) - 1) / J
|
|
81
83
|
# errors of standard age and decay constants were not applied
|
|
82
84
|
sStdR = pow((stdR / J) ** 2 * sJ ** 2, 0.5)
|
|
@@ -85,31 +87,27 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
|
|
|
85
87
|
sR_1 = np.sqrt((sF / stdR) ** 2 + (F * sStdR / stdR ** 2) ** 2) # errors of measured 40Ar/39Ar and J value
|
|
86
88
|
sR_2 = np.sqrt((sF / stdR) ** 2) # error of measured 40Ar/39Ar only
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
useStandardAge = True
|
|
91
|
+
if useStandardAge:
|
|
92
|
+
# ln part in Min 2000 equation
|
|
93
|
+
BB = 1
|
|
94
|
+
KK = np.exp(t / V) - 1 # 40Arr / 40K Use standard age
|
|
95
|
+
else: # use Ar40* and K concentrations of primary standard
|
|
96
|
+
# not fanished, this function is wrong
|
|
97
|
+
BB = (Ab + Ae) / Ae
|
|
98
|
+
KK = Ap / Kp / f
|
|
99
|
+
raise TypeError(f"Not use standard age. Not supported.")
|
|
100
|
+
|
|
90
101
|
XX = BB * KK * R + 1
|
|
91
102
|
k0 = V * np.log(XX)
|
|
92
|
-
|
|
93
|
-
e2 = (np.log(XX) * V / No) ** 2 * sNo ** 2 # sNo
|
|
94
|
-
e3 = (-1 * np.log(XX) * V / A + BB * KK * R / (A * XX)) ** 2 * sAb ** 2 # sAb
|
|
95
|
-
e4 = (-1 * np.log(XX) * V / A - Ab * KK * R / (Ae ** 2 * XX)) ** 2 * sAe ** 2 # sAe
|
|
96
|
-
e5 = (-1 * np.log(XX) * V / W - V * BB * KK * R / (W * XX)) ** 2 * sW ** 2 # sW
|
|
97
|
-
e6 = (np.log(XX) * V / Y) ** 2 * sY ** 2 # sY
|
|
98
|
-
e7 = (V * BB * KK / XX) ** 2 * sR_1 ** 2 # sR
|
|
99
|
-
# e8 = (V * BB * KK * R / (Ap * XX)) ** 2 * sAp ** 2 # sAp
|
|
100
|
-
# e9 = (V * BB * KK * R / (Kp * XX)) ** 2 * sKp ** 2 # sKp
|
|
101
|
-
e8, e9 = 0, 0
|
|
102
|
-
# useDecayConst = False
|
|
103
|
-
# if useDecayConst: # k0 = log(L / Le * KK * R + 1) / L
|
|
104
|
-
# e1 = (V * BB * KK * R / (f * XX)) ** 2 * sf ** 2
|
|
105
|
-
# e2 = 0
|
|
106
|
-
# e3 = (-1 * np.log(XX) * V / L + BB * KK * R / (L * XX)) ** 2 * sLb ** 2
|
|
107
|
-
# e4 = (-1 * np.log(XX) * V / L - Lb * KK * R / (Le ** 2 * XX)) ** 2 * sLe ** 2
|
|
108
|
-
# e5 = (V * BB * KK * R / (W * XX)) ** 2 * sW ** 2
|
|
109
|
-
# e6 = 0
|
|
110
|
-
useStandardAge = True
|
|
103
|
+
|
|
111
104
|
if useStandardAge:
|
|
112
|
-
|
|
105
|
+
# k0 = V * ln(exp(t/V) - 1 * R + 1)
|
|
106
|
+
e1 = (np.log(XX) - R * (KK + 1) * t / (V * XX)) ** 2 * sV ** 2 # sV
|
|
107
|
+
e2 = (BB * (KK + 1) * R / XX) ** 2 * st ** 2 # st
|
|
108
|
+
e3 = (V * BB * KK / XX) ** 2 * sR_1 ** 2 # sR
|
|
109
|
+
else:
|
|
110
|
+
e1, e2, e3 = 0, 0, 0
|
|
113
111
|
|
|
114
112
|
# change to Ma
|
|
115
113
|
# analytical error, error of 40Ar/39Ar only
|
|
@@ -117,7 +115,7 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
|
|
|
117
115
|
# internal error, errors of 40Ar/39Ar and J value
|
|
118
116
|
s2 = np.sqrt((V * KK * BB / XX) ** 2 * sR_1 ** 2)
|
|
119
117
|
# total external error
|
|
120
|
-
s3 = np.sqrt(e1 + e2 + e3
|
|
118
|
+
s3 = np.sqrt(e1 + e2 + e3)
|
|
121
119
|
age = k0
|
|
122
120
|
return age, s1, s2, s3
|
|
123
121
|
|
|
@@ -146,7 +144,7 @@ def calc_age_general(F, sF, J, sJ, L, sL, **kwargs):
|
|
|
146
144
|
v1 = sF ** 2 * (J / (L * (1 + J * F))) ** 2
|
|
147
145
|
v2 = sJ ** 2 * (F / (L * (1 + J * F))) ** 2
|
|
148
146
|
v3 = sL ** 2 * (np.log(1 + J * F) / (L ** 2)) ** 2
|
|
149
|
-
s1 = v1 ** .5 # analytical error
|
|
150
|
-
s2 = (v1 + v2) ** .5 # internal error
|
|
151
|
-
s3 = (v1 + v2 + v3) ** .5 # full external error
|
|
147
|
+
s1 = v1 ** .5 # analytical error, F only
|
|
148
|
+
s2 = (v1 + v2) ** .5 # internal error, F and J
|
|
149
|
+
s3 = (v1 + v2 + v3) ** .5 # full external error. F, J and L
|
|
152
150
|
return age, s1, s2, s3
|
ararpy/calc/arr.py
CHANGED
|
@@ -299,26 +299,6 @@ def remove(array, old):
|
|
|
299
299
|
return res
|
|
300
300
|
|
|
301
301
|
|
|
302
|
-
def merge(*args):
|
|
303
|
-
""" Merge list objects, one dimensional or two dimensional list should be passed in.
|
|
304
|
-
|
|
305
|
-
Parameters
|
|
306
|
-
----------
|
|
307
|
-
args : one or two dimensional list
|
|
308
|
-
|
|
309
|
-
Returns
|
|
310
|
-
-------
|
|
311
|
-
|
|
312
|
-
"""
|
|
313
|
-
res = []
|
|
314
|
-
for arg in args:
|
|
315
|
-
if is_oneD(arg):
|
|
316
|
-
res.append(arg)
|
|
317
|
-
else:
|
|
318
|
-
res = res + arg
|
|
319
|
-
return res
|
|
320
|
-
|
|
321
|
-
|
|
322
302
|
def multi_append(a, *args):
|
|
323
303
|
"""
|
|
324
304
|
Parameters
|
ararpy/calc/basic.py
CHANGED
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
#
|
|
11
11
|
"""
|
|
12
12
|
import copy
|
|
13
|
-
import
|
|
13
|
+
# import secrets
|
|
14
14
|
import string
|
|
15
|
+
import random
|
|
15
16
|
import numpy as np
|
|
16
17
|
from scipy import stats
|
|
17
18
|
from datetime import datetime, timezone, timedelta
|
|
18
19
|
import pytz
|
|
19
20
|
|
|
21
|
+
ALPHABET = string.ascii_lowercase + string.digits
|
|
22
|
+
|
|
20
23
|
|
|
21
24
|
def utc_dt(dt: datetime, tz: str = "utc", is_dst: bool = False) -> datetime:
|
|
22
25
|
"""
|
|
@@ -58,6 +61,18 @@ def get_datetime(t_year: int, t_month: int, t_day: int, t_hour: int, t_min: int,
|
|
|
58
61
|
return ts - base
|
|
59
62
|
|
|
60
63
|
|
|
64
|
+
def get_timestring(timestamp: int = 0, base=None):
|
|
65
|
+
"""
|
|
66
|
+
:param timestamp: timestamp (utz)
|
|
67
|
+
:param base: base time [y, m, d, h, m]
|
|
68
|
+
:return:
|
|
69
|
+
"""
|
|
70
|
+
if base is None:
|
|
71
|
+
base = [1970, 1, 1, 0, 0]
|
|
72
|
+
ts = timestamp + datetime(*base, tzinfo=timezone.utc).timestamp()
|
|
73
|
+
return datetime.fromtimestamp(ts, tz=timezone.utc).isoformat(timespec='seconds')
|
|
74
|
+
|
|
75
|
+
|
|
61
76
|
def merge_dicts(a: dict, b: dict):
|
|
62
77
|
"""
|
|
63
78
|
a and b, two dictionary. Return updated a
|
|
@@ -100,8 +115,8 @@ def update_dicts(a: dict, b: dict):
|
|
|
100
115
|
return res
|
|
101
116
|
|
|
102
117
|
|
|
103
|
-
def
|
|
104
|
-
return ''.join(random.choices(
|
|
118
|
+
def random_choice(length: int = 8) -> str:
|
|
119
|
+
return ''.join(random.choices(ALPHABET, k=length))
|
|
105
120
|
|
|
106
121
|
|
|
107
122
|
def monte_carlo(func, inputs, confidence_level, **kwargs):
|
|
@@ -129,3 +144,11 @@ def monte_carlo(func, inputs, confidence_level, **kwargs):
|
|
|
129
144
|
limits = values[:, [l_range, r_range]]
|
|
130
145
|
|
|
131
146
|
return np.concatenate((means, limits), axis=1), cov
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def parser(v: str, t: type):
|
|
150
|
+
if t == bool:
|
|
151
|
+
if str(v).lower().rstrip() in ["true", "1"]:
|
|
152
|
+
return True
|
|
153
|
+
return t(v)
|
|
154
|
+
|