示例#1
0
    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)
示例#2
0
    def test_units(self):
        # Test writing of units

        u1 = myokit.parse_unit('kg*m^2/mole^3 (0.123)')
        u2 = myokit.parse_unit('1 (4.56)')

        m1 = cellml.Model('mmm')
        m1.add_units('flibbit', u1)
        m1.add_units('special_volt', myokit.units.Volt)
        c = m1.add_component('ccc')
        c.add_units('flibbit', u2)
        p = c.add_variable('p', 'flibbit')
        p.set_rhs(myokit.Number(1, u2))
        d = m1.add_component('ddd')
        q = d.add_variable('q', 'flibbit')
        q.set_rhs(myokit.Number(2, u1))

        xml = cellml.write_string(m1)
        m2 = cellml.parse_string(xml)

        p, q = m2['ccc']['p'], m2['ddd']['q']
        self.assertEqual(p.units().name(), 'flibbit')
        self.assertEqual(q.units().name(), 'flibbit')
        self.assertEqual(p.units().myokit_unit(), u2)
        self.assertEqual(q.units().myokit_unit(), u1)
        self.assertEqual(
            m2.find_units('special_volt').myokit_unit(), myokit.units.volt)
示例#3
0
文件: parser.py 项目: teosbpl/myokit
    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')
示例#4
0
    def __init__(self, value, unit=None):

        if isinstance(value, myokit.Expression):
            # Convert myokit.Expression
            if unit is not None:
                raise ValueError('Cannot specify a unit when creating a'
                                 ' myokit.Quantity from a myokit.Number.')
            self._value = value.eval()
            unit = value.unit()
            self._unit = \
                unit if unit is not None else myokit.units.dimensionless

        else:
            # Convert other types
            self._unit = None
            try:
                # Convert value to float
                self._value = float(value)

            except (ValueError, TypeError):

                # Try parsing string
                try:
                    self._value = str(value)
                    parts = value.split('[', 1)
                except Exception:
                    raise ValueError(
                        'Value of type ' + str(type(value)) +
                        ' could not be converted to myokit.Quantity.')

                # Very simple number-with-unit parsing
                try:
                    self._value = float(parts[0])
                except ValueError:
                    raise ValueError('Failed to parse string "' + str(value) +
                                     '" as myokit.Quantity.')
                self._unit = myokit.parse_unit(parts[1].strip()[:-1])

            # No unit set yet? Then check unit argument
            if self._unit is None:
                if unit is None:
                    self._unit = myokit.units.dimensionless
                elif isinstance(unit, myokit.Unit):
                    self._unit = unit
                else:
                    self._unit = myokit.parse_unit(unit)
            elif unit is not None:
                raise ValueError('Two units specified for myokit.Quantity.')

        # Create string representation
        self._str = str(self._value) + ' ' + str(self._unit)
示例#5
0
    def test_unit(self):
        # Test the unit() method that returns a unit conversion factor.

        m = myokit.Model()
        c = m.add_component('c')
        x = c.add_variable('x')
        x.set_rhs(0)
        x.set_unit(myokit.parse_unit('mV'))

        self.assertRaises(
            myokit.IncompatibleModelError, multi.unit, x,
            myokit.parse_unit('kg'))
        self.assertEqual(multi.unit(x, myokit.parse_unit('V')), 0.001)
        self.assertEqual(multi.unit(x, myokit.parse_unit('mV')), 1)
        self.assertEqual(multi.unit(x, myokit.parse_unit('uV')), 1000)
示例#6
0
    def test_versions(self):
        # Tests writing different CellML versions

        # CellML 1.0
        units = {
            myokit.parse_unit('pF'): 'picofarad',
        }
        w = cellml.CellMLExpressionWriter('1.0')
        w.set_unit_function(lambda x: units[x])
        xml = w.ex(myokit.Number(1, myokit.units.pF))
        self.assertIn(cellml.NS_CELLML_1_0, xml)

        # CellML 1.1
        w = cellml.CellMLExpressionWriter('1.1')
        w.set_unit_function(lambda x: units[x])
        xml = w.ex(myokit.Number(1, myokit.units.pF))
        self.assertIn(cellml.NS_CELLML_1_1, xml)

        # CellML 1.2
        self.assertRaisesRegex(ValueError, 'Unknown CellML version',
                               cellml.CellMLExpressionWriter, '1.2')

        # CellML 2.0
        w = cellml.CellMLExpressionWriter('2.0')
        w.set_unit_function(lambda x: units[x])
        xml = w.ex(myokit.Number(1, myokit.units.pF))
        self.assertIn(cellml.NS_CELLML_2_0, xml)
