ararpy 0.1.11__py3-none-any.whl → 0.1.13__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/smp/export.py CHANGED
@@ -17,9 +17,11 @@ import sys
17
17
  import pickle
18
18
  import traceback
19
19
  import pdf_maker as pm
20
+ import numpy as np
20
21
  from decimal import Decimal
21
22
 
22
- from ..calc import arr, isochron
23
+ from ..calc import arr, isochron, spectra
24
+ from ..calc.basic import get_random_digits
23
25
  from . import basic, sample, consts
24
26
 
25
27
  Sample = sample.Sample
@@ -41,6 +43,467 @@ def to_pdf(file_path: str, figure: str, smp: Sample):
41
43
  pdf.save(figure=figure)
42
44
 
43
45
 
46
+ def get_cv_from_dict(data: dict):
47
+ # create a canvas
48
+ cv = pm.Canvas(width=17, height=12, unit="cm", show_frame=True, clip_outside_plot_areas=False)
49
+ # change frame outline style
50
+ cv.show_frame(color="grey", line_width=0.5)
51
+ axis_num = min([len(data['xAxis']), len(data['yAxis'])])
52
+ # draw axis
53
+ plots = []
54
+ for i in range(axis_num):
55
+ scale = [*data['xAxis'][i]['extent'], *data['yAxis'][i]['extent']]
56
+ scale = (*scale,)
57
+ # create plot area based on axis scale
58
+ pt = cv.add_plot_area(name=f"PlotArea{i}", plot_area=(0.15, 0.15, 0.8, 0.8), plot_scale=scale, show_frame=True)
59
+ for stick in data['xAxis'][i]['interval']:
60
+ start = pt.scale_to_points(stick, scale[2])
61
+ end = pt.scale_to_points(stick, scale[2])
62
+ end = (end[0], end[1] - 5)
63
+ if pt.line(start=start, end=end, width=1, line_style="solid", y_clip=False, coordinate="pt", z_index=100):
64
+ pt.text(x=start[0], y=end[1] - 15, text=f"{stick}", clip=False,
65
+ coordinate="pt", h_align="middle", z_index=150)
66
+ for stick in data['yAxis'][i]['interval']:
67
+ start = pt.scale_to_points(scale[0], stick)
68
+ end = pt.scale_to_points(scale[0], stick)
69
+ end = (end[0] - 5, end[1])
70
+ if pt.line(start=start, end=end, width=1, line_style="solid", x_clip=False, coordinate="pt", z_index=100):
71
+ pt.text(x=end[0] - 5, y=end[1], text=f"{stick}", clip=False,
72
+ coordinate="pt", h_align="right", v_align="center", z_index=150)
73
+ # axis titles
74
+ nloc = pt.scale_to_points(sum(scale[:2]) / 2, scale[2])
75
+ pt.text(x=nloc[0], y=nloc[1] - 30, text=data['xAxis'][i]['title'], clip=False, coordinate="pt",
76
+ h_align="middle", v_align="top", z_index=150)
77
+ nloc = pt.scale_to_points(scale[0], sum(scale[2:4]) / 2)
78
+ pt.text(x=nloc[0] - 50, y=nloc[1], text=data['yAxis'][i]['title'], clip=False, coordinate="pt",
79
+ h_align="middle", v_align="bottom", rotate=90, z_index=150)
80
+ plots.append(pt)
81
+ # draw series
82
+ for se in data['series']:
83
+ data = se.get('data', [])
84
+ try:
85
+ pt = plots[se.get('axis_index', 0)]
86
+ except IndexError:
87
+ continue
88
+ if 'line' in se['type']:
89
+ for index in range(1, len(data)):
90
+ pt.line(
91
+ start=data[index - 1], end=data[index], width=se.get('line_width', 1),
92
+ line_style=se.get('line_style', 'solid'), name=se['name'],
93
+ color=se.get('color', 'black'), clip=True, line_caps=se.get('line_caps', 'none'),
94
+ z_index=se.get('z_index', 9))
95
+ if 'scatter' in se['type'] and se['name'] != 'Text':
96
+ for each in data:
97
+ pt.scatter(
98
+ each[0], each[1], fill_color=se.get('fill_color', 'black'), size=se.get('size', 5),
99
+ stroke_color=se.get('stroke_color', se.get('color', 'black')),
100
+ z_index=se.get('z_index', 9)
101
+ )
102
+ if 'scatter' in se['type'] and se['name'] == 'Text' or 'text' in se['type']:
103
+ for each in data:
104
+ pt.text(*each[:2], **se)
105
+ if 'rect' in se['type']:
106
+ for each in data:
107
+ lb = each[:2]; width, height = each[2:4]
108
+ pt.rect(lb, width, height, **se)
109
+
110
+ return cv
111
+
112
+
113
+ def export_chart_to_pdf(data: dict, filepath: str = "", **kwargs):
114
+ """
115
+
116
+ Parameters
117
+ ----------
118
+ filepath: str
119
+ data: dict
120
+ - file_name: string
121
+ file name, like "24WHA0001"
122
+ - data: list of dicts
123
+ properties:
124
+ - name: string
125
+ diagram name, like "Age spectra"
126
+
127
+ - xAxis: list
128
+ properties:
129
+ - extend: list
130
+ limits of values of axis, like [0, 100]
131
+ - interval: list
132
+ sticks location, like [0, 20, 40, 60, 80, 100]
133
+ - title: string
134
+ - name_location: string
135
+ axis title location, 'middle'
136
+
137
+ - yAxis: same as xAxis
138
+
139
+ - series: list
140
+ properties:
141
+ - type: string
142
+ series type, 'line', 'scatter', 'text', and any string contains these characters
143
+ - id: string
144
+ - name: string
145
+ - color: string or list
146
+ color for outlines, color name | RGB triplet | Hex color code
147
+ - fill_color: string or list
148
+ color for filling markers, format is similar to that of color
149
+ - data: 2-dimensional array
150
+ [[x1, y1], [x2, y2], ...]
151
+ - axis_index: int
152
+ index of axis to combine with, which is useful for plotting on different scales.
153
+
154
+ optional:
155
+ - line_caps: string
156
+ for lines only, 'square', 'none', 'butt'
157
+ - text: string
158
+ for texts only
159
+ - size: int
160
+ for scatters only
161
+ **kwargs:
162
+ author, producer, creator, page_size, ppi, ...
163
+
164
+ Returns
165
+ -------
166
+
167
+ """
168
+ title = data.get('file_name', '')
169
+ # write pdf
170
+ file = pm.NewPDF(filepath=filepath, title=f"{title}", **kwargs)
171
+ plot_data = data.get('data', [])
172
+ for index, each in enumerate(plot_data):
173
+ # rich text tags should follow this priority: color > script > break
174
+ file.text(
175
+ page=index, x=50, y=780, line_space=1.2, size=12, base=0, h_align="left",
176
+ text=f"{each.get('name', '')}"
177
+ )
178
+ cv = get_cv_from_dict(each)
179
+ file.canvas(page=index, base=0, margin_top=5, canvas=cv, unit="cm", h_align="middle")
180
+ if index + 1 < len(plot_data):
181
+ file.add_page()
182
+
183
+ # save pdf
184
+ file.save()
185
+
186
+ return filepath
187
+
188
+
189
+ def get_plot_data(smp: Sample, diagram: str = 'age spectra', **options):
190
+ """
191
+
192
+ Parameters
193
+ ----------
194
+ smp
195
+ diagram
196
+ color
197
+ options
198
+
199
+ Returns
200
+ -------
201
+
202
+ """
203
+ if diagram.lower() == "age spectra":
204
+ xAxis, yAxis, series = _get_plot_data_age_spectra(smp, **options)
205
+ elif diagram.lower() == "inverse isochron":
206
+ xAxis, yAxis, series = _get_plot_data_inv_isochron(smp, **options)
207
+ elif "degas spectra" in diagram.lower():
208
+ xAxis, yAxis, series = _get_plot_data_degas_spectra(smp, diagram_name = diagram.lower(), **options)
209
+ elif "degas curve" in diagram.lower():
210
+ xAxis, yAxis, series = _get_plot_data_degas_curve(smp, diagram_name = diagram.lower(), **options)
211
+ else:
212
+ raise KeyError
213
+
214
+ data = {
215
+ 'name': smp.name(), 'xAxis': xAxis, 'yAxis': yAxis, 'series': series
216
+ }
217
+
218
+ print(data)
219
+
220
+ return data
221
+
222
+
223
+ def _get_plot_data_age_spectra(smp: sample, **options):
224
+ color = options.get('color', 'black')
225
+ xAxis, yAxis, series = [], [], []
226
+ age = smp.ApparentAgeValues[2:4]
227
+ ar = smp.DegasValues[20]
228
+ data = spectra.get_data(*age, ar, cumulative=False)
229
+ series.append({
230
+ 'type': 'series.line', 'id': f'line-{get_random_digits()}', 'name': f'line-{get_random_digits()}',
231
+ 'color': color, 'fill_color': color, 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
232
+ 'data': np.transpose([data[0], data[1]]).tolist(), 'line_caps': 'square',
233
+ 'axis_index': 0,
234
+ })
235
+ series.append({
236
+ 'type': 'series.line', 'id': f'line-{get_random_digits()}', 'name': f'line-{get_random_digits()}',
237
+ 'color': color, 'fill_color': color, 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
238
+ 'data': np.transpose([data[0], data[2]]).tolist(), 'line_caps': 'square',
239
+ 'axis_index': 0,
240
+ })
241
+ text1 = smp.AgeSpectraPlot.text1
242
+ text2 = smp.AgeSpectraPlot.text2
243
+ for text in [text1, text2]:
244
+ series.append({
245
+ 'type': 'text', 'id': f'text-{get_random_digits()}', 'name': f'text-{get_random_digits()}',
246
+ 'color': color, 'fill_color': color,
247
+ 'text': smp.name() + '<r>' + text.text.replace("\n", "<r>"), 'size': int(text.font_size / 1.5),
248
+ 'data': [text.pos],
249
+ 'axis_index': 1,
250
+ })
251
+
252
+ xAxis.append({
253
+ 'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100], 'id': 0, 'show_frame': True,
254
+ 'title': 'Cumulative <sup>39</sup>Ar Released (%)', 'name_location': 'middle',
255
+ 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
256
+ })
257
+ xAxis.append({
258
+ 'extent': [0, 100], 'interval': [], 'id': 1, 'show_frame': False,
259
+ 'title': '', 'name_location': 'middle',
260
+ 'line_width': 1, 'line_style': 'solid', 'z_index': 0,
261
+ })
262
+ yAxis.append({
263
+ 'extent': [0, 25], 'interval': [0, 5, 10, 15, 20, 25], 'id': 0, 'show_frame': True,
264
+ 'title': 'Apparent Age (Ma)', 'name_location': 'middle',
265
+ 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
266
+ })
267
+ yAxis.append({
268
+ 'extent': [0, 100], 'interval': [], 'id': 1, 'show_frame': False,
269
+ 'title': '', 'name_location': 'middle',
270
+ 'line_width': 1, 'line_style': 'solid', 'z_index': 0,
271
+ })
272
+ return xAxis, yAxis, series
273
+
274
+
275
+ def _get_plot_data_inv_isochron(smp: sample, **options):
276
+ color = options.get('color', 'black')
277
+ xAxis, yAxis, series = [], [], []
278
+ age = smp.ApparentAgeValues[2:4]
279
+ ar = smp.DegasValues[20]
280
+ data = np.array(smp.InvIsochronPlot.data)
281
+ set1 = smp.InvIsochronPlot.set1.data
282
+ set2 = smp.InvIsochronPlot.set2.data
283
+ set3 = smp.InvIsochronPlot.set3.data
284
+ # set 1
285
+ series.append({
286
+ 'type': 'series.scatter', 'id': f'scatter-{get_random_digits()}', 'name': f'scattter-{get_random_digits()}',
287
+ 'stroke_color': 'red', 'fill_color': 'red', 'myType': 'scatter', 'size': 4, 'line_width': 1,
288
+ 'data': (data[[0, 2], :][:, set1]).transpose().tolist(),
289
+ 'axis_index': 0, 'z_index': 99
290
+ })
291
+ # set 2
292
+ series.append({
293
+ 'type': 'series.scatter', 'id': f'scatter-{get_random_digits()}', 'name': f'scattter-{get_random_digits()}',
294
+ 'stroke_color': 'blue', 'fill_color': 'blue', 'myType': 'scatter', 'size': 4, 'line_width': 1,
295
+ 'data': (data[[0, 2], :][:, set2]).transpose().tolist(),
296
+ 'axis_index': 0, 'z_index': 99
297
+ })
298
+ # set 3
299
+ series.append({
300
+ 'type': 'series.scatter', 'id': f'scatter-{get_random_digits()}', 'name': f'scattter-{get_random_digits()}',
301
+ 'stroke_color': 'black', 'fill_color': 'none', 'myType': 'scatter', 'size': 4, 'line_width': 1,
302
+ 'data': (data[[0, 2], :][:, set3]).transpose().tolist(),
303
+ 'axis_index': 0, 'z_index': 0
304
+ })
305
+
306
+ text1 = smp.InvIsochronPlot.text1
307
+ text2 = smp.InvIsochronPlot.text2
308
+
309
+ series.append({
310
+ 'type': 'text', 'id': f'text-{get_random_digits()}', 'name': f'text-{get_random_digits()}',
311
+ 'color': 'red', 'fill_color': 'red',
312
+ 'text': smp.name() + '<r>' + text1.text.replace("\n", "<r>"), 'size': int(text1.font_size / 1.5),
313
+ 'data': [text1.pos],
314
+ 'axis_index': 1,
315
+ })
316
+ series.append({
317
+ 'type': 'text', 'id': f'text-{get_random_digits()}', 'name': f'text-{get_random_digits()}',
318
+ 'color': 'blue', 'fill_color': 'blue',
319
+ 'text': smp.name() + '<r>' + text2.text.replace("\n", "<r>"), 'size': int(text2.font_size / 1.5),
320
+ 'data': [text2.pos],
321
+ 'axis_index': 1,
322
+ })
323
+
324
+ xaxis = smp.InvIsochronPlot.xaxis
325
+ yaxis = smp.InvIsochronPlot.yaxis
326
+
327
+ xAxis.append({
328
+ 'extent': [float(xaxis.min), float(xaxis.max)],
329
+ 'interval': [float("{:g}".format(float(xaxis.min) + i * float(xaxis.interval))) for i in range(int(xaxis.split_number) + 1)],
330
+ 'id': 0, 'show_frame': True, 'z_index': 9,
331
+ 'title': 'XXXX', 'name_location': 'middle',
332
+ })
333
+ xAxis.append({
334
+ 'extent': [0, 100], 'interval': [], 'id': 1, 'show_frame': False,
335
+ 'title': '', 'name_location': 'middle', 'z_index': 0,
336
+ })
337
+ yAxis.append({
338
+ 'extent': [float(yaxis.min), float(yaxis.max)],
339
+ 'interval': [float("{:g}".format(float(yaxis.min) + i * float(yaxis.interval))) for i in range(int(yaxis.split_number) + 1)],
340
+ 'id': 0, 'show_frame': True, 'z_index': 9,
341
+ 'title': 'YYYY', 'name_location': 'middle',
342
+ })
343
+ yAxis.append({
344
+ 'extent': [0, 100], 'interval': [], 'id': 1, 'show_frame': False,
345
+ 'title': '', 'name_location': 'middle', 'z_index': 0,
346
+ })
347
+ return xAxis, yAxis, series
348
+
349
+
350
+ def _get_plot_data_degas_pattern(smp: sample, **options):
351
+ color = options.get('color', 'black')
352
+ plot = smp.DegasPatternPlot
353
+ xAxis, yAxis, series = [], [], []
354
+ argon = smp.DegasValues[20] # Ar39K as default
355
+ while argon[-1] == 0:
356
+ argon = argon[:-1]
357
+ y = [argon[i] / sum(argon[i:]) * 100 for i in range(len(argon))]
358
+ x = list(range(1, len(argon) + 1))
359
+ data = np.array([x, y])
360
+ # set 1
361
+ series.append({
362
+ 'type': 'series.scatter', 'id': f'scatter-{get_random_digits()}', 'name': f'scattter-{get_random_digits()}',
363
+ 'stroke_color': color, 'fill_color': 'white', 'myType': 'scatter', 'size': 4, 'line_width': 1,
364
+ 'data': data.transpose().tolist(), 'axis_index': 0, 'z_index': 99
365
+ })
366
+
367
+ xaxis = plot.xaxis
368
+ yaxis = plot.yaxis
369
+
370
+ xaxis.min = 0
371
+ xaxis.max = 100
372
+ xaxis.interval = 20
373
+ xaxis.split_number = 5
374
+ yaxis.min = 0
375
+ yaxis.max = 20
376
+ yaxis.interval = 5
377
+ yaxis.split_number = 4
378
+
379
+ xAxis.append({
380
+ 'extent': [float(xaxis.min), float(xaxis.max)],
381
+ 'interval': [float("{:g}".format(float(xaxis.min) + i * float(xaxis.interval))) for i in range(int(xaxis.split_number) + 1)],
382
+ 'id': 0, 'show_frame': True, 'z_index': 9,
383
+ 'title': 'XXXX', 'name_location': 'middle',
384
+ })
385
+ yAxis.append({
386
+ 'extent': [float(yaxis.min), float(yaxis.max)],
387
+ 'interval': [float("{:g}".format(float(yaxis.min) + i * float(yaxis.interval))) for i in range(int(yaxis.split_number) + 1)],
388
+ 'id': 0, 'show_frame': True, 'z_index': 9,
389
+ 'title': 'YYYY', 'name_location': 'middle',
390
+ })
391
+ return xAxis, yAxis, series
392
+
393
+
394
+ def _get_plot_data_degas_spectra(smp: sample, **options):
395
+ name = options.get('diagram_name', '39Ar')
396
+ color = options.get('color', 'black')
397
+ plot = smp.DegasPatternPlot
398
+ xAxis, yAxis, series = [], [], []
399
+ nindex = {"40": 24, "39": 20, "38": 10, "37": 8, "36": 0}
400
+ if name[:2] in list(nindex.keys()):
401
+ ar = np.array(smp.DegasValues[nindex[name[:2]]], dtype=np.float64) # 20-21 Ar39
402
+ sar = np.array(smp.DegasValues[nindex[name[:2]] + 1], dtype=np.float64)
403
+ elif 'total' in name:
404
+ all_ar = np.array(smp.CorrectedValues, dtype=np.float64) # 20-21 Ar39
405
+ ar, sar = arr.add(*all_ar.reshape(5, 2, len(all_ar[0])))
406
+ ar = np.array(ar); sar = np.array(sar)
407
+ else:
408
+ raise KeyError
409
+
410
+ while ar[-1] == 0:
411
+ ar = ar[:-1]
412
+ x = list(range(0, len(ar)))
413
+ y = [0 for i in range(len(ar))]
414
+ width = [1 for i in range(len(ar))]
415
+ height = [ar[i] / sum(ar) * 100 for i in range(len(ar))]
416
+ data = np.array([x, y, width, height])
417
+
418
+ xaxis = plot.xaxis
419
+ yaxis = plot.yaxis
420
+
421
+ xaxis.min = 0
422
+ xaxis.max = 100
423
+ xaxis.interval = 20
424
+ xaxis.split_number = 5
425
+ yaxis.min = 0
426
+ yaxis.max = 20
427
+ yaxis.interval = 5
428
+ yaxis.split_number = 4
429
+
430
+ # set 1
431
+ series.append({
432
+ 'type': 'rect', 'id': f'rect-{get_random_digits()}', 'name': f'rect-{get_random_digits()}',
433
+ 'color': color, 'myType': 'rect', 'line_width': 1,
434
+ 'data': data.transpose().tolist(),
435
+ 'axis_index': 0, 'z_index': 99
436
+ })
437
+
438
+ xAxis.append({
439
+ 'extent': [float(xaxis.min), float(xaxis.max)],
440
+ 'interval': [float("{:g}".format(float(xaxis.min) + i * float(xaxis.interval))) for i in range(int(xaxis.split_number) + 1)],
441
+ 'id': 0, 'show_frame': True, 'z_index': 9,
442
+ 'title': 'Steps [n]', 'name_location': 'middle',
443
+ })
444
+ yAxis.append({
445
+ 'extent': [float(yaxis.min), float(yaxis.max)],
446
+ 'interval': [float("{:g}".format(float(yaxis.min) + i * float(yaxis.interval))) for i in range(int(yaxis.split_number) + 1)],
447
+ 'id': 0, 'show_frame': True, 'z_index': 9,
448
+ 'title': 'Argon Released [%]', 'name_location': 'middle',
449
+ })
450
+ return xAxis, yAxis, series
451
+
452
+
453
+ def _get_plot_data_degas_curve(smp: sample, **options):
454
+ name = options.get('diagram_name', '39Ar')
455
+ color = options.get('color', 'black')
456
+ xAxis, yAxis, series = [], [], []
457
+ nindex = {"40": 24, "39": 20, "38": 10, "37": 8, "36": 0}
458
+ if name[:2] in list(nindex.keys()):
459
+ ar = np.array(smp.DegasValues[nindex[name[:2]]], dtype=np.float64) # 20-21 Ar39
460
+ sar = np.array(smp.DegasValues[nindex[name[:2]] + 1], dtype=np.float64)
461
+ elif 'total' in name:
462
+ all_ar = np.array(smp.CorrectedValues, dtype=np.float64) # 20-21 Ar39
463
+ ar, sar = arr.add(*all_ar.reshape(5, 2, len(all_ar[0])))
464
+ ar = np.array(ar); sar = np.array(sar)
465
+ else:
466
+ raise KeyError
467
+
468
+ while ar[-1] == 0:
469
+ ar = ar[:-1]
470
+ x = list(range(0, len(ar) + 1))
471
+ f = ar / sum(ar) * 100
472
+ released = np.zeros(len(ar) + 1)
473
+ remained = np.zeros(len(ar) + 1) + 100
474
+ for i in range(1, len(ar) + 1):
475
+ released[i] = sum(f[:i])
476
+ remained[i] = 100 - released[i]
477
+
478
+ # line
479
+ series.append({
480
+ 'type': 'line', 'id': f'line-{get_random_digits()}', 'name': f'line-{get_random_digits()}',
481
+ 'color': color, 'myType': 'line', 'line_width': 1, 'line_style': 'solid',
482
+ 'data': np.array([x, released]).transpose().tolist(),
483
+ 'axis_index': 0, 'z_index': 99
484
+ })
485
+ series.append({
486
+ 'type': 'line', 'id': f'line-{get_random_digits()}', 'name': f'line-{get_random_digits()}',
487
+ 'color': color, 'myType': 'line', 'line_width': 1, 'line_style': 'solid',
488
+ 'data': np.array([x, remained]).transpose().tolist(),
489
+ 'axis_index': 0, 'z_index': 99
490
+ })
491
+
492
+ xAxis.append({
493
+ 'extent': [0, 100],
494
+ 'interval': [0, 20, 40, 60, 80, 100],
495
+ 'id': 0, 'show_frame': True, 'z_index': 9,
496
+ 'title': 'Steps [n]', 'name_location': 'middle',
497
+ })
498
+ yAxis.append({
499
+ 'extent': [0, 100],
500
+ 'interval': [0, 20, 40, 60, 80, 100],
501
+ 'id': 0, 'show_frame': True, 'z_index': 9,
502
+ 'title': 'Argon [%]', 'name_location': 'middle',
503
+ })
504
+ return xAxis, yAxis, series
505
+
506
+
44
507
  class ExcelTemplate:
