def estimate_time_constant_at_end(self): """Calculate the membrane time constant by fitting the voltage response with a single expontial at the end of a hyperpolarising stimulus. Returns ------- tau : membrane time constant in seconds """ # Assumes this is being done on a hyperpolarizing step v_peak, peak_index = self.voltage_deflection("min") v_baseline = self.sweep_feature("v_baseline") if self.end: start_index = ft.find_time_index(self.t, self.end) else: start_index = ft.find_time_index(self.t, 0.7) frac = 0.1 search_result = np.flatnonzero(self.v[start_index:] >= frac * (v_baseline - v_peak) + v_peak) if not search_result.size: raise ft.FeatureError("Could not find interval for time constant estimate") fit_start = self.t[search_result[0] + start_index] fit_end = self.t[-1] b, inv_tau, A = ft.fit_membrane_time_constant_at_end(self.v, self.t, fit_start, fit_end) return 1. / inv_tau
def voltage_deflection(self, deflect_type=None): """Measure deflection (min or max, between start and end if specified). Parameters ---------- deflect_type : measure minimal ('min') or maximal ('max') voltage deflection If not specified, it will check to see if the current (i) is positive or negative between start and end, then choose 'max' or 'min', respectively If the current is not defined, it will default to 'min'. Returns ------- deflect_v : peak deflect_index : index of peak deflection """ deflect_dispatch = { "min": np.argmin, "max": np.argmax, } start = self.start if not start: start = 0 start_index = ft.find_time_index(self.t, start) end = self.end - 0.1 # Let us add -0.1 because we don't expect to find a trough that close to the end of current stimulation # This actually helps us ignore cases where the voltage acts funny (i.e. drops mistakenly taken as trough) # right at current stimulation end. if not end: end = self.t[-1] end_index = ft.find_time_index(self.t, end) if deflect_type is None: if self.i is not None: halfway_index = ft.find_time_index(self.t, (end - start) / 2. + start) if self.i[halfway_index] >= 0: deflect_type = "max" else: deflect_type = "min" else: deflect_type = "min" deflect_func = deflect_dispatch[deflect_type] v_window = self.v[start_index:end_index] deflect_index = deflect_func(v_window) + start_index return self.v[deflect_index], deflect_index
def estimate_sag(self, peak_width=0.005): """Calculate the sag in a hyperpolarizing voltage response. Parameters ---------- peak_width : window width to get more robust peak estimate in sec (default 0.005) Returns ------- sag : fraction that membrane potential relaxes back to baseline sag_ratio: ratio of steady state voltage decrease to the largest voltage decrease """ t = self.t v = self.v start = self.start if not start: start = 0 end = self.end # To calculate the steady state, not the peak deflection (see code below) if not end: end = self.t[-1] v_peak, peak_index = self.voltage_deflection("min") # There was one cell with a noisy (?) peak downwards (to -250 mV) unfortunately. That's why we have the if-statement here. # You can delete this if-statement if you have normal traces. # If this all still didn't work as expected, then hopefully there are more hyperpolarisation traces for which tau can be estimated if (self.v[peak_index] < -200) : print("A DOWNWARD PEAK WAS OBSERVED GOING TO LESS THAN 200 MV!!!") # Look for another local minimum closer to stimulus onset # A spike should only last about a couple of milliseconds, so let's look a bit before the 'spike' peak_index = peak_index - (ft.find_time_index(t, 0.12) - ft.find_time_index(t, 0.1)) #print(t[peak_index]) v_peak_avg = ft.average_voltage(v, t, start=t[peak_index] - peak_width / 2., end=t[peak_index] + peak_width / 2.) v_baseline = self.sweep_feature("v_baseline") v_steady = ft.average_voltage(v, t, start=end - self.baseline_interval, end=end) #print('v_stead: ', v_steady) #print('v_baseline: ', v_baseline) #print('v_peak_avg: ', v_peak_avg) #print('denominater=v_stead-v_baseline: ', v_steady-v_baseline) #print('numerator=v_peak_avg-v_baseline: ', v_peak_avg-v_baseline) sag = (v_peak_avg - v_steady) / (v_peak_avg - v_baseline) sag_ratio = (v_peak_avg - v_baseline)/(v_steady-v_baseline) #print(sag_ratio) return sag, sag_ratio
def voltage_deflection(self, deflect_type=None): """Measure deflection (min or max, between start and end if specified). Parameters ---------- deflect_type : measure minimal ('min') or maximal ('max') voltage deflection If not specified, it will check to see if the current (i) is positive or negative between start and end, then choose 'max' or 'min', respectively If the current is not defined, it will default to 'min'. Returns ------- deflect_v : peak deflect_index : index of peak deflection """ deflect_dispatch = { "min": np.argmin, "max": np.argmax, } start = self.start if not start: start = 0 start_index = ft.find_time_index(self.t, start) end = self.end if not end: end = self.t[-1] end_index = ft.find_time_index(self.t, end) if deflect_type is None: if self.i is not None: halfway_index = ft.find_time_index(self.t, (end - start) / 2. + start) if self.i[halfway_index] >= 0: deflect_type = "max" else: deflect_type = "min" else: deflect_type = "min" deflect_func = deflect_dispatch[deflect_type] v_window = self.v[start_index:end_index] deflect_index = deflect_func(v_window) + start_index return self.v[deflect_index], deflect_index
def estimate_time_constant(self): """Calculate the membrane time constant by fitting the voltage response with a single exponential. Returns ------- tau : membrane time constant in seconds """ # Assumes this is being done on a hyperpolarizing step v_peak, peak_index = self.voltage_deflection("min") v_baseline = self.sweep_feature("v_baseline") if self.start: start_index = ft.find_time_index(self.t, self.start) else: start_index = 0 frac = 0.1 search_result = np.flatnonzero(self.v[start_index:] <= frac * (v_peak - v_baseline) + v_baseline) if not search_result.size: raise ft.FeatureError("could not find interval for time constant estimate") fit_start = self.t[search_result[0] + start_index] fit_end = self.t[peak_index] a, inv_tau, y0 = ft.fit_membrane_time_constant(self.v, self.t, fit_start, fit_end) return 1. / inv_tau
def estimate_time_constant(self): """Calculate the membrane time constant by fitting the voltage response with a single exponential. Returns ------- tau : membrane time constant in seconds """ # Assumes this is being done on a hyperpolarizing step v_peak, peak_index = self.voltage_deflection("min") v_baseline = self.sweep_feature("v_baseline") if self.start: start_index = ft.find_time_index(self.t, self.start) else: start_index = 0 frac = 0.1 search_result = np.flatnonzero(self.v[start_index:] <= frac * (v_peak - v_baseline) + v_baseline) if not search_result.size: raise ft.FeatureError("could not find interval for time constant estimate") fit_start = self.t[search_result[0] + start_index] fit_end = self.t[peak_index] # There was one cell with a noisy (?) peak downwards (to -250 mV) unfortunately. That's why we have the if-statement here. # You can delete this if-statement if you have normal traces. # If this all still didn't work as expected, then hopefully there are more hyperpolarisation traces for which tau can be estimated if (self.v[peak_index] < -200) : print("A DOWNWARD PEAK WAS OBSERVED GOING TO LESS THAN 200 MV!!!") # Look for another local minimum closer to stimulus onset # We look for a couple of milliseconds after stimulus onset to 50 ms before the downward peak end_index = (start_index + 50) + np.argmin(self.v[start_index + 50 : peak_index - 1250]) fit_end = self.t[end_index] fit_start = self.t[start_index + 50] a, inv_tau, y0 = ft.fit_membrane_time_constant(self.v, self.t, fit_start, fit_end) return 1. / inv_tau
def _short_step_stim_amp(sweep): t_index = ft.find_time_index(sweep.t, sweep.start) return sweep.i[t_index + 1:].max()