示例#7
0
    def test_str(self):
        # Test :meth:`Unit.str()`

        # Unit with representation in alternative base
        km_per_s = myokit.Unit([0, 1, -1, 0, 0, 0, 0], 3)

        # Myokit doesn't know km/s, it does know m/s so this should become:
        self.assertEqual(str(km_per_s), '[m/s (1000)]')

        # Myokit doesn't know MA/m^2
        mam2 = myokit.parse_unit('MA/m^2')
        self.assertEqual(str(mam2), '[A/m^2 (1e+06)]')

        # Simple units
        m = myokit.parse_unit('m')
        self.assertEqual(str(m), '[m]')
        im = 1 / m
        self.assertEqual(str(im), '[1/m]')

        # Predefined complex unit
        self.assertEqual(str(myokit.units.N), '[N]')

        # Low mulipliers
        um = m * 1e-6
        self.assertEqual(str(um), '[um]')
        um3 = myokit.parse_unit('um^3')
        self.assertEqual(str(um3), '[um^3]')
        attomol = myokit.parse_unit('amol')
        self.assertEqual(str(attomol), '[mol (1e-18)]')

        # High multipliers
        nn = myokit.units.N * 1e-2
        self.assertEqual(str(nn), '[N (0.01)]')
        nn = myokit.units.N * 1e2
        self.assertEqual(str(nn), '[N (100)]')
        nn = myokit.units.N * 1e7
        self.assertEqual(str(nn), '[N (1e+07)]')

        # Unit very similar to a known unit
        c = myokit.units.V
        d = c * 1.000000001
        self.assertFalse(c == d)
        self.assertTrue(myokit.Unit.close(c, d))
        self.assertEqual(str(c), '[V]')
        self.assertEqual(str(d), '[V]')
示例#8
0
    def test_parse_expression(self):
        """
        Test parse_expression()
        """
        from myokit import parse_expression as p
        from myokit import Number
        e = p('5')
        self.assertIsInstance(e, Number)
        self.assertEqual(e.eval(), 5.0)
        self.assertEqual(float(e), 5.0)
        e = p('5[m]')
        self.assertIsInstance(e, Number)
        self.assertEqual(e.eval(), 5.0)
        self.assertEqual(float(e), 5.0)
        self.assertEqual(e.unit(), myokit.units.m)
        e = p('5 [m/s]')
        self.assertIsInstance(e, Number)
        self.assertEqual(e.eval(), 5.0)
        self.assertEqual(float(e), 5.0)
        self.assertEqual(e.unit(), myokit.parse_unit('m/s'))
        self.assertEqual(e.unit(), myokit.units.m / myokit.units.s)
        e = p('+5')
        self.assertIsInstance(e, myokit.PrefixPlus)
        self.assertEqual(e.eval(), 5.0)
        e = p('++5')
        self.assertIsInstance(e, myokit.PrefixPlus)
        self.assertEqual(e.eval(), 5.0)
        e = p('-5')
        self.assertIsInstance(e, myokit.PrefixMinus)
        self.assertEqual(e.eval(), -5.0)
        e = p('--5')
        self.assertIsInstance(e, myokit.PrefixMinus)
        self.assertEqual(e.eval(), 5.0)
        e = p('5 + 2')
        self.assertIsInstance(e, myokit.Plus)
        self.assertEqual(e.eval(), 7)
        e = p('5 + 1 + 1')
        self.assertIsInstance(e, myokit.Plus)
        self.assertEqual(e.eval(), 7)
        e = p('5 - 2')
        self.assertIsInstance(e, myokit.Minus)
        self.assertEqual(e.eval(), 3)
        e = p('5 -- 2')
        self.assertIsInstance(e, myokit.Minus)
        self.assertEqual(e.eval(), 7)
        e = p('5 --+ 2')
        self.assertIsInstance(e, myokit.Minus)
        self.assertEqual(e.eval(), 7)
        e = p('5 --- 2')
        self.assertIsInstance(e, myokit.Minus)
        self.assertEqual(e.eval(), 3)
        # Etc etc etc

        # Test bad value
        self.assertRaises(myokit.ParseError, p, '5 beans')
