Example #1
0
    def plot(self, *expr_pairs, save=None, xunit=None, yunit=None, xrange=None, yrange=None, ignore_dim=False):
        """ Plots data or functions

        Args:
            expr_pairs: one or more pair of quantity on x-axis and on y-axis. e.g. ["p","V"]
                        y-axis can also be a function. e.g. ["t", "7*exp(t/t0)"]
            save: string of file name without extension. if specified, plot will be saved to '<save>.png'
            xunit: unit on x-axis. if not given, will find unit on its own
            yunit: unit on y-axis. if not given, will find unit on its own
            xrange: pair of x-axis range, e.g. [-5,10]
            yrange: pair of y-axis range
            ignore_dim: if True, will skip dimension check
        """

        if len(expr_pairs) == 0:#
            raise ValueError("nothing to plot specified.")

        expr_pairs_obj = []

        for expr_pair in expr_pairs:
            # parse expressions
            expr_pairs_obj.append( (quantities.parse_expr(expr_pair[0], self.data), quantities.parse_expr(expr_pair[1], self.data)) )

        if not xunit is None:
            xunit = units.parse_unit(xunit)[2]
        if not yunit is None:
            yunit = units.parse_unit(yunit)[2]
        if not xrange is None:
            xrange = [quantities.get_value(quantities.parse_expr(xrange[0], self.data)),
                      quantities.get_value(quantities.parse_expr(xrange[1], self.data))]
        if not yrange is None:
            yrange = [quantities.get_value(quantities.parse_expr(yrange[0], self.data)),
                      quantities.get_value(quantities.parse_expr(yrange[1], self.data))]
        return plotting.plot(expr_pairs_obj, self.config, save=save, xunit=xunit, yunit=yunit, xrange=xrange, yrange=yrange, ignore_dim=ignore_dim)
Example #2
0
    def plot(self,
             *expr_pairs,
             save=None,
             xunit=None,
             yunit=None,
             xrange=None,
             yrange=None,
             ignore_dim=False):
        """ Plots data or functions

        Args:
            expr_pairs: one or more pair of quantity on x-axis and on y-axis. e.g. ["p","V"]
                        y-axis can also be a function. e.g. ["t", "7*exp(t/t0)"]
            save: string of file name without extension. if specified, plot will be saved to '<save>.png'
            xunit: unit on x-axis. if not given, will find unit on its own
            yunit: unit on y-axis. if not given, will find unit on its own
            xrange: pair of x-axis range, e.g. [-5,10]
            yrange: pair of y-axis range
            ignore_dim: if True, will skip dimension check
        """

        if len(expr_pairs) == 0:  #
            raise ValueError("nothing to plot specified.")

        expr_pairs_obj = []

        for expr_pair in expr_pairs:
            # parse expressions
            expr_pairs_obj.append(
                (quantities.parse_expr(expr_pair[0], self.data),
                 quantities.parse_expr(expr_pair[1], self.data)))

        if not xunit is None:
            xunit = units.parse_unit(xunit)[2]
        if not yunit is None:
            yunit = units.parse_unit(yunit)[2]
        if not xrange is None:
            xrange = [
                quantities.get_value(
                    quantities.parse_expr(xrange[0], self.data)),
                quantities.get_value(
                    quantities.parse_expr(xrange[1], self.data))
            ]
        if not yrange is None:
            yrange = [
                quantities.get_value(
                    quantities.parse_expr(yrange[0], self.data)),
                quantities.get_value(
                    quantities.parse_expr(yrange[1], self.data))
            ]
        return plotting.plot(expr_pairs_obj,
                             self.config,
                             save=save,
                             xunit=xunit,
                             yunit=yunit,
                             xrange=xrange,
                             yrange=yrange,
                             ignore_dim=ignore_dim)
Example #3
0
    def fit(self, fit_function, xydata, parameters, weighted=None, plot=False, ignore_dim=False):
        """ fits function to data

        Args:
            fit_function: function to fit, e.g. "n*t**2 + m*t + b"
            xydata: pair of x-quantity and y-quantity of data to fit to, e.g. ["t","U"]
            parameters: list of parameters in fit function, e.g. ["n","m","b"]
            weighted: if True, will weight fit by errors (returns error if not possible)
                      if False, will not weight fit by errors
                      if None, will try to weight fit, but if at least one error is not given, will not weight it
            plot: Bool, if data and fit function should be plotted
            ignore_dim: if True, will ignore dimensions and just calculate in base units instead
        """


        if self.config["fit_module"] == "scipy":
            import errorpro.fit_scipy as fit_module
        else:
            raise ValueError("no fit module called '%s'." % self.config["fit_module"])

        # get parameter quantities
        parameters_obj = []
        for p in parameters:
            if isinstance(p, str):
                if not p in self.data:
                    self.data[p] = quantities.Quantity(p)
                    self.data[p].dim = Dimension()
                parameters_obj.append(self.data[p])
            elif isinstance(p, quantities.Quantity):
                parameters_obj.append(p)
            else:
                raise TypeError("parameters can only be strings or Quantity objects")

        # parse fit function
        fit_function = quantities.parse_expr(fit_function, self.data)

        # get data quantities
        x_data = quantities.parse_expr(xydata[0], self.data)
        # if x-data is an expression
        if not isinstance(x_data, quantities.Quantity):
            dummy = quantities.Quantity()
            fit_function = fit_function.subs(x_data,dummy)
            dummy.value = quantities.get_value(x_data)
            dummy.error = quantities.get_error(x_data)[0]
            dummy.dim = quantities.get_dimension(x_data)
            x_data = dummy
        y_data = quantities.parse_expr(xydata[1], self.data)
        # if y-data is an expression
        if not isinstance(y_data, quantities.Quantity):
            dummy = quantities.Quantity()
            dummy.value = quantities.get_value(y_data)
            dummy.error = quantities.get_error(y_data)[0]
            dummy.dim = quantities.get_dimension(y_data)
            y_data = dummy

        # check if dimension fits
        if not ignore_dim:
            try:
                dim_func = quantities.get_dimension(fit_function)
            except ValueError:
                dim_func = None
            if not dim_func == y_data.dim:
                # try to solve for dimensionless parameters
                known_dimensions = {x_data.name: x_data.dim}
                known_dimensions = dim_solve(fit_function, y_data.dim, known_dimensions)
                for q_name in known_dimensions:
                    if q_name in self.data:
                        if not self.data[q_name].dim == known_dimensions[q_name]:
                            self.data[q_name].dim = known_dimensions[q_name]
                            self.data[q_name].prefer_unit = None
                dim_func = quantities.get_dimension(fit_function)
                # if it still doesn't work, raise error
                if not dim_func == y_data.dim:
                    raise RuntimeError("Finding dimensions of fit parameters was not sucessful.\n"\
                                                     "Check fit function or specify parameter units manually.\n"\
                                                     "This error will occur until dimensions are right.")

        # fit
        values, errors = fit_module.fit(x_data, y_data, fit_function, parameters_obj, weighted)


        # save results
        i = 0
        for p in parameters_obj:
            p.value = values[i]
            p.value_formula = "fit"
            p.error = errors[i]
            p.error_formula = "fit"
            i += 1

        # plot
        if plot:
            return plotting.plot([(x_data, y_data), (x_data, fit_function)], self.config, ignore_dim=ignore_dim)
        else:
            return self.table(*parameters_obj)
