ararpy 0.1.15__tar.gz → 0.1.17__tar.gz

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 (75) hide show
  1. {ararpy-0.1.15 → ararpy-0.1.17}/PKG-INFO +17 -3
  2. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/__init__.py +1 -1
  3. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/age.py +7 -6
  4. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/basic.py +29 -0
  5. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/corr.py +30 -17
  6. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/regression.py +4 -3
  7. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/calc_file.py +7 -6
  8. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/basic.py +50 -12
  9. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/corr.py +8 -6
  10. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/diffusion_funcs.py +73 -99
  11. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/export.py +216 -86
  12. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/initial.py +32 -27
  13. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/plots.py +7 -6
  14. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/sample.py +10 -6
  15. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/style.py +13 -5
  16. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/table.py +19 -21
  17. {ararpy-0.1.15/ararpy/argon_diffusion_simulator → ararpy-0.1.17/ararpy/thermo}/__init__.py +1 -1
  18. ararpy-0.1.17/ararpy/thermo/arrhenius.py +15 -0
  19. ararpy-0.1.15/ararpy/argon_diffusion_simulator/main.py → ararpy-0.1.17/ararpy/thermo/atomic_level_random_walk.py +1 -1
  20. ararpy-0.1.17/ararpy/thermo/basic.py +306 -0
  21. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy.egg-info/PKG-INFO +17 -3
  22. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy.egg-info/SOURCES.txt +5 -2
  23. ararpy-0.1.17/ararpy.egg-info/requires.txt +11 -0
  24. {ararpy-0.1.15 → ararpy-0.1.17}/setup.py +3 -3
  25. {ararpy-0.1.15 → ararpy-0.1.17}/LICENSE +0 -0
  26. {ararpy-0.1.15 → ararpy-0.1.17}/README.md +0 -0
  27. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/__init__.py +0 -0
  28. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/arr.py +0 -0
  29. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/err.py +0 -0
  30. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/histogram.py +0 -0
  31. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/isochron.py +0 -0
  32. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/jvalue.py +0 -0
  33. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/plot.py +0 -0
  34. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/raw_funcs.py +0 -0
  35. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/calc/spectra.py +0 -0
  36. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/022_VU124-M11a.ahd +0 -0
  37. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/20WHA0103.age +0 -0
  38. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/22WHA0078.xls +0 -0
  39. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/22WHA0433.age +0 -0
  40. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/22WHA0433.arr +0 -0
  41. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/22WHA0433.full.xls +0 -0
  42. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/24WHN0001-51-592.XLS +0 -0
  43. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/AHD.input-filter +0 -0
  44. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/ArAr.calc +0 -0
  45. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/ArArCALC.age +0 -0
  46. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/NGX-600 - Copy.TXT +0 -0
  47. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/NGX-600.TXT +0 -0
  48. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/NGX-XLS.input-filter +0 -0
  49. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/Qtegra-exported-xls.input-filter +0 -0
  50. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/S01-239.csv +0 -0
  51. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/WH01.irra +0 -0
  52. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/WHA.pdf +0 -0
  53. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/raw_example.xls +0 -0
  54. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/examples/sample-default.smp +0 -0
  55. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/__init__.py +0 -0
  56. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/arr_file.py +0 -0
  57. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/basic.py +0 -0
  58. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/new_file.py +0 -0
  59. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/raw_file.py +0 -0
  60. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/files/xls.py +0 -0
  61. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/EXPORT_TO_PDF_DATA_PROPERTIES.py +0 -0
  62. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/__init__.py +0 -0
  63. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/calculation.py +0 -0
  64. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/consts.py +0 -0
  65. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/info.py +0 -0
  66. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/json.py +0 -0
  67. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/smp/raw.py +0 -0
  68. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy/test.py +0 -0
  69. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy.egg-info/dependency_links.txt +0 -0
  70. {ararpy-0.1.15 → ararpy-0.1.17}/ararpy.egg-info/top_level.txt +0 -0
  71. {ararpy-0.1.15 → ararpy-0.1.17}/setup.cfg +0 -0
  72. {ararpy-0.1.15 → ararpy-0.1.17}/tests/test.py +0 -0
  73. {ararpy-0.1.15 → ararpy-0.1.17}/tests/test2.py +0 -0
  74. {ararpy-0.1.15 → ararpy-0.1.17}/tests/test_error_correlation.py +0 -0
  75. {ararpy-0.1.15 → ararpy-0.1.17}/tests/test_regression_methods.py +0 -0
