ararpy 0.1.19__tar.gz → 0.1.20__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.19 → ararpy-0.1.20}/PKG-INFO +1 -1
  2. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/__init__.py +4 -2
  3. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/age.py +2 -1
  4. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/arr.py +16 -6
  5. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/corr.py +9 -7
  6. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/jvalue.py +1 -1
  7. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/plot.py +5 -2
  8. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/calc_file.py +2 -5
  9. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/raw_file.py +3 -4
  10. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/xls.py +1 -2
  11. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/basic.py +119 -70
  12. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/corr.py +69 -51
  13. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/export.py +82 -49
  14. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/initial.py +47 -17
  15. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/plots.py +126 -87
  16. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/sample.py +55 -17
  17. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/style.py +23 -16
  18. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy.egg-info/PKG-INFO +1 -1
  19. {ararpy-0.1.19 → ararpy-0.1.20}/setup.py +1 -1
  20. {ararpy-0.1.19 → ararpy-0.1.20}/LICENSE +0 -0
  21. {ararpy-0.1.19 → ararpy-0.1.20}/README.md +0 -0
  22. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/__init__.py +0 -0
  23. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/basic.py +0 -0
  24. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/err.py +0 -0
  25. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/histogram.py +0 -0
  26. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/isochron.py +0 -0
  27. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/raw_funcs.py +0 -0
  28. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/regression.py +0 -0
  29. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/calc/spectra.py +0 -0
  30. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/022_VU124-M11a.ahd +0 -0
  31. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/20WHA0103.age +0 -0
  32. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/22WHA0078.xls +0 -0
  33. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/22WHA0433.age +0 -0
  34. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/22WHA0433.arr +0 -0
  35. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/22WHA0433.full.xls +0 -0
  36. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/24WHN0001-51-592.XLS +0 -0
  37. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/AHD.input-filter +0 -0
  38. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/ArAr.calc +0 -0
  39. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/ArArCALC.age +0 -0
  40. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/NGX-600 - Copy.TXT +0 -0
  41. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/NGX-600.TXT +0 -0
  42. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/NGX-XLS.input-filter +0 -0
  43. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/Qtegra-exported-xls.input-filter +0 -0
  44. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/S01-239.csv +0 -0
  45. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/WH01.irra +0 -0
  46. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/WHA.pdf +0 -0
  47. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/raw_example.xls +0 -0
  48. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/examples/sample-default.smp +0 -0
  49. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/__init__.py +0 -0
  50. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/arr_file.py +0 -0
  51. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/basic.py +0 -0
  52. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/files/new_file.py +0 -0
  53. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/EXPORT_TO_PDF_DATA_PROPERTIES.py +0 -0
  54. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/__init__.py +0 -0
  55. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/calculation.py +0 -0
  56. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/consts.py +0 -0
  57. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/diffusion_funcs.py +0 -0
  58. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/info.py +0 -0
  59. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/json.py +0 -0
  60. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/raw.py +0 -0
  61. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/smp/table.py +0 -0
  62. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/test.py +0 -0
  63. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/thermo/__init__.py +0 -0
  64. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/thermo/arrhenius.py +0 -0
  65. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/thermo/atomic_level_random_walk.py +0 -0
  66. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy/thermo/basic.py +0 -0
  67. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy.egg-info/SOURCES.txt +0 -0
  68. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy.egg-info/dependency_links.txt +0 -0
  69. {ararpy-0.1.19 → ararpy-0.1.20}/ararpy.egg-info/top_level.txt +0 -0
  70. {ararpy-0.1.19 → ararpy-0.1.20}/setup.cfg +0 -0
  71. {ararpy-0.1.19 → ararpy-0.1.20}/tests/test.py +0 -0
  72. {ararpy-0.1.19 → ararpy-0.1.20}/tests/test2.py +0 -0
  73. {ararpy-0.1.19 → ararpy-0.1.20}/tests/test_error_correlation.py +0 -0
  74. {ararpy-0.1.19 → ararpy-0.1.20}/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.19
3
+ Version: 0.1.20
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,10 +16,10 @@ from . import calc, smp, files, thermo, test
16
16
  """ Information """
