Skip to content

Commit

Permalink
Added ability to extract new parameters from transition rate laws thr…
Browse files Browse the repository at this point in the history
…ough explicit argument definition or implicitly and modified unit tests
  • Loading branch information
nanglo123 committed Sep 13, 2023
1 parent a961483 commit 1f9703d
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 36 deletions.
107 changes: 89 additions & 18 deletions mira/modeling/askenet/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sympy import sstr
from mira.metamodel import SympyExprStr, Unit
import mira.metamodel.ops as tmops
from mira.sources.askenet.petrinet import template_model_from_askenet_json, state_to_concept, get_sympy
from mira.sources.askenet.petrinet import template_model_from_askenet_json
from .petrinet import template_model_to_petrinet_json
from mira.metamodel.io import mathml_to_expression
from mira.metamodel.template_model import Parameter, Distribution, Observable, \
Expand Down Expand Up @@ -149,6 +149,32 @@ def add_parameter(tm, parameter_id: str,
return tm


def add_parameter_no_wrapper(tm, parameter_id: str,
name: str = None,
value: float = None,
distribution=None,
units_mathml: str = None):
distribution = Distribution(**distribution) if distribution else None
if units_mathml:
units = {
'expression': mathml_to_expression(units_mathml),
'expression_mathml': units_mathml
}
else:
units = None

data = {
'name': parameter_id,
'display_name': name if name else parameter_id,
'value': value,
'distribution': distribution,
'units': units
}

parameter = Parameter(**data)
tm.parameters[parameter_id] = parameter


@amr_to_mira
def replace_initial_id(tm, old_id, new_id):
"""Replace the ID of an initial."""
Expand Down Expand Up @@ -193,14 +219,14 @@ def add_state(tm, state_id: str, value: float, name: str = None, units_mathml: s
else:
units = None

new_concept_new = Concept(name=state_id,
display_name=name,
identifiers=grounding,
units=units,
context=context)
new_state = Initial(concept=new_concept_new, value=value)
new_concept = Concept(name=state_id,
display_name=name,
identifiers=grounding,
units=units,
context=context)
new_state = Initial(concept=new_concept, value=value)
tm.initials[state_id] = new_state
static_template = StaticConcept(subject=new_concept_new)
static_template = StaticConcept(subject=new_concept)
tm.templates.append(static_template)
return tm

Expand All @@ -214,20 +240,12 @@ def remove_transition(tm, transition_id):

@amr_to_mira
def add_transition(tm, new_transition_id, src_id=None, tgt_id=None,
rate_law_mathml=None):
# TODO: handle parameters added in the rate law as follows
# option 1 take in optional parameters dict if rate law contains parameters
# that aren't already present
# option 2, reverse engineer rate law and find parameters and states within
# the rate law and add to model

# each transition has inputs such as subjects and controllers and those appear in rate laws as states
# look at sympy expression and get free symbols, take out ones that represent the inputs and controllers (states)
# whatever remains are parameters for models
rate_law_mathml=None, params_dict: dict = None):
if src_id is None and tgt_id is None:
ValueError("You must pass in at least one of source and target id")
rate_law_sympy = SympyExprStr(mathml_to_expression(rate_law_mathml)) \
if rate_law_mathml else None

if src_id is None and tgt_id:
template = NaturalProduction(name=new_transition_id, outcome=tgt_id,
rate_law=rate_law_sympy)
Expand All @@ -237,6 +255,59 @@ def add_transition(tm, new_transition_id, src_id=None, tgt_id=None,
else:
template = NaturalConversion(name=new_transition_id, subject=src_id,
outcome=tgt_id, rate_law=rate_law_sympy)
if params_dict:
# add parameters to template model
for free_symbol_sympy in template.rate_law.free_symbols:
free_symbol_str = sstr(free_symbol_sympy)
if free_symbol_str in params_dict:
# free_symbol_str = sstr(free_symbol_sympy)
# distribution = Distribution(**params_dict[free_symbol_str]['distribution']) if \
# 'distribution' in params_dict[free_symbol_str] else None
#
# if 'units' in params_dict[free_symbol_str]:
# units = {
# 'expression': mathml_to_expression(params_dict[free_symbol_str]['units']),
# 'expression_mathml': params_dict[free_symbol_str]['units']
# }
# else:
# units = None
#
# data = {
# 'name': free_symbol_str,
# 'display_name': params_dict[free_symbol_str]['display_name'] if 'display_name' in params_dict[
# free_symbol_str] else free_symbol_str,
# 'value': params_dict[free_symbol_str]['value'] if 'value' in params_dict[free_symbol_str] else None,
# 'distribution': distribution,
# 'units': units
# }
#
# parameter = Parameter(**data)
# tm.parameters[free_symbol_str] = parameter
name = params_dict[free_symbol_str]['display_name'] if 'display_name' in params_dict[
free_symbol_str] else None
value = params_dict[free_symbol_str]['value'] if 'value' in params_dict[free_symbol_str] else None
units = params_dict[free_symbol_str]['units'] if 'units' in params_dict[free_symbol_str] else None
distribution = params_dict[free_symbol_str]['distribution'] if 'distribution' in params_dict[
free_symbol_str] else None
add_parameter_no_wrapper(tm, free_symbol_str, name=name,
value=value,
units_mathml=units,
distribution=distribution)
# If there are no explicitly defined parameters
# Extract new parameters from rate laws without any other information about that parameter
else:
free_symbol_str = {sstr(symbol) for symbol in template.rate_law.free_symbols}

if not isinstance(template, NaturalProduction):
if template.subject.name in free_symbol_str:
free_symbol_str.remove(template.subject.name)

for param in tm.parameters.keys():
if param in free_symbol_str:
free_symbol_str.remove(param)

for new_param in free_symbol_str:
add_parameter_no_wrapper(tm, new_param)
tm.templates.append(template)
return tm

Expand Down
Loading

0 comments on commit 1f9703d

Please sign in to comment.