ararpy 0.1.199__py3-none-any.whl → 0.2.1__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.
Files changed (40) hide show
  1. ararpy/Example - Check arr.py +52 -0
  2. ararpy/Example - Granite Cooling History.py +411 -0
  3. ararpy/Example - Plot temperature calibration.py +291 -0
  4. ararpy/Example - Show MDD results.py +561 -0
  5. ararpy/Example - Show all Kfs age spectra.py +344 -0
  6. ararpy/Example - Show random walk results.py +363 -0
  7. ararpy/Example - Tc calculation.py +437 -0
  8. ararpy/__init__.py +3 -4
  9. ararpy/calc/age.py +34 -36
  10. ararpy/calc/arr.py +0 -20
  11. ararpy/calc/basic.py +26 -3
  12. ararpy/calc/corr.py +131 -85
  13. ararpy/calc/plot.py +1 -2
  14. ararpy/calc/raw_funcs.py +41 -2
  15. ararpy/calc/regression.py +224 -132
  16. ararpy/files/arr_file.py +2 -1
  17. ararpy/files/basic.py +0 -22
  18. ararpy/files/calc_file.py +107 -84
  19. ararpy/files/raw_file.py +242 -229
  20. ararpy/smp/basic.py +133 -34
  21. ararpy/smp/calculation.py +6 -6
  22. ararpy/smp/corr.py +339 -153
  23. ararpy/smp/diffusion_funcs.py +345 -36
  24. ararpy/smp/export.py +247 -129
  25. ararpy/smp/info.py +2 -2
  26. ararpy/smp/initial.py +93 -45
  27. ararpy/smp/json.py +2 -2
  28. ararpy/smp/plots.py +144 -164
  29. ararpy/smp/raw.py +11 -15
  30. ararpy/smp/sample.py +222 -181
  31. ararpy/smp/style.py +26 -7
  32. ararpy/smp/table.py +42 -33
  33. ararpy/thermo/atomic_level_random_walk.py +56 -48
  34. ararpy/thermo/basic.py +2 -2
  35. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/METADATA +1 -1
  36. ararpy-0.2.1.dist-info/RECORD +73 -0
  37. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/WHEEL +1 -1
  38. ararpy-0.1.199.dist-info/RECORD +0 -66
  39. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/licenses/LICENSE +0 -0
  40. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2025 Yang. - All Rights Reserved
