def test_membrane(self): m = sme.open_example_model() self.assertEqual(len(m.membranes), 2) self.assertRaises(sme.InvalidArgument, lambda: m.membranes["X"]) mem = m.membranes["Outside <-> Cell"] self.assertEqual(mem, m.membranes[0]) self.assertEqual(m.membranes[-1], m.membranes[1]) self.assertEqual(repr(mem), "<sme.Membrane named 'Outside <-> Cell'>") self.assertEqual( str(mem)[0:43], "<sme.Membrane>\n - name: 'Outside <-> Cell'") self.assertEqual(mem.name, "Outside <-> Cell") mem.name = "new name" self.assertEqual(mem.name, "new name") self.assertEqual(len(mem.reactions), 2) self.assertRaises(sme.InvalidArgument, lambda: mem.reactions["X"]) r = mem.reactions["A uptake from outside"] self.assertEqual(r.name, "A uptake from outside") # export model, open again, check membrane is preserved m.export_sbml_file("tmp.xml") m2 = sme.open_sbml_file("tmp.xml") self.assertEqual(len(m2.membranes), 2) mem2 = m2.membranes["new name"] self.assertEqual(mem2.name, mem.name) self.assertEqual(len(mem2.reactions), 2) r2 = mem2.reactions["A uptake from outside"] self.assertEqual(r2.name, r.name)
def test_reaction(self): # get an existing reaction m = sme.open_example_model() c = m.compartments["Nucleus"] r = c.reactions["A to B conversion"] # verify name and properties self.assertEqual(repr(r), "<sme.Reaction named 'A to B conversion'>") self.assertEqual( str(r)[0:44], "<sme.Reaction>\n - name: 'A to B conversion'") self.assertEqual(r.name, "A to B conversion") self.assertEqual(len(r.parameters), 1) self.assertEqual(r.parameters[0].name, "k1") self.assertEqual(r.parameters[0].value, 0.3) # assign new values r.name = "New reac" r.parameters[0].name = "kk" r.parameters[0].value = 0.99 self.assertEqual(repr(r), "<sme.Reaction named 'New reac'>") self.assertEqual(str(r)[0:35], "<sme.Reaction>\n - name: 'New reac'") self.assertEqual(r.name, "New reac") # check change was propagated to model self.assertRaises( sme.InvalidArgument, lambda: c.reactions["A to B conversion"], ) r2 = c.reactions["New reac"] self.assertEqual(r2.name, "New reac") self.assertEqual(len(r2.parameters), 1) self.assertEqual(r2.parameters[0].name, "kk") self.assertEqual(r2.parameters[0].value, 0.99)
def test_parameter(self): # get an existing parameter m = sme.open_example_model() p = m.parameters["param"] # verify name and properties self.assertEqual(repr(p), "<sme.Parameter named 'param'>") self.assertEqual(str(p)[0:33], "<sme.Parameter>\n - name: 'param'") self.assertEqual(p.name, "param") self.assertEqual(p.value, "1") # assign new values p.name = "New param" p.value = "0.8765" self.assertEqual(repr(p), "<sme.Parameter named 'New param'>") self.assertEqual( str(p)[0:37], "<sme.Parameter>\n - name: 'New param'") self.assertEqual(p.name, "New param") self.assertEqual(p.value, "0.8765") # check change was propagated to model self.assertRaises( sme.InvalidArgument, lambda: m.parameters["param"], ) p2 = m.parameters["New param"] self.assertEqual(p2.name, "New param") self.assertEqual(p2.value, "0.8765") self.assertEqual(p2, p) self.assertEqual(p2, m.parameters[0]) self.assertEqual(p2, m.parameters[-1])
def test_compartment_image(self): m = sme.open_example_model() img = m.compartment_image self.assertEqual(len(img), 100) self.assertEqual(len(img[0]), 100) self.assertEqual(len(img[0][0]), 3) self.assertEqual(img[0][0].tolist(), [0, 2, 0]) # outside self.assertEqual(img[30][30].tolist(), [144, 97, 193]) # Cell self.assertEqual(img[50][50].tolist(), [197, 133, 96]) # Nucleus
def test_export_sme_file(self): m = sme.open_example_model() m.name = "Mod" m.compartments["Cell"].name = "C" m.export_sme_file("tmp.sme") m2 = sme.open_file("tmp.sme") self.assertEqual(m2.name, "Mod") self.assertEqual(len(m2.membranes), 2) self.assertEqual(len(m2.compartments), 3) self.assertEqual(m2.compartments["C"].name, "C") self.assertEqual(m2.compartments["Nucleus"].name, "Nucleus") self.assertRaises(sme.InvalidArgument, lambda: m2.compartments["Cell"])
def test_open_example_model(self): m = sme.open_example_model() self.assertEqual(repr(m), "<sme.Model named 'Very Simple Model'>") self.assertEqual( str(m), "<sme.Model>\n - name: 'Very Simple Model'\n - compartments:\n - Outside\n - Cell\n - Nucleus\n - membranes:\n - Outside <-> Cell\n - Cell <-> Nucleus", ) self.assertEqual(m.name, "Very Simple Model") self.assertEqual(len(m.compartments), 3) self.assertEqual(len(m.membranes), 2) m.name = "Model !" self.assertEqual(m.name, "Model !") self.assertRaises(sme.InvalidArgument, lambda: sme.open_example_model("idontexist")) self.assertRaises(sme.InvalidArgument, lambda: sme.open_example_model("")) self.assertRaises(TypeError, lambda: sme.open_example_model([1, 2, 3])) m = sme.open_example_model("brusselator-model") self.assertEqual(repr(m), "<sme.Model named 'The Brusselator'>") self.assertEqual(len(m.compartments), 1) self.assertEqual(len(m.membranes), 0) m = sme.open_example_model("gray-scott") self.assertEqual(repr(m), "<sme.Model named 'Gray-Scott Model'>") self.assertEqual(len(m.compartments), 1) self.assertEqual(len(m.membranes), 0)
def test_import_geometry_from_image(self): imgfile_original = _get_abs_path("concave-cell-nucleus-100x100.png") imgfile_modified = _get_abs_path( "modified-concave-cell-nucleus-100x100.png") m = sme.open_example_model() comp_img_0 = m.compartment_image nucl_mask_0 = m.compartments["Nucleus"].geometry_mask m.import_geometry_from_image(imgfile_modified) comp_img_1 = m.compartment_image nucl_mask_1 = m.compartments["Nucleus"].geometry_mask self.assertFalse(np.array_equal(nucl_mask_0, nucl_mask_1)) self.assertFalse(np.array_equal(comp_img_0, comp_img_1)) m.import_geometry_from_image(imgfile_original) comp_img_2 = m.compartment_image nucl_mask_2 = m.compartments["Nucleus"].geometry_mask self.assertTrue(np.array_equal(comp_img_0, comp_img_2)) self.assertTrue(np.array_equal(nucl_mask_0, nucl_mask_2))
def test_compartment(self): m = sme.open_example_model() c = m.compartments["Cell"] self.assertEqual(repr(c), "<sme.Compartment named 'Cell'>") self.assertEqual(str(c)[0:34], "<sme.Compartment>\n - name: 'Cell'") self.assertEqual(c.name, "Cell") self.assertEqual(len(c.species), 2) c.name = "NewCell" self.assertEqual(c.name, "NewCell") self.assertEqual(m.compartments["NewCell"].name, "NewCell") self.assertRaises(sme.InvalidArgument, lambda: m.compartments["Cell"]) img = c.geometry_mask self.assertEqual(len(img), 100) self.assertEqual(len(img[0]), 100) self.assertEqual(img[0][0], False) self.assertEqual(img[30][30], True) self.assertEqual(img[50][50], False)
def test_parameter_list(self): # get an existing reaction parameter list m = sme.open_example_model() ps = m.compartments["Nucleus"].reactions[ "A to B conversion"].parameters # verify indexing / name-lookup self.assertEqual(len(ps), 1) self.assertRaises(sme.InvalidArgument, lambda: ps["k2"]) self.assertRaises(sme.InvalidArgument, lambda: ps[1]) self.assertRaises(sme.InvalidArgument, lambda: ps[-2]) k = ps["k1"] self.assertEqual(k, ps[0]) self.assertEqual(k, ps[-1]) for p in ps: self.assertEqual(p, k)
def test_reactionparameter(self): # get an existing reaction parameter m = sme.open_example_model() r = m.compartments["Nucleus"].reactions["A to B conversion"] k = r.parameters["k1"] # verify name and properties self.assertEqual(repr(k), "<sme.ReactionParameter named 'k1'>") self.assertEqual( str(k)[0:38], "<sme.ReactionParameter>\n - name: 'k1'") self.assertEqual(k.name, "k1") self.assertEqual(k.value, 0.3) # check getting it again doesn't make a copy k2 = r.parameters["k1"] self.assertEqual(k, k2) self.assertEqual(id(k), id(k2)) # assign new values k.name = "New k" k.value = 0.8765 self.assertEqual(repr(k), "<sme.ReactionParameter named 'New k'>") self.assertEqual( str(k)[0:41], "<sme.ReactionParameter>\n - name: 'New k'") self.assertEqual(k.name, "New k") self.assertEqual(k.value, 0.8765) # check change was propagated to model self.assertRaises( sme.InvalidArgument, lambda: r.parameters["k1"], ) k3 = r.parameters["New k"] self.assertEqual(k, k2) self.assertEqual(k, k3)
def test_simulate(self): for sim_type in [sme.SimulatorType.DUNE, sme.SimulatorType.Pixel]: m = sme.open_example_model() sim_results = m.simulate(0.002, 0.001, simulator_type=sim_type) self.assertEqual(len(sim_results), 3) sim_results2 = m.simulation_results() self.assertEqual(len(sim_results), len(sim_results2)) # continue previous sim sim_results = m.simulate(0.002, 0.001, simulator_type=sim_type, continue_existing_simulation=True) self.assertEqual(len(sim_results), 5) sim_results2 = m.simulation_results() self.assertEqual(len(sim_results), len(sim_results2)) # use string overload sim_results = m.simulate( "0.002;0.001", "0.001;0.001", simulator_type=sim_type, continue_existing_simulation=True, ) self.assertEqual(len(sim_results), 8) sim_results2 = m.simulation_results() self.assertEqual(len(sim_results), len(sim_results2)) # previous sim results are cleared by default sim_results = m.simulate(0.002, 0.001, simulator_type=sim_type, n_threads=2) self.assertEqual(len(sim_results), 3) sim_results2 = m.simulation_results() self.assertEqual(len(sim_results), len(sim_results2)) for res in [sim_results[1], sim_results2[1]]: self.assertEqual( repr(res), "<sme.SimulationResult from timepoint 0.001>") self.assertEqual( str(res), "<sme.SimulationResult>\n - timepoint: 0.001\n - number of species: 5\n", ) self.assertEqual(res.time_point, 0.001) img = res.concentration_image self.assertEqual(len(img), 100) self.assertEqual(len(img[0]), 100) self.assertEqual(len(img[0][0]), 3) self.assertEqual(len(res.species_concentration), 5) conc = res.species_concentration["B_cell"] self.assertEqual(len(conc), 100) self.assertEqual(len(conc[0]), 100) self.assertEqual(conc[0][0], 0.0) # set timeout to 1 second: by default simulation throws on timeout # multiple timesteps before timeout: with self.assertRaises(sme.RuntimeError): m.simulate(10000, 0.1, timeout_seconds=0, simulator_type=sim_type) # approximate dcdt (only returned from simulate & pixel & last timepoint) m = sme.open_example_model() sim_results = m.simulate(0.002, 0.001, simulator_type=sme.SimulatorType.Pixel) self.assertEqual(len(sim_results), 3) self.assertEqual(len(sim_results[0].species_dcdt), 0) self.assertEqual(len(sim_results[1].species_dcdt), 0) self.assertEqual(len(sim_results[2].species_dcdt), 5) dcdt_approx = (sim_results[2].species_concentration["A_cell"] - sim_results[1].species_concentration["A_cell"]) / 0.001 dcdt = sim_results[2].species_dcdt["A_cell"] rms_norm = _rms(dcdt) rms_diff = _rms(dcdt - dcdt_approx) self.assertLess(rms_diff / rms_norm, 0.01) # don't get dcdt from simulation_results(): sim_results2 = m.simulation_results() self.assertEqual(len(sim_results2[0].species_dcdt), 0) self.assertEqual(len(sim_results2[1].species_dcdt), 0) self.assertEqual(len(sim_results2[2].species_dcdt), 0) # single long timestep that times out (only pixel) with self.assertRaises(sme.RuntimeError): m.simulate(10000, 10000, 1) # set timeout to 1 second: don't throw on timeout, return partial results res1 = m.simulate(10000, 0.1, 1, False) self.assertGreaterEqual(len(res1), 1) res2 = m.simulate(10000, 10000, 1, False) self.assertEqual(len(res2), 1) # option to not return simulation results for sim_type in [sme.SimulatorType.DUNE, sme.SimulatorType.Pixel]: m = sme.open_example_model() sim_results = m.simulate(0.002, 0.001, simulator_type=sim_type, return_results=False) self.assertEqual(len(sim_results), 0) # but results are still available from the model sim_results2 = m.simulation_results() self.assertEqual(len(sim_results2), 3)
def test_species(self): # get an existing species m = sme.open_example_model() s = m.compartments["Cell"].species["A_cell"] # verify name and properties self.assertEqual(repr(s), "<sme.Species named 'A_cell'>") self.assertEqual(str(s)[0:32], "<sme.Species>\n - name: 'A_cell'") self.assertEqual(s.name, "A_cell") self.assertEqual(s.diffusion_constant, 6.0) self.assertEqual(s.concentration_type, sme.ConcentrationType.Uniform) self.assertEqual(s.uniform_concentration, 0.0) self.assertEqual(s.analytic_concentration, "") self.assertEqual(s.concentration_image.shape, (100, 100)) self.assertEqual(s.concentration_image[1, 2], 0.0) self.assertEqual(s.concentration_image[23, 40], 0.0) # assign new values s.name = "New A!" s.diffusion_constant = 1.0 s.uniform_concentration = 0.3 self.assertEqual(repr(s), "<sme.Species named 'New A!'>") self.assertEqual(str(s)[0:32], "<sme.Species>\n - name: 'New A!'") self.assertEqual(s.name, "New A!") self.assertEqual(s.diffusion_constant, 1.0) self.assertEqual(s.concentration_type, sme.ConcentrationType.Uniform) self.assertEqual(s.uniform_concentration, 0.3) self.assertEqual(s.analytic_concentration, "") self.assertEqual(s.concentration_image.shape, (100, 100)) self.assertAlmostEqual(s.concentration_image[1, 2], 0.0) self.assertAlmostEqual(s.concentration_image[23, 40], 0.3) # check changes were propagated to model self.assertRaises( sme.InvalidArgument, lambda: m.compartments["Cell"].species["A_cell"], ) s2 = m.compartments["Cell"].species["New A!"] self.assertEqual(s, s2) # set an analytic initial concentration s.analytic_concentration = "cos(x)+1" # type of initial concentration changes: self.assertEqual(s.concentration_type, sme.ConcentrationType.Analytic) # uniform concentration value is unchanged: self.assertEqual(s.uniform_concentration, 0.3) # analytic concentration expression is no longer empty: self.assertEqual(s.analytic_concentration, "cos(x) + 1") self.assertEqual(s.concentration_image.shape, (100, 100)) self.assertAlmostEqual(s.concentration_image[1, 2], 0.0) self.assertAlmostEqual(s.concentration_image[23, 40], 0.05748050894911694) # set a uniform initial concentration s.uniform_concentration = 2.0 # type of initial concentration changes: self.assertEqual(s.concentration_type, sme.ConcentrationType.Uniform) self.assertEqual(s.uniform_concentration, 2.0) # analytic concentration expression is now empty: self.assertEqual(s.analytic_concentration, "") self.assertEqual(s.concentration_image.shape, (100, 100)) self.assertAlmostEqual(s.concentration_image[1, 2], 0.0) self.assertAlmostEqual(s.concentration_image[23, 40], 2.0) # round trip check of image concentration a1 = np.random.default_rng().uniform(0, 1, (100, 100)) s.concentration_image = a1 # uniform concentration value is unchanged: self.assertEqual(s.uniform_concentration, 2.0) self.assertEqual(s.concentration_type, sme.ConcentrationType.Image) # get concentration image a2 = s.concentration_image self.assertEqual(s.concentration_type, sme.ConcentrationType.Image) self.assertAlmostEqual(a1[23, 48], a2[23, 48]) # pixels outside of compartment are ignored compartment_mask = m.compartments["Cell"].geometry_mask self.assertLess(np.sum(np.square(a2[~compartment_mask])), 1e-7) a1[~compartment_mask] = 0.0 self.assertLess(np.sum(np.square(a1 - a2)), 1e-7) # set concentration to output concentration image s.concentration_image = a2 a3 = s.concentration_image self.assertEqual(s.concentration_type, sme.ConcentrationType.Image) self.assertAlmostEqual(a2[23, 48], a3[23, 48]) self.assertLess(np.sum(np.square(a2 - a3)), 1e-7) # invalid image assignments throw with helpful message with self.assertRaises(sme.InvalidArgument) as err: s.concentration_image = np.random.default_rng().uniform(0, 1, 100) self.assertEqual( "Invalid concentration image array: is 1-dimensional, should be 2-dimensional", str(err.exception), ) with self.assertRaises(sme.InvalidArgument) as err: s.concentration_image = np.random.default_rng().uniform( 0, 1, (10, 10, 10)) self.assertEqual( "Invalid concentration image array: is 3-dimensional, should be 2-dimensional", str(err.exception), ) with self.assertRaises(sme.InvalidArgument) as err: s.concentration_image = np.random.default_rng().uniform( 0, 1, (10, 100)) self.assertEqual( "Invalid concentration image array: height is 10, should be 100", str(err.exception), ) with self.assertRaises(sme.InvalidArgument) as err: s.concentration_image = np.random.default_rng().uniform( 0, 1, (100, 101)) self.assertEqual( "Invalid concentration image array: width is 101, should be 100", str(err.exception), )