예제 #1
0
 def browse(self, row = 3, col = 3):
     '''
     Plot the raw traces grouped close to each other based on the groups of cells
     parameters:
         row (int) - number of rows of subplots
         col (int) - number of columns of subplots
     return:
         f (list) - list of image windows
     '''
     f = []
     for t in np.unique(self.data['group']):
         cell_ind = self.data.index[np.nonzero(self.data['group'] == t)]
         ft = []
         counter = 0
         for c in cell_ind:
             for trial in self.trial_data[c, :, :]:
                 trace, sr, stim = util.load_wave(self.folder + \
                     util.gen_name(self.data['No'][c], trial[0]))
                 if not len(trace):
                     continue
                 sub_num = counter - row * col * (len(ft) - 1)
                 if row * col <= sub_num:
                     ft.append(pg.GraphicsWindow(title = \
                         'Image {:d}'.format(len(ft) + 1) + ' in ' + t))
                     sub_num -= row * col
                 axis = ft[-1].addPlot(int(sub_num / col), np.mod(sub_num, col))
                 axis.setTitle('Cell {0:d}, rate = {1:.0f} Hz, I = {2:.0f} pA'.format(\
                     self.data['No'][c], trial[1], trial[2] * 1e12))
                 plot.plot_trace_v(trace, sr, ax = axis)
                 counter += 1
         f.extend(ft)
     return f
예제 #2
0
def aveplot(intensity_dir, group_size, folder, cells, intensities, trial, start, freq, num, \
    win = None,  medfilt = True, smooth = False, base_win = 0.3, col = 3, row = 3):
    '''
    f = aveplot(intensity_dir, group_size, folder, cells, intensities, trial, start, freq, \
        num, medfilt = True, smooth = False, base_win = 0.3):
        Plot the averaged responses across several trials with stimulus of certain 
        intensity for different cells at different intensity levels.
    parameters:
        intensity_dir (string) - intensity data file
        folder (string) - dirctory to the data folder
        cells (array_like) - indices of cells
        intensities (array_like) - intensities of the trials to be plotted for each cell
        trial (array_like) - number of trials in each intensity group to be plotted
        start (float) - time of stimulation start
        freq (float) - frequency of stimulation
        num (int) - number of stimuli
        medfilt (float) - median filter threshold
        smooth (boolean) - whether to smooth the traces with default parameters
        base_win (float) - size of baseline window, right before the first stimulation used
            for baseline alignment
        col (int) - number of columns of subplots
        row (int) - number of rows of subplots
    return:
        f (GraphicsWindow) - window object of pyqtgraph package
    '''
    f = []
    count = 0
    pg.setConfigOption('background', 'w')
    pg.setConfigOption('foreground', 'k')
    for i, cell in enumerate(cells):
        for intensity in intensities[i]:
            file_dirs = util.intensity2file(folder, [cell], [intensity], trial, \
                intensity_dir, group_size)
            traces = []
            sr = 0
            if len(file_dirs) == 0:
                continue
            for fd in file_dirs:
                t, sr, stim = util.load_wave(fd)
                if base_win:
                    baseline = np.mean(t[int(start - base_win):int(start)])
                    t = t - baseline
                if smooth:
                    t = process.smooth(t, sr, 600)
                if medfilt:
                    t = process.thmedfilt(t, 5, 30e-12)
                traces.append(t)
            ave_trace = np.mean(traces, 0)
            #print(np.mean(ave_trace))
            sub_num = count - row * col * (len(f) - 1)
            if row * col <= sub_num:
                f.append(pg.GraphicsWindow(title = \
                    'Group {0:d}'.format(len(f) + 1)))
                sub_num -= row * col
            axis = f[-1].addPlot(int(sub_num / col), np.mod(sub_num, col))
            axis.setTitle('Cell {0:d}, Int {1:.2f}'.format(cell, intensity))
            plot.plot_trace_v(ave_trace, sr, ax = axis, win = win, \
                stim = [start + d / freq for d in range(num)])
            count += 1
    return f
