ararpy 0.1.193__tar.gz → 0.1.197__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 (74) hide show
  1. {ararpy-0.1.193 → ararpy-0.1.197}/PKG-INFO +1 -1
  2. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/__init__.py +1 -1
  3. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/age.py +4 -1
  4. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/arr.py +2 -2
  5. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/corr.py +5 -3
  6. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/basic.py +7 -1
  7. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/corr.py +66 -46
  8. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/export.py +1 -1
  9. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/initial.py +29 -11
  10. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/plots.py +29 -15
  11. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/sample.py +7 -5
  12. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy.egg-info/PKG-INFO +1 -1
  13. {ararpy-0.1.193 → ararpy-0.1.197}/setup.py +1 -1
  14. {ararpy-0.1.193 → ararpy-0.1.197}/LICENSE +0 -0
  15. {ararpy-0.1.193 → ararpy-0.1.197}/README.md +0 -0
  16. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/__init__.py +0 -0
  17. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/basic.py +0 -0
  18. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/err.py +0 -0
  19. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/histogram.py +0 -0
  20. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/isochron.py +0 -0
  21. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/jvalue.py +0 -0
  22. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/plot.py +0 -0
  23. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/raw_funcs.py +0 -0
  24. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/regression.py +0 -0
  25. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/calc/spectra.py +0 -0
  26. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/022_VU124-M11a.ahd +0 -0
  27. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/20WHA0103.age +0 -0
  28. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/22WHA0078.xls +0 -0
  29. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/22WHA0433.age +0 -0
  30. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/22WHA0433.arr +0 -0
  31. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/22WHA0433.full.xls +0 -0
  32. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/24WHN0001-51-592.XLS +0 -0
  33. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/AHD.input-filter +0 -0
  34. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/ArAr.calc +0 -0
  35. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/ArArCALC.age +0 -0
  36. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/NGX-600 - Copy.TXT +0 -0
  37. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/NGX-600.TXT +0 -0
  38. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/NGX-XLS.input-filter +0 -0
  39. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/Qtegra-exported-xls.input-filter +0 -0
  40. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/S01-239.csv +0 -0
  41. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/WH01.irra +0 -0
  42. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/WHA.pdf +0 -0
  43. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/raw_example.xls +0 -0
  44. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/examples/sample-default.smp +0 -0
  45. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/__init__.py +0 -0
  46. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/arr_file.py +0 -0
  47. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/basic.py +0 -0
  48. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/calc_file.py +0 -0
  49. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/new_file.py +0 -0
  50. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/raw_file.py +0 -0
  51. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/files/xls.py +0 -0
  52. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/EXPORT_TO_PDF_DATA_PROPERTIES.py +0 -0
  53. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/__init__.py +0 -0
  54. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/calculation.py +0 -0
  55. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/consts.py +0 -0
  56. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/diffusion_funcs.py +0 -0
  57. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/info.py +0 -0
  58. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/json.py +0 -0
  59. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/raw.py +0 -0
  60. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/style.py +0 -0
  61. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/smp/table.py +0 -0
  62. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/test.py +0 -0
  63. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/thermo/__init__.py +0 -0
  64. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/thermo/arrhenius.py +0 -0
  65. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/thermo/atomic_level_random_walk.py +0 -0
  66. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy/thermo/basic.py +0 -0
  67. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy.egg-info/SOURCES.txt +0 -0
  68. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy.egg-info/dependency_links.txt +0 -0
  69. {ararpy-0.1.193 → ararpy-0.1.197}/ararpy.egg-info/top_level.txt +0 -0
  70. {ararpy-0.1.193 → ararpy-0.1.197}/setup.cfg +0 -0
  71. {ararpy-0.1.193 → ararpy-0.1.197}/tests/test.py +0 -0
  72. {ararpy-0.1.193 → ararpy-0.1.197}/tests/test2.py +0 -0
  73. {ararpy-0.1.193 → ararpy-0.1.197}/tests/test_error_correlation.py +0 -0
  74. {ararpy-0.1.193 → ararpy-0.1.197}/tests/test_regression_methods.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ararpy
3
- Version: 0.1.193
3
+ Version: 0.1.197
4
4
  Summary: A project for Ar-Ar geochronology
5
5
  Home-page: https://github.com/wuyangchn/ararpy.git
6
6
  Author: Yang Wu
@@ -16,7 +16,7 @@ from . import calc, smp, files, thermo, test
16
16
  """ Information """
17
17
 
18
18
  name = 'ararpy'
19
- version = '0.1.193'
19
+ version = '0.1.197'
20
20
  __version__ = version
21
21
  full_version = version
22
22
  last_update = '2024-03-28'
@@ -61,15 +61,18 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
61
61
  Lb = arr.array_as_float(kwargs.pop('Lb'))
62
62
  sLb = arr.array_as_float(kwargs.pop('sLb') * Lb / 100)
63
63
  t = arr.array_as_float(kwargs.pop('t'))
