ararpy 0.1.199__py3-none-any.whl → 0.2.1__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.
Files changed (40) hide show
  1. ararpy/Example - Check arr.py +52 -0
  2. ararpy/Example - Granite Cooling History.py +411 -0
  3. ararpy/Example - Plot temperature calibration.py +291 -0
  4. ararpy/Example - Show MDD results.py +561 -0
  5. ararpy/Example - Show all Kfs age spectra.py +344 -0
  6. ararpy/Example - Show random walk results.py +363 -0
  7. ararpy/Example - Tc calculation.py +437 -0
  8. ararpy/__init__.py +3 -4
  9. ararpy/calc/age.py +34 -36
  10. ararpy/calc/arr.py +0 -20
  11. ararpy/calc/basic.py +26 -3
  12. ararpy/calc/corr.py +131 -85
  13. ararpy/calc/plot.py +1 -2
  14. ararpy/calc/raw_funcs.py +41 -2
  15. ararpy/calc/regression.py +224 -132
  16. ararpy/files/arr_file.py +2 -1
  17. ararpy/files/basic.py +0 -22
  18. ararpy/files/calc_file.py +107 -84
  19. ararpy/files/raw_file.py +242 -229
  20. ararpy/smp/basic.py +133 -34
  21. ararpy/smp/calculation.py +6 -6
  22. ararpy/smp/corr.py +339 -153
  23. ararpy/smp/diffusion_funcs.py +345 -36
  24. ararpy/smp/export.py +247 -129
  25. ararpy/smp/info.py +2 -2
  26. ararpy/smp/initial.py +93 -45
  27. ararpy/smp/json.py +2 -2
  28. ararpy/smp/plots.py +144 -164
  29. ararpy/smp/raw.py +11 -15
  30. ararpy/smp/sample.py +222 -181
  31. ararpy/smp/style.py +26 -7
  32. ararpy/smp/table.py +42 -33
  33. ararpy/thermo/atomic_level_random_walk.py +56 -48
  34. ararpy/thermo/basic.py +2 -2
  35. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/METADATA +1 -1
  36. ararpy-0.2.1.dist-info/RECORD +73 -0
  37. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/WHEEL +1 -1
  38. ararpy-0.1.199.dist-info/RECORD +0 -66
  39. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/licenses/LICENSE +0 -0
  40. {ararpy-0.1.199.dist-info → ararpy-0.2.1.dist-info}/top_level.txt +0 -0
