ararpy 0.1.19__py3-none-any.whl → 0.1.20__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ararpy/smp/corr.py CHANGED
@@ -25,16 +25,15 @@ from .sample import Sample
25
25
  def corr_gain(sample: Sample):
26
26
  """Blank Correction"""
27
27
  corrGain = True
28
- gain_corrected = np.zeros([10, len(sample.SequenceName)])
28
+ gain_corrected = np.zeros([10, sample.Info.experiment.step_num])
29
29
  try:
30
30
  for i in range(5):
31
31
  f, sf = np.array(sample.TotalParam[126 + i * 2:128 + i * 2])
32
32
  sf = f * sf / 100
33
33
  gain_corrected[i * 2:2 + i * 2] = calc.corr.gain(*sample.SampleIntercept[i * 2:2 + i * 2], f, sf)
34
- except Exception as e:
35
- print(f"Gain correction failed")
36
- print(traceback.format_exc())
37
- return
34
+ except (Exception, BaseException) as e:
35
+ print(f"Gain correction failed: \n{traceback.format_exc()}")
36
+ raise
38
37
  for i in range(0, 10, 2):
39
38
  gain_corrected[i] = [gain_corrected[i][index] if corrGain else j for index, j in enumerate(sample.SampleIntercept[i])]
40
39
  gain_corrected[i + 1] = [gain_corrected[i + 1][index] if corrGain else j for index, j in enumerate(sample.SampleIntercept[i + 1])]
@@ -156,15 +155,12 @@ def calc_degas_ca(sample: Sample):
156
155
  ar39ca = calc.arr.mul_factor(ar37ca, sample.TotalParam[8:10], isRelative=True)
157
156
  ar38ca = calc.arr.mul_factor(ar37ca, sample.TotalParam[10:12], isRelative=True)
158
157
  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])]
158
+ sample.DegasValues[8:10] = copy.deepcopy(ar37ca) # 37Ca
159
+ sample.DegasValues[ 4] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar36ca[0])] # 36Ca
164
160
  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])]
161
+ sample.DegasValues[18] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar38ca[0])] # 38Ca
166
162
  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])]
163
+ sample.DegasValues[22] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar39ca[0])] # 39Ca
168
164
  sample.DegasValues[23] = [val if corrDecasCa[idx] else 0 for idx, val in enumerate(ar39ca[1])]
169
165
  sample.PublishValues[1] = copy.deepcopy(ar37ca[0])
170
166
 
@@ -241,43 +237,51 @@ def calc_degas_cl(sample: Sample):
241
237
  try:
242
238
  if not corrDecasCl:
243
239
  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
240
+ vDecay = [cl36_cl38_p[0][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i])) for i in
245
241
  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 +
242
+ sDecay = [pow((cl36_cl38_p[1][i] * (1 - np.exp(-1 * decay_const[0][i] * stand_time_year[i]))) ** 2 +
247
243
  (cl36_cl38_p[0][i] * stand_time_year[i] * (np.exp(-1 * decay_const[0][i] * stand_time_year[i])) *
248
244
  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))]
245
+ sDecay = [calc.err.div((1, 0), (vDecay[i], sDecay[i])) for i in range(len(sDecay))]
246
+ vDecay = [1 / vDecay[i] for i in range(len(vDecay))]
247
+
251
248
  # 36ArCl
252
249
  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
250
  # 38ArCl
265
251
  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]))]
