Skip to content

Commit ed9260f

Browse files
committed
Added option to change parameters after compilation
1 parent a665ce8 commit ed9260f

File tree

7 files changed

+83
-16
lines changed

7 files changed

+83
-16
lines changed

for_local_use.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
import dateutil.rrule
2+
13
from mobspy import *
24
import numpy as np
35

46
if __name__ == '__main__':
57

6-
A = BaseSpecies()
7-
B, C = New(A)
8+
A, B = BaseSpecies()
9+
A + B >> Zero [1]
10+
11+
A(200), B(200)
12+
Sim = Simulation(A | B)
13+
Sim.level = -1
14+
descr = Sim.compile()
15+
Sim.plot_data = False
16+
Sim.duration = 30 * u.hour
17+
Sim.volume = 1*u.m**3
18+
Sim.run()
819

9-
A.a1, A.a2, A.a3
20+
assert Sim._parameters_for_sbml['volume'][0] > 100
21+
assert Sim.fres['Time'][-1] > 100
1022

11-
B + C >> Zero [lambda r1, r2: 100 if A(r1) == A(r2) else 0]
1223

13-
S = Simulation(B | C)
14-
print(S.compile())
1524

1625

1726

mobspy/modules/unit_handler.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ def convert_counts(quantity, volume, dimension):
9494
return converted_quantity
9595

9696

97-
def check_dimension(dimension, value):
97+
def check_dimension(dimension, value, error_context=False):
9898
"""
9999
Checks for dimension consistency. It "stores" the first dimension it was given by returning it
100100
101101
:param dimension: (int) model's dimension (1D, 2D, 3D ...)
102102
:param value: (int) dimension value being analysed
103+
:param error_context: (bool or str) context of the error if dimensions are not consistent
103104
104105
:raise simlog.error: If dimensions are not consistent through the given units (units in 1D with 2D mixed)
105106
@@ -109,17 +110,22 @@ def check_dimension(dimension, value):
109110
dimension = int(value)
110111
else:
111112
if dimension != int(value):
112-
simlog.error('The dimensions are not consistent. There are at least two units given for different '
113-
'dimension models')
113+
message = 'The dimensions are not consistent. There are at least two units given for different ' \
114+
'dimension models.'
115+
if error_context:
116+
message = message + '\n ' + error_context
117+
simlog.error(message)
114118
return dimension
115119

116120

117-
def extract_length_dimension(unit_string, dimension, reaction_order=None):
121+
def extract_length_dimension(unit_string, dimension, reaction_order=None, context=False):
118122
"""
119123
Extracts the volume dimension from a Quantity object from Pint
120124
121125
:param unit_string: (str) unit in str format
122126
:param dimension: (int) model's dimension (1D, 2D, 3D ...)
127+
:param reaction_order: (int) number of reactants in a reaction (for dimensional consistency in rates)
128+
:param context: (bool or str) context of the error if dimensions are not consistent
123129
"""
124130
temp_list = unit_string.split()
125131
try:
@@ -131,12 +137,12 @@ def extract_length_dimension(unit_string, dimension, reaction_order=None):
131137
return False
132138
if temp_list[position + 1] == '**':
133139
if reaction_order is None:
134-
dimension = check_dimension(dimension, temp_list[position + 2])
140+
dimension = check_dimension(dimension, temp_list[position + 2], context)
135141
else:
136142
temp_int = int(int(temp_list[position + 2])/(reaction_order - 1))
137-
dimension = check_dimension(dimension, temp_int)
143+
dimension = check_dimension(dimension, temp_int, context)
138144
else:
139-
dimension = check_dimension(dimension, 1)
145+
dimension = check_dimension(dimension, 1, context)
140146

141147
return dimension
142148

mobspy/parameter_scripts/parameter_reader.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import numpy as np
1010
import mobspy.simulation_logging.log_scripts as simlog
1111
from pint import Quantity
12+
import mobspy.modules.unit_handler as uh
13+
import inspect
1214

1315

1416
def read_json(json_file_name):
@@ -84,6 +86,27 @@ def __convert_unit_parameters(params):
8486
params[u] = str(params[u])
8587

8688

89+
def convert_time_parameters_after_compilation(value):
90+
"""
91+
This function converts the duration if the model was already compiled
92+
"""
93+
if isinstance(value, Quantity):
94+
if str(value.dimensionality) == '[time]':
95+
value = value.convert('second').magnitude
96+
return value
97+
98+
def convert_volume_after_compilation(dimension, parameters_for_sbml, value):
99+
if isinstance(value, Quantity):
100+
message = 'Error at '
101+
context = inspect.stack()[2].code_context[0][:-1]
102+
message += context + '\n The dimension is set to tree at the moment of the compilation if not specified' \
103+
' beforehand \n Please set a volume in the correct dimension before compilation'
104+
uh.extract_length_dimension(str(value.dimensionality), dimension, context=message)
105+
106+
value = uh.convert_volume(value, dimension)
107+
parameters_for_sbml['volume'] = (value, f'dimensionless')
108+
return value
109+
87110
def parameter_process(params):
88111
__convert_unit_parameters(params)
89112
__name_output_file(params)

mobspy/simulation.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ def __init__(self, model, names=None, parameters=None, plot_parameters=None):
150150
self.model_parameters = {}
151151
self.sbml_data_list = []
152152
self._parameter_list_of_dic = []
153+
self._is_compiled = False
154+
self.dimension = None
153155

154156
# Must copy to avoid reference assignment
155157
self.model = List_Species(model)
@@ -197,6 +199,9 @@ def compile(self, verbose=True):
197199
198200
:param verbose: (bool) = print or not the results of the compilation
199201
"""
202+
if self.dimension is None:
203+
self.dimension = 3
204+
200205
simlog.global_simlog_level = self.parameters['level']
201206
simlog.debug('Compiling model')
202207

