def get_latency_to_first_spike(v, t, AP_onsets, start_step, end_step):
    dt = t[1] - t[0]
    if len(AP_onsets) >= 1 and start_step < t[AP_onsets[0]] < end_step:
        AP_max_idx = get_AP_max_idx(v, AP_onsets[0], AP_onsets[0] + to_idx(2, dt))
        latency = t[AP_max_idx] - start_step

        # print 'latency: ', latency
        # pl.figure()
        # pl.plot(t, v)
        # pl.plot(t[AP_max_idx], v[AP_max_idx], 'or')
        # pl.show()
        return latency
    else:
        return None
Exemplo n.º 2
0
    def simulate(self, dt, tstop, I_ext):
        assert self.V0 is not None and self.I_l0 is not None, \
            "set V0 and I_l0 beforehand via set_simulation_params"
        assert tstop / dt % 1 == 0
        n_timesteps = int((tstop + dt) / dt)
        n_refractory = to_idx(self.dt_refractory, dt)

        V = np.zeros(n_timesteps)
        t = np.zeros(n_timesteps)
        I_l = np.zeros(n_timesteps)
        V[0] = self.V0
        I_l[0] = self.I_l0

        def f(ts, x):
            V_ = x[0]
            I_l_ = x[1]
            derivatives = self.dynamical_system_equations(V_, I_l_, I_ext(ts))
            return derivatives

        ode_solver = ode(f)
        ode_solver.set_integrator('vode', rtol=1e-8, atol=1e-8, method='bdf')
        ode_solver.set_initial_value([V[0], I_l[0]], 0)

        i = 1
        while i < n_timesteps:
            assert ode_solver.successful()
            if V[i-1] >= (self.V_threshold - self.V_rest):  # model is set up to be around 0 not V_rest
                n_refractory_tmp = n_refractory if i + n_refractory <= n_timesteps \
                    else n_timesteps - (i + n_refractory)
                V[i-1] = (self.V_peak - self.V_rest)
                V[i:i+n_refractory_tmp] = (self.V_reset - self.V_rest)
                I_l[i:i+n_refractory_tmp] = I_l[i-1]
                t[i:i+n_refractory_tmp] = np.arange(i, i+n_refractory_tmp, 1) * dt
                i += n_refractory_tmp - 1
            else:
                ode_solver.set_initial_value([V[i-1], I_l[i-1]], t[i-1])
                # force the integrator to start a new integration at each time step (account for discontinuities in I_ext)
                sol = ode_solver.integrate(t[i-1] + dt)

                V[i] = sol[0]
                t[i] = ode_solver.t
                I_l[i] = sol[1]
            i += 1
        self.I_l = I_l
        return V + self.V_rest, t
Exemplo n.º 3
0
def get_DAP_characteristics_from_v_APs(v_APs, t_AP, AP_threshold):
    DAP_maxs = init_nan(len(v_APs))
    DAP_deflections = init_nan(len(v_APs))
    dt = t_AP[1] - t_AP[0]
    for i, v in enumerate(v_APs):
        AP_max_idx = 0
        v_rest = np.min(v)
        std = np.std(v[-to_idx(2.0, dt):])
        w = np.ones(len(v)) / std
        fAHP_min_idx = get_fAHP_min_idx_using_splines(v,
                                                      t_AP,
                                                      AP_max_idx,
                                                      len(t_AP),
                                                      order=to_idx(1.0, dt),
                                                      interval=to_idx(4.0, dt),
                                                      w=w,
                                                      k=3,
                                                      s=None)
        if fAHP_min_idx is not None:
            DAP_max_idx = get_DAP_max_idx_using_splines(
                v,
                t_AP,
                int(fAHP_min_idx),
                len(t_AP),
                order=to_idx(1.0, dt),
                interval=to_idx(5.0, dt),
                min_dist_to_max=to_idx(0.5, dt),
                w=w,
                k=3,
                s=None)
            if DAP_max_idx is not None and v[DAP_max_idx] > v[fAHP_min_idx]:
                DAP_maxs[i] = v[
                    DAP_max_idx]  # TODO: get_DAP_amp(v, int(DAP_max_idx), v_rest)
                DAP_deflections[i] = get_DAP_deflection(
                    v, int(fAHP_min_idx), int(DAP_max_idx))

                # pl.figure()
                # pl.plot(t_AP, v, 'k')
                # pl.plot(t_AP[fAHP_min_idx], v[fAHP_min_idx], 'or')
                # pl.plot(t_AP[DAP_max_idx], v[DAP_max_idx], 'og')
                # pl.show()
        # else:
        #     pl.figure()
        #     pl.plot(t_AP, v, 'b')
        #     pl.show()

    return DAP_maxs, DAP_deflections
