Skip to content

Param references in Parameter expressions #194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 18, 2021
Merged
69 changes: 16 additions & 53 deletions spatialpy/Model.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def __init__(self, name="spatialpy"):


def __str__(self):
self._resolve_parameters()
divider = f"\n{'*'*10}\n"

def decorate(header):
Expand Down Expand Up @@ -356,8 +357,6 @@ def update_namespace(self):

for param in self.listOfParameters:
self.namespace[param]=self.listOfParameters[param].value
# Dictionary of expressions that can be evaluated in the scope of this model.
self.expressions = {}

def sanitized_species_names(self):
"""
Expand Down Expand Up @@ -514,9 +513,8 @@ def add_parameter(self,params):
problem = self.__problem_with_name(params.name)
if problem is not None:
raise problem
# make sure that you don't overwrite an existing parameter??
if params.name in self.listOfParameters.keys():
raise ParameterError("Parameter '{0}' has already been added to the model.".format(params.name))
self.update_namespace()
params._evaluate(self.namespace)
self.listOfParameters[params.name] = params
else:
raise ParameterError("Parameter '{0}' needs to be of type '{2}', it is of type '{1}'".format(params.name,str(params),str(type(Parameter))))
Expand All @@ -525,28 +523,12 @@ def add_parameter(self,params):
def delete_parameter(self, obj):
self.listOfParameters.pop(obj)

def set_parameter(self,pname,expression):
""" Set the expression of an existing paramter.

:param pname: Name of target parameter for expression
:type pname: str
:param expression: math expression to be assigned to target parameter
:type expression: str

"""
p = self.listOfParameters[pname]
p.expression = expression
p._evaluate()

def _resolve_parameters(self):
""" Attempt to resolve all parameter expressions to scalar floating point values.
Must be called prior to exporting the model. """
self.update_namespace()
for param in self.listOfParameters:
try:
self.listOfParameters[param]._evaluate(self.namespace)
except:
raise ParameterError(f"Could not resolve Parameter '{param}' expression '{self.listOfParameters[param].expression}' to a scalar value.")
self.listOfParameters[param]._evaluate(self.namespace)

def delete_all_parameters(self):
""" Remove all parameters from model.listOfParameters
Expand Down Expand Up @@ -775,48 +757,29 @@ class Parameter():

def __init__(self,name=None,expression=None):

self.name = name
if name is None:
raise ParameterError("name is required for a Parameter.")

if expression is None:
raise ParameterError("expression is required for a Parameter.")

self.name = name
self.value = 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.
if expression is not None:
self.expression = str(expression)
else:
raise ParameterError("expression is required for a Parameter.")
self.expression = str(expression)

self._evaluate()
def __str__(self):
print_string = f"{self.name}: {str(self.expression)}"
return print_string

def _evaluate(self,namespace={}):
""" Evaluate the expression and return the (scalar) value """
try:
self.value = (float(eval(self.expression, namespace)))
except:
self.value = None

def set_expression(self,expression):
""" Sets the Parameters expression

:param expression: Expression to be set for Parameter
:type expression: str
"""
self.expression = expression
# 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.
if expression is not None:
self.expression = str(expression)

if self.expression is None:
raise TypeError

self._evaluate()

def __str__(self):
print_string = f"{self.name}: {str(self.expression)}"
return print_string
except Exception as err:
message = f"Could not evaluate expression '{self.expression}': {err}."
raise ParameterError(message) from err


class Reaction():
Expand Down