コード例 #1
0
    def test_unresolved_references(self):
        """
        Test parsing models with unresolved references.
        """
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = 5
            """
        myokit.parse_model(m)

        # Bad variable in same component
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = 5
            y = z
            """
        self.assertRaises(myokit.ParseError, myokit.parse_model, m)

        # Bad component
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = 5
            y = d.z
            """
        self.assertRaises(myokit.ParseError, myokit.parse_model, m)

        # Bad variable in other component
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = 5
            y = d.b

            [d]
            a = 12
            """
        self.assertRaises(myokit.ParseError, myokit.parse_model, m)
コード例 #2
0
    def test_stimulus_current_1(self):
        # Test finding the stimulus current based on annotations

        m = myokit.parse_model("""
            [[model]]
            c.V = -80

            [c]
            time = 0 bind time
            pace = 0 bind pace
            dot(V) = 0.1
            i_stim = pace * 10 [pA]
                in [pA]
            d = 3 [m]
            """)

        # Annotated with stimulus_current: return regardless of other factors
        x = m.get('c.d')
        x.set_label('stimulus_current')
        self.assertEqual(guess.stimulus_current(m), x)
        x.set_label(None)
        x.set_label('stimulus_currents')
        self.assertNotEqual(guess.stimulus_current(m), x)

        # Alternatively, use oxmeta annotation
        x.meta['oxmeta'] = 'membrane_stimulus_current'
        self.assertEqual(guess.stimulus_current(m), x)
        del (x.meta['oxmeta'])
        self.assertNotEqual(guess.stimulus_current(m), x)
コード例 #3
0
    def test_membrane_potential_1(self):
        # Test finding the membrane potential based on annotations

        m = myokit.parse_model("""
            [[model]]
            membrane.V = -80

            [membrane]
            time = 0 bind time
            dot(V) = 1 [mV/ms]
                in [mV]

            [c]
            x = 5 in [A]
            """)

        # Annotated with membrane_potential: return regardless of other factors
        x = m.get('c.x')
        x.set_label('membrane_potential')
        self.assertEqual(guess.membrane_potential(m), x)
        x.set_label(None)
        x.set_label('membrane_potentials')
        self.assertNotEqual(guess.membrane_potential(m), x)

        # Alternatively, use oxmeta annotation
        x.meta['oxmeta'] = 'membrane_voltage'
        self.assertEqual(guess.membrane_potential(m), x)
        del (x.meta['oxmeta'])
        self.assertNotEqual(guess.membrane_potential(m), x)
コード例 #4
0
    def test_remove_nested(self):
        # Tests the method to remove nested variables

        m = myokit.parse_model("""
            [[model]]
            membrane.V = -80

            [membrane]
            t = 0 bind time
            dot(V) = 1 + x + y
                x = 1 + a + y + c
                    a = b
                        f = 9
                        b = 10 - f * g
                        g = 2
                    c = a + d
                    d = 4 * a
                y = 12
                in [mV]
                label membrane_potential
            """)
        m.validate()

        m2 = m.clone()
        v = m2.get('membrane.V')
        v.set_rhs(0)
        myokit.lib.guess._remove_nested(v)
        self.assertEqual(v.unit(), myokit.units.mV)
        self.assertEqual(len(v), 0)
コード例 #5
0
    def test_automatic_creation_with_v_independence(self):
        # Test with the v-independent states

        model = myokit.parse_model(MODEL)
        m = hh.HHModel.from_component(model.get('binding'))

        self.assertEqual(len(m.states()), 3)
コード例 #6
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)
コード例 #7
0
    def test_against_cvode_v_independent(self):

        # Test with v-independent states
        model = myokit.parse_model(MODEL)
        model.get('membrane.V').set_rhs(-80)
        model.get('membrane.V').demote()
        model.binding('pace').set_binding(None)
        model.get('membrane.V').set_binding('pace')

        # Create a protocol
        vs = [-30, -20, -10]
        p = myokit.pacing.steptrain(vsteps=vs,
                                    vhold=-120,
                                    tpre=8,
                                    tstep=2,
                                    tpost=0)
        t = p.characteristic_time()

        # Run an analytical simulation
        dt = 0.01
        m = hh.HHModel.from_component(model.get('binding'))
        s1 = hh.AnalyticalSimulation(m, p)
        d1 = s1.run(t, log_interval=dt).npview()

        s2 = myokit.Simulation(model, p)
        s2.set_tolerance(1e-8, 1e-8)
        d2 = s2.run(t, log_interval=dt).npview()

        # Test protocol output is the same
        e = np.abs(d1['membrane.V'] - d2['membrane.V'])
        self.assertEqual(np.max(e), 0)

        # Test current output is very similar
        e = np.abs(d1['binding.I'] - d2['binding.I'])
        self.assertLess(np.max(e), 2e-4)