ararpy/calc/corr.py CHANGED
@@ -61,10 +61,10 @@ def mdf(rm: float, srm: float, m1: float, m2: float, ra: float = 298.56,
61
61
  sratio_m = err.div((m2, sm2), (m1, sm1))
62
62
  useRyu = False
63
63
  if not useRyu:
64
- # line
65
- k1 = (ra / rm + delta_m - 1) / delta_m
66
- k2 = err.div(((ra / rm + delta_m - 1), err.div((ra, sra), (rm, srm))), (delta_m, sdelta_m))
67
- # exp
64
+ # line, D = 1 + (ra / rm - 1) / dm # Renne2009
65
+ k1 = 1 + (ra / rm - 1) / delta_m
66
+ k2 = err.div(((ra / rm - 1), err.div((ra, sra), (rm, srm))), (delta_m, sdelta_m))
67
+ # exp, D = 1 + ln(ra / rm) / (m1 * ln(m2/m1)) # Renne2009
68
68
  try:
69
69
  k3 = (np.log(ra / rm) / np.log(ratio_m)) * (1 / m1) + 1
70
70
  v1 = err.log((ra / rm, err.div((ra, sra), (rm, srm))))
@@ -73,7 +73,7 @@ def mdf(rm: float, srm: float, m1: float, m2: float, ra: float = 298.56,
73
73
  k4 = err.div((np.log(ra / rm) / np.log(ratio_m), v3), (m1, sm1))
74
74
  except Exception:
75
75
  k3, k4 = 0, 0
76
- # pow
76
+ # pow, D = pow(ra / rm, 1 / dm) # Renne2009
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))),
@@ -86,8 +86,7 @@ def mdf(rm: float, srm: float, m1: float, m2: float, ra: float = 298.56,
86
86
  return mdf_line_2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
87
87
 
88
88
 
89
- def discr(a0: list, e0: list, mdf: list, smdf: list, m: list, m40: list,
90
- isRelative=True, method="l"):
89
+ def discr(a0: list, e0: list, mdf: list, smdf: list, m: list, m40: list, method: list, isRelative=True):
91
90
  """
92
91
  :param a0: a list of tested isotope value
93
92
  :param e0: 1 sigma error of a0, list type
@@ -101,25 +100,29 @@ def discr(a0: list, e0: list, mdf: list, smdf: list, m: list, m40: list,
101
100
  linear correction, MDF = [(Ar40/Ar36)true / (Ar40/Ar36)measure] * 1 / MD - 1 / MD + 1
102
101
  corr = blank_corrected / [MD * MDF - MD +1]
103
102
  """
103
+
104
+ def _discr(_mdf: float, _smdf: float, _m40: float, _m: float, _method: str):
105
+ delta_m = abs(_m40 - _m)
106
+ ratio_m = abs(_m40 / _m) if _m != 0 else 1
107
+ if _method.lower().startswith("l"): # linear
108
+ k0 = 1 / (delta_m * _mdf - delta_m + 1) if (delta_m * _mdf - delta_m + 1) != 0 else 0
109
+ k1 = err.rec((delta_m * _mdf - delta_m + 1, _smdf * delta_m))
110
+ elif _method.lower().startswith("e"): # exponential
111
+ k0 = 1 / np.exp((_mdf - 1) * _m * ratio_m)
112
+ k1 = err.rec((1 / k0, err.pow((np.e, 0), ((_mdf - 1) * _m * np.log(ratio_m), err.mul((_mdf - 1, _smdf), (_m * np.log(ratio_m), 0))))))
113
+ elif _method.lower().startswith("p"): # power
114
+ k0 = 1 / (_mdf ** delta_m)
115
+ k1 = err.rec((_mdf ** delta_m, err.pow((_mdf, _smdf), (delta_m, 0))))
116
+ else:
117
+ k0 = 1
118
+ k1 = 0
119
+ return k0, k1
120
+
104
121
  r0, r1 = [], []
105
122
  if isRelative:
106
123
  smdf = [smdf[i] * mdf[i] / 100 for i in range(len(smdf))]
107
124
  for i in range(min([len(arg) for arg in [a0, e0, mdf, smdf]])):
108
- delta_mass = abs(m40[i] - m[i])
109
- ratio_mass = abs(m40[i] / m[i]) if m[i] != 0 else 1
110
- if method.lower().startswith("l"):
111
- k0 = 1 / (delta_mass * mdf[i] - delta_mass + 1) if (delta_mass * mdf[i] - delta_mass + 1) != 0 else 0
112
- k1 = err.div((1, 0), (delta_mass * mdf[i] - delta_mass + 1, smdf[i] * delta_mass))
113
- elif method.lower().startswith("e"):
114
- k0 = 1 / (ratio_mass ** (mdf[i] * m40[i] - m[i]))
115
- k1 = err.div((1, 0), (ratio_mass ** (mdf[i] * m40[i] - m[i]), err.pow((ratio_mass, 0), (
116
- mdf[i] * m40[i] - m[i], err.mul((mdf[i], smdf[i]), (m40[i], 0))))))
117
- elif method.lower().startswith("p"):
118
- k0 = 1 / (mdf[i] ** delta_mass)
119
- k1 = err.div((1, 0), (mdf[i] ** delta_mass, err.pow((mdf[i], smdf[i]), (delta_mass, 0))))
120
- else:
121
- k0 = 1
122
- k1 = 0
125
+ k0, k1 = _discr(_mdf=mdf[i], _smdf=smdf[i], _m40=m40[i], _m=m[i], _method=method[i])
123
126
  r0.append(a0[i] * k0)
124
127
  r1.append(err.mul((a0[i], e0[i]), (k0, k1)))
125
128
  return [r0, r1]
@@ -261,8 +264,8 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
261
264
  R39v37ca: Tuple[float, float], R36v37ca: Tuple[float, float], R38v37ca: Tuple[float, float],
262
265
  R40v39k: Tuple[float, float], R38v39k: Tuple[float, float],
263
266
  R36v38clp: Tuple[float, float],
264
- L37ar: Tuple[float, float], L39ar: Tuple[float, float], L36cl: Tuple[float, float],
265
- MDFunc: Union[MethodType],
267
+ L37ar: Tuple[float, float], L39ar: Tuple[float, float],
268
+ L36cl: Tuple[float, float],
266
269
  MDF: Tuple[float, float],
267
270
  M40: Tuple[float, float], M39: Tuple[float, float], M38: Tuple[float, float],
268
271
  M37: Tuple[float, float], M36: Tuple[float, float],
@@ -303,9 +306,19 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
303
306
  """
304
307
  # define parameters
305
308
 
306
- MDFunc = lambda _M40, _mass, _mdf: 1 / ((_M40 - _mass) * (_mdf - 1) + 1)
307
-
308
- Monte_Carlo_Size = 10000
309
+ blank_gain_corr = options.get('blank_gain_corr', True)
310
+ mdf_method = options.get('mdf_method', 'linear')
311
+ force_to_zero = options.get('force_to_zero', True)
312
+ Monte_Carlo_Size = options.get('monte_carlo_size', 5000)
313
+
314
+ if mdf_method.lower().startswith("l"): # linear
315
+ MDFunc = lambda _M40, _mass, _mdf: 1 / ((_M40 - _mass) * (_mdf - 1) + 1)
316
+ elif mdf_method.lower().startswith("e"): # exponential
317
+ MDFunc = lambda _M40, _mass, _mdf: 1 / np.exp((_mdf - 1) * _mass * abs(_M40 / _m))
318
+ elif mdf_method.lower().startswith("p"): # power
319
+ MDFunc = lambda _M40, _mass, _mdf: 1 / (_mdf ** abs(_M40 - _mass))
320
+ else:
321
+ raise KeyError(f"Worong MDF method {mdf_method} found. Linear, exponential or power required.")
309
322
 
310
323
  # generate random
311
324
  ar40m = random_normal_absolute(*ar40m, size=Monte_Carlo_Size)
@@ -348,8 +361,6 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
348
361
 
349
362
  JNFactor = random_normal_absolute(*JNFactor, size=Monte_Carlo_Size)
350
363
 
351
- blank_gain_corr = options.get('blank_gain_corr', True)
352
-
353
364
  def do_simulation():
354
365
  i = 0
355
366
  while i < Monte_Carlo_Size:
@@ -364,61 +375,100 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
364
375
  _ar40m = ar40m[i]
365
376
 
366
377
  _ar36 = (ar36m[i] / G36[i] - ar36b[i] / (G36[i] if blank_gain_corr else 1)) * P36Mdf
367
- _ar37 = (ar37m[i] / G37[i] - ar37b[i] / (G37[i] if blank_gain_corr else 1)) * P37Mdf
378
+ _ar37 = (ar37m[i] / G37[i] - ar37b[i] / (G37[i] if blank_gain_corr else 1)) * P37Mdf * P37Decay
368
379
  _ar38 = (ar38m[i] / G38[i] - ar38b[i] / (G38[i] if blank_gain_corr else 1)) * P38Mdf
369
- _ar39 = (ar39m[i] / G39[i] - ar39b[i] / (G39[i] if blank_gain_corr else 1)) * P39Mdf
380
+ _ar39 = (ar39m[i] / G39[i] - ar39b[i] / (G39[i] if blank_gain_corr else 1)) * P39Mdf * P39Decay
370
381
  _ar40 = (ar40m[i] / G40[i] - ar40b[i] / (G40[i] if blank_gain_corr else 1)) * P40Mdf
371
382
 
372
- _ar37ca = _ar37 * P37Decay
373
- _ar39k = _ar39 * P39Decay - _ar37ca * R39v37ca[i]
374
- _ar38res = _ar38 - _ar39k * R38v39k[i] - _ar37ca * R38v37ca[i]
375
- _ar36res = _ar36 - _ar37ca * R36v37ca[i]
376
- _ar36cl = (_ar36res - _ar38res / R38v36a[i]) / (1 - 1 / (R36v38clp[i] * (1 - exp(-1 * L36cl[i] * stand_time_year)) * R38v36a[i]))
377
- _ar36a = _ar36res - _ar36cl
378
- _ar40r = _ar40 - _ar36a * R40v36a[i] - _ar39k * R40v39k[i]
379
- _ar40ar = _ar40 - _ar39k * R40v39k[i]
380
- _ar39k = _ar39k * JNFactor[i]
381
- _f = _ar40r / _ar39k
383
+ if force_to_zero:
384
+ _ar36 = max(_ar36, 0)
385
+ _ar37 = max(_ar37, 0)
386
+ _ar38 = max(_ar38, 0)
387
+ _ar39 = max(_ar39, 0)
388
+ _ar40 = max(_ar40, 0)
389
+
390
+ _ar37ca = _ar37
391
+ _ar39ca = _ar37ca * R39v37ca[i]
392
+ _ar38ca = _ar37ca * R38v37ca[i]
393
+ _ar36ca = _ar37ca * R36v37ca[i]
394
+
395
+ if force_to_zero:
396
+ _ar39ca = min(_ar39ca, _ar39)
397
+ _ar38ca = min(_ar38ca, _ar38)
398
+ _ar36ca = min(_ar36ca, _ar36)
399
+
400
+ _ar39k = _ar39 - _ar39ca
401
+ _ar38k = _ar39k * R38v39k[i]
402
+ _ar40k = _ar39k * R40v39k[i]
403
+
404
+ if force_to_zero:
405
+ _ar38k = min(_ar38k, _ar38 - _ar38ca)
406
+ _ar40k = min(_ar40k, _ar40)
407
+
408
+ _ar38res = _ar38 - _ar38k - _ar38ca
409
+ _ar36res = _ar36 - _ar36ca
410
+
411
+ if force_to_zero and _ar38res <= 0:
412
+ _ar36cl = _ar38cl = _ar38a= 0
413
+ _ar36a = _ar36res
414
+ else:
415
+ _ar36cl = (_ar36res - _ar38res / R38v36a[i]) / (
416
+ 1 - 1 / (R36v38clp[i] * (1 - exp(-1 * L36cl[i] * stand_time_year)) * R38v36a[i]))
417
+ if force_to_zero:
418
+ _ar36cl = min(max(_ar36cl, 0), _ar36res)
419
+
420
+ _ar36a = _ar36res - _ar36cl
421
+ _ar38cl = _ar36cl / (R36v38clp[i] * (1 - exp(-1 * L36cl[i] * stand_time_year)))
422
+ if force_to_zero:
423
+ _ar38cl = min(max(_ar38cl, 0), _ar38res)
424
+ _ar38a = _ar38res - _ar38cl
425
+
426
+ _ar40ar = _ar40 - _ar40k
427
+ _ar40a = _ar36a * R40v36a[i]
428
+
429
+ if force_to_zero:
430
+ _ar40a = min(_ar40a, _ar40ar)
431
+
432
+ _ar40r = _ar40ar - _ar40a
433
+
434
+ factor = JNFactor[i]
435
+
382
436
  i += 1
383
- # yield _f, _ar36, _ar37, _ar38, _ar39, _ar40, _ar36a, _ar37ca, _ar39k, _ar40r, _ar36cl
384
- yield _f, _ar36a, _ar39k, _ar40ar
385
-
386
- simulation = do_simulation()
387
- F = []
388
- ar36 = []
389
- ar37 = []
390
- ar38 = []
391
- ar39 = []
392
- ar40 = []
393
-
394
- ar36a = []
395
- ar37ca = []
396
- ar39k = []
397
- ar40r = []
398
- ar36cl = []
399
-
400
- nor_x = []
401
- nor_y = []
402
- inv_x = []
403
- inv_y = []
404
- for each in simulation:
405
- F.append(each[0])
406
- nor_x.append(each[2] / each[1])
407
- nor_y.append(each[3] / each[1])
408
- inv_x.append(each[2] / each[3])
409
- inv_y.append(each[1] / each[3])
410
- # ar36.append(each[1])
411
- # ar37.append(each[2])
412
- # ar38.append(each[3])
413
- # ar39.append(each[4])
414
- # ar40.append(each[5])
415
- # ar36a.append(each[6])
416
- # ar37ca.append(each[7])
417
- # ar39k.append(each[8])
418
- # ar40r.append(each[9])
419
- # ar36cl.append(each[10])
420
-
421
- print(f"{np.mean(F) = }, {np.std(F) = }")
437
+
438
+ yield _ar36a, 0, _ar36ca, _ar36cl, _ar37ca, _ar38cl, _ar38a, 0, _ar38k, _ar38ca, _ar39k, _ar39ca, _ar40r, _ar40a, 0, _ar40k, \
439
+ (_ar39k * factor) / _ar36a, _ar40ar / _ar36a, \
440
+ (_ar39k * factor) / _ar40ar, _ar36a / _ar40ar, \
441
+ (_ar39k * factor) / _ar38cl, _ar40r / _ar38cl, \
442
+ (_ar39k * factor) / _ar40r, _ar38cl / _ar40r, \
443
+ _ar38cl / (_ar39k * factor), _ar40r / (_ar39k * factor), \
444
+ _ar36res / _ar40ar, _ar38res / _ar40ar, (_ar39k * factor) / _ar40ar, \
445
+ _ar36, _ar37, _ar38, _ar39, _ar40
446
+
447
+ data = np.array(list(do_simulation()))
448
+ means = data.mean(axis=0)
449
+ stds = data.std(axis=0)
450
+ phi_nor = np.cov(data[:,16:18].T)[0, 1] / (np.dot(*stds[16:18]))
451
+ phi_inv = np.cov(data[:,18:20].T)[0, 1] / (np.dot(*stds[18:20]))
452
+ phi_cl1 = np.cov(data[:,20:22].T)[0, 1] / (np.dot(*stds[20:22]))
453
+ phi_cl2 = np.cov(data[:,22:24].T)[0, 1] / (np.dot(*stds[22:24]))
454
+ phi_cl3 = np.cov(data[:,24:26].T)[0, 1] / (np.dot(*stds[24:26]))
455
+ three_d_cov = np.cov(data[:,26:29].T)
456
+ phi_3d1 = three_d_cov[0, 1] / (np.dot(*stds[26:28]))
457
+ phi_3d2 = three_d_cov[0, 2] / (np.dot(*stds[26:29:2]))
458
+ phi_3d3 = three_d_cov[1, 2] / (np.dot(*stds[27:29]))
459
+
460
+ degas_data = np.column_stack((means[0:16], stds[0:16])).ravel()
461
+ nor_iso = np.append(np.column_stack((means[16:18], stds[16:18])).ravel(), [phi_nor, np.nan])
462
+ inv_iso = np.append(np.column_stack((means[18:20], stds[18:20])).ravel(), [phi_inv, np.nan])
463
+ cl1_iso = np.append(np.column_stack((means[20:22], stds[20:22])).ravel(), [phi_cl1, np.nan])
464
+ cl2_iso = np.append(np.column_stack((means[22:24], stds[22:24])).ravel(), [phi_cl2, np.nan])
465
+ cl3_iso = np.append(np.column_stack((means[24:26], stds[24:26])).ravel(), [phi_cl3, np.nan])
466
+ threed_iso = np.append(np.column_stack((means[26:29], stds[26:29])).ravel(), [phi_3d1, phi_3d2, phi_3d3])
467
+ corrected_data = np.column_stack((means[29:34], stds[29:34])).ravel()
468
+
469
+ F = np.append(means[25], stds[25])
470
+
471
+ return *F, *degas_data, *nor_iso, *inv_iso, *cl1_iso, *cl2_iso, *cl3_iso, *threed_iso, *corrected_data
422
472
 
423
473
  # print("F = {0} ± {1}".format(np.mean(F), np.std(F)))
424
474
  #
@@ -455,11 +505,7 @@ def Monte_Carlo_F(ar40m: Tuple[float, float], ar39m: Tuple[float, float], ar38m:
455
505
  # with open("ar40r.txt", 'w') as f: # save serialized json data to a readable text
456
506
  # f.writelines("\n".join([str(i) for i in ar40r]))
457
507
  # F, sF,
458
- return np.mean(F), np.std(F), \
459
- np.mean(nor_x), np.std(nor_x), np.mean(nor_y), np.std(nor_y), \
460
- np.cov(nor_x, nor_y)[0][1] / (np.std(nor_x) * np.std(nor_y)), \
461
- np.mean(inv_x), np.std(inv_x), np.mean(inv_y), np.std(inv_y), \
462
- np.cov(inv_x, inv_y)[0][1] / (np.std(inv_x) * np.std(inv_y))
508
+
463
509
 
464
510
 
465
511
 
ararpy/calc/plot.py CHANGED
@@ -53,9 +53,8 @@ def get_axis_scale(data: list, count=6, increment=None, extra_count=0, min_inter
53
53
  str(decimal.Decimal(int(interval / mag // min_interval) + min_interval) * decimal.Decimal(str(mag))))
54
54
  else:
55
55
  increment = decimal.Decimal(increment)
56
- start = decimal.Decimal(0)
56
+ start = decimal.Decimal(_min) // increment * increment
57
57
  if _min < 0:
58
- start = -increment
59
58
  while start > _min:
60
59
  start -= increment
61
60
  else:
ararpy/calc/raw_funcs.py CHANGED
@@ -29,6 +29,9 @@ def get_raw_data_regression_results(points_data, unselected: list = None):
29
29
  -------
30
30
 
31
31
  """
32
+ def power(a0, a1):
33
+ # return regression.power(a0, a1)
34
+ raise ValueError("Deprecated regression")
32
35
  # if unselected is None:
33
36
  # unselected = []
34
37
  # linesData = []
@@ -36,12 +39,12 @@ def get_raw_data_regression_results(points_data, unselected: list = None):
36
39
  # un_x = transpose(unselected)[0] if is_twoD(unselected) else []
37
40
  reg_handler = [
38
41
  regression.linest, regression.quadratic, regression.exponential,
39
- regression.power, regression.average]
42
+ power, regression.average]
40
43
  # size = 50
41
44
  # lines_x = [(max(x + un_x) - 0) / size * i for i in range(size + 1)]
45
+ x, y = transpose(points_data, ignore=False)
42
46
  for i in range(len(reg_handler)):
43
47
  try:
44
- x, y = transpose(points_data, ignore=False)
45
48
  res = reg_handler[i](a0=y, a1=x)
46
49
  # line_data = transpose([lines_x, res[7](lines_x)])
47
50
  line_results = res[0:4]
@@ -69,3 +72,39 @@ def get_raw_data_regression_results(points_data, unselected: list = None):
69
72
  regCoeffs.append(reg_coeffs)
70
73
  return None, linesResults, regCoeffs
71
74
 
75
+
76
+ def get_regression_results(points_data, method):
77
+ """
78
+ Parameters
79
+ ----------
80
+ points_data : two dimensional list. like [[x1, y1], [x2, y2], ..., [xn, yn]]
81
+ method :
82
+
83
+ Returns
84
+ -------
85
+
86
+ """
87
+ linesResults, regCoeffs = [], []
88
+ x, y = transpose(points_data, ignore=False)
89
+ try:
90
+ res = method(a0=y, a1=x)
91
+ line_results = res[0:4]
92
+ reg_coeffs = res[5]
93
+ if any(np.isnan(line_results)):
94
+ raise ValueError
95
+ if abs(res[0] - min(y)) > 5 * (max(y) - min(y)):
96
+ raise ValueError
97
+ except RuntimeError:
98
+ line_data, line_results, reg_coeffs = [], ['RuntimeError', np.nan, np.nan, np.nan, ], []
99
+ except np.linalg.LinAlgError:
100
+ line_data, line_results, reg_coeffs = [], ['MatrixError', np.nan, np.nan, np.nan, ], []
101
+ except TypeError or IndexError:
102
+ line_data, line_results, reg_coeffs = [], ['NotEnoughPoints', np.nan, np.nan, np.nan, ], []
103
+ except ZeroDivisionError:
104
+ line_data, line_results, reg_coeffs = [], ['ZeroDivisionError', np.nan, np.nan, np.nan, ], []
105
+ except ValueError:
106
+ line_data, line_results, reg_coeffs = [], ['BadFitting', np.nan, np.nan, np.nan, ], []
107
+ except Exception as e:
108
+ line_data, line_results, reg_coeffs = [], [f'RegressionError: {e}', np.nan, np.nan, np.nan, ], []
109
+ return None, line_results, reg_coeffs
110
+