@@ -1,23 +1,37 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: ararpy
3
- Version: 0.1.15
3
+ Version: 0.1.17
4
4
  Summary: A project for Ar-Ar geochronology
5
5
  Home-page: https://github.com/wuyangchn/ararpy.git
6
6
  Author: Yang Wu
7
7
  Author-email: wuycug@hotmail.com
8
+ License: MIT
8
9
  Classifier: Development Status :: 3 - Alpha
9
10
  Classifier: Programming Language :: Python :: 3
10
- Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.5
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
+ Requires-Dist: chardet
16
+ Requires-Dist: numpy
17
+ Requires-Dist: OriginExt
18
+ Requires-Dist: pandas
19
+ Requires-Dist: parse
20
+ Requires-Dist: python_dateutil
21
+ Requires-Dist: scipy
22
+ Requires-Dist: setuptools
23
+ Requires-Dist: xlrd
24
+ Requires-Dist: XlsxWriter
25
+ Requires-Dist: pdf_maker
15
26
  Dynamic: author
16
27
  Dynamic: author-email
17
28
  Dynamic: classifier
18
29
  Dynamic: description
19
30
  Dynamic: description-content-type
20
31
  Dynamic: home-page
32
+ Dynamic: license
33
+ Dynamic: license-file
34
+ Dynamic: requires-dist
21
35
  Dynamic: requires-python
22
36
  Dynamic: summary
23
37
 
@@ -10,7 +10,7 @@
10
10
  """
11
11
 
12
12
  import pandas as pd
13
- from . import calc, smp, files, test
13
+ from . import calc, smp, files, thermo, test
14
14
 
15
15
 
16
16
  """ Information """
@@ -34,6 +34,7 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
34
34
 
35
35
  Returns
36
36
  -------
37
+ [age, s1, s2, s3] in years
37
38
 
38
39
  """
39
40
  F, sF = arr.array_as_float([F, sF]).astype(float)
@@ -111,12 +112,12 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
111
112
 
112
113
  # change to Ma
113
114
  # analytical error, error of 40Ar/39Ar only
114
- s1 = np.sqrt((V * KK * BB / XX) ** 2 * sR_2 ** 2) / 1000000
115
+ s1 = np.sqrt((V * KK * BB / XX) ** 2 * sR_2 ** 2)
115
116
  # internal error, errors of 40Ar/39Ar and J value
116
- s2 = np.sqrt((V * KK * BB / XX) ** 2 * sR_1 ** 2) / 1000000
117
+ s2 = np.sqrt((V * KK * BB / XX) ** 2 * sR_1 ** 2)
117
118
  # total external error
118
- s3 = np.sqrt(e1 + e2 + e3 + e4 + e5 + e6 + e7 + e8 + e9) / 1000000
119
- age = k0 / 1000000
119
+ s3 = np.sqrt(e1 + e2 + e3 + e4 + e5 + e6 + e7 + e8 + e9)
120
+ age = k0
120
121
  return age, s1, s2, s3
121
122
 
122
123
 
@@ -135,7 +136,7 @@ def calc_age_general(F, sF, J, sJ, L, sL, **kwargs):
135
136
 
136
137
  Returns
137
138
  -------
