ararpy 0.1.30__py3-none-any.whl → 0.1.33__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 +2 -2
- ararpy/calc/raw_funcs.py +2 -2
- ararpy/calc/regression.py +3 -3
- ararpy/files/arr_file.py +2 -1
- ararpy/files/basic.py +1 -1
- ararpy/files/raw_file.py +16 -13
- ararpy/smp/corr.py +10 -10
- ararpy/smp/diffusion_funcs.py +344 -35
- ararpy/smp/export.py +140 -61
- ararpy/smp/initial.py +18 -15
- ararpy/smp/plots.py +4 -4
- ararpy/smp/sample.py +41 -26
- ararpy/smp/style.py +2 -0
- ararpy/smp/table.py +26 -24
- ararpy/thermo/atomic_level_random_walk.py +56 -48
- ararpy/thermo/basic.py +2 -2
- {ararpy-0.1.30.dist-info → ararpy-0.1.33.dist-info}/METADATA +1 -1
- {ararpy-0.1.30.dist-info → ararpy-0.1.33.dist-info}/RECORD +28 -21
- {ararpy-0.1.30.dist-info → ararpy-0.1.33.dist-info}/WHEEL +0 -0
- {ararpy-0.1.30.dist-info → ararpy-0.1.33.dist-info}/licenses/LICENSE +0 -0
- {ararpy-0.1.30.dist-info → ararpy-0.1.33.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.1.
|
|
19
|
+
version = '0.1.33'
|
|
20
20
|
__version__ = version
|
|
21
21
|
full_version = version
|
|
22
|
-
last_update = '
|
|
22
|
+
last_update = '2025-10-01'
|
|
23
23
|
|
|
24
24
|
""" ArArPy Functions """
|
|
25
25
|
|
ararpy/calc/raw_funcs.py
CHANGED
|
@@ -30,8 +30,8 @@ def get_raw_data_regression_results(points_data, unselected: list = None):
|
|
|
30
30
|
|
|
31
31
|
"""
|
|
32
32
|
def power(a0, a1):
|
|
33
|
-
|
|
34
|
-
raise ValueError("Deprecated regression")
|
|
33
|
+
return regression.power(a0, a1)
|
|
34
|
+
# raise ValueError("Deprecated regression")
|
|
35
35
|
# if unselected is None:
|
|
36
36
|
# unselected = []
|
|
37
37
|
# linesData = []
|
ararpy/calc/regression.py
CHANGED
|
@@ -775,11 +775,11 @@ def logest(a0: list, a1: list):
|
|
|
775
775
|
# y = b * m ^ x, Microsoft Excel LOGEST function, ln(y) = ln(b) + ln(m) * x
|
|
776
776
|
a0 = [np.log(i) for i in a0] # ln(y)
|
|
777
777
|
linest_res = linest(a0, a1)
|
|
778
|
-
|
|
779
|
-
b = np.exp(
|
|
778
|
+
lnb, selnb, rseb, r2, mswd, [lnb, lnm], [selnb, selnm] = linest_res[0:7]
|
|
779
|
+
b = np.exp(lnb)
|
|
780
780
|
m = np.exp(lnm)
|
|
781
781
|
sem = np.exp(lnm) * selnm
|
|
782
|
-
seb =
|
|
782
|
+
seb = np.exp(lnb) * selnb # Excel.Logest function do not consider the error propagation
|
|
783
783
|
rseb = seb / b * 100
|
|
784
784
|
return b, seb, rseb, r2, mswd, m, sem
|
|
785
785
|
|
ararpy/files/arr_file.py
CHANGED
|
@@ -26,7 +26,8 @@ def save(file_path, sample):
|
|
|
26
26
|
-------
|
|
27
27
|
str, file name
|
|
28
28
|
"""
|
|
29
|
-
|
|
29
|
+
if not file_path.endswith(".arr"):
|
|
30
|
+
file_path = os.path.join(file_path, f"{sample.Info.sample.name}.arr")
|
|
30
31
|
with open(file_path, 'wb') as f:
|
|
31
32
|
f.write(pickle.dumps(sample))
|
|
32
33
|
# with open(file_path, 'w') as f:
|
ararpy/files/basic.py
CHANGED
|
@@ -21,7 +21,7 @@ def upload(file, media_dir):
|
|
|
21
21
|
name, suffix = os.path.splitext(file.name)
|
|
22
22
|
if suffix.lower() not in [
|
|
23
23
|
'.xls', '.age', '.xlsx', '.arr', '.jpg', '.png', '.txt',
|
|
24
|
-
'.log', '.seq', '.json', '.ahd', '.csv']:
|
|
24
|
+
'.log', '.seq', '.json', '.ahd', '.csv', '.ngxdp']:
|
|
25
25
|
raise TypeError(f"The imported file is not supported: {suffix}")
|
|
26
26
|
web_file_path = os.path.join(media_dir, file.name)
|
|
27
27
|
with open(web_file_path, 'wb') as f:
|
ararpy/files/raw_file.py
CHANGED
|
@@ -303,6 +303,7 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
|
|
|
303
303
|
except (TypeError, ValueError, IndexError):
|
|
304
304
|
# When parsing the step name fails, the end of the file has been reached
|
|
305
305
|
# raise
|
|
306
|
+
print(traceback.format_exc())
|
|
306
307
|
break
|
|
307
308
|
else:
|
|
308
309
|
options.update({'StepName': step_name})
|
|
@@ -316,6 +317,7 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
|
|
|
316
317
|
if res is not None:
|
|
317
318
|
options.update(dict(zip(DEFAULT_SAMPLE_INFO.keys(), [res.named.get(value, options.get(key)) for key, value in DEFAULT_SAMPLE_INFO.items()])))
|
|
318
319
|
except (TypeError, ValueError, IndexError):
|
|
320
|
+
print(traceback.format_exc())
|
|
319
321
|
break
|
|
320
322
|
else:
|
|
321
323
|
pass
|
|
@@ -352,27 +354,28 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
|
|
|
352
354
|
cycle_num = 0
|
|
353
355
|
f = float(data_index[27]) # Intensity Scale Factor
|
|
354
356
|
data_content = file_contents[data_index[0] - 1 if data_index[0] != 0 else 0]
|
|
357
|
+
base = 1
|
|
355
358
|
for i in range(2000): # measurement cycle sloop
|
|
356
359
|
if break_num < data_index[25]:
|
|
357
360
|
break_num += 1
|
|
358
361
|
continue
|
|
359
362
|
break_num = 0
|
|
360
363
|
if int(data_index[2]) == 0: # == 0, vertical
|
|
361
|
-
start_row = data_index[24] * cycle_num + data_index[25] * cycle_num + header + idx
|
|
364
|
+
start_row = data_index[24] * cycle_num + data_index[25] * cycle_num + header + idx
|
|
362
365
|
try:
|
|
363
366
|
current_step.append([
|
|
364
367
|
str(cycle_num + 1),
|
|
365
368
|
# in sequence: Ar36, Ar37, Ar38, Ar39, Ar40
|
|
366
|
-
float(data_content[start_row + isotope_index[18]][isotope_index[19] -
|
|
367
|
-
float(data_content[start_row + isotope_index[16]][isotope_index[17] -
|
|
368
|
-
float(data_content[start_row + isotope_index[14]][isotope_index[15] -
|
|
369
|
-
float(data_content[start_row + isotope_index[12]][isotope_index[13] -
|
|
370
|
-
float(data_content[start_row + isotope_index[10]][isotope_index[11] -
|
|
371
|
-
float(data_content[start_row + isotope_index[ 8]][isotope_index[ 9] -
|
|
372
|
-
float(data_content[start_row + isotope_index[ 6]][isotope_index[ 7] -
|
|
373
|
-
float(data_content[start_row + isotope_index[ 4]][isotope_index[ 5] -
|
|
374
|
-
float(data_content[start_row + isotope_index[ 2]][isotope_index[ 3] -
|
|
375
|
-
float(data_content[start_row + isotope_index[ 0]][isotope_index[ 1] -
|
|
369
|
+
float(data_content[start_row + isotope_index[18] - base][isotope_index[19] - base]),
|
|
370
|
+
float(data_content[start_row + isotope_index[16] - base][isotope_index[17] - base]) * f,
|
|
371
|
+
float(data_content[start_row + isotope_index[14] - base][isotope_index[15] - base]),
|
|
372
|
+
float(data_content[start_row + isotope_index[12] - base][isotope_index[13] - base]) * f,
|
|
373
|
+
float(data_content[start_row + isotope_index[10] - base][isotope_index[11] - base]),
|
|
374
|
+
float(data_content[start_row + isotope_index[ 8] - base][isotope_index[ 9] - base]) * f,
|
|
375
|
+
float(data_content[start_row + isotope_index[ 6] - base][isotope_index[ 7] - base]),
|
|
376
|
+
float(data_content[start_row + isotope_index[ 4] - base][isotope_index[ 5] - base]) * f,
|
|
377
|
+
float(data_content[start_row + isotope_index[ 2] - base][isotope_index[ 3] - base]),
|
|
378
|
+
float(data_content[start_row + isotope_index[ 0] - base][isotope_index[ 1] - base]) * f,
|
|
376
379
|
])
|
|
377
380
|
except (ValueError, IndexError):
|
|
378
381
|
print(f"Cannot parse isotope data")
|
|
@@ -382,7 +385,7 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
|
|
|
382
385
|
])
|
|
383
386
|
elif int(data_index[2]) == 1: # == 1, horizontal
|
|
384
387
|
start_row = data_index[1] + idx
|
|
385
|
-
col_inc = data_index[24] * cycle_num + data_index[25] * cycle_num -
|
|
388
|
+
col_inc = data_index[24] * cycle_num + data_index[25] * cycle_num - base
|
|
386
389
|
try:
|
|
387
390
|
current_step.append([
|
|
388
391
|
str(cycle_num + 1),
|
|
@@ -413,8 +416,8 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
|
|
|
413
416
|
|
|
414
417
|
step_list.append(current_step)
|
|
415
418
|
idx = data_index[28] * len(step_list)
|
|
416
|
-
|
|
417
419
|
if not check_box_index[0] or len(step_list) >= 500: # check_box_index[0]: multiple sequences
|
|
420
|
+
print(f"Multiple Sequence = {check_box_index[0]}, Step number = {len(step_list)}")
|
|
418
421
|
break
|
|
419
422
|
|
|
420
423
|
if not step_list:
|
ararpy/smp/corr.py
CHANGED
|
@@ -365,12 +365,12 @@ def calc_nor_inv_isochrons(sample: Sample):
|
|
|
365
365
|
n = len(sample.SequenceName)
|
|
366
366
|
try:
|
|
367
367
|
isochron_1 = calc.isochron.get_data(
|
|
368
|
-
*calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
368
|
+
*calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138]),
|
|
369
369
|
*calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]),
|
|
370
370
|
*sample.DegasValues[0:2]
|
|
371
371
|
)
|
|
372
372
|
isochron_2 = calc.isochron.get_data(
|
|
373
|
-
*calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
373
|
+
*calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138]),
|
|
374
374
|
*sample.DegasValues[0:2],
|
|
375
375
|
*calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]))
|
|
376
376
|
except (BaseException, Exception):
|
|
@@ -383,17 +383,17 @@ def calc_cl_isochrons(sample: Sample):
|
|
|
383
383
|
n = len(sample.SequenceName)
|
|
384
384
|
try:
|
|
385
385
|
isochron_3 = calc.isochron.get_data(
|
|
386
|
-
*calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
386
|
+
*calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138]),
|
|
387
387
|
*sample.DegasValues[24:26],
|
|
388
|
-
*calc.arr.mul(sample.DegasValues[10:12], sample.
|
|
388
|
+
*calc.arr.mul(sample.DegasValues[10:12], sample.TotalParam[136:138]))
|
|
389
389
|
isochron_4 = calc.isochron.get_data(
|
|
390
|
-
*calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
391
|
-
*calc.arr.mul(sample.DegasValues[10:12], sample.
|
|
390
|
+
*calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138]),
|
|
391
|
+
*calc.arr.mul(sample.DegasValues[10:12], sample.TotalParam[136:138]),
|
|
392
392
|
*sample.DegasValues[24:26])
|
|
393
393
|
isochron_5 = calc.isochron.get_data(
|
|
394
|
-
*calc.arr.mul(sample.DegasValues[10:12], sample.
|
|
394
|
+
*calc.arr.mul(sample.DegasValues[10:12], sample.TotalParam[136:138]),
|
|
395
395
|
*sample.DegasValues[24:26],
|
|
396
|
-
*calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
396
|
+
*calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138]))
|
|
397
397
|
except (BaseException, Exception):
|
|
398
398
|
return np.zeros([5, n]), np.zeros([5, n]), np.zeros([5, n])
|
|
399
399
|
else:
|
|
@@ -451,7 +451,7 @@ def calc_ratio(sample: Sample, monte_carlo: bool = False):
|
|
|
451
451
|
sample.ApparentAgeValues[0:2] = ar40aar36a
|
|
452
452
|
sample.ApparentAgeValues[7] = ar36a_percent
|
|
453
453
|
else:
|
|
454
|
-
ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.
|
|
454
|
+
ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138])
|
|
455
455
|
sum_ar39k = sum(ar39k)
|
|
456
456
|
ar39k_percent = [item / sum_ar39k * 100 if sum_ar39k != 0 else 0 for item in ar39k]
|
|
457
457
|
ar40rar39k = calc.arr.mul_factor(
|
|
@@ -545,7 +545,7 @@ def monte_carlo_f(sample: Sample):
|
|
|
545
545
|
R36v38clp = np.transpose(sample.TotalParam[56:58])
|
|
546
546
|
|
|
547
547
|
stand_time_year = np.transpose(sample.TotalParam[32])
|
|
548
|
-
JNFactor = np.transpose(sample.
|
|
548
|
+
JNFactor = np.transpose(sample.TotalParam[136:138])
|
|
549
549
|
|
|
550
550
|
irradiation_cycles = [list(filter(None, re.split(r'[DS]', each_step))) for each_step in sample.TotalParam[27]]
|
|
551
551
|
t1 = [re.findall(r"\d+", i) for i in sample.TotalParam[31]] # t1: experimental times
|