def plot_inc_exc_trials(IncTrsMat, ax, title=None, ytitle=None, xlab='Trial #', ylab=None,): # Plot on heatmap. sns.heatmap(IncTrsMat, cmap='RdYlGn', center=0.5, cbar=False, ax=ax) # Set tick labels. putil.hide_tick_marks(ax) tr_ticks = [1] + list(np.arange(25, IncTrsMat.shape[1]+1, 25)) ax.xaxis.set_ticks(tr_ticks) ax.set_xticklabels(tr_ticks) putil.rot_xtick_labels(ax, 0) putil.rot_ytick_labels(ax, 0, va='center') putil.set_labels(ax, xlab, ylab, title, ytitle)
def plot_auc_heatmap(aroc_mat, cmap='viridis', events=None, xlbl_freq=500, ylbl_freq=10, xlab='time', ylab='unit index', title='AROC over time', ffig=None, fig=None): """Plot ROC AUC of list of units on heatmap.""" fig = putil.figure(fig) # Plot heatmap. yticklabels = np.arange(len(aroc_mat.index)) + 1 ax = pplot.heatmap(aroc_mat, vmin=0, vmax=1, cmap=cmap, xlab=xlab, ylab=ylab, title=title, yticklabels=yticklabels) # Format labels. xlbls = pd.Series(aroc_mat.columns.map(str)) xlbls[aroc_mat.columns % xlbl_freq != 0] = '' putil.set_xtick_labels(ax, lbls=xlbls) putil.rot_xtick_labels(ax, rot=0, ha='center') putil.sparsify_tick_labels(fig, ax, 'y', istart=ylbl_freq - 1, freq=ylbl_freq, reverse=True) putil.hide_tick_marks(ax) putil.hide_spines(ax) # Plot events. if events is not None: putil.plot_events(events, add_names=False, color='black', alpha=0.3, ls='-', lw=1, ax=ax) # Save plot. putil.save_fig(ffig, dpi=300)
def plot_trial_type_distribution(UA, RecInfo, utids=None, tr_par=('S1', 'Dir'), save_plot=False, fname=None): """Plot distribution of trial types.""" # Init. par_str = util.format_to_fname(str(tr_par)) if utids is None: utids = UA.utids(as_series=True) recs = util.get_subj_date_pairs(utids) tasks = RecInfo.index.get_level_values('task').unique() tasks = [task for task in UA.tasks() if task in tasks] # reorder tasks # Init plotting. putil.set_style('notebook', 'darkgrid') fig, gsp, axs = putil.get_gs_subplots(nrow=len(recs), ncol=len(tasks), subw=4, subh=3, create_axes=True) for ir, rec in enumerate(recs): for it, task in enumerate(tasks): ax = axs[ir, it] rt = rec + (task,) if rt not in RecInfo.index: ax.set_axis_off() continue # Get includecd trials and their parameters. inc_trs = RecInfo.loc[rt, 'trials'] utid = utids.xs(rt, level=('subj', 'date', 'task'))[0] TrData = UA.get_unit(utid[:-1], utid[-1]).TrData.loc[inc_trs] # Create DF to plot. anw_df = TrData[[tr_par, 'correct']].copy() anw_df['answer'] = 'error' anw_df.loc[anw_df.correct, 'answer'] = 'correct' all_df = anw_df.copy() all_df.answer = 'all' comb_df = pd.concat([anw_df, all_df]) if not TrData.size: ax.set_axis_off() continue # Plot as countplot. sns.countplot(x=tr_par, hue='answer', data=comb_df, hue_order=['all', 'correct', 'error'], ax=ax) sns.despine(ax=ax) putil.hide_tick_marks(ax) putil.set_max_n_ticks(ax, 6, 'y') ax.legend(loc=[0.95, 0.7]) # Add title. title = '{} {}'.format(rec, task) nce = anw_df.answer.value_counts() nc, ne = [nce[c] if c in nce else 0 for c in ('correct', 'error')] pnc, pne = 100*nc/nce.sum(), 100*ne/nce.sum() title += '\n\n# correct: {} ({:.0f}%)'.format(nc, pnc) title += ' # error: {} ({:.0f}%)'.format(ne, pne) putil.set_labels(ax, title=title, xlab=par_str) # Format legend. if (ir != 0) or (it != 0): ax.legend_.remove() # Save plot. if save_plot: title = 'Trial type distribution' if fname is None: fname = util.join(['results', 'decoding', 'prepare', par_str + '_trial_type_distr.pdf']) putil.save_fig(fname, fig, title, w_pad=3, h_pad=3)
def PD_across_units(UA, UInc, utids=None, fres=None, ffig=None): """ Test consistency/spread of PD across units per recording. What is the spread in the preferred directions across units? Return population level preferred direction (and direction selectivity), that can be used to determine dominant preferred direction to decode. """ # Init. if utids is None: utids = UA.utids(as_series=True) tasks = utids.index.get_level_values('task').unique() recs = util.get_subj_date_pairs(utids) # Get DS info frame. DSInfo = ua_query.get_DSInfo_table(UA, utids) DSInfo['include'] = UInc # Calculate population PD and DSI. dPPDres = {} for rec in recs: for task in tasks: # Init. rt = rec + (task,) rtDSInfo = DSInfo.xs(rt, level=[0, 1, -1]) if rtDSInfo.empty: continue # Calculate population PD and population DSI. res = direction.calc_PPD(rtDSInfo.loc[rtDSInfo.include]) dPPDres[rt] = res PPDres = pd.DataFrame(dPPDres).T # Save results. if fres is not None: results = {'DSInfo': DSInfo, 'PPDres': PPDres} util.write_objects(results, fres) # Plot results. # Init plotting. putil.set_style('notebook', 'darkgrid') fig, gsp, axs = putil.get_gs_subplots(nrow=len(recs), ncol=len(tasks), subw=6, subh=6, create_axes=True, ax_kws_list={'projection': 'polar'}) xticks = direction.deg2rad(constants.all_dirs + 360/8/2*deg) for ir, rec in enumerate(recs): for it, task in enumerate(tasks): # Init. rt = rec + (task,) rtDSInfo = DSInfo.xs(rt, level=[0, 1, -1]) ax = axs[ir, it] if rtDSInfo.empty: ax.set_axis_off() continue PDSI, PPD, PPDc, PADc = PPDres.loc[rt] # Plot PD - DSI on polar plot. sPPDc, sPADc = [int(v) if not np.isnan(v) else v for v in (PPDc, PADc)] title = (' '.join(rt) + '\n' + 'PPDc = {}$^\circ$ - {}$^\circ$'.format(PPDc, PADc) + ', PDSI = {:.2f}'.format(PDSI)) PDrad = direction.deg2rad(util.remove_dim_from_series(rtDSInfo.PD)) pplot.scatter(PDrad, rtDSInfo.DSI, rtDSInfo.include, ylim=[0, 1], title=title, ytitle=1.08, c='darkblue', ec='k', linewidth=1, s=80, alpha=0.8, zorder=2, ax=ax) # Highlight PPD and PAD. offsets = np.array([-45, 0, 45]) * deg for D, c in [(PPDc, 'g'), (PADc, 'r')]: if np.isnan(D): continue hlDs = direction.deg2rad(np.array(D+offsets)) for hlD, alpha in [(hlDs, 0.2), ([hlDs[1]], 0.4)]: pplot.bars(hlD, len(hlD)*[1], align='center', alpha=alpha, color=c, zorder=1, ax=ax) # Format ticks. ax.set_xticks(xticks, minor=True) ax.grid(b=True, axis='x', which='minor') ax.grid(b=False, axis='x', which='major') putil.hide_tick_marks(ax) # Save plot. title = 'Population direction selectivity' putil.save_fig(ffig, fig, title, w_pad=12, h_pad=20) return DSInfo, PPDres
def plot_DR(dirs, resp, DSI=None, PD=None, baseline=None, plot_type='line', complete_missing_dirs=False, color='b', title=None, ffig=None, ax=None): """ Plot response to each directions on polar plot, with a vector pointing to preferred direction (PD) with length DSI. Use plot_type to change between sector ('bar') and connected ('line') plot types. """ ax = putil.axes(ax, polar=True) # Plot baseline. if baseline is not None: putil.add_baseline(baseline, ax=ax) # Remove NaNs. all_dirs = dirs not_nan = np.array(~pd.isnull(dirs) & ~pd.isnull(resp)) dirs, resp = dirs[not_nan], np.array(resp[not_nan]) # Prepare data. # Complete missing directions with 0 response. if complete_missing_dirs: for i, d in enumerate(all_dirs): if d not in dirs: dirs = np.insert(dirs, i, d) * dirs.units resp = np.insert(resp, i, 0) * 1 / s rad_dirs = dirs.rescale(rad) # Plot response to each directions on polar plot. if plot_type == 'bar': # sector plot ndirs = all_dirs.size left_rad_dirs = rad_dirs - np.pi / ndirs # no need for this in MPL 2.0? w = 2 * np.pi / ndirs # same with edgecolor and else? pplot.bars(left_rad_dirs, resp, width=w, alpha=0.50, color=color, lw=1, edgecolor='w', title=title, ytitle=1.08, ax=ax) else: # line plot rad_dirs, resp = [np.append(v, [v[0]]) for v in (rad_dirs, resp)] pplot.lines(rad_dirs, resp, color=color, marker='o', lw=1, ms=4, mew=0, title=title, ytitle=1.08, ax=ax) ax.fill(rad_dirs, resp, color=color, alpha=0.15) # Add arrow representing PD and weighted DSI. if DSI is not None and PD is not None: rho = np.max(resp) * DSI xy = (float(PD.rescale(rad)), rho) arr_props = dict(facecolor=color, edgecolor='k', shrink=0.0, alpha=0.5) ax.annotate('', xy, xytext=(0, 0), arrowprops=arr_props) # Remove spines and tick marks, maximize tick labels. putil.set_spines(ax, False, False) putil.hide_tick_marks(ax) # Save and return plot. putil.save_fig(ffig) return ax
def plot_up_down_raster(Spikes, task, rec, itrs): """Plot spike raster for up-down dynamics analysis.""" # Set params for plotting. uids, trs = Spikes.index, Spikes.columns plot_trs = trs[itrs] ntrs = len(plot_trs) nunits = len(uids) tr_gap = nunits / 2 # Init figure. putil.set_style('notebook', 'ticks') fig = putil.figure(figsize=(10, ntrs)) ax = fig.add_subplot(111) # Per trial, per unit. for itr, tr in enumerate(plot_trs): for iu, uid in enumerate(uids): # Init y level and spike times. i = (tr_gap + nunits) * itr + iu spk_tr = Spikes.loc[uid, tr] # Plot (spike time, y-level) pairs. x = np.array(spk_tr.rescale('ms')) y = (i+1) * np.ones_like(x) patches = [Rectangle((xi-wsp/2, yi-hsp/2), wsp, hsp) for xi, yi in zip(x, y)] collection = PatchCollection(patches, facecolor=c, edgecolor=c) ax.add_collection(collection) # Add stimulus lines. for stim in constants.stim_dur.index: t_start, t_stop = constants.fixed_tr_prds.loc[stim] events = pd.DataFrame([(t_start, 't_start'), (t_stop, 't_stop')], index=['start', 'stop'], columns=['time', 'label']) putil.plot_events(events, add_names=False, color='grey', alpha=0.5, ls='-', lw=0.5, ax=ax) # Add inter-trial shading. for itr in range(ntrs+1): ymin = itr * (tr_gap + nunits) - tr_gap + 0.5 ax.axhspan(ymin, ymin+tr_gap, alpha=.05, color='grey') # Set tick labels. pos = np.arange(ntrs) * (tr_gap + nunits) + nunits/2 lbls = plot_trs + 1 putil.set_ytick_labels(ax, pos, lbls) # putil.sparsify_tick_labels(ax, 'y', freq=2, istart=1) putil.hide_tick_marks(ax, show_x_tick_mrks=True) # Format plot. xlim = constants.fixed_tr_prds.loc['whole trial'] ylim = [-tr_gap/2, ntrs * (nunits+tr_gap)-tr_gap/2] xlab = 'Time since S1 onset (ms)' ylab = 'Trial number' title = '{} {}'.format(rec, task) putil.format_plot(ax, xlim, ylim, xlab, ylab, title) putil.set_spines(ax, True, False, False, False) # Save figure. fname = 'UpDown_dynamics_{}_{}.pdf'.format(rec, task) ffig = util.join(['results', 'UpDown', fname]) putil.save_fig(ffig, fig, dpi=600)