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/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,MultiNormalDist,MultiTDist)
32
+ MultivariateDistribution,Convolution)
33
33
  from .exceptions import NoSimulatedDataError
34
- from math import isinf,isfinite,isnan,sqrt
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
- dof = float('inf')
144
+ ndof = float('inf')
89
145
  u = float(x.u())
90
146
 
91
- super().__init__(x.x(),u=u,dof=dof,utype=utype)
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._u)
97
- if self._u == 0 or isnan(x) or isinf(x) or isnan(u):
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 = self._dof
101
- if isinf(dof):
102
- self._dist = NormalDist(x,u)
156
+ if isinstance(dof,_udict):
157
+ self._dist = None
103
158
  else:
104
- if nummy._bayesian:
105
- self._dist = TDist(x,u*np.sqrt((dof-2)/dof),dof)
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
- self._dist = TDist(x,u,dof)
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
- fmt = fmt.strip().lower()
174
- if fmt not in {'unicode','html','latex','ascii'}:
175
- raise ValueError('fmt "' + str(fmt) + '" is not recognized')
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
- ufrom = [g._dist for g in ufrom]
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
- @property
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(self.p)
313
+ return [float(i) for i in self.distribution.ci(p)]
295
314
  else:
296
- return self.distribution.cisym(self.p)
315
+ return [float(i) for i in self.distribution.cisym(p)]
297
316
 
298
- @property
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(self.p)
323
+ ci = self.distribution.ci(p)
306
324
  else:
307
- ci = self.distribution.cisym(self.p)
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
- @property
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
- return 0.5*(self.Usim[0] + self.Usim[1])/self.usim
337
+ usm = self.Usim(p)
338
+ return 0.5*(usm[0] + usm[1])/self.usim
321
339
 
322
340
  @property
323
- def independent(self):
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
- @property
369
- def p(self):
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,dof=self.dof)
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,tofloat=False):
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,tofloat=tofloat)
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._u == 0:
413
- r._dist = r._x
427
+ if s.u == 0:
428
+ r._dist = r.x
414
429
  return
415
- dof = s._dof
430
+ dof = s.dof
416
431
  if isinf(dof):
417
- r._dist = NormalDist(s._x,s._u)
432
+ r._dist = NormalDist(s.x,s.u)
418
433
  else:
419
434
  if r._bayesian:
420
- r._dist = TDist(s._x,s._u*np.sqrt((dof-2)/dof),dof)
421
- r._dof = float('inf')
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._x,s._u,dof)
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,correlation_matrix=None,
480
- covariance_matrix=None):
481
- if name is None:
482
- name = [None]*len(x)
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 = [float('inf')]*nd
492
+ dof = float('inf')
501
493
 
502
- ret = super(nummy,cls).create(x.x(),u=u,dof=dof,covariance_matrix=x.cov)
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,correlation_matrix,covariance_matrix)
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,xlabel=None,title=None,hold=False,**kwds):
550
- if xlabel is None and self.name is not None:
551
- xlabel = str(self.name)
552
- if len(xlabel) == 1:
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
- #if self._u == 0 or g._u == 0:
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 = str(x.name)
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 = str(y.name)
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: `gummy`, `str`, or array_like
629
- A gummy, a string referencing a utype or a list containing
630
- gummys and strings.
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
- if not sim:
646
- return super().ufrom(x)
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
- x = [g for g in ummy._toummylist(x) if self.correlation(g) != 0]
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
- v = nummy.correlation_matrix_sim(x)
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
- b = [self.correlation(z) for z in x]
653
- s = np.linalg.lstsq(v,b,rcond=-1)[0]
654
- u = 0
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