diff --git a/README.md b/README.md
index 30400e7..1c3617e 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,66 @@
# labfis.py
-Small library (currently only one class) for uncertainty calculations. Made by and for Physics Laboratory students in IFSC, who can't use uncertainties.py because mean absolute deviation.
+
+## Description
+
+Small library (currently only one class) for uncertainty calculations and error propagation.
+
+The uncertainty calculations are in accordance with gaussian’s propagation, as calculated by an analytical method:
+
+
+
+
+
+Made by and for Physics Laboratory students in IFSC, who can't use uncertainties.py because of mean’s absolute deviation used in its calculation.
To get this library on google colaboratory:
-
+
```
!curl --remote-name \
- -H 'Accept: application/vnd.github.v3.raw' \
- --location https://raw.githubusercontent.com/phisgroup/labfis.py/master/labfis/main.py
+
+-H 'Accept: application/vnd.github.v3.raw' \
+
+--location https://raw.githubusercontent.com/phisgroup/labfis.py/development/labfis/main.py
+```
+
+## Usage
+
+Just import with `from labfis import labfloat` and create an *labfloat* object, as this exemple below:
+
+```py
+>>> from labfis import labfloat
+>>> a = labfloat(1,3)
+>>> b = labfloat(2,4)
+>>> a*b
+(2 ± 7)
```
+Check the Wiki for more details
+
+## Instalation
+
+Intstall main releases with:
+
+```
+pip install labfis
+```
+
+Install development version with:
+
+```
+pip install git+https://github.com/phisgroup/labfis.py/tree/development
+```
+
+## References
+
+ 1. Kirchner, James. ["Data Analysis Toolkit #5: Uncertainty Analysis and Error Propagation"](http://seismo.berkeley.edu/~kirchner/eps_120/Toolkits/Toolkit_05.pdf) (PDF). _Berkeley Seismology Laboratory_. University of California. Retrieved 22 April 2016.
+ 2. [Goodman, Leo](https://en.wikipedia.org/wiki/Leo_Goodman "Leo Goodman") (1960). "On the Exact Variance of Products". _Journal of the American Statistical Association_. **55** (292): 708–713. [doi](https://en.wikipedia.org/wiki/Doi_(identifier) "Doi (identifier)"):[10.2307/2281592](https://doi.org/10.2307%2F2281592). [JSTOR](https://en.wikipedia.org/wiki/JSTOR_(identifier) "JSTOR (identifier)") [2281592](https://www.jstor.org/stable/2281592).
+ 3. Ochoa1,Benjamin; Belongie, Serge ["Covariance Propagation for Guided Matching"](http://vision.ucsd.edu/sites/default/files/ochoa06.pdf)
+ 4. Ku, H. H. (October 1966). ["Notes on the use of propagation of error formulas"](http://nistdigitalarchives.contentdm.oclc.org/cdm/compoundobject/collection/p16009coll6/id/99848/rec/1). _Journal of Research of the National Bureau of Standards_. **70C** (4): 262. [doi](https://en.wikipedia.org/wiki/Doi_(identifier) "Doi (identifier)"):[10.6028/jres.070c.025](https://doi.org/10.6028%2Fjres.070c.025). [ISSN](https://en.wikipedia.org/wiki/ISSN_(identifier) "ISSN (identifier)") [0022-4316](https://www.worldcat.org/issn/0022-4316). Retrieved 3 October 2012.
+ 5. Clifford, A. A. (1973). _Multivariate error analysis: a handbook of error propagation and calculation in many-parameter systems_. John Wiley & Sons. [ISBN](https://en.wikipedia.org/wiki/ISBN_(identifier) "ISBN (identifier)") [978-0470160558](https://en.wikipedia.org/wiki/Special:BookSources/978-0470160558 "Special:BookSources/978-0470160558").
+ 6. Lee, S. H.; Chen, W. (2009). "A comparative study of uncertainty propagation methods for black-box-type problems". _Structural and Multidisciplinary Optimization_. **37** (3): 239–253. [doi](https://en.wikipedia.org/wiki/Doi_(identifier) "Doi (identifier)"):[10.1007/s00158-008-0234-7](https://doi.org/10.1007%2Fs00158-008-0234-7).
+ 7. Johnson, Norman L.; Kotz, Samuel; Balakrishnan, Narayanaswamy (1994). _Continuous Univariate Distributions, Volume 1_. Wiley. p. 171. [ISBN](https://en.wikipedia.org/wiki/ISBN_(identifier) "ISBN (identifier)") [0-471-58495-9](https://en.wikipedia.org/wiki/Special:BookSources/0-471-58495-9 "Special:BookSources/0-471-58495-9").
+ 8. Lecomte, Christophe (May 2013). "Exact statistics of systems with uncertainties: an analytical theory of rank-one stochastic dynamic systems". _Journal of Sound and Vibrations_. **332** (11): 2750–2776. [doi](https://en.wikipedia.org/wiki/Doi_(identifier) "Doi (identifier)"):[10.1016/j.jsv.2012.12.009](https://doi.org/10.1016%2Fj.jsv.2012.12.009).
+ 9. ["A Summary of Error Propagation"](http://ipl.physics.harvard.edu/wp-uploads/2013/03/PS3_Error_Propagation_sp13.pdf) (PDF). p. 2. Retrieved 2016-04-04.
+ 10. ["Propagation of Uncertainty through Mathematical Operations"](http://web.mit.edu/fluids-modules/www/exper_techniques/2.Propagation_of_Uncertaint.pdf) (PDF). p. 5. Retrieved 2016-04-04.
+ 11. ["Strategies for Variance Estimation"](http://www.sagepub.com/upm-data/6427_Chapter_4__Lee_%28Analyzing%29_I_PDF_6.pdf) (PDF). p. 37. Retrieved 2013-01-18.
+ 12. Harris, Daniel C. (2003), [_Quantitative chemical analysis_](https://books.google.com/books?id=csTsQr-v0d0C&pg=PA56)(6th ed.), Macmillan, p. 56, [ISBN](https://en.wikipedia.org/wiki/ISBN_(identifier) "ISBN (identifier)") [978-0-7167-4464-1](https://en.wikipedia.org/wiki/Special:BookSources/978-0-7167-4464-1 "Special:BookSources/978-0-7167-4464-1")
+ 13. ["Error Propagation tutorial"](http://www.foothill.edu/psme/daley/tutorials_files/10.%20Error%20Propagation.pdf) (PDF). _Foothill College_. October 9, 2009. Retrieved 2012-03-01.
diff --git a/labfis/__init__.py b/labfis/__init__.py
index 3e4e35e..1a61054 100644
--- a/labfis/__init__.py
+++ b/labfis/__init__.py
@@ -3,7 +3,7 @@
# Copyright © 2020 labfis.py
# (see LICENSE for details)
-__version__ = '1.0.0'
+__version__ = '1.1.4'
# Local imports
from labfis.main import labfloat
diff --git a/labfis/main.py b/labfis/main.py
index bfc6d71..53329b7 100644
--- a/labfis/main.py
+++ b/labfis/main.py
@@ -1,4 +1,4 @@
-from math import floor, ceil, trunc, log, log10
+from math import floor, ceil, trunc, log, log10, sqrt
from numbers import Number
class LabFloatError(Exception):
@@ -26,12 +26,12 @@ def __init__(self, *args, **kwargs):
if args:
if len(args) == 1:
- mean = args[0]
+ mean = args[0]
elif len(args) == 2:
mean = args[0]
uncertainty = args[1]
else:
- raise LabFloatError("Too many arguments, expected (val,err), got: ",args)
+ raise LabFloatError("Too many arguments, expected (val,err) or ([(val,err),...]), got: ",args)
self.mean = float(mean)
self.uncertainty = abs(float(uncertainty))
@@ -77,29 +77,48 @@ def split(self):
else:
m, u = self.format()
return(["{:g}".format(m),"{:g}".format(u)])
-
- def tex(self):
- val = self.split()
- if len(val) == 1:
- m = val[0].split("e")
+
+ def tex(self,*args,**kwargs):
+ precision = kwargs.get('precision')
+ if args:
+ if len(args) == 2:
+ precision = args
+ elif len(args) > 2:
+ raise LabFloatError("Too many arguments, expected: (precision) or (mean precision,err precision) got: ",args)
+ else:
+ precision = [args[0],args[0]]
+
+ if self.uncertainty == 0:
+ if precision:
+ precision[0] = str(precision[0])
+ m = eval("'{:."+precision[0]+"e}'.format(self.mean)")
+ else:
+ m = self.split()[0]
+ m = m.split("e")
if len(m) > 1:
- m = m[0]+"\cdot 10^{"+m[1]+"}"
+ m = m[0]+r"\cdot 10^{"+m[1]+"}"
else:
m = m[0]
return("{0}".format(m))
else:
- m,u = val
+ if precision:
+ precision = (str(precision[0]),str(precision[1]))
+ m, u = self.format()
+ m = eval("'{:."+precision[0]+"e}'.format(m)")
+ u = eval("'{:."+precision[1]+"e}'.format(u)")
+ else:
+ m, u = self.split()
m = m.split("e")
u = u.split("e")
if len(m) > 1:
- m = m[0]+"\cdot 10^{"+m[1]+"}"
+ m = m[0]+r"\cdot 10^{"+m[1]+"}"
else:
m = m[0]
if len(u) > 1:
- u = u[0]+"\cdot 10^{"+u[1]+"}"
+ u = u[0]+r"\cdot 10^{"+u[1]+"}"
else:
u = u[0]
- return("({0}\, \pm \,{1})".format(m, u))
+ return(r"({0}\, \pm \,{1})".format(m, u))
def __str__(self):
val = self.split()
@@ -110,6 +129,10 @@ def __str__(self):
def __repr__(self):
return self.__str__()
+
+ def __getitem__(self, idx):
+ vals = [self.mean,self.uncertainty]
+ return vals[idx]
def __pos__(self):
return self
@@ -170,7 +193,7 @@ def __ge__(self,other):
def __add__(self, other):
if isinstance(other, labfloat):
- return labfloat(self.mean + other.mean, self.uncertainty + other.uncertainty)
+ return labfloat(self.mean + other.mean, sqrt(self.uncertainty ** 2 + other.uncertainty ** 2))
if isinstance(other, Number):
return labfloat(self.mean + other, self.uncertainty)
@@ -182,13 +205,13 @@ def __iadd__(self, other):
def __sub__(self, other):
if isinstance(other, labfloat):
- return labfloat(self.mean - other.mean, self.uncertainty + other.uncertainty)
+ return labfloat(self.mean - other.mean, sqrt(self.uncertainty ** 2 + other.uncertainty ** 2))
if isinstance(other, Number):
return labfloat(self.mean - other, self.uncertainty)
def __rsub__(self, other):
if isinstance(other, labfloat):
- pass
+ return labfloat(other.mean - self.mean, sqrt(other.uncertainty ** 2 + self.uncertainty ** 2))
if isinstance(other, Number):
return labfloat(other - self.mean, self.uncertainty)
@@ -197,9 +220,9 @@ def __isub__(self, other):
def __mul__(self, other):
if isinstance(other, labfloat):
- return labfloat(self.mean * other.mean, self.mean * other.uncertainty + other.mean * self.uncertainty)
+ return labfloat(self.mean * other.mean, sqrt((other.mean * self.uncertainty) ** 2 + (self.mean * other.uncertainty) ** 2))
if isinstance(other, Number):
- return labfloat(self.mean * other, other * self.uncertainty)
+ return labfloat(self.mean * other, abs(other * self.uncertainty))
def __rmul__(self, other):
return self.__mul__(other)
@@ -209,9 +232,9 @@ def __imul__(self, other):
def __div__(self, other):
if isinstance(other, labfloat):
- return labfloat(self.mean / other.mean, (self.mean * other.uncertainty + other.mean * self.uncertainty)/other.mean**2)
+ return labfloat(self.mean / other.mean, sqrt((self.uncertainty / other.mean) ** 2 + (self.mean * other.uncertainty / (other.mean ** 2)) ** 2 ))
if isinstance(other, Number):
- return labfloat(self.mean / other, self.uncertainty / other)
+ return labfloat(self.mean / other, abs(self.uncertainty / other))
def __truediv__(self, other):
return self.__div__(other)
@@ -224,24 +247,24 @@ def __itruediv__(self, other):
def __rdiv__(self, other):
if isinstance(other, labfloat):
- return labfloat(other.mean / self.mean, (other.mean * self.uncertainty + self.mean * other.uncertainty)/self.mean**2)
+ return labfloat(other.mean / self.mean, sqrt((other.uncertainty / self.mean) ** 2 + (other.mean * self.uncertainty / (self.mean ** 2)) ** 2 ))
if isinstance(other, Number):
- return labfloat(other / self.mean, other * self.uncertainty / self.mean ** 2)
+ return labfloat(other / self.mean, abs(other * self.uncertainty / self.mean ** 2))
def __rtruediv__(self, other):
return self.__rdiv__(other)
def __pow__(self, other):
if isinstance(other, labfloat):
- raise LabFloatError(0)
+ 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))
if isinstance(other, Number):
- return labfloat(self.mean ** other, other * self.mean ** (other-1) * self.uncertainty)
+ return labfloat(self.mean ** other, abs(other * self.mean ** (other - 1) * self.uncertainty))
def __rpow__(self, other):
if isinstance(other, labfloat):
- raise LabFloatError(0)
- if isinstance(other, (float, int, hex, oct, complex)):
- return labfloat(other ** self.mean, other ** self.mean * log(other) * self.uncertainty)
+ 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))
+ if isinstance(other, Number):
+ return labfloat(other ** self.mean, abs(other ** self.mean * log(abs(other)) * self.uncertainty))
def __ipow__(self, other):
return self.__pow__(other)