Skip to content

Commit 8ebbcb3

Browse files
committed
update CVODE to track assignment rules and enable extra output in mod.data_sim
1 parent 25ecb54 commit 8ebbcb3

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

pysces/PyscesModel.py

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,7 @@ def __init__(self, File=None, dir=None, loader='file', fString=None, autoload=Tr
14851485
self.LoadFromFile(File, dir)
14861486
# stuff that needs to be done before initmodel
14871487
self.__settings__['mode_substitute_assignment_rules'] = False
1488+
self.__settings__['cvode_track_assignment_rules'] = True
14881489
self.__settings__['display_compartment_warnings'] = False
14891490
self._TIME_ = 0.0 # this will be the built-in time
14901491
self.piecewise_functions = []
@@ -1931,6 +1932,7 @@ def InitialiseRules(self):
19311932
# defmod
19321933
self.__HAS_FORCED_FUNCS__ = False
19331934
self.__HAS_RATE_RULES__ = False
1935+
self._CVODE_extra_output = []
19341936
rate_rules = {}
19351937
assignment_rules = {}
19361938
for ar in self.__rules__:
@@ -1951,7 +1953,6 @@ def InitialiseRules(self):
19511953
code_string = ''
19521954
all_names = []
19531955
for ar in assignment_rules:
1954-
name = assignment_rules[ar]['name']
19551956
InfixParser.setNameStr('self.', '')
19561957
InfixParser.parse(assignment_rules[ar]['formula'])
19571958
assignment_rules[ar]['symbols'] = InfixParser.names
@@ -1980,12 +1981,13 @@ def InitialiseRules(self):
19801981
keep += dep
19811982
rules = indep
19821983
for ar in indep + keep:
1984+
if self.__settings__['cvode_track_assignment_rules']:
1985+
self._CVODE_extra_output.append(assignment_rules[ar]['name'])
19831986
evalCode = 'self.{} = {}\n'.format(
1984-
assignment_rules[ar]['name'], assignment_rules[ar]['code_string'],
1987+
assignment_rules[ar]['name'], assignment_rules[ar]['code_string']
19851988
)
19861989
self._NewRuleXCode.update({assignment_rules[ar]['name']: evalCode})
19871990
code_string += evalCode
1988-
19891991
print('\nAssignment rule(s) detected.')
19901992
self._Function_forced = code_string
19911993
elif (
@@ -3037,8 +3039,7 @@ def InitialiseModel(self):
30373039
self.sim_time = numpy.arange(
30383040
self.sim_start, self.sim_end + sim_steps, sim_steps
30393041
)
3040-
self.CVODE_extra_output = []
3041-
self.CVODE_xdata = None
3042+
self._CVODE_xdata = None
30423043
self.__SIMPLOT_OUT__ = []
30433044

30443045
# elasticity options
@@ -3781,9 +3782,9 @@ def CVODE_continue(self, tvec):
37813782
self.data_sim.setRates(rates, self.__reactions__)
37823783
if self.__HAS_RATE_RULES__:
37833784
self.data_sim.setRules(rrules, self.__rate_rules__)
3784-
if len(self.CVODE_extra_output) > 0:
3785-
self.data_sim.setXData(self.CVODE_xdata, lbls=self.CVODE_extra_output)
3786-
self.CVODE_xdata = None
3785+
if len(self._CVODE_extra_output) > 0:
3786+
self.data_sim.setXData(self._CVODE_xdata, lbls=self._CVODE_extra_output)
3787+
self._CVODE_xdata = None
37873788
if not simOK:
37883789
print('Simulation failure')
37893790
del sim_res
@@ -3831,32 +3832,27 @@ def ffull(t, s):
38313832
if self.__HAS_RATE_RULES__:
38323833
initial = numpy.concatenate([initial, rrules])
38333834

3834-
# # CVODE extra output
3835-
# CVODE_XOUT = False
3836-
# if len(self.CVODE_extra_output) > 0:
3837-
# out = []
3838-
# for d in self.CVODE_extra_output:
3839-
# if (
3840-
# hasattr(self, d)
3841-
# and d
3842-
# not in self.__species__ + self.__reactions__ + self.__rate_rules__
3843-
# ):
3844-
# out.append(d)
3845-
# else:
3846-
# print(
3847-
# '\nWarning: CVODE is ignoring extra data ({}), it either doesn\'t exist or it\'s a species or rate.\n'.format(
3848-
# d
3849-
# )
3850-
# )
3851-
# if len(out) > 0:
3852-
# self.CVODE_extra_output = out
3853-
# CVODE_XOUT = True
3854-
# del out
3855-
#
3856-
# if CVODE_XOUT:
3857-
# self.CVODE_xdata = numpy.zeros(
3858-
# (len(self.sim_time), len(self.CVODE_extra_output))
3859-
# )
3835+
# CVODE extra output
3836+
self._CVODE_XOUT = False
3837+
if len(self._CVODE_extra_output) > 0:
3838+
out = []
3839+
for d in self._CVODE_extra_output:
3840+
if (
3841+
hasattr(self, d)
3842+
and d
3843+
not in self.__species__ + self.__reactions__ + self.__rate_rules__
3844+
):
3845+
out.append(d)
3846+
else:
3847+
print(
3848+
'\nWarning: CVODE is ignoring extra data ({}), it either doesn\'t exist or it\'s a species or rate.\n'.format(
3849+
d
3850+
)
3851+
)
3852+
if len(out) > 0:
3853+
self._CVODE_extra_output = out
3854+
self._CVODE_XOUT = True
3855+
del out
38603856

38613857
problem = EventsProblem(self, rhs=rhs, y0=initial)
38623858
# for direct access to the problem class
@@ -3909,11 +3905,6 @@ def ffull(t, s):
39093905
sim_res[x] = self._SpeciesAmountToConc(sim_res[x])
39103906
if self.__HAS_RATE_RULES__:
39113907
sim_res = numpy.concatenate([sim_res, rrules], axis=1)
3912-
# if CVODE_XOUT:
3913-
# self.CVODE_xdata[st, :] = self._EvalExtraData(
3914-
# self.CVODE_extra_output
3915-
# )
3916-
39173908

39183909
else:
39193910
# calculate rates from all species
@@ -4723,13 +4714,34 @@ def Simulate(self, userinit=0):
47234714
self.data_sim.setRates(rates, self.__reactions__)
47244715
if self.__HAS_RATE_RULES__:
47254716
self.data_sim.setRules(rrules, self.__rate_rules__)
4726-
if len(self.CVODE_extra_output) > 0:
4727-
self.data_sim.setXData(self.CVODE_xdata, lbls=self.CVODE_extra_output)
4728-
self.CVODE_xdata = None
4717+
if self._CVODE_XOUT:
4718+
self._CVODE_xdata = numpy.zeros((len(self.sim_time), len(self._CVODE_extra_output)))
4719+
# get assignment rules
4720+
r = self.__rules__
4721+
ars = {name: r[name] for name in r if r[name]['type'] == 'assignment'}
4722+
# loop through extra output and evaluate from simulation data
4723+
for i in range(len(self._CVODE_extra_output)):
4724+
name = self._CVODE_extra_output[i]
4725+
self._update_assignment_rule_code(ars[name])
4726+
self._CVODE_xdata[:, i] = eval(ars[name]['data_sim_string'])
4727+
self.data_sim.setXData(self._CVODE_xdata, lbls=self._CVODE_extra_output)
4728+
self._CVODE_xdata = None
47294729
if not simOK:
47304730
print('Simulation failure')
47314731
del sim_res
47324732

4733+
def _update_assignment_rule_code(self, rule):
4734+
replacements = []
4735+
rule['data_sim_string'] = rule['code_string']
4736+
for s in rule['symbols']:
4737+
if s in self.__reactions__ or s in self.__rate_rules__:
4738+
replacements.append((s, 'data_sim.getSimData("' + s + '")[:,1]'))
4739+
elif s in self.__species__:
4740+
replacements.append(('(self.' + s + ')',
4741+
'(self.data_sim.getSimData("' + s + '")[:,1])'))
4742+
for old, new in replacements:
4743+
rule['data_sim_string'] = rule['data_sim_string'].replace(old, new)
4744+
47334745
@property
47344746
def sim(self):
47354747
if self._sim is None and self.data_sim is not None:

0 commit comments

Comments
 (0)