def __set_expression(self, val): if val == '': val = None self._expr = val if val is not None: self.vary = False if not hasattr(self, '_expr_eval'): self._expr_eval = None if val is None: self._expr_ast = None if val is not None and self._expr_eval is not None: self._expr_ast = self._expr_eval.parse(val) check_ast_errors(self._expr_eval) self._expr_deps = get_ast_names(self._expr_ast)
def __set_expression(self, val): if val == '': val = None self._expr = val if val is not None: self.vary = False if not hasattr(self, '_expr_eval'): self._expr_eval = None if val is None: self._expr_ast = None if val is not None and self._expr_eval is not None: self._expr_eval.error = [] self._expr_eval.error_msg = None self._expr_ast = self._expr_eval.parse(val) check_ast_errors(self._expr_eval) self._expr_deps = get_ast_names(self._expr_ast)
def __init__(self, expr, independent_vars=None, init_script=None, nan_policy='raise', **kws): """Generate a model from user-supplied expression. Parameters ---------- expr : str Mathematical expression for model. independent_vars : list of str or None, optional Variable names to use as independent variables. init_script : str or None, optional Initial script to run in asteval interpreter. nan_policy : str, optional How to handle NaN and missing values in data. Must be one of: 'raise' (default), 'propagate', or 'omit'. See Notes below. missing : str, optional Synonym for 'nan_policy' for backward compatibility. **kws : optional Keyword arguments to pass to :class:`Model`. Notes ----- 1. each instance of ExpressionModel will create and using its own version of an asteval interpreter. 2. prefix is **not supported** for ExpressionModel. 3. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of: - 'raise' : Raise a ValueError (default) - 'propagate' : do nothing - 'omit' : (was 'drop') drop missing data 4. The `missing` argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use `nan_policy` instead, as it is consistent with the Minimizer class. """ # create ast evaluator, load custom functions self.asteval = Interpreter() for name in lineshapes.functions: self.asteval.symtable[name] = getattr(lineshapes, name, None) if init_script is not None: self.asteval.eval(init_script) # save expr as text, parse to ast, save for later use self.expr = expr.strip() self.astcode = self.asteval.parse(self.expr) # find all symbol names found in expression sym_names = get_ast_names(self.astcode) if independent_vars is None and 'x' in sym_names: independent_vars = ['x'] if independent_vars is None: raise ValueError(self.idvar_missing % (self.expr)) # determine which named symbols are parameter names, # try to find all independent variables idvar_found = [False] * len(independent_vars) param_names = [] for name in sym_names: if name in independent_vars: idvar_found[independent_vars.index(name)] = True elif name not in param_names and name not in self.asteval.symtable: param_names.append(name) # make sure we have all independent parameters if not all(idvar_found): lost = [] for ix, found in enumerate(idvar_found): if not found: lost.append(independent_vars[ix]) lost = ', '.join(lost) raise ValueError(self.idvar_notfound % (lost, self.expr)) kws['independent_vars'] = independent_vars if 'prefix' in kws: raise Warning(self.no_prefix) def _eval(**kwargs): for name, val in kwargs.items(): self.asteval.symtable[name] = val return self.asteval.run(self.astcode) kws["nan_policy"] = nan_policy super(ExpressionModel, self).__init__(_eval, **kws) # set param names here, and other things normally # set in _parse_params(), which will be short-circuited. self.independent_vars = independent_vars self._func_allargs = independent_vars + param_names self._param_names = param_names self._func_haskeywords = True self.def_vals = {}