def calc_v(self, win, output_file='vhold.txt'): ''' ave_vhold = calc_v(self, output_file = 'vhold.txt'): Calculate holding membrane potential before the spike train. parameter: win (float) - window size before the depolarization to average. output_file (string) - output file directory. return: ave_vhold (array_like) - averaged holding potential for each neuron ''' cell_num = self.trial_data.shape[0] trial_num = self.trial_data.shape[1] vhold = np.zeros((cell_num, trial_num)) for c in range(cell_num): for t in range(trial_num): cind = self.data['No'][c] tind = self.trial_data[c][t][0] if tind != 0: trace, sr, stim = util.load_wave(self.folder + \ util.gen_name(cind, tind)) vhold[c, t] = np.mean(trace[int((stim[0] - win) * sr):\ int(stim[0] * sr)]) util.write_arrays(output_file, ['vhold', vhold]) ave_vhold = np.zeros(cell_num) for i in range(cell_num): ave_vhold[i] = np.mean(vhold[i][np.nonzero(vhold[i])]) return ave_vhold
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
def calc_sahp(self, baseline_win, lat, win, output_file='slow_ahps.txt'): ''' Calculate the slow ahp in chosen trials. In current clamp AP trains, slow AHP is defined as the hyperpolarization at lat time point after the end of the current step relative to the baseline before the current step. Try to avoid the Ih current. Parameters: baseline_win (float) - window size of baseline ahead of the current step lat (float) - latency of sAHP measurement point after the current step win (float) - window size of the sAHP measurement Return: mean_ahps (array_like) - mean slow ahps for each cell ''' cell_num = self.trial_data.shape[0] trial_num = self.trial_data.shape[1] ahps = np.zeros((cell_num, trial_num)) for c in range(cell_num): for t in range(trial_num): cind = self.data['No'][c] tind = self.trial_data[c][t][0] if tind != 0: trace, sr, stim = util.load_wave(self.folder + \ util.gen_name(cind, tind)) baseline = np.mean(trace[int((stim[0] - baseline_win) * sr):\ int(stim[0] * sr)]) ahps[c][t] = baseline - np.mean(trace[int((stim[0] + stim[1] + lat) * sr):\ int((stim[0] + stim[1] + lat + win) * sr)]) util.write_arrays(output_file, ['sahp', ahps]) mean_ahps = np.zeros(cell_num) for i in range(cell_num): mean_ahps[i] = np.mean(ahps[i][np.nonzero(ahps[i])]) return mean_ahps
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
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
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
def firing_rate(folder, cells, trials = [], out = 'firing_rate_data.txt', \ param_file = 'param_spike_detect'): ''' data = firing_rate(folder, cells, trials = [], data_out = 'firing_rate_data.txt') Measure firing rate data and output in two forms, one with firing rate of the same current input averaged and the other with raw firing rate for each trial. output a dictionary with each element having data for one cell, the key is the cell index. data = {cell_idx: [[[stims], [averaged firing rate]], [[trial indices], [stims], [firing rate]]]} parameters: folder (String) - directory to the folder of the trace data files cells (array_like) - indices of cells to analyze trials (array_like) - trial numbers, if not provided analyze all the trials in the folder out (String) - output data file directory param_file (String) - spike detection parameter file return: data (dictionary) - firing rate data ''' data = {} params = get_params(param_file) for cell in cells: print('Cell: ', cell) ctrials = trials[:] _stims = [] _rates = [] if not len(ctrials): data_files = os.listdir(folder) for data_file in data_files: matched = re.match('Cell' + \ '_{:04d}_0*([1-9][0-9]*)\.ibw'.format(int(cell)), data_file) if matched: ctrials.append(int(matched.group(1))) for trial in ctrials: file_dir = folder + os.sep + util.gen_name(cell, trial) trace, sr, stim_i = util.load_wave(file_dir) _stims.append(stim_i[2]) _rates.append(len(spike_detect(trace, sr, params, stim_i[1], \ stim_i[0] + stim_i[1]))) raw = [ctrials, _stims, _rates] _stims = np.array(_stims) _rates = np.array(_rates) stims = np.unique(_stims) ave = np.zeros(len(stims)) for i, current in enumerate(stims): ave[i] = sum(_rates[np.nonzero(_stims == current)[0]]) / \ len(np.nonzero(_stims == current)[0]) ave_data = [stims.tolist(), ave.tolist()] data[cell] = [ave_data, raw] util.write_dict(out, data) return data
def calc_mahp(self, lat_win, spk_win, param_file = 'param_spike_detect', \ output_file = 'medium_ahps.txt'): ''' Calculate medium ahps in chosen trials after spikes in the spk_win. mAHPs are defined as hyperpolarization peak value between two spikes relative to the spiking threshold of the prior spike, excluding the fast AHPs range right after the prior spike. Choose spikes to avoid Ih current and sAHP. Parameters: lat_win (array_like) - 2 scalars, mininum latency for mAHP, window for fAHP, and minimum interspike interval to include ahp. spk_win (array_like) - 2 scalars, begin and end of the window of spikes param_file (String) - directory to parameter files for spike detection output_file (String) - dirctory to output file of medium ahp data of all spikes Returns: mean_ahps (array_like) - 1D array of mean ahps for each cell ''' cell_num = self.trial_data.shape[0] trial_num = self.trial_data.shape[1] spike_num = spk_win[1] - spk_win[0] ahps = np.zeros((cell_num, trial_num, spike_num)) spike_params = get_params(param_file) for c in range(cell_num): for t in range(trial_num): cind = self.data['No'][c] tind = self.trial_data[c][t][0] if tind != 0: trace, sr, stim = util.load_wave(self.folder + \ util.gen_name(cind, tind)) starts = spike_detect(trace, sr, spike_params) # start of all spikes for s in range(spike_num): if spk_win[0] + s < len(starts): # only calculate if it is not the last spike if sr * lat_win[1] < \ starts[spk_win[0] + s + 1] - starts [spk_win[0] + s]: # and the ISI is larger that the minumum threshold ahps[c][t][s] = trace[starts[spk_win[0] + s]] - \ np.min(trace[(starts[spk_win[0] + s] + \ int(sr * lat_win[0])):starts[spk_win[0] + s + 1]]) else: print('Irregular trial: cell', cind, ',trial', tind) util.write_arrays(output_file, ['mahp', ahps]) mean_ahps = np.zeros(cell_num) for i in range(cell_num): mean_ahps[i] = np.mean(ahps[i][np.nonzero(ahps[i])]) return mean_ahps
def get_spike_time(self, param_file='param_spike_detect'): ''' Calculate the spike start time for all the chosen traces. Parameters: param_file (string) - directory to spike detection parameter file ''' spike_params = get_params(param_file) cell_num = self.trial_data.shape[0] trial_num = self.trial_data.shape[1] self.starts = [] # start times of all spikes in all trials for c in range(cell_num): _starts = [] for t in range(trial_num): cind = self.data['No'][c] tind = self.trial_data[c][t][0] if tind != 0: trace, sr, stim = util.load_wave(self.folder + \ util.gen_name(cind, tind)) _starts.append(spike_detect(trace, sr, spike_params)) self.starts.append(_starts)
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
def overlap_trace(folder, cells, trials, win, basewin, legends=[]): ''' plot averaged traces of each cell in different colors, ''' if folder[-1] != os.sep: folder += os.sep ave_traces = [] for i in range(len(cells)): traces = [] for t in trials[i]: file_dir = folder + 'Cell_{0:04d}_{1:04d}.ibw'.format(\ cells[i], t) print(file_dir) trace, sr, st = util.load_wave(file_dir) trace = np.array(trace).copy() traces.append(trace) ave_traces.append(ahp.average(traces, sr, basewin=basewin)) if not len(legends): lg.append('{0:d}. cell {1:d}'.format(i, cells[i])) if len(legends): lg = legends f = plot.overlap(ave_traces, sr, legends=lg, basewin=basewin, win=win) return f
def calc_slope(self, spk_win, output_file='ap_slope.txt'): ''' ave_slopes = calc_slope(self, spk_win, output_file = 'ap_slope.txt'): Caclulate largest slope of the rising of an action potential Parameters spk_win (array_like) - 2 scalars, begin and end of the window of spikes Return ave_slopes (array_like) - average slopes for each cell ''' cell_num = self.trial_data.shape[0] trial_num = self.trial_data.shape[1] spike_num = spk_win[1] - spk_win[0] slopes = np.zeros((cell_num, trial_num, spike_num)) for c in range(cell_num): for t in range(trial_num): cind = self.data['No'][c] tind = self.trial_data[c][t][0] if tind != 0: starts = self.starts[c][t] trace, sr, stim = util.load_wave(self.folder + \ util.gen_name(cind, tind)) for s in range(spk_win[0], spk_win[1]): if s < len(starts) - 1: peak_point = np.argmax(trace[starts[s]:starts[s + 1]]) slopes[c, t, s - spk_win[0]] = np.max(np.diff(trace[starts[s]: \ starts[s] + peak_point])) * sr elif s == len(starts) - 1: peak_point = np.argmax(trace[starts[s]:\ int((stim[0] + stim[1]) * sr)]) slopes[c, t, s - spk_win[0]] = np.max(np.diff(trace[starts[s]: \ starts[s] + peak_point])) * sr util.write_arrays(output_file, ['slopes', slopes]) ave_slopes = np.zeros(cell_num) for i in range(cell_num): ave_slopes[i] = np.mean(slopes[i][np.nonzero(slopes[i])]) return ave_slopes
def sample_aps(folder, cell_num, trial_num, train_win = [], spike_win = [-0.5e-3, 3e-3], \ freq_range = [], ap_ind = [], type_file = None, ave = False, cl = [], lw = 1, \ units = None, scale = [1, 1], scalebar = [0, 0], interp = 0, fname = 'tmp.png'): ''' sample_aps(folder, cell_num, trial_num, train_win, spike_win = [-0.5e-3, 3e-3], \ freq_range = [], ap_ind = [], type_file = None, ave = False, cl = [], \ fname = 'tmp.png'): plot action potentials of each cells with all the qualified action potentials averaged and depending on the input action potentials of cells in the same groups averages. In the latter case, plot shade standard of error. parameters: folder (String) - directory of the folder with the data cell_num (array_o) - indices of cells to plot trial_num (list) - indices of trails in each cell train_win (list) - of two scalar values for the time window where there are spikes spike_win (list) - of two scalar values for the time windoe for the spikes freq_range (list) - of two scalar, range of frequencies to use ap_ind (list) - index of action potentials in each trial to use type_file (String) - directory of the csv file recording the type of cells, the first column has the cell indices and the last column has the cells' types ave (boolean) - whether to average across cells with same type cl (list) - color traces in each type, use default color sequences if not provided interp (float) - time of number of interpolated points to plot over current number of points scale (list) - 2 scalar element [sx, sy], scaling factor for time and value axis sx and sy respectively. units (list) - 2 string elements list [ux, uy], units after scaling. scalebar (list) - 2 scalar elements list [sx, sy] - scale bar lengh of the two axis. fname ('String') - directory of the file to save the image ''' if folder[-1] != '/': folder += '/' spike_params = ap.get_params('param_spike_detect') spikes = [] for cell in cell_num: print('cell: ', cell) _spikes = 0 count = 0 for trial in trial_num: _trace, _sr, _stim_i = util.load_wave(folder + util.gen_name(cell, trial)) if len(_trace) == 0: continue trace, sr, stim_i = _trace, _sr, _stim_i if len(train_win): spike_start = ap.spike_detect(trace, sr, spike_params, train_win[0], \ train_win[1]) freq = len(spike_start) / (train_win[1] - train_win[0]) else: spike_start = ap.trace_detect(trace, sr, spike_params) freq = len(spike_start) / len(trace) * sr if not (len(freq_range) and (freq < freq_range[0] or freq_range[1] < freq)): if len(ap_ind): for i in ap_ind: pre_ind = max(spike_start[i] + int(spike_win[0] * sr), 0) post_ind = min(spike_start[i] + int(spike_win[1] * sr), len(trace)) single = trace[pre_ind:post_ind] - trace[ spike_start[i]] else: for t in spike_start: pre_ind = max(int((t + spike_win[0]) * sr), 0) post_ind = min(int((t + spike_win[1]) * sr), len(trace)) single = trace[pre_ind:post_ind] - trace[t] if interp: interf = interpolate.interp1d(np.arange(pre_ind, post_ind), \ single, 'cubic') single = interf(np.arange(interp * pre_ind, interp * (post_ind - 1)) \ / interp) _spikes = _spikes + single count += 1 print('spike count: ', count) spikes.append(_spikes / count) spikes = np.array(spikes) f = plt.figure() ax = f.add_subplot(111) ax.axis('off') if interp: xt = np.arange(spikes.shape[1]) / sr / interp else: xt = np.arange(spikes.shape[1]) / sr if type_file != None: type_data = util.read_csv(type_file) type_data = type_data[np.nonzero(type_data[:, [0]] == \ np.ones((type_data.shape[0], 1)) * np.array(cell_num))[0], :] types = np.unique(type_data[:, -1]) if len(cl) != len(types): ncolors = len(types) cm = plt.get_cmap('gist_rainbow') cl = [cm(1 * i / ncolors) for i in range(ncolors)] if ave: for i, t in enumerate(types): group_spikes = spikes[np.nonzero(type_data[:, -1] == t)[0], :] m = np.mean(group_spikes, 0) se = np.std(group_spikes, 0) / np.sqrt(group_spikes.shape[0]) # sd = np.std(group_spikes, 0) ax.plot(xt, m, color=cl[i], lw=lw) ax.fill_between(xt, m - se, m + se, facecolor = cl[i], edgecolor = 'none', \ alpha = 0.3) else: for i, cspikes in enumerate(spikes): ax.plot(xt, cspikes, color = cl[np.nonzero(types == type_data[i, -1])[0][0]], \ lw = lw) else: ax.plot(xt, spikes.T, lw=lw) if units is not None: xscale_text = '{0:d} '.format(scalebar[0]) + units[0] yscale_text = '{0:d} '.format(scalebar[1]) + units[1] else: yscale_text, xscale_text = '', '' xscalebar = scalebar[0] / scale[0] yscalebar = scalebar[1] / scale[1] sc = [xt[-1] - xscalebar * 0.5, ax.get_ylim()[0] - yscalebar * 0.5] # coordinate of top right corner of scale bar if yscalebar != 0: yscale = ax.plot([sc[0] - xscalebar] * 2, [sc[1] - yscalebar, sc[1]], \ color = [0, 0, 0, 1], linewidth = 2.0) t2 = ax.text(sc[0] - xscalebar * 1.01, sc[1] - yscalebar * 0.8, \ yscale_text, ha = 'right', va = 'bottom', rotation = 'vertical', size = 20) if xscalebar != 0: xscale = ax.plot([sc[0] - xscalebar, sc[0]], [sc[1] - yscalebar] * 2, \ color = [0, 0, 0, 1], linewidth = 2.0) t1 = ax.text(sc[0] - xscalebar * 0.8, sc[1] - yscalebar * 1.05, \ xscale_text, va = 'top', size = 20) f.set_size_inches(2, 7) f.savefig(fname, dpi=200, transparent=True) plt.close(f) del (f) return 0
def sample_trace(folder, cell_num, trial_num, win, shift = [0], scale = [1, 1], \ units = None, scalebar = [0, 0], stim = [], lowpass = 0, medfilt = 0, ave = False, \ interp = 0, ylim = [-50e-12, 50e-12], lw = 1, cl = 'k', fname = 'tmp.png'): ''' sample_trace(folder, cell_num, trial_num, win, shift = [0], scale = [1, 1], \ units = None, scalebar = [0, 0], stim = [], lowpass = 0, medfilt = 0, ave = False, \ ylim = [-50e-12, 50e-12]) plot a scaled fragment of ephys recording trace as sample inputs: file_dir (string) - directory to igor binary data file. cell_num (list) - list of indices of cells whose traces will be plotted. trial_num (list) - list of trial numbers to be plotted, a pair with the same indices in cell_num and trial_num will define one trace. win (list) - 2 scalar element [w1, w2], fragment time window without scaling. shift (list) - shift on the value axis of each trace, default is not shift. scale (list) - 2 scalar element [sx, sy], scaling factor for time and value axis sx and sy respectively. units (list) - 2 string elements list [ux, uy], units after scaling. scalebar (list) - 2 scalar elements list [sx, sy] - scale bar lengh of the two axis. stim (list) - time points of stimulation lowpass (float) - band with of lowpass filter applied to the trace, default: no filter applied medfilt (float) - median filter threshold, default: no median filter ave (boolean) - whether to plot the average trace of all the traces ylim (list) - 2 scalar element [y1, y2], limits of the y axis interp (float) - time of number of interpolated points to plot over current number of points returns: f - matplotlib figure TODO: 1. more convenient parameters ''' f = plt.figure() ax = f.add_subplot(111) ax.axis('off') if len(shift) == 1 and shift[0] == 0 and len(cell_num) > 1: shift = [0] * len(cell_num) low = 0 if folder[-1] != os.sep: folder += os.sep for i in range(len(cell_num)): file_dir = folder + 'Cell_{0:04d}_{1:04d}.ibw'.format( cell_num[i], trial_num[i]) print(file_dir) trace, sr, st = util.load_wave(file_dir) trace = np.array(trace).copy() if trace is 0: return 0 if medfilt: trace = process.thmedfilt(trace, 7, 20e-12) if lowpass: trace = process.smooth(trace, sr, lowpass) if shift[i]: trace += shift[i] else: trace += 0 - np.mean( trace[int(0.5 * sr):int(win[0] * sr)]) # move bl to 0 t = np.arange(len(trace)) / sr win_ind1 = int(win[0] * sr) win_ind2 = int(win[1] * sr) xwin = t[win_ind1:win_ind2] ywin = trace[win_ind1:win_ind2] trace_color = mpl.colors.colorConverter.to_rgb(cl) if ave: if i == 0: ave_trace = np.zeros(win_ind2 - win_ind1) ave_trace = ave_trace + ywin ave_color = trace_color trace_color = [(1 + d) / 2 for d in color] # interpolate the data to make it look smoother if interp: interf = interpolate.interp1d(xwin, ywin, 'cubic') xwin = np.linspace(xwin[0], xwin[-1], len(xwin) * interp) ywin = interf(xwin) ax.plot(xwin, ywin, color=trace_color, linewidth=lw) low = min(min(ywin), low) if len(stim): level = 40e-12 ax.plot(stim, [level] * len(stim), 'b|', ms=10, mew=2, linewidth=lw) if ave: ave_trace /= len(cell_num) ax.plot(xwin, ave_trace, color=ave_color, linewidth=lw) if units is not None: xscale_text = '{0:d} '.format(scalebar[0]) + units[0] yscale_text = '{0:d} '.format(scalebar[1]) + units[1] else: yscale_text, xscale_text = '', '' xscalebar = scalebar[0] / scale[0] yscalebar = scalebar[1] / scale[1] #sc = [t[win_ind2] - xscalebar * 0.5, np.mean(ylim)] sc = [t[win_ind2] - xscalebar * 0.5, low] # coordinate of top right corner of scale bar if yscalebar != 0: yscale = ax.plot([sc[0] - xscalebar] * 2, [sc[1] - yscalebar, sc[1]], \ color = [0, 0, 0, 1], linewidth = 2.0) t2 = ax.text(sc[0] - xscalebar * 1.01, sc[1] - yscalebar * 0.8, \ yscale_text, ha = 'right', va = 'bottom', rotation = 'vertical', size = 20) if xscalebar != 0: xscale = ax.plot([sc[0] - xscalebar, sc[0]], [sc[1] - yscalebar] * 2, \ color = [0, 0, 0, 1], linewidth = 2.0) t1 = ax.text(sc[0] - xscalebar * 0.8, sc[1] - yscalebar * 1.05, \ xscale_text, va = 'top', size = 20) ax.set_xlim(*win) ax.set_ylim(*ylim) #f.set_size_inches(3, 5) f.savefig(fname, dpi=200, transparent=True) plt.close(f) del (f) return 0
def multiplot(folder, cells, trials, start, freq, num, intensity_dir = '', group_size = 0, \ intensity = [0], window = 0, medfilt = True, smooth = False, average = False, \ base_win = 0.3, lat = []): ''' f = multiplot(folder, cell, trials, start, freq, num, window = 0, medfilt = 0, \ smooth = False, average = False): Overlap segments of one or more traces after stimulus or overlap several traces, with the stimulation time point marked. parameters: folder (string) - dirctory to the data folder cell (array_like) - indices of cells 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 stimulations intensity_dir (string) - intensity data file, not used when it's empty group_size (int) - number of trials in each group of the same intensity, not used when it's 0 intensity (array_like) - intensities of the trials to be plotted window (float) - window size of each segment after the stimulation to be plotted when it's 0, plot the entire trace and mark the stimulus time ponit instead medfilt (float) - median filter threshold smooth (boolean) - whether to smooth the traces with default parameters average (boolean) - whether to plot the average trace base_win (float) - size of baseline window, right before the first stimulation used for baseline alignment lat (array_like) - latencies of the responses to plot return: f (GraphicsWindow) - window object of pyqtgraph package ''' if folder[-1] != os.sep: folder += os.sep if group_size: file_dirs = util.intensity2file(folder, cells, intensity, trials, intensity_dir, \ group_size) else: file_dirs = [] for cell_num in cells: for trial in trials: file_dirs.append(folder + 'Cell_{0:04d}_{1:04d}.ibw'.format(cell_num, trial)) traces = [] lat_data = [] sr = 0 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) if(len(lat)): #lat_data.append(lat[int(fd[-8:-4]) - 1]) lat_data.append(lat[file_dirs.index(fd)]) if window: segs = plot.gen_seg(freq, num, start, window) seg_traces = [] rise_points = [] if(len(lat)): for t, trial_lat in zip(traces, lat_data): for s, l in zip(segs, trial_lat): seg_traces.append(t[int(s[0] * sr):int(s[1] * sr)]) if s[0] + l < s[1] and 0 < l: rise_points.append([l]) else: rise_points.append([]) else: for t in traces: for s in segs: seg_traces.append(t[int(s[0] * sr):int(s[1] * sr)]) legends = [] for c in cells: for i in intensity: for t in trials: for s in range(len(segs)): if group_size: legends.append('cell{0:d}stim{1:.1f}t{2:d}s{3:d}'.format(c, \ i, t, s + 1)) else: legends.append('cell{0:d}t{1:d}s{2:d}'.format(c, \ t, s + 1)) if average: s = np.zeros(len(seg_traces[0])) for st in seg_traces: s = s + st ave = s / len(seg_traces) seg_traces.append(ave) if(len(lat)): rise_points.append([]) legends.append('Average') f = plot.overlap(seg_traces, sr, legends = legends, rise = rise_points) else: legends = [] for c in cells: for i in intensity: for t in trials: if group_size: legends.append('cell{0:d}stim{1:.1f}t{2:d}'.format(c, i, t)) else: legends.append('cell{0:d}t{1:d}'.format(c, t)) if average: s = np.zeros(len(traces[0])) for t in traces: s = s + t ave = s / len(traces) traces.append(ave) legends.append('Average') if(len(lat)): rise_points = [] stim = [start + d / freq for d in range(num)] for i, trial_lat in enumerate(lat_data): rise_points.append([]) for j, s in enumerate(stim): rise_points[i].append(s + trial_lat[j]) f = plot.overlap(traces, sr, stim = stim, legends = legends, rise = lat_data) else: f = plot.overlap(traces, sr, stim = stim, legends = legends) return f
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