252
+ for i in range(len(vDecay)):
253
+ a1 = sample.CorrectedValues[0][i]; s1 = sample.CorrectedValues[1][i]
254
+ a2 = sample.DegasValues[4][i]; s2 = sample.DegasValues[5][i];
255
+ a3 = sample.DegasValues[16][i]; s3 = sample.DegasValues[17][i]
256
+ a4 = sample.DegasValues[18][i]; s4 = sample.DegasValues[19][i]
257
+ a5 = sample.CorrectedValues[4][i]; s5 = sample.CorrectedValues[5][i]
258
+ a6 = vDecay[i]; s6 = sDecay[i]
259
+ a7 = ar38ar36[0][i]; s7 = ar38ar36[1][i]
260
+
261
+ d1 = 1 / (1 - a6 / a7)
262
+ d2 = - 1 / (1 - a6 / a7)
263
+ d3 = 1 / (a7 - a6)
264
+ d4 = 1 / (a7 - a6)
265
+ d5 = - 1 / (a7 - a6)
266
+ d6 = (a1 - a2 + (a3 + a4) / a7 - a5 / a7) / a7 / (1 - a6 / a7) ** 2
267
+ d7 = -(a1 - a2) * (a6) / (a7 - a6) ** 2 - (a3 + a4 - a5) / (a7 - a6) ** 2
268
+
269
+ v1 = (a1 - a2 + (a3 + a4) / a7 - a5 / a7) / (1 - a6 / a7)
270
+ 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
271
+ s2 = calc.err.mul((v1, s1), (vDecay[i], sDecay[i]))
272
+ v1 = 0 if (ar36acl[0][i] - v1 < 0 or v1 < 0) and set_negative_zero[i] else v1
273
+ v2 = v1 * vDecay[i]
274
+
275
+ # Note: Ar36Cl uncertainty is differen with ArArCALC. All calculation was conducted separately considering they are independent
276
+ # 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))))
277
+
278
+ ar36cl[0].append(v1); ar36cl[1].append(s1)
279
+ ar38cl[0].append(v2); ar38cl[1].append(s2)
275
280
 
276
281
  except Exception as e:
277
282
  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])
283
+ ar36cl = np.zeros([2, len(ar36acl[0])])
284
+ ar38cl = np.zeros([2, len(ar36acl[0])])
281
285
 
282
286
  # sample.DegasValues[6:8] = ar36cl
283
287
  # sample.DegasValues[10:12] = ar38cl
@@ -349,7 +353,7 @@ def calc_degas_r(sample: Sample):
349
353
  """
350
354
  ar40ar = calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32])
351
355
  ar40r = calc.arr.sub(ar40ar, sample.DegasValues[26:28])
352
- ar40r[0] = [item if item >= 0 else 0 for item in ar40r[0]]
356
+ ar40r[0] = [0 if item < 0 and sample.TotalParam[101][index] else item for index, item in enumerate(ar40r[0])]
353
357
  sample.DegasValues[24:26] = copy.deepcopy(ar40r)
354
358
  sample.PublishValues[4] = copy.deepcopy(ar40r[0])
355
359
 
@@ -360,11 +364,16 @@ def calc_degas_r(sample: Sample):
360
364
  def calc_nor_inv_isochrons(sample: Sample):
361
365
  n = len(sample.SequenceName)
362
366
  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:
367
+ isochron_1 = calc.isochron.get_data(
368
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
369
+ *calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]),
370
+ *sample.DegasValues[0:2]
371
+ )
372
+ isochron_2 = calc.isochron.get_data(
373
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
374
+ *sample.DegasValues[0:2],
375
+ *calc.arr.sub(sample.CorrectedValues[8:10], sample.DegasValues[30:32]))
376
+ except (BaseException, Exception):
368
377
  return np.zeros([5, n]), np.zeros([5, n])
369
378
  else:
370
379
  return isochron_1, isochron_2
@@ -374,12 +383,18 @@ def calc_cl_isochrons(sample: Sample):
374
383
  n = len(sample.SequenceName)
375
384
  try:
376
385
  isochron_3 = calc.isochron.get_data(
377
- *sample.DegasValues[20:22], *sample.DegasValues[24:26], *sample.DegasValues[10:12])
386
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
387
+ *sample.DegasValues[24:26],
388
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor))
378
389
  isochron_4 = calc.isochron.get_data(
379
- *sample.DegasValues[20:22], *sample.DegasValues[10:12], *sample.DegasValues[24:26])
390
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor),
391
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor),
392
+ *sample.DegasValues[24:26])
380
393
  isochron_5 = calc.isochron.get_data(
381
- *sample.DegasValues[10:12], *sample.DegasValues[24:26], *sample.DegasValues[20:22])
382
- except:
394
+ *calc.arr.mul(sample.DegasValues[10:12], sample.NormalizeFactor),
395
+ *sample.DegasValues[24:26],
396
+ *calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor))
397
+ except (BaseException, Exception):
383
398
  return np.zeros([5, n]), np.zeros([5, n]), np.zeros([5, n])
384
399
  else:
385
400
  return isochron_3, isochron_4, isochron_5
@@ -422,7 +437,6 @@ def calc_ratio(sample: Sample, monte_carlo: bool = False):
422
437
  """