예제 #3
0
 def align_ahp(self, spikes = [0], max_trace = 30, param_file = 'param_spike_detect'):
     '''
     Align and plot specified action potentials from chosen trials in the same graphs.
     parameters:
         spikes (list) - indices of spikes to plot, 0 is the first
         max_trace (int) - maximum number of traces in each graph, not to be too crowded
         param_file (String) - directory of spike detection parameter file
     return:
         f (list) - list of image windows
     '''
     # Traverse all the trials, find the spikes and store the trace, time range 
     # of the spikes and the type of the cell which the trace belong to in 
     # separated lists sequentially
     traces = [[] for d in range(len(spikes))]
     limits = [[] for d in range(len(spikes))]
     cell_types = [[] for d in range(len(spikes))]
     spike_params = ap.get_params(param_file)
     for c in self.data.index:
         for trial in self.trial_data[c, :, :]:
             trace, sr, stim = util.load_wave(self.folder + \
                 util.gen_name(self.data['No'][c], trial[0]))
             if sr > 0:
                 starts = ap.spike_detect(trace, sr, spike_params)  # start of all spikes
                 for i, spike in enumerate(spikes):
                     if spike < len(starts) - 1:
                         traces[i].append(trace)
                         cell_types[i].append(self.data['group'][c])
                         limits[i].append([starts[spike], starts[spike + 1]])
     
     f = []
     for i, spike in enumerate(spikes):
         types = np.sort(np.unique(cell_types[i]))
         image_num = int(np.ceil(len(cell_types[i]) / max_trace))  # number of images
         fs = [pg.GraphicsWindow(title = 'Image {0:d} in spike {1:d}'.format(d, spike)) \
             for d in range(image_num)]
         ax = [d.addPlot(0, 0) for d in fs]
         cl = [pg.intColor(i, hues = len(types)) for i in range(len(types))]  # colors
         # Add legend to the plotItems
         lgit = [pg.PlotDataItem(pen = cl[d]) for d in range(len(cl))]
         for ax_ in ax:
             lg = ax_.addLegend()
             for t, l in zip(types, lgit):
                 lg.addItem(l, t)
         group_max = []  # maximum number of traces in one image for each groups
         for t in types:
             group_max.append(np.ceil(np.count_nonzero(np.array(cell_types[i]) == t) \
                 / image_num))
         group_trial = [0 for d in range(len(types))]  # keep track of trials 
             # plotted in each groups
         for j in range(len(cell_types[i])):
             _group = np.nonzero(types == cell_types[i][j])[0][0]
             plot.plot_trace_v(traces[i][j], 1, win = limits[i][j], ax = \
                 ax[int(np.floor(group_trial[_group] / group_max[_group]))], \
                 shift = [-limits[i][j][0], -traces[i][j][limits[i][j][0]]], \
                 cl = cl[_group])
             group_trial[_group] += 1
         f.extend(fs)
     return f