138
- tuple of array objects, (age, s1, s2, s3)
139
+ tuple of array objects, (age, s1, s2, s3), in years
139
140
  """
140
141
  F, sF, J, sJ, L, sL = np.array([F, sF, J, sJ, L, sL])
141
142
  sJ = sJ * J / 100
@@ -147,4 +148,4 @@ def calc_age_general(F, sF, J, sJ, L, sL, **kwargs):
147
148
  s1 = v1 ** .5 # analytical error
148
149
  s2 = (v1 + v2) ** .5 # internal error
149
150
  s3 = (v1 + v2 + v3) ** .5 # full external error
150
- return age / 1000000, s1 / 1000000, s2 / 1000000, s3 / 1000000
151
+ return age, s1, s2, s3
@@ -12,6 +12,8 @@
12
12
  import copy
13
13
  import random
14
14
  import string
15
+ import numpy as np
16
+ from scipy import stats
15
17
  from datetime import datetime, timezone, timedelta
16
18
  import pytz
17
19
 
@@ -100,3 +102,30 @@ def update_dicts(a: dict, b: dict):
100
102
 
101
103
  def get_random_digits(length: int = 7) -> str:
102
104
  return ''.join(random.choices(string.digits, k=length))
105
+
106
+
107
+ def monte_carlo(func, inputs, confidence_level, **kwargs):
108
+ """
109
+
110
+ Parameters
111
+ ----------
112
+ func: Callable
113
+ inputs: array
114
+ two-dimensional array
115
+ confidence_level: float
116
+ [0, 1]
117
+
118
+ Returns
119
+ -------
120
+
121
+ """
122
+ N = len(inputs)
123
+ l_range = int(0.5 * (1 - confidence_level) * N)
124
+ r_range = N - l_range - 1
125
+ values = np.transpose([func(*each, **kwargs) for each in inputs])
126
+ cov = np.cov(values, rowvar=True)
127
+ values = np.sort(values, axis=1) # sort to find the lower and upper limitation at the given confidence level
128
+ means = np.mean(values, axis=1).reshape(len(values), 1)
129
+ limits = values[:, [l_range, r_range]]
130
+
131
+ return np.concatenate((means, limits), axis=1), cov
@@ -247,6 +247,8 @@ def random_normal_relative(mu, std, size):
247
247
 
248
248
 
249
249
  def random_normal_absolute(mu, std, size):
250
+ if np.isnan(std):
251
+ std = 0
250
252
  return np.random.normal(mu, std, size)
251
253
 
252
254
 
@@ -262,13 +264,12 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
262
264
  L37ar: Tuple[float, float], L39ar: Tuple[float, float], L36cl: Tuple[float, float],
263
265
  MDFunc: Union[MethodType],
264
266
  MDF: Tuple[float, float],
265
- M40: Tuple[float, float],
266
- M39: Tuple[float, float],
267
- M38: Tuple[float, float],
268
- M37: Tuple[float, float],
269
- M36: Tuple[float, float],
267
+ M40: Tuple[float, float], M39: Tuple[float, float], M38: Tuple[float, float],
268
+ M37: Tuple[float, float], M36: Tuple[float, float],
269
+ G40: Tuple[float, float], G39: Tuple[float, float], G38: Tuple[float, float],
270
+ G37: Tuple[float, float], G36: Tuple[float, float],
270
271
  stand_time_year: float,
271
- **options) -> Tuple[float, float]:
272
+ **options):
272
273
  """
273
274
 
274
275
  Parameters
@@ -306,7 +307,9 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
306
307
  Monte_Carlo_Size = 10000
307
308
 
308
309
  # generate random
310
+ print(ar40m)
309
311
  ar40m = random_normal_absolute(*ar40m, size=Monte_Carlo_Size)
312
+ print(ar40m)
310
313
  ar39m = random_normal_absolute(*ar39m, size=Monte_Carlo_Size)
311
314
  ar38m = random_normal_absolute(*ar38m, size=Monte_Carlo_Size)
312
315
  ar37m = random_normal_absolute(*ar37m, size=Monte_Carlo_Size)
@@ -325,6 +328,12 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
325
328
  M37 = random_normal_relative(*M37, size=Monte_Carlo_Size)
326
329
  M36 = random_normal_relative(*M36, size=Monte_Carlo_Size)
327
330
 
331
+ G40 = random_normal_relative(*G40, size=Monte_Carlo_Size)
332
+ G39 = random_normal_relative(*G39, size=Monte_Carlo_Size)
333
+ G38 = random_normal_relative(*G38, size=Monte_Carlo_Size)
334
+ G37 = random_normal_relative(*G37, size=Monte_Carlo_Size)
335
+ G36 = random_normal_relative(*G36, size=Monte_Carlo_Size)
336
+
328
337
  L36cl = random_normal_relative(*L36cl, size=Monte_Carlo_Size)
329
338
  L37ar = random_normal_relative(*L37ar, size=Monte_Carlo_Size)
330
339
  L39ar = random_normal_relative(*L39ar, size=Monte_Carlo_Size)