Exemplo n.º 4
0
    for cell_id in cell_ids:
        print cell_id

        # load data
        v_mat, t_mat, sweep_idxs = get_v_and_t_from_heka(
            os.path.join(data_dir, cell_id + '.dat'),
            protocol,
            return_sweep_idxs=True)
        t = t_mat[0, :]
        dt = t[1] - t[0]
        i_inj_mat = get_i_inj_from_function(protocol, sweep_idxs, t[-1],
                                            t[1] - t[0])

        check_v_at_i_inj_0_is_at_right_sweep_idx(v_mat, i_inj_mat)

        start_step_idx = to_idx(start_step, dt)
        end_step_idx = to_idx(end_step, dt)
        before_AP_idx_sta = to_idx(before_AP_STA, dt)
        after_AP_idx_sta = to_idx(after_AP_STA, dt)
        before_AP_idx_STC = to_idx(before_AP_STC, dt)
        after_AP_idx_STC = to_idx(after_AP_STC, dt)

        v_mat = v_mat[:, start_step_idx:
                      end_step_idx]  # only take v during step current
        t = t[start_step_idx:end_step_idx]

        # save and plot
        save_dir_img = os.path.join(save_dir, str(cell_id))
        if not os.path.exists(save_dir_img):
            os.makedirs(save_dir_img)