64
- st = arr.array_as_float(kwargs.pop('st') * t / 100)
64
+ st = arr.array_as_float(kwargs.pop('st'))
65
65
  # Ap = arr.array_as_float(kwargs.pop('Ap'))
66
66
  # sAp = arr.array_as_float(kwargs.pop('sAp') * Ap / 100)
67
67
  # Kp = arr.array_as_float(kwargs.pop('Kp'))
68
68
  # sKp = arr.array_as_float(kwargs.pop('sKp') * Kp / 100)
69
69
 
70
+ print(f"{t = }, {st = }")
71
+
70
72
  # recalculation using Min et al.(2000) equation
71
73
  # lmd = A * W * Y / (f * No)
72
74
  V = f * No / ((Ab + Ae) * W * Y)
75
+ sf = 0
73
76
  sV = pow((V / f * sf) ** 2 + (V / No * sNo) ** 2 + (V / (Ab + Ae)) ** 2 * (sAb ** 2 + sAe ** 2) +
74
77
  (V / W * sW) ** 2 + (V / Y * sY) ** 2, 0.5)
75
78
  # standard age in year, change to Ma
@@ -38,7 +38,7 @@ def mul(*args):
38
38
 
39
39
  Returns
40
40
  -------
41
- 2D list, [values, errors]
41
+ two-D list, [values, errors]
42
42
  """
43
43
  v = np.array(args)
44
44
  res = np.zeros([2, v.shape[-1]], dtype=np.float64)
@@ -575,7 +575,7 @@ def wtd_mean(a: list, e: list, sf: int = 1, adjust_error: bool = True):
575
575
  k0 = sum(a * wt) / sum(wt) # error weighting
576
576
  k4 = sum((a - k0) ** 2 * wt) # Chi square
577
577
  k3 = k4 / df # MSWD mentioned in Min et al., 2000
578
- if adjust_error:
578
+ if adjust_error and k3 > 1:
579
579
  k1 = (k3 / sum(wt)) ** .5
580
580
  else:
581
581
  k1 = (1 / sum(wt)) ** .5
@@ -268,7 +268,7 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
268
268
  M37: Tuple[float, float], M36: Tuple[float, float],
269
269
  G40: Tuple[float, float], G39: Tuple[float, float], G38: Tuple[float, float],
270
270
  G37: Tuple[float, float], G36: Tuple[float, float],
271
- stand_time_year: float,
271
+ stand_time_year: float, JNFactor: Tuple[float, float],
272
272
  **options):
273
273
  """
274
274
 
@@ -294,6 +294,7 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
294
294
  L36cl
295
295
  MDFunc
296
296
  MDF
297
+ JNFactor
297
298
  options
298
299
 
299
300
  Returns
@@ -307,9 +308,7 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
307
308
  Monte_Carlo_Size = 10000
308
309
 
309
310
  # generate random
310
- print(ar40m)
311
311
  ar40m = random_normal_absolute(*ar40m, size=Monte_Carlo_Size)
312
- print(ar40m)
313
312
  ar39m = random_normal_absolute(*ar39m, size=Monte_Carlo_Size)
314
313
  ar38m = random_normal_absolute(*ar38m, size=Monte_Carlo_Size)
315
314
  ar37m = random_normal_absolute(*ar37m, size=Monte_Carlo_Size)
@@ -347,6 +346,8 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
347
346
  R38v39k = random_normal_relative(*R38v39k, size=Monte_Carlo_Size)
348
347
  R36v38clp = random_normal_relative(*R36v38clp, size=Monte_Carlo_Size)
349
348
 
349
+ JNFactor = random_normal_absolute(*JNFactor, size=Monte_Carlo_Size)
350
+
350
351
  blank_gain_corr = options.get('blank_gain_corr', True)
351
352
 
352
353
  def do_simulation():
@@ -376,6 +377,7 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
376
377
  _ar36a = _ar36res - _ar36cl
377
378
  _ar40r = _ar40 - _ar36a * R40v36a[i] - _ar39k * R40v39k[i]
378
379
  _ar40ar = _ar40 - _ar39k * R40v39k[i]
380
+ _ar39k = _ar39k * JNFactor[i]
379
381
  _f = _ar40r / _ar39k
380
382
  i += 1
381
383
  # yield _f, _ar36, _ar37, _ar38, _ar39, _ar40, _ar36a, _ar37ca, _ar39k, _ar40r, _ar36cl
@@ -500,10 +500,16 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
500
500
  flag = params.split(".")[-1]
501
501
  return set_params(smp, read_params(params), flag=flag)
502
502
 
503
+ def isValid(item):
504
+ valid = True
505
+ if isinstance(item, (float, int)):
506
+ valid = not np.isnan(item)
507
+ return valid and item is not None and item != ""
508
+
503
509
  def remove_none(old_params, new_params, row_list, length):
