def test_load_multiline_string_indent(self): # Test what happens when you load save a string that gets auto-indented # Create model with multi-line meta-data property d1 = 'First line\n\nSecond line' m1 = myokit.Model() m1.meta['desc'] = d1 e = m1.add_component('engine') v = e.add_variable('time') v.set_binding('time') v.set_rhs(0) # Store to disk with TemporaryDirectory() as d: opath = d.path('multiline.mmt') myokit.save_model(opath, m1) # Load and compare the meta-data string m2 = myokit.load_model(opath) d2 = m2.meta['desc'] self.assertEqual(d1, d2) # Create model with indented multi-line meta-data property d1 = ' First line\n\n Second line' dr = 'First line\n\nSecond line' m1 = myokit.Model() m1.meta['desc'] = d1 e = m1.add_component('engine') v = e.add_variable('time') v.set_binding('time') v.set_rhs(0) # Store to disk with TemporaryDirectory() as d: opath = d.path('multiline.mmt') myokit.save_model(opath, m1) # Load and compare the meta-data string m2 = myokit.load_model(opath) d2 = m2.meta['desc'] self.assertEqual(d2, dr) # Create model with strangely indented multi-line meta-data property d1 = ' First line\n\n Second line' dr = 'First line\n\n Second line' m1 = myokit.Model() m1.meta['desc'] = d1 e = m1.add_component('engine') v = e.add_variable('time') v.set_binding('time') v.set_rhs(0) # Store to disk with TemporaryDirectory() as d: opath = d.path('multiline.mmt') myokit.save_model(opath, m1) # Load and compare the meta-data string m2 = myokit.load_model(opath) d2 = m2.meta['desc'] self.assertEqual(d2, dr)
def test_save_frame_csv(self): # Test the save_frame_csv() method. w, h = 2, 3 time = [1, 2, 3] b = myokit.DataBlock2d(w, h, time) x = np.array([ # Each 3 by 2 array is a point in time [[0, 1], [2, 3], [4, 5]], [[5, 4], [3, 2], [1, 0]], [[0, 0], [0, 0], [0, 0]], ]) b.set2d('x', x) with TemporaryDirectory() as d: path = d.path('test.csv') b.save_frame_csv(path, 'x', 0) with open(path, 'r') as f: lines = [str(x) for x in f.readlines()] self.assertEqual(lines[0], '"x","y","value"\n') self.assertEqual(lines[1], '0,0,0\n') self.assertEqual(lines[2], '1,0,1\n') self.assertEqual(lines[3], '0,1,2\n') self.assertEqual(lines[4], '1,1,3\n') self.assertEqual(lines[5], '0,2,4\n') self.assertEqual(lines[6], '1,2,5')
def test_load_save_selection(self): # Tests the load_selection method import myokit._sim.opencl org_name = myokit._sim.opencl.SETTINGS_FILE try: with TemporaryDirectory() as d: fname = d.path('opencl-temp.ini') myokit._sim.opencl.SETTINGS_FILE = fname # Save None and None myokit.OpenCL.save_selection(None, None) platform, device = myokit.OpenCL.load_selection() self.assertIsNone(platform) self.assertIsNone(device) myokit.OpenCL.save_selection(None, 'bert') platform, device = myokit.OpenCL.load_selection() self.assertIsNone(platform) self.assertEqual(device, 'bert') myokit.OpenCL.save_selection('ernie', None) platform, device = myokit.OpenCL.load_selection() self.assertEqual(platform, 'ernie') self.assertIsNone(device) myokit.OpenCL.save_selection('ernie', 'bert') platform, device = myokit.OpenCL.load_selection() self.assertEqual(platform, 'ernie') self.assertEqual(device, 'bert') finally: myokit._sim.opencl.SETTINGS_FILE = org_name
def test_stan_exporter(self): # Basic test self._test(myokit.formats.exporter('stan')) # Test with parameters and output variable specified # Load model m = myokit.load_model('example') # Guess parameters parameters = [] for v in m.get('ina').variables(const=True): if v.name()[:1] == 'p': parameters.append(v) parameters.sort(key=lambda v: myokit.tools.natural_sort_key(v.name())) # Set output output = 'ina.INa' # Export to stan e = myokit.formats.stan.StanExporter() with TemporaryDirectory() as d: dpath = d.path('out') ret = e.runnable(dpath, m, parameters=parameters, output=output) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0)
def test_export_reused_variable(self): # Tests exporting when an `inf` or other special variable is used twice # Create model re-using tau and inf m = myokit.parse_model(""" [[model]] m.V = -80 c.x = 0.1 c.y = 0.1 [m] time = 0 bind time i_ion = c.I dot(V) = -i_ion [c] inf = 0.5 tau = 3 dot(x) = (inf - x) / tau dot(y) = (inf - y) / tau I = x * y * (m.V - 50) """) # Export, and read back in e = myokit.formats.easyml.EasyMLExporter() with TemporaryDirectory() as d: path = d.path('easy.model') e.model(path, m) with open(path, 'r') as f: x = f.read() self.assertIn('x_inf =', x) self.assertIn('y_inf =', x) self.assertIn('tau_x =', x) self.assertIn('tau_y =', x)
def test_easyml_exporter(self): # Tests exporting a model model = myokit.load_model('example') with TemporaryDirectory() as d: path = d.path('easy.model') # Test with simple model e = myokit.formats.easyml.EasyMLExporter() e.model(path, model) # Test with extra bound variables model.get('membrane.C').set_binding('hello') e.model(path, model) # Test without V being a state variable v = model.get('membrane.V') v.demote() v.set_rhs(3) e.model(path, model) # Test with invalid model v.set_rhs('2 * V') self.assertRaisesRegex(myokit.ExportError, 'valid model', e.model, path, model)
def parse_in_file(self, xml): """ Inserts the given ``xml`` into a <model> element, writes it to a temporary file, parses it, and returns the result. """ with TemporaryDirectory() as d: path = d.path('test.cellml') with open(path, 'w') as f: f.write(self.wrap(xml)) return v1.parse_file(path)
def test_write_file(self): # Tests write_file m1 = cellml.Model('ernie') with TemporaryDirectory() as d: path = d.path('test.cellml') cellml.write_file(path, m1) m2 = cellml.parse_file(path) self.assertEqual(m2.name(), 'ernie') self.assertEqual(len(m2), 0)
def test_accessors(self): # Test various accessor methods of :class:`AtfFile`. with TemporaryDirectory() as d: # Create data log log = myokit.DataLog() log.set_time_key('time') log['time'] = np.arange(10) log['sint'] = np.sin(log['time']) log['cost'] = np.cos(log['time']) # Write atf file path = d.path('test.atf') axon.save_atf(log, path) # Read atf file atf = myokit.formats.axon.AtfFile(path) # Test filename() self.assertEqual(atf.filename(), path) # Test iter and getitem self.assertEqual(len(list(iter(atf))), 3) self.assertTrue(np.all(atf['time'] == log['time'])) self.assertTrue(np.all(atf['sint'] == log['sint'])) self.assertTrue(np.all(atf['cost'] == log['cost'])) # Test items() items = list(atf.items()) self.assertEqual(items[0][0], 'time') self.assertEqual(items[1][0], 'sint') self.assertEqual(items[2][0], 'cost') self.assertTrue(np.all(items[0][1] == log['time'])) self.assertTrue(np.all(items[1][1] == log['sint'])) self.assertTrue(np.all(items[2][1] == log['cost'])) # Test keys() self.assertEqual(list(atf.keys()), ['time', 'sint', 'cost']) # Test values() values = list(atf.values()) self.assertTrue(np.all(values[0] == log['time'])) self.assertTrue(np.all(values[1] == log['sint'])) self.assertTrue(np.all(values[2] == log['cost'])) # Test len self.assertEqual(len(atf), 3) # Test info self.assertIn('myokit', atf.info()) # Test version self.assertEqual(atf.version(), '1.0')
def test_load_save_state_bin(self): # Test loading/saving state in binary format. m, p, x = myokit.load('example') with TemporaryDirectory() as d: # Test save and load with double precision f = d.path('state.bin') myokit.save_state_bin(f, m.state()) self.assertEqual(myokit.load_state_bin(f), m.state()) # Test save and load with single precision f = d.path('state.bin') myokit.save_state_bin(f, m.state(), myokit.SINGLE_PRECISION) d = np.array(myokit.load_state_bin(f)) - np.array(m.state()) self.assertTrue(np.all(np.abs(d) < 1e-5)) # Not very precise!
def test_unit_conversion(self): # Tests exporting a model that requires unit conversion # Export model m = myokit.parse_model(units_model) e = myokit.formats.easyml.EasyMLExporter() with TemporaryDirectory() as d: path = d.path('easy.model') e.model(path, m) with open(path, 'r') as f: observed = f.read().strip().splitlines() # Get expected output expected = units_output.strip().splitlines() # Compare (line by line, for readable output) for ob, ex in zip(observed, expected): self.assertEqual(ob, ex) self.assertEqual(len(observed), len(expected)) # Test warnings are raised if conversion fails m.get('membrane.V').set_rhs('hh.I1 + mm.I2') m.get('membrane').remove_variable(m.get('membrane.C')) with TemporaryDirectory() as d: path = d.path('easy.model') with WarningCollector() as c: e.model(path, m) self.assertIn('Unable to convert hh.I1', c.text()) self.assertIn('Unable to convert mm.I2', c.text()) m.get('engine.time').set_unit(myokit.units.cm) with TemporaryDirectory() as d: path = d.path('easy.model') with WarningCollector() as c: e.model(path, m) self.assertIn('Unable to convert time units [cm]', c.text())
def test_create(self): # Test if the `_create` method works. # Import hidden _config module path = sys.path try: sys.path.append(myokit.DIR_MYOKIT) import _config as config finally: sys.path = path # Test _create with TemporaryDirectory() as d: filename = d.path('test.ini') config._create(filename) self.assertTrue(os.path.isfile(filename)) self.assertFalse(os.path.isfile(filename))
def test_writable_dir(self): # Test :meth:`_test_writable_dir` for existing paths. m, p, x = myokit.load('example') e = myokit.formats.exporter('ansic') with TemporaryDirectory() as d: # Create in new dir path = d.path('new-dir') e.runnable(path, m, p) # Create again, in same dir (should be ok) e.runnable(path, m, p) # Create at location of file: not allowed! path = d.path('file') with open(path, 'w') as f: f.write('Hello') self.assertRaisesRegex(myokit.ExportError, 'file exists', e.runnable, path, m, p)
def e(self, template, args, expected_error=None): """ Runs a template, if an error is expected it checks if it's the right one. """ with TemporaryDirectory() as d: path = d.path('template') with open(path, 'w') as f: f.write(template) e = myokit.pype.TemplateEngine() if expected_error is None: e.process(path, args) else: try: e.process(path, args) except myokit.pype.PypeError: # Check expected message in error details self.assertIn(expected_error, e.error_details()) return raise RuntimeError('PypeError not raised.')
def test_easyml_exporter_static(self): # Tests exporting a model (with HH and markov states) and compares # against reference output. # Export model m = myokit.load_model(os.path.join(DIR_DATA, 'decker-2009.mmt')) e = myokit.formats.easyml.EasyMLExporter() with TemporaryDirectory() as d: path = d.path('decker.model') e.model(path, m) with open(path, 'r') as f: observed = f.readlines() # Load expected output with open(os.path.join(DIR_DATA, 'decker.model'), 'r') as f: expected = f.readlines() # Compare (line by line, for readable output) for ob, ex in zip(observed, expected): self.assertEqual(ob, ex) self.assertEqual(len(observed), len(expected))
def test_load_save_state(self): # Test loading/saving state. m, p, x = myokit.load('example') with TemporaryDirectory() as d: # Test save and load without model f = d.path('state.txt') myokit.save_state(f, m.state()) self.assertEqual(myokit.load_state(f), m.state()) # Test save and load with model argument myokit.save_state(f, m.state(), m) self.assertEqual(myokit.load_state(f, m), m.state()) # Save without, load with model myokit.save_state(f, m.state()) self.assertEqual(myokit.load_state(f, m), m.state()) # Save with model, load without # Loaded version is dict! myokit.save_state(f, m.state(), m) dct = dict(zip([v.qname() for v in m.states()], m.state())) self.assertEqual(myokit.load_state(f), dct)
def test_save_protocol(self): # Test if the correct parts are saved/loaded from disk using the # ``save_protocol()`` method. ipath = os.path.join(DIR_DATA, 'lr-1991.mmt') # Test example loading p = myokit.load_protocol('example') self.assertIsInstance(p, myokit.Protocol) # Test file loading p = myokit.load_protocol(ipath) self.assertIsInstance(p, myokit.Protocol) with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save_protocol(opath, p) # Test no other parts were written with open(opath, 'r') as f: text = f.read() self.assertFalse('[[model]]' in text) self.assertTrue('[[protocol]]' in text) self.assertFalse('[[script]]' in text) # Test reloading pp = myokit.load_protocol(opath) self.assertIsInstance(pp, myokit.Protocol) self.assertEqual(pp.code(), p.code())
def test_save_script(self): # Test if the correct parts are saved/loaded from disk using the # ``save_script()`` method. ipath = os.path.join(DIR_DATA, 'lr-1991.mmt') # Test example loading x = myokit.load_script('example') self.assertTrue(isinstance(x, basestring)) # Test file loading x = myokit.load_script(ipath) self.assertTrue(isinstance(x, basestring)) with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save_script(opath, x) # Test no other parts were written with open(opath, 'r') as f: text = f.read() self.assertFalse('[[model]]' in text) self.assertFalse('[[protocol]]' in text) self.assertTrue('[[script]]' in text) # Test reloading xx = myokit.load_script(opath) self.assertTrue(isinstance(xx, basestring)) self.assertEqual(x, xx)
def test_load_read(self): # Test if the `_load` method works, when a config file exists. # Import hidden _config module path = sys.path try: sys.path.append(myokit.DIR_MYOKIT) import _config as config finally: sys.path = path # Back-up current settings date_format = myokit.DATE_FORMAT time_format = myokit.TIME_FORMAT force_pyside = myokit.FORCE_PYSIDE force_pyside2 = myokit.FORCE_PYSIDE2 force_pyqt4 = myokit.FORCE_PYQT4 force_pyqt5 = myokit.FORCE_PYQT5 sundials_lib = myokit.SUNDIALS_LIB sundials_inc = myokit.SUNDIALS_INC opencl_lib = myokit.OPENCL_LIB opencl_inc = myokit.OPENCL_INC # Change myokit config dir temporarily path = myokit.DIR_USER try: with TemporaryDirectory() as d: myokit.DIR_USER = d.path() # Simple test with open(d.path('myokit.ini'), 'w') as f: f.write(config1) config._load() # Full values, PySide gui myokit.SUNDIALS_LIB = [] myokit.SUNDIALS_INC = [] myokit.OPENCL_LIB = [] myokit.OPENCL_INC = [] myokit.FORCE_PYSIDE = myokit.FORCE_PYSIDE2 = False myokit.FORCE_PYQT4 = myokit.FORCE_PYQT5 = False with open(d.path('myokit.ini'), 'w') as f: f.write(config2) config._load() self.assertEqual(myokit.DATE_FORMAT, 'TEST_DATE_FORMAT') self.assertEqual(myokit.TIME_FORMAT, 'TEST_TIME_FORMAT') self.assertFalse(myokit.FORCE_PYSIDE) self.assertFalse(myokit.FORCE_PYSIDE2) self.assertFalse(myokit.FORCE_PYQT4) self.assertFalse(myokit.FORCE_PYQT5) self.assertEqual(myokit.SUNDIALS_LIB, ['one', 'two']) self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four']) self.assertEqual(myokit.OPENCL_LIB, ['five', 'six']) self.assertEqual(myokit.OPENCL_INC, ['three', 'eight']) # Lists of paths should be filtered for empty values and # trimmed myokit.SUNDIALS_LIB = [] myokit.SUNDIALS_INC = [] myokit.OPENCL_LIB = [] myokit.OPENCL_INC = [] with open(d.path('myokit.ini'), 'w') as f: f.write(config_empties_1) config._load() self.assertEqual(myokit.SUNDIALS_LIB, ['five']) self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four']) self.assertEqual(myokit.OPENCL_LIB, ['one', 'two point five', 'three']) self.assertEqual(myokit.OPENCL_INC, []) # Even if the list contains " ;", which Python 2's config # parser treats as a comment myokit.SUNDIALS_LIB = [] myokit.SUNDIALS_INC = [] myokit.OPENCL_LIB = [] myokit.OPENCL_INC = [] with open(d.path('myokit.ini'), 'w') as f: f.write(config_empties_2) if sys.hexversion < 0x03020000: self.assertRaises(ImportError, config._load) else: config._load() self.assertEqual(myokit.SUNDIALS_LIB, ['five', 'six']) self.assertEqual(myokit.SUNDIALS_INC, ['three', 'four']) self.assertEqual(myokit.OPENCL_LIB, ['one', 'two point five', 'three']) self.assertEqual(myokit.OPENCL_INC, []) # Qt gui options with open(d.path('myokit.ini'), 'w') as f: f.write(config_pyqt4) config._load() self.assertFalse(myokit.FORCE_PYSIDE) self.assertFalse(myokit.FORCE_PYSIDE2) self.assertTrue(myokit.FORCE_PYQT4) self.assertFalse(myokit.FORCE_PYQT5) with open(d.path('myokit.ini'), 'w') as f: f.write(config_pyqt5) config._load() self.assertFalse(myokit.FORCE_PYSIDE) self.assertFalse(myokit.FORCE_PYSIDE2) self.assertFalse(myokit.FORCE_PYQT4) self.assertTrue(myokit.FORCE_PYQT5) with open(d.path('myokit.ini'), 'w') as f: f.write(config_pyside) config._load() self.assertTrue(myokit.FORCE_PYSIDE) self.assertFalse(myokit.FORCE_PYSIDE2) self.assertFalse(myokit.FORCE_PYQT4) self.assertFalse(myokit.FORCE_PYQT5) with open(d.path('myokit.ini'), 'w') as f: f.write(config_pyside2) config._load() self.assertFalse(myokit.FORCE_PYSIDE) self.assertTrue(myokit.FORCE_PYSIDE2) self.assertFalse(myokit.FORCE_PYQT4) self.assertFalse(myokit.FORCE_PYQT5) # Odd ini file with open(d.path('myokit.ini'), 'w') as f: f.write(config3) config._load() # No ini file (calls _create()) os.remove(d.path('myokit.ini')) config._load() finally: # Reset path myokit.DIR_USER = path # Reset data and time myokit.DATE_FORMAT = date_format myokit.TIME_FORMAT = time_format myokit.FORCE_PYSIDE = force_pyside myokit.FORCE_PYSIDE2 = force_pyside2 myokit.FORCE_PYQT4 = force_pyqt4 myokit.FORCE_PYQT5 = force_pyqt5 myokit.SUNDIALS_LIB = sundials_lib myokit.SUNDIALS_INC = sundials_inc myokit.OPENCL_LIB = opencl_lib myokit.OPENCL_INC = opencl_inc # Reload local settings config._load() # Sanity check self.assertNotEqual(myokit.DATE_FORMAT, 'TEST_DATE_FORMAT') self.assertNotEqual(myokit.TIME_FORMAT, 'TEST_TIME_FORMAT') self.assertEqual(myokit.FORCE_PYSIDE, force_pyside) self.assertEqual(myokit.FORCE_PYSIDE2, force_pyside2) self.assertEqual(myokit.FORCE_PYQT4, force_pyqt4) self.assertEqual(myokit.FORCE_PYQT5, force_pyqt5) self.assertNotEqual(myokit.SUNDIALS_LIB, ['one', 'two']) self.assertNotEqual(myokit.SUNDIALS_INC, ['three', 'four']) self.assertNotEqual(myokit.OPENCL_LIB, ['five', 'six']) self.assertNotEqual(myokit.OPENCL_INC, ['three', 'eight'])
def test_combined(self): # Runs a combined test of: # # - DataLog to Block conversion # - Access to fields in block # - Saving block to binary file # - Loading block from binary file # # Create simulation log with 1d data log = myokit.DataLog() log.set_time_key('time') t = np.linspace(0, 1, 20) log['time'] = t log['0.x'] = np.sin(t) log['1.x'] = np.cos(t) log['2.x'] = np.tan(t) # Convert to datablock b = log.block1d() # Check block contents self.assertTrue(np.all(b.time() == t)) self.assertFalse(b.time() is t) self.assertEqual(b.len0d(), 0) self.assertEqual(b.len1d(), 1) x = b.get1d('x') self.assertTrue(np.all(x[:, 0] == log['0.x'])) self.assertTrue(np.all(x[:, 1] == log['1.x'])) self.assertTrue(np.all(x[:, 2] == log['2.x'])) # Make bigger log, try again log['pace'] = np.ones(t.shape) + t**2 log['0.y'] = np.sqrt(t) log['1.y'] = 1 + np.sqrt(t) log['2.y'] = 2 + np.sqrt(t) # Convert to datablock b = log.block1d() # Check block contents self.assertTrue(np.all(b.time() == t)) self.assertFalse(b.time() is t) self.assertEqual(b.len0d(), 1) self.assertEqual(b.len1d(), 2) self.assertTrue(np.all(b.get0d('pace') == log['pace'])) self.assertFalse(b.get0d('pace') is log['pace']) x = b.get1d('x') self.assertTrue(np.all(x[:, 0] == log['0.x'])) self.assertTrue(np.all(x[:, 1] == log['1.x'])) self.assertTrue(np.all(x[:, 2] == log['2.x'])) y = b.get1d('y') self.assertTrue(np.all(y[:, 0] == log['0.y'])) self.assertTrue(np.all(y[:, 1] == log['1.y'])) self.assertTrue(np.all(y[:, 2] == log['2.y'])) # Test reading and writing with TemporaryDirectory() as d: fname = d.path('block1d.zip') b.save(fname) c = myokit.DataBlock1d.load(fname) # Test block contents self.assertTrue(np.all(b.time() == c.time())) self.assertFalse(b.time() is c.time()) self.assertEqual(c.len0d(), 1) self.assertEqual(c.len1d(), 2) self.assertTrue(np.all(b.get0d('pace') == c.get0d('pace'))) self.assertFalse(b.get0d('pace') is c.get0d('pace')) xb = b.get1d('x') xc = c.get1d('x') self.assertTrue(np.all(xb == xc)) self.assertFalse(xb is xc) yb = b.get1d('y') yc = c.get1d('y') self.assertTrue(np.all(yb == yc)) self.assertFalse(yb is yc)
def test_write_read(self): # Test writing and reading an ATF file. with TemporaryDirectory() as d: # Create data log log = myokit.DataLog() log.set_time_key('time') log['time'] = np.arange(100) log['sint'] = np.sin(log['time']) log['cost'] = np.cos(log['time']) # Write atf file path = d.path('test.atf') axon.save_atf(log, path) # Read atf file log2 = axon.load_atf(path) self.assertEqual(len(log), len(log2)) self.assertEqual(set(log.keys()), set(log2.keys())) for k, v in log.items(): self.assertTrue(np.all(v == log2[k])) # Write selected fields axon.save_atf(log, path, fields=['time', 'sint']) log2 = axon.load_atf(path) self.assertEqual(set(log2.keys()), set(['time', 'sint'])) # Time must be regularly spaced log['time'][-1] *= 2 self.assertRaisesRegex(ValueError, 'regularly spaced', axon.save_atf, log, path) # Field names can't contain quotes log['time'] = np.arange(100) log['si"nt'] = log['sint'] self.assertRaisesRegex(ValueError, 'double quotes', axon.save_atf, log, path) # Field names can't have newlines del (log['si"nt']) log['si\nnt'] = log['sint'] self.assertRaisesRegex(ValueError, 'newlines', axon.save_atf, log, path) # Fields in `fields` must exist del (log['si\nnt']) self.assertRaisesRegex(ValueError, 'not found', axon.save_atf, log, path, fields=['time', 'sint', 'hi']) # Try using on other formats log.save_csv(path) self.assertRaisesRegex(Exception, 'file type', axon.load_atf, path) # Try reading raw meta data (no key-value pairs) with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('"time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\n') f.write('2\t30\t40\n') log2 = axon.load_atf(path) # Test invalid header detection with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('Hello! This is raw meta data\n') f.write('"time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\n') f.write('2\t30\t40\n') self.assertRaisesRegex(Exception, 'double quotation', axon.load_atf, path) # Bad column headers with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('Bonjou\t"time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\n') f.write('2\t30\t40\n') self.assertRaisesRegex(Exception, 'column headers', axon.load_atf, path) # Bad column headers with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\n') f.write('2\t30\t40\n') self.assertRaisesRegex(Exception, 'column headers', axon.load_atf, path) # Too many headers with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('"Bonjour"\t"time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\n') f.write('2\t30\t40\n') self.assertRaisesRegex(Exception, 'found 4', axon.load_atf, path) # Commas as delimiter are ok with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('"time","sint","cost"\n') f.write('0,0.0,1.0\n') f.write('1,10,20\n') f.write('2,30,40\n') axon.load_atf(path) # But can't mix them with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('"time"\t"sint","cost"\n') f.write('0,0.0,1.0\n') f.write('1,10,20\n') f.write('2,30,40\n') self.assertRaisesRegex(Exception, 'Mixed delimiters', axon.load_atf, path) # Too many columns with open(path, 'w') as f: f.write('ATF\t1.0\n') f.write('1\t3\n') f.write('"Hello! This is raw meta data"\n') f.write('"time"\t"sint"\t"cost"\n') f.write('0\t0.0\t1.0\n') f.write('1\t10\t20\t100\n') f.write('2\t30\t40\n') self.assertRaisesRegex(Exception, 'Invalid data', axon.load_atf, path)
def test_format_parse_error(self): # Test format_parse_error. # Test basic formatting, with and without source bad = ' 5 + / 2' try: myokit.parse_expression(bad) except myokit.ParseError as e: # No source self.assertEqual( myokit.format_parse_error(e), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ]) ) # List-of-strings source self.assertEqual( myokit.format_parse_error(e, source=[bad]), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ' 5 + / 2', ' ^' ]) ) # File source with TemporaryDirectory() as d: path = d.path('mmt') with open(path, 'w') as f: f.write(bad + '\n') myokit.format_parse_error(e, source=path), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ' 5 + / 2', ' ^' ]) # Line doesn't exist in source self.assertEqual( myokit.format_parse_error(e, source=[]), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ]) ) # Char doesn't exist in source self.assertEqual( myokit.format_parse_error(e, source=['x']), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ]) ) # Very long lines bad = ' 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + 1000 + 11' bad += ' + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22' bad += ' + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31' # Error near start error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 12', ' 1 + 2 + / 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + 1000 + ..', ' ^', ]) b = bad[:12] + '/ ' + bad[12:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error) error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 83', ' ..+ 12 + 13 + 14 + 15 + / 16 + 17 + 18 + 19 + 20 + 21 + 22..', ' ^', ]) b = bad[:83] + '/ ' + bad[83:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error) error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 133', ' ..+ 21 + 22 + 23 + 24 + 25 + / 26 + 27 + 28 + 29 + 30 + 31', ' ^', ]) b = bad[:133] + '/ ' + bad[133:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error)
def test_combined(self): # Test loading, saving, conversion from data log. # Create simulation log with 1d data log = myokit.DataLog() log.set_time_key('time') t = np.linspace(0, 1, 20) log['time'] = t log['0.0.x'] = np.sin(t) log['0.1.x'] = np.cos(t) log['0.2.x'] = np.tan(t) log['1.0.x'] = np.sin(2 * t) log['1.1.x'] = np.cos(2 * t) log['1.2.x'] = np.tan(2 * t) # Convert to datablock b = log.block2d() # Check block contents self.assertTrue(np.all(b.time() == t)) self.assertFalse(b.time() is t) self.assertEqual(b.len0d(), 0) self.assertEqual(b.len2d(), 1) x = b.get2d('x') for xx in range(2): for yy in range(3): self.assertTrue(np.all(x[:, yy, xx] == log['x', xx, yy])) # Make bigger log, try again log['pace'] = np.ones(t.shape) + t**2 log['0.0.y'] = np.sqrt(t) log['0.1.y'] = 1 + np.sqrt(t) log['0.2.y'] = 2 + np.sqrt(t) log['1.0.y'] = np.sqrt(t * 2) log['1.1.y'] = 1 + np.sqrt(t * 2) log['1.2.y'] = 2 + np.sqrt(t * 3) # Convert to datablock b = log.block2d() # Check block contents self.assertTrue(np.all(b.time() == t)) self.assertFalse(b.time() is t) self.assertEqual(b.len0d(), 1) self.assertEqual(b.len2d(), 2) self.assertTrue(np.all(b.get0d('pace') == log['pace'])) self.assertFalse(b.get0d('pace') is log['pace']) x = b.get2d('x') y = b.get2d('y') for xx in range(2): for yy in range(3): self.assertTrue(np.all(x[:, yy, xx] == log['x', xx, yy])) self.assertTrue(np.all(y[:, yy, xx] == log['y', xx, yy])) # Test reading and writing with TemporaryDirectory() as td: fname = td.path('block2d.zip') b.save(fname) c = myokit.DataBlock2d.load(fname) # Test block contents self.assertTrue(np.all(b.time() == c.time())) self.assertFalse(b.time() is c.time()) self.assertEqual(c.len0d(), 1) self.assertEqual(c.len2d(), 2) self.assertTrue(np.all(b.get0d('pace') == c.get0d('pace'))) self.assertFalse(b.get0d('pace') is c.get0d('pace')) xb = b.get2d('x') xc = c.get2d('x') self.assertTrue(np.all(xb == xc)) self.assertFalse(xb is xc) yb = b.get2d('y') yc = c.get2d('y') self.assertTrue(np.all(yb == yc)) self.assertFalse(yb is yc)
def test_save(self): # Test if the correct parts are saved/loaded from disk using the # ``save()`` method. # Test example loading m, p, x = myokit.load('example') self.assertIsInstance(m, myokit.Model) self.assertIsInstance(p, myokit.Protocol) self.assertTrue(isinstance(x, basestring)) # Save all three and reload with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, m, p, x) mm, pp, xx = myokit.load(opath) self.assertEqual(m.code(), mm.code()) self.assertEqual(p.code(), pp.code()) self.assertEqual(x, xx) # Save only model with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, model=m) with open(opath, 'r') as f: text = f.read() self.assertTrue('[[model]]' in text) self.assertFalse('[[protocol]]' in text) self.assertFalse('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm.code(), m.code()) self.assertEqual(pp, None) self.assertEqual(xx, None) # Save only protocol with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, protocol=p) with open(opath, 'r') as f: text = f.read() self.assertFalse('[[model]]' in text) self.assertTrue('[[protocol]]' in text) self.assertFalse('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm, None) self.assertEqual(pp.code(), p.code()) self.assertEqual(xx, None) # Save only script with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, script=x) with open(opath, 'r') as f: text = f.read() self.assertFalse('[[model]]' in text) self.assertFalse('[[protocol]]' in text) self.assertTrue('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm, None) self.assertEqual(pp, None) self.assertEqual(xx, x) # Save all but model with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, protocol=p, script=x) with open(opath, 'r') as f: text = f.read() self.assertFalse('[[model]]' in text) self.assertTrue('[[protocol]]' in text) self.assertTrue('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm, None) self.assertEqual(pp.code(), p.code()) self.assertEqual(xx, x) # Save all but protocol with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, model=m, script=x) with open(opath, 'r') as f: text = f.read() self.assertTrue('[[model]]' in text) self.assertFalse('[[protocol]]' in text) self.assertTrue('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm.code(), m.code()) self.assertEqual(pp, None) self.assertEqual(xx, x) # Save all but script with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, model=m, protocol=p) with open(opath, 'r') as f: text = f.read() self.assertTrue('[[model]]' in text) self.assertTrue('[[protocol]]' in text) self.assertFalse('[[script]]' in text) mm, pp, xx = myokit.load(opath) self.assertEqual(mm.code(), m.code()) self.assertEqual(pp.code(), p.code()) self.assertEqual(xx, None) # Save all as strings with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, m, p, x) with open(opath, 'r') as f: text1 = f.read() myokit.save(opath, m.code(), p.code(), x) with open(opath, 'r') as f: text2 = f.read() self.assertEqual(text1, text2) # Save all as strings without [[model]] or [[protocol]] tage with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, m, p, x) with open(opath, 'r') as f: text1 = f.read() mcode = '\n'.join(m.code().splitlines()[1:]) pcode = '\n'.join(p.code().splitlines()[1:]) myokit.save(opath, mcode, pcode, x) with open(opath, 'r') as f: text2 = f.read() self.assertEqual(text1, text2) # Save all, compare with string generated version with TemporaryDirectory() as d: opath = d.path('test.mmt') myokit.save(opath, model=m, protocol=p, script=x) with open(opath, 'r') as f: text = f.read() self.assertEqual(text, myokit.save(model=m, protocol=p, script=x))
def _test(self, e, model=None, protocol=None): """ Test a given exporter `e`. """ # Test info method. self.assertIsInstance(e.post_export_info(), basestring) # Load model, protocol m, p = model, protocol if m is None: m = myokit.load_model('example') if p is None: p = myokit.load_protocol('example') with TemporaryDirectory() as d: path = d.path() # Try exports exports = 0 # Try model export if e.supports_model(): exports += 1 # Basic export fpath = os.path.join(path, 'model.txt') ret = e.model(fpath, m) self.assertIsNone(ret) self.assertTrue(os.path.isfile(fpath)) # Unnamed model name = m.name() try: m.set_name(None) ret = e.model(fpath, m) self.assertIsNone(ret) self.assertTrue(os.path.isfile(fpath)) finally: m.set_name(name) else: self.assertRaises(NotImplementedError, e.model, path, m) # Try runnable export if e.supports_runnable(): exports += 1 # Check without protocol dpath = os.path.join(path, 'runnable1') ret = e.runnable(dpath, m) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # Check with protocol dpath = os.path.join(path, 'runnable2') ret = e.runnable(dpath, m, p) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # Write to complex path dpath = os.path.join(path, 'runnable3', 'nest', 'test') ret = e.runnable(dpath, m, p) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) else: self.assertRaises(NotImplementedError, e.runnable, path, m, p) # Test if any exports were available if exports == 0: raise Exception('No types of export supported by: ' + exporter)
def test_runnable_exporter_shared(self): # Test shared functionality of the TemplatedRunnableExporters. e = myokit.formats.exporter('ansic') # Load model, protocol m, p, x = myokit.load('example') # Create empty output directory as subdirectory of DIR_OUT with TemporaryDirectory() as d: path = d.path() # Simple export dpath = os.path.join(path, 'runnable1') ret = e.runnable(dpath, m) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # Write to complex path dpath = os.path.join(path, 'runnable2', 'nest', 'test') ret = e.runnable(dpath, m, p) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # Overwrite existing path ret = e.runnable(dpath, m, p) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # Path pointing to file dpath = os.path.join(path, 'file') with open(dpath, 'w') as f: f.write('contents\n') self.assertRaisesRegex(myokit.ExportError, 'file exists', e.runnable, dpath, m, p) # Directory exists where we're trying to write a file dpath = os.path.join(path, 'runnable3') fname = os.path.join(dpath, 'sim.c') os.makedirs(fname) self.assertRaisesRegex(myokit.ExportError, 'Directory exists', e.runnable, dpath, m, p) # Directory embedded in the output file path def embedded(): return {'sim.c': 'nested/sim.c'} # 1. Normal operation e._dict = embedded dpath = os.path.join(path, 'runnable4') ret = e.runnable(dpath, m, p) self.assertIsNone(ret) self.assertTrue(os.path.isdir(dpath)) self.assertTrue(len(os.listdir(dpath)) > 0) # 2. Try to create directory where file exists def embedded(): return {'sim.c': 'nested/sim.c/som.c'} e._dict = embedded dpath = os.path.join(path, 'runnable4') self.assertRaisesRegex(myokit.ExportError, 'file or link', e.runnable, dpath, m, p)