@@ -338,6 +347,8 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
338
347
  R38v39k = random_normal_relative(*R38v39k, size=Monte_Carlo_Size)
339
348
  R36v38clp = random_normal_relative(*R36v38clp, size=Monte_Carlo_Size)
340
349
 
350
+ blank_gain_corr = options.get('blank_gain_corr', True)
351
+
341
352
  def do_simulation():
342
353
  i = 0
343
354
  while i < Monte_Carlo_Size:
@@ -351,20 +362,20 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
351
362
 
352
363
  _ar40m = ar40m[i]
353
364
 
354
- _ar36 = (ar36m[i] - ar36b[i]) * P36Mdf
355
- _ar37 = (ar37m[i] - ar37b[i]) * P37Mdf
356
- _ar38 = (ar38m[i] - ar38b[i]) * P38Mdf
357
- _ar39 = (ar39m[i] - ar39b[i]) * P39Mdf
358
- _ar40 = (ar40m[i] - ar40b[i]) * P40Mdf
365
+ _ar36 = (ar36m[i] / G36[i] - ar36b[i] / (G36[i] if blank_gain_corr else 1)) * P36Mdf
366
+ _ar37 = (ar37m[i] / G37[i] - ar37b[i] / (G37[i] if blank_gain_corr else 1)) * P37Mdf
367
+ _ar38 = (ar38m[i] / G38[i] - ar38b[i] / (G38[i] if blank_gain_corr else 1)) * P38Mdf
368
+ _ar39 = (ar39m[i] / G39[i] - ar39b[i] / (G39[i] if blank_gain_corr else 1)) * P39Mdf
369
+ _ar40 = (ar40m[i] / G40[i] - ar40b[i] / (G40[i] if blank_gain_corr else 1)) * P40Mdf
359
370
 
360
- _ar37ca = (ar37m[i] - ar37b[i]) * P37Mdf * P37Decay
361
- _ar39k = (ar39m[i] - ar39b[i]) * P39Mdf * P39Decay - _ar37ca * R39v37ca[i]
362
- _ar38res = (ar38m[i] - ar38b[i]) * P38Mdf - _ar39k * R38v39k[i] - _ar37ca * R38v37ca[i]
363
- _ar36res = (ar36m[i] - ar36b[i]) * P36Mdf - _ar37ca * R36v37ca[i]
371
+ _ar37ca = _ar37 * P37Decay
372
+ _ar39k = _ar39 * P39Decay - _ar37ca * R39v37ca[i]
373
+ _ar38res = _ar38 - _ar39k * R38v39k[i] - _ar37ca * R38v37ca[i]
374
+ _ar36res = _ar36 - _ar37ca * R36v37ca[i]
364
375
  _ar36cl = (_ar36res - _ar38res / R38v36a[i]) / (1 - 1 / (R36v38clp[i] * (1 - exp(-1 * L36cl[i] * stand_time_year)) * R38v36a[i]))
365
376
  _ar36a = _ar36res - _ar36cl
366
- _ar40r = (ar40m[i] - ar40b[i]) * P40Mdf - _ar36a * R40v36a[i] - _ar39k * R40v39k[i]
367
- _ar40ar = (ar40m[i] - ar40b[i]) * P40Mdf - _ar39k * R40v39k[i]
377
+ _ar40r = _ar40 - _ar36a * R40v36a[i] - _ar39k * R40v39k[i]
378
+ _ar40ar = _ar40 - _ar39k * R40v39k[i]
368
379
  _f = _ar40r / _ar39k
369
380
  i += 1
370
381
  # yield _f, _ar36, _ar37, _ar38, _ar39, _ar40, _ar36a, _ar37ca, _ar39k, _ar40r, _ar36cl
@@ -405,6 +416,8 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
405
416
  # ar40r.append(each[9])
406
417
  # ar36cl.append(each[10])
407
418
 
419
+ print(f"{np.mean(F) = }, {np.std(F) = }")
420
+
408
421
  # print("F = {0} ± {1}".format(np.mean(F), np.std(F)))
409
422
  #
410
423
  # with open("ar36m.txt", 'w') as f: # save serialized json data to a readable text
