def test_custom_symtable(self): "test making and using a custom symbol table" if HAS_NUMPY: def cosd(x): "cos with angle in degrees" return np.cos(np.radians(x)) def sind(x): "sin with angle in degrees" return np.sin(np.radians(x)) def tand(x): "tan with angle in degrees" return np.tan(np.radians(x)) sym_table = make_symbol_table(cosd=cosd, sind=sind, tand=tand) aeval = Interpreter(symtable=sym_table) aeval("x1 = sind(30)") aeval("x2 = cosd(30)") aeval("x3 = tand(45)") x1 = aeval.symtable['x1'] x2 = aeval.symtable['x2'] x3 = aeval.symtable['x3'] assert_allclose(x1, 0.50, rtol=0.001) assert_allclose(x2, 0.866025, rtol=0.001) assert_allclose(x3, 1.00, rtol=0.001)
def evaluate(eval_code, input_variables={}, output_variables=[]): """Evaluates a given expression, with the timeout given as decorator. Args: eval_code (str): The code to be evaluated. input_variables (dict): dictionary of input variables and their values. output_variables (array): array of names of output variables. Returns: dict: the output variables or empty. """ # FIXME: use_numpy the process blocks infinitely at the return statement import time sym = make_symbol_table(time=time, use_numpy=False, range=range, **input_variables) aeval = Interpreter( symtable = sym, use_numpy = False, no_if = False, no_for = False, no_while = False, no_try = True, no_functiondef = True, no_ifexp = False, no_listcomp = True, no_augassign = False, # e.g., a += 1 no_assert = True, no_delete = True, no_raise = True, no_print = False) aeval(eval_code) symtable = {x: sym[x] for x in sym if x in output_variables} return symtable
def __init__(self, label: str = None, root_group: ParameterGroup = None): """Initialize a :class:`ParameterGroup` instance with ``label``. Parameters ---------- label : str The label of the group. root_group : ParameterGroup The root group Raises ------ ValueError Raised if the an invalid label is given. """ if label is not None and not Parameter.valid_label(label): raise ValueError(f"'{label}' is not a valid group label.") self._label = label self._parameters: dict[str, Parameter] = {} self._root_group = root_group self._evaluator = (asteval.Interpreter( symtable=asteval.make_symbol_table( group=self)) if root_group is None else None) self.source_path = "parameters.csv" super().__init__()
def test_custom_symtable(self): "test making and using a custom symbol table" def cosd(x): "cos with angle in degrees" return np.cos(np.radians(x)) def sind(x): "sin with angle in degrees" return np.sin(np.radians(x)) def tand(x): "tan with angle in degrees" return np.tan(np.radians(x)) sym_table = make_symbol_table(cosd=cosd, sind=sind, tand=tand) aeval = Interpreter(symtable=sym_table) aeval("x1 = sind(30)") aeval("x2 = cosd(30)") aeval("x3 = tand(45)") x1 = aeval.symtable['x1'] x2 = aeval.symtable['x2'] x3 = aeval.symtable['x3'] assert_allclose(x1, 0.50, rtol=0.001) assert_allclose(x2, 0.866025, rtol=0.001) assert_allclose(x3, 1.00, rtol=0.001)
def __call__(self, parents, accumulator) -> str: """ Execute an action and ship its result """ parent_symbols = { k: ParentSymbol(accumulator[v.id_]) for k, v in self.format_node_names(parents).items() } # children_symbols = {k: ChildSymbol(v.id_) for k, v in self.format_node_names(children).items()} syms = make_symbol_table(use_numpy=False, **parent_symbols) aeval = Interpreter(usersyms=syms, no_while=True, no_try=True, no_functiondef=True, no_ifexp=False, no_augassign=True, no_assert=True, no_delete=True, no_raise=True, no_print=True, use_numpy=False, builtins_readonly=True) aeval(self.transform) output = aeval.symtable.get("result", None) if len(aeval.error) > 0: raise TransformException return output
def __init__(self, load_scipy=False, load_numpy=False): # File opening and other unneeded functions could be dropped unwanted = ['open', 'type', 'dir', 'id', 'str', 'repr'] # Allowed symbol table. Add more if needed. new_syms = { 'np_arange': getattr(np, 'arange'), 'ensemble_ExtraTreesClassifier': getattr(ensemble, 'ExtraTreesClassifier') } syms = make_symbol_table(use_numpy=False, **new_syms) if load_scipy: scipy_distributions = scipy.stats.distributions.__dict__ for key in scipy_distributions.keys(): if isinstance( scipy_distributions[key], (scipy.stats.rv_continuous, scipy.stats.rv_discrete)): syms['scipy_stats_' + key] = scipy_distributions[key] if load_numpy: from_numpy_random = [ 'beta', 'binomial', 'bytes', 'chisquare', 'choice', 'dirichlet', 'division', 'exponential', 'f', 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'mtrand', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random', 'random_integers', 'random_sample', 'ranf', 'rayleigh', 'sample', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf' ] for f in from_numpy_random: syms['np_random_' + f] = getattr(np.random, f) for key in unwanted: syms.pop(key, None) super(SafeEval, self).__init__(symtable=syms, use_numpy=False, minimal=False, no_if=True, no_for=True, no_while=True, no_try=True, no_functiondef=True, no_ifexp=True, no_listcomp=False, no_augassign=False, no_assert=True, no_delete=True, no_raise=True, no_print=True)
def test_partial_exception(self): sym_table = make_symbol_table(sqrt=partial(math.sqrt)) aeval = Interpreter(symtable=sym_table) assert aeval("sqrt(4)") == 2 # Calling sqrt(-1) should raise a ValueError. When the interpreter # encounters an exception, it attempts to form an error string that # uses the function's __name__ attribute. Partials don't have a # __name__ attribute, so we want to make sure that an AttributeError is # not raised. result = aeval("sqrt(-1)") assert aeval.error.pop().exc == ValueError
def __call__(self, parents, children, accumulator) -> str: parent_symbols = {k: ParentSymbol(accumulator[v.id_]) for k, v in self.format_node_names(parents).items()} children_symbols = {k: ChildSymbol(v.id_) for k, v in self.format_node_names(children).items()} syms = make_symbol_table(use_numpy=False, **parent_symbols, **children_symbols) aeval = Interpreter(usersyms=syms, no_for=True, no_while=True, no_try=True, no_functiondef=True, no_ifexp=True, no_listcomp=True, no_augassign=True, no_assert=True, no_delete=True, no_raise=True, no_print=True, use_numpy=False, builtins_readonly=True, readonly_symbols=children_symbols.keys()) aeval(self.conditional) child_id = getattr(aeval.symtable.get("selected_node", None), "id_", None) if len(aeval.error) > 0: raise ConditionException return child_id
def operator_expr(self, expr): """Evaluate an expression composed of single-mode operators. See ``Mode.OPERATORS`` for the full list of supported operators. Args: expr (str): String representation of the operator expression to evaluate. Returns: ``qutip.Qobj``: Evaluated operator expression. """ symbols = {name: getattr(self, name) for name in self.OPERATORS} symtable = make_symbol_table(use_numpy=True, **symbols) aeval = Interpreter(symtable=symtable) return aeval.eval(expr)
def __init__(self, label: str = None, root_group: ParameterGroup = None): """Represents are group of parameters. Can contain other groups, creating a tree-like hierarchy. Parameters ---------- label : The label of the group. """ if label is not None and not Parameter.valid_label(label): raise ValueError(f"'{label}' is not a valid group label.") self._label = label self._parameters = {} self._root_group = root_group self._evaluator = (asteval.Interpreter( symtable=asteval.make_symbol_table( group=self)) if root_group is None else None) super().__init__()
def transform_fields( self, field_dict: Dict[str, Any], task: "Task", formula_dict: Dict[str, str], ) -> None: """ Uses the definitions from the fieldmap XML to set up field values to be exported to REDCap. Args: field_dict: Exported field values go here (the dictionary is modified). task: the :class:`camcops_server.cc_modules.cc_task.Task` formula_dict: dictionary (from the XML information) mapping REDCap field name to a "formula". The formula is applied to extract data from the task in a flexible way. """ extra_symbols = self.get_extra_symbols() symbol_table = make_symbol_table(task=task, **extra_symbols) interpreter = Interpreter(symtable=symbol_table) for redcap_field, formula in formula_dict.items(): v = interpreter(f"{formula}", show_errors=True) if interpreter.error: message = "\n".join([e.msg for e in interpreter.error]) raise RedcapExportException( ( f"Fieldmap:\n" f"Error in formula '{formula}': {message}\n" f"Task: '{task.tablename}'\n" f"REDCap field: '{redcap_field}'\n" ) ) field_dict[redcap_field] = v
def __init__(self, load_scipy=False, load_numpy=False, load_estimators=False): # File opening and other unneeded functions could be dropped unwanted = ['open', 'type', 'dir', 'id', 'str', 'repr'] # Allowed symbol table. Add more if needed. new_syms = { 'np_arange': getattr(np, 'arange'), 'ensemble_ExtraTreesClassifier': getattr(ensemble, 'ExtraTreesClassifier') } syms = make_symbol_table(use_numpy=False, **new_syms) if load_scipy: scipy_distributions = scipy.stats.distributions.__dict__ for k, v in scipy_distributions.items(): if isinstance( v, (scipy.stats.rv_continuous, scipy.stats.rv_discrete)): syms['scipy_stats_' + k] = v if load_numpy: from_numpy_random = [ 'beta', 'binomial', 'bytes', 'chisquare', 'choice', 'dirichlet', 'division', 'exponential', 'f', 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'mtrand', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random', 'random_integers', 'random_sample', 'ranf', 'rayleigh', 'sample', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf' ] for f in from_numpy_random: syms['np_random_' + f] = getattr(np.random, f) if load_estimators: estimator_table = { 'sklearn_svm': getattr(sklearn, 'svm'), 'sklearn_tree': getattr(sklearn, 'tree'), 'sklearn_ensemble': getattr(sklearn, 'ensemble'), 'sklearn_neighbors': getattr(sklearn, 'neighbors'), 'sklearn_naive_bayes': getattr(sklearn, 'naive_bayes'), 'sklearn_linear_model': getattr(sklearn, 'linear_model'), 'sklearn_cluster': getattr(sklearn, 'cluster'), 'sklearn_decomposition': getattr(sklearn, 'decomposition'), 'sklearn_preprocessing': getattr(sklearn, 'preprocessing'), 'sklearn_feature_selection': getattr(sklearn, 'feature_selection'), 'sklearn_kernel_approximation': getattr(sklearn, 'kernel_approximation'), 'skrebate_ReliefF': getattr(skrebate, 'ReliefF'), 'skrebate_SURF': getattr(skrebate, 'SURF'), 'skrebate_SURFstar': getattr(skrebate, 'SURFstar'), 'skrebate_MultiSURF': getattr(skrebate, 'MultiSURF'), 'skrebate_MultiSURFstar': getattr(skrebate, 'MultiSURFstar'), 'skrebate_TuRF': getattr(skrebate, 'TuRF'), 'xgboost_XGBClassifier': getattr(xgboost, 'XGBClassifier'), 'xgboost_XGBRegressor': getattr(xgboost, 'XGBRegressor'), 'imblearn_over_sampling': getattr(imblearn, 'over_sampling'), 'imblearn_combine': getattr(imblearn, 'combine') } syms.update(estimator_table) for key in unwanted: syms.pop(key, None) super(SafeEval, self).__init__(symtable=syms, use_numpy=False, minimal=False, no_if=True, no_for=True, no_while=True, no_try=True, no_functiondef=True, no_ifexp=True, no_listcomp=False, no_augassign=False, no_assert=True, no_delete=True, no_raise=True, no_print=True)
from typing import TYPE_CHECKING import asteval import numpy as np from numpy.typing._array_like import _SupportsArray from glotaran.utils.ipython import MarkdownStr from glotaran.utils.sanitize import sanitize_parameter_list if TYPE_CHECKING: from typing import Any from glotaran.parameter import ParameterGroup RESERVED_LABELS: list[str] = list( asteval.make_symbol_table().keys()) + ["group"] class Keys: """Keys for parameter options.""" EXPR = "expr" MAX = "max" MIN = "min" NON_NEG = "non-negative" STD_ERR = "standard-error" VARY = "vary" PARAMETER_EXPRESSION_REGEX = re.compile( r"\$(?P<parameter_expression>[\w\d\.]+)((?![\w\d\.]+)|$)")
"""The parameter class.""" from __future__ import annotations import re from typing import TYPE_CHECKING from typing import Any if TYPE_CHECKING: from glotaran.parameter import ParameterGroup import asteval import numpy as np RESERVED_LABELS = [symbol for symbol in asteval.make_symbol_table()] + ["group"] class Keys: """Keys for parameter options.""" EXPR = "expr" MAX = "max" MIN = "min" NON_NEG = "non-negative" VARY = "vary" class Parameter: """A parameter for optimization."""
def __init__(self, load_scipy=False, load_numpy=False, load_estimators=False): # File opening and other unneeded functions could be dropped unwanted = ['open', 'type', 'dir', 'id', 'str', 'repr'] # Allowed symbol table. Add more if needed. new_syms = { 'np_arange': getattr(np, 'arange'), 'ensemble_ExtraTreesClassifier': getattr(ensemble, 'ExtraTreesClassifier') } syms = make_symbol_table(use_numpy=False, **new_syms) if load_scipy: scipy_distributions = scipy.stats.distributions.__dict__ for k, v in scipy_distributions.items(): if isinstance(v, (scipy.stats.rv_continuous, scipy.stats.rv_discrete)): syms['scipy_stats_' + k] = v if load_numpy: from_numpy_random = ['beta', 'binomial', 'bytes', 'chisquare', 'choice', 'dirichlet', 'division', 'exponential', 'f', 'gamma', 'geometric', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'mtrand', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random', 'random_integers', 'random_sample', 'ranf', 'rayleigh', 'sample', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf'] for f in from_numpy_random: syms['np_random_' + f] = getattr(np.random, f) if load_estimators: estimator_table = { 'sklearn_svm' : getattr(sklearn, 'svm'), 'sklearn_tree' : getattr(sklearn, 'tree'), 'sklearn_ensemble' : getattr(sklearn, 'ensemble'), 'sklearn_neighbors' : getattr(sklearn, 'neighbors'), 'sklearn_naive_bayes' : getattr(sklearn, 'naive_bayes'), 'sklearn_linear_model' : getattr(sklearn, 'linear_model'), 'sklearn_cluster' : getattr(sklearn, 'cluster'), 'sklearn_decomposition' : getattr(sklearn, 'decomposition'), 'sklearn_preprocessing' : getattr(sklearn, 'preprocessing'), 'sklearn_feature_selection' : getattr(sklearn, 'feature_selection'), 'sklearn_kernel_approximation' : getattr(sklearn, 'kernel_approximation'), 'skrebate_ReliefF': getattr(skrebate, 'ReliefF'), 'skrebate_SURF': getattr(skrebate, 'SURF'), 'skrebate_SURFstar': getattr(skrebate, 'SURFstar'), 'skrebate_MultiSURF': getattr(skrebate, 'MultiSURF'), 'skrebate_MultiSURFstar': getattr(skrebate, 'MultiSURFstar'), 'skrebate_TuRF': getattr(skrebate, 'TuRF'), 'xgboost_XGBClassifier' : getattr(xgboost, 'XGBClassifier'), 'xgboost_XGBRegressor' : getattr(xgboost, 'XGBRegressor') } syms.update(estimator_table) for key in unwanted: syms.pop(key, None) super(SafeEval, self).__init__(symtable=syms, use_numpy=False, minimal=False, no_if=True, no_for=True, no_while=True, no_try=True, no_functiondef=True, no_ifexp=True, no_listcomp=False, no_augassign=False, no_assert=True, no_delete=True, no_raise=True, no_print=True)
from typing import Tuple import matplotlib.pyplot as plt import numpy as np from asteval import Interpreter, make_symbol_table def step(x): return np.heaviside(x, 0) syms = make_symbol_table(use_numpy=True, step=step) aeval = Interpreter(syms) _CONTINUOUS_STEPS = 1000 def visualize_wave(equation_str: str, variable: str, var_range: Tuple[float, float], discretization_step: float = None, wave_title: str = None): """ Displays a plot for visualizing a continuous function over a small period of time. Optionally can display discretization as an overlayed plot :param equation_str: String representing equation :param variable: String representing single variable :param var_range: Range of function to plot
def __init__(self): self.builtinsyms = asteval.make_symbol_table() del self.builtinsyms["open"] self.aeval = asteval.Interpreter(self.builtinsyms, builtins_readonly=True, max_time=1)