def test_unique_names_1(self): # Test Model.create_unique_names(). # Heavily disputed variable names m = myokit.Model() a = m.add_component('a') ax = a.add_variable('x') b = m.add_component('b') bx = b.add_variable('x') x = m.add_component('x') xx = x.add_variable('x') m.create_unique_names() self.assertEqual(a.uname(), 'a') self.assertEqual(ax.uname(), 'a_x') self.assertEqual(b.uname(), 'b') self.assertEqual(bx.uname(), 'b_x') self.assertEqual(x.uname(), 'x_1') self.assertEqual(xx.uname(), 'x_x') # Disputed variable name --> Generated name already exists m = myokit.Model() a = m.add_component('a') ax = a.add_variable('x') abx = a.add_variable('b_x') aax = a.add_variable('a_x') ax11 = a.add_variable('x_1_1') b = m.add_component('b') bx = b.add_variable('x') bx11 = b.add_variable('x_1_1') m.create_unique_names() self.assertEqual(a.uname(), 'a') self.assertEqual(ax.uname(), 'a_x_1') self.assertEqual(abx.uname(), 'b_x') self.assertEqual(aax.uname(), 'a_x') self.assertEqual(ax11.uname(), 'a_x_1_1') self.assertEqual(b.uname(), 'b') self.assertEqual(bx.uname(), 'b_x_1') self.assertEqual(bx11.uname(), 'b_x_1_1') # Disputed component name m = myokit.Model() a = m.add_component('a') a.add_variable('x') m.add_component('x') m.create_unique_names() self.assertEqual(m.get('a').uname(), 'a') self.assertEqual(m.get('a.x').uname(), 'a_x') self.assertEqual(m.get('x').uname(), 'x_1') # Disputed component name --> Generated name already exists m = myokit.Model() a = m.add_component('a') a.add_variable('x') m.add_component('x') m.add_component('x_1') m.create_unique_names() self.assertEqual(m.get('a').uname(), 'a') self.assertEqual(m.get('a.x').uname(), 'a_x') self.assertEqual(m.get('x').uname(), 'x_2') self.assertEqual(m.get('x_1').uname(), 'x_1')
def create_myokit_model(self): if self.pk_model is None: pk_model = myokit.Model() else: pk_model = self.create_myokit_dosed_pk_model() if self.pd_model is None: pd_model = myokit.Model() else: pd_model = self.pd_model.create_myokit_model() have_both_models = (self.pk_model is not None and self.pd_model is not None) have_no_models = (self.pk_model is None and self.pd_model is None) # use pk model as the base and import the pd model pkpd_model = pk_model # default model is one with just time if have_no_models: pkpd_model = myokit.parse_model(''' [[model]] [myokit] time = 0 [s] bind time in [s] ''') # remove time binding if if have_both_models: time_var = pd_model.get('myokit.time') time_var.set_binding(None) pd_components = list(pd_model.components()) pd_names = [c.name().replace('myokit', 'PD') for c in pd_components] if pd_components: pkpd_model.import_component( pd_components, new_name=pd_names, ) # remove imported time var if have_both_models: imported_pd_component = pkpd_model.get('PD') imported_time = imported_pd_component.get('time') imported_pd_component.remove_variable(imported_time) # do mappings for mapping in self.mappings.all(): pd_var = pkpd_model.get( mapping.pd_variable.qname.replace('myokit', 'PD')) pk_var = pkpd_model.get(mapping.pk_variable.qname) unit_conversion_multiplier = myokit.Unit.conversion_factor( pk_var.unit(), pd_var.unit()) pd_var.set_rhs( myokit.Multiply(myokit.Number(unit_conversion_multiplier), myokit.Name(pk_var))) pkpd_model.validate() return pkpd_model
def test_promote_demote(self): # Test variable promotion and demotion. m = myokit.Model() c = m.add_component('c') v = c.add_variable('v') v.set_rhs(3) self.assertTrue(v.is_literal()) self.assertTrue(v.is_constant()) self.assertFalse(v.is_intermediary()) self.assertFalse(v.is_state()) self.assertEqual(v.lhs(), myokit.Name(v)) self.assertRaises(Exception, v.demote) self.assertRaises(Exception, v.indice) self.assertRaises(Exception, v.state_value) v.promote(3) self.assertFalse(v.is_literal()) self.assertFalse(v.is_constant()) self.assertFalse(v.is_intermediary()) self.assertTrue(v.is_state()) self.assertEqual(v.lhs(), myokit.Derivative(myokit.Name(v))) self.assertEqual(v.indice(), 0) self.assertEqual(v.state_value(), 3) v.demote() self.assertTrue(v.is_literal()) self.assertTrue(v.is_constant()) self.assertFalse(v.is_intermediary()) self.assertFalse(v.is_state()) self.assertEqual(v.lhs(), myokit.Name(v)) self.assertRaises(Exception, v.demote) self.assertRaises(Exception, v.indice) self.assertRaises(Exception, v.state_value) # Test errors v.promote(3) self.assertRaisesRegex(Exception, 'already', v.promote, 4) v.demote() v.set_binding('time') self.assertRaisesRegex(Exception, 'cannot be bound', v.promote, 4) w = v.add_variable('w') self.assertRaisesRegex( Exception, 'only be added to Components', w.promote, 4) # Test we can't demote a variable with references to its derivative m = myokit.Model() c = m.add_component('c') x = c.add_variable('x') x.set_rhs(3) x.promote() y = c.add_variable('y') y.set_rhs('1 + dot(x)') self.assertRaisesRegex( Exception, 'references to its derivative', x.demote) y.set_rhs('1 + x') x.demote()
def test_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_version_selection(self): # Test choosing between CellML versions e = formats.exporter('cellml') model = myokit.Model('hello') t = model.add_component('env').add_variable('time') t.set_binding('time') t.set_rhs(0) # Write to 1.0 model with TemporaryDirectory() as d: path = d.path('test.cellml') e.model(path, model, version='1.0') with open(path, 'r') as f: self.assertIn('cellml/1.0#', f.read()) # Write to 1.1 model with TemporaryDirectory() as d: path = d.path('test.cellml') e.model(path, model, version='1.1') with open(path, 'r') as f: self.assertIn('cellml/1.1#', f.read()) # Write to 2.0 model with TemporaryDirectory() as d: path = d.path('test.cellml') e.model(path, model, version='2.0') with open(path, 'r') as f: self.assertIn('cellml/2.0#', f.read())
def test_basic(self): """ Test the basic meta-data functionality """ # Test assignment with simple and namespaced names m = myokit.Model() m.meta['bert'] = 'ernie' m.meta['bert:ernie'] = 'banaan' def f(): m.meta['bert.ernie'] = 'banaan' self.assertRaises(myokit.InvalidMetaDataNameError, f) def f(): m.meta['bert '] = 'banaan' self.assertRaises(myokit.InvalidMetaDataNameError, f) # Test retrieval self.assertEqual(m.meta['bert'], 'ernie') self.assertEqual(m.meta['bert:ernie'], 'banaan') def f(): return m.meta['bert.ernie'] self.assertRaises(myokit.InvalidMetaDataNameError, f) # Test overwriting m.meta['bert'] = 'verrekijker' self.assertEqual(m.meta['bert'], 'verrekijker') # Test deletion del (m.meta['bert']) self.assertRaises(KeyError, lambda: m.meta['bert'])
def test_creation(self): # Test Benchmarker creation. # Create test model m = myokit.Model('test') c = m.add_component('c') t = c.add_variable('time') t.set_rhs('0') t.set_binding('time') v = c.add_variable('V') v.set_rhs('0') v.promote(-80.1) x = c.add_variable('x') x.set_rhs('exp(V)') y = c.add_variable('y') y.set_rhs(3) m.validate() # Create benchmarker without variables myokit.RhsBenchmarker(m) # Create with objects myokit.RhsBenchmarker(m, [x]) # Create with strings myokit.RhsBenchmarker(m, ['c.x']) # Cannot create with constants self.assertRaisesRegex(ValueError, 'constant', myokit.RhsBenchmarker, m, [y]) # Cannot create with bound variables self.assertRaisesRegex(ValueError, 'bound', myokit.RhsBenchmarker, m, [t])
def test_simple(self): # Test basic functionality. # Create test model m = myokit.Model('test') c = m.add_component('c') t = c.add_variable('time') t.set_rhs('0') t.set_binding('time') v = c.add_variable('V') v.set_rhs('0') v.promote(-80.1) x = c.add_variable('x') x.set_rhs('exp(V)') m.validate() # Create simulation log log = myokit.DataLog() log['c.time'] = np.zeros(10) log['c.V'] = np.linspace(-80.0, 50.0, 10) # Number of repeats repeats = 10 # Run x.set_rhs('1 / (7 * exp((V + 12) / 35) + 9 * exp(-(V + 77) / 6))') b = myokit.RhsBenchmarker(m, [x]) t = b.bench_full(log, repeats) t = b.bench_part(log, repeats) # No errors = pass # Get mean and std after outlier removal mean = b.mean(t) mean, std = b.mean_std(t)
def test_add_alias_errors(self): # Test error handling in :meth:`Component.add_alias()`. m = myokit.Model() c = m.add_component('c') x = c.add_variable('x') d = m.add_component('d') y = d.add_variable('y') z = y.add_variable('z') # Duplicate name d.add_alias('great_name', x) self.assertRaises(myokit.DuplicateName, d.add_alias, 'y', x) # Alias for a nested variable c.add_alias('not_a_problem', y) self.assertRaisesRegex(myokit.IllegalAliasError, 'whose parent', c.add_alias, 'xyz', z) # Alias for a variable in the same component self.assertRaisesRegex(myokit.IllegalAliasError, 'same component', c.add_alias, 'zz', x) # Alias for a component self.assertRaisesRegex(myokit.IllegalAliasError, 'for variables', c.add_alias, 'zz', c)
def test_alias_methods(self): # Test various methods to do with aliases. # Proper use of add_alias m = myokit.Model() c1 = m.add_component('c1') a = c1.add_variable('a') a.set_rhs(2) c2 = m.add_component('c2') c2.add_alias('bert', a) b = c2.add_variable('b') b.set_rhs('3 * bert') self.assertEqual(b.eval(), 6) # Test alias() and alias_for(), remove_alias() self.assertTrue(c2.has_alias('bert')) self.assertTrue(c2.has_alias_for(a)) self.assertEqual(c2.alias('bert'), a) self.assertEqual(c2.alias_for(a), 'bert') c2.remove_alias('bert') self.assertFalse(c2.has_alias('bert')) self.assertFalse(c2.has_alias_for(a)) self.assertRaises(KeyError, c2.alias, 'bert') self.assertRaises(KeyError, c2.alias_for, a) c2.add_alias('bert', a) c2.add_alias('ernie', a) c2.add_alias('hello', a) self.assertTrue(c2.has_alias_for(a)) c2.remove_alias('bert') self.assertTrue(c2.has_alias_for(a)) c2.remove_aliases_for(a) self.assertFalse(c2.has_alias_for(a))
def test_default_protocol(self): # Test default_protocol() # Test default version protocol = myokit.default_protocol() self.assertTrue(isinstance(protocol, myokit.Protocol)) self.assertEqual(protocol.head().period(), 1000) # Test adapting the time unit model = myokit.Model() t = model.add_component('c').add_variable('t') t.set_rhs(0) protocol = myokit.default_protocol(model) self.assertTrue(isinstance(protocol, myokit.Protocol)) self.assertEqual(protocol.head().period(), 1000) t.set_binding('time') protocol = myokit.default_protocol(model) self.assertTrue(isinstance(protocol, myokit.Protocol)) self.assertEqual(protocol.head().period(), 1000) t.set_unit('s') protocol = myokit.default_protocol(model) self.assertTrue(isinstance(protocol, myokit.Protocol)) self.assertEqual(protocol.head().period(), 1) t.set_unit('ms') protocol = myokit.default_protocol(model) self.assertTrue(isinstance(protocol, myokit.Protocol)) self.assertEqual(protocol.head().period(), 1000)
def __init__(self, name=None): self._model = myokit.Model() self._roa_set = False # Route of administration self._dose_comp = None self._depot_comp = None self._dose_rate = None self._regimen = None
def test_read_write(self): # Test using the read() and write() methods try: import sympy as sp except ImportError: print('Sympy not found, skipping test.') return # Test writing and reading with a model a = self._a ca = sp.Symbol('c.a') self.assertEqual(mypy.write(a), ca) self.assertEqual(mypy.read(ca, self._model), a) # Test doing it again, with a different model m = myokit.Model() a = m.add_component('cc').add_variable('aa') a = myokit.Name(a) ca = sp.Symbol('cc.aa') self.assertEqual(mypy.write(a), ca) self.assertEqual(mypy.read(ca, m), a) # Test reading without a model b = myokit.Number('12') cb = sp.Float(12) self.assertEqual(mypy.write(b), cb) self.assertEqual(mypy.read(cb), b)
def test_set_state_value(self): # Test :meth:`Variable.set_state_value()`. m = myokit.Model() c = m.add_component('c') v = c.add_variable('v') w = c.add_variable('w') # Test basic functionality v.promote(10) self.assertEqual(v.state_value(), 10) v.set_state_value(12) self.assertEqual(v.state_value(), 12) # Only states have this option v.demote() self.assertRaisesRegex( Exception, 'Only state variables', v.set_state_value, 3) self.assertRaisesRegex( Exception, 'Only state variables', w.set_state_value, 3) # State values must be literals v.promote(3) self.assertRaises( myokit.NonLiteralValueError, v.set_state_value, w.lhs())
def test_is_referenced(self): # Test :meth:`Variable.is_referenced(). m = myokit.Model() c = m.add_component('c') v = c.add_variable('v') v.set_rhs(3) w = c.add_variable('w') w.set_rhs(4) self.assertFalse(v.is_referenced()) self.assertFalse(w.is_referenced()) v.set_rhs('3 * w') self.assertFalse(v.is_referenced()) self.assertTrue(w.is_referenced()) w.set_rhs('2 * v') self.assertTrue(v.is_referenced()) self.assertTrue(w.is_referenced()) z = c.add_variable('z') z.set_rhs('3 * v') self.assertFalse(z.is_referenced()) self.assertTrue(v.is_referenced()) w.set_rhs(1) self.assertTrue(v.is_referenced()) z.set_rhs(2) self.assertFalse(v.is_referenced())
def test_parse_component(self): """ Test parse_component(), uses parse_variable """ from myokit._parser import parse_component as pc from myokit._parser import ParseInfo from myokit._parser import Tokenizer info = ParseInfo() info.model = m = myokit.Model('test_model') def p(s, name=None): pc(Tokenizer(s), info) if name: return m[name] s = """ [test_component] x = 5 + b b = 13 in [mV] desc: \""" This is a test component. \""" """ c = p(s, 'test_component') self.assertEqual(len(c), 1) self.assertIn('desc', c.meta) self.assertEqual(c.meta['desc'], 'This is a test component.') pass
def test_varowner_get(self): # Test VarOwner.get(). # Test basics m = myokit.Model('test') c = m.add_component('c') x = c.add_variable('x') self.assertIs(m.get('c'), c) self.assertIs(m.get('c.x'), x) self.assertIs(c.get('x'), x) # Test asking for object self.assertIs(m.get(c), c) self.assertIs(m.get(x), x) self.assertIs(c.get(x), x) self.assertIs(x.get(c), c) # Test not founds self.assertRaises(KeyError, m.get, 'y') self.assertRaises(KeyError, m.get, 'c.y') self.assertRaises(KeyError, c.get, 'y') # Test class filter self.assertIs(m.get('c', myokit.Component), c) self.assertRaises(KeyError, m.get, 'c', myokit.Variable) self.assertIs(m.get('c.x', myokit.Variable), x) self.assertIs(c.get('x', myokit.Variable), x) self.assertRaises(KeyError, m.get, 'c.x', myokit.Component) self.assertRaises(KeyError, c.get, 'x', myokit.Component)
def test_binding(self): # Tests setting and getting of bindings # Note that set_binding() is part of Variable, so not tested here m = myokit.Model() c = m.add_component('c') x = c.add_variable('x') x.set_binding('hello') y = c.add_variable('y') y.set_binding('goodbye') z = c.add_variable('z') z.set_binding('x') # Test binding() self.assertEqual(m.binding('goodbye'), y) self.assertEqual(m.binding('hello'), x) self.assertEqual(m.binding('x'), z) self.assertEqual(m.binding('y'), None) # Test bindings() bindings = dict(m.bindings()) self.assertEqual(bindings['goodbye'], y) self.assertEqual(bindings['hello'], x) self.assertEqual(bindings['x'], z) self.assertFalse('y' in bindings) # Test bindingx() self.assertEqual(m.bindingx('goodbye'), y) self.assertEqual(m.bindingx('hello'), x) self.assertEqual(m.bindingx('x'), z) self.assertRaisesRegex(myokit.IncompatibleModelError, 'No variable found with binding "y"', m.bindingx, 'y')
def test_parse_variable(self): """ Tests parse_variable(), uses parse_expression() """ from myokit._parser import parse_variable from myokit._parser import Tokenizer m = myokit.Model('test_model') c = m.add_component('test_component') def p(s, name=None): parse_variable(Tokenizer(s), None, c, convert_proto_rhs=True) if name: return c.var(name) s = """ x1 = 5 """ v = p(s, 'x1') self.assertIsInstance(v, myokit.Variable) self.assertTrue(v.is_constant()) self.assertTrue(v.is_literal()) self.assertFalse(v.is_state()) self.assertFalse(v.is_intermediary()) self.assertEqual(v.unit(), None) self.assertEqual(v.rhs().unit(), None) s = """ x2 = 5 [mV] """ v = p(s, 'x2') self.assertIsInstance(v, myokit.Variable) self.assertTrue(v.is_constant()) self.assertTrue(v.is_literal()) self.assertFalse(v.is_state()) self.assertFalse(v.is_intermediary()) self.assertEqual(v.unit(), None) self.assertEqual(v.rhs().unit(), myokit.parse_unit('mV')) s = """ x3 = 5 in [mV] """ v = p(s, 'x3') self.assertIsInstance(v, myokit.Variable) self.assertTrue(v.is_constant()) self.assertTrue(v.is_literal()) self.assertFalse(v.is_state()) self.assertFalse(v.is_intermediary()) self.assertEqual(v.unit(), myokit.parse_unit('mV')) self.assertEqual(v.rhs().unit(), None) s = """ x4 = 5 [V] : This is x4 """ v = p(s, 'x4') self.assertIsInstance(v, myokit.Variable) self.assertTrue(v.is_constant()) self.assertTrue(v.is_literal()) self.assertFalse(v.is_state()) self.assertFalse(v.is_intermediary()) self.assertEqual(v.unit(), None) self.assertEqual(v.rhs().unit(), myokit.units.V) self.assertEqual(v.meta['desc'], 'This is x4')
def test_labels(self): # Test setting labels and :meth:`Model.labels()`. # Test set_label() and labels() m = myokit.Model() c = m.add_component('c') t = c.add_variable('time') t.set_binding('time') t.set_rhs(0) v = c.add_variable('v') v.set_rhs('3 - v') v.set_label('membrane_potential') w = c.add_variable('w') w.set_rhs(1) x = c.add_variable('x') x.set_rhs(1) labels = list(m.labels()) self.assertEqual(len(labels), 1) self.assertEqual(labels[0][0], 'membrane_potential') self.assertEqual(labels[0][1], v) # Can't have two labels self.assertRaisesRegex(myokit.InvalidLabelError, 'already has a label', v.set_label, 'bert') # No two variables can have the same label self.assertRaisesRegex(myokit.InvalidLabelError, 'already in use', w.set_label, 'membrane_potential') # Labels can't overlap with bindings self.assertRaisesRegex(myokit.InvalidLabelError, 'in use as a binding', w.set_label, 'time')
def test_eval_state_derivatives(self): # Test Model.eval_state_derivatives(). model = myokit.Model('m') component = model.add_component('comp1') t = component.add_variable('time') t.set_binding('time') t.set_rhs(1) a = component.add_variable('a') b = component.add_variable('b') c = component.add_variable('c') a.promote(1) a.set_rhs('1') b.promote(2) b.set_rhs('2 * b') c.promote(3) c.set_rhs('b + c') model.validate() self.assertEqual(model.eval_state_derivatives(), [1, 4, 5]) self.assertEqual(model.eval_state_derivatives(state=[1, 1, 2]), [1, 2, 3]) c.set_rhs('b + c + time') self.assertEqual(model.eval_state_derivatives(), [1, 4, 6]) self.assertEqual( model.eval_state_derivatives(state=[1, 1, 2], inputs={'time': 0}), [1, 2, 3]) # Errors c.set_rhs('(b + c) / 0') self.assertRaises(myokit.NumericalError, model.eval_state_derivatives) nan = model.eval_state_derivatives(ignore_errors=True)[2] self.assertNotEqual(nan, nan) # x != x is a nan test...
def test_add_function(self): # Test the ``Model.add_function`` method. m = myokit.Model('m') c = m.add_component('c') x = c.add_variable('x') # Test basics m.add_function('f', ('a', 'b', 'c'), 'a + b + c') x.set_rhs('f(1, 2, 3)') self.assertEqual(x.eval(), 6) # Test duplicate name # Different number of arguments is allowed: m.add_function('f', ('a', 'b'), 'a + b') self.assertRaisesRegex(myokit.DuplicateFunctionName, 'already defined', m.add_function, 'f', ('a', 'b'), 'a - b') # Test duplicate argument name self.assertRaisesRegex(myokit.DuplicateFunctionArgument, 'already in use', m.add_function, 'g', ('a', 'a'), 'a + a') # Dot operator is not allowed self.assertRaisesRegex(myokit.InvalidFunction, r'dot\(\) operator', m.add_function, 'fdot', ('a', ), 'dot(a)') # Unused argument self.assertRaisesRegex(myokit.InvalidFunction, 'never used', m.add_function, 'fun', ('a', 'b'), 'a') # Unspecified variable self.assertRaisesRegex(myokit.InvalidFunction, 'never declared', m.add_function, 'fun', ('a', ), 'a + b')
def test_validate_and_remove_unused_variables(self): # Test :class:`Model.validate` with ``remove_unused_variables=True``. m = myokit.Model() c = m.add_component('c') t = c.add_variable('time') t.set_binding('time') t.set_rhs(0) x = c.add_variable('x') y = c.add_variable('y') z = c.add_variable('z') z1 = z.add_variable('z1') x.set_rhs('(10 - x) / y') x.promote(0) y.set_rhs(1) z.set_rhs('2 + z1') z1.set_rhs(3) # Two unused variables: z and z1 m.validate() self.assertEqual(len(m.warnings()), 2) # Remove unused variables m.validate(remove_unused_variables=True) self.assertEqual(len(m.warnings()), 2) # 2 removal warnings m.validate() self.assertEqual(len(m.warnings()), 0) # issue fixed!
def test_warnings(self): # Test Model.has_warnings(), model.warnings() and # Model.format_warnings(). # Test model without warnings m = myokit.Model() c = m.add_component('c') t = c.add_variable('time') t.set_binding('time') t.set_rhs(0) v = c.add_variable('v') v.set_rhs('3 - v') v.promote(0.1) m.validate() self.assertFalse(m.has_warnings()) self.assertIn('0 validation warning', m.format_warnings()) self.assertEqual(m.warnings(), []) # Test model with warnings v.validate() v.demote() v.validate() v.set_rhs(3) m.validate() self.assertTrue(m.has_warnings()) self.assertIn('1 validation warning', m.format_warnings()) self.assertIn('Unused variable', str(m.warnings()[0]))
def test_suggest(self): # Test :meth:`Model.suggest(variable_name)`. m = myokit.Model() c1 = m.add_component('c1') t = c1.add_variable('time') t.set_binding('time') t.set_rhs(0) c2 = m.add_component('c2') v = c2.add_variable('v') v.set_rhs('3') # Test with correct name found, suggested, msg = m.suggest_variable('c1.time') self.assertEqual(found, t) self.assertIsNone(suggested) self.assertIsNone(msg) # Test with wrong name found, suggested, msg = m.suggest_variable('c1.tim') self.assertIsNone(found) self.assertEqual(suggested, t) self.assertIn('Unknown', msg) # Test with case mismatch found, suggested, msg = m.suggest_variable('c1.timE') self.assertIsNone(found) self.assertEqual(suggested, t) self.assertIn('Case mismatch', msg) # Test without component found, suggested, msg = m.suggest_variable('time') self.assertIsNone(found) self.assertEqual(suggested, t) self.assertIn('No component', msg)
def test_bindings(self): # Test setting bindings and :meth:`Model.bindings()`. # Test set_binding() and bindings() m = myokit.Model() c = m.add_component('c') t = c.add_variable('time') t.set_binding('time') t.set_rhs(0) v = c.add_variable('v') v.set_rhs('3 - v') w = c.add_variable('w') w.set_rhs(0) bindings = list(m.bindings()) self.assertEqual(len(bindings), 1) self.assertEqual(bindings[0][0], 'time') self.assertEqual(bindings[0][1], t) # Can't have two labels self.assertRaisesRegex(myokit.InvalidBindingError, 'already bound to', t.set_binding, 'bert') # No two variables can have the same label self.assertRaisesRegex(myokit.InvalidBindingError, 'Duplicate binding', v.set_binding, 'time') # Binding can't overlap with label v.set_label('membrane_potential') self.assertRaisesRegex(myokit.InvalidBindingError, 'in use as a label', w.set_binding, 'membrane_potential') # State variables can't be bound v.promote(0) self.assertRaisesRegex(myokit.InvalidBindingError, 'State variables', v.set_binding, 'x')
def test_reorder_state(self): # Test :meth:`Model.reorder_state()`. m = myokit.Model() c = m.add_component('c') t = c.add_variable('time') t.set_binding('time') t.set_rhs(0) v = c.add_variable('v') v.set_rhs('3 - v') v.promote(0) w = c.add_variable('w') w.set_rhs(1) w.promote(0) self.assertEqual(list(m.states()), [v, w]) m.reorder_state([w, v]) self.assertEqual(list(m.states()), [w, v]) m.reorder_state([w, v]) self.assertEqual(list(m.states()), [w, v]) m.reorder_state([v, w]) self.assertEqual(list(m.states()), [v, w]) # Wrong number of states self.assertRaisesRegex(ValueError, 'number of entries', m.reorder_state, [v]) self.assertRaisesRegex(ValueError, 'number of entries', m.reorder_state, [v, w, v]) # Duplicate entries self.assertRaisesRegex(ValueError, 'Duplicate', m.reorder_state, [v, v]) # Not a state self.assertRaisesRegex(ValueError, 'must all be', m.reorder_state, [v, t])
def test_no_time_variable(self): # Test an exception is raised if nothing is bound to time. m = myokit.Model('LotkaVolterra') c0 = m.add_component('c0') t = c0.add_variable('time') t.set_rhs(myokit.Number(0)) self.assertRaises(myokit.MissingTimeVariableError, m.validate)
def test_value(self): # Test :meth:`Variable.value()`. m = myokit.Model() c = m.add_component('c') v = c.add_variable('v') v.set_rhs('1 + 2 + 3 + 4') self.assertEqual(v.value(), 10)
def test_pacing_values_at_event_transitions(self): # Tests the value of the pacing signal at event transitions # Create a simple model m = myokit.Model() c = m.add_component('c') t = c.add_variable('t') t.set_rhs(0) t.set_binding('time') v = c.add_variable('v') v.set_rhs('0') v.set_binding('pace') x = c.add_variable('x') x.set_rhs(0.1) x.promote(0) # Create step protocol p = myokit.Protocol() p.schedule(0, 0, 2) p.schedule(1, 2, 2) p.schedule(2, 4, 4) p.schedule(3, 8, 2) # Simulate with dynamic logging s = myokit.LegacySimulation(m, p) d = s.run(p.characteristic_time()) time = list(d.time()) value = list(d['c.v']) if False: for i, t in enumerate(d.time()): t = str(np.round(t, 5)) print(t + ' ' * (10 - len(t)) + str(d['c.v'][i])) # Values should be # t 0 1 2 3 4 5 6 7 8 9 10 # p 0 0 1 1 2 2 2 2 3 3 0 self.assertEqual(value[time.index(0.0)], 0) self.assertEqual(value[time.index(0.0) + 1], 0) self.assertEqual(value[time.index(2.0) - 1], 0) self.assertEqual(value[time.index(2.0)], 1) self.assertEqual(value[time.index(2.0) + 1], 1) self.assertEqual(value[time.index(4.0) - 1], 1) self.assertEqual(value[time.index(4.0)], 2) self.assertEqual(value[time.index(4.0) + 1], 2) self.assertEqual(value[time.index(8.0) - 1], 2) self.assertEqual(value[time.index(8.0)], 3) self.assertEqual(value[time.index(8.0) + 1], 3) self.assertEqual(value[time.index(10.0) - 1], 3) self.assertEqual(value[time.index(10.0)], 0) # Simulate with fixed logging s.reset() d = s.run(p.characteristic_time() + 1, log_times=d.time()) time2 = list(d.time()) value2 = list(d['c.v']) self.assertEqual(time, time2) self.assertEqual(value, value2)