Example #4
0
    def fit(self,
            fit_function,
            xydata,
            parameters,
            weighted=None,
            plot=False,
            ignore_dim=False):
        """ fits function to data

        Args:
            fit_function: function to fit, e.g. "n*t**2 + m*t + b"
            xydata: pair of x-quantity and y-quantity of data to fit to, e.g. ["t","U"]
            parameters: list of parameters in fit function, e.g. ["n","m","b"]
            weighted: if True, will weight fit by errors (returns error if not possible)
                      if False, will not weight fit by errors
                      if None, will try to weight fit, but if at least one error is not given, will not weight it
            plot: Bool, if data and fit function should be plotted
            ignore_dim: if True, will ignore dimensions and just calculate in base units instead
        """

        if self.config["fit_module"] == "scipy":
            import errorpro.fit_scipy as fit_module
        else:
            raise ValueError("no fit module called '%s'." %
                             self.config["fit_module"])

        # get parameter quantities
        parameters_obj = []
        for p in parameters:
            if isinstance(p, str):
                if not p in self.data:
                    self.data[p] = quantities.Quantity(p)
                    self.data[p].dim = Dimension()
                parameters_obj.append(self.data[p])
            elif isinstance(p, quantities.Quantity):
                parameters_obj.append(p)
            else:
                raise TypeError(
                    "parameters can only be strings or Quantity objects")

        # parse fit function
        fit_function = quantities.parse_expr(fit_function, self.data)

        # get data quantities
        x_data = quantities.parse_expr(xydata[0], self.data)
        # if x-data is an expression
        if not isinstance(x_data, quantities.Quantity):
            dummy = quantities.Quantity()
            fit_function = fit_function.subs(x_data, dummy)
            dummy.value = quantities.get_value(x_data)
            dummy.error = quantities.get_error(x_data)[0]
            dummy.dim = quantities.get_dimension(x_data)
            x_data = dummy
        y_data = quantities.parse_expr(xydata[1], self.data)
        # if y-data is an expression
        if not isinstance(y_data, quantities.Quantity):
            dummy = quantities.Quantity()
            dummy.value = quantities.get_value(y_data)
            dummy.error = quantities.get_error(y_data)[0]
            dummy.dim = quantities.get_dimension(y_data)
            y_data = dummy

        # check if dimension fits
        if not ignore_dim:
            try:
                dim_func = quantities.get_dimension(fit_function)
            except ValueError:
                dim_func = None
            if not dim_func == y_data.dim:
                # try to solve for dimensionless parameters
                known_dimensions = {x_data.name: x_data.dim}
                known_dimensions = dim_solve(fit_function, y_data.dim,
                                             known_dimensions)
                for q_name in known_dimensions:
                    if q_name in self.data:
                        if not self.data[q_name].dim == known_dimensions[
                                q_name]:
                            self.data[q_name].dim = known_dimensions[q_name]
                            self.data[q_name].prefer_unit = None
                dim_func = quantities.get_dimension(fit_function)
                # if it still doesn't work, raise error
                if not dim_func == y_data.dim:
                    raise RuntimeError("Finding dimensions of fit parameters was not sucessful.\n"\
                                                     "Check fit function or specify parameter units manually.\n"\
                                                     "This error will occur until dimensions are right.")

        # fit
        values, errors = fit_module.fit(x_data, y_data, fit_function,
                                        parameters_obj, weighted)

        # save results
        i = 0
        for p in parameters_obj:
            p.value = values[i]
            p.value_formula = "fit"
            p.error = errors[i]
            p.error_formula = "fit"
            i += 1

        # plot
        if plot:
            return plotting.plot([(x_data, y_data), (x_data, fit_function)],
                                 self.config,
                                 ignore_dim=ignore_dim)
        else:
            return self.table(*parameters_obj)