示例#9
0
    def test_repr(self):
        # Test :meth:`Unit.repr()`.

        # Simple units
        m = myokit.parse_unit('m')
        self.assertEqual(repr(m), '[m]')
        im = 1 / m
        self.assertEqual(repr(im), '[1/m]')
        um = m * 1e-6

        # Predefined complex unit
        self.assertEqual(repr(myokit.units.N), '[g*m/s^2 (1000)]')

        # Low multipliers
        self.assertEqual(repr(um), '[m (1e-06)]')
        um3 = myokit.parse_unit('um^3')
        self.assertEqual(repr(um3), '[m^3 (1e-18)]')

        # High multipliers
        nn = myokit.units.N * 1e-2
        self.assertEqual(repr(nn), '[g*m/s^2 (10)]')
        nn = myokit.units.N * 1e7
        self.assertEqual(repr(nn), '[g*m/s^2 (1e+10)]')
示例#10
0
    def cast(self, unit):
        """
        Returns a new Quantity with this quantity's value and a different,
        possibly incompatible, unit.

        Example:

            >>> from myokit import Quantity as Q
            >>> a = Q('10 [A/F]')
            >>> b = a.cast('uA/cm^2')
            >>> print(str(b))
            10.0 [uA/cm^2]

        """
        if not isinstance(unit, myokit.Unit):
            unit = myokit.parse_unit(unit)
        return Quantity(self._value, unit)
示例#11
0
    def setUpClass(cls):
        # CellML requires unit mapping
        units = {
            myokit.parse_unit('pF'): 'picofarad',
        }
        cls.w = cellml.CellMLExpressionWriter()
        cls.w.set_unit_function(lambda x: units[x])

        model = myokit.Model()
        component = model.add_component('c')
        cls.avar = component.add_variable('a')

        # Requires valid model with unames set
        cls.avar.set_rhs(0)
        cls.avar.set_binding('time')
        model.validate()

        # MathML opening and closing tags
        cls._math = re.compile(r'^<math [^>]+>(.*)</math>$', re.S)
示例#12
0
    def test_set_unit(self):
        # Test :meth:`Variable.set_unit()`.
        m = myokit.Model()
        c = m.add_component('c')
        v = c.add_variable('v')

        # Test basic functionality
        s = myokit.UNIT_STRICT
        self.assertIsNone(v.unit())
        self.assertEqual(v.unit(s), myokit.units.dimensionless)
        v.set_unit(myokit.units.Newton)
        self.assertEqual(v.unit(), myokit.units.Newton)
        self.assertEqual(v.unit(s), myokit.units.Newton)

        # Set via unit parsing
        v.set_unit('kg/ms')
        self.assertEqual(v.unit(), myokit.parse_unit('kg/ms'))

        # Set to a non unit
        self.assertRaisesRegex(
            TypeError, 'expects a myokit.Unit', v.set_unit, 12)