@@ -253,6 +258,8 @@ def compile(self, verbose=True):
253258

254259
self._list_of_parameters = [self.parameters]
255260

261+
self._is_compiled = True
262+
256263
if self.model_string != '':
257264
return self.model_string
258265

@@ -409,7 +416,7 @@ def __setattr__(self, name, value):
409416
'initial_duration', '_reactions_set', '_list_of_models', '_list_of_parameters',
410417
'_context_not_active', '_species_counts', '_assigned_species_list', '_conditional_event',
411418
'_end_condition', 'orthogonal_vector_structure', 'model_parameters', 'fres',
412-
'sbml_data_list', '_parameter_list_of_dic']
419+
'sbml_data_list', '_parameter_list_of_dic', '_is_compiled', 'dimension']
413420

414421
plotted_flag = False
415422
if name in white_list:
@@ -423,6 +430,12 @@ def __setattr__(self, name, value):
423430
if not plotted_flag:
424431
example_parameters = get_example_parameters()
425432
if name in example_parameters.keys():
433+
# If the model is already compiled, the change in parameters should be faster
434+
if self._is_compiled:
435+
value = pr.convert_time_parameters_after_compilation(value)
436+
if self._is_compiled and name == 'volume':
437+
value = pr.convert_volume_after_compilation(self.dimension, self._parameters_for_sbml, value)
438+
426439
if name == 'duration':
427440
if type(value) == bool:
428441
simlog.error(f'MobsPy has received an invalid trigger type: {type(value)} \n' +
@@ -640,7 +653,6 @@ def __init__(self, S1, S2):
640653
def __add__(self, other):
641654
return SimulationComposition(self, other)
642655

643-
# FIX THIS
644656
def __setattr__(self, name, value):
645657
white_list = ['list_of_simulations', 'results', 'base_sim', 'fres']
646658
broad_cast_parameters = ['level', 'method', 'volume']
-2.72 KB
Loading

test_plot_images/stochastic_tree.png

-2.97 KB
Loading

test_script.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,23 @@ def test_matching_characteristic_rate():
12371237
assert compare_model(S.compile(), 'test_tools/model_43.txt')
12381238

12391239

1240+
def test_changes_after_compilation():
1241+
A, B = BaseSpecies()
1242+
A + B >> Zero [1]
1243+
1244+
A(200), B(200)
1245+
Sim = Simulation(A | B)
1246+
Sim.level = -1
1247+
descr = Sim.compile()
1248+
Sim.plot_data = False
1249+
Sim.duration = 30 * u.hour
1250+
Sim.volume = 1*u.m**3
1251+
Sim.run()
1252+
1253+
assert Sim._parameters_for_sbml['volume'][0] > 100
1254+
assert Sim.fres['Time'][-1] > 100
1255+
1256+
12401257

12411258
# This is here because pytest is slow - but this script works fine with pytest. Just make sure that the
12421259
# python version in terminal is above 3.10
@@ -1256,7 +1273,7 @@ def test_matching_characteristic_rate():
12561273
test_conversion_outside, test_first_characteristic_in_reacting_species, test_model_reference,
12571274
test_sbml_generation, test_multi_sim_sbml, test_inline_comment,
12581275
test_with_statement_any_and_species_characteristics, test_with_statement_on_any_and_event,
1259-
test_matching_characteristic_rate]
1276+
test_matching_characteristic_rate, test_changes_after_compilation]
12601277

12611278
sub_test = test_list
12621279

0 commit comments

Comments
 (0)