def test_range(self): # Tests :meth:`Protocol.range() p = myokit.Protocol() self.assertEqual(p.range(), (0, 0)) p = myokit.Protocol() p.schedule(2, 10, 100, 0, 0) p.schedule(3, 110, 310, 0, 0) p.schedule(1, 420, 1, 0, 0) self.assertTrue(p.is_unbroken_sequence()) self.assertEqual(p.range(), (0, 3)) p = myokit.Protocol() p.schedule(2, 0, 110, 0, 0) p.schedule(3, 110, 310, 0, 0) p.schedule(1, 420, 1, 0, 0) self.assertTrue(p.is_unbroken_sequence()) self.assertEqual(p.range(), (1, 3))
def constant(level): """ Creates a very simple protocol where the pacing variable is held constant at a given level specified by the argument ``level``. """ t = 1e9 p = myokit.Protocol() p.schedule(level, 0, t, t, 0) return p
def test_levels(self): # Tests :meth:`Protocol.levels() p = myokit.Protocol() p.schedule(2, 10, 100, 0, 0) p.schedule(3, 110, 310, 0, 0) p.schedule(1, 420, 1, 0, 0) self.assertTrue(p.is_unbroken_sequence()) self.assertEqual(p.levels(), [2, 3, 1])
def test_clone(self): # Test cloning p1 = myokit.Protocol() p1.schedule(1, 0, 100) p1.schedule(1, 100, 200, 1000, 10) p1.schedule(1, 300, 300, 2000) p2 = p1.clone() self.assertEqual(p1, p2)
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))
def test_simulation_error_1(self): # Test for simulation error detection: massive stimulus. # Silly protocol p = myokit.Protocol() p.schedule(level=1000, start=1, duration=1) self.sim.reset() self.sim.set_protocol(p) self.assertRaises(myokit.SimulationError, self.sim.run, 10) self.sim.set_protocol(self.protocol)
def test_pickling(self): # Test protocol pickling p1 = myokit.Protocol() p1.schedule(1, 0, 100) p1.schedule(1, 100, 200, 1000, 10) p1.schedule(1, 300, 300, 2000) p_bytes = pickle.dumps(p1) p2 = pickle.loads(p_bytes) self.assertEqual(p1, p2)
def _run(self): """ Runs the simulations, saves the data. """ # Create protocol e = { 'level': self._stim_level, 'start': 0, 'duration': self._stim_duration, 'period': self._clmin, 'multiplier': 0, } p = myokit.Protocol() p.schedule(**e) # Create simulation s = myokit.Simulation(self._model, p, apd_var=self._vvar) s.set_max_step_size(self._max_step_size) # Start testing c = self._clmin pcls = [] apds = [] while c < self._clmax: # Run simulation s.reset() s.pre(c * self._pre_beats) d, a = s.run(c * self._beats, log=myokit.LOG_NONE, apd_threshold=self._apd_threshold) # Save apds for apd in a['duration']: pcls.append(c) apds.append(apd) # Increase cycle length c += self._dcl # Create and set new protocol e['period'] = c p = myokit.Protocol() p.schedule(**e) s.set_protocol(p) # Store data self._data = pcls, apds
def test_cvode_floating_point_protocol_1(self): # Tests the protocol handling in a CVODE simulation, which uses the # pacing.h file shared by all C/C++ simulation code. # Create model without states 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') # Create tricky protocol p = myokit.Protocol() p.schedule(-80, 0, 1.2345) p.schedule(-70, 1.2345, 2.3454) p.schedule(-60, 3.5799, 1.4201) # Run & test s = myokit.Simulation(m, p) d = s.run(p.characteristic_time()) self.assertEqual(list(d['c.v']), [-80, -70, -60, 0]) # Test starting/stopping at difficult points p = myokit.Protocol() p.schedule(-80, 0, 1.2345) p.schedule(-70, 1.2345, 2.3454) # Interval end s = myokit.Simulation(m, p) d = s.run(3.5799) self.assertEqual(list(d['c.t']), [0, 1.2345, 3.5799]) self.assertEqual(list(d['c.v']), [-80, -70, 0]) # Interval start d = s.run(6.4201) self.assertEqual(list(d['c.t']), [3.5799, 10]) self.assertEqual(list(d['c.v']), [0, 0])
def availability_linear(vstart: float, vend: float, dv: float, vhold: float, vtest: float, tpre: float, tstep: float, twait: float, ttest: float, tpost: float = 0.) -> myokit.Protocol: """Standard availability (inactivation) protocol with linear steps.""" # Check v arguments if vend > vstart: if dv <= 0: raise ValueError('vend > vstart so dv must be strictly positive.') else: if dv >= 0: raise ValueError('vend < vstart so dv must be negative.') # Check time arguments if tpre < 0: raise ValueError('Time tpre can not be negative.') if tstep < 0: raise ValueError('Time tstep can not be negative.') if twait < 0: raise ValueError('Time tstep can not be negative.') if ttest < 0: raise ValueError('Time tpost can not be negative.') if tpost < 0: raise ValueError('Time tpost can not be negative.') # Create protocol p = myokit.Protocol() time = 0. for i in range(int(abs((vend - vstart) / dv))): if tpre > 0: p.schedule(vhold, time, tpre) time += tpre if tstep > 0: p.schedule(vstart + i * dv, time, tstep) time += tstep if twait > 0: p.schedule(vhold, time, twait) time += twait if ttest > 0: p.schedule(vtest, time, ttest) time += ttest if tpost > 0: p.schedule(vhold, time, tpost) time += tpost return p
def set_dosing_events(simulator, events): """ Parameters ---------- events list of (level, start, duration) """ myokit_protocol = myokit.Protocol() for e in events: myokit_protocol.schedule(e[0], e[1], e[2]) simulator.set_protocol(myokit_protocol)
def test_C_pacing_floats_3(self): p = myokit.Protocol() p.schedule(-80, 0, 22159.6) p.schedule(-70, 22159.6, 1340.6) p.schedule(-60, 23500.2, 6499.8) # Call log_for_interval, which uses the PacingSystem d = AnsicEventBasedPacing.log_for_interval(p, 0, 40000) # Check if the correct values are recorded self.assertEqual(d['time'], [0, 22159.6, 23500.2, 30000, 40000]) self.assertEqual(d['pace'], [-80, -70, -60, 0, 0])
def characteristic_time(self): """ Tests characteristic_time determination. """ # Singular event e = myokit.ProtocolEvent(1, 100, 0.5, 0, 0) self.assertEqual(e.characteristic_time(), 100.5) # Finite event e = myokit.ProtocolEvent(1, 100, 0.5, 1000, 3) self.assertEqual(e.characteristic_time(), 3100) # Indefinite event e = myokit.ProtocolEvent(1, 100, 0.5, 1000, 0) self.assertEqual(e.characteristic_time(), 1000) # Delayed indefinite event e = myokit.ProtocolEvent(1, 900, 200, 1000, 0) self.assertEqual(e.characteristic_time(), 1900) # Test protocols # Singular event p = myokit.Protocol() p.schedule(1, 100, 0.5, 0, 0) self.assertEqual(p.characteristic_time(), 100.5) # Finite event p = myokit.Protocol() p.schedule(1, 100, 0.5, 1000, 3) self.assertEqual(p.characteristic_time(), 3100) # Indefinite event p = myokit.Protocol() p.schedule(1, 100, 0.5, 1000, 0) self.assertEqual(p.characteristic_time(), 1000) # Delayed indefinite event p = myokit.Protocol() p.schedule(1, 800, 250, 1000, 0) self.assertEqual(p.characteristic_time(), 1800) # Sequence of singular events p = myokit.Protocol() p.schedule(1, 0, 100) p.schedule(1, 100, 200) p.schedule(1, 300, 300) self.assertEqual(p.characteristic_time(), 600)
def test_C_pacing_floats_2(self): p = myokit.Protocol() p.schedule(-80, 0, 3.3333) p.schedule(-70, 3.3333, 3.3331) p.schedule(-60, 6.6664, 3.3336) # Call log_for_interval, which uses the PacingSystem d = AnsicEventBasedPacing.log_for_interval(p, 0, 20) # Check if the correct values are recorded self.assertEqual(d['time'], [0, 3.3333, 6.6664, 10, 20]) self.assertEqual(d['pace'], [-80, -70, -60, 0, 0])
def test_log_for_interval(self): # Tests the method Protocol.log_for_interval() # Relies on PacingSystem debug = False # Test basic use + log creation methods p = myokit.Protocol() p.schedule(1, 10, 1, 1000, 0) d = p.log_for_interval(0, 3000) self.assertEqual(d.time(), [0, 10, 11, 1010, 1011, 2010, 2011, 3000]) d = p.log_for_interval(0, 2000, for_drawing=True) if debug: import matplotlib.pyplot as plt plt.figure() plt.plot(d.time(), d['pace']) plt.show() self.assertEqual(d.time(), [0, 10, 10, 11, 11, 1010, 1010, 1011, 1011, 2000]) p = myokit.Protocol() p.schedule(1, 0, 1, 1000, 0) d = p.log_for_interval(0, 3000) self.assertEqual(d.time(), [0, 1, 1000, 1001, 2000, 2001, 3000]) d = p.log_for_interval(0, 2000, for_drawing=True) if debug: import matplotlib.pyplot as plt plt.figure() plt.plot(d.time(), d['pace']) plt.show() self.assertEqual(d.time(), [0, 1, 1, 1000, 1000, 1001, 1001, 2000, 2000]) # Test bad interval call self.assertRaises(ValueError, p.log_for_interval, 100, 0) # Test deprecated alias with WarningCollector() as w: p.create_log_for_interval(0, 2000, for_drawing=True) self.assertIn('deprecated', w.text())
def test_equals(self): # Test protocol equality checking p1 = myokit.Protocol() p2 = myokit.Protocol() self.assertEqual(p1, p2) p1.schedule(1, 0, 100) self.assertNotEqual(p1, p2) p2.schedule(1, 0, 100) self.assertEqual(p1, p2) p1.schedule(1, 100, 200, 1000, 10) p1.schedule(1, 300, 300, 2000) self.assertNotEqual(p1, p2) p2.schedule(1, 100, 200, 1000, 10) p2.schedule(1, 300, 300, 2000) self.assertEqual(p1, p2) self.assertNotEqual(p1, None) self.assertNotEqual(p1, 17) self.assertNotEqual(p1, p1.code()) self.assertEqual(p1, p1)
def recovery_tpreList(twait: List[float], vhold: float, vstep1: float, vstep2: float, tpre: List[float], tstep1: float, tstep2: float, tpost: float=0.) -> myokit.Protocol: """Standard double-pulse recovery protocol.""" # Check time arguments for t in tpre: if t < 0: raise ValueError('Time tpre can not be negative.') if tstep1 < 0: raise ValueError('Time tstep can not be negative.') if tstep2 < 0: raise ValueError('Time tstep can not be negative.') if tpost < 0: raise ValueError('Time tpost can not be negative.') for t in twait: if t < 0: raise ValueError('Time twait can not be negative.') assert(len(tpre) == len(twait)) # Create protocol p = myokit.Protocol() time = 0 for i in range(len(twait)): twait_i = twait[i] tpre_i = tpre[i] if tpre_i > 0: p.schedule(vhold, time, tpre_i) time += tpre_i if tstep1 > 0: p.schedule(vstep1, time, tstep1) time += tstep1 if twait_i > 0: p.schedule(vhold, time, twait_i) time += twait_i if tstep2 > 0: p.schedule(vstep2, time, tstep2) time += tstep2 if tpost > 0: p.schedule(vhold, time, tpost) time += tpost return p
def point_list_2(self): """ Tests 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(myotest.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.Simulation(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])
def recovery(twait: List[float], vhold: float, vstep1: float, vstep2: float, tpre: float, tstep1: float, tstep2: float, vwait: float = None, tpost: float = 0.) -> myokit.Protocol: """Standard double-pulse recovery protocol.""" # Check time arguments if tpre < 0: raise ValueError('Time tpre can not be negative.') if tstep1 < 0: raise ValueError('Time tstep can not be negative.') if tstep2 < 0: raise ValueError('Time tstep can not be negative.') if tpost < 0: raise ValueError('Time tpost can not be negative.') for t in twait: if t < 0: raise ValueError('Time twait can not be negative.') if vwait is None: vwait = vhold # Create protocol p = myokit.Protocol() time = 0 for t in twait: if tpre > 0: p.schedule(vhold, time, tpre) time += tpre if tstep1 > 0: p.schedule(vstep1, time, tstep1) time += tstep1 if t > 0: p.schedule(vwait, time, t) time += t if tstep2 > 0: p.schedule(vstep2, time, tstep2) time += tstep2 if tpost > 0: p.schedule(vhold, time, tpost) time += tpost return p
def test_ending_near_protocol_end(self): # Tests ending a CVODE simulation at a point almost equal to (i.e. # indistinguishable from) an event point m = myokit.load_model('example') m.binding('pace').set_binding(None) v = m.label('membrane_potential') v.set_rhs(0) v.demote() v.set_binding('pace') p = myokit.Protocol() p.schedule(-80, 0, 15400) # This will cause an error unles handled explicitly s = myokit.Simulation(m, p) s.run(15400.000000000002)
def protocol_creation(self): """ Tests the basics of creating a protocol """ p = myokit.Protocol() self.assertIsNone(p.head()) p.schedule(1, 10, 0.5, 0, 0) f = p.head() self.assertEqual(f.level(), 1) self.assertEqual(f.start(), 10) self.assertEqual(f.duration(), 0.5) self.assertEqual(f.period(), 0) self.assertEqual(f.multiplier(), 0) # Invalid event: period is zero but multiplier is not self.assertRaises(myokit.ProtocolEventError, p.schedule, 1, 10, 0.5, 0, 10) # Add second event p.schedule(2, 1, 0.5, 0, 0) e = p.head() self.assertNotEqual(e, f) self.assertEqual(e.level(), 2) self.assertEqual(e.start(), 1) self.assertEqual(e.duration(), 0.5) self.assertEqual(e.period(), 0) self.assertEqual(e.multiplier(), 0) # Add third event p.schedule(3, 100, 0.5, 100, 100) # Invalid event: starts simultaneously def sim(p, start, duration, period=0, multiplier=0, clash=0): self.assertRaises(myokit.SimultaneousProtocolEventError, p.schedule, 2, start, duration, period, multiplier) try: p.schedule(2, start, duration, period, multiplier) except myokit.SimultaneousProtocolEventError as e: m = e.message t = m[2 + m.index('t='):-1] self.assertEqual(float(t), clash) sim(p, 1, 0.5, clash=1) sim(p, 10, 0.5, clash=10) sim(p, 100, 0.5, clash=100)
def varying_test_duration_double_pulse( vstep: float, vhold: float, vtest: float, tpre: float, tsteps: List[float], twait: float, ttest: float, tpost: float=0.) -> myokit.Protocol: """Varying duration of conditioning pulse with test pulse.""" # Check time arguments for tstep in tsteps: if tstep < 0: raise ValueError('Time tstep can not be negative.') if tpre < 0: raise ValueError('Time tpre can not be negative.') if twait < 0: raise ValueError('Time tstep can not be negative.') if ttest < 0: raise ValueError('Time tpost can not be negative.') if tpost < 0: raise ValueError('Time tpost can not be negative.') # Create protocol p = myokit.Protocol() time = 0. for tstep in tsteps: if tpre > 0: p.schedule(vhold, time, tpre) time += tpre if tstep > 0: p.schedule(vstep, time, tstep) time += tstep if twait > 0: p.schedule(vhold, time, twait) time += twait if ttest > 0: p.schedule(vtest, time, ttest) time += ttest if tpost > 0: p.schedule(vhold, time, tpost) time += tpost return p
def set_regimen(self, amount, duration=1.0E-6, start=0, period=0, multiplier=0): """ Sets the dosing regimen. The dosing regimen is set by updating the dose_rate variable in the dosing compartment to dose_rate = amount / duration and setting the regimen variable to a myokit.Protocol with the specified regimen. If a route of administration has not been set with `self.set_roa()` an error will be thrown. Arguments: amount -- Amount of injected dose. Units are specified by dose_rate. duration -- Duration of injection. Units are specfied by the global time. Keyword Arguments: start -- See myokit.Protocol documentation. (default: {0}) period -- See myokit.Protocol documentation. (default: {0}) multiplier -- See myokit.Protocol documentation. (default: {0}) """ # Check whether route of administration has been set. if not self._roa_set: raise ValueError # Set dose rate variable to amount / duration # TODO: handle ZeroDivionError and inf var = self._model.var(self._dose_rate) var.set_rhs(amount / duration) # Set regimen # TODO: check whether more efficient to clean and fill protocol self._regimen = myokit.Protocol() self._regimen.schedule(level=1, start=start, duration=duration, period=period, multiplier=multiplier)
def availability(vsteps: List[float], vhold: float, vtest: float, tpre: float, tstep: float, twait: float, ttest: float, tpost: float = 0.) -> myokit.Protocol: """Standard availability (inactivation) protocol.""" # Check time arguments if tpre < 0: raise ValueError('Time tpre can not be negative.') if tstep < 0: raise ValueError('Time tstep can not be negative.') if twait < 0: raise ValueError('Time tstep can not be negative.') if ttest < 0: raise ValueError('Time tpost can not be negative.') if tpost < 0: raise ValueError('Time tpost can not be negative.') # Create protocol p = myokit.Protocol() time = 0. for vstep in vsteps: if tpre > 0: p.schedule(vhold, time, tpre) time += tpre if tstep > 0: p.schedule(vstep, time, tstep) time += tstep if twait > 0: p.schedule(vhold, time, twait) time += twait if ttest > 0: p.schedule(vtest, time, ttest) time += ttest if tpost > 0: p.schedule(vhold, time, tpost) time += tpost return p
def test_clamp_experiment_model(self): modelname = './tests/test resources/pints_problem_def_test.mmt' # Design the clamp protocol time_max = 30 n_timepoints = 10 time_samples = np.linspace(2, time_max, n_timepoints) read_out = 'comp1.x' exp_clamped_parameter_annot = 'comp1.y' exp_clamped_parameter_values = 1 + np.sin(time_samples) p = myokit.Protocol() for i in range(len(time_samples) - 1): p.schedule(exp_clamped_parameter_values[i], time_samples[i], time_samples[i + 1] - time_samples[i]) # Save the new model and protocol if the user provided the argument # save_new_mmt_filename newmodelname = './tests/test resources/model_clamped.mmt' m = sabs_pkpd.clamp_experiment.clamp_experiment_model( modelname, exp_clamped_parameter_annot, 'engine.pace', p, newmodelname) s = sabs_pkpd.load_model.load_simulation_from_mmt(newmodelname) s.reset() # reset timer s.set_time(0) a = s.run(time_max, log_times=time_samples) output = a[read_out] expected_output = np.array([ 0.00901, 0.02621, 0.00976, 0.02642, 0.00952, 0.02661, 0.00935, 0.02676, 0.00922 ]) diff = np.linalg.norm(output - expected_output) assert diff < 0.001
def test_cvode_floating_point_protocol_3(self): # Tests the protocol handling in a CVODE simulation, which uses the # pacing.h file shared by all C/C++ simulation code. 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') p = myokit.Protocol() p.schedule(-80, 0, 22159.6) p.schedule(-70, 22159.6, 1340.6) p.schedule(-60, 23500.2, 6499.8) # Test without state variables, dynamic logging s = myokit.Simulation(m, p) d = s.run(40000) self.assertEqual(list(d['c.t']), [0, 22159.6, 23500.2, 30000, 40000]) self.assertEqual(list(d['c.v']), [-80, -70, -60, 0, 0]) # Test without state variables, fixed log times s.reset() d = s.run(40001, log_times=d['c.t']) self.assertEqual(list(d['c.t']), [0, 22159.6, 23500.2, 30000, 40000]) self.assertEqual(list(d['c.v']), [-80, -70, -60, 0, 0]) x = c.add_variable('x') x.set_rhs('cos(t)') x.promote(0) # Test with state variables, fixed log times s = myokit.Simulation(m, p) d = s.run(40001, log_times=d['c.t']) self.assertEqual(list(d['c.t']), [0, 22159.6, 23500.2, 30000, 40000]) self.assertEqual(list(d['c.v']), [-80, -70, -60, 0, 0])
def test_event_at_step_size_multiple_no_rl(self): # Test again, with event at step multiple, but now without Rush-Larsen # Load model and event with appropriate level/duration m, p, _ = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt')) e = p.head() dt = 0.01 # Note: this is too big to be very accurate tmax = 200 p = myokit.Protocol() p.schedule(level=e.level(), duration=e.duration(), period=600, start=10) logvars = ['engine.time', 'membrane.V', 'engine.pace', 'ica.ICa'] s1 = myokit.SimulationOpenCL(m, p, ncells=1, rl=False, precision=myokit.DOUBLE_PRECISION) s1.set_step_size(dt) d1 = s1.run(tmax, logvars, log_interval=dt).npview() s2 = myokit.Simulation(m, p) s2.set_tolerance(1e-8, 1e-8) d2 = s2.run(tmax, logvars, log_interval=dt).npview() # Check membrane potential (will have some error!) # Using MRMS from Marsh, Ziaratgahi, Spiteri 2012 r2 = d1['membrane.V', 0] - d2['membrane.V'] r2 /= (1 + np.abs(d2['membrane.V'])) e2 = np.sqrt(np.sum(r2**2) / len(r2)) self.assertLess(e2, 0.05) # Note: The step size is really too big here # Check logging of intermediary variables r3 = d1['ica.ICa', 0] - d2['ica.ICa'] r3 /= (1 + np.abs(d2['ica.ICa'])) e3 = np.sqrt(np.sum(r3**2) / len(r3)) self.assertLess(e3, 0.01)
def test_simultaneous_event_error(self): # Test raising of errors on rescheduled periodic events p = myokit.Protocol() p.schedule(1, 0, 1, 1000) p.schedule(1, 3000, 1) s = myokit.PacingSystem(p) t = s.next_time() self.assertEqual(t, 1) s.advance(t) t = s.next_time() self.assertEqual(t, 1000) s.advance(t) t = s.next_time() self.assertEqual(t, 1001) s.advance(t) t = s.next_time() self.assertEqual(t, 2000) with self.assertRaises(myokit.SimultaneousProtocolEventError) as e: s.advance(t) m = str(e.exception) self.assertEqual(float(m[2 + m.index('t='):-1]), 3000)