17
17
 
18
18
  name = 'ararpy'
19
- version = '0.0.1.a4'
19
+ version = '0.1.20'
20
20
  __version__ = version
21
21
  full_version = version
22
- last_update = '2024-01-04'
22
+ last_update = '2024-03-28'
23
23
 
24
24
  """ ArArPy Functions """
25
25
 
@@ -116,6 +116,8 @@ Sample.plot_cl_3 = lambda _smp: smp.calculation.recalculate(
116
116
  Sample.plot_3D = lambda _smp: smp.calculation.recalculate(
117
117
  _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_7'])
118
118
 
119
+ Sample.to_excel = lambda _smp, file_path, *args, **kwargs: smp.export.to_excel(_smp, file_path=file_path, *args, **kwargs)
120
+
119
121
  Sample.show_data = lambda _smp: \
120
122
  f"Sample Name: \n\t{_smp.name()}\n" \
121
123
  f"Doi: \n\t{_smp.doi()}\n" \
@@ -61,7 +61,7 @@ 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'))
@@ -70,6 +70,7 @@ def calc_age_min(F, sF, **kwargs) -> tuple:
70
70
  # recalculation using Min et al.(2000) equation
71
71
  # lmd = A * W * Y / (f * No)
72
72
  V = f * No / ((Ab + Ae) * W * Y)
73
+ sf = 0
73
74
  sV = pow((V / f * sf) ** 2 + (V / No * sNo) ** 2 + (V / (Ab + Ae)) ** 2 * (sAb ** 2 + sAe ** 2) +
74
75
  (V / W * sW) ** 2 + (V / Y * sY) ** 2, 0.5)
75
76
  # 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)
@@ -67,10 +67,11 @@ def div(a, b):
67
67
  n = np.shape([a, b])[-1]
68
68
  k0, k1 = [], []
69
69
  for i in range(n):
70
- k0.append(np.divide(a[0][i], b[0][i]))
71
- k1.append(
72
- (np.divide(a[1][i] ** 2, b[0][i] ** 2) +
73
- np.divide(a[0][i] ** 2 * b[1][i] ** 2, b[0][i] ** 4)) ** .5)
70
+ try:
71
+ k0.append(np.divide(a[0][i], b[0][i]))
72
+ k1.append((np.divide(a[1][i] ** 2, b[0][i] ** 2) + np.divide(a[0][i] ** 2 * b[1][i] ** 2, b[0][i] ** 4)) ** .5)
73
+ except TypeError as e:
74
+ raise TypeError(f"a = {a[0][i]}, b = {b[0][i]}, {e}")
74
75
  return [k0, k1]
75
76
 
76
77
 
@@ -514,6 +515,15 @@ def transpose(obj, ignore: bool = True):
514
515
  raise ValueError
515
516
 
516
517
 
518
+ def remove_empty(a: list):
519
+ index = 0
520
+ for i in range(len(a)):
521
+ if not is_empty(a[-(i + 1)]):
522
+ index = len(a) - i
523
+ break
524
+ return transpose(a[:index])
525
+
526
+
517
527
  def get_item(obj: list, loc: (list, tuple, int), default: Union[str, int, float, bool] = None,
518
528
  base: Union[int, tuple, list] = 0) -> Union[str, int, float, bool]:
519
529
  """ Get item from a n-dimension list
@@ -566,7 +576,7 @@ def wtd_mean(a: list, e: list, sf: int = 1, adjust_error: bool = True):
566
576
  k0 = sum(a * wt) / sum(wt) # error weighting
567
577
  k4 = sum((a - k0) ** 2 * wt) # Chi square
568
578
  k3 = k4 / df # MSWD mentioned in Min et al., 2000
569
- if adjust_error:
579
+ if adjust_error and k3 > 1:
570
580
  k1 = (k3 / sum(wt)) ** .5
571
581
  else:
572
582
  k1 = (1 / sum(wt)) ** .5
@@ -72,18 +72,18 @@ def mdf(rm: float, srm: float, m1: float, m2: float, ra: float = 298.56,
72
72
  v3 = err.div((np.log(ra / rm), v1), (np.log(ratio_m), v2))
73
73
  k4 = err.div((np.log(ra / rm) / np.log(ratio_m), v3), (m1, sm1))
74
74
  except Exception:
75
- k3, k4 = "Null", "Null"
75
+ k3, k4 = 0, 0
76
76
  # pow
77
77
  try:
78
78
  k5 = pow((ra / rm), (1 / delta_m)) # Renne2009, B.D. Turrin2010
79
79
  k6 = err.pow((ra / rm, err.div((ra, sra), (rm, srm))),
80
80
  (1 / delta_m, err.div((1, 0), (delta_m, sdelta_m))))
81
81
  except Exception:
82
- k5, k6 = "Null", "Null"
83
- return k1, k2, k3, k4, k5, k6
82
+ k5, k6 = 0, 0
83
+ return k1, k2, k2, k2, k3, k4, k4, k4, k5, k6, k6, k6
84
84
  else:
85
85
  mdf_line_2 = (rm / ra - 1) / delta_m # Ryu et al., 2013
86
- return mdf_line_2, 0, 0, 0, 0, 0
86
+ return mdf_line_2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
87
87
 
88
88
 
89
89
  def discr(a0: list, e0: list, mdf: list, smdf: list, m: list, m40: list,
@@ -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
@@ -36,4 +36,4 @@ def j_value(age, sage, r, sr, f, rsf):
36
36
  v2 = sage ** 2 * (f * np.exp(f * age) / r) ** 2
37
37
  v3 = sr ** 2 * ((1 - np.exp(f * age)) / r ** 2) ** 2
38
38
  k1 = np.sqrt(v1 + v2 + v3)
39
- return k0, k1
39
+ return k0, k1, k1, k1
@@ -39,8 +39,11 @@ def get_axis_scale(data: list, count=6, increment=None, extra_count=0, min_inter
39
39
  """
40
40
  if len(data) == 0:
41
41
  return 0, 1, 5, 0.2 # Default return
42
- _max = float(np.ma.masked_invalid(data).max())
43
- _min = float(np.ma.masked_invalid(data).min())
42
+ _max = np.ma.masked_invalid(data).max()
43
+ _min = np.ma.masked_invalid(data).min()
44
+ if isinstance(_max, np.ma.core.MaskedConstant) or isinstance(_min, np.ma.core.MaskedConstant):
45
+ return 0, 1, 5, 0.2 # Default return
46
+ _max = float(_max); _min = float(_min)
44
47
  interval = (_max - _min) / count
45
48
  if interval == 0:
46
49
  interval = 10
@@ -49,8 +49,7 @@ def read_calc_file(file_path: str):
49
49
  book_contents[each_sheet] = sheet_contents
50
50
  os.remove(decrypt_file_path)
51
51
  except Exception as e:
52
- print(traceback.format_exc())
53
- return False
52
+ raise
54
53
  else:
55
54
  return book_contents
56
55
 
@@ -420,7 +419,7 @@ def open_full_xls(file_path: str, sample_name: str = ''):
420
419
  try:
421
420
  res = xls.open_xls(file_path)
422
421
  except (Exception, BaseException) as e:
423
- return e
422
+ raise
424
423
  start_row = 5
425
424
  rows_num = len(res['Sample Parameters']) - 5
426
425
 
@@ -583,8 +582,6 @@ class ArArCalcFile:
583
582
 
584
583
  def open(self):
585
584
  book_contents = read_calc_file(self.file_path)
586
- if not book_contents:
587
- raise ValueError('Fail to open the file')
588
585
  # create data frames for book values
589
586
  content = pd.DataFrame(book_contents['Data Tables'])
590
587
  logs01 = pd.DataFrame(book_contents['Logs01'])
@@ -274,7 +274,7 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
274
274
  raise ValueError(f"Step name not found")
275
275
  except (TypeError, ValueError, IndexError):
276
276
  # When parsing the step name fails, the end of the file has been reached
277
- break
277
+ raise
278
278
 
279
279
  # other information
280
280
  options = get_sample_info(file_contents, optional_info_index, default="", base=[1, 1 - idx, 1])
@@ -345,10 +345,9 @@ def get_raw_data(file_contents: List[List[Union[int, float, str, bool, list]]],
345
345
  break
346
346
 
347
347
  step_list.append(current_step)
348
- step_index += 1
349
- idx = input_filter[32] * step_index
348
+ idx = input_filter[32] * len(step_list)
350
349
 
351
- if not check_box_index[0] or step_index >= 500: # check_box_index[0]: multiple sequences
350
+ if not check_box_index[0] or len(step_list) >= 500: # check_box_index[0]: multiple sequences
352
351
  break
353
352
 
354
353
  return step_list
@@ -20,8 +20,7 @@ def open_xls(filepath: str):
20
20
  sheet = wb.sheet_by_name(sheet_name)
21
21
  res[sheet_name] = [[sheet.cell(row, col).value for col in range(sheet.ncols)] for row in range(sheet.nrows)]
22
22
  except biffh.XLRDError as e:
23
- print('Error in opening excel file: %s' % str(e))
24
- return e
23
+ raise
25
24
  else:
26
25
  return res
27
26
 
@@ -44,39 +44,97 @@ def calc_apparent_ages(smp: Sample):
44
44
  -------
45
45
 
46
46
  """
47
- if smp.Info.sample.type == "Unknown":
48
- age = calc_age(smp=smp)
49
- smp.ApparentAgeValues[2:6] = age
50
- smp.PublishValues[5:7] = copy.deepcopy(age[0:2])
51
- if smp.Info.sample.type == "Standard":
52
- j = calc_j(smp=smp)
53
- smp.ApparentAgeValues[2:4] = j
54
- smp.PublishValues[5:7] = copy.deepcopy(j[0:2])
55
- if smp.Info.sample.type == "Air":
56
- mdf = calc_mdf(smp=smp)
57
- smp.ApparentAgeValues[2:4] = mdf
58
- smp.PublishValues[5:7] = copy.deepcopy(mdf[0:2])
47
+ if str(smp.Info.sample.type).lower() == "unknown":
48
+ v = calc_age(smp=smp)
49
+ elif str(smp.Info.sample.type).lower() == "standard":
50
+ v = calc_j(smp=smp)
51
+ elif str(smp.Info.sample.type).lower() == "air":
52
+ v = calc_mdf(smp=smp)
53
+ else:
54
+ raise TypeError(f"Sample type is not supported: {smp.Info.sample.type}")
55
+ try:
56
+ smp.ApparentAgeValues[2:6] = v[0:4]
57
+ smp.PublishValues[5:7] = copy.deepcopy(v[0:2])
58
+ except (Exception, BaseException):
59
+ raise
59
60
 
60
61
 
61
62
  def calc_j(ar40ar39=None, params: dict = None, smp: Sample = None, index: list = None):
62
- std_age, std_err = smp.TotalParam[59:61]
63
- r, sr = smp.ApparentAgeValues[0:2] # ar40ar39, error
64
- f, rsf = smp.TotalParam[34:36] # L, sL
65
- j, sj = calc.jvalue.j_value(std_age, std_err, r, sr, f, rsf)
66
- return [j.tolist(), sj.tolist()]
63
+ params_index_dict = {
64
+ 34: 'L', 35: 'rsL', 59: 'Age', 60: 'sAge'
65
+ }
66
+ if ar40ar39 is None and smp is not None:
67
+ ar40ar39 = smp.ApparentAgeValues[0:2] # ar40ar39 air, error
68
+ if len(np.shape(ar40ar39)) == 1:
69
+ ar40ar39 = np.reshape(ar40ar39, (2, 1))
70
+ if index is None:
71
+ index = list(range(np.shape(ar40ar39)[-1]))
72
+ if smp is None and params is None:
73
+ raise ValueError(f"Parameters are required for calculating mdf, or it is empty.")
74
+ if params is not None:
75
+ for key, val in params.items():
76
+ if not isinstance(val, list):
77
+ params[key] = list(val)
78
+ if smp is not None:
79
+ try:
80
+ params_from_smp = dict(zip(
81
+ list(params_index_dict.values()),
82
+ [[smp.TotalParam[i][j] for j in index] for i in params_index_dict.keys()]
83
+ ))
84
+ except Exception:
85
+ print(traceback.format_exc())
86
+ raise ValueError(f"Parameters cannot be found in the given sample object")
87
+ if params is not None:
88
+ params_from_smp.update(params)
89
+ params = params_from_smp
90
+
91
+ j = calc.jvalue.j_value(params['Age'], params['sAge'], *ar40ar39, params['L'], params['rsL'])
92
+
93
+ if len(index) == 1:
94
+ return np.array(j).squeeze().tolist()
95
+ else:
96
+ return np.array(j).tolist()
67
97
 
68
98
 
69
99
  def calc_mdf(ar40ar36=None, params: dict = None, smp: Sample = None, index: list = None):
70
- std_air, std_err = smp.TotalParam[93:95]
71
- m36, sm36 = smp.TotalParam[71:73]
72
- m40, sm40 = smp.TotalParam[79:81]
73
- air, sair = smp.ApparentAgeValues[0:2] # ar40ar36 air, error
74
- discrimination_method = smp.TotalParam[100] # L, sL
100
+ params_index_dict = {
101
+ 71: 'M36', 72: 'sM36', 79: 'M40', 80: 'sM40', 93: 'Air', 94: 'rsAir', 100: 'Discr'
102
+ }
103
+ if ar40ar36 is None and smp is not None:
104
+ ar40ar36 = smp.ApparentAgeValues[0:2] # ar40ar36 air, error
105
+ if len(np.shape(ar40ar36)) == 1:
106
+ ar40ar36 = np.reshape(ar40ar36, (2, 1))
107
+ if index is None:
108
+ index = list(range(np.shape(ar40ar36)[-1]))
109
+ if smp is None and params is None:
110
+ raise ValueError(f"Parameters are required for calculating mdf, or it is empty.")
111
+ if params is not None:
112
+ for key, val in params.items():
113
+ if not isinstance(val, list):
114
+ params[key] = list(val)
115
+ if smp is not None:
116
+ try:
117
+ params_from_smp = dict(zip(
118
+ list(params_index_dict.values()),
119
+ [[smp.TotalParam[i][j] for j in index] for i in params_index_dict.keys()]
120
+ ))
121
+ except Exception:
122
+ print(traceback.format_exc())
123
+ raise ValueError(f"Parameters cannot be found in the given sample object")
124
+ if params is not None:
125
+ params_from_smp.update(params)
126
+ params = params_from_smp
127
+
75
128
  mdf = []
76
- for i in range(len(std_air)):
77
- k = calc.corr.mdf(air[i], sair[i], m36[i], m40[i], std_air[i], std_err[i]) # linear, exp, pow
78
- mdf.append({"linear": k[0:2], "exp": k[2:4], "pow": k[4:6]}[discrimination_method[i].lower()])
79
- return np.transpose(mdf).tolist()
129
+ for i in range(len(index)):
130
+ k = calc.corr.mdf(ar40ar36[0][i], ar40ar36[1][i], params['M36'][i], params['M40'][i],
131
+ params['Air'][i], params['rsAir'][i]) # linear, exp, pow
132
+ mdf.append({"linear": k[0:4], "exp": k[4:8], "pow": k[8:12]}[params['Discr'][i].lower()])
133
+
134
+ if len(index) == 1:
135
+ return np.transpose(mdf).squeeze().tolist()
136
+ else:
137
+ return np.transpose(mdf).tolist()
80
138
 
81
139
 
82
140
  def calc_age(ar40ar39=None, params: dict = None, smp: Sample = None, index: list = None):
@@ -477,7 +535,7 @@ def get_diff_smp(backup: (dict, Sample), smp: (dict, Sample)):
477
535
  # =======================
478
536
  # Set parameters
479
537
  # =======================
480
- def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None):
538
+ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None, rows: Optional[List] =None):
481
539
  """
482
540
  Parameters
483
541
  ----------
@@ -485,84 +543,76 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
485
543
  params
486
544
  flag : optional, should be one of 'calc', 'irra', and 'smp'. If it is not given,
487
545
  the text of the extension without a dot will be used
546
+ rows
488
547
 
489
548
  Returns
490
549
  -------
491
550
 
492
551
  """
552
+ if rows is None:
553
+ rows = []
554
+ rows = list(set(rows))
555
+
493
556
  if isinstance(params, str) and os.path.isfile(params):
494
557
  if flag is None:
495
558
  flag = params.split(".")[-1]
496
559
  return set_params(smp, read_params(params), flag=flag)
497
560
 
498
- def remove_none(old_params, new_params, rows, length):
499
- res = [[] for _ in range(length)]
561
+ def isValid(item):
562
+ valid = True
563
+ if isinstance(item, (float, int)):
564
+ valid = not np.isnan(item)
565
+ return valid and item is not None and item != ""
566
+
567
+ def remove_none(old_params, new_params, row_list, length):
568
+ 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))]
500
569
  for index, item in enumerate(new_params):
501
- if item is None:
502
- res[index] = old_params[index]
503
- else:
504
- res[index] = [item] * rows
570
+ if isValid(item):
571
+ for row in row_list:
572
+ res[index][row] = item
505
573
  return res
506
574
 
507
575
  n = len(smp.SequenceName)
508
-
509
576
  if n == 0:
510
- raise ValueError(f"The number of sample sequences is undefined.")
577
+ raise ValueError(f"The number of sample sequences is zero")
511
578
 
512
579
  if flag == 'calc':
513
- smp.TotalParam[34:56] = remove_none(smp.TotalParam[34:56], params[0:22], n, 56 - 34)
514
- smp.TotalParam[71:97] = remove_none(smp.TotalParam[71:97], params[22:48], n, 97 - 71)
580
+ smp.TotalParam[34:56] = remove_none(smp.TotalParam[34:56], params[0:22], rows, n)
581
+ smp.TotalParam[71:97] = remove_none(smp.TotalParam[71:97], params[22:48], rows, n)
515
582
  elif flag == 'irra':
516
- smp.TotalParam[0:20] = remove_none(smp.TotalParam[0:20], params[0:20], n, 20 - 0)
517
- smp.TotalParam[56:58] = remove_none(smp.TotalParam[56:58], params[20:22], n, 57 - 55) # Cl36/38 productivity
518
- smp.TotalParam[20:27] = remove_none(smp.TotalParam[20:27], params[22:29], n, 27 - 20)
519
- # smp.TotalParam[26] = [params[26]] * n
583
+ smp.TotalParam[0:20] = remove_none(smp.TotalParam[0:20], params[0:20], rows, n)
584
+ smp.TotalParam[56:58] = remove_none(smp.TotalParam[56:58], params[20:22], rows, n) # Cl36/38 productivity
585
+ smp.TotalParam[20:27] = remove_none(smp.TotalParam[20:27], params[22:29], rows, n)
520
586
  irradiation_time = []
521
587
  duration = []
522
588
  if None not in params[29:-3] and '' not in params[29:-3]:
523
589
  for i in range(len(params[29:-3])):
524
590
  if i % 2 == 0:
525
- # [d, t] = params[29:-3][i].split('T')
526
- # [t1, t2] = t.split(':')
527
- # irradiation_time.append(d + '-' + t1 + '-' + t2 + 'D' + str(params[29:-3][i + 1]))
528
- text = params[29:-3][i]
529
- for char in ['T', ':']:
530
- text = text.replace(char, '-')
531
591
  irradiation_time.append(params[29:-3][i] + 'D' + str(params[29:-3][i + 1]))
532
592
  duration.append(float(params[29:-3][i + 1]))
533
- smp.TotalParam[27] = ['S'.join(irradiation_time)] * n
534
- smp.TotalParam[28] = [params[-3]] * n
535
- smp.TotalParam[29] = [sum(duration)] * n
593
+ smp.TotalParam[27:30] = remove_none(smp.TotalParam[27:30], ['S'.join(irradiation_time), params[-3], sum(duration)], rows, n)
536
594
  if params[-5] != '':
537
- # [a, b] = params[-5].split('T')
538
- # [b, c] = b.split(':')
539
- # smp.TotalParam[30] = [a + '-' + b + '-' + c] * n
540
- text = params[-5]
541
- for char in ['T', ':']:
542
- text = text.replace(char, '-')
543
- # smp.TotalParam[30] = [text] * n
544
- smp.TotalParam[30] = [params[-5]] * n
595
+ smp.TotalParam[30:32] = remove_none(smp.TotalParam[30:32], [params[-5], None], rows, n)
545
596
  try:
546
597
  stand_time_second = [
547
598
  calc.basic.get_datetime(*re.findall(r"\d+", smp.TotalParam[31][i])) - calc.basic.get_datetime(
548
- *re.findall(r"\d+", smp.TotalParam[30][i])) for i in range(n)]
599
+ *re.findall(r"\d+", smp.TotalParam[30][i])) for i in range(len(smp.TotalParam[30]))]
549
600
  except (BaseException, Exception):
550
601
  print(f'Error in calculate standing duration: {traceback.format_exc()}')
551
- raise
602
+ smp.TotalParam[32] = [None for index in range(n)]
552
603
  else:
553
- smp.TotalParam[32] = [i / (3600 * 24 * 365.242) for i in stand_time_second] # stand year
604
+ smp.TotalParam[32] = [item / (3600 * 24 * 365.242) if index in rows else smp.TotalParam[32][index] for index, item in enumerate(stand_time_second)] # stand year
554
605
 
555
606
  elif flag == 'smp':
556
- print(dict(zip([i for i in range(len(params))], params)))
557
- smp.TotalParam[67:71] = remove_none(smp.TotalParam[67:71], params[0:4], n, 71 - 67)
558
- smp.TotalParam[58:67] = remove_none(smp.TotalParam[58:67], params[4:13], n, 67 - 58)
559
- smp.TotalParam[97:100] = remove_none(smp.TotalParam[97:100], params[13:16], n, 100 - 97)
560
- smp.TotalParam[115:120] = remove_none(smp.TotalParam[115:120], params[16:21], n, 120 - 115)
561
- smp.TotalParam[126:136] = remove_none(smp.TotalParam[126:136], params[21:31], n, 136 - 126)
562
- # smp.TotalParam[120:123] = remove_none(smp.TotalParam[120:123], params[31:34], n, 123 - 120)
607
+ smp.TotalParam[67:71] = remove_none(smp.TotalParam[67:71], params[0:4], rows, n)
608
+ smp.TotalParam[58:67] = remove_none(smp.TotalParam[58:67], params[4:13], rows, n)
609
+ smp.TotalParam[97:100] = remove_none(smp.TotalParam[97:100], params[13:16], rows, n)
610
+ smp.TotalParam[115:120] = remove_none(smp.TotalParam[115:120], params[16:21], rows, n)
611
+ smp.TotalParam[126:136] = remove_none(smp.TotalParam[126:136], params[21:31], rows, n)
612
+ # smp.TotalParam[120:123] = remove_none(smp.TotalParam[120:123], params[31:34], rows, n)
563
613
  smp.TotalParam[100:114] = remove_none(
564
614
  smp.TotalParam[100:114],
565
- [['Linear', 'Exponential', 'Power'][params[35:38].index(True)] if True in params[35:38] else '', *params[38:]], n, 114 - 100)
615
+ [['Linear', 'Exponential', 'Power'][params[35:38].index(True)] if True in params[35:38] else '', *params[38:]], rows, n)
566
616
  pref = dict(zip(preference_keys, params[31:35]))
567
617
  smp.Info.preference.update(pref)
568
618
  for key, comp in get_components(smp).items():
@@ -570,7 +620,6 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
570
620
  comp.decimal_places = pref['decimalPlaces']
571
621
  comp.set_coltypes()
572
622
  smp.AgeSpectraPlot.yaxis.title.text = f"Apparent Age ({str(pref['ageUnit']).capitalize()})"
573
- print(smp.Info.preference)
574
623
 
575
624
  else:
576
625
  raise KeyError(f"{flag = } is not supported. It must be 'calc' for Calc Params, "