def test_static_SSA_submodel_methods(self): # static tests of ssa methods model = MakeModel.make_test_model('1 species, 1 reaction') ssa_submodel = self.make_ssa_submodel(model) self.assertEqual(ssa_submodel.num_SsaWaits, 0) self.assertTrue(0 < ssa_submodel.ema_of_inter_event_time.get_ema()) propensities, total_propensities = ssa_submodel.determine_reaction_propensities( ) # there's only one reaction self.assertEqual(propensities[0], total_propensities) spec_type_0_cn = 1000000 species = ['spec_type_0[compt_1]', 'spec_type_1[compt_1]'] species_copy_numbers = dict( zip(species, [spec_type_0_cn, 2 * spec_type_0_cn])) species_stds = dict(zip(species, [0] * 2)) # with constant reaction rates, all propensities are equal model = MakeModel.make_test_model( '2 species, a pair of symmetrical reactions with constant rates', species_copy_numbers=species_copy_numbers, species_stds=species_stds) ssa_submodel = self.make_ssa_submodel(model) propensities, _ = ssa_submodel.determine_reaction_propensities() self.assertEqual(propensities[0], propensities[1]) # with rates given by reactant population, propensities proportional to copy number model = MakeModel.make_test_model( '2 species, a pair of symmetrical reactions rates given by reactant population', init_vol_stds=[0], species_copy_numbers=species_copy_numbers, species_stds=species_stds) ssa_submodel = self.make_ssa_submodel(model) propensities, _ = ssa_submodel.determine_reaction_propensities() self.assertEqual(2 * propensities[0], propensities[1]) ssa_submodel.execute_SSA_reaction(0) expected_population = dict( zip(species, [spec_type_0_cn - 1, 2 * spec_type_0_cn + 1])) population = ssa_submodel.local_species_population.read( 0, set(species)) self.assertEqual(population, expected_population) # test determine_reaction_propensities() exception model = MakeModel.make_test_model('2 species, 1 reaction', default_species_std=0) # set rxn rate constant to 0 so that reaction propensities are 0 rl_constant = model.parameters.get_or_create(id='k_cat_1_1_for') rl_constant.value = 0 ssa_submodel = self.make_ssa_submodel(model) with self.assertRaisesRegex( DynamicFrozenSimulationError, "propensities == 0 won't change species populations"): ssa_submodel.determine_reaction_propensities()
def test_one_reaction_constant_species_pop(self): # test statics init_volume = 1E-16 init_density = 1000 molecular_weight = 100. default_species_copy_number = 10_000 init_accounted_mass = molecular_weight * default_species_copy_number / Avogadro init_accounted_density = init_accounted_mass / init_volume expected_initial_values_compt_1 = dict(init_volume=init_volume, init_accounted_mass=init_accounted_mass, init_mass= init_volume * init_density, init_density=init_density, init_accounted_density=init_accounted_density, accounted_fraction = init_accounted_density / init_density) expected_initial_values = {'compt_1': expected_initial_values_compt_1} model = MakeModel.make_test_model('1 species, 1 reaction', init_vols=[expected_initial_values_compt_1['init_volume']], init_vol_stds=[0], density=init_density, molecular_weight=molecular_weight, default_species_copy_number=default_species_copy_number, default_species_std=0) multialgorithm_simulation = MultialgorithmSimulation(model, self.wc_sim_config) _, dynamic_model = multialgorithm_simulation.build_simulation() check_simul_results(self, dynamic_model, None, expected_initial_values=expected_initial_values)
def test_make_test_model_init_vols(self): # test the volume settings in make_test_model # no vol arguments default_vol = 1E-16 volumes = [] for _ in range(10): model = MakeModel.make_test_model('no reactions') volumes.append(self.get_volume(model.compartments[0])) self.assertTrue( np.abs((np.mean(volumes) - default_vol) / default_vol) < 0.1) # just init_vols specified_vol = 5E-16 volumes = [] for _ in range(10): model = MakeModel.make_test_model('no reactions', init_vols=[specified_vol]) volumes.append(self.get_volume(model.compartments[0])) self.assertTrue( np.abs((np.mean(volumes) - specified_vol) / specified_vol) < 0.1) # just init_vol_stds volumes = [] for _ in range(10): model = MakeModel.make_test_model( 'no reactions', init_vol_stds=[default_vol / 10.]) volumes.append(self.get_volume(model.compartments[0])) self.assertTrue( np.abs((np.mean(volumes) - default_vol) / default_vol) < 0.1) # no variance model = MakeModel.make_test_model('no reactions', init_vol_stds=[0]) self.assertEqual(self.get_volume(model.compartments[0]), default_vol) # both init_vols and init_vol_stds volumes = [] for _ in range(10): model = MakeModel.make_test_model( 'no reactions', init_vols=[default_vol], init_vol_stds=[default_vol / 10.]) volumes.append(self.get_volume(model.compartments[0])) self.assertTrue( np.abs((np.mean(volumes) - default_vol) / default_vol) < 0.1) # raise init_vols or init_vol_stds exception with self.assertRaises(ValueError): MakeModel.make_test_model('no reactions', init_vols=[default_vol, default_vol]) with self.assertRaises(ValueError): MakeModel.make_test_model('no reactions', init_vol_stds=[])
def test_prepare(self): model = MakeModel.make_test_model( '2 species, 1 reaction, with rates given by reactant population', transform_prep_and_check=False) model.id = 'illegal id' simulation = Simulation(model) with self.assertRaises(MultialgorithmError): simulation._prepare()
def test_provide_event_counts(self): model = MakeModel.make_test_model( '2 species, 1 reaction, with rates given by reactant population') simulation = Simulation(model) self.assertTrue('execute run() to obtain event counts' in simulation.provide_event_counts()) with CaptureOutput(relay=False): simulation.run(time_max=100) self.assertTrue('Event type' in simulation.provide_event_counts())
def test_get_simulation_engine(self): model = MakeModel.make_test_model( '2 species, 1 reaction, with rates given by reactant population') simulation = Simulation(model) self.assertEqual(simulation.get_simulation_engine(), None) with CaptureOutput(relay=False): simulation.run(time_max=5) self.assertTrue( isinstance(simulation.get_simulation_engine(), SimulationEngine))
def setUp(self): self.default_species_copy_number = 1000000000.123 self.mdl_1_spec = \ MakeModel.make_test_model('2 species, 1 reaction, with rates given by reactant population', init_vol_stds=[0], default_species_copy_number=self.default_species_copy_number, default_species_std=0, submodel_framework='WC:ordinary_differential_equations') self.ode_submodel_1 = self.make_ode_submodel(self.mdl_1_spec)
def make_model_and_simulation(self, model_type, num_submodels, species_copy_numbers=None, species_stds=None, init_vols=None, submodel_framework='WC:stochastic_simulation_algorithm'): # make simple model if init_vols is not None: if not isinstance(init_vols, list): init_vols = [init_vols]*num_submodels model = MakeModel.make_test_model(model_type, num_submodels=num_submodels, species_copy_numbers=species_copy_numbers, species_stds=species_stds, init_vols=init_vols, submodel_framework=submodel_framework) multialgorithm_simulation = MultialgorithmSimulation(model, self.wc_sim_config) simulation_engine, _ = multialgorithm_simulation.build_simulation() return (model, multialgorithm_simulation, simulation_engine)
def test_simulation_model_in_memory(self): model = MakeModel.make_test_model('2 species, 1 reaction', transform_prep_and_check=False) self.run_simulation(Simulation(model))
def test_simulate_deterministic_simulation_algorithm_submodel(self): model = MakeModel.make_test_model('1 species, 1 reaction') self.transform_model_for_dsa_simulation(model) simulation = Simulation(model) num_events, _ = simulation.run(time_max=100) self.assertGreater(num_events, 0)
def test_SSA_submodel_init(self): model = MakeModel.make_test_model('1 species, 1 reaction') ssa_submodel = self.make_ssa_submodel(model, default_center_of_mass=20) self.assertTrue(isinstance(ssa_submodel, SsaSubmodel))
def test_check_simul_results(self): init_volume = 1E-16 init_density = 1000 molecular_weight = 100. default_species_copy_number = 10_000 init_accounted_mass = molecular_weight * default_species_copy_number / Avogadro init_accounted_density = init_accounted_mass / init_volume expected_initial_values_compt_1 = dict( init_volume=init_volume, init_accounted_mass=init_accounted_mass, init_mass=init_volume * init_density, init_density=init_density, init_accounted_density=init_accounted_density, accounted_fraction=init_accounted_density / init_density) expected_initial_values = {'compt_1': expected_initial_values_compt_1} model = MakeModel.make_test_model( '1 species, 1 reaction', init_vols=[expected_initial_values_compt_1['init_volume']], init_vol_stds=[0], density=init_density, molecular_weight=molecular_weight, default_species_copy_number=default_species_copy_number, default_species_std=0, submodel_framework='WC:deterministic_simulation_algorithm') multialgorithm_simulation = MultialgorithmSimulation( model, self.wc_sim_config) _, dynamic_model = multialgorithm_simulation.build_simulation() check_simul_results(self, dynamic_model, None, expected_initial_values=expected_initial_values) # test dynamics simulation = Simulation(model) _, results_dir = simulation.run(time_max=2, **self.args) nan = float('NaN') check_simul_results(self, dynamic_model, results_dir, expected_initial_values=expected_initial_values, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 9999., 9998.]}) check_simul_results(self, dynamic_model, results_dir, expected_initial_values=expected_initial_values, expected_species_trajectories=\ {'spec_type_0[compt_1]':[nan, nan, nan]}) with self.assertRaises(AssertionError): check_simul_results(self, dynamic_model, results_dir, expected_initial_values=expected_initial_values, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 10000., 9998.]}) with self.assertRaises(AssertionError): check_simul_results(self, dynamic_model, results_dir, expected_initial_values=expected_initial_values, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 10000.]}) check_simul_results(self, dynamic_model, results_dir, expected_initial_values=expected_initial_values, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 9999., 9998.]}, rel_tol=1E-5) check_simul_results(self, dynamic_model, results_dir, expected_property_trajectories={ 'compt_1': { 'mass': [1.000e-13, 9.999e-14, 9.998e-14] } }) check_simul_results(self, dynamic_model, results_dir, expected_property_trajectories={ 'compt_1': { 'mass': [nan, nan, nan] } }) with self.assertRaises(AssertionError): check_simul_results(self, dynamic_model, results_dir, expected_property_trajectories={ 'compt_1': { 'mass': [1.000e-13, 1.000e-13, 9.999e-14] } }, rel_tol=0) plots_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', 'tests', 'results')) os.makedirs(plots_dir, exist_ok=True) plot_expected_vs_simulated(dynamic_model, 'ordinary_differential_equations', results_dir, trajectory_times=[0, 1, 2], plots_dir=plots_dir, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 10000., 9998.]}, expected_property_trajectories=\ {'compt_1': {'mass':[1.000e-13, 1.000e-13, 9.999e-14]}}) plot_expected_vs_simulated(dynamic_model, 'ordinary_differential_equations', results_dir, trajectory_times=[0, 1, 2], plots_dir=plots_dir, expected_property_trajectories=\ {'compt_1': {'mass':[1.000e-13, 1.000e-13, 9.999e-14]}}) plot_expected_vs_simulated(dynamic_model, 'ordinary_differential_equations', results_dir, trajectory_times=[0, 1, 2], plots_dir=plots_dir, expected_species_trajectories=\ {'spec_type_0[compt_1]':[10000., 10000., 9998.]}) plot_expected_vs_simulated(dynamic_model, 'ordinary_differential_equations', results_dir, trajectory_times=[0, 1, 2], plots_dir=plots_dir, expected_species_trajectories=\ {'spec_type_0[compt_1]':[nan, nan, nan]}, expected_property_trajectories=\ {'compt_1': {'mass':[nan, nan, nan]}})
def test_make_test_model(self): ''' Simple SSA model tests: no reactions: simulation terminates immediately 1 species: one reaction consume species, at constant rate: consume all reactant, in time given by rate 2 species: one reaction: convert all reactant into product, in time given by rate a pair of symmetrical reactions with constant rates: maintain steady state, on average a pair of symmetrical reactions rates given by reactant population: maintain steady state, on average a pair of symmetrical reactions rates given by product population: exhaust on species, with equal chance for each species ** ring of futile reactions with balanced rates: maintain steady state, on average ''' # test get_model_type_params expected_params_list = [(0, 0, False, RateLawType.constant), (1, 1, False, RateLawType.constant), (2, 1, False, RateLawType.constant), (2, 1, True, RateLawType.constant), (2, 1, True, RateLawType.reactant_pop), (2, 1, True, RateLawType.product_pop)] for model_type, expected_params in zip(self.model_types, expected_params_list): params = MakeModel.get_model_type_params(model_type) self.assertEqual(params, expected_params) # test make_test_model for model_type in self.model_types: for num_submodels in [1, 10]: model = MakeModel.make_test_model( model_type, num_submodels=num_submodels, transform_prep_and_check=False) self.assertEqual(model.validate(), None) # test round-tripping file = model_type.replace(' ', '_').replace(',', '') file = "{}_{}_submodels.xlsx".format(file, num_submodels) filename = os.path.join(self.test_dir, file) Writer().run(filename, model, data_repo_metadata=False) round_trip_model = Reader().run(filename)[Model][0] self.assertEqual(round_trip_model.validate(), None) self.assertTrue(round_trip_model.is_equal(model, tol=1e-8)) self.assertEqual(model.difference(round_trip_model, tol=1e-8), '') # unittest one of the models made # TODO (ARTHUR): test with multiple submodels # TODO (ARTHUR): test observables # TODO (ARTHUR): test functions model = MakeModel.make_test_model(self.model_types[4]) self.assertEqual(model.id, 'test_model') comp = model.compartments[0] self.assertEqual(comp.id, 'compt_1') species_type_ids = set([st.id for st in model.species_types]) self.assertEqual(species_type_ids, set(['spec_type_0', 'spec_type_1'])) species_ids = set([s.id for s in comp.species]) self.assertEqual(species_ids, set(['spec_type_0[compt_1]', 'spec_type_1[compt_1]'])) submodel = model.submodels[0] # reaction was split by SplitReversibleReactionsTransform ratelaw_elements = set() for r in submodel.reactions: self.assertFalse(r.reversible) rl = r.rate_laws[0] ratelaw_elements.add((rl.direction, rl.expression.expression)) expected_rate_laws = set([ # direction, expression.expression (RateLawDirection.forward, 'k_cat_1_1_for * spec_type_0[compt_1] / Avogadro / volume_compt_1' ), # forward (RateLawDirection.forward, 'k_cat_1_1_bck * spec_type_1[compt_1] / Avogadro / volume_compt_1' ), # backward, but reversed ]) self.assertEqual(ratelaw_elements, expected_rate_laws) participant_elements = set() for r in submodel.reactions: r_list = [] for part in r.participants: r_list.append((part.species.id, part.coefficient)) participant_elements.add(tuple(sorted(r_list))) expected_participants = set([ # id, coefficient tuple( sorted((('spec_type_0[compt_1]', -1), ('spec_type_1[compt_1]', 1)))), # forward tuple( sorted((('spec_type_1[compt_1]', -1), ('spec_type_0[compt_1]', 1)))), # reversed ]) self.assertEqual(participant_elements, expected_participants) # test exceptions with self.assertRaises(ValueError): MakeModel.make_test_model('3 reactions') with self.assertRaises(ValueError): MakeModel.make_test_model(self.model_types[0], num_submodels=0)
def test_add_test_submodel(self): # test the concentration initialization in add_test_submodel model_type = '1 species, 1 reaction' num_species = 1 vol_mean, vol_std = 1E-16, 1E-17 species_id = 'spec_type_0[compt_1]' model, species_types, comp = self.setup_submodel_params( model_type, num_species, vol_mean, vol_std) default_species_copy_number, default_species_std = 1_000_000, 100_000 species_copy_numbers, species_stds = {}, {} # species not in species_copy_numbers or species_stds MakeModel.add_test_submodel(model, model_type, 0, comp, species_types, default_species_copy_number, default_species_std, species_copy_numbers, species_stds, {}) conc = model.get_distribution_init_concentrations()[0] expected_mean_conc = MakeModel.convert_pop_conc( default_species_copy_number, vol_mean) expected_std_conc = MakeModel.convert_pop_conc(default_species_std, vol_mean) self.assertEqual(conc.mean, expected_mean_conc) self.assertEqual(conc.std, expected_std_conc) # species only in species_copy_numbers model, species_types, comp = self.setup_submodel_params( model_type, num_species, vol_mean, vol_std) species_copy_number = 1_000_000 species_copy_numbers, species_stds = { species_id: species_copy_number }, {} MakeModel.add_test_submodel(model, model_type, 0, comp, species_types, default_species_copy_number, default_species_std, species_copy_numbers, species_stds, {}) conc = model.get_distribution_init_concentrations()[0] expected_mean_conc = MakeModel.convert_pop_conc( species_copy_number, vol_mean) expected_std_conc = MakeModel.convert_pop_conc(default_species_std, vol_mean) self.assertEqual(conc.mean, expected_mean_conc) self.assertEqual(conc.std, expected_std_conc) # species only in species_stds model, species_types, comp = self.setup_submodel_params( model_type, num_species, vol_mean, vol_std) species_std = 100_000 species_copy_numbers, species_stds = {}, {species_id: species_std} MakeModel.add_test_submodel(model, model_type, 0, comp, species_types, default_species_copy_number, default_species_std, species_copy_numbers, species_stds, {}) conc = model.get_distribution_init_concentrations()[0] expected_mean_conc = MakeModel.convert_pop_conc( default_species_copy_number, vol_mean) expected_std_conc = MakeModel.convert_pop_conc(default_species_std, vol_mean) self.assertEqual(conc.mean, expected_mean_conc) self.assertEqual(conc.std, expected_std_conc) # species in species_copy_numbers and species_stds model, species_types, comp = self.setup_submodel_params( model_type, num_species, vol_mean, vol_std) species_copy_numbers, species_stds = { species_id: species_copy_number }, { species_id: species_std } MakeModel.add_test_submodel(model, model_type, 0, comp, species_types, default_species_copy_number, default_species_std, species_copy_numbers, species_stds, {}) conc = model.get_distribution_init_concentrations()[0] expected_mean_conc = MakeModel.convert_pop_conc( species_copy_number, vol_mean) expected_std_conc = MakeModel.convert_pop_conc(species_std, vol_mean) self.assertEqual(conc.mean, expected_mean_conc) self.assertEqual(conc.std, expected_std_conc)