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,344 @@
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 - Show all Kfs age spectra
9
+ # ==========================================
10
+ #
11
+ #
12
+ #
13
+ """
14
+ import os
15
+ import numpy as np
16
+ import ararpy as ap
17
+ import pdf_maker as pm
18
+ import matplotlib
19
+ from matplotlib import cm
20
+ from matplotlib.collections import PathCollection
21
+
22
+ matplotlib.use('TkAgg')
23
+ matplotlib.rc('font',family='Arial', size=10)
24
+ import matplotlib.pyplot as plt
25
+ from matplotlib.patches import Rectangle
26
+
27
+
28
+ heating_schedule = {
29
+ '20240621_24FY56a': 1,
30
+ '20240630_24FY49a': 2,
31
+ '20240705_24FY50a': 2,
32
+ '20240710_24FY51a': 2,
33
+ '20240714_24FY52': 2,
34
+ '20240728_24FY55a': 2,
35
+ '20240821_24FY67a': 2,
36
+ '20240823_24FY71a': 2,
37
+ '20240916_24FY92a': 2,
38
+ '20240920_24FY88a': 2,
39
+ '20240922_24FY89a': 2,
40
+ '20240924_24FY70a': 2,
41
+ '20241005_24FY72a': 3,
42
+ '20241009_24FY62a': 3,
43
+ '20241013_24FY64b': 3,
44
+ '20241016_24FY66a': 4,
45
+ '20241023_24FY68a': 5,
46
+ '20241118_24FY93a': 7,
47
+ '20241204_24FY53b': 7,
48
+ '20241206_24FY54b': 6,
49
+ '20241208_24FY87b': 6,
50
+ '20241209_24FY86b': 6,
51
+ }
52
+
53
+ cc = {
54
+ 'Y49': 2,
55
+ 'Y50': 2,
56
+ 'Y51': 2,
57
+ 'Y52': 2,
58
+ 'Y53': 7,
59
+ 'Y54': 6,
60
+ 'Y55': 2,
61
+ 'Y56': 1,
62
+ 'Y62': 3,
63
+ 'Y64': 3,
64
+ 'Y66': 4,
65
+ 'Y67': 2,
66
+ 'Y68': 5,
67
+ 'Y70': 2,
68
+ 'Y71': 2,
69
+ 'Y72': 3,
70
+ 'Y86': 6,
71
+ 'Y87': 6,
72
+ 'Y88': 2,
73
+ 'Y89': 2,
74
+ 'Y93': 7,
75
+ 'Y92': 2,
76
+ }
77
+
78
+
79
+ def transform(ax: plt.Axes):
80
+ xlabels = [i.get_text().replace('−', '-') for i in ax.get_xticklabels()]
81
+ ylabels = [i.get_text().replace('−', '-') for i in ax.get_yticklabels()]
82
+ linestyles = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
83
+
84
+ series = []
85
+ for i, line in enumerate(ax.lines):
86
+ xy_data = line.get_xydata() # [[x1, y1], [x2, y2], ...]
87
+ line_style = linestyles.get(line.get_linestyle(), 'solid')
88
+ series.append({
89
+ 'type': 'series.line', 'id': f'line-{i}', 'name': f'line-{i}',
90
+ 'color': line.get_color(), 'line_width': 1, 'line_style': line_style,
91
+ 'data': xy_data, 'line_caps': 'none'
92
+ })
93
+ if bool(line._marker):
94
+ series.append({
95
+ 'type': 'series.scatter', 'id': f'line-marker-{i}', 'name': f'line-marker-{i}',
96
+ 'stroke_color': line.get_markeredgecolor(), 'fill_color': line.get_markerfacecolor(),
97
+ 'data': xy_data, 'size': 2,
98
+ # 'symbol': line._marker.markers.get(line.get_marker(), 'square'),
99
+ 'symbol': 'rec'
100
+ })
101
+ for i, collection in enumerate(ax.collections):
102
+ series.append({
103
+ 'type': 'series.scatter', 'id': f'scatter-{i}', 'name': f'{collection.get_label()}',
104
+ 'stroke_color': collection.get_edgecolor()[0][:3], 'fill_color': collection.get_edgecolor()[0][:3],
105
+ 'data': collection.get_offsets(), 'size': 2,
106
+ 'symbol': 'rec'
107
+ })
108
+
109
+ for i, text in enumerate(ax.texts):
110
+ xy_data = text.get_position() # [[x1, y1], [x2, y2], ...]
111
+ series.append({
112
+ 'type': 'series.text', 'id': f'text-{i}', 'name': f'text-{i}',
113
+ 'color': text.get_color(), 'data': [xy_data], 'text': text.get_text().replace('\n', '<r>'),
114
+ 'size': 8
115
+ })
116
+
117
+ for child in ax._children:
118
+ if isinstance(child, Rectangle):
119
+ ld = [*child.get_xy(), child.get_width(), child.get_height()]
120
+ series.append({
121
+ 'type': 'series.rect', 'id': f'rect-{child.get_gid()}', 'name': f'rect-{child.get_gid()}',
122
+ 'color': child.get_edgecolor()[:3], 'fill_color': child.get_facecolor()[:3], 'fill': True,
123
+ 'data': [ld], 'label': child.get_label(), 'clip': True
124
+ })
125
+
126
+ series.append({
127
+ 'type': 'series.text', 'id': f'title', 'name': f'title',
128
+ 'color': 'black', 'data': [[sum(ax.get_xlim()) / 2, ax.get_ylim()[1]]],
129
+ 'h_align': "middle", 'v_align': "top",
130
+ 'text': ax.get_title(), 'size': 8
131
+ })
132
+
133
+ if ax.legend_ is not None:
134
+ for handle, text in zip(ax.legend_.legend_handles, ax.legend_.texts):
135
+ series.append({
136
+ 'type': 'series.text', 'id': f'legend', 'name': f'legend',
137
+ 'color': text.get_color(), 'data': [[ax.get_xlim()[0], ax.get_ylim()[0]]],
138
+ 'h_align': "left", 'v_align': "bottom",
139
+ 'text': text.get_text(), 'size': 8
140
+ })
141
+ if isinstance(handle, plt.Line2D):
142
+ series.append({
143
+ 'type': 'series.line', 'id': f'legend-line', 'name': f'legend-line-{text.get_text()}',
144
+ 'color': handle.get_color(), 'data':[[ax.get_xlim()[0], ax.get_ylim()[0]], [ax.get_xlim()[1], ax.get_ylim()[1]]],
145
+ 'line_width': 1, 'line_style': linestyles.get(handle.get_linestyle(), 'solid')
146
+ })
147
+ if isinstance(handle, PathCollection):
148
+ stroke_c = handle.get_edgecolor()[0][:3]
149
+ stroke_c = f"#{int(stroke_c[0]*255):02x}{int(stroke_c[1]*255):02x}{int(stroke_c[2]*255):02x}"
150
+ fill_c = handle.get_facecolor()[0][:3]
151
+ fill_c = f"#{int(fill_c[0]*255):02x}{int(fill_c[1]*255):02x}{int(fill_c[2]*255):02x}"
152
+ series.append({
153
+ 'type': 'series.scatter', 'id': f'legend-scatter', 'name': f'legend-scatter-{text.get_text()}',
154
+ 'stroke_color': stroke_c, 'fill_color': fill_c,
155
+ 'data': [[sum(ax.get_xlim()) / 2, sum(ax.get_ylim()) / 2]],
156
+ 'size': 2, 'symbol': 'rec'
157
+ })
158
+
159
+ data = {
160
+ 'xAxis': [{
161
+ 'extent': ax.get_xlim(), 'interval': xlabels, 'title': ax.get_xlabel(),
162
+ 'nameLocation': 'middle', 'show_frame': True, 'label_size': 8, 'title_size': 8,
163
+ }],
164
+ 'yAxis': [{
165
+ 'extent': ax.get_ylim(), 'interval': ylabels, 'title': ax.get_ylabel(),
166
+ 'nameLocation': 'middle', 'show_frame': True, 'label_size': 8, 'title_size': 8,
167
+ }],
168
+ 'series': series
169
+ }
170
+
171
+ # print(data)
172
+ return data
173
+
174
+
175
+ def read_sample(arr_file_path):
176
+ # 读取样品信息
177
+ if not arr_file_path.endswith('.arr'):
178
+ for root, dirs, files in os.walk(arr_file_path):
179
+ for file in files:
180
+ if file.endswith('.arr'):
181
+ arr_file_path = os.path.join(arr_file_path, file)
182
+ break
183
+ sample = ap.from_arr(file_path=arr_file_path)
184
+ name = sample.name()
185
+ sequence = sample.sequence()
186
+ nsteps = sequence.size
187
+ te = np.array(sample.TotalParam[124], dtype=np.float64)
188
+ ti = (np.array(sample.TotalParam[123], dtype=np.float64) / 60).round(2) # time in minute
189
+ nindex = {"40": 24, "39": 20, "38": 10, "37": 8, "36": 0}
190
+ argon = "39"
191
+ argon = "40"
192
+ if argon in list(nindex.keys()):
193
+ ar = np.array(sample.DegasValues[nindex[argon]], dtype=np.float64) # 20-21 Argon
194
+ sar = np.array(sample.DegasValues[nindex[argon] + 1], dtype=np.float64)
195
+ elif argon == 'total':
196
+ all_ar = np.array(sample.CorrectedValues, dtype=np.float64) # 20-21 Argon
197
+ ar, sar = ap.calc.arr.add(*all_ar.reshape(5, 2, len(all_ar[0])))
198
+ ar = np.array(ar)
199
+ sar = np.array(sar)
200
+ else:
201
+ raise KeyError
202
+ age = np.array(sample.ApparentAgeValues[2], dtype=np.float64) # 2-3 age
203
+ sage = np.array(sample.ApparentAgeValues[3], dtype=np.float64)
204
+ f = ar / ar.sum() * 100
205
+
206
+ ar39 = np.array(sample.DegasValues[20], dtype=np.float64)
207
+ ar40 = np.array(sample.DegasValues[24], dtype=np.float64)
208
+
209
+ # f = np.ones(60) * 100 / 60
210
+
211
+ x, y1, y2 = ap.calc.spectra.get_data(age, sage, f, cumulative=False)
212
+
213
+ X = x + list(reversed(x))
214
+ Y = y1 + list(reversed(y2))
215
+
216
+ hs = heating_schedule[name]
217
+
218
+ # if hs != 2:
219
+ # raise ValueError
220
+ print(f"{name = }, {nsteps = }")
221
+
222
+ # if max(y1[15:50]) > 50:
223
+ # print(name)
224
+
225
+ only_te = []
226
+ only_f = []
227
+ for i, tei in enumerate(te):
228
+ if tei not in only_te:
229
+ only_te.append(tei)
230
+ only_f.append(0)
231
+ else:
232
+ only_f[-1] += ar[i]
233
+
234
+ age_plot = sample.AgeSpectraPlot
235
+
236
+
237
+
238
+ # return np.cumsum(ar39) / sum(ar39), np.cumsum(ar40) / sum(ar40), name
239
+ # return x, y1, name
240
+ return X, Y, name
241
+ # return list(range(nsteps+1)), np.insert(f, 0, 0), name
242
+ # return only_te, np.cumsum(only_f) / np.sum(only_f), name
243
+ # return te, f, name
244
+ # return np.transpose([[i * 100 / 60 for i in range(60)], age - sage, [100 / 60 for i in range(60)], 2 * sage])
245
+
246
+
247
+ def check_name(name):
248
+ samples = ['Y64', 'Y66', 'Y67', 'Y68', 'Y70', 'Y72', 'Y86', 'Y88', 'Y89']
249
+ # samples = ['Y71', 'Y87', 'Y92', 'Y93']
250
+ samples = ['Y49', 'Y55', 'Y56', 'Y62']
251
+ samples = ['Y71', 'Y92', 'Y93', 'Y72', 'Y87']
252
+ # samples = ['Y51', 'Y52', 'Y53', 'Y54', 'Y50']
253
+ for i in samples:
254
+ if i in name:
255
+ return True
256
+ raise ValueError
257
+
258
+ fig, axs = plt.subplots(1, 1, figsize=(6, 4))
259
+
260
+ axs.set_xlim(0, 20, auto=False)
261
+ axs.set_ylim(0, 10, auto=False)
262
+ axs.set_title(f'All Kfs age spectra', loc='center', y=1)
263
+ axs.set_ylabel(f'Apparent Age (Ma)')
264
+ axs.set_xlabel(f'Cumulative 39Ar released')
265
+
266
+ i = 0
267
+ v = cm.get_cmap('viridis')
268
+ colors = [v(i) for i in np.random.random(22)]
269
+
270
+
271
+ loc = r"C:\Users\Young\OneDrive\00-Projects\【2】个人项目\2024-10 Ar-Ar扩散理论\钾长石Arr"
272
+ for root, dirs, files in os.walk(loc):
273
+ for file in files:
274
+ if file.endswith('.arr'):
275
+ # for smp in samples:
276
+ # if smp in file:
277
+ arr_file_path = os.path.join(loc, file)
278
+ try:
279
+ check_name(file)
280
+ x, y, name = read_sample(arr_file_path)
281
+ # axs.plot(x, [yi + i * 10 for yi in y], label=name)
282
+ axs.plot(x, y, label=name)
283
+ except Exception as e:
284
+ print(e)
285
+ continue
286
+ # continue
287
+ i += 1
288
+
289
+ axs.legend(loc='best')
290
+ fig.tight_layout()
291
+ plt.show()
292
+
293
+
294
+ filename = f"39argon release excess ar - 2 - matplotlib"
295
+
296
+ params_list = {
297
+ "page_size": 'a4', "ppi": 72, "width": 14, "height": 8,
298
+ "pt_width": 0.8, "pt_height": 0.8, "pt_left": 0.16, "pt_bottom": 0.18,
299
+ "offset_top": 0, "offset_right": 0, "offset_bottom": 20, "offset_left": 30,
300
+ "plot_together": False, "show_frame": False,
301
+ 'xlabel_offset': 8, 'ylabel_offset': 2
302
+ }
303
+
304
+ plot_data = {
305
+ "data": [
306
+ transform(axs),
307
+ ],
308
+ "file_name": filename,
309
+ "plot_names": [f"plotname"],
310
+ }
311
+
312
+ filepath = os.path.join(r"C:\Users\Young\Downloads", f"{filename}.pdf")
313
+ cvs = [[ap.smp.export.get_cv_from_dict(plot, **params_list) for plot in plot_data['data']]]
314
+ for i in range(len(cvs[0])):
315
+ pt = cvs[0][i]._plot_areas[0]
316
+ for index, legned in enumerate(list(filter(lambda cp: cp.name() == 'legend', pt._components))):
317
+ legned._size = 7
318
+ legned._z_index = 250
319
+ legned._h_align = "left"
320
+ legned._v_align = "center"
321
+ if i == 0: # age spectra
322
+ legned._x = 175
323
+ legned._y = 40 + index * 10
324
+ elif i == 1: # cooling history
325
+ legned._x = 65
326
+ legned._y = 135 - index * 10
327
+ elif i == 2: # arrhenius
328
+ legned._x = 75
329
+ legned._y = 40 + index * 10
330
+ else:
331
+ legned._x = 65
332
+ legned._y = 40 + index * 10
333
+ for comp in pt._components:
334
+ if legned._text in comp.name() and "legend" in comp.name():
335
+ comp._z_index = 250
336
+ if isinstance(comp, pm.Scatter):
337
+ comp._x = legned._x - 10
338
+ comp._y = legned._y
339
+ if isinstance(comp, pm.Line):
340
+ comp._start = [legned._x - 16, legned._y]
341
+ comp._end = [legned._x - 4, legned._y]
342
+
343
+
344
+ filepath = ap.smp.export.export_chart_to_pdf(cvs, filename, filepath)