metrolopy 0.6.5__py3-none-any.whl → 1.0.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.
- metrolopy/__init__.py +5 -4
- metrolopy/budget.py +61 -50
- metrolopy/builtin_constants.py +903 -0
- metrolopy/constant.py +108 -104
- metrolopy/constcom.py +84 -83
- metrolopy/distributions.py +120 -39
- metrolopy/exceptions.py +7 -9
- metrolopy/fit.py +3 -3
- metrolopy/functions.py +4 -4
- metrolopy/gummy.py +571 -530
- metrolopy/indexed.py +69 -20
- metrolopy/logunit.py +1 -1
- metrolopy/mean.py +8 -9
- metrolopy/miscunits.py +21 -6
- metrolopy/nummy.py +224 -180
- metrolopy/offsetunit.py +2 -3
- metrolopy/prefixedunit.py +24 -23
- metrolopy/relunits.py +1 -2
- metrolopy/siunits.py +7 -5
- metrolopy/tests/__init__.py +6 -6
- metrolopy/tests/test_complex.py +22 -0
- metrolopy/tests/test_create.py +10 -6
- metrolopy/tests/test_gummy.py +93 -43
- metrolopy/tests/test_misc.py +4 -1
- metrolopy/tests/test_operations.py +58 -2
- metrolopy/tests/test_ubreakdown.py +6 -2
- metrolopy/ummy.py +890 -898
- metrolopy/unit.py +287 -182
- metrolopy/unitparser.py +40 -42
- metrolopy/unitutils.py +183 -159
- metrolopy/usunits.py +14 -13
- metrolopy/version.py +1 -1
- {metrolopy-0.6.5.dist-info → metrolopy-1.0.1.dist-info}/METADATA +23 -5
- metrolopy-1.0.1.dist-info/RECORD +45 -0
- metrolopy-0.6.5.dist-info/RECORD +0 -44
- {metrolopy-0.6.5.dist-info → metrolopy-1.0.1.dist-info}/WHEEL +0 -0
- {metrolopy-0.6.5.dist-info → metrolopy-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {metrolopy-0.6.5.dist-info → metrolopy-1.0.1.dist-info}/top_level.txt +0 -0
- {metrolopy-0.6.5.dist-info → metrolopy-1.0.1.dist-info}/zip-safe +0 -0
metrolopy/nummy.py
CHANGED
|
@@ -27,11 +27,12 @@ class is not intended to be used directly; rather it is utilized by the gummy
|
|
|
27
27
|
class.
|
|
28
28
|
"""
|
|
29
29
|
import numpy as np
|
|
30
|
-
from .ummy import ummy
|
|
30
|
+
from .ummy import ummy,_udict,_isscalar
|
|
31
31
|
from .distributions import (Distribution,TDist,NormalDist,MultivariateElement,
|
|
32
|
-
MultivariateDistribution,
|
|
32
|
+
MultivariateDistribution,Convolution)
|
|
33
33
|
from .exceptions import NoSimulatedDataError
|
|
34
|
-
from math import isinf,
|
|
34
|
+
from math import isinf,isnan,sqrt
|
|
35
|
+
from html import escape
|
|
35
36
|
|
|
36
37
|
def _bop(f,npf,s,b):
|
|
37
38
|
if isinstance(b,nummy):
|
|
@@ -50,6 +51,59 @@ def _uop(f,npf,s):
|
|
|
50
51
|
f._dist = Distribution.apply(npf,s._dist)
|
|
51
52
|
return f
|
|
52
53
|
|
|
54
|
+
def _getnrefs(x,fr):
|
|
55
|
+
if isinstance(x,ummy):
|
|
56
|
+
x = [x]
|
|
57
|
+
ret = set()
|
|
58
|
+
for i in x:
|
|
59
|
+
for r in x._getrefs(fr):
|
|
60
|
+
if r.dist is not None:
|
|
61
|
+
ret.add(r.dist)
|
|
62
|
+
return ret
|
|
63
|
+
|
|
64
|
+
def get_name(name,fmt,norm):
|
|
65
|
+
fmt = fmt.strip().lower()
|
|
66
|
+
if fmt not in {'unicode','html','latex','ascii'}:
|
|
67
|
+
raise ValueError('fmt "' + str(fmt) + '" is not recognized')
|
|
68
|
+
|
|
69
|
+
if name is None:
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
if isinstance(name,str):
|
|
73
|
+
name = name.strip()
|
|
74
|
+
if fmt == 'html':
|
|
75
|
+
name = escape(name)
|
|
76
|
+
if len(name) == 1:
|
|
77
|
+
name = '<i>' + name + '</i>'
|
|
78
|
+
elif fmt == 'latex':
|
|
79
|
+
sc = {
|
|
80
|
+
'&': r'\&',
|
|
81
|
+
'%': r'\%',
|
|
82
|
+
'$': r'\$',
|
|
83
|
+
'#': r'\#',
|
|
84
|
+
'_': r'\_',
|
|
85
|
+
'{': r'\{',
|
|
86
|
+
'}': r'\}',
|
|
87
|
+
'~': r'\_',
|
|
88
|
+
'^': r'\_',
|
|
89
|
+
'\\': r'\_'
|
|
90
|
+
}
|
|
91
|
+
name = ''.join(sc[c] if c in sc else c for c in name)
|
|
92
|
+
if len(name) > 1:
|
|
93
|
+
name = norm(name)
|
|
94
|
+
elif fmt == 'ascii':
|
|
95
|
+
name = ''.join(i if ord(i) < 128 else '_' for i in name)
|
|
96
|
+
return name
|
|
97
|
+
|
|
98
|
+
if fmt == 'unicode':
|
|
99
|
+
return name[0]
|
|
100
|
+
if fmt == 'html':
|
|
101
|
+
return name[1]
|
|
102
|
+
if fmt == 'latex':
|
|
103
|
+
return name[2]
|
|
104
|
+
if fmt == 'ascii':
|
|
105
|
+
return name[3]
|
|
106
|
+
|
|
53
107
|
|
|
54
108
|
class nummy(ummy):
|
|
55
109
|
# This class is not intended to be used directly and was created to contain
|
|
@@ -57,7 +111,6 @@ class nummy(ummy):
|
|
|
57
111
|
|
|
58
112
|
_cimethod = 'shortest'
|
|
59
113
|
_bayesian = False # see the gummy bayesian property
|
|
60
|
-
_fp = None
|
|
61
114
|
_nsim = None
|
|
62
115
|
|
|
63
116
|
def __init__(self,x,u=0,dof=float('inf'),utype=None,name=None):
|
|
@@ -75,37 +128,42 @@ class nummy(ummy):
|
|
|
75
128
|
if isinstance(x,MultivariateElement):
|
|
76
129
|
raise TypeError('a MultivariateElement may not be used in a gummy initializer\nuse the create static method with a MultivariateDistribution')
|
|
77
130
|
|
|
131
|
+
if utype is None:
|
|
132
|
+
utype = x.utype
|
|
133
|
+
else:
|
|
134
|
+
x.utype = utype
|
|
78
135
|
self._dist = x
|
|
79
136
|
|
|
80
137
|
if hasattr(x,'dof'):
|
|
138
|
+
ndof = x.dof
|
|
81
139
|
if nummy._bayesian:
|
|
82
140
|
u = float(x.u())*np.sqrt(x.dof/(x.dof-2))
|
|
83
|
-
dof = float('inf')
|
|
84
141
|
else:
|
|
85
142
|
u = float(x.u())
|
|
86
|
-
dof = x.dof
|
|
87
143
|
else:
|
|
88
|
-
|
|
144
|
+
ndof = float('inf')
|
|
89
145
|
u = float(x.u())
|
|
90
146
|
|
|
91
|
-
super().__init__(x.x(),u=u,dof=
|
|
147
|
+
super().__init__(x.x(),u=u,dof=ndof,utype=utype)
|
|
92
148
|
|
|
93
149
|
else:
|
|
94
150
|
super().__init__(x,u=u,dof=dof,utype=utype)
|
|
95
151
|
x = float(x)
|
|
96
|
-
u = float(self.
|
|
97
|
-
if
|
|
152
|
+
u = float(self.u)
|
|
153
|
+
if u == 0 or isnan(x) or isinf(x) or isnan(u) or isinf(u):
|
|
98
154
|
self._dist = x
|
|
99
155
|
return
|
|
100
|
-
dof
|
|
101
|
-
|
|
102
|
-
self._dist = NormalDist(x,u)
|
|
156
|
+
if isinstance(dof,_udict):
|
|
157
|
+
self._dist = None
|
|
103
158
|
else:
|
|
104
|
-
if
|
|
105
|
-
self._dist =
|
|
106
|
-
self._dof = float('inf')
|
|
159
|
+
if dof is None or dof > self.max_dof:
|
|
160
|
+
self._dist = NormalDist(x,u)
|
|
107
161
|
else:
|
|
108
|
-
|
|
162
|
+
if nummy._bayesian:
|
|
163
|
+
self._dist = TDist(x,u*np.sqrt((dof-2)/dof),dof)
|
|
164
|
+
else:
|
|
165
|
+
self._dist = TDist(x,u,dof)
|
|
166
|
+
self._dist.utype = utype
|
|
109
167
|
|
|
110
168
|
@property
|
|
111
169
|
def distribution(self):
|
|
@@ -116,31 +174,6 @@ class nummy(ummy):
|
|
|
116
174
|
"""
|
|
117
175
|
return self._dist
|
|
118
176
|
|
|
119
|
-
@property
|
|
120
|
-
def dof(self):
|
|
121
|
-
"""
|
|
122
|
-
float, read-only
|
|
123
|
-
|
|
124
|
-
Returns the number or degrees of freedom that the uncertainty of the
|
|
125
|
-
gummy is based on. If `gummy.bayesian` is set to `False`, then the Welch-
|
|
126
|
-
Satterthwaite approximation is used to calculate the effective number
|
|
127
|
-
of degrees of freedom for gummys that result from an operation between
|
|
128
|
-
two or more other gummys. A version of the Welch-Satterthwaite
|
|
129
|
-
approximation that takes into account correlations is used here, see
|
|
130
|
-
[R. Willink, Metrologia, 44, 340 (2007)]. If `gummy.bayesian` is `True`
|
|
131
|
-
then gummys that are the result from an opertaion between other gummys
|
|
132
|
-
will always have dof = float('inf').
|
|
133
|
-
"""
|
|
134
|
-
if isinf(self._dof) and hasattr(self._dist,'dof'):
|
|
135
|
-
dof = self._dist.dof
|
|
136
|
-
else:
|
|
137
|
-
dof = self._dof
|
|
138
|
-
if dof < 1:
|
|
139
|
-
# Occasionally correlations can result in a dof less than 1;
|
|
140
|
-
# see the ummy._get_dof method.
|
|
141
|
-
return 1
|
|
142
|
-
return dof
|
|
143
|
-
|
|
144
177
|
@property
|
|
145
178
|
def name(self):
|
|
146
179
|
if self._name is None:
|
|
@@ -170,31 +203,9 @@ class nummy(ummy):
|
|
|
170
203
|
raise ValueError('the name must be a string or a length 4 tuple of str')
|
|
171
204
|
|
|
172
205
|
def get_name(self,fmt='unicode',norm=None):
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if self._name is None:
|
|
178
|
-
return None
|
|
179
|
-
|
|
180
|
-
if isinstance(self._name,str):
|
|
181
|
-
name = str(self._name).strip()
|
|
182
|
-
if fmt == 'html' and len(name) == 1:
|
|
183
|
-
return '<i>' + name + '</i>'
|
|
184
|
-
if fmt == 'latex' and len(name) > 1:
|
|
185
|
-
if norm is None:
|
|
186
|
-
norm = type(self).latex_norm
|
|
187
|
-
return norm(self.name)
|
|
188
|
-
return self._name
|
|
189
|
-
|
|
190
|
-
if fmt == 'unicode':
|
|
191
|
-
return self._name[0]
|
|
192
|
-
if fmt == 'html':
|
|
193
|
-
return self._name[1]
|
|
194
|
-
if fmt == 'latex':
|
|
195
|
-
return self._name[2]
|
|
196
|
-
if fmt == 'ascii':
|
|
197
|
-
return self._name[3]
|
|
206
|
+
if norm is None:
|
|
207
|
+
norm = type(self).latex_norm
|
|
208
|
+
return get_name(self._name,fmt,norm)
|
|
198
209
|
|
|
199
210
|
@property
|
|
200
211
|
def bayesian(self):
|
|
@@ -240,12 +251,21 @@ class nummy(ummy):
|
|
|
240
251
|
@staticmethod
|
|
241
252
|
def simulate(nummys,n=100000,ufrom=None):
|
|
242
253
|
if ufrom is not None:
|
|
243
|
-
|
|
254
|
+
if isinstance(ufrom,(nummy,str,Distribution)):
|
|
255
|
+
ufrom = [ufrom]
|
|
256
|
+
ufrom = [g.distribution if isinstance(g,nummy) else g for g in ufrom]
|
|
244
257
|
if isinstance(nummys,nummy):
|
|
245
258
|
nummys = [nummys]
|
|
246
|
-
Distribution.simulate([g.distribution for g in nummys],n,ufrom)
|
|
259
|
+
Distribution.simulate([g.distribution for g in nummys if isinstance(g,nummy)],n=n,ufrom=ufrom)
|
|
247
260
|
nummy._nsim = n
|
|
248
261
|
|
|
262
|
+
def sim(self,n=100000,ufrom=None):
|
|
263
|
+
return nummy.simulate([self],n=n,ufrom=ufrom)
|
|
264
|
+
|
|
265
|
+
def clear(self):
|
|
266
|
+
if isinstance(self._dist,Distribution):
|
|
267
|
+
self._dist.clear()
|
|
268
|
+
|
|
249
269
|
@property
|
|
250
270
|
def simdata(self):
|
|
251
271
|
"""
|
|
@@ -278,38 +298,35 @@ class nummy(ummy):
|
|
|
278
298
|
def xsim(self):
|
|
279
299
|
if not isinstance(self._dist,Distribution):
|
|
280
300
|
return self._dist
|
|
281
|
-
return self.distribution.mean
|
|
301
|
+
return float(self.distribution.mean)
|
|
282
302
|
|
|
283
303
|
@property
|
|
284
304
|
def usim(self):
|
|
285
305
|
if not isinstance(self._dist,Distribution):
|
|
286
306
|
return 0
|
|
287
|
-
return self.distribution.stdev
|
|
307
|
+
return float(self.distribution.stdev)
|
|
288
308
|
|
|
289
|
-
|
|
290
|
-
def cisim(self):
|
|
309
|
+
def cisim(self,p):
|
|
291
310
|
if not isinstance(self._dist,Distribution):
|
|
292
311
|
return [self._dist,self._dist]
|
|
293
312
|
if self._cimethod == 'shortest':
|
|
294
|
-
return self.distribution.ci(
|
|
313
|
+
return [float(i) for i in self.distribution.ci(p)]
|
|
295
314
|
else:
|
|
296
|
-
return self.distribution.cisym(
|
|
315
|
+
return [float(i) for i in self.distribution.cisym(p)]
|
|
297
316
|
|
|
298
|
-
|
|
299
|
-
def Usim(self):
|
|
317
|
+
def Usim(self,p):
|
|
300
318
|
if not isinstance(self._dist,Distribution):
|
|
301
319
|
return 0
|
|
302
320
|
x = self.distribution.mean
|
|
303
321
|
|
|
304
322
|
if self._cimethod == 'shortest':
|
|
305
|
-
ci = self.distribution.ci(
|
|
323
|
+
ci = self.distribution.ci(p)
|
|
306
324
|
else:
|
|
307
|
-
ci = self.distribution.cisym(
|
|
325
|
+
ci = self.distribution.cisym(p)
|
|
308
326
|
|
|
309
|
-
return (ci[1]-x,x-ci[0])
|
|
327
|
+
return (float(ci[1]-x),float(x-ci[0]))
|
|
310
328
|
|
|
311
|
-
|
|
312
|
-
def ksim(self):
|
|
329
|
+
def ksim(self,p):
|
|
313
330
|
"""
|
|
314
331
|
read-only
|
|
315
332
|
|
|
@@ -317,10 +334,11 @@ class nummy(ummy):
|
|
|
317
334
|
"""
|
|
318
335
|
if self.usim == 0 or not isinstance(self._dist,Distribution):
|
|
319
336
|
return float('inf')
|
|
320
|
-
|
|
337
|
+
usm = self.Usim(p)
|
|
338
|
+
return 0.5*(usm[0] + usm[1])/self.usim
|
|
321
339
|
|
|
322
340
|
@property
|
|
323
|
-
def
|
|
341
|
+
def isindependent(self):
|
|
324
342
|
"""
|
|
325
343
|
`bool`, read-only
|
|
326
344
|
|
|
@@ -364,12 +382,9 @@ class nummy(ummy):
|
|
|
364
382
|
if value not in ['shortest','symmetric']:
|
|
365
383
|
raise ValueError('cimethod ' + str(value) + ' is not recognized')
|
|
366
384
|
self._cimethod = value
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if self._fp is None:
|
|
371
|
-
return 0.68268949213708585
|
|
372
|
-
return self._fp()
|
|
385
|
+
if isinstance(self.distribution,Distribution):
|
|
386
|
+
self.distribution._ci = {}
|
|
387
|
+
self.distribution._cisym = {}
|
|
373
388
|
|
|
374
389
|
@staticmethod
|
|
375
390
|
def set_seed(seed):
|
|
@@ -384,7 +399,7 @@ class nummy(ummy):
|
|
|
384
399
|
"""
|
|
385
400
|
returns an ummy representaion of the nummy
|
|
386
401
|
"""
|
|
387
|
-
r = ummy(self.x,u=self.u
|
|
402
|
+
r = ummy(self.x,u=self.u)
|
|
388
403
|
r._ref = self._ref
|
|
389
404
|
r._refs = self._refs
|
|
390
405
|
return r
|
|
@@ -397,9 +412,9 @@ class nummy(ummy):
|
|
|
397
412
|
|
|
398
413
|
|
|
399
414
|
@staticmethod
|
|
400
|
-
def _copy(s,r,formatting=True,
|
|
415
|
+
def _copy(s,r,formatting=True,totype=None):
|
|
401
416
|
# copies attributes of s to r, called from ummy.copy()
|
|
402
|
-
super(nummy,nummy)._copy(s,r,formatting=formatting,
|
|
417
|
+
super(nummy,nummy)._copy(s,r,formatting=formatting,totype=totype)
|
|
403
418
|
if isinstance(s,nummy):
|
|
404
419
|
r._dist = s._dist
|
|
405
420
|
if formatting:
|
|
@@ -409,18 +424,18 @@ class nummy(ummy):
|
|
|
409
424
|
r.name = None
|
|
410
425
|
else:
|
|
411
426
|
r.name = None
|
|
412
|
-
if s.
|
|
413
|
-
r._dist = r.
|
|
427
|
+
if s.u == 0:
|
|
428
|
+
r._dist = r.x
|
|
414
429
|
return
|
|
415
|
-
dof = s.
|
|
430
|
+
dof = s.dof
|
|
416
431
|
if isinf(dof):
|
|
417
|
-
r._dist = NormalDist(s.
|
|
432
|
+
r._dist = NormalDist(s.x,s.u)
|
|
418
433
|
else:
|
|
419
434
|
if r._bayesian:
|
|
420
|
-
r._dist = TDist(s.
|
|
421
|
-
r.
|
|
435
|
+
r._dist = TDist(s.x,s.u*np.sqrt((dof-2)/dof),dof)
|
|
436
|
+
r.dof = float('inf')
|
|
422
437
|
else:
|
|
423
|
-
r._dist = TDist(s.
|
|
438
|
+
r._dist = TDist(s.x,s.u,dof)
|
|
424
439
|
|
|
425
440
|
@classmethod
|
|
426
441
|
def _apply(cls,function,derivative,*args,fxdx=None):
|
|
@@ -452,34 +467,11 @@ class nummy(ummy):
|
|
|
452
467
|
r._dist = Distribution.apply(function,*a)
|
|
453
468
|
return r
|
|
454
469
|
|
|
455
|
-
@staticmethod
|
|
456
|
-
def _set_correlation_matrix(gummys, matrix):
|
|
457
|
-
super(nummy,nummy)._set_correlation_matrix(gummys,matrix)
|
|
458
|
-
cov = nummy.covariance_matrix(gummys)
|
|
459
|
-
mean = [g.x for g in gummys]
|
|
460
|
-
if isfinite(gummys[0].dof) and all([g.dof==gummys[0].dof for g in gummys]):
|
|
461
|
-
mvdist = MultiTDist(mean,cov,gummys[0].dof)
|
|
462
|
-
else:
|
|
463
|
-
mvdist = MultiNormalDist(mean,cov)
|
|
464
|
-
for i,g in enumerate(gummys):
|
|
465
|
-
g._dist = mvdist[i]
|
|
466
|
-
|
|
467
|
-
@staticmethod
|
|
468
|
-
def _set_covariance_matrix(gummys, matrix):
|
|
469
|
-
super(nummy,nummy)._set_covariance_matrix(gummys,matrix)
|
|
470
|
-
mean = [g.x for g in gummys]
|
|
471
|
-
if isfinite(gummys[0].dof) and all([g.dof==gummys[0].dof for g in gummys]):
|
|
472
|
-
mvdist = MultiTDist(mean,matrix,gummys[0].dof)
|
|
473
|
-
else:
|
|
474
|
-
mvdist = MultiNormalDist(mean,matrix)
|
|
475
|
-
for i,g in enumerate(gummys):
|
|
476
|
-
g._dist = mvdist[i]
|
|
477
|
-
|
|
478
470
|
@classmethod
|
|
479
|
-
def create(cls,x,u=0,dof=float('inf'),name=None,
|
|
480
|
-
covariance_matrix=None):
|
|
481
|
-
if name
|
|
482
|
-
name = [
|
|
471
|
+
def create(cls,x,u=0,dof=float('inf'),name=None,utype=None,
|
|
472
|
+
correlation_matrix=None,covariance_matrix=None):
|
|
473
|
+
if _isscalar(name):
|
|
474
|
+
name = [name]*len(x)
|
|
483
475
|
|
|
484
476
|
if isinstance(x,MultivariateDistribution):
|
|
485
477
|
|
|
@@ -497,9 +489,10 @@ class nummy(ummy):
|
|
|
497
489
|
else:
|
|
498
490
|
dof = x.dof
|
|
499
491
|
else:
|
|
500
|
-
dof =
|
|
492
|
+
dof = float('inf')
|
|
501
493
|
|
|
502
|
-
ret = super(nummy,cls).create(x.x(),u=u,dof=dof,
|
|
494
|
+
ret = super(nummy,cls).create(x.x(),u=u,dof=dof,utype=utype,
|
|
495
|
+
covariance_matrix=x.cov)
|
|
503
496
|
|
|
504
497
|
for i,r in enumerate(ret):
|
|
505
498
|
r._dist = x[i]
|
|
@@ -513,6 +506,11 @@ class nummy(ummy):
|
|
|
513
506
|
|
|
514
507
|
if dof is None:
|
|
515
508
|
dof = [float('inf')]*len(x)
|
|
509
|
+
elif _isscalar(dof):
|
|
510
|
+
dof = [dof]*len(x)
|
|
511
|
+
else:
|
|
512
|
+
dof = [float('inf') if i is None else i for i in dof]
|
|
513
|
+
|
|
516
514
|
if u is None:
|
|
517
515
|
u = [0]*len(x)
|
|
518
516
|
d = [None]*len(x)
|
|
@@ -527,7 +525,9 @@ class nummy(ummy):
|
|
|
527
525
|
u[i] = u[i]*np.sqrt(v.dof/(v.dof-2))
|
|
528
526
|
dof[i] = float('inf')
|
|
529
527
|
|
|
530
|
-
ret = super(nummy,cls).create(x,u,dof,
|
|
528
|
+
ret = super(nummy,cls).create(x,u=u,dof=dof,utype=utype,
|
|
529
|
+
correlation_matrix=correlation_matrix,
|
|
530
|
+
covariance_matrix=covariance_matrix)
|
|
531
531
|
for i,r in enumerate(ret):
|
|
532
532
|
r.name = name[i]
|
|
533
533
|
if d[i] is None:
|
|
@@ -538,7 +538,6 @@ class nummy(ummy):
|
|
|
538
538
|
else:
|
|
539
539
|
if nummy._bayesian:
|
|
540
540
|
r._dist = TDist(x,u[i]*np.sqrt((dof[i]-2)/dof[i]),dof[i])
|
|
541
|
-
r._dof = float('inf')
|
|
542
541
|
else:
|
|
543
542
|
r._dist = TDist(x,u[i],dof[i])
|
|
544
543
|
else:
|
|
@@ -546,12 +545,10 @@ class nummy(ummy):
|
|
|
546
545
|
|
|
547
546
|
return ret
|
|
548
547
|
|
|
549
|
-
def hist(self
|
|
550
|
-
if
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
xlabel = '$ ' + xlabel + ' $'
|
|
554
|
-
self.distribution.hist(xlabel=xlabel,title=title,hold=hold,**kwds)
|
|
548
|
+
def hist(self,**kwds):
|
|
549
|
+
if not isinstance(self._dist,Distribution):
|
|
550
|
+
raise TypeError('hist may not be called from a constant nummy')
|
|
551
|
+
self.distribution.hist(**kwds)
|
|
555
552
|
|
|
556
553
|
def covariance_sim(self,g):
|
|
557
554
|
"""
|
|
@@ -561,9 +558,7 @@ class nummy(ummy):
|
|
|
561
558
|
See the method `gummy.covariance(g)` for the corresponding result based
|
|
562
559
|
on first order error propagation.
|
|
563
560
|
"""
|
|
564
|
-
|
|
565
|
-
#return 0
|
|
566
|
-
return self._dist.covsim(g._dist)
|
|
561
|
+
return float(self._dist.covsim(g._dist))
|
|
567
562
|
|
|
568
563
|
def correlation_sim(self,g):
|
|
569
564
|
"""
|
|
@@ -573,8 +568,6 @@ class nummy(ummy):
|
|
|
573
568
|
See the method `gummy.correlation(g)` for the corresponding result based
|
|
574
569
|
on first order error propagation.
|
|
575
570
|
"""
|
|
576
|
-
#if self._u == 0 or g._u == 0:
|
|
577
|
-
#return 0
|
|
578
571
|
return self.covariance_sim(g)/(self.usim*g.usim)
|
|
579
572
|
|
|
580
573
|
@staticmethod
|
|
@@ -607,59 +600,110 @@ class nummy(ummy):
|
|
|
607
600
|
@staticmethod
|
|
608
601
|
def covplot(x,y,title=None,xlabel=None,ylabel=None,hold=False,**kwds):
|
|
609
602
|
if xlabel is None and x.name is not None:
|
|
610
|
-
xlabel =
|
|
611
|
-
if len(xlabel) == 1:
|
|
612
|
-
xlabel = '$ ' + xlabel + ' $'
|
|
603
|
+
xlabel = x.get_name(fmt='latex')
|
|
613
604
|
if ylabel is None and y.name is not None:
|
|
614
|
-
ylabel =
|
|
615
|
-
if len(ylabel) == 1:
|
|
616
|
-
ylabel = '$ ' + ylabel + ' $'
|
|
605
|
+
ylabel = y.get_name(fmt='latex')
|
|
617
606
|
|
|
618
607
|
Distribution.covplot(x.distribution,y.distribution,xlabel=xlabel,ylabel=ylabel,
|
|
619
608
|
title=title,hold=hold,**kwds)
|
|
620
609
|
|
|
621
|
-
def ufrom(self,x,sim=False):
|
|
622
|
-
"""
|
|
623
|
-
Gets the standard uncertainty contributed from particular gummys
|
|
624
|
-
or utypes if all other free variables are held fixed.
|
|
610
|
+
#def ufrom(self,x,sim=False):
|
|
625
611
|
|
|
612
|
+
#if not sim:
|
|
613
|
+
#return super().ufrom(x)
|
|
614
|
+
|
|
615
|
+
#v = nummy.correlation_matrix_sim(x)
|
|
616
|
+
|
|
617
|
+
#b = [self.correlation(z) for z in x]
|
|
618
|
+
#s = np.linalg.lstsq(v,b,rcond=-1)[0]
|
|
619
|
+
#u = 0
|
|
620
|
+
|
|
621
|
+
#d = [i*self.usim/j.usim for i,j in zip(s,x)]
|
|
622
|
+
#for i in range(len(x)):
|
|
623
|
+
#for j in range(len(x)):
|
|
624
|
+
# u += d[i]*d[j]*x[i].correlation(x[j])*x[i].usim*x[j].usim
|
|
625
|
+
|
|
626
|
+
#return sqrt(u)
|
|
627
|
+
|
|
628
|
+
def ufromsim(self,x):
|
|
629
|
+
"""
|
|
630
|
+
Gets the standard deviation of the Monte-Carlo data only allowing the
|
|
631
|
+
independent variables in `x` to vary. Independent istributions not in
|
|
632
|
+
`x` are held fixed. `sim` or `simulate` must be called to generate
|
|
633
|
+
Monte-Carlo data before calling this method.
|
|
634
|
+
|
|
626
635
|
Parameters
|
|
627
|
-
|
|
628
|
-
x: `
|
|
629
|
-
A
|
|
630
|
-
|
|
631
|
-
|
|
636
|
+
----------
|
|
637
|
+
x: `nummy`, `str`, or array_like
|
|
638
|
+
A nummy, a string referencing a utype or a list containing
|
|
639
|
+
nummys and strings.
|
|
640
|
+
|
|
632
641
|
Returns
|
|
633
642
|
-------
|
|
634
643
|
`float`
|
|
635
|
-
|
|
636
|
-
Example
|
|
637
|
-
-------
|
|
638
|
-
>>> a = gummy(1.2,0.2,utype='A')
|
|
639
|
-
>>> b = gummy(3.2,0.5,utype='A')
|
|
640
|
-
>>> c = gummy(0.9,0.2,utype='B')
|
|
641
|
-
>>> d = a + b + c
|
|
642
|
-
>>> d.ufrom('A')
|
|
643
|
-
0.53851648071345048
|
|
644
644
|
"""
|
|
645
|
-
|
|
646
|
-
|
|
645
|
+
return float(np.std(self.datafrom(x,save=False),ddof=1))
|
|
646
|
+
|
|
647
|
+
def datafrom(self,x,save=True):
|
|
648
|
+
"""
|
|
649
|
+
Recomputes the convolution with only the varaibles in `x` allowed to
|
|
650
|
+
vary. `sim` or `simulate` must be called to generate
|
|
651
|
+
Monte-Carlo data before calling this method. This method cannot be
|
|
652
|
+
called with save == `True` from from a nummy representing an independent
|
|
653
|
+
variable (that is from a nummy not created by by mathematical operations
|
|
654
|
+
between two or more other nummy's).
|
|
647
655
|
|
|
648
|
-
|
|
656
|
+
Parameters
|
|
657
|
+
----------
|
|
658
|
+
x: list containing `nummy` or `str`
|
|
659
|
+
all independent Distributions not in the list or having a utype
|
|
660
|
+
not in the list are held fixed at their `.x()` value
|
|
649
661
|
|
|
650
|
-
|
|
662
|
+
save: If `save` is `True` the recomputed data is stored in the `simdata`
|
|
663
|
+
attribute and `None` is returned. If `save` is `False` then the
|
|
664
|
+
recomputed data is returned and the `simdata` attribute is not
|
|
665
|
+
overwritten.
|
|
666
|
+
|
|
667
|
+
Returns
|
|
668
|
+
-------
|
|
669
|
+
'numpy.array' if `save` is `False`, otherwise returns `None`
|
|
670
|
+
|
|
671
|
+
Raises
|
|
672
|
+
------
|
|
673
|
+
`NoSimulatedDataError`:
|
|
674
|
+
if no simulated data is available from a call to
|
|
675
|
+
`Distribution.simulate`.
|
|
676
|
+
`RuntimeError`:
|
|
677
|
+
if this method is called from an independent `nummy`
|
|
678
|
+
"""
|
|
679
|
+
if not isinstance(self._dist,Distribution):
|
|
680
|
+
if nummy._nsim is None:
|
|
681
|
+
raise NoSimulatedDataError
|
|
682
|
+
return np.full(nummy._nsim,self._dist)
|
|
683
|
+
|
|
684
|
+
if not isinstance(self.distribution,Convolution) and save == 'True':
|
|
685
|
+
raise RuntimeError('datafrom may not be called from an independent nummy with save == True')
|
|
686
|
+
|
|
687
|
+
if self.distribution.simdata is None:
|
|
688
|
+
raise NoSimulatedDataError('no simulated data')
|
|
651
689
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
d = [i*self.usim/j.usim for i,j in zip(s,x)]
|
|
657
|
-
for i in range(len(x)):
|
|
658
|
-
for j in range(len(x)):
|
|
659
|
-
u += d[i]*d[j]*x[i].correlation(x[j])*x[i].usim*x[j].usim
|
|
660
|
-
|
|
661
|
-
return sqrt(u)
|
|
690
|
+
if isinstance(x,(nummy,str,Distribution)):
|
|
691
|
+
x = [x]
|
|
692
|
+
x = [i.distribution if isinstance(i,nummy) else i for i in x]
|
|
662
693
|
|
|
694
|
+
if not isinstance(self.distribution,Convolution):
|
|
695
|
+
if self.distribution in x or self.distribution.utype in x:
|
|
696
|
+
ret = self.distribution.simdata
|
|
697
|
+
else:
|
|
698
|
+
ret = np.full(self.distribution.simdata,self.distribution.x())
|
|
699
|
+
else:
|
|
700
|
+
ret = self.distribution.datafrom(x,save=save)
|
|
701
|
+
|
|
702
|
+
if save:
|
|
703
|
+
self.distribution.simdata = ret
|
|
704
|
+
else:
|
|
705
|
+
return ret
|
|
706
|
+
|
|
663
707
|
def __add__(self,b):
|
|
664
708
|
return _bop(super().__add__(b),np.add,self,b)
|
|
665
709
|
|
metrolopy/offsetunit.py
CHANGED
|
@@ -64,8 +64,6 @@ class _IntervalUnit(Unit):
|
|
|
64
64
|
kwds['parent'] = parent
|
|
65
65
|
Unit.__init__(self,params[0] + ' interval',params[1],conversion=conv,**kwds)
|
|
66
66
|
|
|
67
|
-
def _getme(self,ul,e):
|
|
68
|
-
return self.parent
|
|
69
67
|
|
|
70
68
|
class OffsetUnit(NonlinearUnit):
|
|
71
69
|
"""
|
|
@@ -107,4 +105,5 @@ class OffsetUnit(NonlinearUnit):
|
|
|
107
105
|
return (b - a,self.interval_unit)
|
|
108
106
|
raise IncompatibleUnitsError('a quantity with unit ' + self.tostring() + ' may not be subtracted from a quantity with unit ' + bunit.tostring() + '; automatic conversion is disabled with offset unit instances')
|
|
109
107
|
|
|
110
|
-
|
|
108
|
+
def _getme(self,ul,e):
|
|
109
|
+
return self.interval_unit
|