2
+
3
+ #!/usr/bin/env python
4
+ # -*- coding: UTF-8 -*-
5
+ """
6
+ # ==========================================
7
+ # Copyright 2025 Yang
8
+ # ararpy - Example - Check arr
9
+ # ==========================================
10
+ #
11
+ #
12
+ #
13
+ """
14
+ import os
15
+ import ararpy as ap
16
+ import numpy as np
17
+ import pdf_maker as pm
18
+
19
+
20
+ def read_sample(arr_file_path):
21
+ # 读取样品信息
22
+ if not arr_file_path.endswith('.arr'):
23
+ for root, dirs, files in os.walk(arr_file_path):
24
+ for file in files:
25
+ if file.endswith('.arr'):
26
+ arr_file_path = os.path.join(arr_file_path, file)
27
+ break
28
+ print(f"arr file: {arr_file_path}")
29
+ sample = ap.from_arr(file_path=arr_file_path)
30
+ name = sample.name()
31
+ sequence = sample.sequence()
32
+ nsteps = sequence.size
33
+ arratio = sample.TotalParam[0][0]
34
+ if sample.Info.sample.type == "Unknown":
35
+ print(f"{name = }, {arratio = }")
36
+ # sample.TotalParam[0] = [298.56 for i in sample.TotalParam[0]]
37
+ sample.Info.preference["confidenceLevel"] = 2
38
+ # ap.smp.calculation.recalculate(sample, re_plot=True, re_plot_style=True, re_set_table=True, re_table_style=True)
39
+ ap.save(sample, arr_file_path)
40
+
41
+
42
+ loc = r"C:\Users\Young\OneDrive\00-Projects\【2】个人项目\2022-05论文课题\【3】分析测试\ArAr\01-VU实验数据和记录\Arr Data"
43
+ # read_sample(os.path.join(loc, "20240918_24FY87.arr"))
44
+ # read_sample(loc)
45
+
46
+ for root, dirs, files in os.walk(loc):
47
+ for file in files:
48
+ if file.endswith('.arr'):
49
+ arr_file_path = os.path.join(loc, file)
50
+ read_sample(arr_file_path)
51
+
52
+
@@ -0,0 +1,411 @@
1
+ # Copyright (C) 2025 Yang. - All Rights Reserved
2
+
3
+ #!/usr/bin/env python
4
+ # -*- coding: UTF-8 -*-
5
+ """
6
+ # ==========================================
7
+ # Copyright 2025 Yang
8
+ # ararpy - Example - Granite Cooling History
9
+ # ==========================================
10
+ #
11
+ #
12
+ #
13
+ """
14
+
15
+ # Copyright (C) 2025 Yang. - All Rights Reserved
16
+
17
+ #!/usr/bin/env python
18
+ # -*- coding: UTF-8 -*-
19
+ """
20
+ # ==========================================
21
+ # Copyright 2025 Yang
22
+ # ararpy - Example - Show MDD results
23
+ # ==========================================
24
+ #
25
+ #
26
+ #
27
+ """
28
+ import ararpy as ap
29
+ import numpy as np
30
+ import pdf_maker as pm
31
+ import os
32
+
33
+ import matplotlib
34
+ from matplotlib.collections import PathCollection
35
+
36
+ matplotlib.use('TkAgg')
37
+ matplotlib.rc('font',family='Arial', size=10)
38
+ import matplotlib.pyplot as plt
39
+ from matplotlib.patches import Rectangle
40
+ # 设置全局字体,确保中文正常显示
41
+ # plt.rcParams["font.family"] = ["SimHei"] # 中文字体
42
+ # plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
43
+
44
+
45
+
46
+ def conf(input_x, input_y, num=None, using_binom=False, using_normal=False, start=None, end=None):
47
+ """
48
+ Calculate 90% confident interval of the given distribution of cooling histories.
49
+ Parameters
50
+ ----------
51
+ input_x: x, array like 2D
52
+ input_y: y, array like 2D
53
+ count:
54
+
55
+ Returns
56
+ -------
57
+
58
+ """
59
+
60
+ if len(input_x) != len(input_y):
61
+ raise ValueError("length of input x does not equal to that of input y")
62
+
63
+ ns = len(input_x)
64
+ if start is None:
65
+ start = min([min(i) for i in input_x])
66
+ if end is None:
67
+ end = max([max(i) for i in input_x])
68
+ nt = 18 if num is None else num
69
+
70
+ if not (using_normal or using_binom):
71
+ using_binom = True
72
+
73
+ x_conf = np.linspace(start, end, num=nt)
74
+ y_conf = np.zeros((nt, 4))
75
+ ytemp = np.zeros((nt, ns))
76
+ # 初始化数组
77
+ xmed = np.zeros(nt)
78
+ ave = np.zeros(nt)
79
+ adev = np.zeros(nt)
80
+ sdev = np.zeros(nt)
81
+ var = np.zeros(nt)
82
+ skew = np.zeros(nt)
83
+ curt = np.zeros(nt)
84
+
85
+ # 计算每个曲线的温度值
86
+ for k, out_x in enumerate(x_conf):
87
+ for i in range(ns):
88
+ xs = input_x[i]
89
+ ys = input_y[i]
90
+ for j in range(len(xs)-1):
91
+ if xs[j] >= out_x >= xs[j+1]:
92
+ ytemp[k, i] = (ys[j+1] - ys[j]) / (xs[j+1] - xs[j]) * (out_x - xs[j]) + ys[j]
93
+ break
94
+ # 排序
95
+ ytemp[k] = np.sort(ytemp[k])
96
+ # 计算均值、中位数
97
+ ave[k], adev[k], sdev[k], var[k], skew[k], curt[k], xmed[k] = stats = moment(ytemp[k])
98
+ # 计算置信区间索引
99
+ if using_binom:
100
+ j1, j2 = ap.smp.diffusion_funcs.binom(ns) #
101
+ j3, j4 = int(round(ns * 0.05)) - 1, int(ns - round(ns * 0.05)) - 1 # 95%
102
+ y1, y2, y3, y4 = ytemp[k][j1], ytemp[k][j2], ytemp[k][j3], ytemp[k][j4]
103
+ elif using_normal:
104
+ y1, y2, y3, y4 = ave[k] - sdev[k], ave[k] + sdev[k], ave[k] - 2 * sdev[k], ave[k] + 2 * sdev[k]
105
+ else:
106
+ raise KeyError("use binom or using normal")
107
+ y_conf[k] = [y1, y2, y3, y4]
108
+ return x_conf, y_conf
109
+
110
+
111
+ def moment(data):
112
+ """ 计算分布的统计矩阵:均值、平均偏差、标准差、方差、偏度、峰度、中位数 """
113
+ # 去除NaN值
114
+ data = data[~np.isnan(data)]
115
+ n = len(data)
116
+ if n == 0:
117
+ return [np.nan] * 7
118
+
119
+ mean = np.mean(data)
120
+ adev = np.mean(np.abs(data - mean)) # 平均偏差
121
+ sdev = np.std(data, ddof=1) # 样本标准差
122
+ var = sdev ** 2 # 方差
123
+ med = np.median(data) # 中位数
124
+
125
+ # 偏度 (三阶矩)
126
+ if sdev == 0:
127
+ skew = 0.0
128
+ else:
129
+ skew = np.sum(((data - mean) / sdev) ** 3) / n
130
+
131
+ # 峰度 (四阶矩)
132
+ if sdev == 0:
133
+ curt = 0.0
134
+ else:
135
+ curt = np.sum(((data - mean) / sdev) ** 4) / n - 3.0 # 减去3使正态分布峰度为0
136
+
137
+ return mean, adev, sdev, var, skew, curt, med
138
+
139
+
140
+ def is_number(s):
141
+ try:
142
+ float(s)
143
+ return True
144
+ except:
145
+ return False
146
+
147
+
148
+ def read_data(file):
149
+ data = []
150
+ rows = []
151
+ go = True
152
+ while go:
153
+ go = False
154
+ group = np.zeros([200, 20], dtype='<U64')
155
+ row = 0
156
+ while True:
157
+ try:
158
+ line = file.readline().rstrip("\n")
159
+ print(line)
160
+ if line == "":
161
+ break
162
+ for col, _ in enumerate([str(l) for l in line.split(',')]):
163
+ group[row][col] = _
164
+ except (Exception, BaseException) as e:
165
+ print(e)
166
+ break
167
+ else:
168
+ row += 1
169
+ data.append(group)
170
+ rows.append(row)
171
+ return data, rows
172
+
173
+
174
+ def plot_CH(file, sname=None, title="", **params):
175
+
176
+ file_IN = open(file, "r")
177
+ [data], [nstep] = read_data(file_IN)
178
+
179
+
180
+ initial_age = params.pop("initial_age", 0)
181
+ final_age = params.pop("final_age", 20)
182
+ x1_extent = params.pop("x1_extent", [0, 50])
183
+ y1_extent = params.pop("y1_extent", [0, 900])
184
+ x2_extent = params.pop("x2_extent", [initial_age, final_age])
185
+ y2_extent = params.pop("y2_extent", [0, 500])
186
+ x3_extent = params.pop("x3_extent", [4, 16])
187
+ y3_extent = params.pop("y3_extent", [-10, 0])
188
+ x4_extent = params.pop("x4_extent", [0, 1000])
189
+ y4_extent = params.pop("y4_extent", [200, 1600])
190
+ autoscaling = params.pop("autoscaling", False)
191
+ export_PDF = params.pop("export_PDF", False)
192
+ index = params.pop("index", [])
193
+
194
+ main_color = ['#397DA1', '#BA5624', '#212121', '#3C6933', '#74757C', '#214193', '#524715'] # blue red black green
195
+ middle_color = ['#83CDFA', '#F1B595', '#737373', '#84B775', '#C1C3CB', '#6D8AE1', '#C0A737']
196
+ shallow_color = ['#E0F1FE', '#FBEBE3', '#DDDDDD', '#CFFEC0', '#EDEEF8', '#D6DFFC', '#FCF0BC']
197
+
198
+ print(f"{sname = }, {title = }")
199
+
200
+ fig, axs = plt.subplots(1, 1, figsize=(6, 4))
201
+
202
+ font_settings = {
203
+ # 'fontsize': 10,
204
+ # 'fontfamily': 'Arial'
205
+ }
206
+
207
+ colors = {
208
+ "biotite": {"facecolor": "#F1B595", "edgecolor": "#BA5624"},
209
+ "黑云母": {"facecolor": "#F1B595", "edgecolor": "#BA5624"},
210
+ "zircon": {"facecolor": "#737373", "edgecolor": "#212121"},
211
+ "锆石": {"facecolor": "#737373", "edgecolor": "#212121"},
212
+ "muscovite": {"facecolor": "#83CDFA", "edgecolor": "#397DA1"},
213
+ "白云母": {"facecolor": "#83CDFA", "edgecolor": "#397DA1"},
214
+ "monazite": {"facecolor": "#84B775", "edgecolor": "#3C6933"},
215
+ "独居石": {"facecolor": "#84B775", "edgecolor": "#3C6933"},
216
+ "apatite": {"facecolor": "#D6DFFC", "edgecolor": "#6D8AE1"},
217
+ "磷灰石": {"facecolor": "#D6DFFC", "edgecolor": "#6D8AE1"},
218
+ "xenotime": {"facecolor": "#C0A737", "edgecolor": "#524715"},
219
+ "磷钇矿": {"facecolor": "#C0A737", "edgecolor": "#524715"},
220
+ "电气石": {"facecolor": "white", "edgecolor": "#524715"},
221
+ "角闪石": {"facecolor": "white", "edgecolor": "#524715"},
222
+ }
223
+
224
+ axs.set_xlim(*x1_extent, auto=autoscaling)
225
+ axs.set_ylim(*y1_extent, auto=autoscaling)
226
+ body = data[:nstep, 0]
227
+ area = data[:nstep, 1]
228
+ lithology = data[:nstep, 2]
229
+ sample_number = data[:nstep, 3]
230
+ mineral = data[:nstep, 4]
231
+ method = data[:nstep, 5]
232
+ age = data[:nstep, 6].astype(np.float32)
233
+ sage = data[:nstep, 7].astype(np.float32)
234
+ reference = data[:nstep, 8]
235
+ tc = data[:nstep, 9].astype(np.float32)
236
+ stc = data[:nstep, 10].astype(np.float32)
237
+ print(f"{nstep = }")
238
+ for i in np.argsort(sage)[::-1]:
239
+ color = colors[mineral[i]]
240
+ print(f"age = {age[i]} +/- {sage[i]}, Tc = {tc[i]} +/- {stc[i]}")
241
+ linestyle = "solid"
242
+ rect = Rectangle(
243
+ (age[i]-sage[i], tc[i]-stc[i]), width=2 * sage[i], height=2 * stc[i], **color,
244
+ linestyle=linestyle
245
+ )
246
+ axs.add_patch(rect)
247
+ axs.set_title(f'{title}', loc='center', y=1, **font_settings)
248
+ axs.set_xlabel(f'Age (Ma)', **font_settings)
249
+ axs.set_ylabel(f'Temperature (°C)', **font_settings)
250
+
251
+ fig.tight_layout()
252
+ plt.show()
253
+
254
+ if not export_PDF:
255
+ return
256
+
257
+ filename = f"{title} - cooling history - matplotlib"
258
+
259
+ params_list = {
260
+ "page_size": 'a4', "ppi": 72, "width": 14, "height": 8,
261
+ "pt_width": 0.8, "pt_height": 0.8, "pt_left": 0.16, "pt_bottom": 0.18,
262
+ "offset_top": 0, "offset_right": 0, "offset_bottom": 20, "offset_left": 30,
263
+ "plot_together": False, "show_frame": False,
264
+ 'xlabel_offset': 8, 'ylabel_offset': 2
265
+ }
266
+
267
+ plot_data = {
268
+ "data": [
269
+ transform(axs),
270
+ ],
271
+ "file_name": filename,
272
+ "plot_names": [f"plotname"],
273
+ }
274
+
275
+ filepath = os.path.join(r"C:\Users\Young\Downloads", f"{filename}.pdf")
276
+ cvs = [[ap.smp.export.get_cv_from_dict(plot, **params_list) for plot in plot_data['data']]]
277
+ for i in range(len(cvs[0])):
278
+ pt = cvs[0][i]._plot_areas[0]
279
+ title = pt.get_comp(comp_name="title")
280
+ title._y -= 2
281
+ title._z_index = 999
282
+ filepath = ap.smp.export.export_chart_to_pdf(cvs, filename, filepath)
283
+
284
+
285
+ def transform(ax: plt.Axes):
286
+ xlabels = [i.get_text().replace('−', '-') for i in ax.get_xticklabels()]
287
+ ylabels = [i.get_text().replace('−', '-') for i in ax.get_yticklabels()]
288
+ linestyles = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
289
+
290
+ series = []
291
+ for i, line in enumerate(ax.lines):
292
+ xy_data = line.get_xydata() # [[x1, y1], [x2, y2], ...]
293
+ line_style = linestyles.get(line.get_linestyle(), 'solid')
294
+ series.append({
295
+ 'type': 'series.line', 'id': f'line-{i}', 'name': f'line-{i}',
296
+ 'color': line.get_color(), 'line_width': 1, 'line_style': line_style,
297
+ 'data': xy_data, 'line_caps': 'none'
298
+ })
299
+ if bool(line._marker):
300
+ series.append({
301
+ 'type': 'series.scatter', 'id': f'line-marker-{i}', 'name': f'line-marker-{i}',
302
+ 'stroke_color': line.get_markeredgecolor(), 'fill_color': line.get_markerfacecolor(),
303
+ 'data': xy_data, 'size': 2,
304
+ # 'symbol': line._marker.markers.get(line.get_marker(), 'square'),
305
+ 'symbol': 'rec'
306
+ })
307
+ for i, collection in enumerate(ax.collections):
308
+ series.append({
309
+ 'type': 'series.scatter', 'id': f'scatter-{i}', 'name': f'{collection.get_label()}',
310
+ 'stroke_color': collection.get_edgecolor()[0][:3], 'fill_color': collection.get_edgecolor()[0][:3],
311
+ 'data': collection.get_offsets(), 'size': 2,
312
+ 'symbol': 'rec'
313
+ })
314
+
315
+ for i, text in enumerate(ax.texts):
316
+ xy_data = text.get_position() # [[x1, y1], [x2, y2], ...]
317
+ series.append({
318
+ 'type': 'series.text', 'id': f'text-{i}', 'name': f'text-{i}',
319
+ 'color': text.get_color(), 'data': [xy_data], 'text': text.get_text().replace('\n', '<r>'),
320
+ 'size': 8
321
+ })
322
+
323
+ for child in ax._children:
324
+ if isinstance(child, Rectangle):
325
+ ld = [*child.get_xy(), child.get_width(), child.get_height()]
326
+ series.append({
327
+ 'type': 'series.rect', 'id': f'rect-{child.get_gid()}', 'name': f'rect-{child.get_gid()}',
328
+ 'color': child.get_edgecolor()[:3], 'fill_color': child.get_facecolor()[:3], 'fill': True,
329
+ 'data': [ld], 'label': child.get_label(), 'clip': True
330
+ })
331
+
332
+ series.append({
333
+ 'type': 'series.text', 'id': f'title', 'name': f'title',
334
+ 'color': 'black', 'data': [[sum(ax.get_xlim()) / 2, ax.get_ylim()[1]]],
335
+ 'h_align': "middle", 'v_align': "top",
336
+ 'text': ax.get_title(), 'size': 8
337
+ })
338
+
339
+ if ax.legend_ is not None:
340
+ for handle, text in zip(ax.legend_.legend_handles, ax.legend_.texts):
341
+ series.append({
342
+ 'type': 'series.text', 'id': f'legend', 'name': f'legend',
343
+ 'color': text.get_color(), 'data': [[ax.get_xlim()[0], ax.get_ylim()[0]]],
344
+ 'h_align': "left", 'v_align': "bottom",
345
+ 'text': text.get_text(), 'size': 8
346
+ })
347
+ if isinstance(handle, plt.Line2D):
348
+ series.append({
349
+ 'type': 'series.line', 'id': f'legend-line', 'name': f'legend-line-{text.get_text()}',
350
+ 'color': handle.get_color(), 'data':[[ax.get_xlim()[0], ax.get_ylim()[0]], [ax.get_xlim()[1], ax.get_ylim()[1]]],
351
+ 'line_width': 1, 'line_style': linestyles.get(handle.get_linestyle(), 'solid')
352
+ })
353
+ if isinstance(handle, PathCollection):
354
+ stroke_c = handle.get_edgecolor()[0][:3]
355
+ stroke_c = f"#{int(stroke_c[0]*255):02x}{int(stroke_c[1]*255):02x}{int(stroke_c[2]*255):02x}"
356
+ fill_c = handle.get_facecolor()[0][:3]
357
+ fill_c = f"#{int(fill_c[0]*255):02x}{int(fill_c[1]*255):02x}{int(fill_c[2]*255):02x}"
358
+ series.append({
359
+ 'type': 'series.scatter', 'id': f'legend-scatter', 'name': f'legend-scatter-{text.get_text()}',
360
+ 'stroke_color': stroke_c, 'fill_color': fill_c,
361
+ 'data': [[sum(ax.get_xlim()) / 2, sum(ax.get_ylim()) / 2]],
362
+ 'size': 2, 'symbol': 'rec'
363
+ })
364
+
365
+ data = {
366
+ 'xAxis': [{
367
+ 'extent': ax.get_xlim(), 'interval': xlabels, 'title': ax.get_xlabel(),
368
+ 'nameLocation': 'middle', 'show_frame': True, 'label_size': 8, 'title_size': 8,
369
+ }],
370
+ 'yAxis': [{
371
+ 'extent': ax.get_ylim(), 'interval': ylabels, 'title': ax.get_ylabel(),
372
+ 'nameLocation': 'middle', 'show_frame': True, 'label_size': 8, 'title_size': 8,
373
+ }],
374
+ 'series': series
375
+ }
376
+
377
+ # print(data)
378
+ return data
379
+
380
+
381
+
382
+ if __name__ == "__main__":
383
+
384
+ params = {
385
+ "initial_age": 0,
386
+ "final_age": 11,
387
+ "x1_extent": [0, 60],
388
+ "y1_extent": [0, 900],
389
+ "x2_extent": [0, 11],
390
+ "y2_extent": [0, 500],
391
+ "x3_extent": [4, 16],
392
+ "y3_extent": [-10, 0],
393
+ "x4_extent": [0, 1800],
394
+ "y4_extent": [200, 1600],
395
+ "autoscaling": False,
396
+ # "autoscaling": True,
397
+ # "export_PDF": False,
398
+ "export_PDF": True,
399
+ "index": list(range(2, 17)),
400
+ }
401
+
402
+
403
+ s = 'yalaxiangbo'
404
+ s = 'paiku'
405
+ s = 'kuday'
406
+ s = 'ramba'
407
+ s = 'gaowu'
408
+ s = 'luozha'
409
+ loc = os.path.join("D:\DjangoProjects\webarar\private\mdd", f"{s}.txt")
410
+ plot_CH(file=loc, title=f"{s.capitalize()} - Cooling History", **params)
411
+