Skip to content
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

Update model implementation #8

Merged
merged 8 commits into from
Jan 28, 2025
55 changes: 55 additions & 0 deletions debugging_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from test_script import *

# This is here because pytest is too slow - so it's a faster test that avoid the collection step.
# Pytest is used in the GitHub while pushing
# This script is oriented towards fast debugging and development
# Also in the future, it might be nice to add an automated way to get the test names
test_list = [test_model_1, test_model_2, test_model_3, test_model_4, test_model_5, test_model_6, test_model_7,
test_orthogonal_spaces, test_average_value, test_hybrid_sim, test_concatenated_simulation,
test_event_type, test_reacting_species_event, test_unit_event_test, test_reaction_deactivation,
test_double_rate, test_single_rate, test_triple_rate, test_stochastic_event_duration,
test_logic_operator_syntax, test_stack_position, test_empty_arguments,
test_conditional_between_meta_species, test_conditional_between_meta_species_2,
test_event_reaction_not_allowed, all_test, all_test_2, test_error_mult, test_set_counts,
test_bool_error, test_event_all, test_one_value_concatenation_sim, test_crash_after_modification,
test_unit_bi_dimension, test_bi_dimensional_rates, test_dimension_in_function_only,
test_multiple_simulation_counts, test_string_events_assignment, test_plotting,
test_volume_after_sim, test_parameters_with_sbml, test_shared_parameter_name,
test_set_counts_parameters, test_repeated_parameters, initial_expression_test,
test_wrong_dimension_error, test_more_than_used, zero_rate_test, test_wrong_rate,
test_conversion_outside, test_first_characteristic_in_reacting_species, test_model_reference,
test_sbml_generation, test_multi_sim_sbml, test_inline_comment,
test_with_statement_any_and_species_characteristics, test_with_statement_on_any_and_event,
test_matching_characteristic_rate, test_changes_after_compilation, test_proper_unit_context_exit,
test_run_args, test_unit_args, test_multi_parameters_in_run, test_output_concentration_in_multi_sim,
test_parameter_operation_in_rate, test_multi_parameter_with_expression, test_double_parameters_with_units,
test_parameters_with_units, test_convert_back_parameter,
test_numpy_in_expression_function, test_numpy_in_rates,
test_numpy_in_counts, test_numpy_in_set_counts, test_multi_methods_plot, test_unit_x_conversion,
test_Silicon_valley, test_replacing_species_name_in_expression, test_basic_assignment,
test_all_asgn_ops, text_complex_assignments,
text_assign_context_exit, text_even_more_complex_assignments, test_assign_context_complex,
test_assign_context_constant, test_duration_with_run, test_rev, test_dimensionless_count,
test_assignment_similar_species, test_blocked_names, test_blocked_names_2,
test_update_parameter_for_multi_model, test_update_parameter_through_str,
test_update_multiple_parameters_in_expression, test_update_parameter_with_unit,
test_species_value_modification, test_all_value_modification]

# test_no_species_in_asg
# test_illegal_unit_op_in_assignment
# temporary_test_removal = [test_parameter_fit_with_units, test_multiple_runs_fit, test_simple_fit]
test_remov = [test_antimony_compose_model_gen, test_antimony_model]
sub_test = test_list
#sub_test = [test_antimony_compose_model_gen]
def perform_tests():
any_failed = False
for test in sub_test:
try:
test()
print(f'Test {test} passed')
except:
print('\033[91m' + f'Test {test} failed' + '\033[0m', file=sys.stderr)
any_failed = True
if any_failed:
assert False
perform_tests()
26 changes: 17 additions & 9 deletions for_local_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@

if __name__ == '__main__':

# TODO: Ask Matthias about removed tests

# Replace parameters using units
A = BaseSpecies()
A.a1, A.a2
B = New(A)
B.b1, B.b2
k1 = ModelParameters(1)
A, B, C, D = BaseSpecies()

A >> 2 * B[modules.mobspy_parameters._Internal_Parameter_Constructor('k1', 3)]
B >> C + D[modules.mobspy_parameters._Internal_Parameter_Constructor('k2', 1.4)]
B >> Zero [k1]

B(100), B.b2(100)
S = Simulation(B)
S.level = -1
S.compile()

S.update_model([All[B], 200/u.l])

