Пример #1
0
    def test_pickling(self):
        # Test pickling a simulation

        # Test with myokit.Protocol
        m, p, _ = myokit.load('example')
        s1 = myokit.LegacySimulation(m, p)
        s1.pre(123)
        s_bytes = pickle.dumps(s1)
        s2 = pickle.loads(s_bytes)
        self.assertEqual(s1.time(), s2.time())
        self.assertEqual(s1.state(), s2.state())
        self.assertEqual(s1.default_state(), s2.default_state())
        s1.run(123, log=myokit.LOG_NONE)
        s2.run(123, log=myokit.LOG_NONE)
        self.assertEqual(s1.time(), s2.time())
        self.assertEqual(s1.state(), s2.state())

        # Test simulation properties
        s1.set_tolerance(1e-8, 1e-8)
        s1.set_min_step_size(1e-2)
        s1.set_max_step_size(0.1)
        s2 = pickle.loads(pickle.dumps(s1))
        s1.run(23, log=myokit.LOG_NONE)
        s2.run(23, log=myokit.LOG_NONE)
        self.assertEqual(s1.time(), s2.time())
        self.assertEqual(s1.state(), s2.state())

        # Test changed constants
        s1.set_constant('membrane.C', 1.1)
        s2 = pickle.loads(pickle.dumps(s1))
        s1.run(17, log=myokit.LOG_NONE)
        s2.run(17, log=myokit.LOG_NONE)
        self.assertEqual(s1.time(), s2.time())
        self.assertEqual(s1.state(), s2.state())
Пример #2
0
    def setUpClass(cls):
        # Test simulation creation.

        m, p, x = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        cls.model = m
        cls.protocol = p
        cls.sim = myokit.LegacySimulation(cls.model, cls.protocol)
Пример #3
0
    def test_pacing_values_at_event_transitions(self):
        # Tests the value of the pacing signal at event transitions

        # Create a simple model
        m = myokit.Model()
        c = m.add_component('c')
        t = c.add_variable('t')
        t.set_rhs(0)
        t.set_binding('time')
        v = c.add_variable('v')
        v.set_rhs('0')
        v.set_binding('pace')
        x = c.add_variable('x')
        x.set_rhs(0.1)
        x.promote(0)

        # Create step protocol
        p = myokit.Protocol()
        p.schedule(0, 0, 2)
        p.schedule(1, 2, 2)
        p.schedule(2, 4, 4)
        p.schedule(3, 8, 2)

        # Simulate with dynamic logging
        s = myokit.LegacySimulation(m, p)
        d = s.run(p.characteristic_time())
        time = list(d.time())
        value = list(d['c.v'])

        if False:
            for i, t in enumerate(d.time()):
                t = str(np.round(t, 5))
                print(t + ' ' * (10 - len(t)) + str(d['c.v'][i]))

        # Values should be
        #   t   0   1   2   3   4   5   6   7   8   9   10
        #   p   0   0   1   1   2   2   2   2   3   3   0
        self.assertEqual(value[time.index(0.0)], 0)
        self.assertEqual(value[time.index(0.0) + 1], 0)
        self.assertEqual(value[time.index(2.0) - 1], 0)
        self.assertEqual(value[time.index(2.0)], 1)
        self.assertEqual(value[time.index(2.0) + 1], 1)
        self.assertEqual(value[time.index(4.0) - 1], 1)
        self.assertEqual(value[time.index(4.0)], 2)
        self.assertEqual(value[time.index(4.0) + 1], 2)
        self.assertEqual(value[time.index(8.0) - 1], 2)
        self.assertEqual(value[time.index(8.0)], 3)
        self.assertEqual(value[time.index(8.0) + 1], 3)
        self.assertEqual(value[time.index(10.0) - 1], 3)
        self.assertEqual(value[time.index(10.0)], 0)

        # Simulate with fixed logging
        s.reset()
        d = s.run(p.characteristic_time() + 1, log_times=d.time())
        time2 = list(d.time())
        value2 = list(d['c.v'])
        self.assertEqual(time, time2)
        self.assertEqual(value, value2)
    def test_interpolation_and_pacing(self):
        # Test if interpolation results in correct pacing values.

        # When logging with discontinuous steps, in the adaptive time
        # CVODE sim, the value of pace must be
        #  1. The old value *before* the time of the event
        #  2. The new value *at and after* the time of the event
        #  3. Back to zero *at and after* the end of the event
        #     (Unless it ends sooner due to a new event arriving)
        # Load model
        m = myokit.load_model('example')

        # Voltage-clamp V (but don't bind it directly)
        v = m.label('membrane_potential')
        v.demote()
        v.set_rhs('-80 + 10 * engine.pace')

        # Create protocol
        p = myokit.Protocol()
        p.schedule(level=1, start=0, duration=5, period=10)

        # Create simulation
        s = myokit.LegacySimulation(m, p)

        # Test if this would result in multiple interpolation steps for logging
        # i.e. test if the step before each transition was at least 2 log steps
        # long
        e = s.run(30).npview()
        t = e.time()
        for x in [5, 10, 15, 20, 25]:
            i = e.find_after(x)
            if not t[i] - t[i - 1] > 0.2:
                raise Exception('Issue with test: use longer intervals!')
        del(e, t, x, i)

        # Now test if correct interpolated values are returned by periodic
        # logging.
        d = s.run(30, log_interval=0.1).npview()

        # Test bound variable
        p = d['engine.pace']
        self.assertTrue(np.all(p[0:50] == 1))
        self.assertTrue(np.all(p[50:100] == 0))
        self.assertTrue(np.all(p[100:150] == 1))
        self.assertTrue(np.all(p[150:200] == 0))
        self.assertTrue(np.all(p[200:250] == 1))
        self.assertTrue(np.all(p[250:300] == 0))

        # Test variable dependent on bound variable
        p = d['membrane.V']
        self.assertTrue(np.all(p[0:50] == -70))
        self.assertTrue(np.all(p[50:100] == -80))
        self.assertTrue(np.all(p[100:150] == -70))
        self.assertTrue(np.all(p[150:200] == -80))
        self.assertTrue(np.all(p[200:250] == -70))
        self.assertTrue(np.all(p[250:300] == -80))
Пример #5
0
    def test_simulation_error_2(self):
        # Test for simulation error detection: failure occurred too often.

        # Cvode error (test failure occurred too many times)
        m = self.model.clone()
        v = m.get('membrane.V')
        v.set_rhs(myokit.Multiply(v.rhs(), myokit.Number(1e18)))
        s = myokit.LegacySimulation(m, self.protocol)
        with WarningCollector():
            self.assertRaisesRegex(
                myokit.SimulationError, 'numerical error', s.run, 5000)
Пример #6
0
    def test_last_evaluations_and_steps(self):
        # Test :meth:`LegacySimulation.last_number_of_evaluations()` and
        # :meth:`LegacySimulation.last_number_of_steps()`

        s = myokit.LegacySimulation(self.model, self.protocol)
        self.assertEqual(s.last_number_of_evaluations(), 0)
        self.assertEqual(s.last_number_of_steps(), 0)
        s.run(1)
        self.assertTrue(s.last_number_of_evaluations() > 0)
        self.assertTrue(s.last_number_of_steps() > 0)
        self.assertNotEqual(
            s.last_number_of_evaluations(), s.last_number_of_steps())
Пример #7
0
    def test_apd(self):
        # Test the apd rootfinding routine

        s = myokit.LegacySimulation(
            self.model, self.protocol, apd_var='membrane.V')
        s.set_tolerance(1e-8, 1e-8)
        d, apds = s.run(1800, log=myokit.LOG_NONE, apd_threshold=-70)

        # Check with threshold equal to V
        self.assertEqual(len(apds['start']), 2)
        self.assertEqual(len(apds['duration']), 2)
        self.assertAlmostEqual(apds['start'][0], 1.19, places=1)
        self.assertAlmostEqual(apds['start'][1], 1001.19, places=1)
        self.assertAlmostEqual(apds['duration'][0], 383.88262, places=0)
        self.assertAlmostEqual(apds['duration'][1], 378.31448, places=0)
Пример #8
0
    def test_last_state(self):
        # Returns the last state before an error, or None.

        m = self.model.clone()
        istim = m.get('membrane.i_stim')
        istim.set_rhs('engine.pace / stim_amplitude')
        s = myokit.LegacySimulation(m, self.protocol)
        self.assertIsNone(s.last_state())
        s.run(1)
        self.assertIsNone(s.last_state())
        s.set_constant('membrane.i_stim.stim_amplitude', 0)
        s.reset()
        self.assertRaisesRegex(myokit.SimulationError, "at t = 0", s.run, 5)
        self.assertEqual(len(s.last_state()), len(s.state()))
        self.assertEqual(s.last_state(), s.state())
    def test_point_list_2(self):
        # Test how the point-list logging performs when some of the logging
        # points overlap with protocol change points.

        # Load model
        m = myokit.load_model(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        # Voltage clamp
        m.binding('pace').set_binding(None)
        v = m.get('membrane.V')
        v.demote()
        v.set_rhs(0)
        v.set_binding('pace')
        #TODO: Implement chaining like this?
        #m.get('membrane.V').demote().set_rhs(0).set_binding('pace')
        # Create step protocol
        dt = 0.1
        steps = [
            [-80, 250.1],
            [-120, 50],
            [-80, 200],
            [40, 1000],
            [-120, 500],
            [-80, 1000],
            [-30, 3500],
            [-120, 500],
            [-80, 1000],
        ]
        p = myokit.Protocol()
        for f, t in steps:
            p.add_step(f, t)
        # Create set of times that overlap with change points
        times = np.arange(80000) * dt
        # Create simulation
        s = myokit.LegacySimulation(m, p)
        # Run
        d = s.run(8000, log_times=times).npview()
        # Check if logging points show correct pacing value
        # In an earlier implementation, rounding errors and a difference in the
        # implementation of passing logpoints and passing protocol points could
        # cause the log point to be just before the protocol change.
        # In this case, a change at t=120.0 would only be picked up at t=120.1
        # (but not consistently!)
        # The below code checks for this
        offset = 0
        for v, t in steps[:-1]:
            offset += t
            e = d.trim(offset - dt, offset + 2 * dt)
            self.assertNotEqual(e['membrane.V'][0], e['membrane.V'][1])
Пример #10
0
    def test_apd_tracking(self):
        # Test the APD calculation method.

        # More testing is done in test_datalog.py!

        # Apd var is not a state
        v = self.model.get('ina.INa')
        self.assertRaisesRegex(
            ValueError, 'must be a state', myokit.LegacySimulation, self.model,
            self.protocol, apd_var=v)

        # Set a valid apd variable
        v = self.model.get('ik.x')
        sim = myokit.LegacySimulation(
            self.model, self.protocol, apd_var=v)
        sim.run(1, apd_threshold=12)

        # No apd var given, but threshold provided
        self.assertRaisesRegex(
            ValueError, 'without apd_var', self.sim.run, 1, apd_threshold=12)
Пример #11
0
    def test_sim_stats(self):
        # Test extraction of simulation statistics
        m, p, _ = myokit.load('example')
        rt = m['engine'].add_variable('realtime')
        rt.set_rhs(0)
        rt.set_binding('realtime')
        ev = m['engine'].add_variable('evaluations')
        ev.set_rhs(0)
        ev.set_binding('evaluations')
        s = myokit.LegacySimulation(m, p)
        d = s.run(100, log=myokit.LOG_BOUND).npview()

        self.assertIn('engine.realtime', d)
        self.assertIn('engine.evaluations', d)
        rt, ev = d['engine.realtime'], d['engine.evaluations']
        self.assertEqual(len(d.time()), len(rt))
        self.assertEqual(len(d.time()), len(ev))
        self.assertTrue(np.all(rt >= 0))
        self.assertTrue(np.all(ev >= 0))
        self.assertTrue(np.all(rt[1:] >= rt[:-1]))
        self.assertTrue(np.all(ev[1:] >= ev[:-1]))
Пример #12
0
    def test_progress_reporter(self):
        # Test running with a progress reporter.

        # Test if it works
        sim = myokit.LegacySimulation(self.model, self.protocol)
        with myokit.tools.capture() as c:
            sim.run(110, progress=myokit.ProgressPrinter())
        c = c.text().splitlines()
        self.assertEqual(len(c), 2)
        p = re.compile(re.escape('[0.0 minutes] 1.9 % done, estimated ') +
                       '[0-9]+' + re.escape(' seconds remaining'))
        self.assertIsNotNone(p.match(c[0]))
        p = re.compile(re.escape('[0.0 minutes] 100.0 % done, estimated ') +
                       '[0-9]+' + re.escape(' seconds remaining'))
        self.assertIsNotNone(p.match(c[1]))

        # Not a progress reporter
        self.assertRaisesRegex(
            ValueError, 'ProgressReporter', self.sim.run, 5, progress=12)

        # Cancel from reporter
        self.assertRaises(
            myokit.SimulationCancelledError, self.sim.run, 1,
            progress=CancellingReporter(0))
Пример #13
0
    def test_cvode_simulation_with_zero_states(self):
        # Tests running cvode simulations on models with no ODEs

        # Create a model without states
        m1 = myokit.Model()
        c = m1.add_component('c')
        t = c.add_variable('t')
        t.set_rhs(0)
        t.set_binding('time')
        v = c.add_variable('v')
        v.set_rhs('0')
        v.set_binding('pace')
        w = c.add_variable('w')
        w.set_rhs('2 * v')

        # Create a model with a state
        m2 = m1.clone()
        z = m2.get('c').add_variable('z')
        z.set_rhs(0.1)
        z.promote(0)

        # Test without protocol and dynamic logging
        s1 = myokit.LegacySimulation(m1)
        d1 = s1.run(5)
        self.assertEqual(len(d1.time()), 2)
        self.assertEqual(list(d1.time()), [0, 5])
        self.assertEqual(list(d1['c.w']), [0, 0])
        s2 = myokit.LegacySimulation(m2)
        d2 = s2.run(6, log_times=d1.time())
        self.assertEqual(d1.time(), d2.time())
        self.assertEqual(d1['c.w'], d2['c.w'])

        # Test with a protocol and dynamic logging
        p = myokit.Protocol()
        p.schedule(0, 0, 2)
        p.schedule(1, 2, 2)
        p.schedule(2, 4, 4)
        p.schedule(3, 8, 2)
        s1.reset()
        s1.set_protocol(p)
        d1 = s1.run(p.characteristic_time())
        self.assertEqual(len(d1.time()), 5)
        self.assertEqual(list(d1.time()), [0, 2, 4, 8, 10])
        self.assertEqual(list(d1['c.w']), [0, 2, 4, 6, 0])
        s2.reset()
        s2.set_protocol(p)
        d2 = s2.run(p.characteristic_time() + 1, log_times=d1.time())
        self.assertEqual(d1.time(), d2.time())
        self.assertEqual(d1['c.w'], d2['c.w'])

        # Test with fixed logging times
        s1.reset()
        d1 = s1.run(p.characteristic_time() + 1, log_times=d1['c.t'])
        self.assertEqual(list(d1.time()), [0, 2, 4, 8, 10])
        self.assertEqual(list(d1['c.w']), [0, 2, 4, 6, 0])
        s2.reset()
        d2 = s2.run(p.characteristic_time() + 1, log_times=d1.time())
        self.assertEqual(d1.time(), d2.time())
        self.assertEqual(d1['c.w'], d2['c.w'])

        # Test appending to log
        s1.reset()
        d1 = s1.run(5)
        d1 = s1.run(5, log=d1)
        self.assertEqual(list(d1.time()), [0, 2, 4, 5, 8, 10])
        self.assertEqual(list(d1['c.w']), [0, 2, 4, 4, 6, 0])

        # Test with a log interval
        s1.reset()
        d1 = s1.run(11, log_interval=1)
        self.assertEqual(list(d1.time()), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        self.assertEqual(list(d1['c.w']), [0, 0, 2, 2, 4, 4, 4, 4, 6, 6, 0])
    def test_point_list(self):
        # Test logging with a preset list of points.

        # Load model
        m, p, x = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        # Create simulation
        s = myokit.LegacySimulation(m, p)

        # Don't allow decreasing values
        times = [1, 2, 1]
        self.assertRaisesRegex(
            ValueError, 'non-decreasing', s.run, 5, log_times=times)

        # Can't use together with a log interval
        self.assertRaisesRegex(
            ValueError, 'simultaneously', s.run, 5, log_interval=1,
            log_times=[1, 2, 3])

        # Get some odd times
        times = np.linspace(0, 90, 999)

        # Test!
        s.reset()
        d = s.run(100, log_times=times).npview()
        self.assertTrue(np.all(d.time() == times))

        # Reset and run again
        s.reset()
        d = s.run(100, log_times=times).npview()
        self.assertTrue(np.all(d.time() == times))

        # Run in parts
        s.reset()
        d = s.run(50, log_times=times)
        self.assertEqual(len(d.time()), np.where(times >= 50)[0][0])
        d = s.run(50, log=d, log_times=times).npview()
        self.assertTrue(np.all(d.time() == times))

        # Pre-pacing
        s.reset()
        s.pre(50)
        s.run(100, log_times=times)
        self.assertTrue(np.all(d.time() == times))

        # Partial logging
        s.reset()
        s.run(10)
        d = s.run(10, log_times=times)
        imin = np.where(times >= 10)[0][0]
        imax = np.where(times >= 20)[0][0]
        self.assertEqual(len(d.time()), imax - imin)
        self.assertTrue(np.all(d.time() == times[imin:imax]))
        s.run(20)
        d = s.run(15, log_times=times)
        imin = np.where(times >= 40)[0][0]
        imax = np.where(times >= 55)[0][0]
        self.assertEqual(len(d.time()), imax - imin)
        self.assertTrue(np.all(d.time() == times[imin:imax]))

        # Get some regular times
        times = [0, 1, 2, 3, 4, 5]
        s.reset()
        d = s.run(6, log_times=times).npview()
        self.assertEqual(len(d.time()), len(times))
        self.assertTrue(np.all(d.time() == times))

        # Repeated points
        times = [0, 0, 0, 5, 5, 5]
        s.reset()
        d = s.run(6, log_times=times).npview()
        self.assertEqual(len(d.time()), len(times))
        self.assertTrue(np.all(d.time() == times))

        # End points not included, unless also visited!
        s.reset()
        s.run(5)
        d = s.run(5, log_times=times).npview()
        self.assertEqual(len(d.time()), 3)
        self.assertTrue(np.all(d.time() == times[3:]))
        d = s.run(5, log_times=times).npview()
        self.assertEqual(len(d.time()), 0)

        # Empty list is same as none
        s.reset()
        d = s.run(1, log_times=[])
        self.assertNotEqual(len(d.time()), 0)
    def test_periodic(self):
        # Test periodic logging

        m, p, x = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        s = myokit.LegacySimulation(m, p)
        self.periodic(s)
    def test_dynamic(self):
        # Test dynamic logging.

        emax = 1e-6     # Used for equality testing
        if debug:
            print('= Simulation :: Dynamic logging =')
        # Load model & protocol
        m, p, x = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        # Create simulation
        s = myokit.LegacySimulation(m, p)

        #
        # Test 1: Simple 5 ms simulation, log_interval 0.5 ms
        #
        d = s.run(50, log=['engine.time'])
        t = d['engine.time']
        if debug:
            print(t[:2])
            print(t[-2:])
            print('- ' * 10)
        # Test first point not double
        self.assertGreater(t[1], t[0])
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test first point is 0
        self.assertTrue(np.abs(t[0] - 0) < emax)
        # Test last point is 50
        self.assertTrue(np.abs(t[-1] - 50) < emax)

        #
        # Test 2: Very short simulation
        #
        s.reset()
        d = s.run(1, log=['engine.time'])
        t = d['engine.time']
        if debug:
            print(t[:2])
            print(t[-2:])
            print('- ' * 10)
        # Test first point not double
        self.assertGreater(t[1], t[0])
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test first point is 0
        self.assertTrue(np.abs(t[0] - 0) < emax)
        # Test last point is 50
        self.assertTrue(np.abs(t[-1] - 1) < emax)

        #
        # Test 3: Stop and start a simulation
        #
        s.reset()
        d = s.run(2, log=['engine.time'])
        t = d['engine.time']
        n = len(d['engine.time'])
        if debug:
            print(d['engine.time'][:2])
        # Test first point not double
        self.assertGreater(t[1], t[0])
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test first point is 0
        self.assertTrue(np.abs(t[0] - 0) < emax)
        # Test last point is 2
        self.assertTrue(np.abs(t[-1] - 2) < emax)
        d = s.run(13, log=d)
        t = d['engine.time']
        if debug:
            print(t[n - 2:n + 2])
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test last point is 2+13
        self.assertTrue(np.abs(t[-1] - 15) < emax)
        # Test intermediary points are different
        self.assertGreater(t[n], t[n - 1])
        n = len(d['engine.time'])
        d = s.run(15, log=d)
        t = d['engine.time']
        if debug:
            print(t[n - 2:n + 2])
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test last point is 2 + 13 + 15
        self.assertTrue(np.abs(t[-1] - 30) < emax)
        # Test intermediary points are different
        self.assertGreater(t[n], t[n - 1])
        n = len(d['engine.time'])
        d = s.run(20, log=d)
        t = d['engine.time']
        if debug:
            print(t[n - 2:n + 2])
            print(t[-2:])
            print('- ' * 10)
        # Test last point not double
        self.assertGreater(t[-1], t[-2])
        # Test last point is 2 + 13 + 15 + 20
        self.assertTrue(np.abs(t[-1] - 50) < emax)
        # Test intermediary points are different
        self.assertGreater(t[n], t[n - 1])