예제 #4
0
파일: ap.py 프로젝트: maoyeh/WholeCellPatch
def spike_detect(trace, sr, params, begin=0, end=-1, plotting=False):
    '''
    start_ind = spike_detect(trace, sr, params, begin = 0, end = -1, plotting = False) 
        Detect action potential spikes and return the spike rising time points.
        Find start time of spikes by finding point with slope over slope_th followed by a peak
        of relative amplitude above peak_th.  The peak is defined as the first point reversing 
        slope after the start point. 
    parameters:
        trace (array_like) - voltage trace
        sr (float) - sampling rate
        params (dictionary) - parameters
        begin (float) - begin of the time window to be analyzed
        end (float) - end of the time window to be analyzed, it represents the end of the 
            trace when it's -1
        plotting (boolean) - whether to plot the trace with starting point marked for
            inspection
    return:
        start_ind (array_like) - indices of spike starting points
    '''

    slope_th = params['spike_slope_threshold']
    peak_th = params['spike_peak_threshold']
    width_th = params['half_width_threshold']
    sign = params['sign']

    if sign < 0:
        trace = trace * sign
    trace_diff = np.diff(trace) * sr
    pstart = np.nonzero(trace_diff > slope_th)[0]  # possible start points
    reverse = np.nonzero(trace_diff < 0)[0]  # possible peak points
    start_ind = []
    #print('start len = {:f}'.format(len(pstart)))
    #print('reverse len = {:f}'.format(len(reverse)))
    i = 0  # index in pstart
    j = 0  # index in reverse
    if end == -1:
        end = len(trace) / sr
    while i < len(pstart) and j < len(reverse) and pstart[i] < sr * end:
        if pstart[i] < sr * begin:
            i += 1
        elif pstart[i] < reverse[j]:
            #print('b: {0:f}, p: {1:f}'.format(trace[pstart[i]], trace[reverse[j]]))
            if peak_th < trace[reverse[j]] - trace[pstart[i]] and \
                reverse[j] - pstart[i] < width_th * sr:
                start_ind.append(pstart[i])
                while i < len(pstart) and pstart[i] < reverse[j]:
                    i += 1
            else:
                i += 1
        else:
            j += 1

    # plot trace with spike start points marked if needed
    #print(start_ind)
    start_ind = np.array(start_ind)  # transform to numpy array
    if plotting:
        w = plot.plot_trace_v(trace, sr, points=start_ind / sr)
        return start_ind, w
    else:
        return start_ind
예제 #5
0
def FIcompare(folder, cells, currents = [], freqs = [],\
    firing_rate_data = 'firing_rate_data.txt'):
    '''
    f = FIcompare(folder, cells, currents = [], freqs = [],\
        firing_rate_data = 'firing_rate_data.txt'):
        Plot current clamp firing traces with certain currents input and with firing
        frequencies in a certain range.
    parameters:
        folder (string) - directory to the folder with raw data
        cells (array_like) - indices of neurons to plot
        currents (array_like) - list of input currents
        freqs (list) - of two scalars, range of the firing rates to be included
        firing_rate_data (string) - firing rate data file directory
    return:
        f (list) - list of figure windows
    '''
    data = util.read_dict(firing_rate_data, 'int')
    f = []
    for cell in cells:
        for trial, stim, fr in zip(*data[cell][1]):
            if (len(currents) == 0 or stim in currents) and \
                (len(freqs) == 0 or (freqs[0] <= fr and fr < freqs[1])):
                trace, sr, st = util.load_wave(folder + util.gen_name(cell, trial))
                f.append(plot.plot_trace_v(trace, sr))
                f[-1].setWindowTitle('Cell {0:d}, Trial {1:d}, I = {2:.2e}'.\
                    format(cell, trial, st[2]))
    return f
예제 #6
0
 def align(self, baseline_win = 0.2, max_trace = 30):
     '''
     Plot the chosen trials in the same graphs, aligned to baseline and colored based 
     on groups 
     parameters:
         baseline_win (float) - baseline window size before the start of the stimulation
         max_trace (int) - maximum number of traces in each graph
     retrun:
         f (list) - list of image windows
     '''
     types = np.sort(np.unique(self.data['group']))
     trial_num = np.count_nonzero(self.trial_data[:, :, 0])
     # trial_num = self.trial_data.shape[0] * self.trial_data.shape[1]
     image_num = int(np.ceil(trial_num / max_trace))  # number of images
     f = [pg.GraphicsWindow(title = 'Image {0:d}'.format(d)) for d in range(image_num)]
     ax = [d.addPlot(0, 0) for d in f]
     cl = [pg.intColor(i, hues = len(types)) for i in range(len(types))]  # colors
     # Add legend to the plotItems
     lgit = [pg.PlotDataItem(pen = cl[d]) for d in range(len(cl))]
     for ax_ in ax:
         lg = ax_.addLegend()
         for t, l in zip(types, lgit):
             lg.addItem(l, t)
     counter = 0
     for c in self.data.index:
         for t in self.trial_data[c]:
             if t[0] == 0:
                 break
             trace, sr, stim = util.load_wave(self.folder + \
                 util.gen_name(self.data['No'][c], t[0]))
             if sr > 0:
                 _group = np.nonzero(types == self.data['group'][c])[0][0]
                 plot.plot_trace_v(trace, sr, ax = \
                     ax[int(np.floor(counter / max_trace))], shift = \
                     [0, -np.mean(trace[int(stim[0] - baseline_win):int(stim[0])])], \
                     cl = cl[_group])
                 counter += 1
     return f
