def validate_sweeps(data_set, sweep_numbers, extra_dur=0.2): check_sweeps = data_set.sweep_set(sweep_numbers) valid_sweep_stim = [] start = None dur = None for swp in check_sweeps.sweeps: swp_start, swp_dur, _, _, _ = stf.get_stim_characteristics( swp.i, swp.t, False) if swp_start is None: valid_sweep_stim.append(False) else: start = swp_start dur = swp_dur valid_sweep_stim.append(True) if start is None: # Could not find any sweeps to define stimulus interval return [], None, None end = start + dur # Check that all sweeps are long enough and not ended early good_sweep_numbers = [ n for n, s, v in zip(sweep_numbers, check_sweeps.sweeps, valid_sweep_stim) if s.t[-1] >= end + extra_dur and v is True and not np.all( s.v[tsu.find_time_index(s.t, end) - 100:tsu.find_time_index(s.t, end)] == 0) ] return good_sweep_numbers, start, end
def chirp_amp_phase(v, i, t, start=0.78089, end=49.21, down_rate=20000.0, min_freq=0.1, max_freq=19.5): """ Calculate amplitude and phase of chirp responses Parameters ---------- sweep_set: SweepSet Set of chirp sweeps start: float (optional, default 0.6) Start of chirp stimulus in seconds end: float (optional, default 20.6) End of chirp stimulus in seconds down_rate: int (optional, default 2000) Sampling rate for downsampling before FFT min_freq: float (optional, default 0.2) Minimum frequency for output to contain max_freq: float (optional, default 40) Maximum frequency for output to contain Returns ------- amplitude: array Aka resistance phase: array Aka reactance freq: array Frequencies for amplitude and phase results """ ds_v, ds_i, ds_t = v, i, t start_index = tsu.find_time_index(ds_t, start) end_index = tsu.find_time_index(ds_t, end) N = len(ds_v[start_index:end_index]) T = ds_t[1] - ds_t[0] xf = np.linspace(0.0, 1.0 / (2.0 * T), N // 2) v_fft = fftpack.fft(ds_v[start_index:end_index]) i_fft = fftpack.fft(ds_i[start_index:end_index]) Z = v_fft / i_fft R = np.real(Z) X = np.imag(Z) resistance = np.abs(Z)[0:N // 2] reactance = np.arctan(X / R)[0:N // 2] low_ind = tsu.find_time_index(xf, min_freq) high_ind = tsu.find_time_index(xf, max_freq) return resistance[low_ind:high_ind], reactance[low_ind:high_ind], xf[ low_ind:high_ind]
def test_find_time_out_of_bounds(): t = np.array([0, 1, 2]) t_0 = 4 with pytest.raises(AssertionError): tsu.find_time_index(t, t_0)
def chirp_amp_phase(v, i, t, start=0.78089, end=49.21, down_rate=20000.0, min_freq=0.1, max_freq=19.5): """ Calculate amplitude and phase of chirp responses Parameters ---------- sweep_set: SweepSet Set of chirp sweeps start: float (optional, default 0.6) Start of chirp stimulus in seconds end: float (optional, default 20.6) End of chirp stimulus in seconds down_rate: int (optional, default 2000) Sampling rate for downsampling before FFT min_freq: float (optional, default 0.2) Minimum frequency for output to contain max_freq: float (optional, default 40) Maximum frequency for output to contain Returns ------- amplitude: array Aka resistance phase: array Aka reactance freq: array Frequencies for amplitude and phase results """ v_list = v i_list = i avg_v = np.vstack(v_list).mean(axis=0) avg_i = np.vstack(i_list).mean(axis=0) #plt.plot(t, avg_v) # #plt.plot(t, avg_i) current_rate = np.rint(1 / (t[1] - t[0])) if current_rate > down_rate: width = int(current_rate / down_rate) ds_v = ds_v = fv._subsample_average(avg_v, width) ds_i = fv._subsample_average(avg_i, width) ds_t = t[::width] else: ds_v = avg_v ds_i = avg_i ds_t = t start_index = tsu.find_time_index(ds_t, start) end_index = tsu.find_time_index(ds_t, end) N = len(ds_v[start_index:end_index]) T = ds_t[1] - ds_t[0] xf = np.linspace(0.0, 1.0 / (2.0 * T), N // 2) v_fft = fftpack.fft(ds_v[start_index:end_index]) i_fft = fftpack.fft(ds_i[start_index:end_index]) Z = v_fft / i_fft R = np.real(Z) X = np.imag(Z) resistance = np.abs(Z)[0:N // 2] reactance = np.arctan(X / R)[0:N // 2] low_ind = tsu.find_time_index(xf, min_freq) high_ind = tsu.find_time_index(xf, max_freq) v2 = R[0:N // 2] return resistance[low_ind:high_ind], reactance[low_ind:high_ind], xf[ low_ind:high_ind], v2[low_ind:high_ind]
def extract_features(data_set, ramp_sweep_numbers, ssq_sweep_numbers, lsq_sweep_numbers, amp_interval=20, max_above_rheo=100): features = {} # RAMP FEATURES ----------------- if len(ramp_sweep_numbers) > 0: ramp_sweeps = data_set.sweep_set(ramp_sweep_numbers) ramp_start, ramp_dur, _, _, _ = stf.get_stim_characteristics(ramp_sweeps.sweeps[0].i, ramp_sweeps.sweeps[0].t) ramp_spx, ramp_spfx = dsf.extractors_for_sweeps(ramp_sweeps, start = ramp_start, **dsf.detection_parameters(data_set.RAMP)) ramp_an = spa.RampAnalysis(ramp_spx, ramp_spfx) basic_ramp_features = ramp_an.analyze(ramp_sweeps) first_spike_ramp_features = first_spike_ramp(ramp_an) features.update(first_spike_ramp_features) # SHORT SQUARE FEATURES ----------------- if len(ssq_sweep_numbers) > 0: ssq_sweeps = data_set.sweep_set(ssq_sweep_numbers) ssq_start, ssq_dur, _, _, _ = stf.get_stim_characteristics(ssq_sweeps.sweeps[0].i, ssq_sweeps.sweeps[0].t) ssq_spx, ssq_spfx = dsf.extractors_for_sweeps(ssq_sweeps, est_window = [ssq_start, ssq_start+0.001], **dsf.detection_parameters(data_set.SHORT_SQUARE)) ssq_an = spa.ShortSquareAnalysis(ssq_spx, ssq_spfx) basic_ssq_features = ssq_an.analyze(ssq_sweeps) first_spike_ssq_features = first_spike_ssq(ssq_an) first_spike_ssq_features["short_square_current"] = basic_ssq_features["stimulus_amplitude"] features.update(first_spike_ssq_features) # LONG SQUARE SUBTHRESHOLD FEATURES ----------------- if len(lsq_sweep_numbers) > 0: check_lsq_sweeps = data_set.sweep_set(lsq_sweep_numbers) lsq_start, lsq_dur, _, _, _ = stf.get_stim_characteristics(check_lsq_sweeps.sweeps[0].i, check_lsq_sweeps.sweeps[0].t) # Check that all sweeps are long enough and not ended early extra_dur = 0.2 good_lsq_sweep_numbers = [n for n, s in zip(lsq_sweep_numbers, check_lsq_sweeps.sweeps) if s.t[-1] >= lsq_start + lsq_dur + extra_dur and not np.all(s.v[tsu.find_time_index(s.t, lsq_start + lsq_dur)-100:tsu.find_time_index(s.t, lsq_start + lsq_dur)] == 0)] lsq_sweeps = data_set.sweep_set(good_lsq_sweep_numbers) lsq_spx, lsq_spfx = dsf.extractors_for_sweeps(lsq_sweeps, start = lsq_start, end = lsq_start + lsq_dur, **dsf.detection_parameters(data_set.LONG_SQUARE)) lsq_an = spa.LongSquareAnalysis(lsq_spx, lsq_spfx, subthresh_min_amp=-100.) basic_lsq_features = lsq_an.analyze(lsq_sweeps) features.update({ "input_resistance": basic_lsq_features["input_resistance"], "tau": basic_lsq_features["tau"], "v_baseline": basic_lsq_features["v_baseline"], "sag_nearest_minus_100": basic_lsq_features["sag"], "sag_measured_at": basic_lsq_features["vm_for_sag"], "rheobase_i": int(basic_lsq_features["rheobase_i"]), "fi_linear_fit_slope": basic_lsq_features["fi_fit_slope"], }) # TODO (maybe): port sag_from_ri code over # Identify suprathreshold set for analysis sweep_table = basic_lsq_features["spiking_sweeps"] mask_supra = sweep_table["stim_amp"] >= basic_lsq_features["rheobase_i"] sweep_indexes = fv._consolidated_long_square_indexes(sweep_table.loc[mask_supra, :]) amps = np.rint(sweep_table.loc[sweep_indexes, "stim_amp"].values - basic_lsq_features["rheobase_i"]) spike_data = np.array(basic_lsq_features["spikes_set"]) for amp, swp_ind in zip(amps, sweep_indexes): if (amp % amp_interval != 0) or (amp > max_above_rheo) or (amp < 0): continue amp_label = int(amp / amp_interval) first_spike_lsq_sweep_features = first_spike_lsq(spike_data[swp_ind]) features.update({"ap_1_{:s}_{:d}_long_square".format(f, amp_label): v for f, v in first_spike_lsq_sweep_features.items()}) mean_spike_lsq_sweep_features = mean_spike_lsq(spike_data[swp_ind]) features.update({"ap_mean_{:s}_{:d}_long_square".format(f, amp_label): v for f, v in mean_spike_lsq_sweep_features.items()}) sweep_feature_list = [ "first_isi", "avg_rate", "isi_cv", "latency", "median_isi", "adapt", ] features.update({"{:s}_{:d}_long_square".format(f, amp_label): sweep_table.at[swp_ind, f] for f in sweep_feature_list}) features["stimulus_amplitude_{:d}_long_square".format(amp_label)] = int(amp + basic_lsq_features["rheobase_i"]) rates = sweep_table.loc[sweep_indexes, "avg_rate"].values features.update(fi_curve_fit(amps, rates)) return features