示例#13
0
def create_one_comp_pk_model():
    """
    Returns 1 compartmental PK model.
    """
    # Instantiate model
    model = Model()

    # add central compartment
    central_comp = model.add_compartment('central')

    # add variables and constants to central compartment
    amount = central_comp.add_variable('amount')
    volume = central_comp.add_variable('volume')
    k_e = central_comp.add_variable('k_e')
    conc = central_comp.add_variable('conc')

    # bind time
    time = central_comp.add_variable('time')
    time.set_binding('time')

    # set intial values (some default values)
    time.set_rhs(0)

    amount.set_rhs(0)
    volume.set_rhs(1)
    k_e.set_rhs(0)
    conc.set_rhs(0)

    # set units
    time.set_unit('day')  # time in days

    amount.set_unit('mg')  # miligram
    volume.set_unit('L')  # liter
    k_e.set_unit('1 / day')  # 1 / day
    conc.set_unit('mg / L')  # miligram / liter

    # set preferred representation of units
    # time days
    unit = myokit.parse_unit('day')
    myokit.Unit.register_preferred_representation('day', unit)
    # rates in 1 / day
    unit = myokit.parse_unit('1/day')
    myokit.Unit.register_preferred_representation('1/day', unit)
    # amount in mg
    unit = myokit.parse_unit('mg')
    myokit.Unit.register_preferred_representation('mg', unit)
    # dose rate in mg / day
    unit = myokit.parse_unit('mg/day')
    myokit.Unit.register_preferred_representation('mg/day', unit)
    # concentration mg / L
    unit = myokit.parse_unit('mg/L')
    myokit.Unit.register_preferred_representation('mg/L', unit)

    # set rhs of state variables
    # (dot(amount) = - k_e * amount)
    amount.promote()
    amount.set_rhs(
        myokit.Multiply(myokit.PrefixMinus(myokit.Name(k_e)),
                        myokit.Name(amount)))

    # set algebraic relation between drug and concentration
    conc.set_rhs(myokit.Divide(myokit.Name(amount), myokit.Name(volume)))

    return model
示例#14
0
    def test_parse_variable(self):
        """
        Test parse_variable(), uses parse_expression()
        """
        from myokit._parsing import parse_model as p

        # Test basics
        s = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
        )
        t = p(s).get('x.t')
        self.assertEqual(t.name(), 't')
        self.assertEqual(t.qname(), 'x.t')
        self.assertEqual(t.unit(), None)
        self.assertEqual(t.binding(), 'time')

        s = (
            '[[model]]',
            '[x]',
            't = 0',
            '    bind time',
        )
        t = p(s).get('x.t')
        self.assertEqual(t.name(), 't')
        self.assertEqual(t.qname(), 'x.t')
        self.assertEqual(t.unit(), None)
        self.assertEqual(t.binding(), 'time')

        s = ('[[model]]', '[x]', 't = 0 bind time', 'x1 = 5')
        v = p(s).get('x.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 = ('[[model]]', '[x]', 't = 0 bind time', 'x2 = 5 [mV]')
        v = p(s).get('x.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 = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x3 = 5',
            '    in [mV]',
        )
        v = p(s).get('x.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 = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x3 = 5 in [mV]',
        )
        v = p(s).get('x.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 = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x4 = 5 [V] : This is x4',
        )
        v = p(s).get('x.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')

        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x = 5 label vvv',
        )
        x = p(code).get('x.x')
        self.assertIsInstance(x, myokit.Variable)
        self.assertEqual(x.label(), 'vvv')

        s = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x = 5',
            '    label vvv',
        )
        x = p(code).get('x.x')
        self.assertIsInstance(x, myokit.Variable)
        self.assertEqual(x.label(), 'vvv')

        # Illegal lhs
        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'sin(x) = 5',
        )
        self.assertRaisesRegex(myokit.ParseError, 'variable names or the dot',
                               p, code)

        # Duplicate name
        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'x = 5',
            'x = 5',
        )
        self.assertRaisesRegex(myokit.ParseError, 'Duplicate var', p, code)

        # Missing initial value
        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            'dot(x) = 5',
        )
        self.assertRaisesRegex(myokit.ParseError, 'Missing initial', p, code)

        # Duplicate meta
        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            '    yes: really',
            '    yes: no',
        )
        self.assertRaisesRegex(myokit.ParseError, 'Duplicate meta-data key', p,
                               code)

        # Duplicate unit
        code = (
            '[[model]]',
            '[x]',
            't = 0 bind time',
            '    in [s]',
            '    in [s]',
        )
        self.assertRaisesRegex(myokit.ParseError, 'Duplicate variable unit', p,
                               code)
示例#15
0
def _rep(name):
    unit = myokit.parse_unit(name)
    myokit.Unit.register_preferred_representation(name, unit)
