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())
Example #2
0
    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 )}"
        )
Example #4
0
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"])
Example #5
0
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)
Example #6
0
    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)
Example #7
0
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
Example #8
0
    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)
Example #9
0
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"])