コード例 #8
0
    def test_function_parsing(self):
        """
        Test parsing of functions.
        """
        # Test simple function
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = asin(sin(1))
            """
        m = myokit.parse_model(m)
        self.assertAlmostEqual(m.get('c.x').eval(), 1)

        # Test function with multiple arguments
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = log(8, 2)
            """
        m = myokit.parse_model(m)
        self.assertAlmostEqual(m.get('c.x').eval(), 3)

        # Unknown function
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = blog(8, 2)
            """
        self.assertRaisesRegex(myokit.ParseError, 'Unknown function',
                               myokit.parse_model, m)

        # Wrong number of arguments
        m = """
            [[model]]

            [c]
            t = 0 bind time
            x = sin(8, 2)
            """
        self.assertRaisesRegex(myokit.ParseError, 'Wrong number of arguments',
                               myokit.parse_model, m)
コード例 #9
0
    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
コード例 #10
0
    def test_convert_hh_states_to_inf_tau_form(self):
        # Tests conversion to inf-tau form
        m1 = myokit.parse_model(MODEL)
        self.assertTrue(hh.has_inf_tau_form(m1.get('ikr.a')))
        self.assertFalse(hh.has_inf_tau_form(m1.get('ikr.r')))

        # Rewrite model
        m2 = hh.convert_hh_states_to_inf_tau_form(m1)
        self.assertNotEqual(m1.code(), m2.code())
        self.assertTrue(hh.has_inf_tau_form(m1.get('ikr.a')))
        self.assertFalse(hh.has_inf_tau_form(m1.get('ikr.r')))
        self.assertTrue(hh.has_inf_tau_form(m2.get('ikr.a')))
        self.assertTrue(hh.has_inf_tau_form(m2.get('ikr.r')))

        # Test only r was affected
        self.assertEqual(m1.get('ikr.a').code(), m2.get('ikr.a').code())
        self.assertNotEqual(m1.get('ikr.r').code(), m2.get('ikr.r').code())

        # Test form
        self.assertEqual(m2.get('ikr.r').rhs().code(), '(inf - ikr.r) / tau')
        a = m2.get('ikr.r.alpha').eval()
        b = m2.get('ikr.r.beta').eval()
        inf = m2.get('ikr.r.inf').eval()
        tau = m2.get('ikr.r.tau').eval()
        self.assertAlmostEqual(inf, a / (a + b))
        self.assertAlmostEqual(tau, 1 / (a + b))

        # Test state values are similar
        self.assertAlmostEqual(m1.get('ikr.r').eval(), m2.get('ikr.r').eval())

        # Second rewrite isn't necessary
        m3 = hh.convert_hh_states_to_inf_tau_form(m2)
        self.assertEqual(m2.code(), m3.code())

        # First argument must be a myokit model
        self.assertRaisesRegex(ValueError, 'must be a myokit.Model',
                               hh.convert_hh_states_to_inf_tau_form, [])

        # Membrane potential given explicitly (not as label)
        m2 = m1.clone()
        v = m2.get('membrane.V')
        v.set_label(None)
        m3 = hh.convert_hh_states_to_inf_tau_form(m2, v)
        self.assertNotEqual(m2.code(), m3.code())
        # Note: the next methods are called with v from m2, not v from m3! But
        # this should still work as variables are .get() from the model.
        self.assertTrue(hh.has_inf_tau_form(m3.get('ikr.a'), v))
        self.assertTrue(hh.has_inf_tau_form(m3.get('ikr.r'), v))

        # Unknown membrane potential
        self.assertRaisesRegex(ValueError, 'Membrane potential must be given',
                               hh.convert_hh_states_to_inf_tau_form, m2)
コード例 #11
0
ファイル: test_model.py プロジェクト: darmis007/myokit
    def test_item_at_text_position(self):
        # Test :meth:`Model.item_at_text_position()`.

        text = [
            '[[model]]',  # 1
            'c.x = 0',  # 2
            '',  # 3
            '[e]',  # 4
            't = 0 bind time',
            '',
            '[c]',
            'desc: This is a test component',
            'dot(x) = (10 - x) / y',
            'y = 5 + y1',
            '    y1 = 3',
            ''
        ]
        model = myokit.parse_model(text)
        e = model.get('e')
        t = model.get('e.t')
        c = model.get('c')
        x = model.get('c.x')
        y = model.get('c.y')
        y1 = model.get('c.y.y1')

        def check(line, char, var):
            tv = model.item_at_text_position(line, char)
            if var is None:
                self.assertIsNone(tv)
            else:
                token, var2 = tv
                self.assertIsNotNone(var2)
                self.assertEqual(var.qname(), var2.qname())

        # It doesn't work on initial conditions
        check(1, 0, None)
        check(1, 1, None)
        check(1, 2, None)

        # Find the component e and its variable
        check(4, 0, None)
        check(4, 1, e)
        check(4, 2, None)
        check(5, 0, t)
        check(5, 1, None)

        # Find the component c and its variables
        check(7, 1, c)
        check(9, 4, x)
        check(10, 0, y)
        check(11, 4, y1)
コード例 #12
0
    def test_stimulus_current_info_duration(self):
        # Tests guessing of stimulus duration

        m = myokit.parse_model("""
            [[model]]
            [c]
            t = 0 [s] bind time
                in [s]
            i_stim = if((t - s) % p < d, a, 0 [pA])
                in [pA]
            s = 10 [s] in [s]
                oxmeta: membrane_stimulus_current_offset
            p = 1000 [s] in [s]
                oxmeta: membrane_stimulus_current_period
            d = 0.5 [s] in [s]
            a = 5 [pA] in [pA]
                oxmeta: membrane_stimulus_current_amplitude
            """)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['current'], m.get('c.i_stim'))

        # Note: Having labels above allows the method to exit early. We can't
        # test this mini-optimisation, but it does show up in coverage

        # Guess from name + (correct unit or None)
        v = m.get('c.d')
        self.assertIsNone(i['duration'], v)
        v.rename('durandurations')
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['duration'], v)
        v.set_unit(None)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['duration'], v)
        v.set_unit('s^2')
        i = guess.stimulus_current_info(m)
        self.assertIsNone(i['duration'], v)
        v.set_unit('1')
        i = guess.stimulus_current_info(m)
        self.assertIsNone(i['duration'], v)

        # Can't already be used
        v.set_unit(None)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['duration'], v)
        m.get('c.s').meta['oxmeta'] = 'hello'
        v.meta['oxmeta'] = 'membrane_stimulus_current_offset'
        i = guess.stimulus_current_info(m)
        self.assertNotEqual(i['duration'], v)
コード例 #13
0
ファイル: test_meta.py プロジェクト: darmis007/myokit
    def test_parser(self):
        """
        Test basic meta-data parsing
        """
        # Parse simple model without meta data
        lines = [
            '[[model]]',
            'a.x = 0',
            '[a]',
            't = 0 bind time',
            'dot(x) = 4',
        ]
        m = myokit.parse_model('\n'.join(lines))
        self.assertTrue(m.is_valid())

        # Test simple meta data
        def model(key, value):
            x = list(lines)
            x.insert(1, key + ':' + value)
            m = myokit.parse_model('\n'.join(x))
            self.assertTrue(m.is_valid())
            self.assertEqual(m.meta[key], value)

        def component(key, value):
            m = myokit.parse_model('\n'.join(lines + [key + ':' + value]))
            self.assertTrue(m.is_valid())
            self.assertEqual(m.get('a').meta[key], value)

        def variable(key, value):
            m = myokit.parse_model('\n'.join(lines +
                                             ['    ' + key + ':' + value]))
            self.assertTrue(m.is_valid())
            self.assertEqual(m.get('a.x').meta[key], value)

        def test(key, value):
            model(key, value)
            component(key, value)
            variable(key, value)

        test('vic', 'bob')
        # Test empty property
        test('vic', '')
        # Test namespaced keys
        test('vic:bob', 'uvavu')
        test('vic:bob:eranu', 'uvavu')
        # Test invalid keys
        self.assertRaises(myokit.ParseError, test, 'vic.bob', 'uvavu')
コード例 #14
0
    def test_stimulus_current_3(self):
        # Test finding the stimulus current if it's a constant

        # Find variable furthest from time / pace (in A)
        m = myokit.parse_model("""
            [[model]]

            [t]
            time = 0 bind time
                in [s]
            i_stim = 5 [A]
                in [A]
            i_steam = 4 [A]
                in [A]
            """)

        # Correct name and unit
        i = m.get('t.i_stim')
        self.assertEqual(guess.stimulus_current(m), i)

        # Unit wrong or name wrong: don't return
        i.set_unit('m')
        self.assertIsNone(guess.stimulus_current(m))

        # Other allowed units
        i.set_unit('pA')
        self.assertEqual(guess.stimulus_current(m), i)
        i.set_unit('A/kF')
        self.assertEqual(guess.stimulus_current(m), i)
        i.set_unit('A/hm^2')
        self.assertEqual(guess.stimulus_current(m), i)
        i.set_unit(None)
        self.assertEqual(guess.stimulus_current(m), i)
        i.set_unit('mV')
        self.assertIsNone(guess.stimulus_current(m))

        # Other allowed names
        i.set_unit('pA')
        self.assertEqual(guess.stimulus_current(m), i)
        i.rename('istim')
        self.assertEqual(guess.stimulus_current(m), i)
        i.rename('ist')
        self.assertEqual(guess.stimulus_current(m), i)
        i.rename('i_st')
        self.assertEqual(guess.stimulus_current(m), i)
        i.rename('ii_st')
        self.assertIsNone(guess.stimulus_current(m))
コード例 #15
0
    def test_manual_creation_with_v_independence(self):
        # Test with the v-independent states

        # Load model
        model = myokit.parse_model(MODEL)

        # Select a number of states and parameters
        states = ['binding.act', 'binding.rec', 'binding.b']
        parameters = ['binding.kon', 'binding.koff']

        # Create a HH model
        m = hh.HHModel(model, states, parameters)

        # Also select a current
        current = 'binding.I'
        m = hh.HHModel(model, states, parameters, current)

        # Test steady-state calculation doesn't fail
        m.steady_state(-80)
コード例 #16
0
    def test_stimulus_current_info_period_duration_offset(self):
        # Tests what happens when a single variable matches multiple words

        # In this model, amplitude should be x, and at most 2 variables out of
        # duration, period, and offset can be set.
        m = myokit.parse_model("""
            [[model]]
            [c]
            t = 0 [s] bind time
                in [s]
            i_stim = if((t - x) % perioddurationoffset < x, 1, 0)
            x = 5
            perioddurationoffset = 2
                in [s]
            """)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['current'], m.get('c.i_stim'))
        self.assertEqual(i['amplitude'], m.get('c.x'))
        self.assertIsNone(i['amplitude_expression'])
        empties = [x for x in i.values() if x is None]
        self.assertEqual(len(empties), 3)

        # Don't match period
        x = m.get('c.perioddurationoffset')
        x.rename('durationoffset')
        i = guess.stimulus_current_info(m)
        empties = [k for k, v in i.items() if v is None]
        self.assertEqual(len(empties), 3)
        self.assertIn('period', empties)

        # Don't match duration
        x.rename('periodnoffset')
        i = guess.stimulus_current_info(m)
        empties = [k for k, v in i.items() if v is None]
        self.assertEqual(len(empties), 3)
        self.assertIn('duration', empties)

        # Don't match offset
        x.rename('durationperiod')
        i = guess.stimulus_current_info(m)
        empties = [k for k, v in i.items() if v is None]
        self.assertEqual(len(empties), 3)
        self.assertIn('offset', empties)
コード例 #17
0
    def test_deep_deps(self):
        # Tests the (hidden) method to find all dependencies of a particular
        # variable.

        m = myokit.parse_model("""
            [[model]]
            c.v = -80

            [c]
            time = 0 bind time
            dot(v) = -i_ion
            i_ion = i1 + i2
            i1 = 5 * v
            i2 = x * v
                x = 13 / time
            z = 2 + y
            y = 3
            """)

        # Simple cases
        y, z = m.get('c.y'), m.get('c.z')
        d = guess._deep_deps(y)
        self.assertEqual(len(d), 0)
        d = guess._deep_deps(z)
        self.assertEqual(d[y], 1)
        self.assertEqual(len(d), 1)

        # Harder cases
        v, time, i_ion = m.get('c.v'), m.get('c.time'), m.get('c.i_ion')
        i1, i2, i2x = m.get('c.i1'), m.get('c.i2'), m.get('c.i2.x')
        d = guess._deep_deps(i2)
        self.assertEqual(d[i2x], 1)
        self.assertEqual(d[time], 2)
        self.assertEqual(len(d), 2)

        d = guess._deep_deps(v)
        self.assertEqual(d[i_ion], 1)
        self.assertEqual(d[i1], 2)
        self.assertEqual(d[i2], 2)
        self.assertEqual(d[i2x], 3)
        self.assertEqual(d[time], 4)
        self.assertEqual(len(d), 5)
コード例 #18
0
    def test_stimulus_current_info_offset(self):
        # Tests guessing of stimulus offset

        m = myokit.parse_model("""
            [[model]]
            [c]
            t = 0 [s] bind time
                in [s]
            i_stim = if((t - s) % p < d, a, 0 [pA])
                in [pA]
            s = 10 [s] in [s]
            p = 1000 [s] in [s]
            d = 0.5 [s] in [s]
            a = 5 [pA] in [pA]
            """)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['current'], m.get('c.i_stim'))

        # Guess from name + (correct unit or None)
        v = m.get('c.d')
        self.assertIsNone(i['offset'], v)
        v.rename('foffsetti')
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['offset'], v)
        v.set_unit(None)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['offset'], v)
        v.set_unit('s^2')
        i = guess.stimulus_current_info(m)
        self.assertIsNone(i['offset'], v)
        v.set_unit('1')
        i = guess.stimulus_current_info(m)
        self.assertIsNone(i['offset'], v)

        # Can't already be used
        v.set_unit(None)
        i = guess.stimulus_current_info(m)
        self.assertEqual(i['offset'], v)
        v.meta['oxmeta'] = 'membrane_stimulus_current_period'
        i = guess.stimulus_current_info(m)
        self.assertNotEqual(i['offset'], v)
コード例 #19
0
    def test_rush_larsen_conversion(self):
        # Tests methods for writing RL state updates
        m1 = myokit.parse_model(MODEL)
        m2 = hh.convert_hh_states_to_inf_tau_form(m1)

        # Test RL update method
        dt = myokit.Name('dt')
        rl = hh.get_rl_expression(m2.get('ikr.a'), dt)
        self.assertEqual(rl.code(),
                         'inf + (ikr.a - inf) * exp(-(str:dt / tau))')
        rl = hh.get_rl_expression(m2.get('ikr.r'), dt)
        self.assertEqual(rl.code(),
                         'inf + (ikr.r - inf) * exp(-(str:dt / tau))')

        # Test RL update is close to Euler for small dt
        m2.get('membrane.V').set_rhs(20)
        ikr = m2.get('ikr')
        dt = ikr.add_variable('dt')
        dt.set_rhs(1e-6)
        # Test for a
        a = m2.get('ikr.a')
        rl = hh.get_rl_expression(a, myokit.Name(dt))
        a1 = rl.eval()
        a2 = a.state_value() + dt.eval() * a.rhs().eval()
        self.assertAlmostEqual(a1, a2)
        # And for r
        r = m2.get('ikr.r')
        rl = hh.get_rl_expression(r, myokit.Name(dt))
        r1 = rl.eval()
        r2 = r.state_value() + dt.eval() * r.rhs().eval()
        self.assertAlmostEqual(r1, r2)

        # Dt must be an expression
        self.assertRaisesRegex(ValueError, 'must be a myokit.Expression',
                               hh.get_rl_expression, a, 'dt')

        # Returns None if not in inf-tau form
        self.assertIsNone(
            hh.get_rl_expression(m1.get('ikr.r'), myokit.Name(dt)))
コード例 #20
0
    def test_sensitivites_initial(self):
        # Test setting initial sensitivity values.

        m = myokit.parse_model('''
            [[model]]
            e.y = 2.3

            [e]
            t = 0 bind time
            p = 1 / 100
            dot(y) = 2 * p - y
            ''')
        m.validate()

        #TODO: Test results
        s = myokit.Simulation(m, sensitivities=(['e.y'], ['e.p', 'init(e.y)']))

        # Test bad initial matrix
        self.assertRaisesRegex(ValueError,
                               'None or a list',
                               s.run,
                               10,
                               sensitivities='hello')
コード例 #21
0
    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())
コード例 #22
0
    def test_sensitivity_ordering(self):
        # Tests that sensitivities are returned in the correct order

        # Define model
        model = myokit.parse_model("""
            [[model]]
            name: one_compartment_pk_model
            # Initial values
            central.drug_amount = 0.1
            dose.drug_amount    = 0.1

            [central]
            dose_rate = 0 bind pace
                in [g/s (1.1574074074074077e-08)]
            dot(drug_amount) = -(
                    size * e.elimination_rate * drug_concentration) + (
                    dose.absorption_rate * dose.drug_amount)
                in [kg (1e-06)]
            drug_concentration = drug_amount / size
                in [g/m^3]
            size = 0.1
                in [L]

            [dose]
            absorption_rate = 0.1
                in [S/F (1.1574074074074077e-05)]
            dot(drug_amount) = (-absorption_rate * drug_amount
                                + central.dose_rate)
                in [kg (1e-06)]

            [e]
            elimination_rate = 0.1
                in [S/F (1.1574074074074077e-05)]
            time = 0 bind time
                in [s (86400)]
            """)

        # Select all states and possible independents
        var = ['central.drug_amount', 'dose.drug_amount']
        par = [
            'central.size',
            'init(central.drug_amount)',
            'dose.absorption_rate',
            'init(dose.drug_amount)',
            'e.elimination_rate',
        ]

        # Run and store
        sim = myokit.Simulation(model, sensitivities=(var, par))
        _, s1 = sim.run(6, log=myokit.LOG_NONE, log_interval=2)
        s1 = np.array(s1)

        # Now use reverse order
        var.reverse()
        par.reverse()

        # Run and store
        sim = myokit.Simulation(model, sensitivities=(var, par))
        _, s2 = sim.run(6, log=myokit.LOG_NONE, log_interval=2)
        s2 = np.array(s2)

        # Reverse results, to get back original order
        s2 = s2[:, ::-1, ::-1]
        self.assertTrue(np.all(s1 == s2))
コード例 #23
0
ファイル: test_model.py プロジェクト: darmis007/myokit
    def test_remove_derivative_references(self):
        # Test the remove_derivative_references() method.

        m0 = myokit.parse_model("""
            [[model]]
            c.x = 0
            c.y = 1

            [e]
            t = 0 bind time

            [c]
            dot(x) = (1 - x) * alpha
                alpha = 3 * beta + dot_x
                beta = exp(-y) + cc
                    cc = 1.23
                dot_x = 3
            dot(y) = (12 - y) / 7
            z = 3 * dot(y)

            [d]
            z = 3 * dot(c.x) / dot(c.y)
            """)
        m2 = myokit.parse_model("""
            [[model]]
            c.x = 0
            c.y = 1

            [e]
            t = 0 bind time

            [c]
            dot(x) = dot_x_1
            dot_x_1 = (1 - x) * alpha
                alpha = 3 * beta + dot_x
                beta = exp(-y) + cc
                    cc = 1.23
                dot_x = 3
            dot(y) = dot_y
            dot_y = (12 - y) / 7
            z = 3 * dot_y

            [d]
            z = 3 * c.dot_x_1 / c.dot_y
            """)

        # Remove derivatives from m1
        m1 = m0.clone()
        m1.remove_derivative_references()

        # Assert model matches expected code
        self.assertEqual(m1.code(), m2.code())

        # Assert models both produce the same derivatives
        dy1 = m1.eval_state_derivatives()
        dy2 = m2.eval_state_derivatives()
        self.assertEqual(dy1, dy2)

        # Test time unit is None
        self.assertIsNone(m1.get('c.dot_y').unit())

        # Only one unit set? Then unit is still None
        m1 = m0.clone()
        m1.get('c.y').set_unit('mV')
        m1.remove_derivative_references()
        self.assertIsNone(m1.get('c.dot_y').unit())

        m1 = m0.clone()
        m1.get('e.t').set_unit('ms')
        m1.remove_derivative_references()
        self.assertIsNone(m1.get('c.dot_y').unit())

        # Both units set? Then unit is division of two
        m1 = m0.clone()
        m1.get('e.t').set_unit('ms')
        m1.get('c.y').set_unit('mV')
        m1.remove_derivative_references()
        self.assertEqual(m1.get('c.dot_y').unit(), myokit.parse_unit('mV/ms'))
コード例 #24
0
    def test_sensitivities_with_derivatives(self):
        # Test various inputs to the `sensitivities` argument are handled
        # correctly, including sensitivites of derivatives and intermediary
        # variables depending on derivatives.

        # Note: passing the wrong values into the sensitivities constructor arg
        # is tested in the CModel tests.

        m = myokit.parse_model('''
            [[model]]
            e.x = 1.2
            e.y = 2.3

            [e]
            t = 0 bind time
            p = 1 / 100
            q = 2
            r = 3
            dot(x) = p * q
            dot(y) = 2 * p - y
            fx = x^2
            fy = r + p^2 + dot(y)
            ''')
        m.validate()

        x0 = m.get('e.x').state_value()
        y0 = m.get('e.y').state_value()
        p = m.get('e.p').eval()
        q = m.get('e.q').eval()
        r = m.get('e.r').eval()

        # Dependents is a list of y in dy/dx.
        # Must refer to state, derivative, or intermediary, given as:
        #  - Variable
        #  - Name
        #  - Derivative
        #  - "qname"
        #  - "dot(qname)"
        dependents = [
            'e.x',  # qname
            'e.y',  # qname
            'dot(e.x)',  # dot(qname)
            m.get('e.y').lhs(),  # Derivative
            m.get('e.fx'),  # Variable
            m.get('e.fy').lhs(),  # Name
        ]

        # Independents is a list of x in dy/dx
        # Must refer to literals or initial values, given as:
        #  - Variable
        #  - Name
        #  - InitialValue
        #  - "qname"
        #  - "init(qname)"
        independents = [
            'e.p',  # qname
            m.get('e.q'),  # qname
            m.get('e.r').lhs(),  # Name
            'init(e.x)',  # init(qname)
            myokit.InitialValue(myokit.Name(m.get('e.y'))),  # InitialValue
        ]

        # Run, get output
        s = myokit.Simulation(m, sensitivities=(dependents, independents))
        s.set_tolerance(1e-9, 1e-9)
        d, e = s.run(8)
        d, e = d.npview(), np.array(e)
        t = d.time()

        # Check solution
        self.assertTrue(np.allclose(d['e.x'], x0 + p * q * t))
        self.assertTrue(
            np.allclose(d['e.y'], 2 * p + (y0 - 2 * p) * np.exp(-t)))
        self.assertTrue(
            np.allclose(d['e.fx'],
                        (p * q * t)**2 + 2 * p * q * t * x0 + x0**2))
        self.assertTrue(
            np.allclose(d['e.fy'], r + p**2 + (2 * p - y0) * np.exp(-t)))
        self.assertTrue(np.allclose(d['dot(e.x)'], p * q))
        self.assertTrue(np.allclose(d['dot(e.y)'], (2 * p - y0) * np.exp(-t)))

        # Sensitivities of  x  to (p, q, r, x0, y0)
        self.assertTrue(np.allclose(e[:, 0, 0], q * t))
        self.assertTrue(np.allclose(e[:, 0, 1], p * t))
        self.assertTrue(np.allclose(e[:, 0, 2], 0))
        self.assertTrue(np.allclose(e[:, 0, 3], 1))
        self.assertTrue(np.allclose(e[:, 0, 4], 0))

        # Sensitivities of  y  to (p, q, r, x0, y0)
        self.assertTrue(np.allclose(e[:, 1, 0], 2 - 2 * np.exp(-t)))
        self.assertTrue(np.allclose(e[:, 1, 1], 0))
        self.assertTrue(np.allclose(e[:, 1, 2], 0))
        self.assertTrue(np.allclose(e[:, 1, 3], 0))
        self.assertTrue(np.allclose(e[:, 1, 4], np.exp(-t)))

        # Sensitivities of  dot(x)  to (p, q, r, x0, y0)
        self.assertTrue(np.allclose(e[:, 2, 0], q))
        self.assertTrue(np.allclose(e[:, 2, 1], p))
        self.assertTrue(np.allclose(e[:, 2, 2], 0))
        self.assertTrue(np.allclose(e[:, 2, 3], 0))
        self.assertTrue(np.allclose(e[:, 2, 4], 0))

        # Sensitivities of  dot(y)  to (p, q, r, x0, y0)
        self.assertTrue(np.allclose(e[:, 3, 0], 2 * np.exp(-t)))
        self.assertTrue(np.allclose(e[:, 3, 1], 0))
        self.assertTrue(np.allclose(e[:, 3, 2], 0))
        self.assertTrue(np.allclose(e[:, 3, 3], 0))
        self.assertTrue(np.allclose(e[:, 3, 4], -np.exp(-t)))

        # Sensitivities of  fx  to (p, q, r, x0, y0)
        self.assertTrue(
            np.allclose(e[:, 4, 0], 2 * p * (q * t)**2 + 2 * q * t * x0))
        self.assertTrue(
            np.allclose(e[:, 4, 1], 2 * q * (p * t)**2 + 2 * p * t * x0))
        self.assertTrue(np.allclose(e[:, 4, 2], 0))
        self.assertTrue(np.allclose(e[:, 4, 3], 2 * p * q * t + 2 * x0))
        self.assertTrue(np.allclose(e[:, 4, 4], 0))

        # Sensitivities of  fy  to (p, q, r, x0, y0)
        self.assertTrue(np.allclose(e[:, 5, 0], 2 * p + 2 * np.exp(-t)))
        self.assertTrue(np.allclose(e[:, 5, 1], 0))
        self.assertTrue(np.allclose(e[:, 5, 2], 1))
        self.assertTrue(np.allclose(e[:, 5, 3], 0))
        self.assertTrue(np.allclose(e[:, 5, 4], -np.exp(-t)))
コード例 #25
0
ファイル: test_model.py プロジェクト: darmis007/myokit
    def test_check_units(self):
        # Test the ``model.check_units`` method.

        model = myokit.Model('m')
        component = model.add_component('c')
        t = component.add_variable('time')
        t.set_binding('time')

        # Check units before any rhs or units set
        s = myokit.UNIT_STRICT
        self.assertRaisesRegex(myokit.IntegrityError, 'No RHS set',
                               model.check_units)
        self.assertRaisesRegex(myokit.IntegrityError, 'No RHS set',
                               model.check_units, s)

        # Check units before any rhs set
        t.set_unit('s')
        self.assertRaisesRegex(myokit.IntegrityError, 'No RHS set',
                               model.check_units)
        self.assertRaisesRegex(myokit.IntegrityError, 'No RHS set',
                               model.check_units, s)

        # Check mini model with rhs and units, no states
        t.set_rhs('0 [s]')
        a = component.add_variable('a')
        a.set_rhs(1)
        model.check_units()
        model.check_units(s)

        # Check mini model with a state
        # Strict check should fail: a's RHS should be in 1/s
        a.promote(0)
        model.check_units()
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units, s)
        a.set_rhs('1 [1/s]')
        model.check_units(s)

        b = component.add_variable('b')
        b.set_rhs(2)
        c = component.add_variable('c')
        c.set_rhs('2 * b')
        model.check_units()
        model.check_units(s)

        a.set_rhs('1 [N/s]')
        b.set_rhs('2 [m]')
        c.set_rhs('a * b')

        # No variable units set
        model.check_units()
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units, s)

        # Variable unit set for state
        a.set_unit('N')  # So rhs should be N/s
        b.set_unit('m')
        model.check_units()
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units, s)

        # Bad derived unit
        c.set_unit('A')
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units)
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units, s)

        c.set_unit(myokit.parse_unit('N*m'))
        model.check_units()
        model.check_units(s)

        # References use variable unit, not RHS unit!
        model = myokit.Model('m')
        component = model.add_component('c')
        x = component.add_variable('x')
        y = component.add_variable('y')
        x.set_unit(None)
        y.set_unit(None)
        x.set_rhs('5 [mV]')
        y.set_rhs('3 [A] + x')  # x unit is unspecified, not mV!
        model.check_units()
        self.assertRaises(myokit.IncompatibleUnitError, model.check_units, s)

        # Tokens are used in IncompatibleUnitError messages
        m = myokit.parse_model('\n'.join([
            '[[model]]',
            '[a]',
            't = 0 [ms] bind time',
        ]))
        try:
            m.check_units(s)
        except myokit.IncompatibleUnitError as e:
            self.assertIn('on line 3', str(e))
            token = e.token()
            self.assertIsNotNone(token)
            self.assertEqual(token[2], 3)
            self.assertEqual(token[3], 0)

        # Test comparison with floating point issues
        m = myokit.parse_model('\n'.join([
            '[[model]]',
            '[a]',
            'x = 1 [cm^3] bind time',
            '    in [cm^3]',
            'y = 2 [day]',
            '    in [day]',
            'z = 3 [day^3]',
            '    in [day^3]',
            'a = (x / y / y / y) * z',
            '    in [cm^3]',
        ]))
        m.check_units(s)
コード例 #26
0
    def test_inf_tau_form(self):
        # Test methods for working with inf-tau form
        m = myokit.parse_model(MODEL)
        self.assertIsInstance(m, myokit.Model)
        v = m.get('membrane.V')
        a = m.get('ikr.a')
        r = m.get('ikr.r')

        # Test with v detected from label
        self.assertTrue(hh.has_inf_tau_form(a))
        inf, tau = hh.get_inf_and_tau(a)
        self.assertEqual(inf, m.get('ikr.a.inf'))
        self.assertEqual(tau, m.get('ikr.a.tau'))
        self.assertFalse(hh.has_inf_tau_form(r))
        self.assertIsNone(hh.get_inf_and_tau(r))

        # Test with v argument, no label
        v.set_label(None)
        self.assertRaisesRegex(ValueError, 'Membrane potential must be given',
                               hh.has_inf_tau_form, a)
        self.assertTrue(hh.has_inf_tau_form(a, v))
        inf, tau = hh.get_inf_and_tau(a, v)
        self.assertEqual(inf, m.get('ikr.a.inf'))
        self.assertEqual(tau, m.get('ikr.a.tau'))
        self.assertFalse(hh.has_inf_tau_form(r, v))
        self.assertIsNone(hh.get_inf_and_tau(r, v))

        # Test with v as a constant
        v.demote()
        v.set_rhs(-80)
        self.assertTrue(hh.has_inf_tau_form(a, v))
        inf, tau = hh.get_inf_and_tau(a, v)
        self.assertEqual(inf, m.get('ikr.a.inf'))
        self.assertEqual(tau, m.get('ikr.a.tau'))
        self.assertFalse(hh.has_inf_tau_form(r, v))
        self.assertIsNone(hh.get_inf_and_tau(r, v))
        del (r)

        # a is not a state
        self.assertTrue(hh.has_inf_tau_form(a, v))
        a.demote()
        self.assertFalse(hh.has_inf_tau_form(a, v))
        a.promote(0)
        self.assertTrue(hh.has_inf_tau_form(a, v))

        # Almost correct forms / different ways to fail
        def bad(e):
            a.set_rhs(e)
            self.assertFalse(hh.has_inf_tau_form(a, v))
            a.set_rhs('(inf - a) / tau')
            self.assertTrue(hh.has_inf_tau_form(a, v))

        def good(e):
            a.set_rhs(e)
            self.assertTrue(hh.has_inf_tau_form(a, v))

        bad('(inf - a) / (1 + tau)')
        bad('(inf + a) / tau')
        bad('(inf - 1) / tau')
        bad('(1 - inf) / tau')
        bad('(inf - r) / tau')

        # Inf and tau can't be states
        m.get('ikr.a').move_variable(m.get('ikr.a.inf'), m.get('ikr'), 'ainf')
        m.get('ikr.a').move_variable(m.get('ikr.a.tau'), m.get('ikr'), 'atau')
        self.assertTrue(hh.has_inf_tau_form(a, v))
        m.get('ikr.ainf').promote(1)
        self.assertFalse(hh.has_inf_tau_form(a, v))
        m.get('ikr.ainf').demote()
        self.assertTrue(hh.has_inf_tau_form(a, v))
        m.get('ikr.atau').promote(1)
        self.assertFalse(hh.has_inf_tau_form(a, v))
        m.get('ikr.atau').demote()
        self.assertTrue(hh.has_inf_tau_form(a, v))

        # Inf and tau can't depend on other states than v
        c = m.add_component('ccc')
        x = c.add_variable('vvv')
        x.set_rhs(1)
        x.promote(0)
        ainf = m.get('ikr.ainf').rhs()
        m.get('ikr.ainf').set_rhs('2 + ccc.vvv * V')
        self.assertFalse(hh.has_inf_tau_form(a, v))
        m.get('ikr.ainf').set_rhs(ainf)
        self.assertTrue(hh.has_inf_tau_form(a, v))
        atau = m.get('ikr.atau').rhs()
        m.get('ikr.atau').set_rhs('3 * ccc.vvv * V')
        self.assertFalse(hh.has_inf_tau_form(a, v))
        m.get('ikr.atau').set_rhs(atau)
        self.assertTrue(hh.has_inf_tau_form(a, v))
コード例 #27
0
ファイル: test_meta.py プロジェクト: darmis007/myokit
 def variable(key, value):
     m = myokit.parse_model('\n'.join(lines +
                                      ['    ' + key + ':' + value]))
     self.assertTrue(m.is_valid())
     self.assertEqual(m.get('a.x').meta[key], value)
コード例 #28
0
ファイル: test_meta.py プロジェクト: darmis007/myokit
 def component(key, value):
     m = myokit.parse_model('\n'.join(lines + [key + ':' + value]))
     self.assertTrue(m.is_valid())
     self.assertEqual(m.get('a').meta[key], value)
コード例 #29
0
ファイル: test_meta.py プロジェクト: darmis007/myokit
 def model(key, value):
     x = list(lines)
     x.insert(1, key + ':' + value)
     m = myokit.parse_model('\n'.join(x))
     self.assertTrue(m.is_valid())
     self.assertEqual(m.meta[key], value)
コード例 #30
0
    def test_alpha_beta_form(self):
        # Test methods for working with alpha-beta form
        m = myokit.parse_model(MODEL)
        self.assertIsInstance(m, myokit.Model)
        v = m.get('membrane.V')
        a = m.get('ikr.a')
        r = m.get('ikr.r')

        # Test without v (detected from label)
        self.assertTrue(hh.has_alpha_beta_form(r))
        alph, beta = hh.get_alpha_and_beta(r)
        self.assertEqual(alph, m.get('ikr.r.alpha'))
        self.assertEqual(beta, m.get('ikr.r.beta'))
        self.assertFalse(hh.has_alpha_beta_form(a))
        self.assertIsNone(hh.get_alpha_and_beta(a))

        # Test with v as a state, without a label
        v.set_label(None)
        self.assertRaisesRegex(ValueError, 'Membrane potential must be given',
                               hh.has_alpha_beta_form, r)
        self.assertTrue(hh.has_alpha_beta_form(r, v))
        alph, beta = hh.get_alpha_and_beta(r, v)
        self.assertEqual(alph, m.get('ikr.r.alpha'))
        self.assertEqual(beta, m.get('ikr.r.beta'))
        self.assertFalse(hh.has_alpha_beta_form(a, v))
        self.assertIsNone(hh.get_alpha_and_beta(a, v))

        # Test with v as a constant
        v.demote()
        v.set_rhs(-80)
        self.assertTrue(hh.has_alpha_beta_form(r, v))
        alph, beta = hh.get_alpha_and_beta(r, v)
        self.assertEqual(alph, m.get('ikr.r.alpha'))
        self.assertEqual(beta, m.get('ikr.r.beta'))
        self.assertFalse(hh.has_alpha_beta_form(a, v))
        self.assertIsNone(hh.get_alpha_and_beta(a, v))

        # Almost correct forms / different ways to fail
        def bad(e):
            r.set_rhs(e)
            self.assertFalse(hh.has_alpha_beta_form(r, v))
            r.set_rhs('alpha * (1 - r) - beta * r')
            self.assertTrue(hh.has_alpha_beta_form(r, v))

        def good(e):
            r.set_rhs(e)
            self.assertTrue(hh.has_alpha_beta_form(r, v))

        # r is not a state
        self.assertTrue(hh.has_alpha_beta_form(r, v))
        r.demote()
        self.assertFalse(hh.has_alpha_beta_form(r, v))
        r.promote(0)
        self.assertTrue(hh.has_alpha_beta_form(r, v))

        # Not a minus
        bad('alpha * (1 - r) + beta * r')

        # Minus, but terms aren't multiplies
        bad('alpha / (1 - r) - beta * r')
        bad('alpha * (1 - r) - beta / r')

        # Terms in multiplications can be switched
        good('(1 - r) * alpha - beta * r')
        good('(1 - r) * alpha - r * beta')
        good('alpha * (1 - r) - beta * r')

        # But the correct terms are required
        bad('alpha * (2 - r) - beta * r')
        bad('alpha^2 * (1 - r) - beta * r')
        bad('alpha * (1 - r) - beta * r^2')
        bad('alpha * (1 - r) - beta^2 * r')

        # Alpha and beta can't be states
        m2 = m.clone()
        m2.get('membrane.V').set_label('membrane_potential')
        m2.get('ikr.r').move_variable(m2.get('ikr.r.alpha'), m2.get('ikr'),
                                      'ralpha')
        self.assertTrue(hh.has_alpha_beta_form(m2.get('ikr.r')))
        m2.get('ikr.ralpha').promote(1)
        self.assertFalse(hh.has_alpha_beta_form(m2.get('ikr.r')))
        m2.get('ikr.ralpha').demote()
        m2.get('ikr.r').move_variable(m2.get('ikr.r.beta'), m2.get('ikr'),
                                      'rbeta')
        self.assertTrue(hh.has_alpha_beta_form(m2.get('ikr.r')))
        m2.get('ikr.rbeta').promote(1)

        # Alpha and beta can't depend on other states than v
        c = m.add_component('ccc')
        x = c.add_variable('vvv')
        x.set_rhs(1)
        x.promote(0)
        ralph = m.get('ikr.r.alpha').rhs()
        self.assertTrue(hh.has_alpha_beta_form(r, v))
        m.get('ikr.r.alpha').set_rhs('3 * ccc.vvv + V')
        self.assertFalse(hh.has_alpha_beta_form(r, v))
        m.get('ikr.r.alpha').set_rhs(ralph)
        self.assertTrue(hh.has_alpha_beta_form(r, v))
        ralph = m.get('ikr.r.beta').rhs()
        m.get('ikr.r.beta').set_rhs('2 + ccc.vvv - V')
        self.assertFalse(hh.has_alpha_beta_form(r, v))
        m.get('ikr.r.beta').set_rhs(ralph)
        self.assertTrue(hh.has_alpha_beta_form(r, v))