504
510
  res = [[old_params[i][j] if j < len(old_params[i]) else None for j in range(max(len(old_params[i]), length))] for i in range(len(old_params))]
505
511
  for index, item in enumerate(new_params):
506
- if item is not None:
512
+ if isValid(item):
507
513
  for row in row_list:
508
514
  res[index][row] = item
509
515
  return res
@@ -156,15 +156,12 @@ def calc_degas_ca(sample: Sample):
156
156
  ar39ca = calc.arr.mul_factor(ar37ca, sample.TotalParam[8:10], isRelative=True)
157
157
  ar38ca = calc.arr.mul_factor(ar37ca, sample.TotalParam[10:12], isRelative=True)
158
158
  ar36ca = calc.arr.mul_factor(ar37ca, sample.TotalParam[12:14], isRelative=True)
159
- sample.DegasValues[8:10] = copy.deepcopy(ar37ca)
160
- # sample.DegasValues[22:24] = ar39ca if corrDecasCa else [[0] * n, [0] * n]
161
- # sample.DegasValues[18:20] = ar38ca if corrDecasCa else [[0] * n, [0] * n]
162
- # sample.DegasValues[4:6] = ar36ca if corrDecasCa else [[0] * n, [0] * n]
163
- sample.DegasValues[ 4] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar36ca[0])]
159
+ sample.DegasValues[8:10] = copy.deepcopy(ar37ca) # 37Ca
160
+ sample.DegasValues[ 4] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar36ca[0])] # 36Ca
164
161
  sample.DegasValues[ 5] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar36ca[1])]
165
- sample.DegasValues[18] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar38ca[0])]
162
+ sample.DegasValues[18] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar38ca[0])] # 38Ca
166
163
  sample.DegasValues[19] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar38ca[1])]
167
- sample.DegasValues[22] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar39ca[0])]
164
+ sample.DegasValues[22] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar39ca[0])] # 39Ca
168
165
  sample.DegasValues[23] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar39ca[1])]
169
166
  sample.PublishValues[1] = copy.deepcopy(ar37ca[0])
170
167
 
@@ -241,43 +238,51 @@ def calc_degas_cl(sample: Sample):
241
238
  try:
242
239
  if not corrDecasCl:
243
240
  raise ValueError("Do not apply degas chlorine")
244
- v3 = [cl36_cl38_p[0][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i])) for i in
241
+ vDecay = [cl36_cl38_p[0][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i])) for i in
245
242
  range(len(stand_time_year))]
246
- s3 = [pow((cl36_cl38_p[1][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i]))) ** 2 +
243
+ sDecay = [pow((cl36_cl38_p[1][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i]))) ** 2 +
247
244
  (cl36_cl38_p[0][i] * stand_time_year[i] * (np.exp(-1 * decay_const[0][i] * stand_time_year[i])) *
248
245
  decay_const[1][i]) ** 2, 0.5) for i in range(len(stand_time_year))]
249
- s3 = [calc.err.div((1, 0), (v3[i], s3[i])) for i in range(len(s3))]
250
- v3 = [1 / v3[i] for i in range(len(v3))]
246
+ sDecay = [calc.err.div((1, 0), (vDecay[i], sDecay[i])) for i in range(len(sDecay))]
247
+ vDecay = [1 / vDecay[i] for i in range(len(vDecay))]
248
+
251
249
  # 36ArCl
252
250
  ar36cl = [[], []]
253
- ar36cl[0] = [(ar36acl[0][i] * ar38ar36[0][i] - ar38acl[0][i]) / (ar38ar36[0][i] - v3[i])
254
- for i in range(len(ar36acl[0]))]
255
- s1 = [(ar36acl[1][i] * ar38ar36[0][i] / (ar38ar36[0][i] - v3[i])) ** 2 for i in range(len(ar36cl[0]))]
256
- s2 = [(ar38acl[1][i] / (ar38ar36[0][i] - v3[i])) ** 2 for i in range(len(ar36cl[0]))]
257
- s3 = [(s3[i] * (ar36acl[0][i] * ar38ar36[0][i] - ar38acl[0][i]) / (ar38ar36[0][i] - v3[i]) ** 2) ** 2
258
- for i in range(len(ar36cl[0]))]
259
- s4 = [(ar36acl[0][i] / (ar38ar36[0][i] - v3[i]) -
260
- (ar36acl[0][i] * ar38ar36[0][i] - ar38acl[0][i]) / (ar38ar36[0][i] - v3[i]) ** 2) ** 2 *
261
- (ar38ar36[1][i]) ** 2 for i in range(len(ar36cl[0]))]
262
- ar36cl[1] = [pow(s1[i] + s2[i] + s3[i] + s4[i], 0.5) for i in range(len(ar36cl[0]))]
263
-
264
251
  # 38ArCl
265
252
  ar38cl = [[], []]
