Skip to content

Commit 4b2b652

Browse files
committed
Merge branch 'development'
2 parents 2e5fec5 + f9cf0fc commit 4b2b652

File tree

4 files changed

+158
-72
lines changed

4 files changed

+158
-72
lines changed

.travis.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
language: python
2+
python:
3+
# - "3.6" # current default Python on Travis CI
4+
# - "3.7"
5+
- "3.8"
6+
- "3.8-dev" # 3.8 development branch
7+
# - "nightly" # nightly build
8+
install:
9+
- pip install numpy
10+
- pip install .
11+
script:
12+
- pytest

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# labfis.py
22

3+
[![Travis - CI](https://img.shields.io/travis/com/phisgroup/labfis.py/development?style=for-the-badge)](https://travis-ci.com/phisgroup/labfis.py) [![PyPI](https://img.shields.io/pypi/v/labfis?style=for-the-badge)](https://pypi.org/project/labfis/) [![License](https://img.shields.io/github/license/phisgroup/labfis.py?style=for-the-badge)](https://github.com/phisgroup/labfis.py/blob/master/LICENSE)
4+
35
## Description
46

57
Small library (currently only one class) for uncertainty calculations and error propagation.

labfis/uncertainty.py

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
2-
from math import floor, ceil, trunc, log, log10, sqrt, cos, sin, tan
2+
from math import (floor, ceil, trunc, log, log10, sqrt,
3+
cos, sin, tan, asin, acos, atan)
34
from numbers import Number
45

56
logger = logging.getLogger(__name__)
@@ -8,20 +9,6 @@
89
import numpy
910
except ImportError:
1011
numpy = None
11-
logger.warning(
12-
'Faild to import numpy; sqrt, sin, cos, tan and numpy.ndarray list method wont function')
13-
14-
15-
def skipif(condition, message):
16-
def decorator(fnc):
17-
def wrapper(*args, **kwargs):
18-
if condition:
19-
return fnc(*args, **kwargs)
20-
else:
21-
logger.info(message)
22-
pass
23-
return wrapper
24-
return decorator
2512

2613

2714
class LabFloatError(Exception):
@@ -30,7 +17,7 @@ def __init__(self, *args):
3017
if args[0] == 0:
3118
self.message = "This operation is not supported."
3219
elif args[0] == 1:
33-
self.message = "Too many arguments, expected '(val,err)' or '([(val,err),...])' , got: '{0}'".format(
20+
self.message = "Too many arguments, expected '(val,err)' or '([val1,val2,...],[err1,err2,...],...])' , got: '{0}'".format(
3421
args[1])
3522
elif args[0] == 2:
3623
self.message = "Mean list and Uncertainty list must have the same size, expected: '[[val1,val2,...,valn],[err1,err2,...,errn]]' , got: '{0}'".format(
@@ -86,8 +73,8 @@ def __init__(self, *args, **kwargs):
8673
elif len(args) > 2:
8774
raise LabFloatError(1, args)
8875

89-
self.mean = float(mean)
90-
self.uncertainty = abs(float(uncertainty))
76+
self._mean = float(mean)
77+
self._uncertainty = abs(float(uncertainty))
9178

9279
@classmethod
9380
def list(cls, listargs):
@@ -105,12 +92,12 @@ def list(cls, listargs):
10592
return(listlabfloat)
10693

10794
def format(self):
108-
su = "%.16f" % self.uncertainty
95+
su = "%.16f" % self._uncertainty
10996
i = su.find(".")
11097
if i == -1:
11198
r = - len(su) + 1
112-
m = round(self.mean, r)
113-
u = round(self.uncertainty, r)
99+
m = round(self._mean, r)
100+
u = round(self._uncertainty, r)
114101
return((m, u))
115102
else:
116103
r = -i
@@ -127,8 +114,8 @@ def format(self):
127114
u = round(self.uncertainty, r)
128115
return((m, u))
129116

130-
m = round(self.mean, r)
131-
u = round(self.uncertainty, r)
117+
m = round(self._mean, r)
118+
u = round(self._uncertainty, r)
132119
return((m, u))
133120

134121
def split(self):
@@ -145,10 +132,10 @@ def tex(self, *args, **kwargs):
145132
else:
146133
precision = [args[0], args[0]]
147134

148-
if self.uncertainty == 0:
135+
if self._uncertainty == 0:
149136
if precision:
150137
precision[0] = str(precision[0])
151-
m = eval("'{:."+precision[0]+"e}'.format(self.mean)")
138+
m = eval("'{:."+precision[0]+"e}'.format(self._mean)")
152139
else:
153140
m = self.split()[0]
154141
m = m.split("e")
@@ -183,72 +170,80 @@ def __str__(self):
183170
def __repr__(self):
184171
return self.__str__()
185172

173+
@property
174+
def mean(self):
175+
return self._mean
176+
177+
@property
178+
def uncertainty(self):
179+
return self._uncertainty
180+
186181
def __getitem__(self, idx):
187-
vals = [self.mean, self.uncertainty]
182+
vals = (self.uncertainty, self.mean)
188183
return vals[idx]
189184

190185
def __pos__(self):
191186
return self
192187

193188
def __neg__(self):
194-
return labfloat(-self.mean, self.uncertainty)
189+
return labfloat(-self._mean, self._uncertainty)
195190

196191
def __abs__(self):
197-
return labfloat(abs(self.mean), self.uncertainty)
192+
return labfloat(abs(self._mean), self._uncertainty)
198193

199194
def __round__(self, n):
200-
return labfloat(round(self.mean, n), round(self.uncertainty, n))
195+
return labfloat(round(self._mean, n), round(self._uncertainty, n))
201196

202197
def __floor__(self):
203-
return labfloat(floor(self.mean), floor(self.uncertainty))
198+
return labfloat(floor(self._mean), floor(self._uncertainty))
204199

205200
def __ceil__(self):
206-
return labfloat(ceil(self.mean), ceil(self.uncertainty))
201+
return labfloat(ceil(self._mean), ceil(self._uncertainty))
207202

208203
def __trunc__(self):
209-
return labfloat(trunc(self.mean), trunc(self.uncertainty))
204+
return labfloat(trunc(self._mean), trunc(self._uncertainty))
210205

211206
def __eq__(self, other):
212207
if isinstance(other, labfloat):
213-
return abs(self.mean - other.mean) < 2 * (self.uncertainty + other.uncertainty)
208+
return abs(self._mean - other.mean) < 2 * (self._uncertainty + other.uncertainty)
214209
if isinstance(other, Number):
215-
return abs(self.mean - other) < 2 * self.uncertainty
210+
return abs(self._mean - other) < 2 * self._uncertainty
216211

217212
def __ne__(self, other):
218213
if isinstance(other, labfloat):
219-
return abs(self.mean - other.mean) > 3 * (self.uncertainty + other.uncertainty)
214+
return abs(self._mean - other.mean) > 3 * (self._uncertainty + other.uncertainty)
220215
if isinstance(other, Number):
221-
return abs(self.mean - other) > 3 * self.uncertainty
216+
return abs(self._mean - other) > 3 * self._uncertainty
222217

223218
def __lt__(self, other):
224219
if isinstance(other, labfloat):
225-
return self.mean + self.uncertainty < other.mean - other.uncertainty
220+
return self._mean + self._uncertainty < other.mean - other.uncertainty
226221
if isinstance(other, Number):
227-
return self.mean + self.uncertainty < other
222+
return self._mean + self._uncertainty < other
228223

229224
def __gt__(self, other):
230225
if isinstance(other, labfloat):
231-
return self.mean - self.uncertainty > other.mean + other.uncertainty
226+
return self._mean - self._uncertainty > other.mean + other.uncertainty
232227
if isinstance(other, Number):
233-
return self.mean - self.uncertainty > other
228+
return self._mean - self._uncertainty > other
234229

235230
def __le__(self, other):
236231
if isinstance(other, labfloat):
237-
return self.mean + self.uncertainty <= other.mean + other.uncertainty
232+
return self._mean + self._uncertainty <= other.mean + other.uncertainty
238233
if isinstance(other, Number):
239-
return self.mean + self.uncertainty <= other
234+
return self._mean + self._uncertainty <= other
240235

241236
def __ge__(self, other):
242237
if isinstance(other, labfloat):
243-
return self.mean - self.uncertainty >= other.mean - other.uncertainty
238+
return self._mean - self._uncertainty >= other.mean - other.uncertainty
244239
if isinstance(other, Number):
245-
return self.mean - self.uncertainty >= other
240+
return self._mean - self._uncertainty >= other
246241

247242
def __add__(self, other):
248243
if isinstance(other, labfloat):
249-
return labfloat(self.mean + other.mean, sqrt(self.uncertainty ** 2 + other.uncertainty ** 2))
244+
return labfloat(self._mean + other.mean, sqrt(self._uncertainty ** 2 + other.uncertainty ** 2))
250245
if isinstance(other, Number):
251-
return labfloat(self.mean + other, self.uncertainty)
246+
return labfloat(self._mean + other, self._uncertainty)
252247

253248
def __radd__(self, other):
254249
return self.__add__(other)
@@ -258,24 +253,24 @@ def __iadd__(self, other):
258253

259254
def __sub__(self, other):
260255
if isinstance(other, labfloat):
261-
return labfloat(self.mean - other.mean, sqrt(self.uncertainty ** 2 + other.uncertainty ** 2))
256+
return labfloat(self._mean - other.mean, sqrt(self._uncertainty ** 2 + other.uncertainty ** 2))
262257
if isinstance(other, Number):
263-
return labfloat(self.mean - other, self.uncertainty)
258+
return labfloat(self._mean - other, self._uncertainty)
264259

265260
def __rsub__(self, other):
266261
if isinstance(other, labfloat):
267-
return labfloat(other.mean - self.mean, sqrt(other.uncertainty ** 2 + self.uncertainty ** 2))
262+
return labfloat(other.mean - self._mean, sqrt(other.uncertainty ** 2 + self._uncertainty ** 2))
268263
if isinstance(other, Number):
269-
return labfloat(other - self.mean, self.uncertainty)
264+
return labfloat(other - self._mean, self._uncertainty)
270265

271266
def __isub__(self, other):
272267
return self.__sub__(other)
273268

274269
def __mul__(self, other):
275270
if isinstance(other, labfloat):
276-
return labfloat(self.mean * other.mean, sqrt((other.mean * self.uncertainty) ** 2 + (self.mean * other.uncertainty) ** 2))
271+
return labfloat(self._mean * other.mean, sqrt((other.mean * self._uncertainty) ** 2 + (self._mean * other.uncertainty) ** 2))
277272
if isinstance(other, Number):
278-
return labfloat(self.mean * other, abs(other * self.uncertainty))
273+
return labfloat(self._mean * other, abs(other * self._uncertainty))
279274

280275
def __rmul__(self, other):
281276
return self.__mul__(other)
@@ -285,9 +280,9 @@ def __imul__(self, other):
285280

286281
def __div__(self, other):
287282
if isinstance(other, labfloat):
288-
return labfloat(self.mean / other.mean, sqrt((self.uncertainty / other.mean) ** 2 + (self.mean * other.uncertainty / (other.mean ** 2)) ** 2))
283+
return labfloat(self._mean / other.mean, sqrt((self._uncertainty / other.mean) ** 2 + (self._mean * other.uncertainty / (other.mean ** 2)) ** 2))
289284
if isinstance(other, Number):
290-
return labfloat(self.mean / other, abs(self.uncertainty / other))
285+
return labfloat(self._mean / other, abs(self._uncertainty / other))
291286

292287
def __truediv__(self, other):
293288
return self.__div__(other)
@@ -300,55 +295,60 @@ def __itruediv__(self, other):
300295

301296
def __rdiv__(self, other):
302297
if isinstance(other, labfloat):
303-
return labfloat(other.mean / self.mean, sqrt((other.uncertainty / self.mean) ** 2 + (other.mean * self.uncertainty / (self.mean ** 2)) ** 2))
298+
return labfloat(other.mean / self._mean, sqrt((other.uncertainty / self._mean) ** 2 + (other.mean * self._uncertainty / (self._mean ** 2)) ** 2))
304299
if isinstance(other, Number):
305-
return labfloat(other / self.mean, abs(other * self.uncertainty / self.mean ** 2))
300+
return labfloat(other / self._mean, abs(other * self._uncertainty / self._mean ** 2))
306301

307302
def __rtruediv__(self, other):
308303
return self.__rdiv__(other)
309304

310305
def __pow__(self, other):
311306
if isinstance(other, labfloat):
312-
return labfloat(self.mean ** other.mean, sqrt((other.mean * self.mean ** (other.mean - 1) * self.uncertainty) ** 2 + (self.mean ** other.mean * log(abs(self.mean)) * other.uncertainty) ** 2))
307+
return labfloat(self._mean ** other.mean, sqrt((other.mean * self._mean ** (other.mean - 1) * self._uncertainty) ** 2 + (self._mean ** other.mean * log(abs(self._mean)) * other.uncertainty) ** 2))
313308
if isinstance(other, Number):
314-
return labfloat(self.mean ** other, abs(other * self.mean ** (other - 1) * self.uncertainty))
309+
return labfloat(self._mean ** other, abs(other * self._mean ** (other - 1) * self._uncertainty))
315310

316311
def __rpow__(self, other):
317312
if isinstance(other, labfloat):
318-
return labfloat(other.mean ** self.mean, sqrt((self.mean * other.mean ** (self.mean - 1) * other.uncertainty) ** 2 + (other.mean ** self.mean * log(abs(other.mean)) * self.uncertainty) ** 2))
313+
return labfloat(other.mean ** self._mean, sqrt((self._mean * other.mean ** (self._mean - 1) * other.uncertainty) ** 2 + (other.mean ** self._mean * log(abs(other.mean)) * self._uncertainty) ** 2))
319314
if isinstance(other, Number):
320-
return labfloat(other ** self.mean, abs(other ** self.mean * log(abs(other)) * self.uncertainty))
315+
return labfloat(other ** self._mean, abs(other ** self._mean * log(abs(other)) * self._uncertainty))
321316

322317
def __ipow__(self, other):
323318
return self.__pow__(other)
324319

325-
@skipif(numpy, "The sqrt() method is not supported without numpy")
326320
def sqrt(self):
327321
return self.__pow__(0.5)
328322

329-
@skipif(numpy, "The cos() method is not supported without numpy")
330323
def cos(self):
331-
return labfloat(cos(self.mean), abs(-(sin(self.mean)) * self.uncertainty))
324+
return labfloat(cos(self._mean), abs(-(sin(self._mean)) * self._uncertainty))
332325

333-
@skipif(numpy, "The sin() method is not supported without numpy")
334326
def sin(self):
335-
return labfloat(sin(self.mean), abs(cos(self.mean) * self.uncertainty))
327+
return labfloat(sin(self._mean), abs(cos(self._mean) * self._uncertainty))
336328

337-
@skipif(numpy, "The tan() method is not supported without numpy")
338329
def tan(self):
339-
return labfloat(tan(self.mean), sqrt((cos(self.mean) ** -4) * self.uncertainty ** 2))
330+
return labfloat(tan(self._mean), sqrt((cos(self._mean) ** -4) * self._uncertainty ** 2))
331+
332+
def arcsin(self):
333+
return labfloat(asin(self._mean), self._uncertainty/sqrt(1 - self._mean ** 2))
334+
335+
def arccos(self):
336+
return labfloat(acos(self._mean), abs(-self._uncertainty/sqrt(1 - self._mean ** 2)))
337+
338+
def arctan(self):
339+
return labfloat(atan(self._mean), self._uncertainty/(1 + self._mean ** 2))
340340

341341
def __int__(self):
342-
return int(self.mean)
342+
return int(self._mean)
343343

344344
def __float__(self):
345-
return float(self.mean)
345+
return float(self._mean)
346346

347347
def __complex__(self):
348-
return complex(self.mean)
348+
return complex(self._mean)
349349

350350
def __oct__(self):
351-
return oct(self.mean)
351+
return oct(self._mean)
352352

353353
def __hex__(self):
354-
return hex(self.mean)
354+
return hex(self._mean)

0 commit comments

Comments
 (0)