ararpy 0.2.3__tar.gz → 0.2.4__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 (82) hide show
  1. {ararpy-0.2.3 → ararpy-0.2.4}/PKG-INFO +1 -1
  2. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/__init__.py +2 -20
  3. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/arr.py +5 -2
  4. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/basic.py +11 -5
  5. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/corr.py +8 -5
  6. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/initial.py +19 -4
  7. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/plots.py +248 -203
  8. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/sample.py +2 -1
  9. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/style.py +10 -4
  10. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/table.py +66 -32
  11. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy.egg-info/PKG-INFO +1 -1
  12. {ararpy-0.2.3 → ararpy-0.2.4}/setup.py +1 -1
  13. {ararpy-0.2.3 → ararpy-0.2.4}/LICENSE +0 -0
  14. {ararpy-0.2.3 → ararpy-0.2.4}/README.md +0 -0
  15. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Check arr.py +0 -0
  16. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Granite Cooling History.py +0 -0
  17. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Plot temperature calibration.py +0 -0
  18. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Show MDD results.py +0 -0
  19. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Show all Kfs age spectra.py +0 -0
  20. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Show random walk results.py +0 -0
  21. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/Example - Tc calculation.py +0 -0
  22. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/__init__.py +0 -0
  23. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/age.py +0 -0
  24. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/basic.py +0 -0
  25. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/corr.py +0 -0
  26. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/err.py +0 -0
  27. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/histogram.py +0 -0
  28. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/isochron.py +0 -0
  29. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/jvalue.py +0 -0
  30. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/plot.py +0 -0
  31. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/raw_funcs.py +0 -0
  32. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/regression.py +0 -0
  33. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/calc/spectra.py +0 -0
  34. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/022_VU124-M11a.ahd +0 -0
  35. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/20WHA0103.age +0 -0
  36. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/22WHA0078.xls +0 -0
  37. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/22WHA0433.age +0 -0
  38. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/22WHA0433.arr +0 -0
  39. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/22WHA0433.full.xls +0 -0
  40. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/24WHN0001-51-592.XLS +0 -0
  41. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/AHD.input-filter +0 -0
  42. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/ArAr.calc +0 -0
  43. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/ArArCALC.age +0 -0
  44. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/NGX-600 - Copy.TXT +0 -0
  45. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/NGX-600.TXT +0 -0
  46. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/NGX-XLS.input-filter +0 -0
  47. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/Qtegra-exported-xls.input-filter +0 -0
  48. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/S01-239.csv +0 -0
  49. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/WH01.irra +0 -0
  50. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/WHA.pdf +0 -0
  51. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/raw_example.xls +0 -0
  52. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/examples/sample-default.smp +0 -0
  53. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/__init__.py +0 -0
  54. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/arr_file.py +0 -0
  55. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/basic.py +0 -0
  56. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/calc_file.py +0 -0
  57. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/new_file.py +0 -0
  58. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/raw_file.py +0 -0
  59. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/files/xls.py +0 -0
  60. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/EXPORT_TO_PDF_DATA_PROPERTIES.py +0 -0
  61. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/__init__.py +0 -0
  62. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/calculation.py +0 -0
  63. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/consts.py +0 -0
  64. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/diffusion_funcs.py +0 -0
  65. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/export.py +0 -0
  66. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/info.py +0 -0
  67. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/json.py +0 -0
  68. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/smp/raw.py +0 -0
  69. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/test.py +0 -0
  70. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/thermo/__init__.py +0 -0
  71. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/thermo/arrhenius.py +0 -0
  72. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/thermo/atomic_level_random_walk.py +0 -0
  73. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy/thermo/basic.py +0 -0
  74. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy.egg-info/SOURCES.txt +0 -0
  75. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy.egg-info/dependency_links.txt +0 -0
  76. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy.egg-info/requires.txt +0 -0
  77. {ararpy-0.2.3 → ararpy-0.2.4}/ararpy.egg-info/top_level.txt +0 -0
  78. {ararpy-0.2.3 → ararpy-0.2.4}/setup.cfg +0 -0
  79. {ararpy-0.2.3 → ararpy-0.2.4}/tests/test.py +0 -0
  80. {ararpy-0.2.3 → ararpy-0.2.4}/tests/test2.py +0 -0
  81. {ararpy-0.2.3 → ararpy-0.2.4}/tests/test_error_correlation.py +0 -0
  82. {ararpy-0.2.3 → ararpy-0.2.4}/tests/test_regression_methods.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ararpy
3
- Version: 0.2.3
3
+ Version: 0.2.4
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.2.3'
19
+ version = '0.2.4'
20
20
  __version__ = version
21
21
  full_version = version
22
- last_update = '2026-01-01'
22
+ last_update = '2026-01-07'
23
23
 
24
24
  """ ArArPy Functions """
25
25
 
@@ -97,24 +97,6 @@ Sample.set_params = smp.basic.set_params
97
97
  Sample.set_info = lambda _smp, info: setattr(_smp, 'Info', smp.basic.update_plot_from_dict(_smp.Info, info))
98
98
 
99
99
  Sample.recalculate = lambda _smp, *args, **kwargs: smp.calculation.recalculate(_smp, *args, **kwargs)
