I don't know how exactly is called what I want to do. I'm also a new user of Python. Basically I have created a very simple class that is intended to represent measured quantities of the form
and automatically do the error propagation. Here's the definition:
from math import sqrt
from math import log10
from math import fabs
from math import floor
from math import ceil
from math import pi
class magnitude:
def __init__(self, val, err):
self.val = val
self.err = err
def __str__(self):
"Prints the magnitude in the format v.vvvv(v+-e) being 'v' the relevant digits of the magnitude value and '+-e' the most significant digit of the error."
if self.err == 0 or self.val == 0:
return str(self.val)
if self.err >= fabs(self.val):
return '{:.0e} +- {:.0e}'.format(self.val, self.err) + ' (Infinite uncertainty!)'
else:
temp = '{:.' + str(ceil(log10(fabs(self.val*(1+pi*1e-3))) - ceil(log10(self.err*(1+pi*1e-3))) )) + 'e}' # Calculates number of digits for the representative part. The adition of 'pi*1e-3' is to add some noise and avoid error values of '1', '10', '100', ..., because they are not well printed.
temp = temp.format(self.val)
temp = temp[:-4] # Remove last 4 chars.
return temp + '(+-' + str(int(self.err*10**(ceil(-log10(self.err))))) + ')' + '{:.0e}'.format(fabs(self.val))[1:] + ' ({:d} ppm)'.format(int(self.err/fabs(self.val)*1e6))
# --------------------
def __add__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val + other.val, sqrt(self.err**2 + other.err**2))
def __radd__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val + other.val, sqrt(self.err**2 + other.err**2))
# --------------------
def __sub__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val - other.val, sqrt(self.err**2 + other.err**2))
def __rsub__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(-self.val + other.val, sqrt(self.err**2 + other.err**2))
# --------------------
def __mul__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val*other.val, sqrt(self.val**2*other.err**2 + self .err**2*other.val**2))
def __rmul__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val*other.val, sqrt(self.val**2*other.err**2 + self .err**2*other.val**2))
# --------------------
def __truediv__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(self.val/other.val, sqrt(self.err**2/other.val**2 + self.val**2/other.val**2*other.err**2))
def __rtruediv__(self, other):
if type(other) == int or type(other) == float:
other = magnitude(other, 0)
return magnitude(other.val/self.val, sqrt(other.err**2/self.val**2 + other.val**2/self.val**2*self.err**2))
Now what I want is to overload the matplotlib plot function in order to tell it how this should be plotted, i.e. a bold line for the magnitude.val value and two thin lines surrounding it with a distance of magnitude.err.
How should I do this?