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.
@@ -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.26'
19
+ version = '0.1.33'
20
20
  __version__ = version
21
21
  full_version = version
22
- last_update = '2024-05-22'
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
- # 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/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:
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.NormalizeFactor),
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.NormalizeFactor),
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.NormalizeFactor),
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.NormalizeFactor))
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.NormalizeFactor),
391
- *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor),
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.NormalizeFactor),
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.NormalizeFactor))
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.NormalizeFactor)
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.NormalizeFactor)
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