Exemplo n.º 5
0
def get_spike_characteristics(v,
                              t,
                              return_characteristics,
                              v_rest,
                              std_idx_times=(None, None),
                              AP_threshold=-10,
                              AP_interval=None,
                              AP_max_idx=None,
                              AP_onset=None,
                              AP_width_before_onset=0,
                              k_splines=None,
                              s_splines=None,
                              fAHP_interval=None,
                              order_fAHP_min=None,
                              DAP_interval=None,
                              order_DAP_max=None,
                              min_dist_to_DAP_max=None,
                              check=False):
    """
    Computes the spike characteristics defined in return_characteristics.

    :param v: Membrane Potential (must just contain one spike or set up proper intervals).
    :type v: np.array
    :param t: Time.
    :type t: np.array
    :param return_characteristics: Name of characteristics that shall be returned. Options: AP_amp, AP_width, AP_time,
                                   fAHP_amp, fAHP_min_idx, DAP_amp, DAP_deflection, DAP_width, DAP_time, DAP_time_abs,
                                   DAP_lin_slope, DAP_exp_slope.
    :type return_characteristics: list[str]
    :param AP_threshold: Threshold for detecting APs.
    :param AP_max_idx: Can be used instead of AP threshold to give the location of the AP directly. If used also need
                       to define AP_onset.
    :param: AP_onset: Just define when AP_max_idx is used otherwise it will be inferred using AP_threshold.
    :param v_rest: Resting potential.
    :type v_rest: float
    :param AP_interval: Maximal time (ms) between crossing AP threshold and AP peak.
    :type AP_interval: float
    :param fAHP_interval: Maximal time (ms) between AP peak and fAHP minimum.
    :type fAHP_interval: float
    :param std_idx_times: Time (ms) of the start and end indices for the region in which the std of v shall be estimated.
    :type std_idx_times: tuple[float, float]
    :param k_splines: Degree of the smoothing spline. Must be <= 5.
    :type k_splines: int
    :param s_splines: Positive smoothing factor used to choose the number of knots. Number of knots will be increased
        until the smoothing condition is satisfied:

            sum((w[i] * (y[i]-spl(x[i])))**2, axis=0) <= s

        If None (default), ``s = len(w)`` which should be a good value if ``1/w[i]`` is an estimate of the
        standard deviation of ``y[i]``.
        If 0, spline will interpolate through all data points.
    :type s_splines: float
    :param order_fAHP_min: Time interval (ms) to consider around the minimum for the comparison.
    :type order_fAHP_min: float
    :param DAP_interval: Maximal time (ms) between the fAHP_min and the DAP peak.
    :type DAP_interval: float
    :param order_DAP_max: Time interval (ms) to consider around the maximum for the comparison.
    :type order_DAP_max: float
    :param min_dist_to_DAP_max: 
    :param check: Whether to print and plot the computed values.
    :type check: bool
    :return: Return characteristics.
    :rtype: list[float]
    """
    dt = t[1] - t[0]

    characteristics = {k: None for k in return_characteristics}

    characteristics['v_rest'] = v_rest
    characteristics['AP_interval_idx'] = to_idx(
        AP_interval, dt) if not AP_interval is None else None
    characteristics['AP_width_before_onset_idx'] = to_idx(
        AP_width_before_onset, dt)
    characteristics['fAHP_interval_idx'] = to_idx(
        fAHP_interval, dt) if not fAHP_interval is None else None
    characteristics['std_idxs'] = [
        to_idx(std_idx_time, dt) if not std_idx_time is None else None
        for std_idx_time in std_idx_times
    ]
    characteristics['k_splines'] = k_splines if not k_splines is None else 3
    characteristics['s_splines'] = s_splines
    characteristics['order_fAHP_min_idx'] = to_idx(
        order_fAHP_min, dt) if not order_fAHP_min is None else 1
    characteristics['DAP_interval_idx'] = to_idx(
        DAP_interval, dt) if not DAP_interval is None else None
    characteristics['order_DAP_max_idx'] = to_idx(
        order_DAP_max, dt) if not order_DAP_max is None else 1
    characteristics['min_dist_to_DAP_max'] = to_idx(
        min_dist_to_DAP_max, dt) if not min_dist_to_DAP_max is None else None

    if AP_max_idx is None:
        AP_onset, AP_end = get_AP_start_end(v, AP_threshold)
        if AP_onset is None or AP_end is None:
            print 'No AP found!'
            return [characteristics[k] for k in return_characteristics]
        characteristics['AP_max_idx'] = get_AP_max_idx(
            v, AP_onset, AP_end, interval=characteristics['AP_interval_idx'])
        if characteristics['AP_max_idx'] is None:
            if check:
                check_measures(v, t, characteristics)
            return [characteristics[k] for k in return_characteristics]
    else:
        characteristics['AP_max_idx'] = AP_max_idx

    characteristics['AP_amp'] = get_AP_amp(v, characteristics['AP_max_idx'],
                                           characteristics['v_rest'])
    characteristics['AP_width_idxs'] = get_AP_width_idxs(
        v, t, AP_onset - characteristics['AP_width_before_onset_idx'],
        characteristics['AP_max_idx'],
        AP_onset + characteristics['AP_interval_idx'],
        characteristics['v_rest'])
    characteristics['AP_width'] = get_AP_width(
        v, t, AP_onset - characteristics['AP_width_before_onset_idx'],
        characteristics['AP_max_idx'],
        AP_onset + characteristics['AP_interval_idx'],
        characteristics['v_rest'])
    characteristics['AP_time'] = t[characteristics['AP_max_idx']]

    #characteristics['height_3ms_after_AP'] = v[characteristics['AP_max_idx'] + to_idx(3, dt)]

    std = np.std(
        v[characteristics['std_idxs'][0]:characteristics['std_idxs'][1]])
    w = np.ones(len(v)) / std
    characteristics['fAHP_min_idx'] = get_fAHP_min_idx_using_splines(
        v,
        t,
        characteristics['AP_max_idx'],
        len(t),
        order=characteristics['order_fAHP_min_idx'],
        interval=characteristics['fAHP_interval_idx'],
        w=w,
        k=characteristics['k_splines'],
        s=characteristics['s_splines'])
    if characteristics['fAHP_min_idx'] is None:
        if check:
            check_measures(v, t, characteristics)
        return [characteristics[k] for k in return_characteristics]
    characteristics['fAHP_amp'] = v[characteristics['fAHP_min_idx']] - v_rest
    characteristics['DAP_max_idx'] = get_DAP_max_idx_using_splines(
        v,
        t,
        int(characteristics['fAHP_min_idx']),
        len(t),
        order=characteristics['order_DAP_max_idx'],
        interval=characteristics['DAP_interval_idx'],
        min_dist_to_max=characteristics['min_dist_to_DAP_max'],
        w=w,
        k=characteristics['k_splines'],
        s=characteristics['s_splines'])
    if characteristics['DAP_max_idx'] is None:
        if check:
            check_measures(v, t, characteristics)
        return [characteristics[k] for k in return_characteristics]

    characteristics['DAP_amp'] = get_DAP_amp(
        v, int(characteristics['DAP_max_idx']), characteristics['v_rest'])
    characteristics['DAP_deflection'] = get_DAP_deflection(
        v, int(characteristics['fAHP_min_idx']),
        int(characteristics['DAP_max_idx']))
    characteristics['DAP_width_idx'] = get_DAP_width_idx(
        v, t, int(characteristics['fAHP_min_idx']),
        int(characteristics['DAP_max_idx']), len(t), characteristics['v_rest'])
    characteristics['DAP_width'] = get_DAP_width(
        v, t, int(characteristics['fAHP_min_idx']),
        int(characteristics['DAP_max_idx']), len(t), characteristics['v_rest'])
    characteristics['DAP_time'] = t[int(round(
        characteristics['DAP_max_idx']))] - t[characteristics['AP_max_idx']]
    characteristics['DAP_time_abs'] = t[int(
        round(characteristics['DAP_max_idx']))]
    characteristics['fAHP2DAP_time'] = t[int(
        round(characteristics['DAP_max_idx']))] - t[
            characteristics['fAHP_min_idx']]

    if characteristics['DAP_width_idx'] is None:
        if check:
            check_measures(v, t, characteristics)
        return [characteristics[k] for k in return_characteristics]

    characteristics['half_fAHP_crossings'] = np.nonzero(
        np.diff(
            np.sign(v[int(characteristics['DAP_max_idx']):len(t)] -
                    v[int(characteristics['fAHP_min_idx'])])) == -2)[0]
    if len(characteristics['half_fAHP_crossings']) == 0:
        if check:
            check_measures(v, t, characteristics)
        return [characteristics[k] for k in return_characteristics]

    half_fAHP_idx = characteristics['half_fAHP_crossings'][
        0] + characteristics['DAP_max_idx']
    characteristics['slope_start'] = half_fAHP_idx
    characteristics['slope_end'] = len(t) - 1
    characteristics['DAP_lin_slope'] = np.abs(
        (v[int(characteristics['slope_end'])] -
         v[int(characteristics['slope_start'])]) /
        (t[int(characteristics['slope_end'])] -
         t[int(characteristics['slope_start'])]))

    try:
        characteristics['DAP_exp_slope'] = curve_fit(
            partial(exp_fit,
                    v=v[int(characteristics['slope_start']
                            ):int(characteristics['slope_end'])]),
            np.arange(characteristics['slope_end'] -
                      int(characteristics['slope_start'])) * dt,
            v[int(characteristics['slope_start']
                  ):int(characteristics['slope_end'])],
            p0=1,
            bounds=(0, np.inf))[0][0]
    except RuntimeError:
        characteristics['DAP_exp_slope'] = None
    if check:
        check_measures(v, t, characteristics)
    return [characteristics[k] for k in return_characteristics]
def estimate_passive_parameter(v, t, i_inj):
    """
    Protocol: negative step current.
    Assumes cm = 1 uF/cm**2
    :param v: Membrane potential.
    :param t: Time.
    :param i_inj: Injected current.
    :return: c_m, r_in, tau_m, cell_area, diam, g_pas: Capacitance (pF), input resistance (MOhm),
    membrane time constant (ms), cell area (cm**2), diameter (um), passive/leak conductance (S/cm**2)
    """

    start_step = np.where(np.diff(np.abs(i_inj)) > 0)[0][0] + 1
    end_step = np.where(-np.diff(np.abs(i_inj)) > 0)[0][0]

    # fit tau
    peak_hyperpolarization = argrelmin(v[start_step:end_step],
                                       order=to_idx(
                                           5, t[1] - t[0]))[0][0] + start_step
    v_expdecay = v[start_step:peak_hyperpolarization] - v[start_step]
    t_expdecay = t[start_step:peak_hyperpolarization] - t[start_step]
    v_diff = np.abs(v_expdecay[-1] - v_expdecay[0])

    def exp_decay(t, tau):
        return v_diff * np.exp(-t / tau) - v_diff

    tau_m, _ = curve_fit(exp_decay, t_expdecay, v_expdecay)  # ms
    tau_m = tau_m[0]

    pl.figure()
    pl.plot(t, v, 'k')
    pl.plot(t_expdecay + start_step * (t[1] - t[0]),
            exp_decay(t_expdecay, tau_m) + v[0],
            'r',
            label='fitted exp. decay',
            linewidth=1.5)
    pl.legend()
    pl.xlabel('Time (ms)')
    pl.ylabel('Membrane Potential (mV)')
    pl.tight_layout()
    pl.show()

    # compute Rin
    last_fourth_i_inj = 3 / 4 * (end_step - start_step) + start_step

    v_rest = np.mean(v[0:start_step - 1])
    i_rest = np.mean(i_inj[0:start_step - 1])
    v_in = np.mean(v[last_fourth_i_inj:end_step]) - v_rest
    i_in = np.mean(i_inj[last_fourth_i_inj:end_step]) - i_rest

    r_in = v_in / i_in  # mV / nA = MOhm

    # compute capacitance
    c_m = tau_m / r_in * 1000  # ms / MOhm to pF

    # estimate cell size
    c_m_ind = 1.0 * 1e6  # pF/cm2  # from experiments
    cell_area = 1.0 / (c_m_ind / c_m)  # cm2
    diam = np.sqrt(cell_area / np.pi) * 1e4  # um

    # estimate g_pas
    g_pas = 1 / convert_unit_prefix('M', r_in) / cell_area  # S/cm2

    print 'tau: ' + str(tau_m) + ' ms'
    print 'Rin: ' + str(r_in) + ' MOhm'
    print 'c_m: ' + str(c_m) + ' pF'
    print 'cell_area: ' + str(cell_area) + ' cm2'
    print 'diam: ' + str(diam) + ' um'
    print 'g_pas: '******' S/cm2'

    return c_m, r_in, tau_m, cell_area, diam, g_pas