266
- ar38cl[1] = [calc.err.mul((ar36cl[0][i], ar36cl[1][i]), (v3[i], s3[i])) for i in range(len(ar36cl[0]))]
267
-
268
- # Negative number set to zero
269
- ar36cl[0] = [0 if i < 0 and set_negative_zero else i for i in ar36cl[0]]
270
- # force 36ArCl to zero if 36Ar - 36ArCa - 36Cl < 0
271
- ar36cl[0] = [0 if ar36acl[0][i] - item < 0 and set_negative_zero else item
272
- for i, item in enumerate(ar36cl[0])]
273
-
274
- ar38cl[0] = [ar36cl[0][i] * v3[i] for i in range(len(ar36cl[0]))]
253
+ for i in range(len(vDecay)):
254
+ a1 = sample.CorrectedValues[0][i]; s1 = sample.CorrectedValues[1][i]
255
+ a2 = sample.DegasValues[4][i]; s2 = sample.DegasValues[5][i];
256
+ a3 = sample.DegasValues[16][i]; s3 = sample.DegasValues[17][i]
257
+ a4 = sample.DegasValues[18][i]; s4 = sample.DegasValues[19][i]
258
+ a5 = sample.CorrectedValues[4][i]; s5 = sample.CorrectedValues[5][i]
259
+ a6 = vDecay[i]; s6 = sDecay[i]
260
+ a7 = ar38ar36[0][i]; s7 = ar38ar36[1][i]
261
+
262
+ d1 = 1 / (1 - a6 / a7)
263
+ d2 = - 1 / (1 - a6 / a7)
264
+ d3 = 1 / (a7 - a6)
265
+ d4 = 1 / (a7 - a6)
266
+ d5 = - 1 / (a7 - a6)
267
+ d6 = (a1 - a2 + (a3 + a4) / a7 - a5 / a7) / a7 / (1 - a6 / a7) ** 2
268
+ d7 = -(a1 - a2) * (a6) / (a7 - a6) ** 2 - (a3 + a4 - a5) / (a7 - a6) ** 2
269
+
270
+ v1 = (a1 - a2 + (a3 + a4) / a7 - a5 / a7) / (1 - a6 / a7)
271
+ s1 = (d1**2*s1**2 + d2**2*s2**2 + d3**2*s3**2 + d4**2*s4**2+ d5**2*s5**2 + d6**2*s6**2 + d7**2*s7**2) ** .5
272
+ s2 = calc.err.mul((v1, s1), (vDecay[i], sDecay[i]))
273
+ v1 = 0 if (ar36acl[0][i] - v1 < 0 or v1 < 0) and set_negative_zero[i] else v1
274
+ v2 = v1 * vDecay[i]
275
+
276
+ # Note: Ar36Cl uncertainty is differen with ArArCALC. All calculation was conducted separately considering they are independent
277
+ # s1 = calc.err.div((a1 - a2 + (a3 + a4) / a7 - a5 / a7, calc.err.add(s1, s2, calc.err.div((a3 + a4, calc.err.add(s3, s4)), (a7, s7)), calc.err.div((a5, s5), (a7, s7)))), (1 - a6 / a7, calc.err.div((a6, s6), (a7, s7))))
278
+
279
+ ar36cl[0].append(v1); ar36cl[1].append(s1)
280
+ ar38cl[0].append(v2); ar38cl[1].append(s2)
275
281
 
276
282
  except Exception as e:
277
283
  print('Error in corr Cl: {}, lines: {}'.format(e, e.__traceback__.tb_lineno))
278
- n = len(ar36acl[0])
279
- ar36cl = np.zeros([2, n])
280
- ar38cl = np.zeros([2, n])
284
+ ar36cl = np.zeros([2, len(ar36acl[0])])
285
+ ar38cl = np.zeros([2, len(ar36acl[0])])
281
286
 
282
287
  # sample.DegasValues[6:8] = ar36cl
283
288
  # sample.DegasValues[10:12] = ar38cl
