def plot_lfp_grouped_by_sound(ssl, plot_difference=True, p_adj_meth=None, mark_significance=True, t_start=None, t_stop=None, **kwargs): # First get grouped averages res_d = ssl.average_grouped_by_sound(**kwargs) # set time limits if t_start is None: t_start = ssl.t[0] if t_stop is None: t_stop = ssl.t[-1] t1bin = np.argmin(np.abs(ssl.t - t_start)) t2bin = np.argmin(np.abs(ssl.t - t_stop)) + 1 f = plt.figure() for n, sound in enumerate(['lehi', 'rihi', 'lelo', 'rilo']): # Create an axis for this sound and plot both blocks ax = f.add_subplot(2, 2, n+1) for block in ['LB', 'PB']: myutils.plot_mean_trace(ax=ax, x=ssl.t[t1bin:t2bin], data=res_d[sound][block][:, t1bin:t2bin], label=block) # Optionally plot difference if plot_difference: di = res_d[sound]['LB'] - res_d[sound]['PB'] myutils.plot_mean_trace(ax=ax, x=ssl.t[t1bin:t2bin], data=di[:, t1bin:t2bin], label='diff', color='m') # Optionally mark significance if mark_significance: p_vals = scipy.stats.ttest_rel(res_d[sound]['LB'][:, t1bin:t2bin], res_d[sound]['PB'][:, t1bin:t2bin])[1] if p_adj_meth is not None: p_vals = myutils.r_adj_pval(p_vals, meth=p_adj_meth) pp = np.where(p_vals < .05)[0] plt.plot(ssl.t[t1bin:t2bin][pp], np.zeros_like(pp), 'k*') pp = np.where(p_vals < .01)[0] plt.plot(ssl.t[t1bin:t2bin][pp], np.zeros_like(pp), 'ko', markerfacecolor='w') plt.legend(loc='best') ax.set_title(sound) ax.set_xlim((t_start, t_stop)) plt.show()
def plot_psths_by_sound(df, plot_difference=True, split_on=None, mark_significance=False, plot_errorbars=True, p_adj_meth=None, plot_all=False): """Plots PSTHs for each sound, for a single unit or average across multiple. df : DataFrame containing binned data with following columns :split_on: - Tell me how to group the data eg 'nid', or ['session', 'unit'], or None (single trace) time - time in sec counts - number of spikes in that bin trials - number of trials included in that bin sound, block - what the stimulus was Run bin_flat_spike_data and replace_stim_numbers_with_names to produce these columns. """ # Create figure f = plt.figure(figsize=(9,9)) # Pivot data to allow sound/block access. if split_on is None: # Aggregate all data into a single trace pdata = df.pivot_table(rows=['time'], cols=['sound', 'block'], values=['counts', 'trials'], aggfunc=np.sum) else: # Split according to request pdata = df.pivot_table(rows=['time'], cols=(['sound', 'block'] + split_on), values=['counts', 'trials'], aggfunc=np.sum) # Double-check we didn't lose data #if len(df) != pdata['counts'].shape[0] * pdata['counts'].shape[1]: if len(df) != np.sum(~np.isnan(pdata['counts'].values)): print "warning: refolded data doesn't match shape" print "avoid this warning by passing a single trace, or specifying merge column" # Iterate over sounds (one axis per sound) for n, sound_name in enumerate(['lehi', 'rihi', 'lelo', 'rilo']): # extract data LB_counts = pdata['counts'][sound_name]['LB'].dropna(axis=1).values.astype(np.int) LB_trials = pdata['trials'][sound_name]['LB'].dropna(axis=1).values.astype(np.int) PB_counts = pdata['counts'][sound_name]['PB'].dropna(axis=1).values.astype(np.int) PB_trials = pdata['trials'][sound_name]['PB'].dropna(axis=1).values.astype(np.int) assert(LB_counts.shape == LB_trials.shape) assert(PB_counts.shape == PB_trials.shape) assert(PB_counts.shape == LB_trials.shape) # get time vector and check for consistency # technically could be in arbitrary order, in which case will error times = pdata['counts'][sound_name]['LB'].index.values.astype(np.float) assert (times == pdata['trials'][sound_name]['LB'].index.values).all() assert (times == pdata['counts'][sound_name]['PB'].index.values).all() assert (times == pdata['trials'][sound_name]['PB'].index.values).all() # remove columns with no trials bad_cols1 = np.array([np.all(t == 0) for t in LB_trials.transpose()]) bad_cols2 = np.array([np.all(t == 0) for t in PB_trials.transpose()]) bad_cols = bad_cols1 | bad_cols2 print "dropping %d sessions with insufficient trials" % np.sum(bad_cols) LB_trials = LB_trials[:, ~bad_cols] LB_counts = LB_counts[:, ~bad_cols] PB_trials = PB_trials[:, ~bad_cols] PB_counts = PB_counts[:, ~bad_cols] assert LB_counts.shape[1] != 0 assert PB_counts.shape[1] != 0 # Create axis for this plot and plot means with errorbars ax = f.add_subplot(2, 2, n + 1) if plot_all: ax.plot(times, LB_counts / LB_trials.astype(np.float), label='LB', color='b') ax.plot(times, PB_counts / PB_trials.astype(np.float), label='PB', color='r') else: myutils.plot_mean_trace(ax=ax, x=times, data=LB_counts / LB_trials.astype(np.float), label='LB', color='b', axis=1, errorbar=True) myutils.plot_mean_trace(ax=ax, x=times, data=PB_counts / PB_trials.astype(np.float), label='PB', color='r', axis=1, errorbar=True) assert(LB_counts.shape == LB_trials.shape) assert(PB_counts.shape == PB_trials.shape) assert(PB_counts.shape == LB_trials.shape) if plot_difference: myutils.plot_mean_trace(ax=ax, x=times, data=( LB_counts / LB_trials.astype(np.float) - PB_counts / PB_trials.astype(np.float)), label='diff', color='m', axis=1, errorbar=True) ax.plot(times, np.zeros_like(times), 'k') if mark_significance: LB_rate = LB_counts / LB_trials.astype(np.float) PB_rate = PB_counts / PB_trials.astype(np.float) p_vals = scipy.stats.ttest_rel(LB_rate.transpose(), PB_rate.transpose())[1] if p_adj_meth is not None: p_vals = myutils.r_adj_pval(p_vals, meth=p_adj_meth) pp = np.where(p_vals < .05)[0] plt.plot(times[pp], np.zeros_like(pp), 'k*') pp = np.where(p_vals < .01)[0] plt.plot(times[pp], np.zeros_like(pp), 'ko', markerfacecolor='w') ax.set_title(myutils.longname[sound_name]) plt.legend(loc='best') plt.show() return f