示例#16
0
def create_tumour_growth_model():
    r"""
    Returns a tumour growth myokit model.

    .. math::
        \frac{\text{d}V^s_T}{\text{d}t} = \frac{2\lambda _0\lambda _1 V^s_T}
        {2\lambda _0 V^s_T + \lambda _1},

    where the tumour volume :math:`V^s_T` is measured in :math:`\text{cm}^3`,
    the exponential growth rate :math:`\lambda _0` is mesured in
    :math:`\text{day}` and the linear growth rate :math:`\lambda _1` is
    measured in :math:`\text{cm}^3/\text{day}`.
    """
    # 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')
    lambda_0 = central_comp.add_variable('lambda_0')
    lambda_1 = central_comp.add_variable('lambda_1')

    # bind time
    time = central_comp.add_variable('time')
    time.set_binding('time')

    # set preferred representation of units
    # time in days
    unit = myokit.parse_unit('day')
    myokit.Unit.register_preferred_representation('day', unit)
    # rates in 1 / day
    unit = myokit.parse_unit('1/day')
    myokit.Unit.register_preferred_representation('1/day', unit)
    # tumor volume
    unit = myokit.parse_unit('cm^3')
    myokit.Unit.register_preferred_representation('cm^3', unit)
    # linear growth
    unit = myokit.parse_unit('cm^3/day')
    myokit.Unit.register_preferred_representation('cm^3/day', unit)

    # set intial values (some default values) and units
    time.set_rhs(0)

    volume_t.set_rhs(0)
    lambda_0.set_rhs(0)
    lambda_1.set_rhs(1)  # avoid ZeroDivisionError

    # set units
    time.set_unit('day')  # time in days

    volume_t.set_unit('cm^3')  # milimeter cubed
    lambda_0.set_unit('1 / day')  # per day
    lambda_1.set_unit('cm^3 / day')  # milimiter cubed per day

    # set rhs of tumor volume
    # dot(volume_t) =
    #  (2 * lambda_0 * lambda_1 * volume_t) /
    #  (2 * lambda_0 * volume_t + lambda_1)
    volume_t.promote()
    volume_t.set_rhs(
        myokit.Divide(
            myokit.Multiply(
                myokit.Number(2),
                myokit.Multiply(
                    myokit.Name(lambda_0),
                    myokit.Multiply(myokit.Name(lambda_1),
                                    myokit.Name(volume_t)))),
            myokit.Plus(
                myokit.Multiply(
                    myokit.Number(2),
                    myokit.Multiply(myokit.Name(lambda_0),
                                    myokit.Name(volume_t))),
                myokit.Name(lambda_1))))

    # Validate model
    model.validate()

    # TODO: Check units
    # model.check_units()

    return model
