Example #1
0
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()
Example #2
0
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