Beispiel #1
0
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
Beispiel #2
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
        """
    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]
Beispiel #3
0
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)
Beispiel #4
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