示例#17
0
    def conversion_factor(unit1, unit2, helpers=None):
        """
        Returns a :class:`myokit.Quantity` ``c`` to convert from ``unit1`` to
        ``unit2``, such that ``1 [unit1] * c = 1 [unit2]``.

        For example::

            >>> import myokit
            >>> myokit.Unit.conversion_factor('m', 'km')
            0.001 [1 (1000)]

        Where::

            1 [m] = 0.001 [km/m] * 1 [km]

        so that ``c = 0.001 [km/m]``, and the unit ``[km/m]`` can be written as
        ``[km/m] = [ kilo ] = [1 (1000)]``.

        Conversions between incompatible units can be performed if one or
        multiple helper :class:`Quantity` objects are passed in.

        For example::

            >>> import myokit
            >>> myokit.Unit.conversion_factor(
            ...     'uA/cm^2', 'uA/uF', ['1 [uF/cm^2]'])
            1.0 [cm^2/uF]

        Where::

            1 [uA/cm^2] = 1 [cm^2/uF] * 1 [uA/uF]

        Note that this method uses the :meth:`close()` and
        :meth:`close_exponent` comparisons to see if units are equal.

        Arguments:

        ``unit1``
            The new unit to convert from, given as a :class:`myokit.Unit` or as
            a string that can be converted to a unit with
            :meth:`myokit.parse_unit()`.
        ``unit2``
            The new unit to convert to.
        ``helpers=None``
            An optional list of conversion factors, which the method will
            attempt to use if the new and old units are incompatible. Each
            factor should be specified as a :class:`myokit.Quantity` or
            something that can be converted to a Quantity e.g. a string
            ``1 [uF/cm^2]``.

        Returns a :class:`myokit.Quantity`.

        Raises a :class:`myokit.IncompatibleUnitError` if the units cannot be
        converted.'
        """
        # Check unit1
        if not isinstance(unit1, myokit.Unit):
            if unit1 is None:
                unit1 = myokit.units.dimensionless
            else:
                unit1 = myokit.parse_unit(unit1)

        # Check unit2
        if not isinstance(unit2, myokit.Unit):
            if unit2 is None:
                unit2 = myokit.units.dimensionless
            else:
                unit2 = myokit.parse_unit(unit2)

        # Check helper units
        factors = []
        if helpers is not None:
            for factor in helpers:
                if not isinstance(factor, myokit.Quantity):
                    factor = myokit.Quantity(factor)
                factors.append(factor)
        del (helpers)

        # Simplest case: units are (almost) equal
        if Unit.close(unit1, unit2):
            return Quantity(1)

        # Get conversion factor
        fw = None
        if Unit.close_exponent(unit1, unit2):

            # Directly convertible
            fw = 10**(unit1._m - unit2._m)

        else:
            # Try conversion via one of the helpers
            for factor in factors:

                unit1a = unit1 * factor.unit()
                if Unit.close_exponent(unit1a, unit2):
                    fw = 10**(unit1a._m - unit2._m) * factor.value()
                    break

                unit1a = unit1 / factor.unit()
                if Unit.close_exponent(unit1a, unit2):
                    fw = 10**(unit1a._m - unit2._m) / factor.value()
                    break

        # Unable to convert?
        if fw is None:
            msg = 'Unable to convert from ' + unit1.clarify()
            msg += ' to ' + unit2.clarify()
            if factors:
                msg += ' (even with help of conversion factors).'
            raise myokit.IncompatibleUnitError(msg + '.')

        # Create Quantity and return
        fw = myokit.float.round(fw)
        return Quantity(fw, unit2 / unit1)
示例#18
0
    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)
