1__author__ = "Jonathan Karr" 2__email__ = "karr@mssm.edu" 3 4try: 5 import biosimulators_utils 6 from biosimulators_utils.combine.data_model import CombineArchive, CombineArchiveContent, CombineArchiveContentFormat 7 from biosimulators_utils.combine.io import CombineArchiveWriter 8 from biosimulators_utils.config import get_config 9 from biosimulators_utils.report.data_model import ReportFormat 10 from biosimulators_utils.report.io import ReportReader 11 from biosimulators_utils.sedml.data_model import ( 12 SedDocument, 13 Model, ModelLanguage, ModelAttributeChange, 14 UniformTimeCourseSimulation, Algorithm, AlgorithmParameterChange, 15 Task, DataGenerator, Report, DataSet, Variable, Symbol) 16 from biosimulators_utils.sedml.io import SedmlSimulationWriter 17 from smoldyn.biosimulators.data_model import Simulation, SimulationInstruction 18 from smoldyn.biosimulators.utils import read_simulation, _read_simulation_line 19except ModuleNotFoundError: 20 biosimulators_utils = None 21from unittest import mock 22import datetime 23import dateutil.tz 24import flaky 25import numpy 26import numpy.testing 27import os 28import shutil 29import smoldyn 30try: 31 import smoldyn.biosimulators.__main__ 32 import smoldyn.biosimulators.combine 33except ModuleNotFoundError: 34 biosimulators_utils = None 35import tempfile 36import unittest 37 38 39@unittest.skipIf(biosimulators_utils is None, "BioSimulators-utils must be installed") 40class BioSimulatorsUtilsTestCase(unittest.TestCase): 41 EXAMPLES_DIRNAME = os.path.join(os.path.dirname(__file__), '..', 'examples') 42 43 def test__read_simulation_line(self): 44 sim = Simulation() 45 46 _read_simulation_line('dim 3', {}, sim) 47 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 48 id='number_dimensions', 49 description='Number of dimensions', 50 macro='dim', 51 arguments='3', 52 ))) 53 54 _read_simulation_line('low_wall x -100 p', {}, sim) 55 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 56 id='low_x_wall_1', 57 description='Low x wall 1', 58 macro='low_wall x', 59 arguments='-100 p', 60 ))) 61 62 _read_simulation_line('high_wall x -100 p', {}, sim) 63 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 64 id='high_x_wall_1', 65 description='High x wall 1', 66 macro='high_wall x', 67 arguments='-100 p', 68 ))) 69 70 _read_simulation_line('boundaries x 0 1', {}, sim) 71 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 72 id='x_boundary', 73 description='X boundary', 74 macro='boundaries x', 75 arguments='0 1', 76 ))) 77 78 _read_simulation_line('define SYSLENGTH 50', {}, sim) 79 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 80 id='value_parameter_SYSLENGTH', 81 description='Value of parameter "SYSLENGTH"', 82 macro='define SYSLENGTH', 83 arguments='50', 84 ))) 85 86 _read_simulation_line('difc all 1', {}, sim) 87 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 88 id='diffusion_coefficient_species_all', 89 description='Diffusion coefficient of species "all"', 90 macro='difc all', 91 arguments='1', 92 ))) 93 94 _read_simulation_line('difc all(x) 1', {}, sim) 95 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 96 id='diffusion_coefficient_species_all_state_x', 97 description='Diffusion coefficient of species "all" in state "x"', 98 macro='difc all(x)', 99 arguments='1', 100 ))) 101 102 _read_simulation_line('difc_rule Prot* 22', {}, sim) 103 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 104 id='diffusion_coefficient_rule_species_Prot_', 105 description='Diffusion coefficient rule for species "Prot*"', 106 macro='difc_rule Prot*', 107 arguments='22', 108 ))) 109 110 _read_simulation_line('difc_rule Prot*(x) 22', {}, sim) 111 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 112 id='diffusion_coefficient_rule_species_Prot__state_x', 113 description='Diffusion coefficient rule for species "Prot*" in state "x"', 114 macro='difc_rule Prot*(x)', 115 arguments='22', 116 ))) 117 118 _read_simulation_line('difm red 1 0 0 0 0 0 0 0 2', {}, sim) 119 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 120 id='membrane_diffusion_coefficient_species_red', 121 description='Membrane diffusion coefficient of species "red"', 122 macro='difm red', 123 arguments='1 0 0 0 0 0 0 0 2', 124 ))) 125 126 _read_simulation_line('difm red(x) 1 0 0 0 0 0 0 0 2', {}, sim) 127 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 128 id='membrane_diffusion_coefficient_species_red_state_x', 129 description='Membrane diffusion coefficient of species "red" in state "x"', 130 macro='difm red(x)', 131 arguments='1 0 0 0 0 0 0 0 2', 132 ))) 133 134 _read_simulation_line('difm_rule red* 1 0 0 0 0 0 0 0 2', {}, sim) 135 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 136 id='membrane_diffusion_coefficient_rule_species_red_', 137 description='Membrane diffusion coefficient rule for species "red*"', 138 macro='difm_rule red*', 139 arguments='1 0 0 0 0 0 0 0 2', 140 ))) 141 142 _read_simulation_line('difm_rule red*(x) 1 0 0 0 0 0 0 0 2', {}, sim) 143 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 144 id='membrane_diffusion_coefficient_rule_species_red__state_x', 145 description='Membrane diffusion coefficient rule for species "red*" in state "x"', 146 macro='difm_rule red*(x)', 147 arguments='1 0 0 0 0 0 0 0 2', 148 ))) 149 150 _read_simulation_line('drift red 0 0 0', {}, sim) 151 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 152 id='drift_species_red', 153 description='Drift of species "red"', 154 macro='drift red', 155 arguments='0 0 0', 156 ))) 157 158 _read_simulation_line('drift red(x) 0 0 0', {}, sim) 159 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 160 id='drift_species_red_state_x', 161 description='Drift of species "red" in state "x"', 162 macro='drift red(x)', 163 arguments='0 0 0', 164 ))) 165 166 _read_simulation_line('drift_rule red* 0 0 0', {}, sim) 167 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 168 id='drift_rule_species_red_', 169 description='Drift rule for species "red*"', 170 macro='drift_rule red*', 171 arguments='0 0 0', 172 ))) 173 174 _read_simulation_line('drift_rule red*(x) 0 0 0', {}, sim) 175 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 176 id='drift_rule_species_red__state_x', 177 description='Drift rule for species "red*" in state "x"', 178 macro='drift_rule red*(x)', 179 arguments='0 0 0', 180 ))) 181 182 _read_simulation_line('surface_drift red surf1 all 0.1', {}, sim) 183 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 184 id='surface_drift_species_red_surface_surf1_shape_all', 185 description='Surface drift of species "red" on surface "surf1" with panel shape "all"', 186 macro='surface_drift red surf1 all', 187 arguments='0.1', 188 ))) 189 190 _read_simulation_line('surface_drift red(x) surf1 all 0.1', {}, sim) 191 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 192 id='surface_drift_species_red_state_x_surface_surf1_shape_all', 193 description='Surface drift of species "red" in state "x" on surface "surf1" with panel shape "all"', 194 macro='surface_drift red(x) surf1 all', 195 arguments='0.1', 196 ))) 197 198 _read_simulation_line('surface_drift_rule red* surf1 all 0.1', {}, sim) 199 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 200 id='surface_drift_rule_species_red__surface_surf1_panel_all', 201 description='Surface drift rule for species "red*" on surface "surf1" of panel shape "all"', 202 macro='surface_drift_rule red* surf1 all', 203 arguments='0.1', 204 ))) 205 206 _read_simulation_line('surface_drift_rule red*(x) surf1 all 0.1', {}, sim) 207 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 208 id='surface_drift_rule_species_red__state_x_surface_surf1_panel_all', 209 description='Surface drift rule for species "red*" in state "x" on surface "surf1" of panel shape "all"', 210 macro='surface_drift_rule red*(x) surf1 all', 211 arguments='0.1', 212 ))) 213 214 _read_simulation_line('mol 167 A 5 u u', {}, sim) 215 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 216 id='initial_count_species_A_5_u_u', 217 description='Initial count of species "A 5 u u"', 218 macro='mol A 5 u u', 219 arguments='167', 220 ))) 221 222 _read_simulation_line('compartment_mol 500 red intersection', {}, sim) 223 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 224 id='initial_count_species_red_intersection', 225 description='Initial count of species "red intersection"', 226 macro='compartment_mol red intersection', 227 arguments='500', 228 ))) 229 230 _read_simulation_line('surface_mol 100 red(up) all rect r1', {}, sim) 231 self.assertTrue(sim.instructions[-1].is_equal(SimulationInstruction( 232 id='initial_count_species_red_up__all_rect_r1', 233 description='Initial count of species "red(up) all rect r1"', 234 macro='surface_mol red(up) all rect r1', 235 arguments='100', 236 ))) 237 238 def test_read_simulation(self): 239 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 240 sim = read_simulation(filename) 241 self.assertEqual(sim.species, ['red', 'green']) 242 self.assertEqual(sim.compartments, []) 243 self.assertEqual(sim.surfaces, []) 244 245 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S9_compartments', 'compart.txt') 246 sim = read_simulation(filename) 247 self.assertEqual(sim.species, ['red', 'green']) 248 self.assertEqual(sim.compartments, ['middle']) 249 self.assertEqual(sim.surfaces, ['walls', 'surf']) 250 251 252@unittest.skipIf(biosimulators_utils is None, "BioSimulators-utils must be installed") 253class BioSimulatorsCombineTestCase(unittest.TestCase): 254 EXAMPLES_DIRNAME = os.path.join(os.path.dirname(__file__), '..', 'examples') 255 256 def setUp(self): 257 self.dirname = tempfile.mkdtemp() 258 259 def tearDown(self): 260 shutil.rmtree(self.dirname) 261 262 def test_SmoldynOutputFile(self): 263 output_file = smoldyn.biosimulators.data_model.SmoldynOutputFile('out.txt', '/tmp/out.txt') 264 self.assertEqual(output_file.name, 'out.txt') 265 self.assertEqual(output_file.filename, '/tmp/out.txt') 266 267 def test_SmoldynCommand(self): 268 output_file = smoldyn.biosimulators.data_model.SmoldynCommand('molcount', 'E') 269 self.assertEqual(output_file.command, 'molcount') 270 self.assertEqual(output_file.type, 'E') 271 272 def test_init_smoldyn_simulation_from_configuration_file(self): 273 sim = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file( 274 os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt')) 275 self.assertIsInstance(sim, smoldyn.Simulation) 276 277 with self.assertRaises(FileNotFoundError): 278 smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file('not a file') 279 280 with self.assertRaisesRegex(ValueError, 'Error: '): 281 smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file( 282 os.path.join(self.EXAMPLES_DIRNAME, 'CMakeLists.txt')) 283 284 def test_read_write_smoldyn_simulation_configuration(self): 285 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 286 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 287 self.assertEqual(config[2], 'graphics opengl') 288 self.assertEqual(config[-6], 'mol 2 green 50') 289 290 filename2 = os.path.join(self.dirname, 'config.txt') 291 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 292 293 config2 = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename2) 294 self.assertEqual(config2, config) 295 296 def test_normalize_smoldyn_simulation_configuration(self): 297 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 298 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 299 self.assertEqual(len(config), 30) 300 301 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 302 303 self.assertEqual(len(config), 25) 304 305 self.assertEqual(config[2], 'graphics opengl') 306 self.assertEqual(config[-1], 'mol 2 green 50') 307 308 config[0] = '#' 309 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 310 self.assertEqual(len(config), 23) 311 312 config[0] = 'graphics opengl###comment #comment2' 313 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 314 self.assertEqual(config[0], 'graphics opengl # comment #comment2') 315 316 config[0] = 'graphics opengl## ' 317 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 318 self.assertEqual(config[0], 'graphics opengl') 319 320 config[0] = '#comment comment2' 321 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 322 self.assertEqual(config[0], '# comment comment2') 323 324 config[0] = 'graphics opengl ' 325 smoldyn.biosimulators.combine.normalize_smoldyn_simulation_configuration(config) 326 self.assertEqual(config[0], 'graphics opengl') 327 328 def test_disable_smoldyn_graphics_in_simulation_configuration(self): 329 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 330 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 331 self.assertEqual(config[2], 'graphics opengl') 332 333 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 334 self.assertEqual(config[2], 'graphics none') 335 336 def test_apply_change_to_smoldyn_simulation(self): 337 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 338 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 339 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 340 filename2 = os.path.join(self.dirname, 'config.txt') 341 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 342 343 smoldyn_simulation = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 344 change = ModelAttributeChange(target='define K_1', new_value='0') 345 preprocessed_change = smoldyn.biosimulators.combine.validate_model_change(change) 346 smoldyn.biosimulators.combine.apply_change_to_smoldyn_simulation_configuration(config, change, preprocessed_change) 347 348 smoldyn_simulation = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 349 change = ModelAttributeChange(target='killmol red', new_value='0') 350 preprocessed_change = smoldyn.biosimulators.combine.validate_model_change(change) 351 smoldyn.biosimulators.combine.apply_change_to_smoldyn_simulation(smoldyn_simulation, change, preprocessed_change) 352 353 smoldyn_simulation = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 354 change = ModelAttributeChange(target='fixmolcount green', new_value='10') 355 preprocessed_change = smoldyn.biosimulators.combine.validate_model_change(change) 356 smoldyn.biosimulators.combine.apply_change_to_smoldyn_simulation(smoldyn_simulation, change, preprocessed_change) 357 358 smoldyn_simulation = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 359 change = ModelAttributeChange(target='fixmolcountincmpt green cytosol', new_value='10') 360 preprocessed_change = smoldyn.biosimulators.combine.validate_model_change(change) 361 smoldyn.biosimulators.combine.apply_change_to_smoldyn_simulation(smoldyn_simulation, change, preprocessed_change) 362 363 change = ModelAttributeChange(target=' dim ', new_value=' 5 ') 364 with self.assertRaises(NotImplementedError): 365 smoldyn.biosimulators.combine.validate_model_change(change) 366 367 def test_get_smoldyn_run_timecourse_args(self): 368 sim = UniformTimeCourseSimulation( 369 initial_time=10., 370 output_start_time=20., 371 output_end_time=30., 372 number_of_points=10, 373 ) 374 375 self.assertEqual(smoldyn.biosimulators.combine.get_smoldyn_run_timecourse_args(sim), { 376 'start': 10., 377 'stop': 30., 378 'dt': 1., 379 }) 380 381 sim.output_end_time += 0.01 382 with self.assertRaises(NotImplementedError): 383 smoldyn.biosimulators.combine.get_smoldyn_run_timecourse_args(sim) 384 385 def test_get_smoldyn_instance_attr_or_run_algorithm_parameter_arg(self): 386 change = AlgorithmParameterChange(kisao_id='KISAO_0000254', new_value='5') 387 param = smoldyn.biosimulators.combine.get_smoldyn_instance_attr_or_run_algorithm_parameter_arg(change) 388 self.assertEqual(param, { 389 'name': 'accuracy', 390 'type': smoldyn.biosimulators.combine.AlgorithmParameterType.run_argument, 391 'value': 5., 392 }) 393 394 change = AlgorithmParameterChange(kisao_id='KISAO_0000488', new_value='10') 395 param = smoldyn.biosimulators.combine.get_smoldyn_instance_attr_or_run_algorithm_parameter_arg(change) 396 self.assertEqual(param, { 397 'name': 'setRandomSeed', 398 'type': smoldyn.biosimulators.combine.AlgorithmParameterType.instance_attribute, 399 'value': 10, 400 }) 401 402 change = AlgorithmParameterChange(kisao_id='KISAO_0000488', new_value='not a float') 403 with self.assertRaises(ValueError): 404 smoldyn.biosimulators.combine.get_smoldyn_instance_attr_or_run_algorithm_parameter_arg(change) 405 406 change = AlgorithmParameterChange(kisao_id='KISAO_0000001', new_value='not a float') 407 with self.assertRaises(NotImplementedError): 408 smoldyn.biosimulators.combine.get_smoldyn_instance_attr_or_run_algorithm_parameter_arg(change) 409 410 def test_add_smoldyn_output_file(self): 411 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 412 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 413 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 414 415 filename2 = os.path.join(self.dirname, 'config.txt') 416 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 417 418 sim = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 419 sim.setGraphics('none') 420 output_file = smoldyn.biosimulators.combine.add_smoldyn_output_file(self.dirname, sim) 421 self.assertIsInstance(output_file, smoldyn.biosimulators.data_model.SmoldynOutputFile) 422 423 smoldyn.biosimulators.combine.add_commands_to_smoldyn_output_file(sim, output_file, [ 424 smoldyn.biosimulators.data_model.SmoldynCommand(command='molcount', type='E'), 425 ]) 426 427 def test_add_smoldyn_output_files_for_sed_variables(self): 428 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 429 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 430 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 431 432 filename2 = os.path.join(self.dirname, 'config.txt') 433 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 434 435 sim = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 436 sim.setGraphics('none') 437 438 var = Variable(id='time', symbol=Symbol.time.value) 439 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables([var]) 440 smoldyn_output_files = smoldyn.biosimulators.combine.add_smoldyn_output_files_for_sed_variables( 441 self.dirname, [var], variable_output_cmd_map, sim) 442 self.assertEqual(set(smoldyn_output_files.keys()), set(['molcount'])) 443 444 var.symbol = 'undefined' 445 with self.assertRaises(ValueError): 446 smoldyn.biosimulators.combine.validate_variables([var]) 447 448 var.symbol = None 449 var.target = 'undefined ' 450 with self.assertRaises(NotImplementedError): 451 smoldyn.biosimulators.combine.validate_variables([var]) 452 453 def test_get_variable_results(self): 454 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt') 455 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 456 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 457 458 filename2 = os.path.join(self.dirname, 'config.txt') 459 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 460 461 sim = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 462 sim.setGraphics('none') 463 464 vars = [ 465 Variable(id='time', symbol=Symbol.time.value), 466 Variable(id='red', target='molcount red'), 467 Variable(id='green', target='molcountspecies green'), 468 Variable(id='greenBox', target='molcountinbox green 0 10'), 469 Variable(id='greenHist', target='molcountspace green x 0 100 20') 470 ] 471 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables(vars) 472 smoldyn_output_files = smoldyn.biosimulators.combine.add_smoldyn_output_files_for_sed_variables( 473 self.dirname, vars, variable_output_cmd_map, sim) 474 475 sim.run(start=0., stop=0.2, dt=0.01, overwrite=True, display=False, quit_at_end=False) 476 477 results = smoldyn.biosimulators.combine.get_variable_results(10, vars, variable_output_cmd_map, smoldyn_output_files) 478 self.assertEqual(set(results.keys()), set(['time', 'red', 'green', 'greenBox', 'greenHist'])) 479 numpy.testing.assert_allclose(results['time'], numpy.linspace(0.1, 0.2, 11)) 480 481 self.assertEqual(results['red'].shape, (11, )) 482 self.assertFalse(numpy.any(numpy.isnan(results['red']))) 483 484 self.assertEqual(results['green'].shape, (11, )) 485 self.assertFalse(numpy.any(numpy.isnan(results['green']))) 486 487 self.assertEqual(results['greenBox'].shape, (11, )) 488 self.assertFalse(numpy.any(numpy.isnan(results['greenBox']))) 489 490 self.assertEqual(results['greenHist'].shape, (11, 20)) 491 self.assertFalse(numpy.any(numpy.isnan(results['greenHist']))) 492 493 vars = [ 494 Variable(id='time', symbol='undefined'), 495 ] 496 with self.assertRaises(ValueError): 497 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables(vars) 498 smoldyn.biosimulators.combine.get_variable_results(10, vars, variable_output_cmd_map, smoldyn_output_files) 499 500 vars = [ 501 Variable(id='red', target='molcount blue'), 502 ] 503 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables(vars) 504 with self.assertRaises(ValueError): 505 smoldyn.biosimulators.combine.get_variable_results(10, vars, variable_output_cmd_map, smoldyn_output_files) 506 507 vars = [ 508 Variable(id='red', target='undefined blue'), 509 ] 510 with self.assertRaises(NotImplementedError): 511 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables(vars) 512 smoldyn.biosimulators.combine.get_variable_results(10, vars, variable_output_cmd_map, smoldyn_output_files) 513 514 def test_get_variable_results_2d(self): 515 filename = os.path.join(self.EXAMPLES_DIRNAME, 'S4_molecules', 'isotropic', 'diffi.txt') 516 config = smoldyn.biosimulators.combine.read_smoldyn_simulation_configuration(filename) 517 smoldyn.biosimulators.combine.disable_smoldyn_graphics_in_simulation_configuration(config) 518 519 filename2 = os.path.join(self.dirname, 'config.txt') 520 smoldyn.biosimulators.combine.write_smoldyn_simulation_configuration(config, filename2) 521 522 sim = smoldyn.biosimulators.combine.init_smoldyn_simulation_from_configuration_file(filename2) 523 sim.setGraphics('none') 524 525 vars = [ 526 Variable(id='time', symbol=Symbol.time.value), 527 Variable(id='greenHist', target='molcountspace2d green(all) z -10 10 30 -10 10 40 -10 10') 528 ] 529 variable_output_cmd_map = smoldyn.biosimulators.combine.validate_variables(vars) 530 smoldyn_output_files = smoldyn.biosimulators.combine.add_smoldyn_output_files_for_sed_variables( 531 self.dirname, vars, variable_output_cmd_map, sim) 532 533 sim.run(start=0., stop=0.2, dt=0.01, overwrite=True, display=False, quit_at_end=False) 534 535 results = smoldyn.biosimulators.combine.get_variable_results(10, vars, variable_output_cmd_map, smoldyn_output_files) 536 self.assertEqual(set(results.keys()), set(['time', 'greenHist'])) 537 numpy.testing.assert_allclose(results['time'], numpy.linspace(0.1, 0.2, 11)) 538 539 self.assertEqual(results['greenHist'].shape, (11, 30, 40)) 540 self.assertFalse(numpy.any(numpy.isnan(results['greenHist']))) 541 542 def test_exec_sed_task(self): 543 task = Task( 544 id='task', 545 model=Model( 546 id='model', 547 source=os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt'), 548 language=ModelLanguage.Smoldyn.value, 549 ), 550 simulation=UniformTimeCourseSimulation( 551 initial_time=0., 552 output_start_time=0.1, 553 output_end_time=0.2, 554 number_of_points=10, 555 algorithm=Algorithm( 556 kisao_id='KISAO_0000057', 557 changes=[ 558 AlgorithmParameterChange(kisao_id='KISAO_0000488', new_value='10'), 559 ] 560 ) 561 ), 562 ) 563 564 variables = [ 565 Variable(id='time', symbol=Symbol.time.value, task=task), 566 Variable(id='red', target='molcount red', task=task), 567 Variable(id='green', target='molcount green', task=task), 568 ] 569 570 results, log = smoldyn.biosimulators.combine.exec_sed_task(task, variables) 571 572 self.assertEqual(set(results.keys()), set(['time', 'red', 'green'])) 573 numpy.testing.assert_allclose(results['time'], numpy.linspace(0.1, 0.2, 11)) 574 for result in results.values(): 575 self.assertEqual(result.shape, (11, )) 576 self.assertFalse(numpy.any(numpy.isnan(result))) 577 578 self.assertEqual(log.algorithm, 'KISAO_0000057') 579 self.assertEqual(log.simulator_details, { 580 'class': 'smoldyn.Simulation', 581 'instanceAttributes': {'setRandomSeed': 10}, 582 'method': 'run', 583 'methodArguments': { 584 'start': 0., 585 'stop': 0.2, 586 'dt': 0.01, 587 }, 588 }) 589 590 task.simulation.algorithm.changes.append(AlgorithmParameterChange('KISAO_0000254', '5')) 591 results, log = smoldyn.biosimulators.combine.exec_sed_task(task, variables) 592 self.assertEqual(log.simulator_details, { 593 'class': 'smoldyn.Simulation', 594 'instanceAttributes': {'setRandomSeed': 10}, 595 'method': 'run', 596 'methodArguments': { 597 'start': 0., 598 'stop': 0.2, 599 'dt': 0.01, 600 'accuracy': 5., 601 }, 602 }) 603 604 task.simulation.algorithm.kisao_id = 'KISAO_0000437' 605 with self.assertRaises(NotImplementedError): 606 smoldyn.biosimulators.combine.exec_sed_task(task, variables) 607 608 def test_exec_sed_task_positive_initial_time(self): 609 task = Task( 610 id='task', 611 model=Model( 612 id='model', 613 source=os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt'), 614 language=ModelLanguage.Smoldyn.value, 615 ), 616 simulation=UniformTimeCourseSimulation( 617 initial_time=0.01, 618 output_start_time=0.01, 619 output_end_time=0.11, 620 number_of_points=10, 621 algorithm=Algorithm( 622 kisao_id='KISAO_0000057', 623 ) 624 ), 625 ) 626 627 variables = [ 628 Variable(id='time', symbol=Symbol.time.value, task=task), 629 Variable(id='red', target='molcount red', task=task), 630 Variable(id='green', target='molcount green', task=task), 631 ] 632 633 results, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables) 634 635 self.assertEqual(set(results.keys()), set(['time', 'red', 'green'])) 636 numpy.testing.assert_allclose(results['time'], numpy.linspace(0.01, 0.11, 11)) 637 638 def test_exec_sed_task_negative_initial_time(self): 639 task = Task( 640 id='task', 641 model=Model( 642 id='model', 643 source=os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt'), 644 language=ModelLanguage.Smoldyn.value, 645 ), 646 simulation=UniformTimeCourseSimulation( 647 initial_time=-0.01, 648 output_start_time=-0.01, 649 output_end_time=0.09, 650 number_of_points=10, 651 algorithm=Algorithm( 652 kisao_id='KISAO_0000057', 653 ) 654 ), 655 ) 656 657 variables = [ 658 Variable(id='time', symbol=Symbol.time.value, task=task), 659 Variable(id='red', target='molcount red', task=task), 660 Variable(id='green', target='molcount green', task=task), 661 ] 662 663 results, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables) 664 665 self.assertEqual(set(results.keys()), set(['time', 'red', 'green'])) 666 numpy.testing.assert_allclose(results['time'], numpy.linspace(-0.01, 0.09, 11), rtol=5e-6) 667 668 @flaky.flaky(max_runs=10, min_passes=1) 669 def test_exec_sed_task_with_changes(self): 670 task = Task( 671 id='task', 672 model=Model( 673 id='model', 674 source=os.path.join(os.path.dirname(__file__), 'fixtures', 'lotvolt.txt'), 675 language=ModelLanguage.Smoldyn.value, 676 ), 677 simulation=UniformTimeCourseSimulation( 678 initial_time=0., 679 output_start_time=0., 680 output_end_time=0.1, 681 number_of_points=10, 682 algorithm=Algorithm( 683 kisao_id='KISAO_0000057', 684 changes=[ 685 AlgorithmParameterChange(kisao_id='KISAO_0000488', new_value='10'), 686 ] 687 ) 688 ), 689 ) 690 model = task.model 691 sim = task.simulation 692 693 variable_ids = ['rabbit', 'fox'] 694 695 variables = [] 696 for variable_id in variable_ids: 697 variables.append(Variable(id=variable_id, target='molcount ' + variable_id, task=task)) 698 699 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 700 results, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 701 with self.assertRaises(AssertionError): 702 for variable_id in variable_ids: 703 numpy.testing.assert_allclose( 704 results[variable_id][0:int(sim.number_of_points / 2 + 1)], 705 results[variable_id][-int(sim.number_of_points / 2 + 1):]) 706 707 # check simulation is repeatable 708 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 709 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 710 for variable_id in variable_ids: 711 numpy.testing.assert_allclose( 712 results2[variable_id], 713 results[variable_id]) 714 715 # check simulation is repeatable in two steps 716 sim.output_end_time = sim.output_end_time / 2 717 sim.number_of_points = int(sim.number_of_points / 2) 718 719 model.changes = [] 720 for variable_id in variable_ids: 721 model.changes.append(ModelAttributeChange(target='fixmolcount ' + variable_id, new_value=None)) 722 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 723 model.changes = [] 724 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 725 for variable_id in variable_ids: 726 numpy.testing.assert_allclose( 727 results2[variable_id], 728 results[variable_id][0:sim.number_of_points + 1]) 729 730 for variable_id in variable_ids: 731 model.changes.append(ModelAttributeChange(target='fixmolcount ' + variable_id, new_value=results2[variable_id][-1])) 732 results3, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 733 for variable_id in variable_ids: 734 numpy.testing.assert_allclose( 735 results3[variable_id], 736 results[variable_id][-(sim.number_of_points + 1):]) 737 738 # check model change modifies simulation 739 model.changes = [] 740 for variable_id in variable_ids: 741 model.changes.append(ModelAttributeChange(target='fixmolcount ' + variable_id, new_value=None)) 742 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 743 model.changes = [] 744 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 745 for variable_id in variable_ids: 746 numpy.testing.assert_allclose( 747 results2[variable_id], 748 results[variable_id][0:sim.number_of_points + 1]) 749 750 for variable_id in variable_ids: 751 model.changes.append(ModelAttributeChange(target='fixmolcount ' + variable_id, new_value=results2[variable_id][-1] + 1)) 752 results3, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 753 with self.assertRaises(AssertionError): 754 for variable_id in variable_ids: 755 numpy.testing.assert_allclose( 756 results3[variable_id], 757 results[variable_id][-(sim.number_of_points + 1):]) 758 759 # check model change modifies simulation 760 model.changes = [] 761 for variable_id in variable_ids: 762 model.changes.append(ModelAttributeChange(target='killmol ' + variable_id, new_value=None)) 763 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 764 model.changes = [] 765 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 766 for variable_id in variable_ids: 767 numpy.testing.assert_allclose( 768 results2[variable_id], 769 results[variable_id][0:sim.number_of_points + 1]) 770 771 for variable_id in variable_ids: 772 model.changes.append(ModelAttributeChange(target='killmol ' + variable_id, new_value=0)) 773 results3, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 774 with self.assertRaises(AssertionError): 775 for variable_id in variable_ids: 776 numpy.testing.assert_allclose( 777 results3[variable_id], 778 results[variable_id][-(sim.number_of_points + 1):]) 779 780 # preprocessing-time change 781 model.changes = [] 782 for variable_id in variable_ids: 783 model.changes.append(ModelAttributeChange(target='define K_1', new_value=10)) 784 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables) 785 for variable_id in variable_ids: 786 numpy.testing.assert_allclose( 787 results2[variable_id], 788 results[variable_id][0:sim.number_of_points + 1]) 789 790 model.changes = [] 791 for variable_id in variable_ids: 792 model.changes.append(ModelAttributeChange(target='define K_1', new_value=10)) 793 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 794 with self.assertRaisesRegex(NotImplementedError, 'can only be changed during simulation preprocessing'): 795 smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 796 model.changes = [] 797 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 798 for variable_id in variable_ids: 799 numpy.testing.assert_allclose( 800 results2[variable_id], 801 results[variable_id][0:sim.number_of_points + 1]) 802 803 model.changes = [] 804 for variable_id in variable_ids: 805 model.changes.append(ModelAttributeChange(target='define K_1', new_value=0)) 806 preprocessed_task = smoldyn.biosimulators.combine.preprocess_sed_task(task, variables) 807 model.changes = [] 808 results2, _ = smoldyn.biosimulators.combine.exec_sed_task(task, variables, preprocessed_task=preprocessed_task) 809 with self.assertRaises(AssertionError): 810 for variable_id in variable_ids: 811 numpy.testing.assert_allclose( 812 results2[variable_id], 813 results[variable_id][0:sim.number_of_points + 1]) 814 815 def test_exec_sedml_docs_in_combine_archive(self): 816 doc, archive_filename = self._build_combine_archive() 817 818 out_dir = os.path.join(self.dirname, 'out') 819 820 config = get_config() 821 config.REPORT_FORMATS = [ReportFormat.h5] 822 823 _, log = smoldyn.biosimulators.combine.exec_sedml_docs_in_combine_archive( 824 archive_filename, out_dir, config=config) 825 if log.exception: 826 raise log.exception 827 828 self._assert_combine_archive_outputs(doc, out_dir) 829 830 def test_command_line_interface(self): 831 doc, archive_filename = self._build_combine_archive() 832 833 out_dir = os.path.join(self.dirname, 'out') 834 with mock.patch.dict(os.environ, self._get_combine_archive_exec_env()): 835 with smoldyn.biosimulators.__main__.App(argv=['-i', archive_filename, '-o', out_dir]) as app: 836 app.run() 837 838 self._assert_combine_archive_outputs(doc, out_dir) 839 840 def test_raw_command_line_interface(self): 841 with mock.patch('sys.argv', ['', '--help']): 842 with self.assertRaises(SystemExit) as context: 843 smoldyn.biosimulators.__main__.main() 844 self.assertRegex(context.Exception, 'usage: ') 845 846 def _build_combine_archive(self): 847 task = Task( 848 id='task', 849 model=Model( 850 id='model', 851 source='bounce1.txt', 852 language=ModelLanguage.Smoldyn.value, 853 ), 854 simulation=UniformTimeCourseSimulation( 855 id='sim', 856 initial_time=0., 857 output_start_time=0.1, 858 output_end_time=0.2, 859 number_of_points=10, 860 algorithm=Algorithm( 861 kisao_id='KISAO_0000057', 862 changes=[ 863 AlgorithmParameterChange(kisao_id='KISAO_0000488', new_value='10'), 864 ] 865 ) 866 ), 867 ) 868 869 variables = [ 870 Variable(id='time', symbol=Symbol.time.value, task=task), 871 Variable(id='red', target='molcount red', task=task), 872 Variable(id='green', target='molcount green', task=task), 873 ] 874 875 doc = SedDocument( 876 models=[task.model], 877 simulations=[task.simulation], 878 tasks=[task], 879 data_generators=[ 880 DataGenerator( 881 id='data_gen_time', 882 variables=[Variable(id='var_time', symbol=Symbol.time.value, task=task)], 883 math='var_time', 884 ), 885 DataGenerator( 886 id='data_gen_red', 887 variables=[Variable(id='var_red', target='molcount red', task=task)], 888 math='var_red', 889 ), 890 DataGenerator( 891 id='data_gen_green', 892 variables=[Variable(id='var_green', target='molcount green', task=task)], 893 math='var_green', 894 ), 895 ], 896 ) 897 doc.outputs.append(Report( 898 id='report', 899 data_sets=[ 900 DataSet(id='data_set_time', label='time', data_generator=doc.data_generators[0]), 901 DataSet(id='data_set_red', label='red', data_generator=doc.data_generators[1]), 902 DataSet(id='data_set_green', label='green', data_generator=doc.data_generators[2]), 903 ] 904 )) 905 906 archive_dirname = os.path.join(self.dirname, 'archive') 907 os.makedirs(archive_dirname) 908 shutil.copyfile(os.path.join(self.EXAMPLES_DIRNAME, 'S1_intro', 'bounce1.txt'), os.path.join(archive_dirname, 'bounce1.txt')) 909 sim_filename = os.path.join(archive_dirname, 'sim_1.sedml') 910 SedmlSimulationWriter().run(doc, sim_filename) 911 912 archive = CombineArchive( 913 contents=[ 914 CombineArchiveContent( 915 'bounce1.txt', CombineArchiveContentFormat.Smoldyn.value), 916 CombineArchiveContent( 917 'sim_1.sedml', CombineArchiveContentFormat.SED_ML.value), 918 ], 919 ) 920 archive_filename = os.path.join(self.dirname, 'archive.omex') 921 CombineArchiveWriter().run(archive, archive_dirname, archive_filename) 922 923 return doc, archive_filename 924 925 def _get_combine_archive_exec_env(self): 926 return { 927 'REPORT_FORMATS': 'h5' 928 } 929 930 def _assert_combine_archive_outputs(self, doc, out_dir): 931 results = ReportReader().run(doc.outputs[0], out_dir, os.path.join('sim_1.sedml', doc.outputs[0].id), format=ReportFormat.h5) 932 933 self.assertEqual(set(results.keys()), set(['data_set_time', 'data_set_red', 'data_set_green'])) 934 numpy.testing.assert_allclose(results['data_set_time'], numpy.linspace(0.1, 0.2, 11)) 935 for result in results.values(): 936 self.assertEqual(result.shape, (11, )) 937 self.assertFalse(numpy.any(numpy.isnan(result))) 938 939 940if __name__ == "__main__": 941 unittest.main() 942