A(100)
S = Simulation(A | B | C | D)
S.duration = 10
print(S.compile())
# print(S.generate_sbml()[0])
print(S.generate_sbml()[0])

S.update_model()
# print(A.get_characteristics())


1 change: 1 addition & 0 deletions mobspy/data_handler/time_series_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pandas as pd
from mobspy.modules.meta_class import *
from mobspy.modules.class_of_meta_specie_named_any import *
import mobspy.simulation_logging as simlog
import inspect


Expand Down
11 changes: 6 additions & 5 deletions mobspy/modules/compiler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from mobspy.simulation_logging.log_scripts import error as simlog_error, warning as simlog_warning
from mobspy.modules.mobspy_parameters import _Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.mobspy_parameters import Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.species_string_generator import construct_all_combinations as ssg_construct_all_combinations, \
construct_species_char_list as ssg_construct_species_char_list
from pint import Quantity
Expand Down Expand Up @@ -29,7 +29,8 @@ def add_to_parameters_to_sbml(cls, parameters_used, parameters_for_sbml, paramet
if parameter.name in parameters_used:
parameters_used[parameter.name]['used_in'].add('$sbml')
else:
temp = {'name': parameter.name, 'values': parameter.value, 'used_in': {'$sbml'}}
temp = {'name': parameter.name, 'values': parameter.value, 'used_in': {'$sbml'},
'object': parameter}
parameters_used[parameter.name] = temp

try:
Expand Down Expand Up @@ -138,7 +139,7 @@ def compile(cls, meta_species_to_simulate, reactions_set, species_counts, orthog
species.order_references()

# Start by creating the Mappings for the SBML
# Convert to user friendly format as well
# Convert to user-friendly format as well
mappings_for_sbml = {}
for spe_object in meta_species_to_simulate:
mappings_for_sbml[spe_object.get_name()] = []
Expand Down Expand Up @@ -202,7 +203,7 @@ def compile(cls, meta_species_to_simulate, reactions_set, species_counts, orthog
= parameters_used[count['quantity'].name]['used_in'].union(set(species_strings))
else:
temp = {'name': count['quantity'].name, 'values': count['quantity'].value,
'used_in': set(species_strings)}
'used_in': set(species_strings), 'object': count['quantity']}
parameters_used[count['quantity'].name] = temp

temp_count = uh_convert_counts(count['quantity'], volume, dimension)
Expand Down Expand Up @@ -232,7 +233,7 @@ def compile(cls, meta_species_to_simulate, reactions_set, species_counts, orthog
parameters_used[count['quantity'].name]['used_in'].add(species_string)
else:
temp = {'name': count['quantity'].name, 'values': count['quantity'].value,
'used_in': {species_string}}
'used_in': {species_string}, 'object': count['quantity']}
parameters_used[count['quantity'].name] = temp

temp_count = uh_convert_counts(count['quantity'], volume, dimension)
Expand Down
2 changes: 1 addition & 1 deletion mobspy/modules/event_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from mobspy.modules.species_string_generator import construct_all_combinations as ssg_construct_all_combinations, \
construct_species_char_list as ssg_construct_species_char_list
from pint import Quantity
from mobspy.modules.mobspy_parameters import _Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.mobspy_parameters import Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.function_rate_code import search_for_parameters_in_str as frc_search_for_parameters_in_str


Expand Down
2 changes: 1 addition & 1 deletion mobspy/modules/function_rate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from mobspy.modules.mobspy_expressions import MobsPyExpression as mbe_MobsPyExpression, \
ExpressionDefiner as mbe_ExpressionDefiner, Specific_Species_Operator as mbe_Specific_Species_Operator
from pint import Quantity
from mobspy.modules.mobspy_parameters import _Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.mobspy_parameters import Internal_Parameter_Constructor as mp_Mobspy_Parameter
from re import split as re_split
import timeit

Expand Down
26 changes: 24 additions & 2 deletions mobspy/modules/meta_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from mobspy.modules.mobspy_expressions import OverrideQuantity as me_OverrideQuantity, \
MobsPyExpression as me_MobsPyExpression, Specific_Species_Operator as me_Specific_Species_Operator, \
ExpressionDefiner as me_ExpressionDefiner
from mobspy.modules.mobspy_parameters import _Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.mobspy_parameters import Internal_Parameter_Constructor as mp_Mobspy_Parameter
from numpy import integer as np_int_, floating as np_float_
from inspect import stack as inspect_stack
from mobspy.modules.meta_class_utils import unite_characteristics as mcu_unite_characteristics, \
Expand Down Expand Up @@ -356,6 +356,22 @@ def __init__(self, object_reference, characteristics, stoichiometry=1, label=Non
self.list_of_reactants = [{'object': object_reference, 'characteristics': characteristics,
'stoichiometry': stoichiometry, 'label': label}]

def get_spe_object(self):
if len(self.list_of_reactants) != 1:
simlog_error("The internal method get_queried_characteristics can only be used for "
"Reacting_Species with a single ",
full_exception_log=True)
else:
return self.list_of_reactants[0]['object']

def get_query_characteristics(self):
if len(self.list_of_reactants) != 1:
simlog_error("The internal method get_queried_characteristics can only be used for "
"Reacting_Species with a single ",
full_exception_log=True)
else:
return self.list_of_reactants[0]['characteristics']

def __rmul__(self, stoichiometry):
"""
Multiplication by the stoichiometry for reactions
Expand Down Expand Up @@ -442,7 +458,7 @@ def __call__(self, quantity):
if len(self.list_of_reactants) != 1:
simlog_error('Assignment used incorrectly. Only one species at a time', stack_index=2)
quantity_dict = species_object.add_quantities(characteristics, quantity)
# elif isinstance(quantity, ExpressionDefiner) and not isinstance(quantity, _Internal_Parameter_Constructor):
# elif isinstance(quantity, ExpressionDefiner) and not isinstance(quantity, Internal_Parameter_Constructor):
# simlog.error('Operations are not allowed for count assignment. Only individual parameters', stack_index=2)
elif asgi_Assign.check_context():
dummy_rsp = species_object
Expand Down Expand Up @@ -1096,6 +1112,12 @@ def __init__(self, name):
# This will store the quantities relating to the species counts
self._species_counts = []

def get_spe_object(self):
return self

def get_query_characteristics(self):
return 'std$'

def link_a_species(self, other_species):
"""
Links a species with another. So if one is added to the model, the other is also added to the model
Expand Down
58 changes: 39 additions & 19 deletions mobspy/modules/mobspy_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pint import Quantity, UnitRegistry


class _Internal_Parameter_Constructor(me_ExpressionDefiner, me_QuantityConverter):
class Internal_Parameter_Constructor(me_ExpressionDefiner, me_QuantityConverter):
"""
This is the constructor that is called by ModelParameters to create a model parameter
(not a simulation parameter). The user is not supposed to create parameters using this object.
Expand All @@ -28,34 +28,38 @@ def __init__(self, name, value):
self._operation = str(name)
self._parameter_set.add(self)

def unit_process(value):
# We convert into MobsPy units already during the definition of a parameter
self.value = self.convert_received_unit(value).magnitude
self.process_value(value)

self.original_magnitude = value.magnitude
self.conversion_factor = self.value / self.original_magnitude
self.original_unit = value.units
def unit_process(self, value):
# We convert into MobsPy units already during the definition of a parameter
self.value = self.convert_received_unit(value).magnitude

# For future developers, the T is there to avoid potential bugs with the . query
self._unit_count_op = value
self._unit_conc_op = value
self._unit_operation = value
self._has_units = 'T'
self.original_magnitude = value.magnitude
self.conversion_factor = self.value / self.original_magnitude
self.original_unit = value.units

return self.value, self.original_unit
# For future developers, the T is there to avoid potential bugs with the . query
self._unit_count_op = value
self._unit_conc_op = value
self._unit_operation = value
self._has_units = 'T'

return self.value, self.original_unit

def process_value(self, value):

if isinstance(value, Quantity):
unit_process(value)
self.unit_process(value)
elif type(value) == list or type(value) == tuple:
new_list = []
first_unit = None
for i, val in enumerate(value):
if isinstance(val, Quantity) and i == 0:
new_value, first_unit = unit_process(val)
new_value, first_unit = self.unit_process(val)
elif isinstance(val, Quantity) and i > 0 and first_unit is None:
simlog.error("MobsPy parameters must all be the same unit", stack_index=1)
elif isinstance(val, Quantity) and i > 0 and first_unit is not None:
new_value, unit = unit_process(val)
new_value, unit = self.unit_process(val)
if unit != first_unit:
simlog.error("MobsPy parameters must all be the same unit", stack_index=1)
else:
Expand All @@ -72,6 +76,7 @@ def unit_process(value):
self.conversion_factor = 1
self._has_units = False


def convert_to_original_unit(self):
"""
Converts the parameter from the MobsPy standard unit to the original unit of the parameter
Expand Down Expand Up @@ -108,6 +113,21 @@ def has_units(self):
else:
return False

def update_value(self, new_value):

temp_set = set()
temp_set.add(self)
self.original_value = new_value

self._ms_active = True

self._parameter_set.add(self)

self.process_value(new_value)

def get_name(self):
return self.name

def __str__(self):
return str(self._operation)

Expand All @@ -124,9 +144,9 @@ def ModelParameters(*args):
simlog.error('You must provide an initial value for every parameter variable declared', stack_index=2)

if len(parameter_variable_names) > 1:
parameters_to_return = [_Internal_Parameter_Constructor(p, v) for p, v in zip(parameter_variable_names, args)]
parameters_to_return = [Internal_Parameter_Constructor(p, v) for p, v in zip(parameter_variable_names, args)]
else:
parameters_to_return = _Internal_Parameter_Constructor(parameter_variable_names[0], args[0])
parameters_to_return = Internal_Parameter_Constructor(parameter_variable_names[0], args[0])

return parameters_to_return

Expand All @@ -137,5 +157,5 @@ def ModelParameters(*args):
r1 = (a + b + c)/5
print(r1._operation)
# print(type(r1._parameter_set))
# print(_Internal_Parameter_Constructor.parameter_stack)
# print(Internal_Parameter_Constructor.parameter_stack)

2 changes: 1 addition & 1 deletion mobspy/modules/set_counts_module.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from mobspy.simulation_logging.log_scripts import error as simlog_error
from inspect import stack as inspect_stack
from mobspy.modules.meta_class import List_Species, Species, Reacting_Species
from mobspy.modules.mobspy_parameters import _Internal_Parameter_Constructor as mp_Mobspy_Parameter
from mobspy.modules.mobspy_parameters import Internal_Parameter_Constructor as mp_Mobspy_Parameter
from pint import Quantity
from numpy import integer as np_int_, floating as np_float_

Expand Down
11 changes: 9 additions & 2 deletions mobspy/modules/species_string_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def characteristics_dictionary(characteristics, characteristics_to_object):
return object_to_characteristic


def construct_species_char_list(spe_object, characteristics, characteristics_to_object, symbol=None):
def construct_species_char_list(spe_or_reactiong_object, characteristics,
characteristics_to_object, symbol=None):
"""
This function constructs a list in the format ['species_name', 'char1', 'char2', ...]. It generetes this list
for a given meta-species and the specified characteristics. Values of characteristics not specified in a
Expand All @@ -31,26 +32,31 @@ def construct_species_char_list(spe_object, characteristics, characteristics_to_
"""
if characteristics == 'std$':
characteristics = set()
spe_object = spe_or_reactiong_object.get_spe_object()

ordered_references_list = spe_object.get_ordered_references()

objects_to_characteristic = characteristics_dictionary(characteristics, characteristics_to_object)

species_char_list = [spe_object]

for obj in ordered_references_list:
if obj in objects_to_characteristic:
species_char_list.append(objects_to_characteristic[obj])
else:
species_char_list.append(obj.first_characteristic)


if symbol is not None:
species_char_list = symbol.join([spe_object.get_name()] + species_char_list [1:]) \
if len(species_char_list) > 1 else spe_object.get_name()


return species_char_list


def construct_all_combinations(spe_object, characteristics, characteristics_to_object, symbol=None):
def construct_all_combinations(spe_or_reactiong_object,
characteristics, characteristics_to_object, symbol=None):
"""
This function constructs all possible list in the format ['species_name', 'char1', 'char2', ...] using
all combinations of characteristics from the vector coordinates not used in the characteristics specified
Expand All @@ -65,6 +71,7 @@ def construct_all_combinations(spe_object, characteristics, characteristics_to_o

if characteristics == 'std$':
characteristics = set()
spe_object = spe_or_reactiong_object.get_spe_object()

spe_object.order_references()
ordered_references_list = spe_object.get_ordered_references()
Expand Down
Loading
Loading