45
508
  def __init__(self, **kwargs):
46
509
  self.name = ""
ararpy/smp/json.py CHANGED
@@ -22,7 +22,8 @@ def dumps(a):
22
22
 
23
23
 
24
24
  def loads(a):
25
- return json.loads(a)
25
+ # null will be converted to None by default, replace None with np.nan
26
+ return json.loads(a, object_hook=myHook)
26
27
 
27
28
 
28
29
  class MyEncoder(json.JSONEncoder):
@@ -51,3 +52,13 @@ class MyEncoder(json.JSONEncoder):
51
52
  if not isinstance(obj, (int, str, list, dict, tuple, float)):
52
53
  print(f"Special type, {type(obj) = }, {obj = }")
53
54
  return super(MyEncoder, self).default(obj)
55
+
56
+
57
+ def myHook(obj):
58
+ if isinstance(obj, dict):
59
+ return {k: myHook(v) for k, v in obj.items()}
60
+ elif isinstance(obj, list):
61
+ return [myHook(v) for v in obj]
62
+ elif obj is None:
63
+ return np.nan
64
+ return obj
ararpy/smp/plots.py CHANGED
@@ -61,16 +61,20 @@ def set_plot_data(sample: Sample, isInit: bool = True, isIsochron: bool = True,
61
61
  try:
62
62
  initial_plot_data(sample)
63
63
  except (Exception, BaseException):
64
- print(traceback.format_exc())
64
+ # print(traceback.format_exc())
65
65
  pass
66
66
 
67
67
  # Recalculate isochron lines
68
68
  if isIsochron:
69
69
  try:
70
70
  recalc_isochrons(sample, **kwargs)
71
+ except (Exception, BaseException):
72
+ # print(traceback.format_exc())
73
+ pass
74
+ try:
71
75
  reset_isochron_line_data(sample)
72
76
  except (Exception, BaseException):
73
- print(traceback.format_exc())
77
+ # print(traceback.format_exc())
74
78
  pass
75
79
 
76
80
  # Recalculate plateaus
@@ -78,7 +82,7 @@ def set_plot_data(sample: Sample, isInit: bool = True, isIsochron: bool = True,
78
82
  try:
79
83
  recalc_plateaus(sample)
80
84
  except (Exception, BaseException):
81
- print(traceback.format_exc())
85
+ # print(traceback.format_exc())
82
86
  pass
83
87
 
84
88
 
@@ -237,7 +241,7 @@ def get_isochron_results(data: list, smp: Sample, sequence, figure_type: int = 0
237
241
  try:
238
242
  regression_res = regression_method(*data[:5])
239
243
  except (Exception, BaseException):
240
- print(f"Warning: {traceback.format_exc()}")
244
+ # print(f"Warning: {traceback.format_exc()}")
241
245
  return iso_res
242
246
  else:
243
247
  iso_res.update(dict(zip(reg_res_index, regression_res)))
@@ -305,11 +309,11 @@ def get_3D_results(data: list, sequence: list, sample: Sample):
305
309
  Q = 1 - np.exp(-1 * sample.TotalParam[46][0] * sum(sample.TotalParam[32]) / len(sample.TotalParam[32]))
306
310
  P = PQ / Q
307
311
  except:
308
- print(f"Warning: {traceback.format_exc()}")
312
+ # print(f"Warning: {traceback.format_exc()}")
309
313
  P = 0
310
314
  age = basic.calc_age([f, sf], smp=sample)
311
315
  except:
312
- print(f"Warning: {traceback.format_exc()}")
316
+ # print(f"Warning: {traceback.format_exc()}")
313
317
  k = [0] * 15
314
318
  age = [0] * 4
315
319
  ar40ar36, sar40ar36, P = 0, 0, 0
ararpy/smp/raw.py CHANGED
@@ -50,8 +50,15 @@ def to_raw(file_path: Union[str, List[str]], input_filter_path: Union[str, List[
50
50
  data = res.get('data', None)
51
51
  sequences = res.get('sequences', None)
52
52
  sequence_num = len(data) if data is not None else len(sequences)
53
- raw = RawData(name=file_name, data=data, isotopic_num=10, sequence_num=sequence_num,
54
- source=[file_path], sequence=sequences, unit=str(input_filter[30]))
53
+ # default fitting method, all exponential
54
+ # <option value=0>Linear</option>
55
+ # <option value=1>Quadratic</option>
56
+ # <option value=2>Exponential</option>
57
+ # <option value=3>Power</option>
58
+ # <option value=4>Average</option>
59
+ fitting_method = [2, 0, 2, 2, 2]
60
+ raw = RawData(name=file_name, data=data, isotopic_num=10, sequence_num=sequence_num, source=[file_path],
61
+ sequence=sequences, unit=str(input_filter[30]), fitting_method=[*fitting_method])
55
62
  else:
56
63
  raise ValueError("File path and input filter should be both string or list with a same length.")
57
64
  return raw
ararpy/smp/sample.py CHANGED
@@ -119,8 +119,8 @@ TOTAL_PARAMS_HEADERS = [
119
119
  '\u2074\u2070Ar/\u00B3\u2076Ar air', '%1\u03C3',
120
120
  '\u00B3\u2078Ar/\u00B3\u2076Ar air', '%1\u03C3', # 95-98
121
121
  'Isochron Fitting', 'Convergence', 'Iteration', 'Discrimination', # 99-102
122
- 'Not Zero', 'Corr Blank', 'Corr Discr', 'Corr \u00B3\u2077Ar Decay',
123
- 'Corr \u00B3\u2079Ar Decay', # 103-107
122
+ 'Not Zero', 'Corr Blank', 'Corr Discr', 'Corr \u00B3\u2077Ar Decay', # 103-106
123
+ 'Corr \u00B3\u2079Ar Decay', # 107
124
124
  'Ca Degassing', 'K Degassing', 'Cl Degassing', 'Trap Degassing', # 108-111
125
125
  'Using Min Equation',
126
126
  # 'Recalibration', 'Using Std Age', 'Use Std Ratio', # 112-115 to be completed
@@ -137,6 +137,11 @@ TOTAL_PARAMS_HEADERS = [
137
137
  'Heating Time (s)', # 125
138
138
  'Heating Actual Temp (C)', # 126
139
139
  'Heating AT 1\u03C3', # 127
140
+ '36Ar Gain', '%1\u03C3', # 128-129
141
+ '37Ar Gain', '%1\u03C3', # 130-131
142
+ '38Ar Gain', '%1\u03C3', # 132-133
143
+ '39Ar Gain', '%1\u03C3', # 134-135
144
+ '40Ar Gain', '%1\u03C3', # 136-137
140
145
  ]
141
146
 
142
147
  SAMPLE_INTERCEPT_SHORT_HEADERS = [
@@ -245,6 +250,11 @@ TOTAL_PARAMS_SHORT_HEADERS = [
245
250
  'HeatingTime', # 125
246
251
  'HeatingActualTemp', # 126
247
252
  'HeatingActualTempError', # 127
253
+ '36Gain', '%1s', # 128-129
254
+ '37Gain', '%1s', # 130-131
255
+ '38Gain', '%1s', # 132-133
256
+ '39Gain', '%1s', # 134-135
257
+ '40Gain', '%1s', # 136-137
248
258
  ]
249
259
 
250
260
  DEFAULT_PLOT_STYLES = {
@@ -731,7 +741,7 @@ DEFAULT_PLOT_STYLES = {
731
741
  },
732
742
  }
733
743
 
734
- VERSION = '20240730'
744
+ VERSION = '20241028'
735
745
 
736
746
  NAMED_DICT = {
737
747
  "unknown": {"header": SAMPLE_INTERCEPT_HEADERS.copy()},
@@ -832,7 +842,8 @@ class Sample:
832
842
  # self.__version = '20230730' # delete calcparams attribute
833
843
  # self.__version = '20230827' # using merge smp to update arr version
834
844
  # self.__version = '20231116' # change smp parameters
835
- self.__version = '20240730' # change parameter table for thermo calculation
845
+ # self.__version = '20240730' # change parameter table for thermo calculation
846
+ self.__version = '20241028' # gain correction
836
847
 
837
848
  @property
838
849
  def version(self):
@@ -854,7 +865,7 @@ class Sample:
854
865
 
855
866
  def sequence(self) -> ArArBasic: ...
856
867
 
857
- def recalculate(self, *args): ...
868
+ def recalculate(self, *args, **kwargs): ...
858
869
 
859
870
  def plot_age_plateau(self): ...
860
871
 
@@ -1144,16 +1155,21 @@ class RawData:
1144
1155
  self.isotopic_num = isotopic_num
1145
1156
  self.sequence_num = sequence_num
1146
1157
  self.interpolated_blank = None
1147
- if data is not None:
1158
+ if sequence is not None:
1159
+ self.sequence = sequence
1160
+ elif data is not None:
1148
1161
  self.sequence: List[Sequence] = [
1149
- Sequence(index=index, name=item[0][0] if isinstance(item[0][0], str) and item[0][
1150
- 0] != '' else f"{self.name}-{index + 1:02d}", data=item[1:], datetime=item[0][1], type_str=item[0][2],
1151
- fitting_method=[0] * 5, options=item[0][3])
1152
- for index, item in enumerate(data)]
1162
+ Sequence(
1163
+ index=index,
1164
+ name=item[0][0] if isinstance(item[0][0], str) and item[0][0] != '' else f"{self.name}-{index + 1:02d}",
1165
+ data=item[1:],
1166
+ datetime=item[0][1],
1167
+ type_str=item[0][2],
1168
+ fitting_method=[*kwargs.get("fitting_method", [0] * 5)],
1169
+ options=item[0][3]
1170
+ ) for index, item in enumerate(data)]
1153
1171
  else:
1154
1172
  self.sequence: List[Sequence] = []
1155
- if sequence is not None:
1156
- self.sequence = sequence
1157
1173
  for k, v in kwargs.items():
1158
1174
  if hasattr(self, k) and type(getattr(self, k)) is MethodType:
1159
1175
  continue