def test_concat(self): p = Project() p.data["a"] = Quantity("a") p.data["a"].value = np.float_([1, 2, 3]) p.data["b"] = Quantity("b") p.data["b"].value = np.float_(4) p.concat("c", "a", "b") self.assertTrue((p.data["c"].value == np.float_([1, 2, 3, 4])).all())
def test_plot(self): p = Project() p.data["x"]=Quantity("x") p.data["y"]=Quantity("y") p.data["y"].value_prefUnit = si["ms"] p.data["x"].value = np.float_([0,1,2,3,4,5]) p.data["x"].error = np.float_([0.1,0.1,0.2,0.3,0.4,0.3]) p.data["x"].dim = Dimension(time=1) p.data["y"].value = np.float_([1,2.3,1.8,3.4,4.5,8]) p.data["y"].dim = Dimension(time=1) p.plot(("x","y"))
def test_formula(self): p = Project() p.data["U_I"] = Quantity("U_I") p.data["I_I"] = Quantity("I_I") u_err = Symbol("U_I_err", positive=True) i_err = Symbol("I_I_err", positive=True) p.data["Z_I"] = Quantity("Z_I", "Impedanz") p.data["Z_I"].error_formula = u_err * i_err + p.data["U_I"] * p.data[ "I_I"]**2 self.assertEqual( p.formula("Z_I", True), r"\sigma{\left (Z_{I} \right )} = I_{I}^{2} U_{I} + \sigma{\left (I_{I} \right )} \sigma{\left (U_{I} \right )}" )
def plot(expr_pairs, config, save=None, xunit=None, yunit=None, xrange=None, yrange=None, ignore_dim=False): # TODO it should be possible to e.g. plot the function [t,2*r] if r depends on t # one or multiple things to plot if len(expr_pairs) > 1: single_plot = False else: single_plot = True x_dim = None y_dim = None data_sets = [] functions = [] if ignore_dim: xunit = S.One yunit = S.One for expr_pair in expr_pairs: x = expr_pair[0] y = expr_pair[1] if not ignore_dim: # check dimensions if x_dim is None: x_dim = get_dimension(x) else: if not x_dim == get_dimension(x): raise RuntimeError("dimension mismatch\n%s != %s" % (x_dim, get_dimension(x))) if y_dim is None: y_dim = get_dimension(y) else: if not y_dim == get_dimension(y): raise RuntimeError("dimension mismatch\n%s != %s" % (y_dim, get_dimension(y))) # if y contains x, it must be a function dummy = Quantity() rep_y = y.subs(x,dummy) if rep_y.has(dummy): # get titles if isinstance(x, Quantity): x_title = ((x.longname + " ") if x.longname else "") + str(x) else: x_title = str(x) y_title = str(y) # check if x not only quantity but more complicated expression if not isinstance(x,Quantity): # replace by Dummy y = rep_y x = dummy if not ignore_dim: # get factors x_factor, xunit = convert_to_unit(x_dim, outputUnit=xunit) y_factor, yunit = convert_to_unit(y_dim, outputUnit=yunit) # scale function to units y = y.subs(x,x*x_factor) / y_factor # if only one thing on plot, write labels to x-axis and y-axis if single_plot: title = None x_label = x_title + ("" if xunit == S.One else " [" + str(xunit) + "]") y_label = y_title + ("" if yunit == S.One else " [" + str(yunit) + "]") # if more than one thing, use legend for title else: title = y_title functions.append({"x":x,"term":y,"title":title}) # if y doesn't contain x, it must be a data set else: # calculate expressions first if necessary if isinstance(expr_pair[0], Quantity): x = expr_pair[0] x_title = ((x.longname + " ") if x.longname else "") + str(x) else: # dummy quantity for calculation x = Quantity() x.value = get_value(expr_pair[0]) x.error = get_error(expr_pair[0])[0] x.dim = x_dim x_title = str(expr_pair[0]) if isinstance(expr_pair[1], Quantity): y = expr_pair[1] y_title = ((y.longname + " ") if y.longname else "") + str(y) else: # dummy quantity for calculation y = Quantity() y.value = get_value(expr_pair[1]) y.error = get_error(expr_pair[1])[0] y.dim = y_dim y_title = str(expr_pair[1]) if ignore_dim: x_values = x.value x_errors = x.error y_values = y.value y_errors = y.error else: # get values and errors all in one unit x_values, x_errors, xunit = adjust_to_unit(x, unit = xunit) y_values, y_errors, yunit = adjust_to_unit(y, unit = yunit) # if only one thing on plot, write labels to x-axis and y-axis if single_plot: title = None x_label = x_title + ("" if xunit == S.One else " [" + str(xunit) + "]") y_label = y_title + ("" if yunit == S.One else " [" + str(yunit) + "]") # if more than one thing, use legend for title else: title = y_title data_sets.append({"x_values": x_values, "y_values": y_values, "x_errors": x_errors, "y_errors":y_errors, "title": title}) # if more than one thing on plot, write only units to axes if not single_plot: x_label = ("" if xunit == S.One else "[" + str(xunit) + "]") y_label = ("" if yunit == S.One else "[" + str(yunit) + "]") # plot if config["plot_module"] == "matplotlib": from errorpro import plot_mat return plot_mat.plot(data_sets, functions, save=save, xrange=xrange, yrange=yrange, x_label=x_label, y_label=y_label) elif config["plot_module"] == "gnuplot": from errorpro import plot_gnu return plot_gnu.plot(data_sets, functions, save=save, xrange=xrange, yrange=yrange, x_label=x_label, y_label=y_label) else: raise ValueError("There is not plot module called '%s'" % config["plot_module"])
import errorpro.plot_mat as matplot import numpy as np from errorpro.dimensions.dimensions import Dimension from errorpro.si import system as si from errorpro.quantities import Quantity # not suitable for automated testing, so must be tested manually if __name__ == '__main__': # single data set data = { "t": Quantity("t", "Zeit"), "v": Quantity("v", "Geschwindigkeit"), "t0": Quantity("t0", "Startzeit"), "e": Quantity("e", "Bremsdings"), "s": Quantity("s", "Startgeschwindigkeit") } data["t"].value = np.float_([0, 1, 2, 3, 4, 5]) data["t"].dim = Dimension(time=1) data["v"].value = np.float_([33, 23, 14, 10, 7, 3]) data["v"].error = np.float_([1, 2, 1.3, 2.1, 0.5, 0.6]) data["v"].value_prefUnit = si["km"] / si["h"] data["v"].dim = Dimension(length=1, time=-1) matplot.plot([(data["t"], data["v"])], [], si)
def test_fit(self): # test fit_scipy on its own a = Quantity("a") a.value = np.float_([1,3,5,6,7,9]) b = Quantity("b") b.value = np.float_([2.3,4,5.5,6,9.2,10.5]) c = Quantity("c") c.value = np.float_(1) d = Quantity("d") d.value = np.float_(1) f = a*c+d popt,perr = (sc.fit(a,b,f,[c,d])) small = 0.0001 self.assertTrue(abs(popt[0] - 1.05184) < small) self.assertTrue(abs(perr[0] - 0.1328) < small) self.assertTrue(abs(popt[1] - 0.81551) < small) self.assertTrue(abs(perr[1] - 0.7684) < small) # test fit command small = 0.001 p = Project() g = commands.Assignment("x") g.value = ["1","2","3"] g.value_unit = "A" g.execute(p) g = commands.Assignment("y") g.value = ["6","3","2.1"] g.value_unit = "C" g.error = ["1","1","2"] g.error_unit = "1e-1*C" g.execute(p) h = commands.Assignment("m") h.value = "1" h.value_unit = "s" h.execute(p) i = commands.Assignment("b") i.value = "1" i.value_unit = "C" i.execute(p) p.fit("m*x+b",("x","y"),["m","b"]) self.assertTrue(abs(p.data["m"].value - (-2.3)) < small) self.assertTrue(abs(p.data["m"].error - 0.7) < small) self.assertTrue(abs(p.data["b"].value - 8.06667) < small) self.assertTrue(abs(p.data["b"].error - 1.257) < small) p.fit("m*x+b",("x","y"),["m","b"],weighted=False) self.assertTrue(abs(p.data["m"].value - (-1.95)) < small) self.assertTrue(abs(p.data["m"].error - 0.6062) < small) self.assertTrue(abs(p.data["b"].value - 7.6) < small) self.assertTrue(abs(p.data["b"].error - 1.31) < small) p.data["y"].error = None self.assertRaises(RuntimeError,p.fit,"m*x+b",("x","y"),["m","b"],weighted=True)
def assign(value, error=None, unit=None, name=None, longname=None, value_unit=None, error_unit=None, ignore_dim=False): """ function to create a new quantity Args: value: number or string that can be parsed by numpy, or sympy expression. If it's a sympy expression containing quantities, it will perform the calculation, otherwise it just saves the value. error: number that is saved as the value's uncertainty. this will replace any error coming from a calculation. unit: sympy expression of Unit objects. This is used to convert and save value and error in base units. Replaces value_unit and error_unit if specified. name: short name of the quantity (usually one letter). If not specified, quantity will get a dummy name. longname: optional additional description of the quantity value_unit: unit of value. Use this if value and error have different units. error_unit: unit of error. ignore_dim: bool. Keeps function from raising an error even if calculated and given unit don't match. Then given unit is used instead. """ value_formula = None value_factor = 1 value_dim = Dimension() error_formula = None error_factor = 1 error_dim = Dimension() # parse units if unit is not None: # if one general unit is given value_factor, value_dim, value_unit = parse_unit(unit) error_factor = value_factor error_dim = value_dim error_unit = value_unit else: # if value unit is given if value_unit is not None: value_factor, value_dim, value_unit = parse_unit(value_unit) # if error unit is given if error_unit is not None: error_factor, error_dim, error_unit = parse_unit(error_unit) # check dimension consistency between value_dim and error_dim if value_unit is not None and not value_dim == error_dim: raise RuntimeError("dimension mismatch\n%s != %s" % (value_dim, error_dim)) # process value # if it's a calculation if isinstance(value, Expr) and not value.is_number: value_formula = value value = get_value(value_formula) if ignore_dim: # with ignore_dim=True, calculated value is converted to given unit value = np.float_(value_factor)*np.float_(value) else: # calculate dimension from dependency calculated_dim = get_dimension(value_formula) if value_unit is None: value_dim = calculated_dim else: if not calculated_dim == value_dim: raise RuntimeError("dimension mismatch \n%s != %s" % (value_dim, calculated_dim)) # if it's a number else: value=np.float_(value_factor)*np.float_(value) # process error if error is not None: error=np.float_(error_factor)*np.float_(error) # check value and error shapes and duplicate error in case if error.shape == () or value.shape[-len(error.shape):] == error.shape: error = np.resize(error, value.shape) else: raise RuntimeError("length of value and error don't match and "\ "can't be adjusted by duplicating.\n"\ "%s and %s" % (value.shape, error.shape)) # if error can be calculated elif value_formula is not None: error, error_formula = get_error(value_formula) if ignore_dim: # with ignore_dim=True, calculated error is converted to given unit error = np.float_(error_factor)*np.float_(error) q = Quantity(name, longname) q.value = value q.value_formula = value_formula q.error = error q.error_formula = error_formula if value_unit is not None: q.prefer_unit = value_unit else: q.prefer_unit = error_unit q.dim = value_dim return q
def test_fit(self): # test fit_scipy on its own a = Quantity("a") a.value = np.float_([1, 3, 5, 6, 7, 9]) b = Quantity("b") b.value = np.float_([2.3, 4, 5.5, 6, 9.2, 10.5]) c = Quantity("c") c.value = np.float_(1) d = Quantity("d") d.value = np.float_(1) f = a * c + d popt, perr = (sc.fit(a, b, f, [c, d])) small = 0.0001 self.assertTrue(abs(popt[0] - 1.05184) < small) self.assertTrue(abs(perr[0] - 0.1328) < small) self.assertTrue(abs(popt[1] - 0.81551) < small) self.assertTrue(abs(perr[1] - 0.7684) < small) # test fit command small = 0.001 p = Project() g = commands.Assignment("x") g.value = ["1", "2", "3"] g.value_unit = "A" g.execute(p) g = commands.Assignment("y") g.value = ["6", "3", "2.1"] g.value_unit = "C" g.error = ["1", "1", "2"] g.error_unit = "1e-1*C" g.execute(p) h = commands.Assignment("m") h.value = "1" h.value_unit = "s" h.execute(p) i = commands.Assignment("b") i.value = "1" i.value_unit = "C" i.execute(p) p.fit("m*x+b", ("x", "y"), ["m", "b"]) self.assertTrue(abs(p.data["m"].value - (-2.3)) < small) self.assertTrue(abs(p.data["m"].error - 0.7) < small) self.assertTrue(abs(p.data["b"].value - 8.06667) < small) self.assertTrue(abs(p.data["b"].error - 1.257) < small) p.fit("m*x+b", ("x", "y"), ["m", "b"], weighted=False) self.assertTrue(abs(p.data["m"].value - (-1.95)) < small) self.assertTrue(abs(p.data["m"].error - 0.6062) < small) self.assertTrue(abs(p.data["b"].value - 7.6) < small) self.assertTrue(abs(p.data["b"].error - 1.31) < small) p.data["y"].error = None self.assertRaises(RuntimeError, p.fit, "m*x+b", ("x", "y"), ["m", "b"], weighted=True)
def plot(expr_pairs, config, save=None, xunit=None, yunit=None, xrange=None, yrange=None, ignore_dim=False): # TODO it should be possible to e.g. plot the function [t,2*r] if r depends on t # one or multiple things to plot if len(expr_pairs) > 1: single_plot = False else: single_plot = True x_dim = None y_dim = None data_sets = [] functions = [] if ignore_dim: xunit = S.One yunit = S.One for expr_pair in expr_pairs: x = expr_pair[0] y = expr_pair[1] if not ignore_dim: # check dimensions if x_dim is None: x_dim = get_dimension(x) else: if not x_dim == get_dimension(x): raise RuntimeError("dimension mismatch\n%s != %s" % (x_dim, get_dimension(x))) if y_dim is None: y_dim = get_dimension(y) else: if not y_dim == get_dimension(y): raise RuntimeError("dimension mismatch\n%s != %s" % (y_dim, get_dimension(y))) # if y contains x, it must be a function dummy = Quantity() rep_y = y.subs(x, dummy) if rep_y.has(dummy): # get titles if isinstance(x, Quantity): x_title = ((x.longname + " ") if x.longname else "") + str(x) else: x_title = str(x) y_title = str(y) # check if x not only quantity but more complicated expression if not isinstance(x, Quantity): # replace by Dummy y = rep_y x = dummy if not ignore_dim: # get factors x_factor, xunit = convert_to_unit(x_dim, outputUnit=xunit) y_factor, yunit = convert_to_unit(y_dim, outputUnit=yunit) # scale function to units y = y.subs(x, x * x_factor) / y_factor # if only one thing on plot, write labels to x-axis and y-axis if single_plot: title = None x_label = x_title + ("" if xunit == S.One else " [" + str(xunit) + "]") y_label = y_title + ("" if yunit == S.One else " [" + str(yunit) + "]") # if more than one thing, use legend for title else: title = y_title functions.append({"x": x, "term": y, "title": title}) # if y doesn't contain x, it must be a data set else: # calculate expressions first if necessary if isinstance(expr_pair[0], Quantity): x = expr_pair[0] x_title = ((x.longname + " ") if x.longname else "") + str(x) else: # dummy quantity for calculation x = Quantity() x.value = get_value(expr_pair[0]) x.error = get_error(expr_pair[0])[0] x.dim = x_dim x_title = str(expr_pair[0]) if isinstance(expr_pair[1], Quantity): y = expr_pair[1] y_title = ((y.longname + " ") if y.longname else "") + str(y) else: # dummy quantity for calculation y = Quantity() y.value = get_value(expr_pair[1]) y.error = get_error(expr_pair[1])[0] y.dim = y_dim y_title = str(expr_pair[1]) if ignore_dim: x_values = x.value x_errors = x.error y_values = y.value y_errors = y.error else: # get values and errors all in one unit x_values, x_errors, xunit = adjust_to_unit(x, unit=xunit) y_values, y_errors, yunit = adjust_to_unit(y, unit=yunit) # if only one thing on plot, write labels to x-axis and y-axis if single_plot: title = None x_label = x_title + ("" if xunit == S.One else " [" + str(xunit) + "]") y_label = y_title + ("" if yunit == S.One else " [" + str(yunit) + "]") # if more than one thing, use legend for title else: title = y_title data_sets.append({ "x_values": x_values, "y_values": y_values, "x_errors": x_errors, "y_errors": y_errors, "title": title }) # if more than one thing on plot, write only units to axes if not single_plot: x_label = ("" if xunit == S.One else "[" + str(xunit) + "]") y_label = ("" if yunit == S.One else "[" + str(yunit) + "]") # plot if config["plot_module"] == "matplotlib": from errorpro import plot_mat return plot_mat.plot(data_sets, functions, save=save, xrange=xrange, yrange=yrange, x_label=x_label, y_label=y_label) elif config["plot_module"] == "gnuplot": from errorpro import plot_gnu return plot_gnu.plot(data_sets, functions, save=save, xrange=xrange, yrange=yrange, x_label=x_label, y_label=y_label) else: raise ValueError("There is not plot module called '%s'" % config["plot_module"])