Exemplo n.º 1
0
def analyze_response_strength(rec,
                              source,
                              remove_artifacts=False,
                              deconvolve=True,
                              lpf=True,
                              bsub=True,
                              lowpass=1000):
    """Perform a standardized strength analysis on a record selected by response_query or baseline_query.

    1. Determine timing of presynaptic stimulus pulse edges and spike
    2. Measure peak deflection on raw trace
    3. Apply deconvolution / artifact removal / lpf
    4. Measure peak deflection on deconvolved trace
    """
    data = TSeries(rec.data, sample_rate=db.default_sample_rate)
    if source == 'pulse_response':
        # Find stimulus pulse edges for artifact removal
        start = rec.pulse_start - rec.rec_start
        pulse_times = [start, start + rec.pulse_dur]
        if rec.spike_time is None:
            # these pulses failed QC, but we analyze them anyway to make all data visible
            spike_time = 11e-3
        else:
            spike_time = rec.spike_time - rec.rec_start
    elif source == 'baseline':
        # Fake stimulus information to ensure that background data receives
        # the same filtering / windowing treatment
        pulse_times = [10e-3, 12e-3]
        spike_time = 11e-3
    else:
        raise ValueError("Invalid source %s" % source)

    results = {}

    results['raw_trace'] = data
    results['pulse_times'] = pulse_times
    results['spike_time'] = spike_time

    # Measure crosstalk from pulse onset
    p1 = data.time_slice(pulse_times[0] - 200e-6, pulse_times[0]).median()
    p2 = data.time_slice(pulse_times[0], pulse_times[0] + 200e-6).median()
    results['crosstalk'] = p2 - p1

    # crosstalk artifacts in VC are removed before deconvolution
    if rec.clamp_mode == 'vc' and remove_artifacts is True:
        data = remove_crosstalk_artifacts(data, pulse_times)
        remove_artifacts = False

    # Measure deflection on raw data
    results['pos_amp'], _ = measure_peak(data, '+', spike_time, pulse_times)
    results['neg_amp'], _ = measure_peak(data, '-', spike_time, pulse_times)

    # Deconvolution / artifact removal / filtering
    if deconvolve:
        tau = 15e-3 if rec.clamp_mode == 'ic' else 5e-3
    else:
        tau = None
    dec_data = deconv_filter(data,
                             pulse_times,
                             tau=tau,
                             lpf=lpf,
                             remove_artifacts=remove_artifacts,
                             bsub=bsub,
                             lowpass=lowpass)
    results['dec_trace'] = dec_data

    # Measure deflection on deconvolved data
    results['pos_dec_amp'], results['pos_dec_latency'] = measure_peak(
        dec_data, '+', spike_time, pulse_times)
    results['neg_dec_amp'], results['neg_dec_latency'] = measure_peak(
        dec_data, '-', spike_time, pulse_times)

    return results
Exemplo n.º 2
0
    def set_data(self, data, show_spikes=False, subtract_baseline=True):
        self.spike_plot.setVisible(show_spikes)
        self.spike_plot.enableAutoRange(False, False)
        self.data_plot.enableAutoRange(False, False)
        psp = StackedPsp()

        for recording in data:
            pulses = sorted(list(data[recording].keys()))
            for pulse_n in pulses:
                rec = data[recording][pulse_n]
                # spike-align pulse + offset for pulse number
                spike_t = rec.StimPulse.first_spike_time
                if spike_t is None:
                    spike_t = rec.StimPulse.onset_time + 1e-3

                qc_pass = rec.PulseResponse.in_qc_pass if rec.Synapse.synapse_type == 'in' else rec.PulseResponse.ex_qc_pass
                pen = (255, 255, 255, 100) if qc_pass else (200, 50, 0, 100)

                t0 = rec.PulseResponse.data_start_time - spike_t
                ts = TSeries(data=rec.data,
                             t0=t0,
                             sample_rate=db.default_sample_rate)
                c = self.data_plot.plot(ts.time_values, ts.data, pen=pen)

                # arrange plots nicely
                y0 = 0 if not subtract_baseline else ts.time_slice(None,
                                                                   0).median()
                shift = (pulse_n * 35e-3 + (30e-3 if pulse_n > 8 else 0), -y0)
                zval = 0 if qc_pass else -10
                c.setPos(*shift)
                c.setZValue(zval)

                if show_spikes:
                    t0 = rec.spike_data_start_time - spike_t
                    spike_ts = TSeries(data=rec.spike_data,
                                       t0=t0,
                                       sample_rate=db.default_sample_rate)
                    c = self.spike_plot.plot(spike_ts.time_values,
                                             spike_ts.data,
                                             pen=pen)
                    c.setPos(*shift)
                    c.setZValue(zval)

                # evaluate recorded fit for this response
                fit_par = rec.PulseResponseFit
                if fit_par.fit_amp is None:
                    continue
                fit = psp.eval(
                    x=ts.time_values,
                    exp_amp=fit_par.fit_exp_amp,
                    exp_tau=fit_par.fit_decay_tau,
                    amp=fit_par.fit_amp,
                    rise_time=fit_par.fit_rise_time,
                    decay_tau=fit_par.fit_decay_tau,
                    xoffset=fit_par.fit_latency,
                    yoffset=fit_par.fit_yoffset,
                    rise_power=2,
                )
                pen = (0, 255, 0, 100) if qc_pass else (50, 150, 0, 100)
                c = self.data_plot.plot(ts.time_values, fit, pen=pen)
                c.setZValue(10)
                c.setPos(*shift)

                if not qc_pass:
                    print(
                        "qc fail: ",
                        rec.PulseResponse.meta.get('qc_failures',
                                                   'no qc failures recorded'))

        self.spike_plot.enableAutoRange(True, True)
        self.data_plot.enableAutoRange(True, True)