Source code for gillespy2.core.parameter
# GillesPy2 is a modeling toolkit for biochemical simulation.
# Copyright (C) 2019-2024 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.")