示例#19
0
    def test_convert_unit(self):
        # Test changing variable units

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

            [env]
            t = 0 [ms] bind time
                in [ms]

            [membrane]
            dot(V) = - (ikr.i + ina.i * 1 [cm^2/uF])
                in [mV]
            dotv = 5 [mV/ms] + dot(V)
                in [mV/ms]

            [cell]
            Cm = 0.123 [uF]
                in [uF]

            [ina]
            i = 12 [uA/cm^2]
                in [uA/cm^2]

            [ikr]
            use membrane.V
            E = -81 [mV]
                in [mV]
            g = 23 [mS/uF]
                in [mS/uF]
            i = g * (V - E)
                in [uA/uF]
        """)
        m.check_units(myokit.UNIT_STRICT)

        # Convert to same
        code = m.code()
        v = m.get('membrane.V')
        v.convert_unit('mV')
        self.assertEqual(code, m.code())

        # Convert state
        vdot = v.rhs().eval()
        self.assertNotEqual(v.unit(), myokit.units.V)
        v.convert_unit('V')
        self.assertEqual(v.unit(), myokit.units.V)

        # Check dot(v) is the same, and all units are compatible
        vdot /= 1000
        self.assertEqual(vdot, v.rhs().eval())
        m.check_units(myokit.UNIT_STRICT)

        # Convert non-state
        i = m.get('ina.i')
        self.assertNotEqual(i.unit(), myokit.parse_unit('uA/uF'))
        i.convert_unit('uA/uF', ['1 [uF/cm^2]'])
        self.assertEqual(i.unit(), myokit.parse_unit('uA/uF'))

        # Check dot(v) is the same, and all units are compatible
        self.assertEqual(vdot, v.rhs().eval())
        m.check_units(myokit.UNIT_STRICT)

        # Convert time variable
        t = m.time()
        self.assertNotEqual(t.unit(), myokit.units.s)
        t.convert_unit('s')
        self.assertEqual(t.unit(), myokit.units.s)

        # Check dot(v) is the same, and all units are compatible
        vdot *= 1000
        self.assertEqual(vdot, v.rhs().eval())
        m.check_units(myokit.UNIT_STRICT)
示例#20
0
    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'))
示例#21
0
def create_pktgi_model():
    """
    Returns 1 compartmental PK model.
    """
    # Instantiate model
    model = Model()

    # Add central compartment
    central_comp = model.add_compartment('central')

    # Add PK variables and constants to central compartment
    amount = central_comp.add_variable('amount')
    volume_c = central_comp.add_variable('volume_c')
    k_e = central_comp.add_variable('k_e')
    conc = central_comp.add_variable('conc')

    # add PD variables to central compartment
    volume_t = central_comp.add_variable('volume_t')
    lambda_0 = central_comp.add_variable('lambda_0')
    lambda_1 = central_comp.add_variable('lambda_1')
    kappa = central_comp.add_variable('kappa')

    # bind time
    time = central_comp.add_variable('time')
    time.set_binding('time')

    # set intial values (some default values)
    time.set_rhs(0)

    amount.set_rhs(0)
    volume_c.set_rhs(1)  # avoid ZeroDivisionError
    k_e.set_rhs(0)
    conc.set_rhs(0)

    volume_t.set_rhs(0)
    lambda_0.set_rhs(0)
    lambda_1.set_rhs(1)  # avoid ZeroDivisionError
    kappa.set_rhs(0)

    # set units
    time.set_unit('day')  # time in days

    amount.set_unit('mg')  # miligram
    volume_c.set_unit('L')  # liter
    k_e.set_unit('1 / day')  # 1 / day
    conc.set_unit('mg / L')  # miligram / liter

    volume_t.set_unit('cm^3')  # milimeter cubed
    lambda_0.set_unit('1 / day')  # per day
    lambda_1.set_unit('cm^3 / day')  # milimiter cubed per day
    kappa.set_unit('L / mg / day')  # in reference L / ug / day,

    # set preferred representation of units
    # time days
    unit = myokit.parse_unit('day')
    myokit.Unit.register_preferred_representation('day', unit)
    # rates in 1 / day
    unit = myokit.parse_unit('1/day')
    myokit.Unit.register_preferred_representation('1/day', unit)
    # amount in mg
    unit = myokit.parse_unit('mg')
    myokit.Unit.register_preferred_representation('mg', unit)
    # dose rate in mg / day
    unit = myokit.parse_unit('mg/day')
    myokit.Unit.register_preferred_representation('mg/day', unit)
    # concentration mg / L
    unit = myokit.parse_unit('mg/L')
    myokit.Unit.register_preferred_representation('mg/L', unit)

    # tumor volume
    unit = myokit.parse_unit('cm^3')
    myokit.Unit.register_preferred_representation('cm^3', unit)
    # linear growth
    unit = myokit.parse_unit('cm^3/day')
    myokit.Unit.register_preferred_representation('cm^3/day', unit)
    # potency
    unit = myokit.parse_unit('L/mg/day')
    myokit.Unit.register_preferred_representation('L/mg/day', unit)

    # set rhs of drug amount
    # (dot(amount) = - k_e * amount)
    amount.promote()
    amount.set_rhs(
        myokit.Multiply(myokit.PrefixMinus(myokit.Name(k_e)),
                        myokit.Name(amount)))

    # set rhs of tumor volume
    # dot(volume_t) =
    #  (2 * lambda_0 * lambda_1 * volume_t) /
    #  (2 * lambda_0 * volume_t + lambda_1) -
    #  kappa * conc * volume_t
    volume_t.promote()
    volume_t.set_rhs(
        myokit.Minus(
            myokit.Divide(
                myokit.Multiply(
                    myokit.Number(2),
                    myokit.Multiply(
                        myokit.Name(lambda_0),
                        myokit.Multiply(myokit.Name(lambda_1),
                                        myokit.Name(volume_t)))),
                myokit.Plus(
                    myokit.Multiply(
                        myokit.Number(2),
                        myokit.Multiply(myokit.Name(lambda_0),
                                        myokit.Name(volume_t))),
                    myokit.Name(lambda_1))),
            myokit.Multiply(
                myokit.Name(kappa),
                myokit.Multiply(myokit.Name(conc), myokit.Name(volume_t)))))

    # set algebraic relation between drug and concentration
    # conc = amount / volume_c
    conc.set_rhs(myokit.Divide(myokit.Name(amount), myokit.Name(volume_c)))

    return model