Source code for ctapipe.core.expression_engine

"""
Expression Engine
"""

import astropy.units as u  # for use in selection functions
import numpy as np  # for use in selection functions

# the following are what are allowed to be used
# in selection functions (passed to eval())
ALLOWED_GLOBALS = {"u": u, "np": np}  # astropy units  # numpy

for func in ("sin", "cos", "tan", "arctan2", "log", "log10", "exp", "sqrt"):
    ALLOWED_GLOBALS[func] = getattr(np, func)


[docs] class ExpressionError(TypeError): """Signal a problem with a user-defined selection criteria function"""
[docs] class ExpressionEngine: """ Compile expressions on init, evaluate on call. The expressions are evaluated as python code in the context that is passed. Additionally, astropy.units is exposed as ``u`` and numpy as ``np``. Basic mathematical functions are also exposed without the np prefix. """ def __init__(self, expressions): self.expressions = expressions self._compile() def _compile(self): self.compiled = [] for name, expression in self.expressions: try: self.compiled.append(compile(expression, __name__, mode="eval")) except Exception as err: raise ExpressionError( f"Error compiling expression '{expression}' for {name}\n" f"{type(err).__name__}: {err}" ) from err
[docs] def __call__(self, locals): for compiled, expression in zip(self.compiled, self.expressions): try: yield eval(compiled, ALLOWED_GLOBALS, locals) except NameError as err: raise ExpressionError( f"Error evaluating expression '{expression}': {err}" ) from None except Exception as err: raise ExpressionError( f"Error evaluating expression '{expression}': {err}" ) from err
def __getstate__(self): state = self.__dict__.copy() del state["compiled"] return state def __setstate__(self, state): self.__dict__ = state self._compile()