Source code for gillespy2.core.parameter

# GillesPy2 is a modeling toolkit for biochemical simulation.
# Copyright (C) 2019-2023 GillesPy2 developers.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from gillespy2.core.jsonify import Jsonify
from gillespy2.core.sortableobject import SortableObject

from gillespy2.core.gillespyError import ParameterError

[docs]class Parameter(SortableObject, Jsonify): """ A parameter can be given as an expression (function) or directly as a value (scalar). If given an expression, it should be understood as evaluable in the namespace of a parent Model. :param name: The name by which this parameter is called or referenced in \ reactions, rate rules, assignment rules, and events. :type name: str :param expression: String for a function calculating parameter values. Should be evaluable in namespace of Model. :type expression: str :raises ParameterError: Arg is of invalid type. Required arg set to None. Arg value is outside of accepted bounds. """ def __init__(self, name=None, expression=None): # We allow expression to be passed in as a non-string type. Invalid strings # will be caught below. It is perfectly fine to give a scalar value as the expression. # This can then be evaluated in an empty namespace to the scalar value. self.value = None self.name = name if isinstance(expression, (int, float)): expression = str(expression) self.expression = expression self.validate() def __str__(self): return f"{self.name}: {self.expression}" def _evaluate(self, namespace=None): """ Evaluate the expression and return the (scalar) value in the given namespace. :param namespace: The namespace in which to test evaulation of the parameter, if it involves other parameters, etc. :type namespace: dict :raises ParameterError: expression is of invalid type. expression is set to None. \ expression is not evaluable within the given namespace. """ if isinstance(self.expression, (int, float)): self.expression = str(self.expression) self.validate(coverage="expression") try: if namespace is None: namespace = {} self.value = float(eval(self.expression, namespace)) except Exception as err: raise ParameterError( f"Could not evaluate expression: '{self.expression}'. Reason given: {err}." ) from err
[docs] def sanitized_expression(self, species_mappings, parameter_mappings): names = sorted(list(species_mappings.keys()) + list(parameter_mappings.keys()), key=lambda x: len(x), reverse=True) replacements = [parameter_mappings[name] if name in parameter_mappings else species_mappings[name] for name in names] sanitized_expression = self.expression for i, name in enumerate(names): sanitized_expression = sanitized_expression.replace( name, "{"+str(i)+"}") return sanitized_expression.format(*replacements)
[docs] def validate(self, expression=None, coverage="all"): """ Validate the parameter. :param expression: String for a function calculating parameter values. Should be evaluable in namespace of Model. :type expression: str :param coverage: The scope of attributes to validate. Set to an attribute name to restrict validation \ to a specific attribute. :type coverage: str :raises ParameterError: Attribute is of invalid type. Required attribute set to None. \ Attribute value is outside of accepted bounds. """ # Check name if coverage in ("all", "name"): if self.name is None: raise ParameterError("name can't be None type.") if not isinstance(self.name, str): raise ParameterError("name must be of type str.") if self.name == "": raise ParameterError("name can't be an empty string.") # Check expression if coverage in ("all", "expression"): if expression is None: expression = self.expression if expression is None: raise ParameterError("initial_value can't be None type.") if not isinstance(expression, str): raise ParameterError("expression must be of type str.") if expression == "": raise ParameterError("expression can't be an empty string.")