ararpy 0.1.31__py3-none-any.whl → 0.1.34__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/plot.py +1 -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/calc_file.py +6 -6
- ararpy/files/raw_file.py +16 -13
- ararpy/smp/diffusion_funcs.py +344 -35
- ararpy/smp/export.py +140 -61
- ararpy/smp/initial.py +17 -14
- ararpy/smp/plots.py +4 -4
- ararpy/smp/sample.py +39 -25
- ararpy/smp/style.py +2 -0
- ararpy/smp/table.py +26 -24
- ararpy/thermo/atomic_level_random_walk.py +6 -3
- ararpy/thermo/basic.py +2 -2
- {ararpy-0.1.31.dist-info → ararpy-0.1.34.dist-info}/METADATA +1 -1
- {ararpy-0.1.31.dist-info → ararpy-0.1.34.dist-info}/RECORD +29 -22
- {ararpy-0.1.31.dist-info → ararpy-0.1.34.dist-info}/WHEEL +0 -0
- {ararpy-0.1.31.dist-info → ararpy-0.1.34.dist-info}/licenses/LICENSE +0 -0
- {ararpy-0.1.31.dist-info → ararpy-0.1.34.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.34'
|
|
20
20
|
__version__ = version
|
|
21
21
|
full_version = version
|
|
22
|
-
last_update = '
|
|
22
|
+
last_update = '2025-10-22'
|
|
23
23
|
|
|
24
24
|
""" ArArPy Functions """
|
|
25
25
|
|
ararpy/calc/plot.py
CHANGED
|
@@ -53,9 +53,8 @@ def get_axis_scale(data: list, count=6, increment=None, extra_count=0, min_inter
|
|
|
53
53
|
str(decimal.Decimal(int(interval / mag // min_interval) + min_interval) * decimal.Decimal(str(mag))))
|
|
54
54
|
else:
|
|
55
55
|
increment = decimal.Decimal(increment)
|
|
56
|
-
start = decimal.Decimal(
|
|
56
|
+
start = decimal.Decimal(_min) // increment * increment
|
|
57
57
|
if _min < 0:
|
|
58
|
-
start = -increment
|
|
59
58
|
while start > _min:
|
|
60
59
|
start -= increment
|
|
61
60
|
else:
|
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/calc_file.py
CHANGED
|
@@ -291,8 +291,8 @@ def open_240(data: pd.DataFrame, logs01: pd.DataFrame, logs02: pd.DataFrame):
|
|
|
291
291
|
-999, -999, -999, -999, -999, -999, -999, -999,
|
|
292
292
|
# 123-130
|
|
293
293
|
-999, -999, -999, -999, -999, -999, -999, -999,
|
|
294
|
-
# 131-
|
|
295
|
-
-999, -999, -999, -999, -999,
|
|
294
|
+
# 131-137
|
|
295
|
+
-999, -999, -999, -999, -999, -999, -999,
|
|
296
296
|
]
|
|
297
297
|
|
|
298
298
|
# double transpose to remove keys
|
|
@@ -591,9 +591,9 @@ class ArArCalcFile:
|
|
|
591
591
|
book_contents = read_calc_file(self.file_path)
|
|
592
592
|
# create data frames for book values
|
|
593
593
|
content = pd.DataFrame(book_contents['Data Tables'])
|
|
594
|
-
logs01 = pd.DataFrame(book_contents
|
|
595
|
-
logs02 = pd.DataFrame(book_contents
|
|
596
|
-
logs03 = pd.DataFrame(book_contents
|
|
594
|
+
logs01 = pd.DataFrame(book_contents.get('Logs01', [[]]))
|
|
595
|
+
logs02 = pd.DataFrame(book_contents.get('Logs02', [[]]))
|
|
596
|
+
logs03 = pd.DataFrame(book_contents.get('Logs03', [[]]))
|
|
597
597
|
|
|
598
598
|
start_row = 5
|
|
599
599
|
sequence_num = int(logs03[2][0])
|
|
@@ -613,7 +613,7 @@ class ArArCalcFile:
|
|
|
613
613
|
material = data[46][0]
|
|
614
614
|
analyst = data[48][0]
|
|
615
615
|
else:
|
|
616
|
-
raise ValueError(f'
|
|
616
|
+
raise ValueError(f'Unsupported version: {version}')
|
|
617
617
|
|
|
618
618
|
# change error type, 2sigma to 1sigma..., relative errors to absolute errors
|
|
619
619
|
data = change_error_type(data, header)
|
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:
|