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
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
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
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)
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