def test_csymbol(self): # Test csymbol parsing # A csymbol MathML's way to define extensions, e.g. functions or # operators or symbols not defined in MathML. In Myokit we only # support their use as a type of <ci>. self.assertEqual( self.p('<csymbol definitionURL="hello" />'), myokit.Name('hello') ) # Missing definition url self.assertRaisesRegex( mathml.MathMLError, 'must contain a definitionURL attribute', self.p, '<csymbol>Hiya</csymbol>') # Unknown variable d = {'a': myokit.Name('a')} p = mathml.MathMLParser( lambda x, y: d[x], lambda x, y: myokit.Number(x), ) x = etree.fromstring('<csymbol definitionURL="a" />') self.assertEqual(p.parse(x), myokit.Name('a')) x = etree.fromstring('<csymbol definitionURL="b" />') self.assertRaisesRegex( mathml.MathMLError, 'Unable to create Name from csymbol', p.parse, x)
def _add_dose_compartment(model, drug_amount, time_unit): """ Adds a dose compartment to the model with a linear absorption rate to the connected compartment. """ # Add a dose compartment to the model dose_comp = model.add_component_allow_renaming('dose') # Create a state variable for the drug amount in the dose compartment dose_drug_amount = dose_comp.add_variable('drug_amount') dose_drug_amount.set_rhs(0) dose_drug_amount.set_unit(drug_amount.unit()) dose_drug_amount.promote() # Create an absorption rate variable absorption_rate = dose_comp.add_variable('absorption_rate') absorption_rate.set_rhs(1) absorption_rate.set_unit(1 / time_unit) # Add outflow expression to dose compartment dose_drug_amount.set_rhs( myokit.Multiply(myokit.PrefixMinus(myokit.Name(absorption_rate)), myokit.Name(dose_drug_amount))) # Add inflow expression to connected compartment rhs = drug_amount.rhs() drug_amount.set_rhs( myokit.Plus( rhs, myokit.Multiply(myokit.Name(absorption_rate), myokit.Name(dose_drug_amount)))) return dose_drug_amount
def equal(self): """ Test of __eq__ operators """ a1 = myokit.Number(4) a2 = myokit.Number(5) self.assertEqual(a1, a1) self.assertEqual(a1, myokit.Number(4)) self.assertEqual(a1, myokit.Number(4.0)) self.assertNotEqual(a1, a2) b1 = myokit.Name('test') b2 = myokit.Name('tost') self.assertEqual(b1, b1) self.assertNotEqual(b1, b2) c1 = myokit.PrefixPlus(a1) c2 = myokit.PrefixPlus(a1) self.assertEqual(c1, c1) self.assertEqual(c1, c2) c2 = myokit.PrefixPlus(a2) self.assertNotEqual(c1, c2) d1 = myokit.Plus(a1, a2) d2 = myokit.Plus(a1, a2) self.assertEqual(d1, d1) self.assertEqual(d1, d2) d2 = myokit.Plus(a2, a1) self.assertNotEqual(d2, d1) e1 = myokit.Sqrt(a1) e2 = myokit.Sqrt(a1) self.assertEqual(e1, e1) self.assertEqual(e1, e2) e2 = myokit.Sqrt(a2) self.assertNotEqual(e1, e2)
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 create_dimless_tumour_growth_model(): r""" Returns a tumour growth myokit model. .. math:: \frac{\text{d}v}{\text{d}\tau} = \frac{a_1 v} {v + a_0}, where the tumour volume :math:`v` and time :math:`\tau` are dimensionless and measured in characteristic scales :math:`V^c_T` and :math:`t^c`. The model parameters :math:`a_0` and :math:`a_1` are also dimensionless. """ # Instantiate model model = Model() # Add central compartment central_comp = model.add_compartment('central') # Add tumour growth variables to central compartment volume_t = central_comp.add_variable('volume_t') a_0 = central_comp.add_variable('a_0') a_1 = central_comp.add_variable('a_1') # Bind time time = central_comp.add_variable('time') time.set_binding('time') # Set intial values (some default values) and units time.set_rhs(0) volume_t.set_rhs(0) a_0.set_rhs(1) # Avoid ZeroDivisionError a_1.set_rhs(0) # Set units time.set_unit('dimensionless') volume_t.set_unit('dimensionless') a_0.set_unit('dimensionless') a_1.set_unit('dimensionless') # Set rhs of tumor volume # dot(volume_t) = # (a_1 * volume_t) / # (volume_t + a_0) volume_t.promote() volume_t.set_rhs( myokit.Divide(myokit.Multiply(myokit.Name(a_1), myokit.Name(volume_t)), myokit.Plus(myokit.Name(volume_t), myokit.Name(a_0)))) # Validate model model.validate() # Check units model.check_units() return model
def setUpClass(cls): # Create a model with a variable cls._model = myokit.Model() component = cls._model.add_component('c') bvar = component.add_variable('b') bvar.set_rhs(1.23) avar = component.add_variable('a') avar.set_rhs('b') cls._a = myokit.Name(avar) cls._b = myokit.Name(bvar)
def _ex_name(self, e): var = str(e) # Check if this is a derivative # See :meth:`SymPyExpressionWriter._ex_derivative()`. if self._model: if var[:4] == 'dot(' and var[-1:] == ')': var = self._model.get(var[4:-1], myokit.Variable) return myokit.Derivative(myokit.Name(var)) var = self._model.get(var, myokit.Variable) return myokit.Name(var)
def fit(self, model, var, rng, report=None): """ Attempts to approximate suitable functions in the given model. A variable ``var`` must be specified, as well as the range ``rng`` that this variable is likely to take. A typical example would be the variable ``membrane.V`` and the range ``(-100, 50)``. The variable can be specified as a name (string), an object representing a variable or an LhsExpression. The range can be specified as any sequence type of length 2. If the variable ``report`` is set, a small HTML based report will be generated and stored in the directory indicated by ``report``. """ # Copy model self.original_model = model model = model.clone() # Get left-hand side expression for variable if isinstance(var, myokit.LhsExpression): if isinstance(var, myokit.Derivative): raise ValueError('Cannot fit with respect to a state.') # Get equivalent variable from cloned model var = model.get(var.var().qname()) lhs = myokit.Name(var) else: if type(var) in [str, unicode]: lhs = myokit.Name(model.get(var)) elif isinstance(var, myokit.Variable): # Get equivalent variable from cloned model var = model.get(var.var().qname()) lhs = myokit.Name(var) else: raise ValueError( 'The argument "var" must be either an LhsExpression, a' ' Variable or a string referencing a model variable') # Test suitability of variable if lhs.is_constant(): raise ValueError('The given variable can not be constant.') # Test suitability of range if len(rng) < 2: raise ValueError( 'The argument "rng" must contain the lower and' ' upper boundaries of the variable\'s name.') if rng[0] == rng[1]: raise ValueError( 'The given range must contain two distinct values.') if rng[0] > rng[1]: rng = rng.reverse() # Reset list of changed variables self._changed = [] # Go! return self._fit(model, lhs, rng, report)
def _test_maths(self, version): # Test maths is written (in selected ``version``) # Create model m1 = cellml.Model('m', version) c1 = m1.add_component('c') p1 = c1.add_variable('p', 'mole') p1.set_initial_value(2) q1 = c1.add_variable('q', 'dimensionless') r1 = c1.add_variable('r', 'second') r1.set_initial_value(0.1) t1 = c1.add_variable('t', 'second') m1.set_variable_of_integration(t1) # Add component without maths d1 = m1.add_component('d') s1 = d1.add_variable('s', 'volt') s1.set_initial_value(1.23) # Add two equations # Note: Numbers without units become dimensionless in CellML eq1 = myokit.Equation( myokit.Name(q1), myokit.Plus(myokit.Number(3, myokit.units.mole), myokit.Name(p1))) er1 = myokit.Equation(myokit.Derivative(myokit.Name(r1)), myokit.Power(myokit.Name(q1), myokit.Number(2))) q1.set_equation(eq1) r1.set_equation(er1) # Write and read xml = cellml.write_string(m1) m2 = cellml.parse_string(xml) # Check results p2, q2, r2, s2 = m2['c']['p'], m2['c']['q'], m2['c']['r'], m2['d']['s'] subst = { myokit.Name(p1): myokit.Name(p2), myokit.Name(q1): myokit.Name(q2), myokit.Name(r1): myokit.Name(r2), } eq2 = eq1.clone(subst) er2 = er1.clone(subst) self.assertEqual(q2.equation(), eq2) self.assertEqual(r2.equation(), er2) self.assertEqual(s2.initial_value(), myokit.Number(1.23, myokit.units.volt)) self.assertFalse(p2.is_state()) self.assertFalse(q2.is_state()) self.assertTrue(r2.is_state()) self.assertFalse(s2.is_state()) self.assertIs(m2.variable_of_integration(), m2['c']['t'])
def test_user_function(self): # Test :class:`UserFunction` creation and methods. # Create without arguments f = myokit.UserFunction('bert', [], myokit.Number(12)) args = list(f.arguments()) self.assertEqual(len(args), 0) self.assertEqual(f.convert([]), myokit.Number(12)) # Create with one argument f = myokit.UserFunction('x', [myokit.Name('a')], myokit.parse_expression('1 + a')) self.assertEqual(len(list(f.arguments())), 1) args = {myokit.Name('a'): myokit.Number(3)} self.assertEqual(f.convert(args).eval(), 4) # Create with two argument f = myokit.UserFunction( 'x', [myokit.Name('a'), myokit.Name('b')], myokit.parse_expression('a + b')) self.assertEqual(len(list(f.arguments())), 2) args = { myokit.Name('a'): myokit.Number(3), myokit.Name('b'): myokit.Number(4) } self.assertEqual(f.convert(args), myokit.parse_expression('3 + 4')) # Call with wrong arguments del (args[myokit.Name('a')]) self.assertRaisesRegex(ValueError, 'Wrong number', f.convert, args) args[myokit.Name('c')] = myokit.Number(100) self.assertRaisesRegex(ValueError, 'Missing input argument', f.convert, args)
def test_remove_component(self): # Test the removal of a component. # Create model m = myokit.Model('LotkaVolterra') # Simplest case X = m.add_component('X') self.assertEqual(m.count_components(), 1) m.remove_component(X) self.assertEqual(m.count_components(), 0) self.assertRaises(KeyError, m.remove_component, X) # Test if orphaned self.assertIsNone(X.parent()) # Re-adding self.assertEqual(m.count_components(), 0) X = m.add_component('X') self.assertEqual(m.count_components(), 1) # With internal variables and string name a = X.add_variable('a') a.set_rhs(myokit.Number(4)) b = X.add_variable('b') b.set_rhs(myokit.Name(a)) m.remove_component('X') self.assertEqual(m.count_components(), 0) # With dependencies from another component X = m.add_component('X') a = X.add_variable('a') a.set_rhs(myokit.Number(45)) b = X.add_variable('b') b.set_rhs(myokit.Name(b)) Y = m.add_component('Y') c = Y.add_variable('c') c.set_rhs(myokit.Name(a)) d = Y.add_variable('d') d.set_rhs(myokit.Name(c)) self.assertEqual(m.count_components(), 2) self.assertRaises(myokit.IntegrityError, m.remove_component, X) self.assertEqual(m.count_components(), 2) # In the right order... m.remove_component(Y) self.assertEqual(m.count_components(), 1) m.remove_component(X) self.assertEqual(m.count_components(), 0)
def polynomial(self): """ Test of Polynomial class """ x = myokit.Name('x') c = [ myokit.Number(5), myokit.Number(4), myokit.Number(3), myokit.Number(2) ] p = myokit.Polynomial(x, *c) self.assertEqual(p.eval(subst={x: 0}), 5) self.assertEqual(p.eval(subst={x: 1}), 14) self.assertEqual(p.eval(subst={x: 2}), 41) self.assertEqual(p.eval(subst={x: -1}), 2) self.assertEqual(p.eval(subst={x: 0.5}), 8) q = p.tree() self.assertNotEqual(p, q) for i in [-1, 0, 0.5, 1, 2]: s = {x: i} self.assertEqual(p.eval(subst=s), q.eval(subst=s)) q = p.tree(horner=False) self.assertNotEqual(p, q) for i in [-1, 0, 0.5, 1, 2]: s = {x: i} self.assertEqual(p.eval(subst=s), q.eval(subst=s))
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_conditionals(self): # Tests if and piecewise writing a = myokit.Name('a') b = myokit.Number(1) cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<apply><gt/><cn>5.0</cn><cn>3.0</cn></apply>' c2 = '<apply><lt/><cn>2.0</cn><cn>1.0</cn></apply>' # If e = myokit.If(cond1, a, b) x = ( '<piecewise>' '<piece><ci>a</ci>' + c1 + '</piece>' '<otherwise><cn>1.0</cn></otherwise>' '</piecewise>' ) self.assertWrite(e, x) # Piecewise e = myokit.Piecewise(cond1, a, cond2, b, myokit.Number(100)) x = ( '<piecewise>' '<piece><ci>a</ci>' + c1 + '</piece>' '<piece><cn>1.0</cn>' + c2 + '</piece>' '<otherwise><cn>100.0</cn></otherwise>' '</piecewise>' ) self.assertWrite(e, x)
def test_inequalities(self): # Test parsing (in)equalities # Equal a = myokit.Name('a') b = myokit.Number(1.0) e = myokit.Equal(a, b) x = '<apply><eq/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e) # NotEqual e = myokit.NotEqual(a, b) x = '<apply><neq/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e) # More e = myokit.More(a, b) x = '<apply><gt/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e) # Less e = myokit.Less(a, b) x = '<apply><lt/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e) # MoreEqual e = myokit.MoreEqual(a, b) x = '<apply><geq/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e) # LessEqual e = myokit.LessEqual(a, b) x = '<apply><leq/><ci>a</ci><cn>1.0</cn></apply>' self.assertEqual(self.p(x), e)
def test_constants(self): # Tests parsing of MathML special constants. # Pi import math x = self.p('<pi/>') self.assertAlmostEqual(math.pi, float(x)) # Test e import math x = self.p('<exponentiale/>') self.assertAlmostEqual(math.e, float(x)) # Test booleans import math x = self.p('<true/>') self.assertEqual(float(x), 1) x = self.p('<false/>') self.assertEqual(float(x), 0) # Nan and inf x = self.p('<notanumber/>') self.assertTrue(math.isnan(float(x))) x = self.p('<infinity/>') self.assertEqual(float(x), float('inf')) # Test constants are handled via the number factory xml = '<pi/>' x = mathml.parse_mathml_etree( etree.fromstring(xml), lambda x, y: myokit.Name(x), lambda x, y: myokit.Number(x, myokit.units.volt), ) self.assertEqual(x.unit(), myokit.units.volt)
def test_name_and_numbers(self): # Test name and number writing self.assertWrite(myokit.Name('a'), '<ci>a</ci>') # Number without unit self.assertWrite(myokit.Number(0), '<cn>0.0</cn>') self.assertWrite(myokit.Number(1), '<cn>1.0</cn>') # Number with unit # Unit isn't exported by default! self.assertWrite(myokit.Number('-12', 'pF'), '<cn>-12.0</cn>') # Number with e notation (note that Python will turn e.g. 1e3 into # 1000, so must pick tests carefully) self.assertWrite(myokit.Number(1e3), '<cn>1000.0</cn>') self.assertWrite(myokit.Number(1e-3), '<cn>0.001</cn>') self.assertWrite( myokit.Number(1e-6), '<cn type="e-notation">1<sep/>-6</cn>') self.assertWrite( myokit.Number(2.3e24), '<cn type="e-notation">2.3<sep/>24</cn>') # myokit.float.str(1.23456789) = 1.23456788999999989e+00 self.assertWrite( myokit.Number(1.23456789), '<cn>1.23456788999999989</cn>')
def test_conditionals(self): # Tests if and piecewise writing a = myokit.Name('a') b = myokit.Number(1) c = myokit.Number(1) cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') ca = '<mi>a</mi>' cb = '<mn>1.0</mn>' cc = '<mn>1.0</mn>' c1 = '<mrow><mn>5.0</mn><mo>></mo><mn>3.0</mn></mrow>' c2 = '<mrow><mn>2.0</mn><mo><</mo><mn>1.0</mn></mrow>' # If x = myokit.If(cond1, a, b) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<otherwise>' + cb + '</otherwise>' '</piecewise>') # Piecewise x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<piece>' + cb + c2 + '</piece>' '<otherwise>' + cc + '</otherwise>' '</piecewise>')
def test_functions(self): # Test printing functions a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') ca = '<ci>a</ci>' cb = ('<cn cellml:units="picofarad">12.0</cn>') # Power x = myokit.Power(a, b) self.assertWrite(x, '<apply><power/>' + ca + cb + '</apply>') # Sqrt x = myokit.Sqrt(b) self.assertWrite(x, '<apply><root/>' + cb + '</apply>') # Exp x = myokit.Exp(a) self.assertWrite(x, '<apply><exp/>' + ca + '</apply>') # Floor x = myokit.Floor(b) self.assertWrite(x, '<apply><floor/>' + cb + '</apply>') # Ceil x = myokit.Ceil(b) self.assertWrite(x, '<apply><ceiling/>' + cb + '</apply>') # Abs x = myokit.Abs(b) self.assertWrite(x, '<apply><abs/>' + cb + '</apply>')
def test_inequalities(self): # Test writing (in)equalities a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') ca = '<mi>c.a</mi>' cb = '<mn>12.0</mn>' # Equal x = myokit.Equal(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>==</mo>' + cb + '</mrow>') # NotEqual x = myokit.NotEqual(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>!=</mo>' + cb + '</mrow>') # More x = myokit.More(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>></mo>' + cb + '</mrow>') # Less x = myokit.Less(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo><</mo>' + cb + '</mrow>') # MoreEqual # Named version ≥ is not output, shows decimal code instead x = myokit.MoreEqual(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>≥</mo>' + cb + '</mrow>') # LessEqual # Named version ≤ is not output, shows decimal code instead x = myokit.LessEqual(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>≤</mo>' + cb + '</mrow>')
def test_inequalities(self): # Tests printing inequalities a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') ca = '<ci>a</ci>' cb = ('<cn cellml:units="picofarad">12.0</cn>') # Equal x = myokit.Equal(a, b) self.assertWrite(x, '<apply><eq/>' + ca + cb + '</apply>') # NotEqual x = myokit.NotEqual(a, b) self.assertWrite(x, '<apply><neq/>' + ca + cb + '</apply>') # More x = myokit.More(a, b) self.assertWrite(x, '<apply><gt/>' + ca + cb + '</apply>') # Less x = myokit.Less(a, b) self.assertWrite(x, '<apply><lt/>' + ca + cb + '</apply>') # MoreEqual x = myokit.MoreEqual(a, b) self.assertWrite(x, '<apply><geq/>' + ca + cb + '</apply>') # LessEqual x = myokit.LessEqual(a, b) self.assertWrite(x, '<apply><leq/>' + ca + cb + '</apply>')
def test_arithmetic(self): # Test basic arithmetic a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') ca = '<ci>a</ci>' cb = ('<cn cellml:units="picofarad">12.0</cn>') # Prefix plus x = myokit.PrefixPlus(b) self.assertWrite(x, '<apply><plus/>' + cb + '</apply>') # Prefix minus x = myokit.PrefixMinus(b) self.assertWrite(x, '<apply><minus/>' + cb + '</apply>') # Plus x = myokit.Plus(a, b) self.assertWrite(x, '<apply><plus/>' + ca + cb + '</apply>') # Minus x = myokit.Minus(a, b) self.assertWrite(x, '<apply><minus/>' + ca + cb + '</apply>') # Multiply x = myokit.Multiply(a, b) self.assertWrite(x, '<apply><times/>' + ca + cb + '</apply>') # Divide x = myokit.Divide(a, b) self.assertWrite(x, '<apply><divide/>' + ca + cb + '</apply>')
def test_units(self): # Test writing of units u1 = myokit.parse_unit('kg*m^2/mole^3 (0.123)') m1 = cellml.Model('mmm') m1.add_units('flibbit', u1) m1.add_units('special_volt', myokit.units.Volt) d = m1.add_component('ddd') q = d.add_variable('q', 'flibbit') q.set_equation(myokit.Equation(myokit.Name(q), myokit.Number(2, u1))) xml = cellml.write_string(m1) m2 = cellml.parse_string(xml) q = m2['ddd']['q'] self.assertEqual(q.units().name(), 'flibbit') self.assertEqual(q.units().myokit_unit(), u1) self.assertEqual( m2.find_units('special_volt').myokit_unit(), myokit.units.volt) # Dimensionless units with a multiplier u1 = myokit.parse_unit('1 (0.123)') m1 = cellml.Model('mmm') m1.add_units('flibbit', u1) xml = cellml.write_string(m1) m2 = cellml.parse_string(xml) u2 = m2.find_units('flibbit') u2 = u2.myokit_unit() self.assertEqual(u1, u2)
def test_functions(self): # Tests writing basic functions a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') ca = '<mi>c.a</mi>' cb = '<mn>12.0</mn>' # Power x = myokit.Power(a, b) self.assertWrite(x, '<msup>' + ca + cb + '</msup>') # Sqrt x = myokit.Sqrt(b) self.assertWrite( x, '<mrow><mi>root</mi><mfenced>' + cb + '</mfenced></mrow>') # Exp x = myokit.Exp(a) self.assertWrite(x, '<msup><mi>e</mi>' + ca + '</msup>') # Log(a) x = myokit.Log(b) self.assertWrite( x, '<mrow><mi>ln</mi><mfenced>' + cb + '</mfenced></mrow>') # Log(a, b) x = myokit.Log(a, b) self.assertWrite( x, '<mrow><msub><mi>log</mi>' + cb + '</msub>' '<mfenced>' + ca + '</mfenced></mrow>') # Log10 x = myokit.Log10(b) self.assertWrite( x, '<mrow><mi>log</mi><mfenced>' + cb + '</mfenced></mrow>') # Floor x = myokit.Floor(b) self.assertWrite( x, '<mrow><mi>floor</mi><mfenced>' + cb + '</mfenced></mrow>') # Ceil x = myokit.Ceil(b) self.assertWrite( x, '<mrow><mi>ceiling</mi><mfenced>' + cb + '</mfenced></mrow>') # Abs x = myokit.Abs(b) self.assertWrite( x, '<mrow><mi>abs</mi><mfenced>' + cb + '</mfenced></mrow>') # Quotient x = myokit.Quotient(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>//</mo>' + cb + '</mrow>') # Remainder x = myokit.Remainder(a, b) self.assertWrite(x, '<mrow>' + ca + '<mo>%</mo>' + cb + '</mrow>')
def test_functions(self): # Tests writing basic functions # Power a = myokit.Name('a') b = myokit.Number(1) e = myokit.Power(a, b) x = '<apply><power/><ci>a</ci><cn>1.0</cn></apply>' self.assertWrite(e, x) # Sqrt e = myokit.Sqrt(b) x = '<apply><root/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Exp e = myokit.Exp(a) x = '<apply><exp/><ci>a</ci></apply>' self.assertWrite(e, x) # Log(a) e = myokit.Log(b) x = '<apply><ln/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Log(a, b) e = myokit.Log(a, b) x = '<apply><log/><logbase><cn>1.0</cn></logbase><ci>a</ci></apply>' self.assertWrite(e, x) # Log10 e = myokit.Log10(b) x = '<apply><log/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Floor e = myokit.Floor(b) x = '<apply><floor/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Ceil e = myokit.Ceil(b) x = '<apply><ceiling/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Abs e = myokit.Abs(b) x = '<apply><abs/><cn>1.0</cn></apply>' self.assertWrite(e, x) # Quotient e = myokit.Quotient(a, b) x = '<apply><quotient/><ci>a</ci><cn>1.0</cn></apply>' self.assertWrite(e, x) # Remainder e = myokit.Remainder(a, b) x = '<apply><rem/><ci>a</ci><cn>1.0</cn></apply>' self.assertWrite(e, x)
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 p(self, xml): """ Parses a MathML string and returns a myokit.Expression. """ return mathml.parse_mathml_etree( etree.fromstring(xml), lambda x, y: myokit.Name(x), lambda x, y: myokit.Number(x), )
def variable_factory(name, element): try: var = component.variable(name) except KeyError: raise CellMLParsingError( 'Variable references in equation must name a variable from' ' the local component (4.4.2.1).', element) return myokit.Name(var)
def test_piecewise_polynomial(self): """ Test piecewise polynomial """ # Set up test space x = np.linspace(-10, 10, 10000) # Test number one knots = [1, 2] coeff = [ [0.123, 0.456, 2.789, -0.123, -0.456], [5.4123, -0.1456, 7.789, -0.123, -0.456], [-40.6123, 0.2456, -0.86453, 0.23, -0.753], ] f = approx.PiecewisePolynomial(coeff, knots) g = f.myokit_form(myokit.Name('x')).pyfunc() if myotest.DEBUG: import matplotlib.pyplot as pl pl.figure() p0 = approx.Polynomial(coeff[0]) p1 = approx.Polynomial(coeff[1]) p2 = approx.Polynomial(coeff[2]) pl.plot(x, p0(x), label='p0') pl.plot(x, p1(x), label='p1') pl.plot(x, p2(x), label='p2') pl.plot(x, f(x), label='f') pl.plot(x, g(x), label='g') pl.legend(loc='lower left') pl.show() self.assertTrue(np.all(np.abs(f(x) - g(x)) < 1e-15)) # Test number two knots = [-5.0, 1.0, 3.123] coeff = [ [0.123, 0.456, 2.789, -0.123, -0.456, 0.0035], [5.4123, -0.1456, 7.789, -0.123, -0.456, 0.023], [-40.6123, 0.2456, -0.86453, 0.23, -0.753, 0.4262], [-20.4123, -2.0156, 1.79, -0.00642, -0.2632, -1.098], ] f = approx.PiecewisePolynomial(coeff, knots) g = f.myokit_form(myokit.Name('x')).pyfunc() self.assertTrue(np.all(np.abs(f(x) - g(x)) < 1e-15)) # Test cloning h = approx.PiecewisePolynomial(f) self.assertTrue(np.all(np.abs(f(x) - h(x)) < 1e-15))
def parse_mathml_string(s): """ Parses a MathML string that should contain a single expression. """ import xml.etree.ElementTree as etree p = MathMLParser( lambda x, y: myokit.Name(x), lambda x, y: myokit.Number(x), ) return p.parse(etree.fromstring(s))