I'm using python with numpy, scipy and matplotlib for data evaluation. As results I obtain averages and fitting parameters with errorbars.
I would like python to automatically pretty-print this data according to a given precision. For example:
Suppose I got the result x = 0.012345 +/- 0.000123
.
Is there a way to automatically format this as 1.235(12) x 10^-2
when a precision of 2 was specified. That is, counting the precision in the errorbar, rather than in the value.
Does anyone know a package that provides such functionality, or would I have to implement this myself?
Is there a way to inject this into the python string formatting mechanism? I.e. being able to write something like "%.2N" % (0.012345, 0.0000123)
.
I already looked through the docs of numpy and scipy and googled around, but I couldn't find anything. I think this would be a useful feature for everyone who deals with statistics.
Thanks for your help!
EDIT: As requested by Nathan Whitehead I'll give a few examples.
123 +- 1 ----precision 1-----> 123(1)
123 +- 1.1 ----precision 2-----> 123.0(11)
0.0123 +- 0.001 ----precision 1-----> 0.012(1)
123.111 +- 0.123 ----precision 2-----> 123.11(12)
The powers of ten are omitted for clarity. The number inside the parenthesis is a shorthand notation for the standard error. The last digit of the number before the parens and the last digit of the number inside the parens have to be at the same decimal power. For some reason I cannot find a good explanation of this concept online. Only thing I got is this German Wikpedia article here. However, it is a quite common and very handy notation.
EDIT2: I implemented the shorthand notation thing myself:
#!/usr/bin/env python
# *-* coding: utf-8 *-*
from math import floor, log10
# uncertainty to string
def un2str(x, xe, precision=2):
"""pretty print nominal value and uncertainty
x - nominal value
xe - uncertainty
precision - number of significant digits in uncertainty
returns shortest string representation of `x +- xe` either as
x.xx(ee)e+xx
or as
xxx.xx(ee)"""
# base 10 exponents
x_exp = int(floor(log10(x)))
xe_exp = int(floor(log10(xe)))
# uncertainty
un_exp = xe_exp-precision+1
un_int = round(xe*10**(-un_exp))
# nominal value
no_exp = un_exp
no_int = round(x*10**(-no_exp))
# format - nom(unc)exp
fieldw = x_exp - no_exp
fmt = '%%.%df' % fieldw
result1 = (fmt + '(%.0f)e%d') % (no_int*10**(-fieldw), un_int, x_exp)
# format - nom(unc)
fieldw = max(0, -no_exp)
fmt = '%%.%df' % fieldw
result2 = (fmt + '(%.0f)') % (no_int*10**no_exp, un_int*10**max(0, un_exp))
# return shortest representation
if len(result2) <= len(result1):
return result2
else:
return result1
if __name__ == "__main__":
xs = [123456, 12.34567, 0.123456, 0.001234560000, 0.0000123456]
xes = [ 123, 0.00123, 0.000123, 0.000000012345, 0.0000001234]
precs = [ 1, 2, 3, 4, 1]
for (x, xe, prec) in zip(xs, xes, precs):
print '%.6e +- %.6e @%d --> %s' % (x, xe, prec, un2str(x, xe, prec))
Output:
1.234560e+05 +- 1.230000e+02 @1 --> 1.235(1)e5
1.234567e+01 +- 1.230000e-03 @2 --> 12.3457(12)
1.234560e-01 +- 1.230000e-04 @3 --> 0.123456(123)
1.234560e-03 +- 1.234500e-08 @4 --> 0.00123456000(1235)
1.234560e-05 +- 1.234000e-07 @1 --> 1.23(1)e-5
For people that are still interested in this question, see the gvar
library and here for an example of (at last part of) the desired behavior by the OP.
since x +- y
is not a standard type (it could be seen as a complex with real and imaginary as x and y i guess, but that does not simplify anything...) but you can get full control over the presentation by creating a type and overriding the string function, i.e. something like this
class Res(object):
def __init__(self, res, delta):
self.res = res
self.delta = delta
def __str__(self):
return "%f +- %f"%(self.res,self.delta)
if __name__ == '__main__':
x = Res(0.2710,0.001)
print(x)
print(" a result: %s" % x)
you could naturally do something a bit more fancy inside the __str__
function...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With