423
438
  ar40r_percent = [item / sample.CorrectedValues[8][index] * 100 if sample.CorrectedValues[8][index] != 0 else 0
424
439
  for index, item in enumerate(sample.DegasValues[24])]
425
- sum_ar39k = sum(sample.DegasValues[20])
426
440
  sum_ar36a = sum(sample.DegasValues[ 0])
427
441
  CaK = calc.arr.mul_factor(calc.arr.mul_factor(
428
442
  sample.DegasValues[8:10], calc.arr.rec_factor(sample.DegasValues[20:22], isRelative=False)),
@@ -437,10 +451,12 @@ def calc_ratio(sample: Sample, monte_carlo: bool = False):
437
451
  sample.ApparentAgeValues[0:2] = ar40aar36a
438
452
  sample.ApparentAgeValues[7] = ar36a_percent
439
453
  else:
454
+ ar39k, sar39k = calc.arr.mul(sample.DegasValues[20:22], sample.NormalizeFactor)
455
+ sum_ar39k = sum(ar39k)
456
+ ar39k_percent = [item / sum_ar39k * 100 if sum_ar39k != 0 else 0 for item in ar39k]
440
457
  ar40rar39k = calc.arr.mul_factor(
441
458
  sample.DegasValues[24:26], calc.arr.rec_factor(sample.DegasValues[20:22], isRelative=False),
442
459
  isRelative=False)
443
- ar39k_percent = [item / sum_ar39k * 100 if sum_ar39k != 0 else 0 for item in sample.DegasValues[20]]
444
460
  sample.ApparentAgeValues[0:2] = ar40rar39k
445
461
  sample.ApparentAgeValues[7] = ar39k_percent
446
462
 
@@ -529,6 +545,7 @@ def monte_carlo_f(sample: Sample):
529
545
  R36v38clp = np.transpose(sample.TotalParam[56:58])
530
546
 
531
547
  stand_time_year = np.transpose(sample.TotalParam[32])
548
+ JNFactor = sample.NormalizeFactor
532
549
 
533
550
  irradiation_cycles = [list(filter(None, re.split(r'[DS]', each_step))) for each_step in sample.TotalParam[27]]
534
551
  t1 = [re.findall(r"\d+", i) for i in sample.TotalParam[31]] # t1: experimental times
@@ -562,6 +579,7 @@ def monte_carlo_f(sample: Sample):
562
579
  L37ar=L37ar[i], L39ar=L39ar[i], L36cl=L36cl[i],
563
580
  MDFunc=None,
564
581
  MDF=MDF[i], stand_time_year=stand_time_year[i],
582
+ JNFactor=JNFactor,
565
583
  blank_gain_corr=sample.TotalParam[111][i]
566
584
  )
567
585
 
ararpy/smp/export.py CHANGED
@@ -38,8 +38,8 @@ except ModuleNotFoundError:
38
38
  SETTINGS_ROOT = ""
39
39
 
40
40
 
41
- def to_excel(file_path: str):
42
- excel = WritingWorkbook(filepath=file_path)
41
+ def to_excel(smp: Sample, file_path: str, *args, **kwargs):
42
+ excel = WritingWorkbook(sample=smp, filepath=file_path, *args, **kwargs)
43
43
  excel.get_xls()
44
44
 
45
45
 
@@ -297,6 +297,24 @@ def get_plot_series_data(smp: Sample, diagram: str = 'age spectra', **options):
297
297
  return series
298
298
 
299
299
 
300
+ def spectraData2Sgima(data, sigma=2):
301
+ return list(map(lambda row: [row[0], (row[1] - row[2]) / 2 * (sigma - 1) + row[1], (row[2] - row[1]) / 2 * (sigma - 1) + row[2]], data))
302
+
303
+
304
+ def getRectFromSpectra(data):
305
+ """
306
+ Parameters
307
+ ----------
308
+ data: [x, y1, y2]
309
+
310
+ Returns
311
+ -------
312
+
313
+ """
314
+ data = np.array(data)
315
+ return list(map(lambda index: [data[index,0], min(data[index,[1,2]]), np.diff(data[[index,index+1],0])[0], np.diff(data[index,[1,2]])[0]], list(range(len(data) - 1))))
316
+
317
+
300
318
  def _get_additional_text_series(name):