예제 #7
0
    def analyze(self, verbose=0):
        '''
		Detect the spikes of the minis and analyze them
		Criterions:
		  1. Rise time short enough
		  2. Amplitude large enough
		  3. Decay fit exponential curve with low enough residual
		  4. Decay time constant big enough
		'''
        # miniEPSC parameters after analysis
        self.miniRises = []  # valid minis' rise times
        self.miniPeaks = []  # valid mini's peak index
        self.miniAmps = []  # valid mini's peak amplitude
        self.miniDecayTaus = []  # valid mini's decay time constant
        x = self.x[int(self.sr * self.params['start']): \
          int(self.sr * self.params['end'])] * self.params['sign']
        # rig defect related single point noise
        x = self.thmedfilt(x, self.params['medianFilterWinSize'], \
          self.params['medianFilterThresh'])
        # scale
        x = x * self.scale
        # remove linear shifting baseline
        p = np.polyfit(np.arange(len(x)), x, 1)
        x = (x - np.polyval(p, np.arange(len(x))))
        # low pass filter
        fx = self.smooth(x, self.sr, self.params['lowBandWidth'])
        dfx = np.diff(fx) * self.sr
        peaks = (0 < dfx[0:-1]) & (dfx[1:] < 0)
        troughs = (dfx[0:-1] < 0) & (0 < dfx[1:])
        # points with local maximum slope, which is also larger than threshold
        rises = (dfx[0:-1] < self.params["riseSlope"]) & \
          (self.params["riseSlope"] < dfx[1:])
        '''
		rises = np.zeros(peaks.shape)
		rises = (dfx[0:-2] < dfx[1:-1]) & (dfx[2:] < dfx[1:-1]) & \
				(self.params['riseSlope'] < dfx[1:-1])
		'''
        # indices of either rises or peaks
        ptrInds = np.concatenate((np.nonzero(peaks | rises | troughs)[0], \
          [int(self.params['end'] * self.sr)]), axis = None)
        lastRise = -self.params["riseTime"] * self.sr  # last rise point index
        last2Rise = 0  # the rise point index before last rise point
        baseline = 0  # current baseline level
        peakStack = []  # peaks stacked to close to each other
        for i in range(len(ptrInds) - 1):
            if peaks[ptrInds[i]]:
                if ptrInds[i] - lastRise < self.params['riseTime'] * self.sr or \
                  len(peakStack):
                    if (len(peakStack) and ptrInds[i + 1] - peakStack[0] \
                       < self.params["stackWin"] * self.sr):
                        peakStack.append(ptrInds[i])
                    else:
                        if last2Rise < lastRise - \
                         int(self.params['baseLineWin'] * self.sr):
                            baseline = np.mean(x[lastRise - \
                              int(self.params['baseLineWin'] * self.sr):\
                              lastRise])
                        amp = fx[ptrInds[i]] - baseline
                        if self.params['minAmp'] < amp or len(peakStack):
                            if not len(peakStack) and ptrInds[i + 1] - ptrInds[i] < \
                              self.params["stackWin"] * self.sr and \
                              i + 3 < len(ptrInds) and not rises[ptrInds[i + 2]]:
                                peakStack.append(ptrInds[i])
                            else:
                                if len(peakStack):
                                    amp = np.max(fx[peakStack] - baseline)
                                    peakStack = []
                                sample = x[lastRise:ptrInds[i + 1]]
                                # exponential function to fit the decay
                                fun = lambda x, t1, t2, a, b, c: \
                                  a * np.exp(-x / t1) - b * np.exp(-x / t2) + c
                                # initial parameter values
                                p0 = [self.params["offTauIni"], self.params["onTauIni"], \
                                  fx[lastRise] + amp - baseline, amp, baseline]
                                # boundaries
                                bounds = ([-np.inf, -np.inf, 0, 0, -np.inf], \
                                  [np.inf, np.inf, np.inf, np.inf, np.inf])
                                try:
                                    popt, pcov = curve_fit(fun, np.arange(len(sample)), \
                                      sample, p0, bounds = bounds, \
                                      loss = "linear", max_nfev = 1e3 * len(sample))
                                    tau_rise = popt[1] / self.sr
                                    tau_decay = popt[0] / self.sr
                                    res = np.sqrt(np.sum((fun(np.arange(len(sample)), \
                                      *popt) - sample) ** 2))
                                    if verbose > 1:
                                        print("popt: ", popt)
                                        print("tau rise: ", tau_rise, "tau decay: ", \
                                          tau_decay, "res: ", res, "time:", \
                                          lastRise / self.sr)
                                        fm = pg.GraphicsWindow()
                                        ax = fm.addPlot(0, 0)
                                        plot.plot_trace_v(x[lastRise:ptrInds[i + 1]], \
                                          self.sr, ax = ax)
                                        plot.plot_trace_v(fx[lastRise:ptrInds[i + 1]], \
                                          self.sr, ax = ax, cl = 'g')
                                        plot.plot_trace_v(\
                                          fun(np.arange(len(sample)), *popt), \
                                          self.sr, ax = ax, cl = 'r')
                                        print("Continue (c) or step ([s])")
                                        if input() == 'c':
                                            verbose = 1
                                    if self.params['minTau'] < tau_decay \
                                      and res < self.params['residual']:
                                        '''
										self.miniPeaks.append(self.params['start'] + \
												ptrInds[i] / self.sr)
										self.miniRises.append(self.params["start"] + \
												lastRise / self.sr)
										'''
                                        self.miniPeaks.append(ptrInds[i] /
                                                              self.sr)
                                        self.miniRises.append(lastRise /
                                                              self.sr)
                                        self.miniAmps.append(amp / self.scale)
                                        self.miniDecayTaus.append(tau_decay)
                                except RuntimeError as e:
                                    print("Fit Error")
                                    print(e)
                                except ValueError as e:
                                    print("Initialization Error")
                                    print(e)
            elif rises[ptrInds[i]]:
                last2Rise = lastRise
                lastRise = ptrInds[i]
        if verbose > 0:
            fs = pg.GraphicsWindow()
            ax = [fs.addPlot(i, 0) for i in range(3)]
            plot.plot_trace_v(x, self.sr, ax=ax[0])
            plot.plot_trace_v(fx, self.sr, ax=ax[0], cl='g')
            plot.plot_trace_v(fx, self.sr, ax = ax[1], pcl = 'r', \
              points = np.nonzero(rises)[0] / self.sr)
            plot.plot_trace_v(fx, self.sr, ax = ax[1], pcl = None, \
              points = np.nonzero(peaks)[0] / self.sr)
            plot.plot_trace_v(fx, self.sr, points = self.miniRises, \
              ax = ax[1], pcl = 'b')
            ax[0].setXLink(ax[1])
            ax[0].setYLink(ax[1])
            plot.plot_trace_v(dfx, self.sr, ax=ax[2])
            return fs