@@ -349,7 +354,7 @@ def calc_degas_r(sample: Sample):
349
354
  """
350
355
  ar40ar = calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32])
351
356
  ar40r = calc.arr.sub(ar40ar, sample.DegasValues[26:28])
352
- ar40r[0] = [item if item >= 0 else 0 for item in ar40r[0]]
357
+ ar40r[0] = [0 if item < 0 and sample.TotalParam[101][index] else item for index, item in enumerate(ar40r[0])]
353
358
  sample.DegasValues[24:26] = copy.deepcopy(ar40r)
354
359
  sample.PublishValues[4] = copy.deepcopy(ar40r[0])
355
360
 
@@ -360,11 +365,16 @@ def calc_degas_r(sample: Sample):
360
365
  def calc_nor_inv_isochrons(sample: Sample):
361
366
  n = len(sample.SequenceName)
362
367
  try:
363
- isochron_1 = calc.isochron.get_data(*sample.DegasValues[20:22], *calc.arr.sub(
364
- sample.CorrectedValues[8:10], sample.DegasValues[30:32]), *sample.DegasValues[0:2])
365
- isochron_2 = calc.isochron.get_data(*sample.DegasValues[20:22], *sample.DegasValues[0:2], *calc.arr.sub(
366
- sample.CorrectedValues[8:10], sample.DegasValues[30:32]))
367
- except:
368
+ isochron_1 = calc.isochron.get_data(
369
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
370
+ *calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]),
371
+ *sample.DegasValues[0:2]
372
+ )
373
+ isochron_2 = calc.isochron.get_data(
374
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
375
+ *sample.DegasValues[0:2],
376
+ *calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]))
377
+ except (BaseException, Exception):
368
378
  return np.zeros([5, n]), np.zeros([5, n])
369
379
  else:
370
380
  return isochron_1, isochron_2
@@ -374,12 +384,18 @@ def calc_cl_isochrons(sample: Sample):
374
384
  n = len(sample.SequenceName)
375
385
  try:
376
386
  isochron_3 = calc.isochron.get_data(
377
- *sample.DegasValues[20:22], *sample.DegasValues[24:26], *sample.DegasValues[10:12])
387
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
388
+ *sample.DegasValues[24:26],
389
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor))
378
390
  isochron_4 = calc.isochron.get_data(
379
- *sample.DegasValues[20:22], *sample.DegasValues[10:12], *sample.DegasValues[24:26])
391
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
392
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor),
393
+ *sample.DegasValues[24:26])
380
394
  isochron_5 = calc.isochron.get_data(
381
- *sample.DegasValues[10:12], *sample.DegasValues[24:26], *sample.DegasValues[20:22])
382
- except:
395
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor),
396
+ *sample.DegasValues[24:26],
397
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor))
398
+ except (BaseException, Exception):
383
399
  return np.zeros([5, n]), np.zeros([5, n]), np.zeros([5, n])
384
400
  else:
385
401
  return isochron_3, isochron_4, isochron_5
@@ -422,7 +438,6 @@ def calc_ratio(sample: Sample, monte_carlo: bool = False):
422
438
  """
423
439
  ar40r_percent = [item / sample.CorrectedValues[8][index] * 100 if sample.CorrectedValues[8][index] != 0 else 0
424
440
  for index, item in enumerate(sample.DegasValues[24])]
425
- sum_ar39k = sum(sample.DegasValues[20])
426
441
  sum_ar36a = sum(sample.DegasValues[ 0])
427
442
  CaK = calc.arr.mul_factor(calc.arr.mul_factor(
428
443
  sample.DegasValues[8:10], calc.arr.rec_factor(sample.DegasValues[20:22], isRelative=False)),
@@ -437,10 +452,12 @@ def calc_ratio(sample: Sample, monte_carlo: bool = False):
437
452
  sample.ApparentAgeValues[0:2] = ar40aar36a
438
453
  sample.ApparentAgeValues[7] = ar36a_percent
439
454
  else:
455
+ ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor)
456
+ sum_ar39k = sum(ar39k)
457
+ ar39k_percent = [item / sum_ar39k * 100 if sum_ar39k != 0 else 0 for item in ar39k]
440
458
  ar40rar39k = calc.arr.mul_factor(
441
459
  sample.DegasValues[24:26], calc.arr.rec_factor(sample.DegasValues[20:22], isRelative=False),
442
460
  isRelative=False)
443
- ar39k_percent = [item / sum_ar39k * 100 if sum_ar39k != 0 else 0 for item in sample.DegasValues[20]]
444
461
  sample.ApparentAgeValues[0:2] = ar40rar39k
445
462
  sample.ApparentAgeValues[7] = ar39k_percent
446
463
 
@@ -528,6 +545,8 @@ def monte_carlo_f(sample: Sample):
528
545
  R38v36a = np.transpose(sample.TotalParam[4:6])
529
546
  R36v38clp = np.transpose(sample.TotalParam[56:58])
530
547
 
548
+ JNFactor = np.transpose(sample.NormalizeFactor)
549
+
531
550
  stand_time_year = np.transpose(sample.TotalParam[32])
532
551
 
533
552
  irradiation_cycles = [list(filter(None, re.split(r'[DS]', each_step))) for each_step in sample.TotalParam[27]]
@@ -562,6 +581,7 @@ def monte_carlo_f(sample: Sample):
562
581
  L37ar=L37ar[i], L39ar=L39ar[i], L36cl=L36cl[i],
563
582
  MDFunc=None,
564
583
  MDF=MDF[i], stand_time_year=stand_time_year[i],
584
+ JNFactor=JNFactor,
565
585
  blank_gain_corr=sample.TotalParam[111][i]
566
586
  )
567
587
 
@@ -1069,7 +1069,7 @@ class WritingWorkbook:
1069
1069
  material = self.sample.Info.sample.material
1070
1070
  weight = self.sample.Info.sample.weight
1071
1071
  J_value = self.sample.TotalParam[67][0]