301
319
  return {
302
320
  'type': 'text', 'id': f'text-{name}-{get_random_digits()}',
@@ -330,22 +348,42 @@ def _get_plot_data_age_spectra_series(smp: sample, **options):
330
348
  })
331
349
  text1 = smp.AgeSpectraPlot.text1
332
350
  text2 = smp.AgeSpectraPlot.text2
351
+ sigma = 1
352
+ set_data = [spectraData2Sgima(smp.AgeSpectraPlot.set1.data, sigma),
353
+ spectraData2Sgima(smp.AgeSpectraPlot.set2.data, sigma)]
333
354
  for index, text in enumerate([text1, text2]):
334
- if not np.isnan(smp.Info.results.age_spectra[index]['age']):
355
+ res = smp.Info.results.age_plateau[index]
356
+ if not np.isnan(res['age']):
335
357
  selection = np.array(smp.Info.results.selection[index]['data']) * 2 + 1
336
- set_data = list(map(lambda each: [data[0][each - 1], min(data[1][each], data[2][each]), data[0][each + 1] - data[0][each], sigma * abs(data[1][each] - data[2][each])], selection))
358
+ plateau_data = np.array(set_data[index])
359
+ # spectra_fill_data = list(map(lambda each: [data[0][each - 1], min(data[1][each], data[2][each]), data[0][each + 1] - data[0][each], sigma * abs(data[1][each] - data[2][each])], selection))
360
+ spectra_fill_data = getRectFromSpectra(plateau_data)
337
361
  series.append({
338
362
  'type': 'series.rect', 'id': f'rect-{smp.name()}-{get_random_digits()}', 'name': f'rect-{smp.name()}-{get_random_digits()}',
339
- 'color': 'none', 'fill_color': ['red', 'blue'][index], 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
340
- 'data': set_data, 'line_caps': 'square', 'fill': True,
363
+ 'color': ['red', 'blue'][index], 'fill_color': ['red', 'blue'][index], 'line_width': 0, 'line_style': 'solid', 'z_index': 9,
364
+ 'data': spectra_fill_data, 'line_caps': 'square', 'fill': True,
365
+ 'axis_index': 0,
366
+ })
367
+ series.append({
368
+ 'type': 'series.line', 'id': f'line-{smp.name()}-{get_random_digits()}',
369
+ 'name': f'line-{smp.name()}-{get_random_digits()}',
370
+ 'color': ['red', 'blue'][index], 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
371
+ 'data': plateau_data[:,[0,1]].tolist(), 'line_caps': 'square',
372
+ 'axis_index': 0,
373
+ })
374
+ series.append({
375
+ 'type': 'series.line', 'id': f'line-{smp.name()}-{get_random_digits()}',
376
+ 'name': f'line-{smp.name()}-{get_random_digits()}',
377
+ 'color': ['red', 'blue'][index], 'line_width': 1, 'line_style': 'solid', 'z_index': 9,
378
+ 'data': plateau_data[:,[0,2]].tolist(), 'line_caps': 'square',
341
379
  'axis_index': 0,
342
380
  })