@@ -42,8 +42,8 @@ def york2(x: list, sx: list, y: list, sy: list, ri: list, f: int = 1,
42
42
  Returns
43
43
  -------
44
44
  Intercept | Error | slope | Error | MSWD | Convergence | Number of Iterations | error magnification | other
45
- b, sb, a, sa, mswd, dF, Di, k, r2, chi_square, p_value
46
- b, seb, m, sem, mswd, abs(m - last_m), Di, k, r2, chi_square, p_value, avg_err_s
45
+ b, sb, a, sa, mswd, dF, Di, k, r2, chi_square, p_value, avg_err_s, cov_b_m
46
+ b, seb, m, sem, mswd, abs(m - last_m), Di, k, r2, chi_square, p_value, avg_err_s, cov_b_m
47
47
  """
48
48
  data = np.array([x, sx, y, sy, ri])
49
49
  data = data[:, np.where(
@@ -110,6 +110,7 @@ def york2(x: list, sx: list, y: list, sy: list, ri: list, f: int = 1,
110
110
  r2 = ssreg / sstotal if sstotal != 0 else np.inf # r2 = ssreg / sstotal
111
111
  chi_square = mswd * (n - 2)
112
112
  p_value = distributions.chi2.sf(chi_square, n - 2)
113
+ cov_b_m = - np.mean(X) * (ssresid / (n - 2) / np.sum((X - np.mean(X)) ** 2)) # covariance of intercept b and slope m
113
114
  # average error of S
114
115
  err_s = lambda m, b: list(map(lambda Zi, Yi, Xi: (1 / Zi) ** (1./2.) / abs(Yi - m * Xi - b), Z(m, b), y, x))
115
116
  avg_err_s = sum(err_s(m, b)) / len(x) * 100
@@ -127,7 +128,7 @@ def york2(x: list, sx: list, y: list, sy: list, ri: list, f: int = 1,
127
128
  # k, sk, m, sm, mswd, conv, iter, mag, r2, chisq, p, avg_err
128
129
  # ]
129
130
 
130
- return b, seb, m, sem, mswd, abs(m - last_m), Di, k, r2, chi_square, p_value, avg_err_s
131
+ return b, seb, m, sem, mswd, abs(m - last_m), Di, k, r2, chi_square, p_value, avg_err_s, cov_b_m
131
132
 
132
133
 
133
134
  def york2_df(data: pd.DataFrame, f: int = 1, convergence: float = 0.001,
@@ -128,7 +128,7 @@ def open_252(data: pd.DataFrame, logs01: pd.DataFrame, logs02: pd.DataFrame):
128
128
  sequence = get_data(data, sequence_index)
129
129
 
130
130
  # adjustment
131
- isochron_mark.replace({4.0: 1}, inplace=True)
131
+ isochron_mark.replace({4.0: '1'}, inplace=True)
132
132
  total_param[83] = logs01[1][9] # No
133
133
  total_param[84] = logs01[1][10] # %SD
134
134
  total_param[81] = logs01[1][11] # K mass
@@ -310,7 +310,7 @@ def open_240(data: pd.DataFrame, logs01: pd.DataFrame, logs02: pd.DataFrame):
310
310
  total_param.copy(), logs02, get_data(data, [59, 58, 57, 60, 61]), data[63][0]
311
311
  )
312
312
  # Do adjustment
313
- isochron_mark.replace({4.0: 1}, inplace=True)
313
+ isochron_mark.replace({4.0: '1'}, inplace=True)
314
314
  total_param[44] = logs01[1][40]
315
315
  total_param[45] = logs01[1][41]
316
316
  total_param[42] = logs01[1][38]
@@ -423,9 +423,10 @@ def open_full_xls(file_path: str, sample_name: str = ''):
423
423
  return e
424
424
  start_row = 5
425
425
  rows_num = len(res['Sample Parameters']) - 5
426
+
426
427
  for key, val in res.items():
427
428
  res[key] = arr.transpose(val[:start_row + rows_num])
428
- # 2倍误差改回1
429
+ # 2 sigma errors to 1 sigma
429
430
  for i in range(len(res[key])):
430
431
  if res[key][i][2] in ['2s', '%2s', '± 2s']:
431
432
  _temp = []
@@ -448,7 +449,7 @@ def open_full_xls(file_path: str, sample_name: str = ''):
448
449
  res['Incremental Heating Summary'][13][start_row: start_row + rows_num] = _temp
449
450
  res['Incremental Heating Summary'][13][start_row: start_row + rows_num] = _s
450
451
 
451
- # degas相对误差改为绝对误差
452
+ # degas: change relative uncertainties to absolute
452
453
  for i in range(len(res['Degassing Patterns'])):
453
454
  if res['Degassing Patterns'][i][2] in ['%1s', '%2s']:
454
455
  _temp = []
@@ -459,7 +460,7 @@ def open_full_xls(file_path: str, sample_name: str = ''):
459
460
  except TypeError:
460
461
  _temp.append('')
461
462
  res['Degassing Patterns'][i][start_row: start_row + rows_num] = _temp
462
- rows = list(range(start_row, rows_num))
463
+ rows = list(range(start_row, start_row + rows_num))
463
464
  sequence_name = arr.partial(res['Procedure Blanks'], rows, 1)
464
465
  sequence_value = arr.partial(res['Procedure Blanks'], rows, 2)
465
466
  blank_values = arr.partial(
@@ -552,7 +553,7 @@ def open_full_xls(file_path: str, sample_name: str = ''):
552
553
  isochron_values[24:29] = isochron.get_data(
553
554
  degas_values[10], degas_values[11], degas_values[24], degas_values[25], degas_values[20], degas_values[21]
554
555
  ) # 38/39, 40/39
555
- isochron_mark = [1 if i == 'P' else '' for i in arr.partial(
556
+ isochron_mark = ['1' if i == 'P' else '' for i in arr.partial(
556
557
  res['Normal Isochron Table'], rows, 3)]
557
558
 
558
559
  sample_info = {
@@ -20,6 +20,7 @@ from typing import Optional, Union, List
20
20
  from .. import calc
21
21
  from ..files.basic import (read as read_params)
22
22
  from .sample import Sample, Table, Plot, ArArData, ArArBasic, Sequence, RawData
23
+ from .initial import preference_keys
23
24
 
24
25
  Set = Plot.Set
25
26
  Label = Plot.Label
@@ -128,20 +129,38 @@ def calc_age(ar40ar39=None, params: dict = None, smp: Sample = None, index: list
128
129
  params_from_smp.update(params)
129
130
  params = params_from_smp
130
131
 
132
+ u = 'Ma'
133
+ try:
134
+ u = smp.Info.preference['ageUnit']
135
+ except:
136
+ print(traceback.format_exc())
137
+ pass
138
+ finally:
139
+ if u.lower() == 'ga':
140
+ age_unit_factor = 1000000000
141
+ elif u.lower() == 'ma':
142
+ age_unit_factor = 1000000
143
+ elif u.lower() == 'ka':
144
+ age_unit_factor = 1000
145
+ else:
146
+ age_unit_factor = 1
147
+
131
148
  # check if using Min equation
132
149
  params['Min'] = [i if isinstance(i, bool) else False for i in params['Min']]
133
150
 
134
- idx1 = np.flatnonzero(np.where(params['Min'], True, False)) # True, using Min euqation
151
+ idx1 = np.flatnonzero(np.where(params['Min'], True, False)) # True, using Min equation
135
152
  idx2 = np.flatnonzero(np.where(params['Min'], False, True)) # False
136
153
  k1, k2 = [], []
137
154
  if np.size(idx1) > 0:
138
155
  k1 = calc.age.calc_age_min(
139
156
  F=[ar40ar39[0][i] for i in idx1], sF=[ar40ar39[1][i] for i in idx1],
140
157
  **dict(zip(params.keys(), [[val[i] for i in idx1] for val in params.values()])))
158
+ k1 = [i / age_unit_factor for i in k1]
141
159
  if np.size(idx2) > 0:
142
160
  k2 = calc.age.calc_age_general(
143
161
  F=[ar40ar39[0][i] for i in idx2], sF=[ar40ar39[1][i] for i in idx2],
144
162
  **dict(zip(params.keys(), [[val[i] for i in idx2] for val in params.values()])))
163
+ k2 = [i / age_unit_factor for i in k2]
145
164
 
146
165
  # idx1 = params[params['Min'].astype(bool)].index
147
166
  # idx2 = params[~params['Min'].astype(bool)].index # The operators are: | for or, & for and, and ~ for not
@@ -477,7 +496,7 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
477
496
  return set_params(smp, read_params(params), flag=flag)
478
497
 
479
498
  def remove_none(old_params, new_params, rows, length):
480
- res = [[]] * length
499
+ res = [[] for _ in range(length)]
481
500
  for index, item in enumerate(new_params):
482
501
  if item is None:
483
502
  res[index] = old_params[index]
@@ -487,6 +506,9 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
487
506
 
488
507
  n = len(smp.SequenceName)
489
508
 
509
+ if n == 0:
510
+ raise ValueError(f"The number of sample sequences is undefined.")
511
+
490
512
  if flag == 'calc':
491
513
  smp.TotalParam[34:56] = remove_none(smp.TotalParam[34:56], params[0:22], n, 56 - 34)
492
514
  smp.TotalParam[71:97] = remove_none(smp.TotalParam[71:97], params[22:48], n, 97 - 71)
@@ -524,22 +546,32 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
524
546
  stand_time_second = [
525
547
  calc.basic.get_datetime(*re.findall(r"\d+", smp.TotalParam[31][i])) - calc.basic.get_datetime(
526
548
  *re.findall(r"\d+", smp.TotalParam[30][i])) for i in range(n)]
527
- except TypeError:
549
+ except (BaseException, Exception):
528
550
  print(f'Error in calculate standing duration: {traceback.format_exc()}')
551
+ raise
529
552
  else:
530
553
  smp.TotalParam[32] = [i / (3600 * 24 * 365.242) for i in stand_time_second] # stand year
531
554
 
532
555
  elif flag == 'smp':
533
- print(params)
556
+ print(dict(zip([i for i in range(len(params))], params)))
534
557
  smp.TotalParam[67:71] = remove_none(smp.TotalParam[67:71], params[0:4], n, 71 - 67)
535
558
  smp.TotalParam[58:67] = remove_none(smp.TotalParam[58:67], params[4:13], n, 67 - 58)
536
559
  smp.TotalParam[97:100] = remove_none(smp.TotalParam[97:100], params[13:16], n, 100 - 97)
537
560
  smp.TotalParam[115:120] = remove_none(smp.TotalParam[115:120], params[16:21], n, 120 - 115)
538
561
  smp.TotalParam[126:136] = remove_none(smp.TotalParam[126:136], params[21:31], n, 136 - 126)
539
- smp.TotalParam[120:123] = remove_none(smp.TotalParam[120:123], params[31:34], n, 123 - 120)
562
+ # smp.TotalParam[120:123] = remove_none(smp.TotalParam[120:123], params[31:34], n, 123 - 120)
540
563
  smp.TotalParam[100:114] = remove_none(
541
564
  smp.TotalParam[100:114],
542
- [['Linear', 'Exponential', 'Power'][params[34:37].index(True)] if True in params[34:37] else '', *params[37:]], n, 114 - 100)
565
+ [['Linear', 'Exponential', 'Power'][params[35:38].index(True)] if True in params[35:38] else '', *params[38:]], n, 114 - 100)
566
+ pref = dict(zip(preference_keys, params[31:35]))
567
+ smp.Info.preference.update(pref)
568
+ for key, comp in get_components(smp).items():
569
+ if isinstance(comp, Table):
570
+ comp.decimal_places = pref['decimalPlaces']
571
+ comp.set_coltypes()
572
+ smp.AgeSpectraPlot.yaxis.title.text = f"Apparent Age ({str(pref['ageUnit']).capitalize()})"
573
+ print(smp.Info.preference)
574
+
543
575
  else:
544
576
  raise KeyError(f"{flag = } is not supported. It must be 'calc' for Calc Params, "
545
577
  f"'irra' for Irradiation Params, or 'smp' for Sample Params.")
@@ -547,16 +579,22 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
547
579
 
548
580
 
549
581
  def get_sequence(smp: Sample):
582
+ set1_index = [index for index, _ in enumerate(smp.IsochronMark) if _ in [1, '1']]
583
+ set2_index = [index for index, _ in enumerate(smp.IsochronMark) if _ in [2, '2']]
584
+ set3_index = list(set(range(0, len(smp.IsochronMark))) - set(set1_index) - set(set2_index))
585
+ smp.SelectedSequence1 = set1_index
586
+ smp.SelectedSequence2 = set2_index
587
+ smp.UnselectedSequence = set3_index
588
+ smp.Info.results.selection[0]['data'] = smp.SelectedSequence1
589
+ smp.Info.results.selection[1]['data'] = smp.SelectedSequence2
590
+ smp.Info.results.selection[2]['data'] = smp.UnselectedSequence
550
591
  return ArArBasic(
551
592
  size=len(smp.SequenceName), name=smp.SequenceName, value=smp.SequenceValue, unit=smp.SequenceUnit,
552
593
  mark=ArArBasic(
553
594
  size=len(smp.IsochronMark), value=smp.IsochronMark,
554
- set1=ArArBasic(size=sum([1 if i == 1 else 0 for i in smp.IsochronMark]),
555
- index=[index for index, _ in enumerate(smp.IsochronMark) if _ == 1]),
556
- set2=ArArBasic(size=sum([1 if i == 2 else 0 for i in smp.IsochronMark]),
557
- index=[index for index, _ in enumerate(smp.IsochronMark) if _ == 2]),
558
- unselected=ArArBasic(size=sum([0 if i == 2 or i == 1 else 1 for i in smp.IsochronMark]),
559
- index=[index for index, _ in enumerate(smp.IsochronMark) if _ != 1 and _ != 2]),
595
+ set1=ArArBasic(size=len(set1_index), index=set1_index),
596
+ set2=ArArBasic(size=len(set2_index), index=set2_index),
597
+ unselected=ArArBasic(size=len(set3_index), index=set3_index),
560
598
  )
561
599
  )
562
600
 
@@ -506,11 +506,11 @@ def monte_carlo_f(sample: Sample):
506
506
  M39 = np.transpose(sample.TotalParam[77:79])
507
507
  M40 = np.transpose(sample.TotalParam[79:81])
508
508
 
509
- # M36 = [[35.96754628, 0] for i in range(sequence_num)]
510
- # M37 = [[36.9667759, 0] for i in range(sequence_num)]
511
- # M38 = [[37.9627322, 0] for i in range(sequence_num)]
512
- # M39 = [[38.964313, 0] for i in range(sequence_num)]
513
- # M40 = [[39.962383123, 0] for i in range(sequence_num)]
509
+ G36 = np.transpose(sample.TotalParam[126:128]) # gain correction factors
510
+ G37 = np.transpose(sample.TotalParam[128:130])
511
+ G38 = np.transpose(sample.TotalParam[130:132])
512
+ G39 = np.transpose(sample.TotalParam[132:134])
513
+ G40 = np.transpose(sample.TotalParam[134:136])
514
514
 
515
515
  MDF = np.transpose(sample.TotalParam[69:71])
516
516
 
@@ -553,6 +553,7 @@ def monte_carlo_f(sample: Sample):
553
553
  ar40m=ar40m[i], ar39m=ar39m[i], ar38m=ar38m[i], ar37m=ar37m[i], ar36m=ar36m[i],
554
554
  ar40b=ar40b[i], ar39b=ar39b[i], ar38b=ar38b[i], ar37b=ar37b[i], ar36b=ar36b[i],
555
555
  M40=M40[i], M39=M39[i], M38=M38[i], M37=M37[i], M36=M36[i],
556
+ G40=G40[i], G39=G39[i], G38=G38[i], G37=G37[i], G36=G36[i],
556
557
  t1=t1[i], t2=t2[i], t3=t3[i],
557
558
  R40v36a=R40v36a[i], R38v36a=R38v36a[i],
558
559
  R39v37ca=R39v37ca[i], R36v37ca=R36v37ca[i], R38v37ca=R38v37ca[i],
@@ -560,7 +561,8 @@ def monte_carlo_f(sample: Sample):
560
561
  R36v38clp=R36v38clp[i],
561
562
  L37ar=L37ar[i], L39ar=L39ar[i], L36cl=L36cl[i],
562
563
  MDFunc=None,
563
- MDF=MDF[i], stand_time_year=stand_time_year[i]
564
+ MDF=MDF[i], stand_time_year=stand_time_year[i],
565
+ blank_gain_corr=sample.TotalParam[111][i]
564
566
  )
565
567
 
566
568
  yield res