1072
- J_error = self.sample.TotalParam[68][0]
1072
+ J_error = self.sample.TotalParam[68][0] * self.sample.TotalParam[67][0] / 100
1073
1073
  sigma = self.sample.Info.preference['confidenceLevel']
1074
1074
  sequence_type = {"StepLaser": "Laser", "StepFurnace": "Temperature", "StepCrusher": "Drop", }.get(method, "Step Value")
1075
1075
  sequence_unit = self.sample.Info.sample.sequence_unit if self.sample.Info.sample.sequence_unit != "" else "Unit"
@@ -16,7 +16,7 @@ import pandas as pd
16
16
  import numpy as np
17
17
  import copy
18
18
  from typing import List, Union, Optional
19
- from ..calc import arr
19
+ from ..calc import arr, err
20
20
  from ..files import calc_file
21
21
  from . import (sample as samples, basic, table, raw as smp_raw)
22
22
 
@@ -268,10 +268,10 @@ def initial_plot_styles(sample: Sample, except_attrs=None):
268
268
  set_attr(plot, key, attr)
269
269
 
270
270
 
271
- def re_set_smp(sample: Sample):
271
+ def re_set_smp(smp: Sample):
272
272
  std = initial(Sample())
273
- basic.get_merged_smp(sample, std)
274
- return sample
273
+ basic.get_merged_smp(smp, std)
274
+ return check_version(smp)
275
275
 
276
276
 
277
277
  def check_version(smp: Sample):
@@ -286,10 +286,28 @@ def check_version(smp: Sample):
286
286
 
287
287
  """
288
288
  if smp.version != samples.VERSION:
289
- re_set_smp(smp)
290
- if int(smp.version) <= 20250328: # Experiment info
291
- smp.Info.experiment.name = smp.name()
292
- smp.Info.experiment.step_num = smp.sequence().size
289
+ std = initial(Sample())
290
+ basic.get_merged_smp(smp, std)
291
+
292
+ # 20250328: # Experiment info
293
+ smp.Info.experiment.name = smp.name()
294
+ smp.Info.experiment.step_num = smp.sequence().size
295
+
296
+ # 20250404
297
+ doNormalize = True
298
+ v, sv = [], []
299
+ if smp.Info.sample.type.lower() != "unknown":
300
+ v, sv = smp.TotalParam[67:69]
301
+ sv = np.multiply(v, sv) / 100
302
+ elif smp.Info.sample.type.lower() != "air":
303
+ v, sv = smp.TotalParam[95:97]
304
+ sv = np.multiply(v, sv) / 100
305
+ elif smp.Info.sample.type.lower() != "standard":
306
+ v, sv = smp.TotalParam[59:61]
307
+ smp.NormalizeFactor = [
308
+ [1 if v[0] == each or not doNormalize else v[0] / each for each in v],
309
+ [0 if v[0] == v[i] or not doNormalize else err.div((v[0], sv[0]), (v[i], sv[i])) for i in range(len(v))]
310
+ ]
293
311
  return smp
294
312
 
295
313
 
@@ -356,7 +374,7 @@ def from_calc_files(file_path: str, **kwargs):
356
374
  """
357
375
  file = calc_file.ArArCalcFile(file_path=file_path, **kwargs).open()
358
376
  sample = create_sample_from_df(file.get_content(), file.get_smp_info())
359
- return sample
377
+ return check_version(sample)
360
378
 
361
379
 
362
380
  # create
@@ -375,7 +393,7 @@ def from_full_files(file_path: str, sample_name: str = None):
375
393
  sample_name = str(os.path.split(file_path)[-1]).split('.')[0]
376
394
  content, sample_info = calc_file.open_full_xls(file_path, sample_name)
377
395
  sample = create_sample_from_dict(content=content, smp_info=sample_info)
378
- return sample
396
+ return check_version(sample)
379
397
 
380
398
 
381
399
  # create
@@ -453,4 +471,4 @@ def from_raw_data(raw: RawData, mapping: Optional[List[dict]] = None) -> Sample:
453
471
 
454
472
  # sample.TotalParam[31] = [raw.get_sequence(row['unknown'], flag='name').datetime for row in mapping]
455
473
 
456
- return sample
474
+ return check_version(sample)
@@ -405,6 +405,9 @@ def recalc_age_plateaus(sample: Sample, **kwargs):
405
405
  -------
406
406
  None