343
381
  series.append({
344
382
  'type': 'text', 'id': f'text-{smp.name()}-{get_random_digits()}', 'name': f'text-{smp.name()}-{get_random_digits()}',
345
383
  'color': ['red', 'blue'][index], 'fill_color': ['red', 'blue'][index],
346
- 'text': f"WMPA = {smp.Info.results.age_spectra[index]['age']:.2f} ± {(sigma * smp.Info.results.age_spectra[index]['s3']):.2f} Ma<r>"
347
- f"MSWD = {smp.Info.results.age_spectra[index]['MSWD']:.2f}, n = {smp.Info.results.age_spectra[index]['Num']:.0f}<r>"
348
- f"<sup>39</sup>Ar = {smp.Info.results.age_spectra[index]['Ar39']:.2f}%",
384
+ 'text': f"WMPA = {res['age']:.2f} ± {(sigma * res['s3']):.2f} Ma<r>"
385
+ f"MSWD = {res['MSWD']:.2f}, n = {res['Num']:.0f}<r>"
386
+ f"<sup>39</sup>Ar = {res['Ar39']:.2f}%",
349
387
  'size': title_size,
350
388
  'data': [text.pos],
351
389
  'axis_index': 1,
@@ -386,10 +424,15 @@ def _get_plot_data_age_spectra_axis(smp: sample, **options):
386
424
  y_low_limit, y_up_limit, stick_num, inc = get_axis_scale(np.array(data[1:3]).flatten())
387
425
  y_extent = [y_low_limit, y_up_limit]
388
426
  y_interval = [y_low_limit + i * inc for i in range(stick_num + 1)]
427
+ y_interval.extend([y_up_limit * 10] * 3)
428
+ dp = int(np.log10(abs(y_up_limit - y_low_limit)) - 1)
429
+ dp = 0 if dp >= 0 else abs(dp)
430
+ print(f"{dp = }")
431
+ y_interval = [f"{i:.{dp}f}" for i in y_interval]
389
432
 
390
- y_extent = [4, 12]
391
- y_interval = ['0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100']
392
- y_interval = ['0', '4', '6', '8', '10', '12', '60', '70', '80', '90', '100']
433
+ # y_extent = [4, 12]
434
+ # y_interval = ['0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100']
435
+ # y_interval = ['0', '4', '6', '8', '10', '12', '60', '70', '80', '90', '100']
393
436
 
394
437
  xAxis.append({
395
438
  'extent': [0, 100], 'interval': [0, 20, 40, 60, 80, 100], 'id': 0, 'show_frame': True,
@@ -762,16 +805,6 @@ class WritingWorkbook:
762
805
 
763
806
  if self.template_filepath is not None:
764
807
  self.read_template()
765
- if self.style is None:
766
- self.style = {
767
- 'font_size': 10, 'font_name': 'Microsoft Sans Serif', 'bold': False,
768
- 'bg_color': '#FFFFFF', # back ground
769
- 'font_color': '#000000', 'align': 'left',
770
- 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 # border width
771
- }
772
-
773
- def spectraData2Sgima(self, data, sigma=2):
774
- return list(map(lambda row: [row[0], (row[1] - row[2]) / 2 * (sigma - 1) + row[1], (row[2] - row[1]) / 2 * (sigma - 1) + row[2]], data))
775
808
 
776
809
  def read_template(self):
777
810
  # print(self.template_filepath)
@@ -781,7 +814,7 @@ class WritingWorkbook:
781
814
  # TypeError: NAN/INF not supported in write_number() without 'nan_inf_to_errors' Workbook() option
782
815
  xls = Workbook(self.filepath, {"nan_inf_to_errors": True})
783
816
 
784
- style = xls.add_format(self.style)
817
+ style = xls.add_format(self.default_fmt_prop)
785
818
 
786
819
  sigma = int(self.sample.Info.preference['confidenceLevel'])
787
820
 
@@ -809,9 +842,9 @@ class WritingWorkbook:
809
842
 
810
843
  # Data for age spectra
811
844
  try:
812
- spectra_data = arr.transpose(self.spectraData2Sgima(self.sample.AgeSpectraPlot.data, sigma))
813
- spectra_set1_data = arr.transpose(self.spectraData2Sgima(self.sample.AgeSpectraPlot.set1.data, sigma)) or [[]] * 3
814
- spectra_set2_data = arr.transpose(self.spectraData2Sgima(self.sample.AgeSpectraPlot.set2.data, sigma)) or [[]] * 3
845
+ spectra_data = arr.transpose(spectraData2Sgima(self.sample.AgeSpectraPlot.data, sigma))
846
+ spectra_set1_data = arr.transpose(spectraData2Sgima(self.sample.AgeSpectraPlot.set1.data, sigma)) or [[]] * 3
847
+ spectra_set2_data = arr.transpose(spectraData2Sgima(self.sample.AgeSpectraPlot.set2.data, sigma)) or [[]] * 3
815
848
  sht_reference.write_column(f"A{start_row}", spectra_data[0], style)
816
849
  sht_reference.write_column(f"B{start_row}", spectra_data[1], style)
817
850
  sht_reference.write_column(f"C{start_row}", spectra_data[2], style)
@@ -1036,7 +1069,7 @@ class WritingWorkbook:
1036
1069
  material = self.sample.Info.sample.material
1037
1070
  weight = self.sample.Info.sample.weight
1038
1071
  J_value = self.sample.TotalParam[67][0]
1039
- J_error = self.sample.TotalParam[68][0]
1072
+ J_error = self.sample.TotalParam[68][0] * self.sample.TotalParam[67][0] / 100
1040
1073
  sigma = self.sample.Info.preference['confidenceLevel']
1041
1074
  sequence_type = {"StepLaser": "Laser", "StepFurnace": "Temperature", "StepCrusher": "Drop", }.get(method, "Step Value")
1042
1075
  sequence_unit = self.sample.Info.sample.sequence_unit if self.sample.Info.sample.sequence_unit != "" else "Unit"
@@ -1046,27 +1079,27 @@ class WritingWorkbook:
1046
1079
  set2_ratio = [self.sample.Info.results.isochron['figure_3'][1]['initial'], self.sample.Info.results.isochron['figure_2'][1]['initial'], self.sample.TotalParam[118][0]][int(self.sample.TotalParam[115][0])]
1047
1080
 
1048
1081
  content = [
1049
- [(0, 0, 0, 14), f"Table 1. 40Ar/39Ar dating results", {'bold': 1, 'top': 1, 'bottom': 1, 'align': 'left'}],
1050
- [(1, 0, 2, 0), f"Step", {'bold': 1}],
1051
- [(1, 1), f"{sequence_type}", {'bold': 1}],
1052
- [(2, 1), f"({sequence_unit})", {'bold': 1}],
1053
- [(1, 2, 2, 2), f"Set", {'bold': 1}],
1054
- [(1, 3, 2, 3), f"36Arair", {'bold': 1}],
1055
- [(1, 4, 2, 4), f"36ArCa", {'bold': 1}],
1056
- [(1, 5, 2, 5), f"36ArCl", {'bold': 1}],
1057
- [(1, 6, 2, 6), f"36ArK", {'bold': 1}],
1058
- [(1, 7, 2, 7), f"36Ar*", {'bold': 1}],
1059
- [(1, 8, 2, 8), f"39Ar/40Ar", {'bold': 1}],
1060
- [(1, 9, 2, 9), f"36Ar/40Ar", {'bold': 1}],
1061
- [(1, 10), f"Apparent Age", {'bold': 1}],
1062
- [(1, 11), f"± {sigma} σ", {'bold': 1}],
1063
- [(2, 10, 2, 11), f"({age_unit})", {'bold': 1}],
1064
- [(1, 12), f"40Ar*", {'bold': 1}],
1065
- [(2, 12), f"(%)", {'bold': 1}],
1066
- [(1, 13), f"39ArK", {'bold': 1}],
1067
- [(2, 13), f"(%)", {'bold': 1}],
1068
- [(1, 14, 2, 14), f"Ca/K", {'bold': 1}],
1069
- [(3, 0, 3, 14), f"Sample {name} ({material}){' by ' if method != '' else ''}{method}, weight = {weight} mg, J = {J_value} ± {J_error}", {'bold': 1, 'italic': 1, 'top': 6, 'align': 'left'}],
1082
+ [(0, 0), f"Table 1. 40Ar/39Ar dating results", {'bold': 1, 'top': 1, 'align': 'left'}],
1083
+ [(1, 0, 2, 0), f"Step", {'bold': 1, 'top': 1, 'bottom': 6}],
1084
+ [(1, 1), f"{sequence_type}", {'bold': 1, 'top': 1}],
1085
+ [(2, 1), f"({sequence_unit})", {'bold': 1, 'bottom': 6}],
1086
+ [(1, 2, 2, 2), f"Set", {'bold': 1, 'top': 1, 'bottom': 6}],
1087
+ [(1, 3, 2, 3), f"36Arair", {'bold': 1, 'top': 1, 'bottom': 6}],
1088
+ [(1, 4, 2, 4), f"37ArCa", {'bold': 1, 'top': 1, 'bottom': 6}],
1089
+ [(1, 5, 2, 5), f"38ArCl", {'bold': 1, 'top': 1, 'bottom': 6}],
1090
+ [(1, 6, 2, 6), f"39ArK", {'bold': 1, 'top': 1, 'bottom': 6}],
1091
+ [(1, 7, 2, 7), f"40Ar*", {'bold': 1, 'top': 1, 'bottom': 6}],
1092
+ [(1, 8, 2, 8), f"39Ar/40Ar", {'bold': 1, 'top': 1, 'bottom': 6}],
1093
+ [(1, 9, 2, 9), f"36Ar/40Ar", {'bold': 1, 'top': 1, 'bottom': 6}],
1094
+ [(1, 10), f"Apparent Age", {'bold': 1, 'top': 1}],
1095
+ [(1, 11), f"± {sigma} σ", {'bold': 1, 'top': 1}],
1096
+ [(2, 10, 2, 11), f"({age_unit})", {'bold': 1, 'bottom': 6}],
1097
+ [(1, 12), f"40Ar*", {'bold': 1, 'top': 1}],
1098
+ [(2, 12), f"(%)", {'bold': 1, 'bottom': 6}],
1099
+ [(1, 13), f"39ArK", {'bold': 1, 'top': 1}],
1100
+ [(2, 13), f"(%)", {'bold': 1, 'bottom': 6}],
1101
+ [(1, 14, 2, 14), f"Ca/K", {'bold': 1, 'top': 1, 'bottom': 6}],
1102
+ [(3, 0), f"Sample {name} ({material}){' by ' if method != '' else ''}{method}, weight = {weight} mg, J = {J_value} ± {J_error}", {'bold': 1, 'italic': 1, 'align': 'left'}],
1070
1103
  [(4, 0, 1), self.sample.SequenceName, {'align': 'left'}],
1071
1104
  [(4, 1, 1), self.sample.SequenceValue, {'num_format': 'General'}],
1072
1105
  [(4, 2, 1), list(map(lambda x: int(x) if str(x).isnumeric() else "", self.sample.IsochronMark)), {'num_format': 'General'}],
@@ -1084,7 +1117,7 @@ class WritingWorkbook:
1084
1117
  [(4, 14, 1), self.sample.PublishValues[9], {}],
1085
1118
  [(4 + num_step, 0, 0), [''] * 15, {'bold': 1, 'top': 1}],
1086
1119
 
1087
- [(5 + num_step, 0, 5 + num_step, 8), "Table 2. 40Ar/39Ar age summary", {'bold': 1, 'align': 'left'}],
1120
+ [(5 + num_step, 0), "Table 2. 40Ar/39Ar age summary", {'bold': 1, 'align': 'left'}],
1088
1121
  [(6 + num_step, 0, 7 + num_step, 0), "Group", {'bold': 1, 'top': 1}],
1089
1122
  [(6 + num_step, 1, 7 + num_step, 1), "40Arr/39K", {'bold': 1, 'top': 1}],
1090
1123
  [(6 + num_step, 2, 7 + num_step, 2), f"± {sigma} σ", {'bold': 1, 'top': 1}],
ararpy/smp/initial.py CHANGED
@@ -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
 
@@ -183,7 +183,10 @@ def initial(smp: Sample):
183
183
  reference=ArArBasic(
184
184
  name='REFERENCE', journal='JOURNAL', doi='DOI'
185
185
  ),
186
- preference=copy.deepcopy(PREFERENCE_RES)
186
+ preference=copy.deepcopy(PREFERENCE_RES),
187
+ experiment=ArArBasic(
188
+ name='', mass_spec='', collectors='', step_num=0
189
+ ),
187
190
  ))
188
191
 
189
192
  decimal_places = PREFERENCE_RES['decimalPlaces']
@@ -234,7 +237,7 @@ def initial(smp: Sample):
234
237
  return smp
235
238
 
236
239
 
237
- def initial_plot_styles(sample: Sample, except_attrs=None):
240
+ def initial_plot_styles(smp: Sample, except_attrs=None):
238
241
  """
239
242
  Initialize plot components styles based on Default Styles. Except attrs is a list containing attrs
240
243
  that are not expected to be initialized.
@@ -258,17 +261,26 @@ def initial_plot_styles(sample: Sample, except_attrs=None):
258
261
  for k, v in value.items():
259
262
  set_attr(getattr(obj, name), k, v)
260
263
 
261
- default_styles = copy.deepcopy(samples.DEFAULT_PLOT_STYLES)
264
+ default_styles = get_default_plot_style(smp)
262
265
  for figure_index, figure_attr in default_styles.items():
263
- plot = getattr(sample, figure_attr['attr_name'], Plot())
266
+ plot = getattr(smp, figure_attr['attr_name'], Plot())
264
267
  for key, attr in figure_attr.items():
265
268
  set_attr(plot, key, attr)
266
269
 
267
270
 
268
- def re_set_smp(sample: Sample):
271
+ def get_default_plot_style(smp: Sample):
272
+ sample_type = smp.Info.sample.type
273
+ try:
274
+ age_unit = str(smp.Info.preference['ageUnit']).capitalize()
275
+ except:
276
+ age_unit = "Undefined"
277
+ return copy.deepcopy(samples.DEFAULT_PLOT_STYLES(sample_type, age_unit))
278
+
279
+
280
+ def re_set_smp(smp: Sample):
269
281
  std = initial(Sample())
270
- basic.get_merged_smp(sample, std)
271
- return sample
282
+ basic.get_merged_smp(smp, std)
283
+ return check_version(smp)
272
284
 
273
285
 
274
286
  def check_version(smp: Sample):
@@ -283,7 +295,28 @@ def check_version(smp: Sample):
283
295
 
284
296
  """
285
297
  if smp.version != samples.VERSION:
286
- re_set_smp(smp)
298
+ std = initial(Sample())
299
+ basic.get_merged_smp(smp, std)
300
+
301
+ # 20250328: # Experiment info
302
+ smp.Info.experiment.name = smp.name()
303
+ smp.Info.experiment.step_num = smp.sequence().size
304
+
305
+ # 20250404
306
+ doNormalize = True
307
+ v, sv = [], []
308
+ if smp.Info.sample.type.lower() == "unknown":
309
+ v, sv = smp.TotalParam[67:69]
310
+ sv = np.multiply(v, sv) / 100
311
+ elif smp.Info.sample.type.lower() == "air":
312
+ v, sv = smp.TotalParam[93:95]
313
+ sv = np.multiply(v, sv) / 100
314
+ elif smp.Info.sample.type.lower() == "standard":
315
+ v, sv = smp.TotalParam[59:61]
316
+ smp.NormalizeFactor = [
317
+ [1 if v[0] == each or not doNormalize else v[0] / each for each in v],
318
+ [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))]
319
+ ]
287
320
  return smp
288
321
 
289
322
 
@@ -329,11 +362,8 @@ def from_arr_files(file_path, sample_name: str = ""):
329
362
  def renamed_load(file_obj):
330
363
  return RenameUnpickler(file_obj).load()
331
364
 
332
- try:
333
- with open(file_path, 'rb') as f:
334
- sample = renamed_load(f)
335
- except (Exception, BaseException):
336
- raise ValueError(f"Fail to open arr file: {file_path}")
365
+ with open(file_path, 'rb') as f:
366
+ sample = renamed_load(f)
337
367
  # Check arr version
338
368
  # recalculation will not be applied automatically
339
369
  return check_version(sample)
@@ -353,7 +383,7 @@ def from_calc_files(file_path: str, **kwargs):
353
383
  """
354
384
  file = calc_file.ArArCalcFile(file_path=file_path, **kwargs).open()
355
385
  sample = create_sample_from_df(file.get_content(), file.get_smp_info())
356
- return sample
386
+ return check_version(sample)
357
387
 
358
388
 
359
389
  # create
@@ -372,7 +402,7 @@ def from_full_files(file_path: str, sample_name: str = None):
372
402
  sample_name = str(os.path.split(file_path)[-1]).split('.')[0]
373
403
  content, sample_info = calc_file.open_full_xls(file_path, sample_name)
374
404
  sample = create_sample_from_dict(content=content, smp_info=sample_info)
375
- return sample
405
+ return check_version(sample)
376
406
 
377
407
 
378
408
  # create
@@ -450,4 +480,4 @@ def from_raw_data(raw: RawData, mapping: Optional[List[dict]] = None) -> Sample:
450
480
 
451
481
  # sample.TotalParam[31] = [raw.get_sequence(row['unknown'], flag='name').datetime for row in mapping]
452
482
 
453
- return sample
483
+ return check_version(sample)