예제 #8
0
def browse(folder, cell_num, trial_num = None, row = 3, col = 3, medfilt = True): 
    '''
    f = browse(folder, cell_num, trial_num = None, row = 3, col = 3, medfilt = True): 
        Plot data traces of a cell in figures with multiple subplots to quicky review 
        the traces
    parameters:
        folder (string) - directory to the folder with the data files
        cell_num (int) - cell index
        trial_num (int or list) - trial index or indices, include all the trials if it's None
        row (int) - number of rows of subplots
        col (int) - number of cols of subplots
        medfilt (boolean) - whether to apply median filter with a default threshold
    return:
        f (list) - list of window objects of pyqtgraph package
    '''
    if(folder[-1] is not os.sep):
        folder = folder + os.sep
    if type(trial_num) is int:
        file_dir = folder + 'Cell_{0:04d}_{1:04d}.ibw'.format(cell_num, trial_num)
        print(file_dir)
        trace, sr, stim = util.load_wave(file_dir)
        if not len(trace):
            return
        if medfilt:
            trace = process.thmedfilt(trace, 5, 40e-12)
        f = plot.plot_trace_v(trace, sr)
        if stim[2] != 0:
            f.getItem(0, 0).setTitle('Trial {0:d}, I = {1:.2e}'.format(trial_num, stim[2]))
        #f.save_fig('tmp.png', dpi = 96)
    elif type(trial_num) is list:
        f = []
        for i in range(len(trial_num)):
            file_dir = folder + 'Cell_{0:04d}_{1:04d}.ibw'.format(cell_num, trial_num[i])
            print(file_dir)
            trace, sr, stim = util.load_wave(file_dir)
            if not len(trace):
                continue
            if medfilt:
                trace = process.thmedfilt(trace, 5, 40e-12)
            sub_num = i - row * col * (len(f) - 1)
            if row * col <= sub_num:
                f.append(pg.GraphicsWindow(title = \
                    'Cell {0:d}, Group {1:d}'.format(cell_num, len(f) + 1)))
                sub_num -= row * col
            #axis = f[-1].addPlot(int(sub_num / row), np.mod(sub_num, col), \
            axis = f[-1].addPlot(int(sub_num / col), np.mod(sub_num, col))
            if stim[2] != 0:
                axis.setTitle('Trial {0:d}, I = {1:.2e}'.format(trial_num[i], stim[2]))
            else:
                axis.setTitle('Trial {0:d}'.format(trial_num[i]))
            plot.plot_trace_v(trace, sr, ax = axis)
    else:
        f = []
        file_pre = 'Cell_{0:04d}_'.format(cell_num)
        print(file_pre)
        data_files = os.listdir(folder)
        count = 0
        for data_file in data_files:
            matched = re.match(file_pre + '0*([1-9][0-9]*).ibw', data_file)
            if matched:
                trial_num = int(matched.group(1))
                sub_num = count - row * col * (len(f) - 1)
                if row * col <= sub_num:
                    f.append(pg.GraphicsWindow(title = 
                        'Cell {0:d}, Group {1:d}'.format(cell_num, len(f) + 1)))
                    sub_num -= row * col
                axis = f[-1].addPlot(int(sub_num / col), np.mod(sub_num, col))
                file_dir = folder + data_file
                trace, sr, stim = util.load_wave(file_dir)
                print(file_dir + ' {:f}'.format(len(trace) / sr))
                if stim[2] != 0:
                    axis.setTitle('Trial {0:d}, I = {1:.2e}'.format(trial_num, stim[2]))
                else:
                    axis.setTitle('Trial {0:d}'.format(trial_num))
                if medfilt:
                    trace = process.thmedfilt(trace, 5, 40e-12)
                plot.plot_trace_v(trace, sr, ax = axis)
                count += 1
    return f