407
407
  """
408
+ ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor)
409
+ ar40r, sar40r = sample.DegasValues[24:26]
410
+ ar40rar39k = calc.arr.div([ar40r, sar40r], [ar39k, sar39k])
408
411
  params_initial_ratio = calc.arr.partial(sample.TotalParam, cols=list(range(115, 120)))
409
412
  ratio_set1 = [[], []]
410
413
  ratio_set2 = [[], []]
@@ -430,10 +433,12 @@ def recalc_age_plateaus(sample: Sample, **kwargs):
430
433
  ratio_set2[0].append(298.56)
431
434
  ratio_set2[1].append(0.31)
432
435
 
433
- # Get ages and line data points for each set
436
+ # Weighted mean ages of two sets with the given initial ratios
434
437
  try:
435
- set1_res, set1_age, set1_data = \
436
- get_plateau_results(sample, sample.SelectedSequence1, calc_ar40ar39(*ratio_set1, smp=sample), **kwargs)
438
+ set1_res, set1_age, set1_data = get_plateau_results(
439
+ sample, sample.SelectedSequence1, calc_ar40ar39(*ratio_set1, smp=sample),
440
+ ar39k_percentage=np.cumsum(ar39k) / np.sum(ar39k),
441
+ **kwargs)
437
442
  except ValueError:
438
443
  # print(traceback.format_exc())
439
444
  pass
@@ -443,8 +448,10 @@ def recalc_age_plateaus(sample: Sample, **kwargs):
443
448
  sample.AgeSpectraPlot.set1.data = calc.arr.transpose(set1_data)
444
449
  sample.AgeSpectraPlot.text1.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
445
450
  try:
446
- set2_res, set2_age, set2_data = \
447
- get_plateau_results(sample, sample.SelectedSequence2, calc_ar40ar39(*ratio_set2, smp=sample), **kwargs)
451
+ set2_res, set2_age, set2_data = get_plateau_results(
452
+ sample, sample.SelectedSequence2, calc_ar40ar39(*ratio_set2, smp=sample),
453
+ ar39k_percentage=np.cumsum(ar39k) / np.sum(ar39k),
454
+ **kwargs)
448
455
  except ValueError:
449
456
  # print(traceback.format_exc())
450
457
  pass
@@ -454,16 +461,18 @@ def recalc_age_plateaus(sample: Sample, **kwargs):
454
461
  sample.AgeSpectraPlot.set2.data = calc.arr.transpose(set2_data)
455
462
  sample.AgeSpectraPlot.text2.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
456
463
 
457
- # Get weighted mean ages of two sets
464
+ # Weighted mean ages of two sets with 298.56 (defoult air ratio)
458
465
  try:
459
- set1_res = get_wma_results(sample, sample.SelectedSequence1)
466
+ set1_res = get_wma_results(
467
+ sample, sample.SelectedSequence1, ar40rar39k=ar40rar39k, ar39k_percentage=np.cumsum(ar39k) / np.sum(ar39k))
460
468
  except ValueError:
461
469
  pass
462
470
  # raise ValueError(f"Set 1 WMA calculation error.")
463
471
  else:
464
472
  sample.Info.results.age_spectra.update({0: set1_res})
465
473
  try:
466
- set2_res = get_wma_results(sample, sample.SelectedSequence2)
474
+ set2_res = get_wma_results(
475
+ sample, sample.SelectedSequence2, ar40rar39k=ar40rar39k, ar39k_percentage=np.cumsum(ar39k) / np.sum(ar39k))
467
476
  except ValueError:
468
477
  pass
469
478
  # raise ValueError(f"Set 2 WMA calculation error.")
@@ -558,7 +567,7 @@ def calc_ar40ar39(r, sr, smp):
558
567
  """
559
568
  try:
560
569
  ar36a = np.array(smp.DegasValues[0:2])
561
- ar39k = smp.DegasValues[20:22]
570
+ ar39k = calc.arr.mul(smp.DegasValues[20:22], smp.NormalizeFactor)
562
571
  ar40 = smp.CorrectedValues[8:10]
563
572
  ar40k = smp.DegasValues[30:32]
564
573
  size = ar36a.shape[-1]
@@ -568,8 +577,6 @@ def calc_ar40ar39(r, sr, smp):
568
577
  ratio = np.array([r, sr])
569
578
  else:
570
579
  raise ValueError(f"Initial ratio is unsupported.")
571
- # print(f"{ratio = }")
572
- # print(f"{ar36a = }")
573
580
  ar40a = calc.arr.mul(ar36a, ratio)
574
581
  ar40r = calc.arr.sub(ar40, ar40k, ar40a)
575
582
  ar40rar39k: list = calc.arr.div(ar40r, ar39k)
