richvalues 4.2.4__tar.gz → 4.2.6__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.
- {richvalues-4.2.4 → richvalues-4.2.6}/PKG-INFO +1 -1
- {richvalues-4.2.4 → richvalues-4.2.6}/pyproject.toml +1 -1
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues/__init__.py +103 -68
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues.egg-info/PKG-INFO +1 -1
- {richvalues-4.2.4 → richvalues-4.2.6}/setup.py +1 -1
- {richvalues-4.2.4 → richvalues-4.2.6}/LICENSE +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/README.md +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues.egg-info/SOURCES.txt +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues.egg-info/dependency_links.txt +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues.egg-info/requires.txt +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/richvalues.egg-info/top_level.txt +0 -0
- {richvalues-4.2.4 → richvalues-4.2.6}/setup.cfg +0 -0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "richvalues"
|
7
|
-
version = "4.2.
|
7
|
+
version = "4.2.6"
|
8
8
|
description = "Python library for working with uncertainties and upper/lower limits"
|
9
9
|
license = {file="LICENSE"}
|
10
10
|
authors = [{name="Andrés Megías Toledano"}]
|
@@ -13,12 +13,12 @@ modification, are permitted provided that the following conditions are
|
|
13
13
|
met:
|
14
14
|
|
15
15
|
(1) Redistributions of source code must retain the above copyright
|
16
|
-
notice, this list of conditions and the following disclaimer.
|
16
|
+
notice, this list of conditions and the following disclaimer.
|
17
17
|
|
18
18
|
(2) Redistributions in binary form must reproduce the above copyright
|
19
19
|
notice, this list of conditions and the following disclaimer in
|
20
20
|
the documentation and/or other materials provided with the
|
21
|
-
distribution.
|
21
|
+
distribution.
|
22
22
|
|
23
23
|
(3) The name of the author may not be used to endorse or promote
|
24
24
|
products derived from this software without specific prior written
|
@@ -37,7 +37,7 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
37
37
|
POSSIBILITY OF SUCH DAMAGE.
|
38
38
|
"""
|
39
39
|
|
40
|
-
__version__ = '4.2.
|
40
|
+
__version__ = '4.2.6'
|
41
41
|
__author__ = 'Andrés Megías Toledano'
|
42
42
|
|
43
43
|
import copy
|
@@ -59,7 +59,7 @@ defaultparams = {
|
|
59
59
|
'size of samples': int(8e3),
|
60
60
|
'number of significant figures': 1,
|
61
61
|
'minimum exponent for scientific notation': 4,
|
62
|
-
'maximum number of decimals': 5,
|
62
|
+
'maximum number of decimals to use parenthesis': 5,
|
63
63
|
'limit for extra significant figure': 2.5,
|
64
64
|
'use extra significant figure for exact values': True,
|
65
65
|
'use extra significant figure for finite intervals': True,
|
@@ -211,7 +211,7 @@ def round_sf_unc(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
211
211
|
"""
|
212
212
|
n = set_default_value(n, 'number of significant figures')
|
213
213
|
min_exp = set_default_value(min_exp, 'minimum exponent for scientific notation')
|
214
|
-
max_dec = set_default_value(max_dec, 'maximum number of decimals')
|
214
|
+
max_dec = set_default_value(max_dec, 'maximum number of decimals to use parenthesis')
|
215
215
|
extra_sf_lim = set_default_value(extra_sf_lim, 'limit for extra significant figure')
|
216
216
|
use_exp = True
|
217
217
|
if ((float(x) > float(dx)
|
@@ -303,20 +303,29 @@ def round_sf_unc(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
303
303
|
min_exp = np.inf
|
304
304
|
y, dy = round_sf_unc(x, dx, n, min_exp, max_dec, extra_sf_lim)
|
305
305
|
y = y.replace('e+', 'e').replace('e00', 'e0')
|
306
|
-
dy = dy.replace('e+','e').replace('e00', 'e0')
|
307
|
-
d = len(y.split('e')[0].split('.')[-1])
|
308
|
-
if d > max_dec and ')' not in dy:
|
306
|
+
dy = dy.replace('e+','e').replace('e00', 'e0') .replace('(', '').replace(')', '')
|
307
|
+
d = len(y.split('e')[0].split('.')[-1]) if '.' in y else 0
|
308
|
+
if max_dec == 0 or d > max_dec and ')' not in dy:
|
309
309
|
if 'e' in y:
|
310
|
-
y,
|
310
|
+
y, exp_y = y.split('e')
|
311
311
|
dy, _ = dy.split('e')
|
312
312
|
else:
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
313
|
+
exp_y = None
|
314
|
+
if dy != '0':
|
315
|
+
d = len(y.split('.')[-1]) if '.' in y else 0
|
316
|
+
d_ = len(dy.split('.')[-1]) if '.' in dy else 0
|
317
|
+
dy_ = round_sf(float(dy)*10**(d-d_), n, 0, extra_sf_lim)
|
318
|
+
dy, exp_dy = dy_.split('e')
|
319
|
+
exp_y_ = 0 if exp_y is None else exp_y
|
320
|
+
if int(exp_y_) > int(exp_dy):
|
321
|
+
dy = round_sf(float(dy)*10**int(exp_dy), n, np.inf, extra_sf_lim)
|
322
|
+
if '.' in dy:
|
323
|
+
dy = dy.split('.')[-1]
|
324
|
+
dy = '(' + dy + ')'
|
325
|
+
else:
|
326
|
+
dy = ''
|
327
|
+
if exp_y is not None:
|
328
|
+
y = '{}e{}'.format(y, exp_y)
|
320
329
|
return y, dy
|
321
330
|
|
322
331
|
def round_sf_uncs(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
@@ -351,7 +360,7 @@ def round_sf_uncs(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
351
360
|
"""
|
352
361
|
n = set_default_value(n, 'number of significant figures')
|
353
362
|
min_exp = set_default_value(min_exp, 'minimum exponent for scientific notation')
|
354
|
-
max_dec = set_default_value(max_dec, 'maximum number of decimals')
|
363
|
+
max_dec = set_default_value(max_dec, 'maximum number of decimals to use parenthesis')
|
355
364
|
extra_sf_lim = set_default_value(extra_sf_lim, 'limit for extra significant figure')
|
356
365
|
dx1, dx2 = dx
|
357
366
|
y1, dy1 = round_sf_unc(x, dx1, n, min_exp, max_dec, extra_sf_lim)
|
@@ -580,7 +589,7 @@ class RichValue():
|
|
580
589
|
self.domain = domain
|
581
590
|
self.num_sf = defaultparams['number of significant figures']
|
582
591
|
self.min_exp = defaultparams['minimum exponent for scientific notation']
|
583
|
-
self.max_dec = defaultparams['maximum number of decimals']
|
592
|
+
self.max_dec = defaultparams['maximum number of decimals to use parenthesis']
|
584
593
|
self.extra_sf_lim = defaultparams['limit for extra significant figure']
|
585
594
|
self.pdf_info = 'default'
|
586
595
|
self.variables = variables
|
@@ -632,11 +641,11 @@ class RichValue():
|
|
632
641
|
"""Constant value."""
|
633
642
|
isconst = self.is_exact and self.domain[0] == self.domain[1]
|
634
643
|
return isconst
|
635
|
-
@property
|
644
|
+
@property
|
636
645
|
def center(self):
|
637
646
|
"""Central value."""
|
638
647
|
cent = self.main if self.is_centr else np.nan
|
639
|
-
return cent
|
648
|
+
return cent
|
640
649
|
@property
|
641
650
|
def unc_eb(self):
|
642
651
|
"""Uncertainties with shape (2,1)."""
|
@@ -663,7 +672,7 @@ class RichValue():
|
|
663
672
|
else:
|
664
673
|
s_n = [np.nan]*2
|
665
674
|
return s_n
|
666
|
-
@property
|
675
|
+
@property
|
667
676
|
def ampl(self):
|
668
677
|
"""Amplitudes."""
|
669
678
|
m, b = self.main, self.domain
|
@@ -784,7 +793,7 @@ class RichValue():
|
|
784
793
|
m = np.nanmedian(distr)
|
785
794
|
else:
|
786
795
|
m = np.nan
|
787
|
-
return m
|
796
|
+
return m
|
788
797
|
|
789
798
|
def mean(self, num_points=int(1e4), sigmas=8.):
|
790
799
|
"""Mean of the PDF of the rich value."""
|
@@ -840,7 +849,7 @@ class RichValue():
|
|
840
849
|
y = self.pdf(x)
|
841
850
|
c = np.trapz(y*x, x) if central or standarized else 0.
|
842
851
|
s = np.sqrt(np.trapz(y*(x-c)**2)) if standarized else 1.
|
843
|
-
moment = np.trapz((y*(x-c)**n)) / s**n
|
852
|
+
moment = np.trapz((y*(x-c)**n)) / s**n
|
844
853
|
else:
|
845
854
|
moment = np.nan
|
846
855
|
return moment
|
@@ -1094,7 +1103,7 @@ class RichValue():
|
|
1094
1103
|
else:
|
1095
1104
|
if is_lolim:
|
1096
1105
|
symbol = '>'
|
1097
|
-
y = int(np.floor(x)) if is_int else x
|
1106
|
+
y = int(np.floor(x)) if is_int else x
|
1098
1107
|
elif is_uplim:
|
1099
1108
|
symbol = '<'
|
1100
1109
|
y = int(np.ceil(x)) if is_int else x
|
@@ -1144,10 +1153,10 @@ class RichValue():
|
|
1144
1153
|
else:
|
1145
1154
|
if is_lolim:
|
1146
1155
|
symbol = '>'
|
1147
|
-
y = int(np.floor(x)) if is_int else x
|
1156
|
+
y = int(np.floor(x)) if is_int else x
|
1148
1157
|
elif is_uplim:
|
1149
1158
|
symbol = '<'
|
1150
|
-
y = int(np.ceil(x)) if is_int else x
|
1159
|
+
y = int(np.ceil(x)) if is_int else x
|
1151
1160
|
y = round_sf(y, n, min_exp, extra_sf_lim)
|
1152
1161
|
if 'e' in y:
|
1153
1162
|
y, a = y.split('e')
|
@@ -1215,6 +1224,7 @@ class RichValue():
|
|
1215
1224
|
rvalue = RichValue(x, dx, domain=domain, is_int=self.is_int)
|
1216
1225
|
rvalue.num_sf = self.num_sf
|
1217
1226
|
rvalue.min_exp = self.min_exp
|
1227
|
+
rvalue.max_dec = self.max_dec
|
1218
1228
|
rvalue.extra_sf_lim = self.extra_sf_lim
|
1219
1229
|
rvalue.variables = self.variables
|
1220
1230
|
expression = self.expression
|
@@ -1253,6 +1263,7 @@ class RichValue():
|
|
1253
1263
|
rvalue.domain[0] = max(0, rvalue.domain[0])
|
1254
1264
|
rvalue.num_sf = self.num_sf
|
1255
1265
|
rvalue.min_exp = self.min_exp
|
1266
|
+
rvalue.max_dec = self.max_dec
|
1256
1267
|
rvalue.extra_sf_lim = self.extra_sf_lim
|
1257
1268
|
rvalue.variables = self.variables
|
1258
1269
|
rvalue.expression = 'abs({})'.format(self.expression)
|
@@ -1431,7 +1442,7 @@ class RichValue():
|
|
1431
1442
|
if domain[0] > 0 and other_.sign() != -1:
|
1432
1443
|
domain[0] = 0
|
1433
1444
|
if domain[1] < 0 and other_.sign() != 1:
|
1434
|
-
domain[1] = 0
|
1445
|
+
domain[1] = 0
|
1435
1446
|
rvalue = function_with_rich_values('{}%{}', [self, other_],
|
1436
1447
|
domain=domain, is_domain_cyclic=True)
|
1437
1448
|
return rvalue
|
@@ -1498,6 +1509,7 @@ class RichValue():
|
|
1498
1509
|
rvalue = RichValue(np.nan)
|
1499
1510
|
rvalue.num_sf = self.num_sf
|
1500
1511
|
rvalue.min_exp = self.min_exp
|
1512
|
+
rvalue.max_dec = self.max_dec
|
1501
1513
|
rvalue.extra_sf_lim = self.extra_sf_lim
|
1502
1514
|
else:
|
1503
1515
|
vars_str = ','.join(variables)
|
@@ -1546,7 +1558,7 @@ class RichValue():
|
|
1546
1558
|
x = [x]
|
1547
1559
|
x = np.array(x)
|
1548
1560
|
y = np.zeros(len(x))
|
1549
|
-
if self.is_exact:
|
1561
|
+
if self.is_exact:
|
1550
1562
|
ind = np.argmin(abs(x - main))
|
1551
1563
|
if hasattr(ind, '__iter__'):
|
1552
1564
|
ind = ind[0]
|
@@ -1607,7 +1619,7 @@ class RichValue():
|
|
1607
1619
|
if not self.is_lim:
|
1608
1620
|
distr = general_distribution(main, unc, domain, N)
|
1609
1621
|
else:
|
1610
|
-
x1, x2 = self.interval()
|
1622
|
+
x1, x2 = self.interval()
|
1611
1623
|
distr = loguniform_distribution(x1, x2, N)
|
1612
1624
|
elif not is_finite_interv and all(np.isinf(unc)):
|
1613
1625
|
distr = loguniform_distribution(-np.inf, np.inf, N)
|
@@ -1857,17 +1869,17 @@ class RichArray(np.ndarray):
|
|
1857
1869
|
return np.array([x.main for x in self.flat]).reshape(self.shape)
|
1858
1870
|
@property
|
1859
1871
|
def uncs(self):
|
1860
|
-
return np.array([x.unc for x in self.flat]).reshape([*self.shape,2])
|
1872
|
+
return np.array([x.unc for x in self.flat]).reshape([*self.shape,2])
|
1861
1873
|
@property
|
1862
1874
|
def are_lolims(self):
|
1863
1875
|
return np.array([x.is_lolim for x in self.flat]).reshape(self.shape)
|
1864
1876
|
@property
|
1865
1877
|
def are_uplims(self):
|
1866
|
-
return np.array([x.is_uplim for x in self.flat]).reshape(self.shape)
|
1878
|
+
return np.array([x.is_uplim for x in self.flat]).reshape(self.shape)
|
1867
1879
|
@property
|
1868
1880
|
def are_ranges(self):
|
1869
1881
|
return np.array([x.is_range for x in self.flat]).reshape(self.shape)
|
1870
|
-
@property
|
1882
|
+
@property
|
1871
1883
|
def domains(self):
|
1872
1884
|
return np.array([x.domain for x in self.flat]).reshape([*self.shape,2])
|
1873
1885
|
@property
|
@@ -1908,7 +1920,7 @@ class RichArray(np.ndarray):
|
|
1908
1920
|
return np.array([x.is_inf for x in self.flat]).reshape(self.shape)
|
1909
1921
|
@property
|
1910
1922
|
def centers(self):
|
1911
|
-
return np.array([x.center for x in self.flat]).reshape(self.shape)
|
1923
|
+
return np.array([x.center for x in self.flat]).reshape(self.shape)
|
1912
1924
|
@property
|
1913
1925
|
def rel_uncs(self):
|
1914
1926
|
return (np.array([x.rel_unc for x in self.flat])
|
@@ -1982,36 +1994,36 @@ class RichArray(np.ndarray):
|
|
1982
1994
|
|
1983
1995
|
def medians(self, num_points=None):
|
1984
1996
|
return np.array([x.median(num_points)
|
1985
|
-
for x in self.flat]).reshape(self.shape)
|
1997
|
+
for x in self.flat]).reshape(self.shape)
|
1986
1998
|
|
1987
1999
|
def means(self, num_points=int(1e4), sigmas=8.):
|
1988
2000
|
return np.array([x.mean(num_points, sigmas)
|
1989
|
-
for x in self.flat]).reshape(self.shape)
|
2001
|
+
for x in self.flat]).reshape(self.shape)
|
1990
2002
|
|
1991
2003
|
def modes(self, num_points=int(1e4), sigmas=8.):
|
1992
2004
|
return np.array([x.mode(num_points, sigmas)
|
1993
|
-
for x in self.flat]).reshape(self.shape)
|
2005
|
+
for x in self.flat]).reshape(self.shape)
|
1994
2006
|
|
1995
2007
|
def variances(self, num_points=int(1e4), sigmas=8.):
|
1996
2008
|
return np.array([x.var(num_points, sigmas)
|
1997
|
-
for x in self.flat]).reshape(self.shape)
|
2009
|
+
for x in self.flat]).reshape(self.shape)
|
1998
2010
|
|
1999
2011
|
def stds(self, num_points=int(1e4), sigmas=8.):
|
2000
2012
|
return np.array([x.std(num_points, sigmas)
|
2001
|
-
for x in self.flat]).reshape(self.shape)
|
2013
|
+
for x in self.flat]).reshape(self.shape)
|
2002
2014
|
|
2003
2015
|
def moments(self, n, central=True, standarized=False):
|
2004
2016
|
return np.array([x.moments(n, central, standarized)
|
2005
|
-
for x in self.flat]).reshape(self.shape)
|
2017
|
+
for x in self.flat]).reshape(self.shape)
|
2006
2018
|
|
2007
2019
|
def set_params(self, params):
|
2008
2020
|
"""Set the rich value parameters of each entry of the rich array."""
|
2009
2021
|
abbreviations = {'is integer': 'is_int',
|
2010
2022
|
'number of significant figures': 'num_sf',
|
2011
2023
|
'minimum exponent for scientific notation': 'min_exp',
|
2012
|
-
'maximum number of decimals': 'max_dec',
|
2024
|
+
'maximum number of decimals to use parenthesis': 'max_dec',
|
2013
2025
|
'limit for extra significant figure': 'extra_sf_lim'}
|
2014
|
-
attributes = ['domain'] + list(abbreviations.values())
|
2026
|
+
attributes = ['domain'] + list(abbreviations.values())
|
2015
2027
|
for entry in abbreviations:
|
2016
2028
|
name = abbreviations[entry]
|
2017
2029
|
if entry in params:
|
@@ -2163,7 +2175,7 @@ class RichDataFrame(pd.DataFrame):
|
|
2163
2175
|
exec(code, {**{'self': self}, **globals()}, output)
|
2164
2176
|
return output['df']
|
2165
2177
|
|
2166
|
-
@property
|
2178
|
+
@property
|
2167
2179
|
def mains(self): return self._property('mains')
|
2168
2180
|
@property
|
2169
2181
|
def uncs(self): return self._property2('uncs')
|
@@ -2247,7 +2259,7 @@ class RichDataFrame(pd.DataFrame):
|
|
2247
2259
|
abbreviations = {'is integer': 'is_int',
|
2248
2260
|
'number of significant figures': 'num_sf',
|
2249
2261
|
'minimum exponent for scientific notation': 'min_exp',
|
2250
|
-
'maximum number of decimals': 'max_dec',
|
2262
|
+
'maximum number of decimals to use parenthesis': 'max_dec',
|
2251
2263
|
'limit for extra significant figure': 'extra_sf_lim'}
|
2252
2264
|
attributes = ['domain'] + list(abbreviations.values())
|
2253
2265
|
for entry in abbreviations:
|
@@ -2595,7 +2607,7 @@ class ComplexRichValue():
|
|
2595
2607
|
Parameters
|
2596
2608
|
----------
|
2597
2609
|
real : rich value
|
2598
|
-
Real part of the complex rich value.
|
2610
|
+
Real part of the complex rich value.
|
2599
2611
|
imag : rich value
|
2600
2612
|
Imaginary part of the complex rich value
|
2601
2613
|
"""
|
@@ -2676,14 +2688,14 @@ class ComplexRichValue():
|
|
2676
2688
|
self.imag.num_sf = x
|
2677
2689
|
|
2678
2690
|
@property
|
2679
|
-
def min_exp(self): return round(np.mean([self.real.min_exp, self.imag.min_exp]))
|
2691
|
+
def min_exp(self): return round(np.mean([self.real.min_exp, self.imag.min_exp]))
|
2680
2692
|
@min_exp.setter
|
2681
2693
|
def min_exp(self, x):
|
2682
2694
|
self.real.min_exp = x
|
2683
2695
|
self.imag.min_exp = x
|
2684
2696
|
|
2685
2697
|
@property
|
2686
|
-
def max_dec(self): return min(self.real.max_dec, self.imag.max_dec)
|
2698
|
+
def max_dec(self): return min(self.real.max_dec, self.imag.max_dec)
|
2687
2699
|
@max_dec.setter
|
2688
2700
|
def max_dec(self, x):
|
2689
2701
|
self.real.max_dec = x
|
@@ -2723,7 +2735,7 @@ class ComplexRichValue():
|
|
2723
2735
|
def main(self):
|
2724
2736
|
"""Main value."""
|
2725
2737
|
x = self.real.main + 1j*self.imag.main
|
2726
|
-
return x
|
2738
|
+
return x
|
2727
2739
|
|
2728
2740
|
@property
|
2729
2741
|
def unc(self):
|
@@ -2943,7 +2955,7 @@ class ComplexRichValue():
|
|
2943
2955
|
"""Apply a function to the rich value"""
|
2944
2956
|
return function_with_rich_values(function, self, **kwargs)
|
2945
2957
|
|
2946
|
-
# Instance variable acronyms.
|
2958
|
+
# Instance variable acronyms.
|
2947
2959
|
|
2948
2960
|
@property
|
2949
2961
|
def real_part(self): return self.real
|
@@ -2988,6 +3000,7 @@ def add_rich_values(x, y):
|
|
2988
3000
|
"""Sum two rich values to get a new one."""
|
2989
3001
|
num_sf = min(x.num_sf, y.num_sf)
|
2990
3002
|
min_exp = round(np.mean([x.min_exp, y.min_exp]))
|
3003
|
+
max_dec = round(np.mean([x.max_dec, y.max_dec]))
|
2991
3004
|
extra_sf_lim = max(x.extra_sf_lim, y.extra_sf_lim)
|
2992
3005
|
is_int = x.is_int and y.is_int
|
2993
3006
|
domain = [x.domain[0] + y.domain[0], x.domain[1] + y.domain[1]]
|
@@ -3005,6 +3018,7 @@ def add_rich_values(x, y):
|
|
3005
3018
|
is_vectorizable=True)
|
3006
3019
|
z.num_sf = num_sf
|
3007
3020
|
z.min_exp = min_exp
|
3021
|
+
z.max_dec = max_dec
|
3008
3022
|
z.extra_sf_lim = extra_sf_lim
|
3009
3023
|
return z
|
3010
3024
|
|
@@ -3012,6 +3026,7 @@ def multiply_rich_values(x, y):
|
|
3012
3026
|
"""Multiply two rich values to get a new one."""
|
3013
3027
|
num_sf = min(x.num_sf, y.num_sf)
|
3014
3028
|
min_exp = round(np.mean([x.min_exp, y.min_exp]))
|
3029
|
+
max_dec = round(np.mean([x.max_dec, y.max_dec]))
|
3015
3030
|
extra_sf_lim = max(x.extra_sf_lim, y.extra_sf_lim)
|
3016
3031
|
is_int = x.is_int and y.is_int
|
3017
3032
|
domain = propagate_domain(x.domain, y.domain, lambda a,b: a*b)
|
@@ -3030,6 +3045,7 @@ def multiply_rich_values(x, y):
|
|
3030
3045
|
is_vectorizable=True)
|
3031
3046
|
z.num_sf = num_sf
|
3032
3047
|
z.min_exp = min_exp
|
3048
|
+
z.max_dec = max_dec
|
3033
3049
|
z.extra_sf_lim = extra_sf_lim
|
3034
3050
|
return z
|
3035
3051
|
|
@@ -3037,6 +3053,7 @@ def divide_rich_values(x, y):
|
|
3037
3053
|
"""Divide two rich values to get a new one."""
|
3038
3054
|
num_sf = min(x.num_sf, y.num_sf)
|
3039
3055
|
min_exp = round(np.mean([x.min_exp, y.min_exp]))
|
3056
|
+
max_dec = round(np.mean([x.max_dec, y.max_dec]))
|
3040
3057
|
extra_sf_lim = max(x.extra_sf_lim, y.extra_sf_lim)
|
3041
3058
|
is_int = x.is_int and y.is_int
|
3042
3059
|
domain = propagate_domain(x.domain, y.domain, lambda a,b: a/b)
|
@@ -3078,6 +3095,7 @@ def divide_rich_values(x, y):
|
|
3078
3095
|
is_vectorizable=True, sigmas=sigmas)
|
3079
3096
|
z.num_sf = num_sf
|
3080
3097
|
z.min_exp = min_exp
|
3098
|
+
z.max_dec = max_dec
|
3081
3099
|
z.extra_sf_lim = extra_sf_lim
|
3082
3100
|
return z
|
3083
3101
|
|
@@ -3211,7 +3229,8 @@ def less_equiv(x, y, sigmas_interval=None, sigmas_overlap=None):
|
|
3211
3229
|
return output
|
3212
3230
|
|
3213
3231
|
def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
3214
|
-
consider_intervs=True,
|
3232
|
+
consider_intervs=True, use_default_max_dec=False,
|
3233
|
+
use_default_extra_sf_lim=False):
|
3215
3234
|
"""
|
3216
3235
|
Convert the input text to a rich value.
|
3217
3236
|
|
@@ -3233,6 +3252,10 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3233
3252
|
If the PDF is given, this variable determines if we consider the
|
3234
3253
|
possibility that the rich value is an upper/lower limit or a finite
|
3235
3254
|
interval of values. By default, it is True.
|
3255
|
+
use_default_max_dec : bool, optional
|
3256
|
+
If True, the default maximum number of decimals to show uncertainties
|
3257
|
+
between parenthesis will be used instead of inferring it from the input
|
3258
|
+
text. This will reduce the computation time a little bit.
|
3236
3259
|
use_default_extra_sf_lim : bool, optional
|
3237
3260
|
If True, the default limit for extra significant figure will be used
|
3238
3261
|
instead of inferring it from the input text. This will reduce the
|
@@ -3258,6 +3281,7 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3258
3281
|
|
3259
3282
|
input_domain = copy.copy(domain)
|
3260
3283
|
default_num_sf = defaultparams['number of significant figures']
|
3284
|
+
default_max_dec = defaultparams['maximum number of decimals to use parenthesis']
|
3261
3285
|
default_extra_sf_lim = defaultparams['limit for extra significant figure']
|
3262
3286
|
abbreviations = {'inf': 'np.inf', 'tau': 'math.tau', 'pi': 'np.pi',
|
3263
3287
|
'nan': 'np.nan', 'NaN': 'np.nan', 'none': 'np.nan'}
|
@@ -3287,7 +3311,7 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3287
3311
|
domain = read_domain(text)
|
3288
3312
|
if domain is not None:
|
3289
3313
|
text = text.split('[')[0][:-1]
|
3290
|
-
if not '--' in text:
|
3314
|
+
if not '--' in text:
|
3291
3315
|
if text.startswith('+'):
|
3292
3316
|
text = text[1:]
|
3293
3317
|
if 'e' in text:
|
@@ -3341,8 +3365,8 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3341
3365
|
d = len(x.split('.')[1]) if '.' in x else 0
|
3342
3366
|
d1 = len(dx1.split('.')[1]) if '.' in dx1 else 0
|
3343
3367
|
d2 = len(dx1.split('.')[1]) if '.' in dx2 else 0
|
3344
|
-
dx1 =
|
3345
|
-
dx2 =
|
3368
|
+
dx1 = str(float(dx1)*10**(-(d-d1)))
|
3369
|
+
dx2 = str(float(dx2)*10**(-(d-d2)))
|
3346
3370
|
elif '+/-' in text:
|
3347
3371
|
x, dx = x_dx.split('+/-')
|
3348
3372
|
text = '{}-{}+{} {}'.format(x, dx, dx, e)
|
@@ -3370,6 +3394,11 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3370
3394
|
x = parse_value(x)
|
3371
3395
|
dx1 = parse_value(dx1)
|
3372
3396
|
dx2 = parse_value(dx2)
|
3397
|
+
if not use_default_max_dec:
|
3398
|
+
num_dec = len(x.split('.')[1].split('e')[0]) if '.' in x else 0
|
3399
|
+
max_dec = num_dec - 1
|
3400
|
+
else:
|
3401
|
+
max_dec = default_max_dec
|
3373
3402
|
if not use_default_extra_sf_lim:
|
3374
3403
|
if (not (is_lolim or is_uplim)
|
3375
3404
|
and not (eval(dx1) == eval(dx2) == 0)):
|
@@ -3397,11 +3426,11 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3397
3426
|
if eval(dx1) == eval(dx2) == 0:
|
3398
3427
|
extra_sf_lim = 1 - 1e-8
|
3399
3428
|
else:
|
3400
|
-
extra_sf_lim = default_extra_sf_lim
|
3429
|
+
extra_sf_lim = default_extra_sf_lim
|
3401
3430
|
base = float('{:e}'.format(eval(val)).split('e')[0])
|
3402
3431
|
if base <= default_extra_sf_lim:
|
3403
3432
|
if num_sf < default_num_sf + 1:
|
3404
|
-
extra_sf_lim = base - 1e-8
|
3433
|
+
extra_sf_lim = base - 1e-8
|
3405
3434
|
else:
|
3406
3435
|
extra_sf_lim = default_extra_sf_lim
|
3407
3436
|
x = x.replace('e0','')
|
@@ -3409,31 +3438,33 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3409
3438
|
unc = [eval(dx1), eval(dx2)]
|
3410
3439
|
is_range = False
|
3411
3440
|
if domain is None and np.isfinite(main) and unc[0] == 0. == unc[1]:
|
3412
|
-
domain = [main]*2
|
3441
|
+
domain = [main]*2
|
3413
3442
|
else:
|
3414
3443
|
text = text.replace(' --','--').replace('-- ','--')
|
3415
3444
|
text1, text2 = text.split('--')
|
3416
|
-
x1, _, _, _, _, _, me1, el1 = parse_as_rich_value(text1)
|
3417
|
-
x2, _, _, _, _, _, me2, el2 = parse_as_rich_value(text2)
|
3445
|
+
x1, _, _, _, _, _, me1, md1, el1 = parse_as_rich_value(text1)
|
3446
|
+
x2, _, _, _, _, _, me2, md2, el2 = parse_as_rich_value(text2)
|
3418
3447
|
main = [x1, x2]
|
3419
3448
|
unc = 0
|
3420
3449
|
is_lolim, is_uplim, is_range = False, False, True
|
3421
3450
|
min_exp = round(np.mean([me1, me2]))
|
3451
|
+
max_dec = round(np.mean([md1, md2]))
|
3422
3452
|
extra_sf_lim = max(el1, el2)
|
3423
3453
|
return (main, unc, is_lolim, is_uplim, is_range, domain,
|
3424
|
-
min_exp, extra_sf_lim)
|
3454
|
+
min_exp, max_dec, extra_sf_lim)
|
3425
3455
|
|
3426
3456
|
if pdf is None:
|
3427
3457
|
text = str(text)
|
3428
3458
|
is_complex = 'j' in text
|
3429
3459
|
if not is_complex:
|
3430
|
-
(main, unc, is_lolim, is_uplim, is_range, domain,
|
3431
|
-
|
3460
|
+
(main, unc, is_lolim, is_uplim, is_range, domain, min_exp,
|
3461
|
+
max_dec, extra_sf_lim) = parse_as_rich_value(text)
|
3432
3462
|
if input_domain is not None:
|
3433
3463
|
domain = input_domain
|
3434
3464
|
rvalue = RichValue(main, unc, is_lolim, is_uplim,
|
3435
3465
|
is_range, domain, is_int)
|
3436
3466
|
rvalue.min_exp = min_exp
|
3467
|
+
rvalue.max_dec = max_dec
|
3437
3468
|
rvalue.extra_sf_lim = extra_sf_lim
|
3438
3469
|
else:
|
3439
3470
|
if '+/-' in text or '-' in text[1:] and '+' in text[1:]:
|
@@ -3451,12 +3482,13 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None,
|
|
3451
3482
|
text_imag = text_imag[1:]
|
3452
3483
|
if text_imag[-1] == ')':
|
3453
3484
|
text_imag = text_imag[:-1]
|
3454
|
-
args = (domain, is_int, pdf,
|
3485
|
+
args = (domain, is_int, pdf,
|
3486
|
+
use_default_max_dec, use_default_extra_sf_lim)
|
3455
3487
|
real = rich_value(text_real, *args)
|
3456
3488
|
imag = rich_value(text_imag, *args)
|
3457
3489
|
else:
|
3458
3490
|
text = text.replace(' + ', '+').replace(' - ', '-')
|
3459
|
-
val = complex(text)
|
3491
|
+
val = complex(text)
|
3460
3492
|
real = val.real
|
3461
3493
|
imag = val.imag
|
3462
3494
|
rvalue = ComplexRichValue(real, imag, domain, is_int)
|
@@ -4173,7 +4205,7 @@ def loguniform_distribution(low=-1, high=1, size=1,
|
|
4173
4205
|
log_x2 = _log10(abs(x2))
|
4174
4206
|
if log_x1 < zero_log:
|
4175
4207
|
log_x1 = zero_log
|
4176
|
-
if log_x2 > inf_log:
|
4208
|
+
if log_x2 > inf_log:
|
4177
4209
|
log_x2 = inf_log
|
4178
4210
|
if x1 < 0:
|
4179
4211
|
if x2 <= 0:
|
@@ -4315,7 +4347,7 @@ def add_zero_infs(interval, zero_log, inf_log):
|
|
4315
4347
|
elif x2 > 0 and x2 > 10**inf_log:
|
4316
4348
|
x2 = np.inf
|
4317
4349
|
new_interval = [x1, x2]
|
4318
|
-
return new_interval
|
4350
|
+
return new_interval
|
4319
4351
|
def remove_zero_infs(interval, zero_log, inf_log):
|
4320
4352
|
"""Replace 0 and infinity for the given values in the input interval."""
|
4321
4353
|
x1, x2 = interval
|
@@ -4782,6 +4814,7 @@ def function_with_rich_values(function, args, unc_function=None,
|
|
4782
4814
|
len_samples = int(len(args)**0.5 * defaultparams['size of samples'])
|
4783
4815
|
num_sf = int(np.median([arg.num_sf for arg in args]))
|
4784
4816
|
min_exp = round(np.mean([arg.min_exp for arg in args]))
|
4817
|
+
max_dec = round(np.mean([arg.max_dec for arg in args]))
|
4785
4818
|
extra_sf_lim = max([arg.extra_sf_lim for arg in args])
|
4786
4819
|
|
4787
4820
|
if consider_intervs is None:
|
@@ -4919,6 +4952,7 @@ def function_with_rich_values(function, args, unc_function=None,
|
|
4919
4952
|
rval_k = ComplexRichValue(real_k, imag_k)
|
4920
4953
|
rval_k.num_sf = num_sf
|
4921
4954
|
rval_k.min_exp = min_exp
|
4955
|
+
rval_k.max_dec = max_dec
|
4922
4956
|
rval_k.extra_sf_lim = extra_sf_lim
|
4923
4957
|
output += [rval_k]
|
4924
4958
|
|
@@ -4946,6 +4980,7 @@ def function_with_rich_values(function, args, unc_function=None,
|
|
4946
4980
|
num_reps_lims, save_pdf)
|
4947
4981
|
rval_k.num_sf = num_sf
|
4948
4982
|
rval_k.min_exp = min_exp
|
4983
|
+
rval_k.max_dec = max_dec
|
4949
4984
|
rval_k.extra_sf_lim = extra_sf_lim
|
4950
4985
|
if type(input_function) is str:
|
4951
4986
|
if type(rval_k) is RichValue:
|
@@ -5427,7 +5462,7 @@ def curve_fit(x, y, function, guess, num_samples=3000,
|
|
5427
5462
|
lim1, lim2 = 0.2, 1.2
|
5428
5463
|
if disp_coef <= lim1:
|
5429
5464
|
frac1 = 1.
|
5430
|
-
elif disp_coef < lim2:
|
5465
|
+
elif disp_coef < lim2:
|
5431
5466
|
frac1 = 1. - disp_coef / (lim2 - lim1)
|
5432
5467
|
else:
|
5433
5468
|
frac1 = 0.
|
@@ -5440,7 +5475,7 @@ def curve_fit(x, y, function, guess, num_samples=3000,
|
|
5440
5475
|
result = {'parameters': params_fit, 'dispersion': dispersion, 'loss': loss,
|
5441
5476
|
'parameters samples': samples, 'dispersion sample': dispersions,
|
5442
5477
|
'loss sample': losses, 'number of fails': num_fails}
|
5443
|
-
return result
|
5478
|
+
return result
|
5444
5479
|
|
5445
5480
|
def point_fit(y, function, guess, num_samples=3000,
|
5446
5481
|
loss=lambda a,b: (a-b)**2, lim_loss_factor=4.,
|
@@ -5517,7 +5552,7 @@ def point_fit(y, function, guess, num_samples=3000,
|
|
5517
5552
|
lim1, lim2 = 0.2, 1.2
|
5518
5553
|
if disp_coef <= lim1:
|
5519
5554
|
frac1 = 1.
|
5520
|
-
elif disp_coef < lim2:
|
5555
|
+
elif disp_coef < lim2:
|
5521
5556
|
frac1 = 1. - disp_coef / (lim2 - lim1)
|
5522
5557
|
else:
|
5523
5558
|
frac1 = 0.
|
@@ -5760,4 +5795,4 @@ evaluate_distribution = evaluate_distr
|
|
5760
5795
|
center_and_uncertainties = center_and_uncs
|
5761
5796
|
is_not_a_number = is_nan = isnan
|
5762
5797
|
is_infinite = is_inf = isinf
|
5763
|
-
is_finite = is_finite = isfinite
|
5798
|
+
is_finite = is_finite = isfinite
|
@@ -5,7 +5,7 @@ with open('README.md', 'r') as file:
|
|
5
5
|
|
6
6
|
setuptools.setup(
|
7
7
|
name = 'richvalues',
|
8
|
-
version = '4.2.
|
8
|
+
version = '4.2.6',
|
9
9
|
license = 'BSD-3-Clause',
|
10
10
|
author = 'Andrés Megías Toledano',
|
11
11
|
description = 'Python library for working with uncertainties and upper/lower limits',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|