richvalues 4.2.26__tar.gz → 4.2.28__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.26/richvalues.egg-info → richvalues-4.2.28}/PKG-INFO +1 -1
- {richvalues-4.2.26 → richvalues-4.2.28}/pyproject.toml +1 -1
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues/__init__.py +288 -103
- {richvalues-4.2.26 → richvalues-4.2.28/richvalues.egg-info}/PKG-INFO +1 -1
- {richvalues-4.2.26 → richvalues-4.2.28}/setup.py +1 -1
- {richvalues-4.2.26 → richvalues-4.2.28}/LICENSE +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/README.md +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues.egg-info/.DS_Store +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues.egg-info/SOURCES.txt +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues.egg-info/dependency_links.txt +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues.egg-info/requires.txt +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/richvalues.egg-info/top_level.txt +0 -0
- {richvalues-4.2.26 → richvalues-4.2.28}/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.28"
|
|
8
8
|
description = "Python package for working with uncertainties and upper/lower limits"
|
|
9
9
|
license = {file="LICENSE"}
|
|
10
10
|
authors = [{name="Andrés Megías Toledano"}]
|
|
@@ -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.28'
|
|
41
41
|
__author__ = 'Andrés Megías Toledano'
|
|
42
42
|
|
|
43
43
|
import copy
|
|
@@ -61,10 +61,11 @@ defaultparams = {
|
|
|
61
61
|
'maximum number of decimals to use parentheses': 5,
|
|
62
62
|
'limit for extra significant figure': 2.5,
|
|
63
63
|
'use extra significant figure for exact values': True,
|
|
64
|
+
'use extra significant figure for upper/lower limits': True,
|
|
64
65
|
'use extra significant figure for integers': True,
|
|
65
66
|
'omit ones in scientific notation in LaTeX': False,
|
|
66
67
|
'always show inferior and superior uncertainties': False,
|
|
67
|
-
'multiplication symbol for scientific notation in LaTeX': '
|
|
68
|
+
'multiplication symbol for scientific notation in LaTeX': r'\cdot',
|
|
68
69
|
'sigmas to define upper/lower limits from read values': 3.,
|
|
69
70
|
'decimal exponent to define zero': -90.,
|
|
70
71
|
'decimal exponent to define infinity': 90.,
|
|
@@ -273,8 +274,13 @@ def round_sf_unc(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
|
273
274
|
else:
|
|
274
275
|
mantissa_dy, exp_dy = dy, '0'
|
|
275
276
|
m = len(mantissa_dy.split('.')[1]) if '.' in dy else 0
|
|
276
|
-
mantissa_y = ('{:.{}f}'.format(float(mantissa_y)
|
|
277
|
+
mantissa_y = ('{:.{}f}'.format(float(mantissa_y), m)
|
|
277
278
|
if x != 0 else '0')
|
|
279
|
+
if float(mantissa_y) == 10.:
|
|
280
|
+
exp_dy = int(exp_dy) + 1
|
|
281
|
+
exp_y = exp_dy
|
|
282
|
+
mantissa_y = '{:.{}f}'.format(float(mantissa_y)/10, m+1)
|
|
283
|
+
mantissa_dy = '{:.{}f}'.format(float(mantissa_dy)/10, m+1)
|
|
278
284
|
y = '{}e{}'.format(mantissa_y, exp_dy)
|
|
279
285
|
else:
|
|
280
286
|
f = 10**(-int(exp_y))
|
|
@@ -282,9 +288,6 @@ def round_sf_unc(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
|
282
288
|
np.inf, max_dec, extra_sf_lim)
|
|
283
289
|
y = '{}e{}'.format(mantissa_y, exp_y)
|
|
284
290
|
dy = '{}e{}'.format(mantissa_dy, exp_y)
|
|
285
|
-
if len(dy) > len(y)+1:
|
|
286
|
-
min_exp = np.inf
|
|
287
|
-
y, dy = round_sf_unc(x, dx, n, min_exp, max_dec, extra_sf_lim)
|
|
288
291
|
elif dx == 0:
|
|
289
292
|
y = round_sf(x, n, min_exp, extra_sf_lim)
|
|
290
293
|
dy = '0e0'
|
|
@@ -297,7 +300,7 @@ def round_sf_unc(x, dx, n=None, min_exp=None, max_dec=None, extra_sf_lim=None):
|
|
|
297
300
|
y = y.replace('e0','')
|
|
298
301
|
dy = dy.replace('e0','')
|
|
299
302
|
else:
|
|
300
|
-
if
|
|
303
|
+
if np.isfinite(x):
|
|
301
304
|
if not 'e' in y:
|
|
302
305
|
y = '{:e}'.format(float(y))
|
|
303
306
|
exp = int(y.split('e')[1]) if 'e' in y else 0
|
|
@@ -475,9 +478,11 @@ class RichValue():
|
|
|
475
478
|
integer, so when creating samples it will have integer values.
|
|
476
479
|
"""
|
|
477
480
|
|
|
481
|
+
input_main = copy.copy(main)
|
|
478
482
|
input_domain = copy.copy(domain)
|
|
479
483
|
domain = set_default_value(domain, 'domain')
|
|
480
|
-
possible_kwargs = ['
|
|
484
|
+
possible_kwargs = ['nominal', 'center', 'rel_unc', 'main_value'
|
|
485
|
+
'uncertainty', 'relative_uncertainty', 'is_integer',
|
|
481
486
|
'is_lower_limit', 'is_upper_limit', 'is_finite_range',
|
|
482
487
|
'num_sf', 'min_exp', 'max_dec', 'extra_sf_lim']
|
|
483
488
|
for kwarg in kwargs:
|
|
@@ -486,8 +491,20 @@ class RichValue():
|
|
|
486
491
|
+ " '{}'".format(kwarg))
|
|
487
492
|
if 'main_value' in kwargs:
|
|
488
493
|
main = kwargs['main_value']
|
|
494
|
+
elif 'nominal' in kwargs:
|
|
495
|
+
main = kwargs['nominal']
|
|
496
|
+
elif 'center' in kwargs:
|
|
497
|
+
main = kwargs['center']
|
|
498
|
+
is_uplim, is_lolim, is_range = False, False, False
|
|
499
|
+
if main is None:
|
|
500
|
+
raise TypeError("RichValue() missing required argument 'main'"
|
|
501
|
+
+ " (first argument)")
|
|
489
502
|
if 'uncertainty' in kwargs:
|
|
490
503
|
unc = kwargs['uncertainty']
|
|
504
|
+
elif 'relative_uncertainty' in kwargs or 'rel_unc' in kwargs:
|
|
505
|
+
rel_unc = (kwargs['rel_unc'] if 'rel_unc' in kwargs
|
|
506
|
+
else kwargs['relative_uncertainty'])
|
|
507
|
+
unc = np.array(rel_unc) * main
|
|
491
508
|
if 'is_upper_limit' in kwargs:
|
|
492
509
|
is_uplim = kwargs['is_upper_limit']
|
|
493
510
|
if 'is_lower_limit' in kwargs:
|
|
@@ -498,12 +515,6 @@ class RichValue():
|
|
|
498
515
|
is_int = kwargs['is_integer']
|
|
499
516
|
if 'show_both_uncertainties' in kwargs:
|
|
500
517
|
show_both_uncs = kwargs['show_both_uncertainties']
|
|
501
|
-
if 'center' in kwargs:
|
|
502
|
-
main = kwargs['center']
|
|
503
|
-
is_uplim, is_lolim, is_range = False, False, False
|
|
504
|
-
if main is None:
|
|
505
|
-
raise TypeError("RichValue() missing required argument 'main'"
|
|
506
|
-
+ " (first argument)")
|
|
507
518
|
|
|
508
519
|
num_sf = (kwargs['num_sf'] if 'num_sf' in kwargs
|
|
509
520
|
else defaultparams['number of significant figures'])
|
|
@@ -610,7 +621,7 @@ class RichValue():
|
|
|
610
621
|
main = np.nan
|
|
611
622
|
unc = [np.nan]*2
|
|
612
623
|
|
|
613
|
-
if type(main)
|
|
624
|
+
if type(main) is list:
|
|
614
625
|
is_lolim, is_uplim, is_range = False, False, False
|
|
615
626
|
if main[0] > main[1]:
|
|
616
627
|
raise ValueError('Upper edge of interval must be greater or'
|
|
@@ -649,7 +660,8 @@ class RichValue():
|
|
|
649
660
|
else:
|
|
650
661
|
main = np.nan
|
|
651
662
|
unc = [np.nan]*2
|
|
652
|
-
|
|
663
|
+
|
|
664
|
+
main = float(main)
|
|
653
665
|
if np.isnan(main):
|
|
654
666
|
is_uplim, is_lolim, is_range = False, False, False
|
|
655
667
|
if is_lolim or is_uplim:
|
|
@@ -727,8 +739,11 @@ class RichValue():
|
|
|
727
739
|
else:
|
|
728
740
|
main = (x1 + x2) / 2
|
|
729
741
|
unc = [(x2 - x1) / 2] * 2
|
|
730
|
-
|
|
731
|
-
|
|
742
|
+
if is_range and not np.array_equal(input_main, [main-unc[0], main+unc[1]]):
|
|
743
|
+
main = input_main
|
|
744
|
+
if is_int:
|
|
745
|
+
x1, x2 = main
|
|
746
|
+
main = [int(x1), int(x2)]
|
|
732
747
|
|
|
733
748
|
global variable_count
|
|
734
749
|
if domain[0] != domain[1]:
|
|
@@ -760,11 +775,14 @@ class RichValue():
|
|
|
760
775
|
variable_dict[expression] = self
|
|
761
776
|
|
|
762
777
|
def __setattr__(self, name, value):
|
|
763
|
-
descriptors = ['main', 'unc', 'is_uplim', 'is_lolim',
|
|
764
|
-
'is_int', 'domain']
|
|
778
|
+
descriptors = ['main', 'unc', 'is_uplim', 'is_lolim',
|
|
779
|
+
'is_range', 'is_int', 'domain']
|
|
765
780
|
internals = ['pdf_info', 'variables', 'expression']
|
|
766
781
|
display_options = ['num_sf', 'min_exp', 'max_dec', 'extra_sf_lim',
|
|
767
782
|
'show_both_uncs']
|
|
783
|
+
if name == 'rel_unc':
|
|
784
|
+
self.unc = value * self.main
|
|
785
|
+
return
|
|
768
786
|
if name in internals:
|
|
769
787
|
raise AttributeError(f'Cannot modify attribute {name}.')
|
|
770
788
|
return
|
|
@@ -778,9 +796,16 @@ class RichValue():
|
|
|
778
796
|
value = int(value) if self.is_int else float(value)
|
|
779
797
|
else:
|
|
780
798
|
super().__setattr__('unc', [np.nan]*2)
|
|
799
|
+
elif isinstance(value, (list, tuple, np.ndarray)):
|
|
800
|
+
main = (value[0] + value[1]) / 2
|
|
801
|
+
unc = [main - value[0], value[1] - main]
|
|
802
|
+
super().__setattr__('unc', unc)
|
|
803
|
+
super().__setattr__('is_range', True)
|
|
804
|
+
value = main
|
|
781
805
|
else:
|
|
782
806
|
raise TypeError('Wrong type for attribute main.')
|
|
783
|
-
elif name == 'unc' and isinstance(value,
|
|
807
|
+
elif name == 'unc' and isinstance(value,
|
|
808
|
+
(int, float, np.integer, np.floating)):
|
|
784
809
|
if value < 0:
|
|
785
810
|
raise ValueError('Uncertainty cannot be negative.')
|
|
786
811
|
value = float(abs(value))
|
|
@@ -788,28 +813,37 @@ class RichValue():
|
|
|
788
813
|
elif name in ('unc', 'domain'):
|
|
789
814
|
if isinstance(value, (tuple, list)):
|
|
790
815
|
if len(value) != 2:
|
|
791
|
-
raise ValueError(f'Wrong number of elements for
|
|
816
|
+
raise ValueError(f'Wrong number of elements for'
|
|
817
|
+
f' attribute {name}.')
|
|
792
818
|
else:
|
|
793
|
-
if not (isinstance(value[0],
|
|
794
|
-
|
|
795
|
-
|
|
819
|
+
if not (isinstance(value[0],
|
|
820
|
+
(int, float, np.integer, np.floating))
|
|
821
|
+
and isinstance(value[1],
|
|
822
|
+
(int, float, np.integer, np.floating))):
|
|
823
|
+
raise TypeError(f'Wrong type for elements of'
|
|
824
|
+
f' attribute {name}.')
|
|
796
825
|
value = [float(value[0]), float(value[1])]
|
|
797
826
|
elif isinstance(value, np.ndarray):
|
|
798
827
|
if value.size > 2:
|
|
799
|
-
raise ValueError(f'Too many elements for
|
|
828
|
+
raise ValueError(f'Too many elements for'
|
|
829
|
+
f' attribute {name}.')
|
|
800
830
|
else:
|
|
801
831
|
value = value.flatten().tolist()
|
|
802
|
-
if not (isinstance(value[0],
|
|
803
|
-
|
|
804
|
-
|
|
832
|
+
if not (isinstance(value[0],
|
|
833
|
+
(int, float, np.integer, np.floating))
|
|
834
|
+
and isinstance(value[1],
|
|
835
|
+
(int, float, np.integer, np.floating))):
|
|
836
|
+
raise TypeError('Wrong type for elements of'
|
|
837
|
+
f' attribute {name}.')
|
|
805
838
|
else:
|
|
806
839
|
raise TypeError(f'Wrong type for attribute {name}.')
|
|
807
840
|
if name == 'unc':
|
|
808
841
|
if value[1] < 0:
|
|
809
|
-
raise ValueError('Superior uncertainty cannot be
|
|
842
|
+
raise ValueError('Superior uncertainty cannot be'
|
|
843
|
+
' negaive.')
|
|
810
844
|
elif value[0] == 0. != value[1] or value[1] == 0. != value[0]:
|
|
811
|
-
raise ValueError('Superior and inferior uncertainties
|
|
812
|
-
|
|
845
|
+
raise ValueError('Superior and inferior uncertainties'
|
|
846
|
+
' must be either both zero or both non-zero.')
|
|
813
847
|
value[0] = abs(value[0])
|
|
814
848
|
if any(np.isinf(value)) or any(np.isnan(value)):
|
|
815
849
|
value = [np.nan]*2
|
|
@@ -886,6 +920,22 @@ class RichValue():
|
|
|
886
920
|
else:
|
|
887
921
|
raise AttributeError('Wrong attribute for RichValue class.')
|
|
888
922
|
|
|
923
|
+
def __getattribute__(self, name):
|
|
924
|
+
if name in ('main', 'unc'):
|
|
925
|
+
self_main = self.__dict__['main']
|
|
926
|
+
if type(self_main) is list:
|
|
927
|
+
main = (self_main[0] + self_main[1]) / 2
|
|
928
|
+
if name == 'main':
|
|
929
|
+
value = main
|
|
930
|
+
else:
|
|
931
|
+
unc = [main - self_main[0], self_main[1] - main]
|
|
932
|
+
value = unc
|
|
933
|
+
else:
|
|
934
|
+
value = super().__getattribute__(name)
|
|
935
|
+
else:
|
|
936
|
+
value = super().__getattribute__(name)
|
|
937
|
+
return value
|
|
938
|
+
|
|
889
939
|
@property
|
|
890
940
|
def is_lim(self):
|
|
891
941
|
"""Upper/lower limit."""
|
|
@@ -1063,7 +1113,8 @@ class RichValue():
|
|
|
1063
1113
|
elif self.is_lolim:
|
|
1064
1114
|
interv = [self.main, self.domain[1]]
|
|
1065
1115
|
elif self.is_range:
|
|
1066
|
-
interv =
|
|
1116
|
+
interv = (self.__dict__['main'] if type(self.__dict__['main']) is list
|
|
1117
|
+
else [self.main - self.unc[0], self.main + self.unc[1]])
|
|
1067
1118
|
else:
|
|
1068
1119
|
interv = [np.nan, np.nan]
|
|
1069
1120
|
if self.is_int:
|
|
@@ -1208,6 +1259,8 @@ class RichValue():
|
|
|
1208
1259
|
show_asterisk = defaultparams['show asterisk for rich values with custom PDF']
|
|
1209
1260
|
use_extra_sf_in_exacts = \
|
|
1210
1261
|
defaultparams['use extra significant figure for exact values']
|
|
1262
|
+
use_extra_sf_in_lims = \
|
|
1263
|
+
defaultparams['use extra significant figure for upper/lower limits']
|
|
1211
1264
|
use_extra_sf_in_ints = \
|
|
1212
1265
|
defaultparams['use extra significant figure for integers']
|
|
1213
1266
|
unc = self.unc
|
|
@@ -1238,6 +1291,13 @@ class RichValue():
|
|
|
1238
1291
|
if '.' not in y_:
|
|
1239
1292
|
y, (dy1, dy2) = y_, (dy1_, dy2_)
|
|
1240
1293
|
num_sf += 1
|
|
1294
|
+
if self.is_int:
|
|
1295
|
+
if '.' in y:
|
|
1296
|
+
y = str(round(float(y)))
|
|
1297
|
+
if '.' in dy1:
|
|
1298
|
+
dy1 = str(round(float(dy1)))
|
|
1299
|
+
if '.' in dy2:
|
|
1300
|
+
dy2 = str(round(float(dy2)))
|
|
1241
1301
|
if 'e' in y:
|
|
1242
1302
|
y, a = y.split('e')
|
|
1243
1303
|
a = int(a)
|
|
@@ -1265,6 +1325,8 @@ class RichValue():
|
|
|
1265
1325
|
if not use_exp:
|
|
1266
1326
|
text = text.replace(' e0','')
|
|
1267
1327
|
else:
|
|
1328
|
+
if use_extra_sf_in_lims:
|
|
1329
|
+
num_sf += 1
|
|
1268
1330
|
y = round_sf(x, num_sf, min_exp, extra_sf_lim)
|
|
1269
1331
|
if use_extra_sf_in_ints and '.' not in y and y.endswith('0'):
|
|
1270
1332
|
y_ = round_sf(x, num_sf+1, min_exp, extra_sf_lim)
|
|
@@ -1304,7 +1366,7 @@ class RichValue():
|
|
|
1304
1366
|
elif not self.is_range and np.isnan(self.main):
|
|
1305
1367
|
text = 'nan'
|
|
1306
1368
|
else:
|
|
1307
|
-
x1, x2 = self.
|
|
1369
|
+
x1, x2 = self.interval()
|
|
1308
1370
|
if self.is_int:
|
|
1309
1371
|
x1 = np.ceil(x1)
|
|
1310
1372
|
x2 = np.floor(x2)
|
|
@@ -1317,19 +1379,50 @@ class RichValue():
|
|
|
1317
1379
|
x.__dict__['extra_sf_lim'] = extra_sf_lim
|
|
1318
1380
|
x.__dict__['range_bound'] = True
|
|
1319
1381
|
while str(x1) == str(x2):
|
|
1320
|
-
x1.num_sf
|
|
1321
|
-
x2.num_sf
|
|
1382
|
+
x1.num_sf += 1
|
|
1383
|
+
x2.num_sf += 1
|
|
1322
1384
|
num_sf += 1
|
|
1385
|
+
if '.' in str(x1) and '.' not in str(x2):
|
|
1386
|
+
while '.' not in str(x2):
|
|
1387
|
+
x2.num_sf += 1
|
|
1323
1388
|
text = '{} -- {}'.format(x1, x2)
|
|
1389
|
+
if ' e' in text:
|
|
1390
|
+
exp1 = int(str(x1).split(' e')[1]) if 'e' in str(x1) else 0
|
|
1391
|
+
exp2 = int(str(x2).split(' e')[1]) if 'e' in str(x2) else 0
|
|
1392
|
+
exp = round((exp1 + exp2) / 2)
|
|
1393
|
+
if ((abs(exp2-exp) < min_exp//2) and (abs(exp-exp1) < min_exp//2)
|
|
1394
|
+
and abs(exp) >= min_exp):
|
|
1395
|
+
x1.main /= 10**exp
|
|
1396
|
+
x2.main /= 10**exp
|
|
1397
|
+
x1.min_exp = np.inf
|
|
1398
|
+
x2.min_exp = np.inf
|
|
1399
|
+
if '.' in str(x1) and '.' not in str(x2):
|
|
1400
|
+
while '.' not in str(x2):
|
|
1401
|
+
x2.num_sf += 1
|
|
1402
|
+
text = '({} -- {}) e{}'.format(x1, x2, exp)
|
|
1324
1403
|
if show_domain and self.domain[0] != self.domain[1] and not range_bound:
|
|
1325
1404
|
text += ' [{}, {}]'.format(self.domain[0], self.domain[1])
|
|
1326
1405
|
return text
|
|
1327
1406
|
|
|
1328
1407
|
def __repr__(self):
|
|
1408
|
+
text = self._format_as_rich_value()
|
|
1329
1409
|
if self.is_exact:
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1410
|
+
text_ = text.split(' [')[0] if '[' in text else text
|
|
1411
|
+
text_ = text_.replace(' e', 'e')
|
|
1412
|
+
if '.' in text_ and float(text_) != self.main:
|
|
1413
|
+
if ' e' in text:
|
|
1414
|
+
mantissa, exp = text.split(' ')
|
|
1415
|
+
text = f'{mantissa}... {exp}'
|
|
1416
|
+
else:
|
|
1417
|
+
text += '...'
|
|
1418
|
+
else:
|
|
1419
|
+
if float(text_) != self.main:
|
|
1420
|
+
text = str(int(self.main))
|
|
1421
|
+
elif self.is_lim:
|
|
1422
|
+
text = text.replace('< ', '<').replace('> ', '>')
|
|
1423
|
+
elif self.is_range and not text.startswith('('):
|
|
1424
|
+
text = text.replace(' e', 'e')
|
|
1425
|
+
return text
|
|
1333
1426
|
|
|
1334
1427
|
def __str__(self):
|
|
1335
1428
|
return self._format_as_rich_value()
|
|
@@ -1351,16 +1444,25 @@ class RichValue():
|
|
|
1351
1444
|
char = '<' if self.is_uplim else '>'
|
|
1352
1445
|
text = char + self.main.__format__(format_spec)
|
|
1353
1446
|
elif self.is_range:
|
|
1354
|
-
x1 = self.
|
|
1355
|
-
x2 = self.main + self.unc[1]
|
|
1447
|
+
x1, x2 = self.interval()
|
|
1356
1448
|
text = x1.__format__(format_spec) + ' -- ' + x2.__format__(format_spec)
|
|
1357
1449
|
else:
|
|
1358
1450
|
text = str(self)
|
|
1359
1451
|
return text
|
|
1452
|
+
|
|
1453
|
+
def __round__(self, n=0):
|
|
1454
|
+
rval = copy.copy(self)
|
|
1455
|
+
rval.min_exp = 0
|
|
1456
|
+
exp = int(repr(rval).split(' e')[1])
|
|
1457
|
+
n += exp
|
|
1458
|
+
rval.num_sf = n
|
|
1459
|
+
rval.min_exp = np.inf
|
|
1460
|
+
text = repr(rval)
|
|
1461
|
+
return text
|
|
1360
1462
|
|
|
1361
1463
|
def latex(self, show_dollars=True, mult_symbol=None,
|
|
1362
|
-
use_extra_sf_in_exacts=None,
|
|
1363
|
-
omit_ones_in_sci_notation=None):
|
|
1464
|
+
use_extra_sf_in_exacts=None, use_extra_sf_in_lims=None,
|
|
1465
|
+
use_extra_sf_in_ints=None, omit_ones_in_sci_notation=None):
|
|
1364
1466
|
"""Display rich value in LaTeX format."""
|
|
1365
1467
|
mult_symbol = set_default_value(mult_symbol,
|
|
1366
1468
|
'multiplication symbol for scientific notation in LaTeX')
|
|
@@ -1368,6 +1470,8 @@ class RichValue():
|
|
|
1368
1470
|
'use extra significant figure for exact values')
|
|
1369
1471
|
use_extra_sf_in_ints = set_default_value(use_extra_sf_in_ints,
|
|
1370
1472
|
'use extra significant figure for integers')
|
|
1473
|
+
use_extra_sf_in_lims = set_default_value(use_extra_sf_in_lims,
|
|
1474
|
+
'use extra significant figure for upper/lower limits')
|
|
1371
1475
|
omit_ones_in_sci_notation = set_default_value(omit_ones_in_sci_notation,
|
|
1372
1476
|
'omit ones in scientific notation in LaTeX')
|
|
1373
1477
|
if not np.isfinite(self.main):
|
|
@@ -1430,6 +1534,8 @@ class RichValue():
|
|
|
1430
1534
|
extra_sf_lim)
|
|
1431
1535
|
text = y + '_{-'+dy[0]+'}^{+'+dy[1]+'}'
|
|
1432
1536
|
else:
|
|
1537
|
+
if use_extra_sf_in_lims:
|
|
1538
|
+
num_sf += 1
|
|
1433
1539
|
y = round_sf(x, num_sf, min_exp, extra_sf_lim)
|
|
1434
1540
|
if use_extra_sf_in_ints and '.' not in y and y.endswith('0'):
|
|
1435
1541
|
y_ = round_sf(x, num_sf+1, min_exp, extra_sf_lim)
|
|
@@ -1496,9 +1602,11 @@ class RichValue():
|
|
|
1496
1602
|
text = (y + dy1 + dy2 + ' '
|
|
1497
1603
|
+ mult_symbol + ' 10^{'+a+'}')
|
|
1498
1604
|
else:
|
|
1499
|
-
text = (y + '_{-'+dy1+'}^{+'+dy2+'}
|
|
1500
|
-
+ mult_symbol + ' 10^{'+a+'}')
|
|
1605
|
+
text = (r'\left(' + y + r'\,_{-'+dy1+'}^{+'+dy2+'}'
|
|
1606
|
+
+ r' \right)' + mult_symbol + ' 10^{'+a+'}')
|
|
1501
1607
|
else:
|
|
1608
|
+
if use_extra_sf_in_lims:
|
|
1609
|
+
num_sf += 1
|
|
1502
1610
|
if self.is_lolim:
|
|
1503
1611
|
symbol = '>'
|
|
1504
1612
|
y = int(np.floor(x)) if self.is_int and a > num_sf else x
|
|
@@ -1530,7 +1638,7 @@ class RichValue():
|
|
|
1530
1638
|
if '.' not in text:
|
|
1531
1639
|
text = text.replace('1 {} '.format(mult_symbol), '')
|
|
1532
1640
|
else:
|
|
1533
|
-
x1, x2 = self.
|
|
1641
|
+
x1, x2 = self.interval()
|
|
1534
1642
|
if self.is_int:
|
|
1535
1643
|
x1 = np.ceil(x1)
|
|
1536
1644
|
x2 = np.floor(x2)
|
|
@@ -1543,11 +1651,32 @@ class RichValue():
|
|
|
1543
1651
|
x.__dict__['extra_sf_lim'] = extra_sf_lim
|
|
1544
1652
|
x.__dict__['range_bound'] = True
|
|
1545
1653
|
while str(x1) == str(x2):
|
|
1546
|
-
x1.num_sf
|
|
1547
|
-
x2.num_sf
|
|
1654
|
+
x1.num_sf += 1
|
|
1655
|
+
x2.num_sf += 1
|
|
1548
1656
|
num_sf += 1
|
|
1549
|
-
|
|
1550
|
-
|
|
1657
|
+
if '.' in str(x1) and '.' not in str(x2):
|
|
1658
|
+
while '.' not in str(x2):
|
|
1659
|
+
x2.num_sf += 1
|
|
1660
|
+
text = r'{} \,{}\, {}'.format(x1.latex(show_dollars=False),
|
|
1661
|
+
r'\text{ --- }', x2.latex(show_dollars=False))
|
|
1662
|
+
if ' e' in str(x):
|
|
1663
|
+
exp1 = int(str(x1).split(' e')[1]) if 'e' in str(x1) else 0
|
|
1664
|
+
exp2 = int(str(x2).split(' e')[1]) if 'e' in str(x2) else 0
|
|
1665
|
+
exp = round((exp1 + exp2) / 2)
|
|
1666
|
+
if ((abs(exp2-exp) <= min_exp//2) and (abs(exp-exp1) <= min_exp//2)
|
|
1667
|
+
and abs(exp) >= min_exp):
|
|
1668
|
+
x1.main /= 10**exp
|
|
1669
|
+
x2.main /= 10**exp
|
|
1670
|
+
x1.min_exp = np.inf
|
|
1671
|
+
x2.min_exp = np.inf
|
|
1672
|
+
if '.' in str(x1) and '.' not in str(x2):
|
|
1673
|
+
while '.' not in str(x2):
|
|
1674
|
+
x2.num_sf += 1
|
|
1675
|
+
text = r'({} \,{}\, {})'.format(x1.latex(show_dollars=False),
|
|
1676
|
+
r'\text{---}', x2.latex(show_dollars))
|
|
1677
|
+
text += ' ' + mult_symbol + ' 10^{'+str(exp)+'}'
|
|
1678
|
+
elif ' e' in str(x1):
|
|
1679
|
+
text = text.replace(r' \,\text', r' \text')
|
|
1551
1680
|
else:
|
|
1552
1681
|
text = (str(self.main).replace('NaN','nan').replace('nan','...')
|
|
1553
1682
|
.replace('inf','\\infty'))
|
|
@@ -1859,6 +1988,10 @@ class RichValue():
|
|
|
1859
1988
|
domain = [-np.inf, np.inf]
|
|
1860
1989
|
rvalue = RichValue(x, dx, self.is_uplim, self.is_lolim,
|
|
1861
1990
|
domain=domain, is_int=is_int)
|
|
1991
|
+
min_exp = self.min_exp
|
|
1992
|
+
num_sf = self.num_sf
|
|
1993
|
+
max_dec = self.max_dec
|
|
1994
|
+
extra_sf_lim = self.extra_sf_lim
|
|
1862
1995
|
else:
|
|
1863
1996
|
other_ = other if type(other) is RichValue else RichValue(other)
|
|
1864
1997
|
domain = None
|
|
@@ -1870,10 +2003,14 @@ class RichValue():
|
|
|
1870
2003
|
[self, other_], domain=domain)
|
|
1871
2004
|
else:
|
|
1872
2005
|
rvalue = RichValue(0., domain=domain, is_int=self.is_int)
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
2006
|
+
num_sf = int(np.mean([self.num_sf, other.num_sf]))
|
|
2007
|
+
min_exp = round(np.mean([self.min_exp, other.min_exp]))
|
|
2008
|
+
max_dec = round(np.mean([self.max_dec, other.max_dec]))
|
|
2009
|
+
extra_sf_lim = max([self.extra_sf_lim, other.extra_sf_lim])
|
|
2010
|
+
rvalue.num_sf = num_sf
|
|
2011
|
+
rvalue.min_exp = min_exp
|
|
2012
|
+
rvalue.max_dec = max_dec
|
|
2013
|
+
rvalue.extra_sf_lim = extra_sf_lim
|
|
1877
2014
|
else:
|
|
1878
2015
|
vars_str = ','.join(variables)
|
|
1879
2016
|
function = eval('lambda {}: {}'.format(vars_str, expression))
|
|
@@ -1983,22 +2120,7 @@ class RichValue():
|
|
|
1983
2120
|
if self.is_range:
|
|
1984
2121
|
sample_ = np.random.uniform(x1, x2, N)
|
|
1985
2122
|
elif np.isfinite(xrange):
|
|
1986
|
-
|
|
1987
|
-
# pdf = lambda x: truncated_normal_pdf(x,
|
|
1988
|
-
# self.domain[0],
|
|
1989
|
-
# (self.main - self.domain[0])/3,
|
|
1990
|
-
# [self.domain[0], self.main])
|
|
1991
|
-
# sample_ = sample_from_pdf(pdf, N,
|
|
1992
|
-
# [self.domain[0], self.main])
|
|
1993
|
-
sample_ = np.random.uniform(x1, x2, N)
|
|
1994
|
-
else:
|
|
1995
|
-
# pdf = lambda x: truncated_normal_pdf(x,
|
|
1996
|
-
# self.domain[1],
|
|
1997
|
-
# (self.domain[1] - self.main)/3,
|
|
1998
|
-
# [self.main, self.domain[1]])
|
|
1999
|
-
# sample_ = sample_from_pdf(pdf, N,
|
|
2000
|
-
# [self.main, self.domain[1]])
|
|
2001
|
-
sample_ = np.random.uniform(x1, x2, N)
|
|
2123
|
+
sample_ = np.random.uniform(x1, x2, N)
|
|
2002
2124
|
if N >= 20:
|
|
2003
2125
|
diffs = sample_ - x1
|
|
2004
2126
|
inds = np.argsort(diffs)
|
|
@@ -2038,6 +2160,11 @@ class RichValue():
|
|
|
2038
2160
|
@main_value.setter
|
|
2039
2161
|
def main_value(self, x): self.main = x
|
|
2040
2162
|
|
|
2163
|
+
@property
|
|
2164
|
+
def nominal(self): return self.nominal
|
|
2165
|
+
@nominal.setter
|
|
2166
|
+
def nominal(self, x): self.nominal = x
|
|
2167
|
+
|
|
2041
2168
|
@property
|
|
2042
2169
|
def uncertainty(self): return self.unc
|
|
2043
2170
|
@uncertainty.setter
|
|
@@ -2114,27 +2241,49 @@ class RichArray(np.ndarray):
|
|
|
2114
2241
|
corresponds to an integer variable. The default is False.
|
|
2115
2242
|
"""
|
|
2116
2243
|
|
|
2117
|
-
acronyms = ['
|
|
2118
|
-
|
|
2244
|
+
acronyms = ['nominals', 'centers', 'rel_uncs', 'main_values',
|
|
2245
|
+
'uncertainties', 'relative_uncertainties', 'are_integers',
|
|
2246
|
+
'are_lower_limits', 'are_upper_limits', 'are_finite_ranges']
|
|
2119
2247
|
for kwarg in kwargs:
|
|
2120
2248
|
if kwarg not in acronyms:
|
|
2121
2249
|
raise TypeError("RichArray() got an unexpected keyword argument"
|
|
2122
2250
|
+ " '{}'".format(kwarg))
|
|
2123
2251
|
if 'main_values' in kwargs:
|
|
2124
2252
|
mains = kwargs['main_values']
|
|
2253
|
+
elif 'nominals' in kwargs:
|
|
2254
|
+
mains = kwargs['nominals']
|
|
2255
|
+
elif 'centers' in kwargs:
|
|
2256
|
+
mains = kwargs['centers']
|
|
2257
|
+
are_uplims, are_lolims, are_ranges = False, False, False
|
|
2125
2258
|
if mains is None:
|
|
2126
|
-
raise TypeError("
|
|
2127
|
-
+ " (
|
|
2259
|
+
raise TypeError("RichValue() missing required argument 'mains'"
|
|
2260
|
+
+ " (first argument)")
|
|
2128
2261
|
if 'uncertainties' in kwargs:
|
|
2129
2262
|
uncs = kwargs['uncertainties']
|
|
2130
|
-
|
|
2131
|
-
|
|
2263
|
+
elif 'relative_uncertainties' in kwargs or 'rel_uncs' in kwargs:
|
|
2264
|
+
rel_uncs = (kwargs['rel_uncs'] if 'rel_uncs' in kwargs
|
|
2265
|
+
else kwargs['relative_uncertainties'])
|
|
2266
|
+
rel_uncs = np.array(rel_uncs)
|
|
2267
|
+
mains = np.array(mains)
|
|
2268
|
+
shape = mains.shape
|
|
2269
|
+
if rel_uncs.size == 1:
|
|
2270
|
+
rel_uncs = np.full((*shape, 2), rel_uncs).transpose()
|
|
2271
|
+
elif len(rel_uncs) == 2 and type(rel_uncs[0]) is not np.ndarray:
|
|
2272
|
+
rel_uncs = np.array([np.full(shape, rel_uncs[0]),
|
|
2273
|
+
np.full(shape, rel_uncs[1])])
|
|
2274
|
+
elif rel_uncs.shape == (*shape, 2):
|
|
2275
|
+
rel_uncs = rel_uncs.transpose()
|
|
2276
|
+
elif rel_uncs.shape == shape:
|
|
2277
|
+
rel_uncs = np.array([[rel_uncs]]*2).reshape((2, *shape))
|
|
2278
|
+
uncs = (rel_uncs * mains).transpose()
|
|
2132
2279
|
if 'are_upper_limits' in kwargs:
|
|
2133
|
-
|
|
2134
|
-
if '
|
|
2135
|
-
|
|
2136
|
-
if '
|
|
2137
|
-
|
|
2280
|
+
is_uplim = kwargs['are_upper_limits']
|
|
2281
|
+
if 'are_lower_limits' in kwargs:
|
|
2282
|
+
is_lolim = kwargs['are_lower_limits']
|
|
2283
|
+
if 'are_finite_range' in kwargs:
|
|
2284
|
+
is_range = kwargs['are_finite_ranges']
|
|
2285
|
+
if 'are_integer' in kwargs:
|
|
2286
|
+
is_int = kwargs['are_integers']
|
|
2138
2287
|
|
|
2139
2288
|
mains = np.array(mains)
|
|
2140
2289
|
shape = mains.shape
|
|
@@ -2373,6 +2522,17 @@ class RichArray(np.ndarray):
|
|
|
2373
2522
|
return np.array([x.moments(n, central, standarized)
|
|
2374
2523
|
for x in self.flat]).reshape(self.shape)
|
|
2375
2524
|
|
|
2525
|
+
def __setattr__(self, name, value):
|
|
2526
|
+
alt_names = {'mains': 'main', 'uncs': 'unc', 'rel_uncs': 'rel_unc',
|
|
2527
|
+
'are_uplims': 'is_uplim', 'are_lolims': 'is_lolim',
|
|
2528
|
+
'are_ranges': 'is_range', 'nums_sf': 'num_sf',
|
|
2529
|
+
'min_exps': 'min_exp', 'max_decs': 'max_dec',
|
|
2530
|
+
'extra_sf_lims': 'extra_sf_lim'}
|
|
2531
|
+
if name in alt_names.keys():
|
|
2532
|
+
name = alt_names[name]
|
|
2533
|
+
for x in self.flat:
|
|
2534
|
+
setattr(x, name, value)
|
|
2535
|
+
|
|
2376
2536
|
def set_params(self, params):
|
|
2377
2537
|
"""Set the rich value parameters of each entry of the rich array."""
|
|
2378
2538
|
abbreviations = {'is integer': 'is_int',
|
|
@@ -2433,13 +2593,16 @@ class RichArray(np.ndarray):
|
|
|
2433
2593
|
"""Apply a function to the rich array."""
|
|
2434
2594
|
return function_with_rich_arrays(function, self, **kwargs)
|
|
2435
2595
|
|
|
2436
|
-
def mean(self):
|
|
2437
|
-
return np.array(self).mean()
|
|
2596
|
+
def mean(self, axis, dtype, out, **kwargs):
|
|
2597
|
+
return np.array(self).mean(axis, dtype, out, **kwargs)
|
|
2438
2598
|
|
|
2439
2599
|
def std(self):
|
|
2440
2600
|
std_function = lambda u: (np.sum((u-u.mean())**2)/(len(self)-1))**0.5
|
|
2441
|
-
return self.function(std_function)
|
|
2442
|
-
|
|
2601
|
+
return self.function(std_function)
|
|
2602
|
+
|
|
2603
|
+
def __str__(self):
|
|
2604
|
+
text = np.array2string(self, separator=', ')
|
|
2605
|
+
return text
|
|
2443
2606
|
|
|
2444
2607
|
# Attribute synonims.
|
|
2445
2608
|
main = mains
|
|
@@ -3411,7 +3574,8 @@ def add_rich_values(x, y):
|
|
|
3411
3574
|
extra_sf_lim = max(x.extra_sf_lim, y.extra_sf_lim)
|
|
3412
3575
|
is_int = x.is_int and y.is_int
|
|
3413
3576
|
domain = [x.domain[0] + y.domain[0], x.domain[1] + y.domain[1]]
|
|
3414
|
-
if (x.is_exact or y.is_exact) and (x.is_interv or y.is_interv)
|
|
3577
|
+
if ((x.is_exact or y.is_exact) and (x.is_interv or y.is_interv)
|
|
3578
|
+
or x.is_interv and y.is_interv):
|
|
3415
3579
|
z = list(np.array(x.interval()) + np.array(y.interval()))
|
|
3416
3580
|
z = RichValue(z, domain=domain, is_int=is_int)
|
|
3417
3581
|
elif (not (x.is_interv or y.is_interv)
|
|
@@ -3450,6 +3614,8 @@ def multiply_rich_values(x, y):
|
|
|
3450
3614
|
else:
|
|
3451
3615
|
z = function_with_rich_values(lambda a,b: a*b, [x, y], domain=domain,
|
|
3452
3616
|
is_vectorizable=True)
|
|
3617
|
+
if x.is_range and y.is_centered or x.is_centered and y.is_range:
|
|
3618
|
+
z.is_range = True
|
|
3453
3619
|
z.num_sf = num_sf
|
|
3454
3620
|
z.min_exp = min_exp
|
|
3455
3621
|
z.max_dec = max_dec
|
|
@@ -3503,6 +3669,10 @@ def divide_rich_values(x, y):
|
|
|
3503
3669
|
else:
|
|
3504
3670
|
z = function_with_rich_values(lambda a,b: a/b, [x, y], domain=domain,
|
|
3505
3671
|
is_vectorizable=True)
|
|
3672
|
+
if ((x.is_range and y.is_centered or x.is_centered and y.is_range)
|
|
3673
|
+
and z.is_centered):
|
|
3674
|
+
z.main = z.interval(3.)
|
|
3675
|
+
# z.is_range = True
|
|
3506
3676
|
z.num_sf = num_sf
|
|
3507
3677
|
z.min_exp = min_exp
|
|
3508
3678
|
z.max_dec = max_dec
|
|
@@ -3750,7 +3920,7 @@ def parse_as_rich_value(text, abbreviations={}, use_default_extra_sf_lim=False):
|
|
|
3750
3920
|
dx1 = x_dx.split('-')[1]
|
|
3751
3921
|
x = sign + x
|
|
3752
3922
|
else:
|
|
3753
|
-
x = _eval(x_dx)
|
|
3923
|
+
x = str(_eval(x_dx))
|
|
3754
3924
|
dx1, dx2 = '0', '0'
|
|
3755
3925
|
if e != 'e0':
|
|
3756
3926
|
if 'e' in x:
|
|
@@ -3801,7 +3971,7 @@ def parse_as_rich_value(text, abbreviations={}, use_default_extra_sf_lim=False):
|
|
|
3801
3971
|
if mantissa <= default_extra_sf_lim:
|
|
3802
3972
|
default_num_sf = defaultparams['number of significant figures']
|
|
3803
3973
|
if num_sf < default_num_sf + 1:
|
|
3804
|
-
extra_sf_lim = mantissa
|
|
3974
|
+
extra_sf_lim = mantissa - 0.5
|
|
3805
3975
|
x = x.replace('e0', '')
|
|
3806
3976
|
main = _eval(x)
|
|
3807
3977
|
unc = [_eval(dx1), _eval(dx2)]
|
|
@@ -3809,7 +3979,13 @@ def parse_as_rich_value(text, abbreviations={}, use_default_extra_sf_lim=False):
|
|
|
3809
3979
|
min_exp = min(min_exp, default_min_exp)
|
|
3810
3980
|
else:
|
|
3811
3981
|
text = text.replace(' --','--').replace('-- ','--')
|
|
3812
|
-
|
|
3982
|
+
if text.startswith('('):
|
|
3983
|
+
group, exp = text.split(' e')
|
|
3984
|
+
text1, text2 = group[1:-1].split('--')
|
|
3985
|
+
text1 += 'e'+exp
|
|
3986
|
+
text2 += 'e'+exp
|
|
3987
|
+
else:
|
|
3988
|
+
text1, text2 = text.split('--')
|
|
3813
3989
|
x1, _, _, _, _, _, me1, md1, el1 = parse_as_rich_value(text1,
|
|
3814
3990
|
abbreviations, use_default_extra_sf_lim)
|
|
3815
3991
|
x2, _, _, _, _, _, me2, md2, el2 = parse_as_rich_value(text2,
|
|
@@ -3877,6 +4053,11 @@ def rich_value(text=None, domain=None, is_int=None, pdf=None, support=None,
|
|
|
3877
4053
|
' represent the rich value, not both.')
|
|
3878
4054
|
|
|
3879
4055
|
input_domain = copy.copy(domain)
|
|
4056
|
+
if type(input_domain) is str:
|
|
4057
|
+
if input_domain in ('p', 'pos', 'positive'):
|
|
4058
|
+
input_domain = [0., np.inf]
|
|
4059
|
+
elif input_domain in ('n', 'neg', 'negative'):
|
|
4060
|
+
input_domain = [-np.inf, 0.]
|
|
3880
4061
|
abbreviations = {'inf': 'np.inf', 'tau': 'math.tau', 'pi': 'np.pi',
|
|
3881
4062
|
'nan': 'np.nan', 'NaN': 'np.nan', 'none': 'np.nan'}
|
|
3882
4063
|
|
|
@@ -5057,28 +5238,26 @@ def evaluate_sample(sample, function=None, args=None, len_samples=None,
|
|
|
5057
5238
|
if not is_range:
|
|
5058
5239
|
probs_hr, bins_hr = np.histogram(sample, bins=60, density=True)
|
|
5059
5240
|
probs_hr /= probs_hr.max()
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
cond_hr2 = probs_hr[0] > hr2f
|
|
5063
|
-
is_lim = cond_hr1 or cond_hr2
|
|
5241
|
+
cond_hr = probs_hr[0] > 0.9 or probs_hr[-1] > 0.9
|
|
5242
|
+
is_lim = cond_hr and (x1 == domain[0] or x1 == domain[1])
|
|
5064
5243
|
if is_lim:
|
|
5065
5244
|
ord_range_b1 = magnitude_order_range([x1, median])
|
|
5066
5245
|
ord_range_b2 = magnitude_order_range([median, x2])
|
|
5067
5246
|
x1, x2 = add_zero_infs([x1, x2], zero_log-6, inf_log-6)
|
|
5068
5247
|
if (ord_range_b1 > inf_log-6 and ord_range_b2 > inf_log-6
|
|
5069
|
-
and
|
|
5248
|
+
and cond_hr):
|
|
5070
5249
|
is_lim = False
|
|
5071
5250
|
is_nan = True
|
|
5072
5251
|
if not is_lim and not is_nan:
|
|
5073
|
-
cond_lr =
|
|
5252
|
+
cond_lr = 0.5 < probs_lr[0] < 1.
|
|
5074
5253
|
interval_1s = [np.quantile(sample, 0.15865),
|
|
5075
5254
|
np.quantile(sample, 0.84135)]
|
|
5076
5255
|
ord_range_1s = magnitude_order_range(interval_1s)
|
|
5077
5256
|
ord_range_x = magnitude_order_range([x1, x2])
|
|
5078
|
-
cond_ord = (ord_range_x - ord_range_1s <
|
|
5257
|
+
cond_ord = (ord_range_x - ord_range_1s < 0.4 if x1 != x2
|
|
5079
5258
|
else False)
|
|
5080
|
-
is_range = (cond_ord or (not cond_ord and
|
|
5081
|
-
or (not cond_ord and not
|
|
5259
|
+
is_range = (cond_ord or (not cond_ord and cond_hr)
|
|
5260
|
+
or (not cond_ord and not cond_hr and cond_lr))
|
|
5082
5261
|
if not is_range:
|
|
5083
5262
|
is_centered = True
|
|
5084
5263
|
if is_lim and args is not None:
|
|
@@ -5143,7 +5322,7 @@ def evaluate_sample(sample, function=None, args=None, len_samples=None,
|
|
|
5143
5322
|
x1, x2 = add_zero_infs([x1, x2], zero_log+6, inf_log-6)
|
|
5144
5323
|
ampls = [x1 - domain[0], domain[1] - x2]
|
|
5145
5324
|
rel_ampls = np.array(ampls) / (x2 - x1)
|
|
5146
|
-
threshold =
|
|
5325
|
+
threshold = 1e-9
|
|
5147
5326
|
if rel_ampls[0] < threshold:
|
|
5148
5327
|
x1 = domain[0]
|
|
5149
5328
|
if rel_ampls[1] < threshold:
|
|
@@ -5157,6 +5336,10 @@ def evaluate_sample(sample, function=None, args=None, len_samples=None,
|
|
|
5157
5336
|
if is_centered:
|
|
5158
5337
|
if not is_exact:
|
|
5159
5338
|
main, unc = center_and_uncs(sample)
|
|
5339
|
+
asymmetry = abs(unc[1] - unc[0]) / (unc[0] + unc[1])
|
|
5340
|
+
threshold = min(0.05, 10. / np.sqrt(len_samples))
|
|
5341
|
+
if asymmetry < threshold:
|
|
5342
|
+
unc = (unc[0] + unc[1]) / 2
|
|
5160
5343
|
rvalue = RichValue(main, unc, domain=domain, is_int=is_int)
|
|
5161
5344
|
else:
|
|
5162
5345
|
rvalue = RichValue(main, unc=0., domain=domain, is_int=is_int)
|
|
@@ -5307,6 +5490,7 @@ def function_with_rich_values(function, args, len_samples=None, domain=None,
|
|
|
5307
5490
|
|
|
5308
5491
|
if len_samples is None:
|
|
5309
5492
|
len_samples = int(len(args)**0.5 * defaultparams['size of samples'])
|
|
5493
|
+
len_samples = int(len_samples)
|
|
5310
5494
|
num_sf = int(np.median([arg.num_sf for arg in args]))
|
|
5311
5495
|
min_exp = round(np.mean([arg.min_exp for arg in args]))
|
|
5312
5496
|
max_dec = round(np.mean([arg.max_dec for arg in args]))
|
|
@@ -6106,8 +6290,9 @@ def _log10(x):
|
|
|
6106
6290
|
|
|
6107
6291
|
def _eval(text):
|
|
6108
6292
|
"""Evaluate a mathematical expression."""
|
|
6109
|
-
y = eval(text, {'__builtins__': {}},
|
|
6110
|
-
|
|
6293
|
+
y = eval(text, {'__builtins__': {}},
|
|
6294
|
+
{'math': math, 'np': np, 'pi': math.pi, 'tau': math.tau,
|
|
6295
|
+
'nan': np.nan})
|
|
6111
6296
|
return y
|
|
6112
6297
|
|
|
6113
6298
|
# Abbreviations from NumPy.
|
|
@@ -6134,9 +6319,9 @@ def concatenate(arrs, **kwargs):
|
|
|
6134
6319
|
# Mathematical functions.
|
|
6135
6320
|
get_operation_function = lambda x: (function if type(x) in
|
|
6136
6321
|
(str, RichValue, ComplexRichValue) else array_function)
|
|
6137
|
-
def sqrt(x):
|
|
6322
|
+
def sqrt(x, **kwargs):
|
|
6138
6323
|
function_ = get_operation_function(x)
|
|
6139
|
-
return function_('np.sqrt({})', x, domain=[0., np.inf])
|
|
6324
|
+
return function_('np.sqrt({})', x, domain=[0., np.inf], **kwargs)
|
|
6140
6325
|
def exp(x):
|
|
6141
6326
|
function_ = get_operation_function(x)
|
|
6142
6327
|
return function_('np.exp({})', x, domain=[0., np.inf])
|
|
@@ -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.28',
|
|
9
9
|
license = 'BSD-3-Clause',
|
|
10
10
|
author = 'Andrés Megías Toledano',
|
|
11
11
|
description = 'Python package 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
|
|
File without changes
|