@@ -627,13 +634,15 @@ def get_plateau_results(sample: Sample, sequence: list, ar40rar39k: list = None,
627
634
  return plateau_res, age, plot_data
628
635
 
629
636
 
630
- def get_wma_results(sample: Sample, sequence: list):
637
+ def get_wma_results(sample: Sample, sequence: list, ar40rar39k: list = None, ar39k_percentage: list = None):
631
638
  """
632
639
  Get initial ratio re-corrected plateau results
633
640
  Parameters
634
641
  ----------
635
642
  sample : sample instance
636
643
  sequence : data slice index
644
+ ar40rar39k :
645
+ ar39k_percentage :
637
646
 
638
647
  Returns
639
648
  -------
@@ -642,6 +651,11 @@ def get_wma_results(sample: Sample, sequence: list):
642
651
  'age', 's1', 's2', 's3', 'Ar39', 'rs'
643
652
  ]
644
653
  """
654
+ if ar40rar39k is None:
655
+ ar40rar39k = sample.ApparentAgeValues[0:2]
656
+ if ar39k_percentage is None:
657
+ ar39k_percentage = sample.ApparentAgeValues[7]
658
+
645
659
  spectra_res = initial.SPECTRA_RES.copy()
646
660
  # spectra_res = initial.SPECTRA_RES
647
661
 
@@ -649,9 +663,9 @@ def get_wma_results(sample: Sample, sequence: list):
649
663
  return [arg[min(points): max(points) + 1] for arg in args]
650
664
 
651
665
  if len(sequence) > 0:
652
- sum_ar39k = sum(_get_partial(sequence, sample.ApparentAgeValues[7])[0])
653
- fs = _get_partial(sequence, sample.ApparentAgeValues[0])[0]
654
- sfs = _get_partial(sequence, sample.ApparentAgeValues[1])[0]
666
+ sum_ar39k = sum(_get_partial(sequence, ar39k_percentage)[0])
667
+ fs = _get_partial(sequence, ar40rar39k[0])[0]
668
+ sfs = _get_partial(sequence, ar40rar39k[1])[0]
655
669
 
656
670
  wmf, swmf, num, mswd, chisq, p = calc.arr.wtd_mean(fs, sfs)
657
671
  age, s1, s2, s3 = basic.calc_age([wmf, swmf], smp=sample)
@@ -115,9 +115,9 @@ TOTAL_PARAMS_HEADERS = [
115
115
  'Mass \u00B3\u2078Ar', '%1\u03C3', 'Mass \u00B3\u2079Ar', '%1\u03C3',
116
116
  'Mass \u2074\u2070', '%1\u03C3', 'K Mass', '%1\u03C3', # 73-84
117
117
  'No', '%1\u03C3', 'Year', '%1\u03C3', '\u2074\u2070K/K', '%1\u03C3',
118
- '\u00B3\u2075/\u00B3\u2077Cl', '%1\u03C3', 'HCl/Cl', '%1\u03C3', # 85-94
119
- '\u2074\u2070Ar/\u00B3\u2076Ar air', '%1\u03C3',
120
- '\u00B3\u2078Ar/\u00B3\u2076Ar air', '%1\u03C3', # 95-98
118
+ '\u00B3\u2075Cl/\u00B3\u2077Cl', '%1\u03C3', 'HCl/Cl', '%1\u03C3', # 85-94
119
+ '\u2074\u2070Ar/\u00B3\u2076Ar air', '%1\u03C3', # 95-96
120
+ '\u00B3\u2078Ar/\u00B3\u2076Ar air', '%1\u03C3', # 97-98
121
121
  'Isochron Fitting', 'Convergence', 'Iteration', 'Discrimination', # 99-102
122
122
  'Not Zero', 'Corr Blank', 'Corr Discr', 'Corr \u00B3\u2077Ar Decay', # 103-106
123
123
  'Corr \u00B3\u2079Ar Decay', # 107
@@ -743,7 +743,7 @@ DEFAULT_PLOT_STYLES = {
743
743
  },
744
744
  }
745
745
 
746
- VERSION = '20250328'
746
+ VERSION = '20250404'
747
747
 
748
748
  NAMED_DICT = {
749
749
  "unknown": {"header": SAMPLE_INTERCEPT_HEADERS.copy()},
@@ -812,6 +812,7 @@ class Sample:
812
812
  self.SelectedSequence2 = []
813
813
  self.UnselectedSequence = []
814
814
  self.IsochronMark = []
815
+ self.NormalizeFactor = [[], []]
815
816
 
816
817
  # Tables and Plots
817
818
  self.UnknownTable = Table()
@@ -849,7 +850,8 @@ class Sample:
849
850
  # self.__version = '20250102' # gain correction to blanks
850
851
  # self.__version = '20250301' # update sample info
851
852
  # self.__version = '20250321' # error sigma adjustment
852
- self.__version = '20250328' # Experiment info
853
+ # self.__version = '20250328' # Experiment info
854
+ self.__version = '20250404' # J normalization factor
853
855
 
854
856
  @property
855
857
  def version(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ararpy
3
- Version: 0.1.193
3
+ Version: 0.1.197
4
4
  Summary: A project for Ar-Ar geochronology
5
5
  Home-page: https://github.com/wuyangchn/ararpy.git
6
6
  Author: Yang Wu
@@ -16,7 +16,7 @@ long_description = (here / 'README.md').read_text(encoding='utf-8')
16
16
 
17
17
  setuptools.setup(
18
18
  name='ararpy', #
19
- version='0.1.193', # version
19
+ version='0.1.197', # version
20
20
  author='Yang Wu',
21
21
  author_email='wuycug@hotmail.com',
22
22
  description='A project for Ar-Ar geochronology', # short description
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes