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.
@@ -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.31'
19
+ version = '0.1.34'
20
20
  __version__ = version
21
21
  full_version = version
22
- last_update = '2024-05-22'
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(0)
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
- # return regression.power(a0, a1)
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
- b, seb, rseb, r2, mswd, [b, lnm], [seb, selnm] = linest_res[0:7]
779
- b = np.exp(b)
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 = b * seb # Excel.Logest function do not consider the error propagation
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
- file_path = os.path.join(file_path, f"{sample.Info.sample.name}.arr")
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-135
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['Logs01'])
595
- logs02 = pd.DataFrame(book_contents['Logs02'])
596
- logs03 = pd.DataFrame(book_contents['Logs03'])
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'non-supported version: {version}')
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 - 1
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] - 1]),
367
- float(data_content[start_row + isotope_index[16]][isotope_index[17] - 1]) * f,
368
- float(data_content[start_row + isotope_index[14]][isotope_index[15] - 1]),
369
- float(data_content[start_row + isotope_index[12]][isotope_index[13] - 1]) * f,
370
- float(data_content[start_row + isotope_index[10]][isotope_index[11] - 1]),
371
- float(data_content[start_row + isotope_index[ 8]][isotope_index[ 9] - 1]) * f,
372
- float(data_content[start_row + isotope_index[ 6]][isotope_index[ 7] - 1]),
373
- float(data_content[start_row + isotope_index[ 4]][isotope_index[ 5] - 1]) * f,
374
- float(data_content[start_row + isotope_index[ 2]][isotope_index[ 3] - 1]),
375
- float(data_content[start_row + isotope_index[ 0]][isotope_index[ 1] - 1]) * f,
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 - 1
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: