Example #1
0
def save_all_summary_statistics(basename, ta, tr, ai, ri, iv):
    """
    Saves summary statistics to files.
    Arguments ``ta`` etc. must be tuples (v, stats).
    """
    d = myokit.DataLog()
    d['v'] = ta[0]
    d['ta'] = ta[1]
    d.save_csv(basename + '-ta.csv')

    d = myokit.DataLog()
    d['v'] = tr[0]
    d['tr'] = tr[1]
    d.save_csv(basename + '-tr.csv')

    d = myokit.DataLog()
    d['v'] = ai[0]
    d['ai'] = ai[1]
    d.save_csv(basename + '-ai.csv')

    d = myokit.DataLog()
    d['v'] = ri[0]
    d['ri'] = ri[1]
    d.save_csv(basename + '-ri.csv')

    d = myokit.DataLog()
    d['v'] = iv[0]
    d['iv'] = iv[1]
    d.save_csv(basename + '-iv.csv')
Example #2
0
    def test_from_data_log(self):
        # Test some edge cases of `DataBlock2d.from_log`.

        # Test valid construction
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = [1, 2, 3]
        d['x', 0, 0] = [0, 0, 0]
        d['x', 1, 0] = [1, 1, 2]
        d['x', 0, 1] = [1, 2, 2]
        d['x', 1, 1] = [3, 4, 5]
        d['x', 0, 2] = [6, 6, 6]
        d['x', 1, 2] = [7, 7, 2]
        myokit.DataBlock2d.from_log(d)

        # Deprecated alias
        with WarningCollector() as wc:
            myokit.DataBlock2d.from_DataLog(d)
        self.assertIn('deprecated', wc.text())

        # No time key
        d.set_time_key(None)
        self.assertRaises(ValueError, myokit.DataBlock2d.from_log, d)

        # Bad time key
        d.set_time_key('z')

        # Multi-dimensional time key
        d.set_time_key('0.0.x')
        self.assertRaises(ValueError, myokit.DataBlock2d.from_log, d)

        # 1-dimensional stuff
        d.set_time_key('time')
        myokit.DataBlock2d.from_log(d)
        d['y', 0] = [10, 10, 10]
        d['y', 1] = [20, 20, 20]
        self.assertRaises(ValueError, myokit.DataBlock2d.from_log, d)

        # Mismatched dimensions
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = [1, 2, 3]
        d['x', 0, 0] = [0, 0, 0]
        d['x', 1, 0] = [1, 1, 2]
        d['x', 0, 1] = [1, 2, 2]
        d['x', 1, 1] = [3, 4, 5]
        d['x', 0, 2] = [6, 6, 6]
        d['x', 1, 2] = [7, 7, 2]
        d['y', 0, 0] = [0, 0, 0]
        d['y', 1, 0] = [1, 1, 2]
        d['y', 0, 1] = [1, 2, 2]
        d['y', 1, 1] = [3, 4, 5]
        d['y', 0, 2] = [6, 6, 6]
        d['y', 1, 2] = [7, 7, 2]
        myokit.DataBlock2d.from_log(d)
        del (d['0.2.y'])
        del (d['1.2.y'])
        self.assertRaises(ValueError, myokit.DataBlock2d.from_log, d)
Example #3
0
    def test_cv(self):
        # Test the CV method.

        b = os.path.join(DIR_DATA, 'cv1d.zip')
        b = myokit.DataBlock1d.load(b)
        self.assertAlmostEqual(b.cv('membrane.V'), 5.95272837350686004e+01)

        # Invalid border argument
        # Negative
        self.assertRaises(ValueError, b.cv, 'membrane.V', border=-1)
        # Too large
        self.assertRaises(ValueError, b.cv, 'membrane.V', border=1000)

        # No upstroke
        time = np.linspace(0, 1, 100)
        down = np.zeros(100) - 85

        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = time
        d['x', 0] = down
        d['x', 1] = down
        d['x', 2] = down
        d['x', 3] = down
        d['x', 4] = down
        b = myokit.DataBlock1d.from_log(d)
        self.assertEqual(b.cv('x'), 0)

        # No propagation: Single-cell stimulus
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = time
        d['x', 0] = np.array(down, copy=True)
        d['x', 1] = np.array(down, copy=True)
        d['x', 2] = np.array(down, copy=True)
        d['x', 3] = np.array(down, copy=True)
        d['x', 4] = np.array(down, copy=True)
        d['x', 1][10:] = 40
        b = myokit.DataBlock1d.from_log(d)
        self.assertEqual(b.cv('x'), 0)

        # No propagation: Multi-cell stimulus
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = time
        d['x', 0] = np.array(down, copy=True)
        d['x', 1] = np.array(down, copy=True)
        d['x', 2] = np.array(down, copy=True)
        d['x', 3] = np.array(down, copy=True)
        d['x', 4] = np.array(down, copy=True)
        d['x', 1][10:] = 40
        d['x', 2][10:] = 40
        d['x', 3][10:] = 40
        b = myokit.DataBlock1d.from_log(d)
        self.assertEqual(b.cv('x'), 0)
Example #4
0
 def ratio(self):
     """
     Returns the ratios of the peak conductances (p1 / p2) for step 1 and
     step 2.
     
     The returned value is a :class:`myokit.DataLog` with entries
     corresponding to the given variable names.
     """
     # Times to wait
     twaits = np.exp(
         np.linspace(np.log(self._tmin), np.log(self._tmax), self._nt))
     # Variables to log
     log_vars = [x.qname() for x in self._vars]
     # Run simulations
     self._vvar.set_rhs(self._vhold)  # Make V a constant
     s = myokit.Simulation(self._model)
     log = myokit.DataLog()
     gvars = [x.qname() for x in self._vars]
     for g in gvars:
         log[g] = []
     log[self._tvar.qname()] = list(twaits)
     for twait in twaits:
         s.set_constant(self._vvar, self._vhold)
         s.run(self._thold, log=myokit.LOG_NONE)
         s.set_constant(self._vvar, self._vstep)
         d1 = s.run(self._tstep1, log=log_vars)
         s.set_constant(self._vvar, self._vhold)
         s.run(twait, log=myokit.LOG_NONE)
         s.set_constant(self._vvar, self._vstep)
         d2 = s.run(self._tstep2, log=log_vars)
         for g in gvars:
             ratio = np.max(d1[g])
             ratio = np.nan if ratio == 0 else np.max(d2[g]) / ratio
             log[g].append(ratio)
     return log
    def test_simple(self):
        # Test basic functionality.

        # Create test model
        m = myokit.Model('test')
        c = m.add_component('c')
        t = c.add_variable('time')
        t.set_rhs('0')
        t.set_binding('time')
        v = c.add_variable('V')
        v.set_rhs('0')
        v.promote(-80.1)
        x = c.add_variable('x')
        x.set_rhs('exp(V)')
        m.validate()

        # Create simulation log
        log = myokit.DataLog()
        log['c.time'] = np.zeros(10)
        log['c.V'] = np.linspace(-80.0, 50.0, 10)

        # Number of repeats
        repeats = 10

        # Run
        x.set_rhs('1 / (7 * exp((V + 12) / 35) + 9 * exp(-(V + 77) / 6))')
        b = myokit.RhsBenchmarker(m, [x])
        t = b.bench_full(log, repeats)
        t = b.bench_part(log, repeats)
        # No errors = pass

        # Get mean and std after outlier removal
        mean = b.mean(t)
        mean, std = b.mean_std(t)
    def log_for_interval(protocol, a, b):
        """
        Copied from PacingSystem. This is useful for testing!
        """
        # Test the input
        a, b = float(a), float(b)
        if b < a:
            raise ValueError('The argument `b` cannot be smaller than `a`')

        # Create a simulation log
        log = myokit.DataLog()
        log.set_time_key('time')
        log['time'] = time = []
        log['pace'] = pace = []

        # Create a pacing system
        p = AnsicEventBasedPacing(protocol)

        # Fill in points
        t = a
        v = p.advance(t)
        time.append(t)
        pace.append(v)
        while t < b:
            t = min(p.next_time(), b)
            v = p.advance(t)
            time.append(t)
            pace.append(v)
        return log
Example #7
0
    def create_log_for_times(self, times):
        """
        Creates a :class:`myokit.DataLog` containing the entries `time`
        and `pace` representing the value of the pacing stimulus at each point.

        The time entries ``times`` must be an non-descreasing series of
        non-negative points.
        """
        # Create empty log
        log = myokit.DataLog()
        log.set_time_key('time')
        # Times empty? Then return empty log
        if len(times) == 0:
            log['time'] = []
            log['pace'] = []
            return log
        # Test times
        times = np.asarray(times)
        dt = times[1:] - times[:-1]
        if np.any(dt < 0):
            raise ValueError('The argument `times` must contain a'
                             ' non-decreasing sequence of time points.')
        if times[0] < 0:
            raise ValueError('Times cannot be negative.')
        # Create a pacing system and calculate the values
        p = PacingSystem(self)
        # Return log
        log['time'] = list(times)
        log['pace'] = [p.advance(t) for t in times]
        return log
Example #8
0
    def test_from_log(self):
        # Test some edge cases of `DataBlock1d.from_log`.

        # Test valid construction
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = [1, 2, 3]
        d['x', 0] = [0, 0, 0]
        d['x', 1] = [1, 1, 2]
        myokit.DataBlock1d.from_log(d)

        # Deprecated alias
        with WarningCollector() as wc:
            myokit.DataBlock1d.from_DataLog(d)
        self.assertIn('deprecated', wc.text())

        # No time key
        d = myokit.DataLog()
        d['time'] = [1, 2, 3]
        d['x', 0] = [0, 0, 0]
        d['x', 1] = [1, 1, 2]
        self.assertRaises(ValueError, myokit.DataBlock1d.from_log, d)

        # Multi-dimensional time key
        d.set_time_key('0.x')
        self.assertRaises(ValueError, myokit.DataBlock1d.from_log, d)

        # 2-dimensional stuff
        d.set_time_key('time')
        myokit.DataBlock1d.from_log(d)
        d['y', 0, 0] = [10, 10, 10]
        self.assertRaises(ValueError, myokit.DataBlock1d.from_log, d)

        # Mismatched dimensions
        d = myokit.DataLog()
        d.set_time_key('time')
        d['time'] = [1, 2, 3]
        d['x', 0] = [0, 0, 0]
        d['x', 1] = [1, 1, 2]
        d['y', 0] = [2, 0, 0]
        d['y', 1] = [3, 1, 2]
        d['y', 2] = [0, 4, 5]
        self.assertRaises(ValueError, myokit.DataBlock1d.from_log, d)
 def myokit_log(self):
     """
     Returns this file's time series data as a :class:`myokit.DataLog`.
     """
     import myokit
     log = myokit.DataLog()
     if len(self._data) > 0:
         log.set_time_key(next(iter(self._data.keys())))
     for k, v in self._data.items():
         log[k] = v
     return log
Example #10
0
    def test_accessors(self):
        # Test various accessor methods of :class:`AtfFile`.

        with TemporaryDirectory() as d:
            # Create data log
            log = myokit.DataLog()
            log.set_time_key('time')
            log['time'] = np.arange(10)
            log['sint'] = np.sin(log['time'])
            log['cost'] = np.cos(log['time'])

            # Write atf file
            path = d.path('test.atf')
            axon.save_atf(log, path)

            # Read atf file
            atf = myokit.formats.axon.AtfFile(path)

            # Test filename()
            self.assertEqual(atf.filename(), path)

            # Test iter and getitem
            self.assertEqual(len(list(iter(atf))), 3)
            self.assertTrue(np.all(atf['time'] == log['time']))
            self.assertTrue(np.all(atf['sint'] == log['sint']))
            self.assertTrue(np.all(atf['cost'] == log['cost']))

            # Test items()
            items = list(atf.items())
            self.assertEqual(items[0][0], 'time')
            self.assertEqual(items[1][0], 'sint')
            self.assertEqual(items[2][0], 'cost')
            self.assertTrue(np.all(items[0][1] == log['time']))
            self.assertTrue(np.all(items[1][1] == log['sint']))
            self.assertTrue(np.all(items[2][1] == log['cost']))

            # Test keys()
            self.assertEqual(list(atf.keys()), ['time', 'sint', 'cost'])

            # Test values()
            values = list(atf.values())
            self.assertTrue(np.all(values[0] == log['time']))
            self.assertTrue(np.all(values[1] == log['sint']))
            self.assertTrue(np.all(values[2] == log['cost']))

            # Test len
            self.assertEqual(len(atf), 3)

            # Test info
            self.assertIn('myokit', atf.info())

            # Test version
            self.assertEqual(atf.version(), '1.0')
Example #11
0
    def log_for_times(self, times):
        """
        Returns a :class:`myokit.DataLog` containing the entries ``time`` and
        ``pace`` representing the value of the pacing stimulus at each point.

        The time entries ``times`` must be an non-descreasing series of
        non-negative points.
        """
        log = myokit.DataLog()
        log.set_time_key('time')
        log['time'] = times
        log['pace'] = self.value_at_times(times)
        return log
Example #12
0
    def test_bad_log(self):
        """ Test error handling when unsuitable log is used. """

        # Create test model
        m = myokit.Model('test')
        c = m.add_component('c')
        t = c.add_variable('time')
        t.set_rhs('0')
        t.set_binding('time')
        v = c.add_variable('V')
        v.set_rhs('0')
        v.promote(-80.1)
        w = c.add_variable('W')
        w.set_rhs(0)
        w.promote(10)
        x = c.add_variable('x')
        x.set_rhs('exp(V) + W')
        m.validate()

        # Create benchmarker
        b = myokit.RhsBenchmarker(m, [x])

        # Missing state variable
        d = myokit.DataLog()
        d['c.time'] = np.zeros(10)
        #d['c.V'] = np.linspace(-80.0, 50.0, 10)
        d['c.W'] = np.linspace(0.0, 10.0, 10)
        self.assertRaisesRegex(
            ValueError, 'State variable <c.V> not found', b.bench_full, d, 1)

        # Different size log entries
        d = myokit.DataLog()
        d['c.time'] = np.zeros(1000)
        d['c.V'] = np.linspace(-80.0, 50.0, 10)
        d['c.W'] = np.linspace(0.0, 10.0, 11)
        self.assertRaisesRegex(
            ValueError, 'same length', b.bench_full, d, 1)
Example #13
0
 def log(self):
     """
     Returns a myokit DataLog containing the data currently displayed in the
     graph area.
     """
     d = myokit.DataLog()
     if self._data:
         d['engine.time'] = self._data.time()
         for index in self._frozen.iterkeys():
             x, y, variable = index
             d[variable, x, y] = self._data.trace(variable, x, y)
         if self._temp_index:
             x, y, variable = self._temp_index
             d[variable, x, y] = self._data.trace(variable, x, y)
     return d
Example #14
0
    def log_for_interval(self, a, b, for_drawing=False):
        """
        Returns a :class:`myokit.DataLog` containing the entries ``time`` and
        ``pace``, representing the value of the pacing stimulus at each  point
        on the interval ``[a, b]``.

        The time points in the log will be ``a`` and ``b``, and any time in
        between at which the pacing value changes.

        If ``for_drawing`` is set to ``True`` each time value where the
        protocol changes will be listed twice, so that a vertical line can be
        drawn from the old to the new pacing value.

        Note that the points returned are from ``a`` to ``b`` inclusive (the
        interval ``[a, b]``), and so if ``b`` coincides with the end of the
        protocol a point ``(b, 0)`` will be included in the output (protocol
        steps are defined as half-open, so include their starting point but not
        their end point).
        """
        # Test the input
        a, b = float(a), float(b)
        if b < a:
            raise ValueError('The argument `b` cannot be smaller than `a`')

        # Create a simulation log
        log = myokit.DataLog()
        log.set_time_key('time')
        log['time'] = time = []
        log['pace'] = pace = []

        # Create a pacing system
        p = PacingSystem(self)

        # Fill in points
        t = a
        v = p.advance(t)
        time.append(t)
        pace.append(v)
        while t < b:
            t = min(p.next_time(), b)
            w = p.advance(t)
            if for_drawing and v != w:
                time.append(t)
                pace.append(v)
            v = w
            time.append(t)
            pace.append(v)
        return log
Example #15
0
    def myokit_log(self):
        """
        Creates and returns a:class:`myokit.DataLog` containing all the
        data from this file.

        Each channel is stored under its own name, with an indice indicating
        the record it was from. Time is stored under ``time``.
        """
        log = myokit.DataLog()
        log.set_time_key('time')
        log['time'] = np.array(self._time)
        for i, record in enumerate(self._records):
            for j, data in enumerate(record):
                name = self._channel_names[j]
                log[name, i] = np.array(data)
        return log
Example #16
0
    def simulate(self, parameters):

        # Transform parameters back to model space
        parameters = self.transformation.detransform(parameters)

        # Run all simulations
        logs = [0] * 4
        for i, s in enumerate(self.simulations):

            # Reset simulation
            s.reset()

            # Update simulation parameters
            s.set_parameters(parameters)

            # Run simulation
            t = self.times[i]
            try:
                d = s.run(t[-1] + 0.1, log_times=t).npview()
            except myokit.SimulationError:
                return float('inf')

            # Store in same format as experimental data
            e = myokit.DataLog()
            e.set_time_key('time')
            e['time'] = d['engine.time']
            e['current'] = d['ikr.IKr']
            logs[i] = e

        # Calculate summary statistics
        try:
            stats = sumstat.all_summary_statistics(self.cell,
                                                   pr2_log=logs[0],
                                                   pr3_log=logs[1],
                                                   pr4_log=logs[2],
                                                   pr5_log=logs[3])
        except Exception:
            import traceback
            e = traceback.format_exc()
            if 'Optimal parameters not found' not in e:
                print(e)
            return None

        return stats[0][1], stats[1][1], stats[2][1], stats[3][1], stats[4][1]
Example #17
0
 def run(self):
     """
     Returns a :class:`DataLog` containing the tested cycle lengths as
     ``cl`` and the measured action potential durations as ``apd``. The
     diastolic intervals are given as ``di``.
     
     Each cycle length is repeated ``beats`` number of times, where
     ``beats`` is the number of beats specified in the constructor.
     """
     # Run
     if self._data is None:
         self._run()
     # Get data
     cl, apd = self._data
     d = myokit.DataLog()
     d['cl'] = list(cl)
     d['apd'] = list(apd)
     d['di'] = list(np.array(cl, copy=False) - np.array(apd, copy=False))
     return d
Example #18
0
 def peaks(self, normalize=False):
     """
     Returns a :class:`myokit.DataLog` containing the tested step
     voltages and the peak values of the logged variable(s).
     
     The names used in the simulation log correspond to those used in the
     model. For example, when doing an experiment on a Sodium channel the
     simulation log might have entries ``membrane.v`` and ``ina.g`` where
     ``membrane.v`` contains the used voltage steps while ``ina.g`` contains
     the peak values measured at those voltages.
     
     If ``normalize`` is set to ``True``, the peak data returned will be
     normalized by dividing all values by the largest (most positive) peak
     in the list. If no positive, non-zero values are found no normalization
     will be applied.
     
     If any conversion factor was specified the data will be converted
     before normalization.
     """
     # Run simulation if needed
     if self._logs is None:
         self._run()
     # Create a copy of the voltage steps
     v = np.array(self._steps, copy=True)
     # Create a simulation log
     d = myokit.DataLog()
     d[self._vvar] = v
     # Factor
     factor = self._factor if self._factor is not None else 1
     # Find the peaks
     for var in self._vars:
         peaks = np.zeros(len(v))
         for k, log in enumerate(self._logs):
             peaks[k] = log[var][np.argmax(np.abs(log[var]))]
         d[var] = peaks * factor
     # Normalize (only if log contains positive values)
     if normalize:
         for var in self._vars:
             x = d[var]
             m = np.max(x)
             if m > 0:
                 d[var] = x / m
     return d
Example #19
0
def load_base_aps(force=False):
    """
    Loads the baseline APs from the optical mapping data.
    """
    cachefile = os.path.join(methods.RESULTS, 'exp-aps-base.csv')
    if not force and os.path.isfile(cachefile):
        print('Using cached baseline optical APs')
        log = myokit.DataLog.load_csv(cachefile).npview()
        time = log.time()
        aps = [log['ap', i] for i in xrange(len(log) - 1)]
        return time, np.array(aps)

    print('Collecting baseline optical APs!')
    files = glob.glob('optical/Group */Well*.csv')
    aps = []
    log = myokit.DataLog()
    log.set_time_key('time')
    for i, filename in enumerate(files):
        data = np.loadtxt(filename, delimiter=',')

        # Split into time and voltage
        t = data[:, 0] * 1000
        v = data[:, 1]

        # Normalise
        filename = os.path.join(AP_FIGURES, 'exp-base-' + str(i + 1) + '.png')
        t, v = normalise(t, v, filename=filename, correct_time=True)

        # Select bit that's present in all traces
        imin = np.where(t >= 0)[0][0]
        imax = np.where(t >= 575)[0][0]
        t = t[imin:imax]
        v = v[imin:imax]

        # Store
        aps.append(v)
        log['ap', i] = v

    # Store and return
    log['time'] = t
    log.save_csv(cachefile)
    return t, np.array(aps)
Example #20
0
 def times(self):
     """
     Returns a :class:`myokit.DataLog` containing the time-to-peak for
     each logged variable at each voltage step.
     """
     # Run simulation if needed
     if self._logs is None:
         self._run()
     # Create a copy of the voltage steps
     v = np.array(self._steps, copy=True)
     # Create a simulation log
     d = myokit.DataLog()
     d[self._vvar] = v
     # Find the peaks
     for var in self._vars:
         times = np.zeros(len(v))
         for k, log in enumerate(self._logs):
             times[k] = log[self._tvar][np.argmax(np.abs(log[var]))]
         d[var] = times
     return d
Example #21
0
    def create_log_for_interval(self, a, b, for_drawing=False):
        """
        Creates a :class:`myokit.DataLog` containing the entries `time`
        and `pace` representing the value of the pacing stimulus at each point.

        The time points in the log will be on the interval ``[a, b]``, such
        that every time at which the pacing value changes is present in the
        log.

        If ``for_drawing`` is set to ``True`` each time value between ``a`` and
        ``b`` will be listed twice, so that a vertical line can be drawn from
        the old to the new pacing value.
        """
        # Test the input
        a, b = float(a), float(b)
        if b < a:
            raise ValueError('The argument `b` cannot be smaller than `a`')
        # Create a simulation log
        log = myokit.DataLog()
        log.set_time_key('time')
        log['time'] = time = []
        log['pace'] = pace = []
        # Create a pacing system
        p = PacingSystem(self)
        # Fill in points
        t = a
        v = p.advance(t, max_time=b)
        time.append(t)
        pace.append(v)
        while t < b:
            t = p.next_time()
            if for_drawing:
                if t != b:
                    time.append(t)
                    pace.append(v)
            v = p.advance(t, max_time=b)
            time.append(t)
            pace.append(v)
        return log
Example #22
0
def calculate_base_apds(time, aps, pt=0.1, force=False):
    """
    Calculates APDs for baseline optical experiments.
    """
    cachefile = os.path.join(methods.RESULTS,
                             'exp-apds-base-' + str(pt) + '.csv')
    if not force and os.path.isfile(cachefile):
        print('Using cached baseline optical APDs')
        log = myokit.DataLog.load_csv(cachefile).npview()
        return log['apds']

    print('Collecting baseline optical APDs!')
    apds = []
    for i, ap in enumerate(aps):
        filename = os.path.join(APD_FIGURES, 'exp-base-' + str(i) + '.png')
        apds.append(calculate_apd(time, ap, pt, filename=filename)[0])
    apds = np.array(apds)

    # Store and return
    log = myokit.DataLog()
    log['apds'] = apds
    log.save_csv(cachefile)
    return apds
Example #23
0
 def traces(self):
     """
     Returns the logged traces for each variable as an ordered list of
     tuples ``(v, DataLog)``.
     
     If any conversion factor was specified the data will be converted
     before returning.
     """
     if self._logs is None:
         self._run()
     data = []
     steps = iter(self._steps)
     factor = self._factor
     if factor is None:
         factor = np.ones(len(self._steps))
     for k, log in enumerate(self._logs):
         v = steps.next()
         d = myokit.DataLog()
         for var in self._vars:
             d[var] = np.array(log[var]) * factor[k]
             d[self._tvar] = log[self._tvar]
         data.append((v, d))
     return data
Example #24
0
    def test_block(self):
        # Test :meth:`PSimulation.block()`.

        m, p, x = myokit.load(os.path.join(DIR_DATA, 'lr-1991.mmt'))
        with WarningCollector() as c:
            s = myokit.PSimulation(m,
                                   p,
                                   variables=['membrane.V'],
                                   parameters=['ina.gNa', 'ica.gCa'])
        s.set_step_size(0.002)
        d, dp = s.run(10, log_interval=2)

        b = s.block(d, dp)
        self.assertIsInstance(b, myokit.DataBlock2d)
        self.assertEqual(b.len0d(), len(d) - 1)
        self.assertTrue(np.all(b.time() == d.time()))

        # Log without time
        e = myokit.DataLog(d)
        del (e[e.time_key()])
        self.assertRaisesRegex(ValueError, 'must contain', s.block, e, dp)

        # Wrong size derivatives array
        self.assertRaisesRegex(ValueError, 'shape', s.block, d, dp[:, :-1])
def load_outward_peaks(force=False):
    """
    Loads the peak outward current per cell.
    """
    # Return cached version
    cachefile = os.path.join(methods.RESULTS, 'exp-peaks.csv')
    if not force and os.path.isfile(cachefile):
        print('Using cached peak outward current data!')
        log = myokit.DataLog.load_csv(cachefile).npview()
        return log['peaks']
    print('Gathering peak outward current data!')

    peaks = []
    for i, long_id in enumerate(ORDER):
        t, v = load(i)
        peaks.append(np.max(v))

    # Store
    log = myokit.DataLog()
    log['peaks'] = peaks
    log.save_csv(cachefile)

    # Return
    return peaks
Example #26
0
def calculate_tailored_apds(time, aps, pt=0.1, force=False):
    """
    Calculates the tailored simulation aps using the results from
    :meth:`normalise_tailored_simulations`.
    """
    cachefile = os.path.join(methods.RESULTS,
                             'sim-base-apds-' + str(pt) + '.csv')
    if not force and os.path.isfile(cachefile):
        print('Using cached baseline tailored APDs')
        log = myokit.DataLog.load_csv(cachefile).npview()
        return log['apds']

    print('Collecting baseline tailored APDs!')
    apds = []
    for i, long_id in enumerate(outward.ORDER):
        filename = os.path.join(APD_FIGURES, 'sim-base-' + long_id + '.png')
        apds.append(calculate_apd(time, aps[i], pt, filename=filename)[0])
    apds = np.array(apds)

    # Store and return
    log = myokit.DataLog()
    log['apds'] = apds
    log.save_csv(cachefile)
    return apds
Example #27
0
 def run_simple(self):
     # Create test model
     m = myokit.Model('test')
     c = m.add_component('c')
     t = c.add_variable('time')
     t.set_rhs('0')
     t.set_binding('time')
     v = c.add_variable('V')
     v.set_rhs('0')
     v.promote(-80.1)
     x = c.add_variable('x')
     x.set_rhs('exp(V)')
     m.validate()
     # Create simulation log
     log = myokit.DataLog()
     log['c.time'] = np.zeros(1000)
     log['c.V'] = np.linspace(-80.0, 50.0, 10)
     # Number of repeats
     repeats = 10
     # Run
     x.set_rhs('1 / (7 * exp((V + 12) / 35) + 9 * exp(-(V + 77) / 6))')
     b = myokit.RhsBenchmarker(m, [x])
     t = b.bench_full(log, repeats)
     t = b.bench_part(log, repeats)
Example #28
0
 def current(self, parameter, voltage, times):
     """
     Generate current of voltage clamp using the given scalings.
     - Not fitting on this, so voltage resolution is not as important.
     - Not running this often, so can setup everything here...
     """
     parameter = np.array(parameter)
     # Update model parameters
     if self.transform is not None:
         parameter = self.transform(parameter)
     model = myokit.load_model(self._model_file)
     # Simulate with modified model
     for i, name in enumerate(self._conductance):
         '''
         # normal way of doing it...
         self.simulation.set_constant(name, 
                                      parameter[i] * self.original[i])
         '''
         # try to set conductance for non-literal...
         model.get(name).set_rhs(
             parameter[i] * self.original[i]
         #'''
         )
     # Get current names of output
     current = []
     m_cur = model_current[self._model_file_name]
     for name in self.parameters:
         current.append(m_cur[name])
     # Set up voltage clamp
     #for ion_var, ion_conc in model_ion[self._model_file_name]:
     #    self._fix_concentration(model, ion_var, ion_conc)
     # Detach voltage for voltage clamp(?)
     model_v = model.get('membrane.V')
     model_v.demote()
     tmp_vhold = vhold
     model_v.set_rhs(tmp_vhold)
     model.get('engine.pace').set_binding(None)
     model_v.set_binding('pace')
     
     # Create pre-pacing protocol
     
     protocol = pacing.constant(tmp_vhold)
     # Create pre-pacing simulation
     simulation1 = myokit.Simulation(model, protocol)
     simulation2 = myokit.Simulation(model)
     simulation2.set_fixed_form_protocol(
         times, 
         voltage
     )
     simulation2.set_tolerance(1e-8, 1e-10)
     simulation2.set_max_step_size(1e-2)  # ms
     # Run
     simulation1.reset()
     simulation2.reset()
     simulation1.set_state(self.original_state)
     simulation1.pre(100)
     simulation2.set_state(simulation1.state())
     # Log some beats
     d = simulation2.run(np.max(times)+0.02, 
         log_times = times, 
         log = current,
         ).npview()
     # rename output names
     d_out = myokit.DataLog()
     for s, c in m_cur.iteritems():
         if s in self.parameters:
             d_out[s[:-2]] = d[c]
     del(d)
     return d_out
Example #29
0
 def _run(self, duration, log, log_interval, apd_threshold, progress, msg):
     # Reset error state
     self._error_state = None
     # Simulation times
     if duration < 0:
         raise Exception('Simulation time can\'t be negative.')
     tmin = self._time
     tmax = tmin + duration
     # Parse log argument
     log = myokit.prepare_log(log, self._model, if_empty=myokit.LOG_ALL)
     # Logging period (0 = disabled)
     log_interval = 0 if log_interval is None else float(log_interval)
     if log_interval < 0:
         log_interval = 0
     # Threshold for APD measurement
     root_list = None
     root_threshold = 0
     if apd_threshold is not None:
         if self._apd_var is None:
             raise ValueError('Threshold given but Simulation object was'
                              ' created without apd_var argument.')
         else:
             root_list = []
             root_threshold = float(apd_threshold)
     # Get progress indication function (if any)
     if progress is None:
         progress = myokit._Simulation_progress
     if progress:
         if not isinstance(progress, myokit.ProgressReporter):
             raise ValueError(
                 'The argument "progress" must be either a'
                 ' subclass of myokit.ProgressReporter or None.')
     # Determine benchmarking mode, create time() function if needed
     if self._model.binding('realtime') is not None:
         import timeit
         bench = timeit.default_timer
     else:
         bench = None
     # Run simulation
     with myokit.SubCapture():
         arithmetic_error = None
         if duration > 0:
             # Initialize
             state = [0] * len(self._state)
             bound = [0, 0, 0, 0]  # time, pace, realtime, evaluations
             self._sim.sim_init(
                 tmin,
                 tmax,
                 list(self._state),
                 state,
                 bound,
                 self._protocol,
                 self._fixed_form_protocol,
                 log,
                 log_interval,
                 root_list,
                 root_threshold,
                 bench,
             )
             t = tmin
             try:
                 if progress:
                     # Loop with feedback
                     with progress.job(msg):
                         r = 1.0 / duration if duration != 0 else 1
                         while t < tmax:
                             t = self._sim.sim_step()
                             if not progress.update(min((t - tmin) * r, 1)):
                                 raise myokit.SimulationCancelledError()
                 else:
                     # Loop without feedback
                     while t < tmax:
                         t = self._sim.sim_step()
             except ArithmeticError as ea:
                 self._error_state = list(state)
                 txt = [
                     'A numerical error occurred during simulation at'
                     ' t = ' + str(t) + '.', 'Last reached state: '
                 ]
                 txt.extend([
                     '  ' + x
                     for x in self._model.format_state(state).splitlines()
                 ])
                 txt.append('Inputs for binding: ')
                 txt.append('  time        = ' + myokit.strfloat(bound[0]))
                 txt.append('  pace        = ' + myokit.strfloat(bound[1]))
                 txt.append('  realtime    = ' + myokit.strfloat(bound[2]))
                 txt.append('  evaluations = ' + myokit.strfloat(bound[3]))
                 try:
                     self._model.eval_state_derivatives(state)
                 except myokit.NumericalError as en:
                     txt.append(en.message)
                 raise myokit.SimulationError('\n'.join(txt))
             except Exception as e:
                 # Store error state
                 self._error_state = list(state)
                 # Check for zero-step error
                 if e.message[0:9] == 'ZERO_STEP':
                     time = float(e.message[10:])
                     raise myokit.SimulationError('Too many failed steps at'
                                                  ' t=' + str(time))
                 # Unhandled exception: re-raise!
                 raise
             finally:
                 # Clean even after KeyboardInterrupt or other Exception
                 self._sim.sim_clean()
             # Update internal state
             self._state = state
     # Return
     if root_list is not None:
         # Calculate apds and return (log, apds)
         st = []
         dr = []
         if root_list:
             roots = iter(root_list)
             time, direction = roots.next()
             tlast = time if direction > 0 else None
             for time, direction in roots:
                 if direction > 0:
                     tlast = time
                 else:
                     st.append(tlast)
                     dr.append(time - tlast)
         apds = myokit.DataLog()
         apds['start'] = st
         apds['duration'] = dr
         return log, apds
     else:
         # Return log
         return log
Example #30
0
    def run(self, duration, log=None, log_interval=0.01, log_times=None):
        """
        Runs a simulation for ``duration`` time units.

        After the simulation:

        - The simulation time will be increased by ``duration`` time units.
        - The simulation state will be updated to the last reached state.

        Arguments:

        ``duration``
            The number of time units to simulate.
        ``log``
            A log from a previous run can be passed in, in which case the
            results will be appended to this one.
        ``log_interval``
            The time between logged points.
        ``log_times``
            A pre-defined sequence of times to log at. If set, ``log_interval``
            will be ignored.

        Returns a :class:`myokit.DataLog` with the simulation results.
        """
        # Check arguments
        duration = float(duration)
        if duration < 0:
            raise ValueError('Duration must be non-negative.')
        log_interval = float(log_interval)
        if log_interval <= 0:
            raise ValueError('Log interval must be greater than zero.')

        # Check log_times
        if log_times is None:
            log_times = self._time + np.arange(0, duration, log_interval)

        # Set up logging
        if log is None:

            # Create new log
            log = myokit.DataLog()
            log.set_time_key(self._time_key)
            for key in self._log_keys:
                log[key] = np.zeros(log_times.shape)
            offset = 0

        else:

            # Check existing log
            if len(log.keys()) > len(self._log_keys):
                raise ValueError('Invalid log: contains extra keys.')
            try:
                key = self._time_key  # Note: error msg below uses `key`
                offset = len(log[key])
                for key in self._log_keys:
                    log[key] = np.concatenate(
                        (log[key], np.zeros(log_times.shape)))
            except KeyError:
                raise ValueError('Invalid log: missing entry for <' +
                                 str(key) + '>.')

        # Run simulation
        if self._protocol is None:

            # User defined membrane potential
            self._run(log, log_times, self._time + duration, offset)

        else:

            # Voltage clamp
            tfinal = self._time + duration
            while self._time < tfinal:
                # Run simulation
                tnext = min(tfinal, self._pacing.next_time())
                times = log_times[np.logical_and(log_times >= self._time,
                                                 log_times < tnext)]
                self._run(log, times, tnext, offset)
                offset += len(times)

                # Update pacing
                self._membrane_potential = self._pacing.advance(tnext)

        # Return
        return log