100
- Sample.plot_init = lambda _smp: smp.calculation.recalculate(
101
- _smp, re_plot=True, isIsochron=False, isInit=True, isPlateau=False)
102
- Sample.plot_isochron = lambda _smp, **kwargs: smp.calculation.recalculate(
103
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, **kwargs)
104
- Sample.plot_age_plateau = lambda _smp: smp.calculation.recalculate(
105
- _smp, re_plot=True, isIsochron=False, isInit=False, isPlateau=True)
106
- Sample.plot_normal = lambda _smp: smp.calculation.recalculate(
107
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_2'])
108
- Sample.plot_inverse = lambda _smp: smp.calculation.recalculate(
109
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_3'])
110
- Sample.plot_cl_1 = lambda _smp: smp.calculation.recalculate(
111
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_4'])
112
- Sample.plot_cl_2 = lambda _smp: smp.calculation.recalculate(
113
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_5'])
114
- Sample.plot_cl_3 = lambda _smp: smp.calculation.recalculate(
115
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_6'])
116
- Sample.plot_3D = lambda _smp: smp.calculation.recalculate(
117
- _smp, re_plot=True, isIsochron=True, isInit=False, isPlateau=False, figures=['figure_7'])
118
100
 
119
101
  Sample.to_excel = lambda _smp, file_path, *args, **kwargs: smp.export.to_excel(_smp, file_path=file_path, *args, **kwargs)
120
102
 
@@ -311,7 +311,10 @@ def multi_append(a, *args):
311
311
 
312
312
  """
313
313
  for arg in args:
314
- a.append(arg)
314
+ if isinstance(a, list):
315
+ a.append(arg)
316
+ if isinstance(a, np.ndarray):
317
+ a = np.append(a, arg)
315
318
  return a
316
319
 
317
320
 
@@ -351,7 +354,7 @@ def create_arr(shape: tuple):
351
354
 
352
355
  """
353
356
  if len(shape) == 1:
354
- return []
357
+ return [0 for i in range(shape[0])]
355
358
  return [create_arr(shape[1:]) for i in range(shape[0])]
356
359
 
357
360
 
@@ -35,15 +35,16 @@ pd.options.mode.chained_assignment = None # default='warn'
35
35
  # =======================
36
36
  class ParamsInvalid(Exception):
37
37
  """ """
38
- def __init__(self, code, message, context=None):
38
+ def __init__(self, code=400, message="", context=None, fatal=True):
39
39
  self.code = code
40
40
  self.message = message
41
41
  self.context = context or {}
42
+ self.fatal = fatal
42
43
  # 调用父类构造函数,确保异常能正常抛出
43
44
  super().__init__(f"{self.message}")
44
45
 
45
46
 
46
- def validate_params(**kwargs):
47
+ def validate_params(fatal=True, **kwargs):
47
48
 
48
49
  def check(data, dtype, **kwargs):
49
50
  k = np.array(data, dtype=dtype)
@@ -65,7 +66,7 @@ def validate_params(**kwargs):
65
66
  if not kwargs.get('func')(each):
66
67
  raise ValueError
67
68
  except (Exception, BaseException) as e:
68
- raise ValueError(f"{type(e).__name__}: invalid value, {each}")
69
+ raise ValueError(f"invalid value, {each}")
69
70
 
70
71
  context = {'names': [], 'classnames': [], 'messages': []}
71
72
  for index, (name, content) in enumerate(kwargs.items(), 1):
@@ -83,7 +84,7 @@ def validate_params(**kwargs):
83
84
  if not context['names']:
84
85
  return True
85
86
  else:
86
- raise ParamsInvalid(400, '. '.join(context['messages']), context)
87
+ raise ParamsInvalid(400, '. '.join(context['messages']), context, fatal=fatal)
87
88
 
88
89
 
89
90
  # =======================
@@ -268,7 +269,7 @@ def calc_age(ar40ar39=None, params: dict = None, smp: Sample = None, index: list
268
269
  age_unit_factor = 1
269
270
 
270
271
  # check if using Min equation
271
- params['Min'] = [i if isinstance(i, bool) else False for i in params['Min']]
272
+ params['Min'] = [bool(i) for i in params['Min']]
272
273
 
273
274
  idx1 = np.flatnonzero(np.where(params['Min'], True, False)) # True, using Min equation
274
275
  idx2 = np.flatnonzero(np.where(params['Min'], False, True)) # False
@@ -668,6 +669,10 @@ def set_params(smp: Sample, params: Union[List, str], flag: Optional[str] = None
668
669
  else:
669
670
  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
670
671
 
672
+ smp.Info.irradiation.label = params[-3]
673
+ smp.Info.irradiation.location = params[-2]
674
+ smp.Info.irradiation.info = params[-1]
675
+
671
676
  elif flag == 'smp':
672
677
  smp.TotalParam[67:71] = remove_none(smp.TotalParam[67:71], params[0:4], rows, n)
673
678
  smp.TotalParam[58:67] = remove_none(smp.TotalParam[58:67], params[4:13], rows, n)
@@ -702,6 +707,7 @@ def get_sequence(smp: Sample):
702
707
  smp.Info.results.selection[0]['data'] = smp.SelectedSequence1
703
708
  smp.Info.results.selection[1]['data'] = smp.SelectedSequence2
704
709
  smp.Info.results.selection[2]['data'] = smp.UnselectedSequence
710
+ smp.Info.experiment.step_num = len(smp.SequenceName)
705
711
  return ArArBasic(
706
712
  size=len(smp.SequenceName), name=smp.SequenceName, value=smp.SequenceValue, unit=smp.SequenceUnit,
707
713
  mark=ArArBasic(
@@ -153,10 +153,13 @@ def corr_decay(sample: Sample):
153
153
  corrDecay37 = sample.TotalParam[104]
154
154
  corrDecay39 = sample.TotalParam[105]
155
155
  sample.CorrectedValues = copy.deepcopy(sample.MassDiscrCorrected)
156
- sample.CorrectedValues[2] = [val if corrDecay37[idx] else 0 for idx, val in enumerate(decay_corrected[2])]
157
- sample.CorrectedValues[3] = [val if corrDecay37[idx] else 0 for idx, val in enumerate(decay_corrected[3])]
158
- sample.CorrectedValues[6] = [val if corrDecay39[idx] else 0 for idx, val in enumerate(decay_corrected[6])]
159
- sample.CorrectedValues[7] = [val if corrDecay39[idx] else 0 for idx, val in enumerate(decay_corrected[7])]
156
+ for idx in range(sample.Info.experiment.step_num):
157
+ if corrDecay37[idx]:
158
+ sample.CorrectedValues[2][idx] = decay_corrected[2][idx]
159
+ sample.CorrectedValues[3][idx] = decay_corrected[3][idx]
160
+ if corrDecay39[idx]:
161
+ sample.CorrectedValues[6][idx] = decay_corrected[6][idx]
162
+ sample.CorrectedValues[7][idx] = decay_corrected[7][idx]
160
163
 
161
164
  data = np.array(sample.CorrectedValues)
162
165
  data[1:10:2] = data[1:10:2] = np.abs(np.divide(data[1:10:2], data[0:10:2])) * 100
@@ -769,7 +772,7 @@ def monte_carlo_f(sample: Sample):
769
772
  blank_gain_corr=sample.TotalParam[111][i],
770
773
  MDF_method=sample.TotalParam[100][i],
771
774
  force_to_zero=sample.TotalParam[101][i],
772
- monte_carlo_size=1000,
775
+ monte_carlo_size=4000,
773
776
  )
774
777
 
775
778
  yield res
@@ -191,7 +191,7 @@ def initial(smp: Sample):
191
191
  ),
192
192
  preference=ArArBasic(**PREFERENCE_RES),
193
193
  irradiation= ArArBasic(
194
- label='', pos_h='', pos_x='', pos_y='',
194
+ label='', pos_h='', pos_x='', pos_y='', location='', info=''
195
195
  )
196
196
  ))
197
197
 
@@ -234,7 +234,7 @@ def initial(smp: Sample):
234
234
  ))
235
235
  setattr(smp, 'TotalParamsTable', Table(
236
236
  id='8', name='Total Params', header=samples.TOTAL_PARAMS_HEADERS, decimal_places=decimal_places,
237
- text_indexes=[0, 1, 2, 30, 31, 33, 34, 61, 100, 103, *list(range(104, 118))],
237
+ text_indexes=[0, 1, 2, 29, 30, 31, 33, 34, 61, 100, 103, 118],
238
238
  # numeric_indexes=list(range(1, 120)),
239
239
  ))
240
240
 
@@ -359,10 +359,25 @@ def check_version(smp: Sample):
359
359
  smp.TotalParam[32] = [np.nan for index in range(smp.Info.experiment.step_num)]
360
360
  else:
361
361
  smp.TotalParam[32] = [item / (3600 * 24 * 365.242) for item in stand_time_second] # stand year
362
- smp = smp.recalculate(re_table_style=True)
363
- smp = smp.recalculate(re_set_table=True)
364
362
  smp.version = "20251001"
365
363
 
364
+ # 20251231 change publish table
365
+ if version < 20251231:
366
+ smp.PublishValues = arr.create_arr((len(samples.PUBLISH_TABLE_HEADERS) - 3, smp.Info.experiment.step_num))
367
+ try:
368
+ data = np.array(smp.CorrectedValues)
369
+ data[1:10:2] = np.abs(np.divide(data[1:10:2], data[0:10:2])) * 100
370
+ smp.PublishValues[0:10] = copy.deepcopy(data.tolist())
371
+ smp.PublishValues[10:14] = copy.deepcopy(smp.ApparentAgeValues[0:4])
372
+ smp.PublishValues[14:16] = copy.deepcopy(smp.ApparentAgeValues[6:8])
373
+ except (BaseException, Exception) as e:
374
+ print(f"{type(e).__name__}: {str(e)}")
375
+ pass
376
+ else:
377
+ smp = smp.recalculate(re_table_style=True)
378
+ smp = smp.recalculate(re_set_table=True)
379
+ smp.version = "20251231"
380
+
366
381
  return smp
367
382
 
368
383
 
@@ -36,182 +36,176 @@ ISOCHRON_INDEX_DICT = {
36
36
  }
37
37
 
38
38
 
39
- # =======================
40
- # Reset plot data
41
- # =======================
42
- def set_plot_data(sample: Sample, isInit: bool = True, isIsochron: bool = True,
43
- isPlateau: bool = True, **kwargs):
39
+ def set_plot_data(sample: Sample, isInit: bool = True, **kwargs):
44
40
  """
45
41
  Parameters
46
42
  ----------
47
43
  sample
48
- isInit
49
- isIsochron
50
- isPlateau
51
44
  kwargs
52
45
 
53
46
  Returns
54
47
  -------
55
48
 
56
49
  """
57
- # print(f"isInit: {isInit}, isIsochron: {isIsochron}, isPlateau: {isPlateau}")
58
-
59
- # Initialization, apply age spectra data and isochron plot data
60
- if isInit:
61
- initial_plot_data(sample)
62
- # try:
63
- # initial_plot_data(sample)
64
- # except (Exception, BaseException):
65
- # print("initial_plot_data(sample) error:\n", traceback.format_exc())
66
- # pass
67
-
68
- # Recalculate isochron lines
69
- if isIsochron:
70
- recalc_isochrons(sample, **kwargs)
71
- reset_isochron_line_data(sample)
72
- # try:
73
- # recalc_isochrons(sample, **kwargs)
74
- # except (Exception, BaseException):
75
- # print("recalc_isochrons(sample, **kwargs) error:\n", traceback.format_exc())
76
- # pass
77
- # try:
78
- # reset_isochron_line_data(sample)
79
- # except (Exception, BaseException):
80
- # print("reset_isochron_line_data(sample):\n", traceback.format_exc())
81
- # pass
82
-
83
- # Recalculate plateaus
84
- if isPlateau:
85
- recalc_plateaus(sample)
86
- # try:
87
- # recalc_plateaus(sample)
88
- # except (Exception, BaseException):
89
- # print("recalc_plateaus(sample) error:\n", traceback.format_exc())
90
- # pass
91
-
92
-
93
- # =======================
94
- # Initialize plot data
95
- # =======================
96
- def initial_plot_data(smp: Sample):
50
+ all_figures = ['figure_2', 'figure_3', 'figure_4', 'figure_5', 'figure_6', 'figure_7', 'figure_8', 'figure_9', 'figure_1', ]
51
+ figures = kwargs.get('figures', all_figures)
52
+ for idx, fig_id in enumerate(all_figures):
53
+ if fig_id not in figures:
54
+ continue
55
+ if fig_id == 'figure_1':
56
+ if isInit:
57
+ init_age_spec_plot(sample)
58
+ recalc_plateaus(sample)
59
+ if fig_id == 'figure_2':
60
+ plot_normal_iso(sample, isInit=isInit)
61
+ if fig_id == 'figure_3':
62
+ plot_inverse_iso(sample, isInit=isInit)
63
+ if fig_id == 'figure_4':
64
+ plot_cl1_iso(sample, isInit=isInit)
65
+ if fig_id == 'figure_5':
66
+ plot_cl2_iso(sample, isInit=isInit)
67
+ if fig_id == 'figure_6':
68
+ plot_cl3_iso(sample, isInit=isInit)
69
+ if fig_id == 'figure_7':
70
+ plot_3D_iso(sample, isInit=isInit)
71
+ if fig_id == 'figure_8':
72
+ recalc_degassing_plot(sample)
73
+ if fig_id == 'figure_9':
74
+ recalc_agedistribution(sample)
75
+
76
+
77
+ # Isochrons
78
+ def get_iso_res(sample: Sample, figure: Plot):
97
79
  """
98
- Assign initial data for plots
80
+
99
81
  Parameters
100
82
  ----------
101
- smp : Sample instance
83
+ sample
84
+ kwargs
102
85
 
103
86
  Returns
104
87
  -------
105
- None
106
- """
107
- try:
108
- params_to_check = {
109
- 'normal': {'data': smp.IsochronValues[0:5], 'dtype': float, 'class': 'k1', },
110
- 'inverse': {'data': smp.IsochronValues[6:11], 'dtype': float, 'class': 'k2', },
111
- 'K-Cl-Ar 1': {'data': smp.IsochronValues[12:17], 'dtype': float, 'class': 'k3', },
112
- 'K-Cl-Ar 2': {'data': smp.IsochronValues[18:23], 'dtype': float, 'class': 'k4', },
113
- 'K-Cl-Ar 3': {'data': smp.IsochronValues[24:29], 'dtype': float, 'class': 'k5', },
114
- '3D': {'data': smp.IsochronValues[30:39], 'dtype': float, 'class': 'k6', },
115
- 'age spectra': [
116
- {'data': smp.ApparentAgeValues[2:4], 'dtype': float, 'class': 'k7', },
117
- {'data': smp.ApparentAgeValues[7], 'dtype': float, 'class': 'k7', },
118
- ],
119
- 'degas pattern': {'data': smp.IsochronValues[30:39], 'dtype': float, 'class': 'k8', },
120
- 'age distribution': {'data': smp.IsochronValues[30:39], 'dtype': float, 'class': 'k9', },
121
- }
122
- except (IndexError, AttributeError) as e:
123
- raise
124
- if not basic.validate_params(**params_to_check):
125
- return
126
88
 
127
- # Isochron plots
128
- for key, val in ISOCHRON_INDEX_DICT.items():
129
- figure = basic.get_component_byid(smp, key)
130
- figure.data = [
131
- *smp.IsochronValues[val['data_index'][0]:val['data_index'][1]],
132
- list(range(smp.Info.experiment.step_num))
133
- ]
134
- # Ellipse
135
- if key != 'figure_7':
136
- ellipse_data = []
137
- for point in calc.arr.transpose(figure.data[:5]):
138
- if '' not in point and None not in point:
139
- ellipse_data.append(calc.isochron.get_ellipse(*point))
140
- getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
141
-
142
- # Age spectra plot
143
- # Try to calculate total gas age
144
- try:
145
- if str(smp.Info.sample.type).lower() == "unknown":
146
- a0, e0 = sum(smp.DegasValues[24]), pow(sum([i ** 2 for i in smp.DegasValues[25]]), 0.5)
147
- a1, e1 = sum(smp.DegasValues[20]), pow(sum([i ** 2 for i in smp.DegasValues[21]]), 0.5)
148
- handle = basic.calc_age
149
- elif str(smp.Info.sample.type).lower() == "standard":
150
- a0, e0 = sum(smp.DegasValues[24]), pow(sum([i ** 2 for i in smp.DegasValues[25]]), 0.5)
151
- a1, e1 = sum(smp.DegasValues[20]), pow(sum([i ** 2 for i in smp.DegasValues[21]]), 0.5)
152
- handle = basic.calc_j
153
- elif str(smp.Info.sample.type).lower() == "air":
154
- a0, e0 = sum(smp.DegasValues[26]), pow(sum([i ** 2 for i in smp.DegasValues[27]]), 0.5)
155
- a1, e1 = sum(smp.DegasValues[ 0]), pow(sum([i ** 2 for i in smp.DegasValues[ 1]]), 0.5)
156
- handle = basic.calc_mdf
89
+ """
90
+ figure.set3.data, figure.set1.data, figure.set2.data = \
91
+ sample.UnselectedSequence.copy(), sample.SelectedSequence1.copy(), sample.SelectedSequence2.copy()
92
+ for index, sequence in enumerate([figure.set1.data, figure.set2.data, figure.set3.data]):
93
+ set_data = calc.arr.partial(
94
+ sample.IsochronValues, rows=sequence, cols=list(range(*ISOCHRON_INDEX_DICT[figure.id]['data_index'])))
95
+ if figure.id != 'figure_7':
96
+ iso_res = get_isochron_results(
97
+ set_data, figure_type=ISOCHRON_INDEX_DICT[figure.id]["figure_type"], smp=sample, sequence=sequence)
98
+ sample.Info.results.isochron[figure.id].update({index: iso_res})
157
99
  else:
158
- raise TypeError(f"Sample type is not supported: {smp.Info.sample.type}")
159
- total_f = [a0 / a1, calc.err.div((a0, e0), (a1, e1))]
160
- total_age = handle(total_f[:2], smp=smp)
161
- except (Exception, BaseException):
162
- print(traceback.format_exc())
163
- total_f = [np.nan] * 2
164
- total_age = [np.nan] * 4
165
- smp.Info.results.age_spectra['TGA'].update(
166
- {'Ar39': 100, 'F': total_f[0], 'sF': total_f[1], 'age': total_age[0],
167
- 's1': total_age[1], 's2': total_age[2], 's3': total_age[3], 'Num': len(smp.DegasValues[24])}
168
- )
169
- try:
170
- smp.AgeSpectraPlot.data = calc.spectra.get_data(*smp.ApparentAgeValues[2:4], smp.ApparentAgeValues[7])
171
- smp.AgeSpectraPlot.data = calc.arr.transpose(smp.AgeSpectraPlot.data)
172
- except (Exception, BaseException):
173
- print(traceback.format_exc())
174
- smp.AgeSpectraPlot.data = []
100
+ iso_res = get_3D_results(data=set_data, sequence=sequence, sample=sample)
101
+ sample.Info.results.isochron[figure.id].update({index: iso_res})
175
102
 
176
- # Degassing plot
177
- recalc_degassing_plot(smp)
178
103
 
179
- # Age distribution plot
180
- recalc_agedistribution(smp)
181
-
182
-
183
- # =======================
184
- # Isochron results
185
- # =======================
186
- def recalc_isochrons(sample: Sample, **kwargs):
104
+ def set_iso_line_data(sample: Sample, figure: Plot):
187
105
  """
188
-
106
+ Set isochron regression lines
189
107
  Parameters
190
108
  ----------
191
- sample
192
- kwargs
109
+ sample : sample instance
193
110
 
194
111
  Returns
195
112
  -------
196
-
113
+ None, set regression lines data to sample instance.
197
114
  """
198
- figures = kwargs.pop('figures', ['figure_2', 'figure_3', 'figure_4', 'figure_5', 'figure_6', 'figure_7', ])
199
- for key, val in ISOCHRON_INDEX_DICT.items():
200
- if key not in figures:
201
- continue
202
- figure = basic.get_component_byid(sample, key)
203
- figure.set3.data, figure.set1.data, figure.set2.data = \
204
- sample.UnselectedSequence.copy(), sample.SelectedSequence1.copy(), sample.SelectedSequence2.copy()
205
- for index, sequence in enumerate([figure.set1.data, figure.set2.data, figure.set3.data]):
206
- set_data = calc.arr.partial(
207
- sample.IsochronValues, rows=sequence, cols=list(range(*val['data_index'])))
208
- if key != 'figure_7':
209
- iso_res = get_isochron_results(
210
- set_data, figure_type=val["figure_type"], smp=sample, sequence=sequence)
211
- sample.Info.results.isochron[figure.id].update({index: iso_res})
212
- else:
213
- iso_res = get_3D_results(data=set_data, sequence=sequence, sample=sample)
214
- sample.Info.results.isochron[figure.id].update({index: iso_res})
115
+ for index in [0, 1]:
116
+ xscale, yscale = [figure.xaxis.min, figure.xaxis.max], [figure.yaxis.min, figure.yaxis.max]
117
+ coeffs = [sample.Info.results.isochron[figure.id][index]['k'], sample.Info.results.isochron[figure.id][index]['m1']]
118
+ line_point = calc.isochron.get_line_points(xscale, yscale, coeffs)
119
+ setattr(getattr(figure, ['line1', 'line2'][index]), 'data', line_point)
120
+ setattr(getattr(figure, ['text1', 'text2'][index]), 'text', "") # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
121
+
122
+
123
+ def get_iso_init(sample: Sample, figure: Plot):
124
+ # data
125
+ val = ISOCHRON_INDEX_DICT.get(figure.id)['data_index']
126
+ data = [*sample.IsochronValues[val[0]:val[1]], list(range(sample.Info.experiment.step_num))]
127
+ # ellipse
128
+ ellipse_data = []
129
+ if figure.id != 'figure_7':
130
+ for point in calc.arr.transpose(data[:5]):
131
+ if '' not in point and None not in point:
132
+ ellipse_data.append(calc.isochron.get_ellipse(*point))
133
+ return data, ellipse_data
134
+
135
+
136
+ def plot_normal_iso(sample: Sample, isInit: bool = False):
137
+ figure = sample.NorIsochronPlot
138
+ # data
139
+ if isInit:
140
+ data, ellipse_data = get_iso_init(sample, figure)
141
+ figure.data = data
142
+ getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
143
+ # iso res
144
+ get_iso_res(sample, figure)
145
+ # line data
146
+ set_iso_line_data(sample, figure)
147
+
148
+
149
+ def plot_inverse_iso(sample: Sample, isInit: bool = False):
150
+ figure = sample.InvIsochronPlot
151
+ # data
152
+ if isInit:
153
+ data, ellipse_data = get_iso_init(sample, figure)
154
+ figure.data = data
155
+ getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
156
+ # iso res
157
+ get_iso_res(sample, figure)
158
+ # line data
159
+ set_iso_line_data(sample, figure)
160
+
161
+
162
+ def plot_cl1_iso(sample: Sample, isInit: bool = False):
163
+ figure = sample.KClAr1IsochronPlot
164
+ # data
165
+ if isInit:
166
+ data, ellipse_data = get_iso_init(sample, figure)
167
+ figure.data = data
168
+ getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
169
+ # iso res
170
+ get_iso_res(sample, figure)
171
+ # line data
172
+ set_iso_line_data(sample, figure)
173
+
174
+
175
+ def plot_cl2_iso(sample: Sample, isInit: bool = False):
176
+ figure = sample.KClAr2IsochronPlot
177
+ # data
178
+ if isInit:
179
+ data, ellipse_data = get_iso_init(sample, figure)
180
+ figure.data = data
181
+ getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
182
+ # iso res
183
+ get_iso_res(sample, figure)
184
+ # line data
185
+ set_iso_line_data(sample, figure)
186
+
187
+
188
+ def plot_cl3_iso(sample: Sample, isInit: bool = False):
189
+ figure = sample.KClAr3IsochronPlot
190
+ # data
191
+ if isInit:
192
+ data, ellipse_data = get_iso_init(sample, figure)
193
+ figure.data = data
194
+ getattr(figure, 'ellipse', Set(id='ellipse')).data = ellipse_data
195
+ # iso res
196
+ get_iso_res(sample, figure)
197
+ # line data
198
+ set_iso_line_data(sample, figure)
199
+
200
+
201
+ def plot_3D_iso(sample: Sample, isInit: bool = False):
202
+ figure = sample.ThreeDIsochronPlot
203
+ # data
204
+ if isInit:
205
+ data, ellipse_data = get_iso_init(sample, figure)
206
+ figure.data = data
207
+ # iso res
208
+ get_iso_res(sample, figure)
215
209
 
216
210
 
217
211
  def get_isochron_results(data: list, smp: Sample, sequence, figure_type: int = 0):
@@ -331,33 +325,55 @@ def get_3D_results(data: list, sequence: list, sample: Sample):
331
325
  return iso_res
332
326
 
333
327
 
334
- def reset_isochron_line_data(smp: Sample):
335
- """
336
- Set isochron regression lines
337
- Parameters
338
- ----------
339
- smp : sample instance
328
+ # Spectra
329
+ def init_age_spec_plot(sample: Sample):
340
330
 
341
- Returns
342
- -------
343
- None, set regression lines data to sample instance.
344
- """
345
- for k, v in basic.get_components(smp).items():
346
- if not isinstance(v, Plot):
347
- continue
348
- if k not in ['figure_2', 'figure_3', 'figure_4', 'figure_5', 'figure_6', ]:
349
- continue
350
- for index in [0, 1]:
351
- xscale, yscale = [v.xaxis.min, v.xaxis.max], [v.yaxis.min, v.yaxis.max]
352
- coeffs = [smp.Info.results.isochron[k][index]['k'], smp.Info.results.isochron[k][index]['m1']]
353
- line_point = calc.isochron.get_line_points(xscale, yscale, coeffs)
354
- setattr(getattr(v, ['line1', 'line2'][index]), 'data', line_point)
355
- setattr(getattr(v, ['text1', 'text2'][index]), 'text', "") # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
331
+ figure = sample.AgeSpectraPlot
332
+
333
+ try:
334
+ params_to_check = {
335
+ '40Arr/39ArK': {'data': sample.ApparentAgeValues[2:4], 'dtype': float, 'func': lambda x: np.isfinite(x), 'class': 'k1', },
336
+ '39ArK%': {'data': sample.ApparentAgeValues[7], 'dtype': float, 'func': lambda x: np.isfinite(x), 'class': 'k1', },
337
+ }
338
+ except (IndexError, AttributeError) as e:
339
+ raise
340
+ if not basic.validate_params(fatal=False, **params_to_check):
341
+ return
342
+
343
+ try:
344
+ if str(sample.Info.sample.type).lower() == "unknown":
345
+ a0, e0 = sum(sample.DegasValues[24]), pow(sum([i ** 2 for i in sample.DegasValues[25]]), 0.5)
346
+ a1, e1 = sum(sample.DegasValues[20]), pow(sum([i ** 2 for i in sample.DegasValues[21]]), 0.5)
347
+ handler = basic.calc_age
348
+ elif str(sample.Info.sample.type).lower() == "standard":
349
+ a0, e0 = sum(sample.DegasValues[24]), pow(sum([i ** 2 for i in sample.DegasValues[25]]), 0.5)
350
+ a1, e1 = sum(sample.DegasValues[20]), pow(sum([i ** 2 for i in sample.DegasValues[21]]), 0.5)
351
+ handler = basic.calc_j
352
+ elif str(sample.Info.sample.type).lower() == "air":
353
+ a0, e0 = sum(sample.DegasValues[26]), pow(sum([i ** 2 for i in sample.DegasValues[27]]), 0.5)
354
+ a1, e1 = sum(sample.DegasValues[ 0]), pow(sum([i ** 2 for i in sample.DegasValues[ 1]]), 0.5)
355
+ handler = basic.calc_mdf
356
+ else:
357
+ msg = f"Sample type is not supported: {sample.Info.sample.type}"
358
+ context = {'names': [figure.name], 'classnames': [f'k7'], 'messages': [msg]}
359
+ raise basic.ParamsInvalid(400, msg, context=context, fatal=False)
360
+
361
+ total_f = [a0 / a1, calc.err.div((a0, e0), (a1, e1))]
362
+ total_age = handler(total_f[:2], smp=sample)
363
+ except (Exception, BaseException) as e:
364
+ total_f = [np.nan] * 2
365
+ total_age = [np.nan] * 4
366
+
367
+ sample.Info.results.age_spectra['TGA'].update(
368
+ {'Ar39': 100, 'F': total_f[0], 'sF': total_f[1], 'age': total_age[0],
369
+ 's1': total_age[1], 's2': total_age[2], 's3': total_age[3], 'Num': len(sample.DegasValues[24])}
370
+ )
371
+
372
+ figure.data = calc.arr.transpose(
373
+ calc.spectra.get_data(*sample.ApparentAgeValues[2:4], sample.ApparentAgeValues[7])
374
+ )
356
375
 
357
376
 
358
- # =======================
359
- # Age spectra results
360
- # =======================
361
377
  def recalc_plateaus(sample: Sample, **kwargs):
362
378
  if sample.Info.sample.type == "Unknown":
363
379
  return recalc_age_plateaus(sample, **kwargs)
@@ -379,6 +395,19 @@ def recalc_age_plateaus(sample: Sample, **kwargs):
379
395
  -------
380
396
  None
381
397
  """
398
+
399
+ try:
400
+ params_to_check = {
401
+ '39ArK': {'data': sample.DegasValues[20:22], 'dtype': float, 'func': lambda x: np.isfinite(x), 'class': 'k1', },
402
+ '40Arr': {'data': sample.DegasValues[24:26], 'dtype': float, 'func': lambda x: np.isfinite(x), 'class': 'k1', },
403
+ 'J Factor': {'data': sample.TotalParam[136], 'dtype': float, 'func': lambda x: np.isfinite(x) and x > 0, 'class': 'k1', },
404
+ 'J Factor': {'data': sample.TotalParam[137], 'dtype': float, 'func': lambda x: np.isfinite(x), 'class': 'k1', },
405
+ }
406
+ except (IndexError, AttributeError) as e:
407
+ raise
408
+ if not basic.validate_params(fatal=False, **params_to_check):
409
+ return
410
+
382
411
  ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.TotalParam[136:138])
383
412
  ar40r, sar40r = sample.DegasValues[24:26]
384
413
  ar40rar39k = calc.arr.div([ar40r, sar40r], [ar39k, sar39k])
@@ -561,6 +590,30 @@ def recalc_mdf_plateaus(sample: Sample, **kwargs):
561
590
  sample.AgeSpectraPlot.text2.text = ""
562
591
 
563
592
 
593
+ def recalc_j_plateaus(sample: Sample, **kwargs):
594
+
595
+ ar40rar39k = sample.ApparentAgeValues[0:2]
596
+ j = sample.ApparentAgeValues[2:4]
597
+
598
+ try:
599
+ set1_res, _, set1_data = get_plateau_results(sample, sample.SelectedSequence1, ar40rar39k=ar40rar39k)
600
+ except ValueError:
601
+ pass
602
+ else:
603
+ sample.Info.results.age_plateau.update({0: set1_res})
604
+ sample.AgeSpectraPlot.set1.data = calc.arr.transpose(set1_data)
605
+ sample.AgeSpectraPlot.text1.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
606
+
607
+ try:
608
+ set2_res, _, set2_data = get_plateau_results(sample, sample.SelectedSequence2, ar40rar39k=ar40rar39k)
609
+ except ValueError:
610
+ pass
611
+ else:
612
+ sample.Info.results.age_plateau.update({1: set2_res})
613
+ sample.AgeSpectraPlot.set2.data = calc.arr.transpose(set2_data)
614
+ sample.AgeSpectraPlot.text2.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
615
+
616
+
564
617
  def calc_ar40ar39(r, sr, smp):
565
618
  """
566
619
  Calculate Ar40r / Ar39K based on passed initial ratio.
@@ -693,33 +746,7 @@ def get_wma_results(sample: Sample, sequence: list, ar40rar39k: list = None, ar3
693
746
  return spectra_res
694
747
 
695
748
 
696
- def recalc_j_plateaus(sample: Sample, **kwargs):
697
-
698
- ar40rar39k = sample.ApparentAgeValues[0:2]
699
- j = sample.ApparentAgeValues[2:4]
700
-
701
- try:
702
- set1_res, _, set1_data = get_plateau_results(sample, sample.SelectedSequence1, ar40rar39k=ar40rar39k)
703
- except ValueError:
704
- pass
705
- else:
706
- sample.Info.results.age_plateau.update({0: set1_res})
707
- sample.AgeSpectraPlot.set1.data = calc.arr.transpose(set1_data)
708
- sample.AgeSpectraPlot.text1.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
709
-
710
- try:
711
- set2_res, _, set2_data = get_plateau_results(sample, sample.SelectedSequence2, ar40rar39k=ar40rar39k)
712
- except ValueError:
713
- pass
714
- else:
715
- sample.Info.results.age_plateau.update({1: set2_res})
716
- sample.AgeSpectraPlot.set2.data = calc.arr.transpose(set2_data)
717
- sample.AgeSpectraPlot.text2.text = "" # 注意和js的配合,js那边根据text是否为空判断是否重新生成文字
718
-
719
-
720
- # =======================
721
749
  # Age Distribution Plot
722
- # =======================
723
750
  def recalc_agedistribution(smp: Sample, **kwargs):
724
751
  try:
725
752
  ages = smp.ApparentAgeValues[2]
@@ -769,14 +796,32 @@ def recalc_agedistribution(smp: Sample, **kwargs):
769
796
  plot.set2.data = [[], []]
770
797
 
771
798
 
772
- # =======================
773
799
  # Age Distribution Plot
774
- # =======================
775
800
  def recalc_degassing_plot(smp: Sample, **kwargs):
801
+ figure = smp.DegasPatternPlot
802
+
803
+ try:
804
+ params_to_check = {
805
+ 'degas pattern': [
806
+ {'data': smp.DegasValues[0], 'dtype': float, 'class': 'k8', },
807
+ {'data': smp.DegasValues[8], 'dtype': float, 'class': 'k8', },
808
+ {'data': smp.DegasValues[10], 'dtype': float, 'class': 'k8', },
809
+ {'data': smp.DegasValues[20], 'dtype': float, 'class': 'k8', },
810
+ {'data': smp.DegasValues[24], 'dtype': float, 'class': 'k8', },
811
+ {'data': smp.CorrectedValues[0:10:2], 'dtype': float, 'class': 'k8', },
812
+ ],
813
+ }
814
+ except (IndexError, AttributeError) as e:
815
+ context = {'names': [figure.name], 'classnames': [f'k8'], 'messages': [f"{figure.name}: {str(e)}"]}
816
+ raise basic.ParamsInvalid(400, f"{figure.name}: {str(e)}", context=context, fatal=False)
817
+
818
+ if not basic.validate_params(fatal=False, **params_to_check):
819
+ return
820
+
776
821
  if not hasattr(smp, 'DegasPatternPlot'):
777
822
  setattr(smp, 'DegasPatternPlot', Plot(id='figure_8', name='Degas Pattern Plot'))
778
823
  isotope_percentage = lambda l: [e / sum(l) * 100 if sum(l) != 0 else 0 for e in l]
779
- smp.DegasPatternPlot.data = [
824
+ figure.data = [
780
825
  isotope_percentage(smp.DegasValues[0]), # Ar36a
781
826
  isotope_percentage(smp.DegasValues[8]), # Ar37Ca
782
827
  isotope_percentage(smp.DegasValues[10]), # Ar38Cl
@@ -788,4 +833,4 @@ def recalc_degassing_plot(smp: Sample, **kwargs):
788
833
  isotope_percentage(smp.CorrectedValues[6]), # Ar39
789
834
  isotope_percentage(smp.CorrectedValues[8]), # Ar40
790
835
  ]
791
- smp.DegasPatternPlot.info = [True] * 10
836
+ figure.info = [True] * 10
@@ -855,7 +855,8 @@ class Sample:
855
855
  # self.__version = '20250328' # Experiment info
856
856
  # self.__version = '20250404' # J normalization factor
857
857
  # self.__version = '20251001' # add marker col for all tables
858
- self.__version = '20251231' # move montecarlo to params-112
858
+ # self.__version = '20251231' # move montecarlo to params-112
859
+ self.__version = '20260101' #
859
860
 
860
861
  self.Doi = ""
861
862
  self.RawData = RawData()
@@ -60,8 +60,6 @@ def set_plot_style(smp: Sample):
60
60
  initial.initial_plot_styles(smp, except_attrs=['data'])
61
61
  # Auto scale
62
62
  reset_plot_scale(smp)
63
- # Reset isochron data
64
- plots.reset_isochron_line_data(smp)
65
63
  # Auto position and contents of texts
66
64
  reset_text(smp)
67
65
  # Set title, which are deleted in initializing
@@ -69,8 +67,16 @@ def set_plot_style(smp: Sample):
69
67
  smp_name = smp.Info.sample.name
70
68
  name = f"{exp_name} {smp_name}" if str(exp_name).lower().strip() != str(smp_name).lower().strip() else exp_name
71
69
  suffix = f"{name} {smp.Info.sample.material}"
70
+
72
71
  for figure_id, figure in basic.get_components(smp).items():
72
+ if not isinstance(figure, Plot):
73
+ continue
74
+
73
75
  if isinstance(figure, Plot):
76
+ # Reset isochron line
77
+ if figure_id in ['figure_2', 'figure_3', 'figure_4', 'figure_5', 'figure_6', ]:
78
+ plots.set_iso_line_data(smp, figure)
79
+ # name and title
74
80
  if not hasattr(figure, 'title'):
75
81
  setattr(figure, 'title', Plot.Text())
76
82
  setattr(getattr(figure, 'title'), 'text', f"{suffix} {getattr(figure, 'name', '')}")
@@ -111,8 +117,8 @@ def reset_plot_scale(smp: Sample, only_figure: str = None):
111
117
  if k == 'figure_1':
112
118
  try:
113
119
  k0 = calc.arr.transpose(v.data)
114
- k1 = calc.arr.transpose(v.set1.data) if len(v.set1.data) != 0 else [[]] * 3
115
- k2 = calc.arr.transpose(v.set2.data) if len(v.set2.data) != 0 else [[]] * 3
120
+ k1 = calc.arr.transpose(v.set1.data) if len(v.set1.data) != 0 else [[] for i in range(3)]
121
+ k2 = calc.arr.transpose(v.set2.data) if len(v.set2.data) != 0 else [[] for i in range(3)]
116
122
  data = np.concatenate([k0, k1, k2], axis=1)
117
123
  ylist = np.concatenate([data[1], data[2]])
118
124
  yscale = calc.plot.get_axis_scale(ylist, min_interval=5, extra_count=1)
@@ -60,7 +60,10 @@ def update_table_data(smp: Sample, only_table: str = None):
60
60
  elif key == '8':
61
61
  data = [smp.SequenceName, smp.SequenceValue, smp.IsochronMark, *smp.TotalParam]
62
62
  else:
63
- data = [['']]
63
+ raise KeyError(f"Invalid table id")
64
+
65
+ data = _normalize_data(
66
+ data, len(comp.header), smp.Info.experiment.step_num, text_col_indexes=comp.text_indexes)
64
67
 
65
68
  try:
66
69
  params_to_check = {
@@ -94,61 +97,46 @@ def update_handsontable(smp: Sample, data: list, id: str):
94
97
 
95
98
  """
96
99
 
97
- def _normalize_data(a, cols, start_col=0):
98
- if len(a) >= cols:
99
- return a[start_col:cols]
100
- else:
101
- return a[start_col:] + [[''] * len(a[0])] * (cols - len(a))
102
-
103
- def _strToBool(cols):
104
- bools_dict = {
105
- 'true': True, 'false': False, 'True': True, 'False': False, '1': True, '0': False, 'none': False,
106
- }
107
- return [bools_dict.get(str(col).lower(), False) for col in cols]
108
-
109
- def _digitize_data(a):
110
- # pattern = r'^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$'
111
- # return [[ast.literal_eval(str(cell)) if re.fullmatch(pattern, str(cell)) else np.nan if str(cell) == "" else cell for cell in row] for row in a]
112
- return a
113
100
 
114
101
  try:
115
- smp.SequenceName = data[0]
102
+ col3 = _normalize_data(data[0:3], cols=3, rows=len(data[0]), text_col_indexes=[0, 1, 2])
116
103
  except IndexError:
117
- pass
104
+ raise
118
105
 
119
106
  update_all_table = False
120
107
  try:
121
- if data[1] != smp.SequenceValue or data[2] != smp.IsochronMark:
108
+ if col3[0] != smp.SequenceName or col3[1] != smp.SequenceValue or col3[2] != smp.IsochronMark:
122
109
  update_all_table = True
123
- smp.SequenceValue = data[1]
124
- smp.IsochronMark = data[2]
110
+ smp.SequenceName = col3[0]
111
+ smp.SequenceValue = col3[1]
112
+ smp.IsochronMark = col3[2]
125
113
  except IndexError:
126
114
  print(f"Check sequence value / isochron mark failed")
127
- pass
128
-
115
+ raise
116
+ n = len(data[0])
129
117
  if id == '1': # 样品值
130
- data = _normalize_data(data, len(samples.SAMPLE_INTERCEPT_HEADERS), 3)
118
+ data = _normalize_data(data, len(samples.SAMPLE_INTERCEPT_HEADERS), n, 3)
131
119
  smp.SampleIntercept = _digitize_data(data)
132
120
  elif id == '2': # 本底值
133
- data = _normalize_data(data, len(samples.BLANK_INTERCEPT_HEADERS), 3)
121
+ data = _normalize_data(data, len(samples.BLANK_INTERCEPT_HEADERS), n, 3)
134
122
  smp.BlankIntercept = _digitize_data(data)
135
123
  elif id == '3': # 校正值
136
- data = _normalize_data(data, len(samples.CORRECTED_HEADERS), 3)
124
+ data = _normalize_data(data, len(samples.CORRECTED_HEADERS), n, 3)
137
125
  smp.CorrectedValues = _digitize_data(data)
138
126
  elif id == '4': # Degas table
139
- data = _normalize_data(data, len(samples.DEGAS_HEADERS), 3)
127
+ data = _normalize_data(data, len(samples.DEGAS_HEADERS), n, 3)
140
128
  smp.DegasValues = _digitize_data(data)
141
129
  elif id == '5': # 发行表
142
- data = _normalize_data(data, len(samples.PUBLISH_TABLE_HEADERS), 3)
130
+ data = _normalize_data(data, len(samples.PUBLISH_TABLE_HEADERS), n, 3)
143
131
  smp.PublishValues = _digitize_data(data)
144
132
  elif id == '6': # 年龄谱
145
- data = _normalize_data(data, len(samples.SPECTRUM_TABLE_HEADERS), 3)
133
+ data = _normalize_data(data, len(samples.SPECTRUM_TABLE_HEADERS), n, 3)
146
134
  smp.ApparentAgeValues = _digitize_data(data)
147
135
  elif id == '7': # 等时线
148
- data = _normalize_data(data, len(samples.ISOCHRON_TABLE_HEADERS), 3)
136
+ data = _normalize_data(data, len(samples.ISOCHRON_TABLE_HEADERS), n, 3)
149
137
  smp.IsochronValues = _digitize_data(data)
150
138
  elif id == '8': # 总参数
151
- data = _normalize_data(data, len(samples.TOTAL_PARAMS_HEADERS), 3)
139
+ data = _normalize_data(data, len(samples.TOTAL_PARAMS_HEADERS), n, 3)
152
140
  data = _digitize_data(data)
153
141
  data[101: 112] = [_strToBool(i) for i in data[101: 112]]
154
142
  smp.TotalParam = data
@@ -198,4 +186,50 @@ def update_data_from_table(smp: Sample, only_table: str = None):
198
186
  pass
199
187
 
200
188
 
189
+ def _normalize_data(a, cols, rows, start_col=0, start_row=0, text_col_indexes=[]):
190
+ if isinstance(a, np.ndarray):
191
+ a = a.tolist()
192
+ if not isinstance(a, list):
193
+ raise ValueError(f"List required, but {type(a)} given.")
194
+ if len(a) >= cols:
195
+ a = a[start_col:cols]
196
+ else:
197
+ a = a[start_col:] + [[] for j in range(cols - len(a))]
198
+
199
+ def f(_, _i):
200
+ if _i in text_col_indexes:
201
+ if isinstance(_, type(None)):
202
+ return ""
203
+ if isinstance(_, float) and np.isnan(_):
204
+ return ""
205
+ return str(_)
206
+ else:
207
+ if _ in ["", None, np.nan]:
208
+ return np.nan
209
+ elif isinstance(_, str):
210
+ if _.lower() == 'true':
211
+ return 1
212
+ elif _.lower() == 'false':
213
+ return 0
214
+ return float(_)
215
+
216
+ for i in range(cols - start_col):
217
+ if len(a[i]) >= rows:
218
+ a[i] = [f(each, i + start_col) for each in a[i][start_row:rows]]
219
+ else:
220
+ a[i] = [f(each, i + start_col) for each in a[i][start_row:]] + [f("", i + start_col) for j in range(rows - len(a[i]))]
221
+
222
+ return a
223
+
224
+
225
+ def _digitize_data(a):
226
+ # pattern = r'^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$'
227
+ # return [[ast.literal_eval(str(cell)) if re.fullmatch(pattern, str(cell)) else np.nan if str(cell) == "" else cell for cell in row] for row in a]
228
+ return a
229
+
201
230
 
231
+ def _strToBool(cols):
232
+ bools_dict = {
233
+ 'true': True, 'false': False, 'True': True, 'False': False, '1': True, '0': False, 'none': False,
234
+ }
235
+ return [bools_dict.get(str(col).lower(), False) for col in cols]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ararpy
3
- Version: 0.2.3
3
+ Version: 0.2.4
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.2.3', # version
19
+ version='0.2.4', # 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
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
File without changes