def summary_fig(contrasts, CURVES, Ntot): fig, AX = ge.figure(axes=(4, 1), figsize=(1., 1.)) AX[0].axis('off') if len(CURVES) > 1: ge.plot(contrasts, np.mean(np.array(CURVES), axis=0), sy=np.std(np.array(CURVES), axis=0), ax=AX[1]) else: AX[1].axis('off') ge.set_plot(AX[1], xlabel='contrast', ylabel='$\delta$ dF/F') AX[2].axis('off') ge.annotate(AX[2], 'n=%i/%i resp. cells' % (len(CURVES), Ntot), (0.5, .0), ha='center', va='top') frac_resp = len(CURVES) / Ntot data = np.array([100 * frac_resp, 100 * (1 - frac_resp)]) ge.pie(data, COLORS=[plt.cm.tab10(2), plt.cm.tab10(3)], pie_labels=[' %.1f%%' % (100 * d / data.sum()) for d in data], ext_labels=['', ''], ax=AX[3]) return fig
def plot_FOV(self): if self.fovMap.currentText() == 'black_to_green': cmap = ge.get_linear_colormap('k', ge.green) elif self.fovMap.currentText() == 'white_to_green': cmap = ge.get_linear_colormap('w', 'darkgreen') elif self.fovMap.currentText() == 'grey': cmap = ge.get_linear_colormap('w', 'darkgrey') else: cmap = ge.viridis self.fig, ax = ge.figure(figsize=(2., 4.), bottom=0, top=0, right=0., left=0.) self.data.show_CaImaging_FOV(\ self.fovType.currentText(), NL=float(self.fovNL.value()), cmap=cmap, ax=ax) ge.annotate(ax, self.fovLabel.text(), (.99, .99), ha='right', va='top', color='white') ge.show()
def population_analysis(FILES, min_time_minutes=2, exclude_subjects=[], ax=None, running_speed_threshold=0.1): times, fracs_running, subjects = [], [], [] if ax is None: fig, ax = ge.figure(figsize=(5, 1), top=5) else: fig = None for f in FILES: data = MultimodalData(f) if (data.nwbfile is not None) and ('Running-Speed' in data.nwbfile.acquisition): speed = data.nwbfile.acquisition['Running-Speed'].data[:] max_time = len( speed) / data.nwbfile.acquisition['Running-Speed'].rate if (max_time > 60 * min_time_minutes) and ( data.metadata['subject_ID'] not in exclude_subjects): times.append(max_time) fracs_running.append( 100 * np.sum(speed > running_speed_threshold) / len(speed)) subjects.append(data.metadata['subject_ID']) i = -1 for c, s in enumerate(np.unique(subjects)): s_cond = np.array(subjects) == s ax.bar(np.arange(1 + i, i + 1 + np.sum(s_cond)), np.array(fracs_running)[s_cond] + 1, width=.75, color=plt.cm.tab10(c % 10)) i += np.sum(s_cond) + 1 ax.bar([i + 2], [np.mean(fracs_running)], yerr=[np.std(fracs_running)], width=1.5, color='grey') ge.annotate(ax, 'frac. running:\n%.1f+/-%.1f %%' % (np.mean(fracs_running), np.std(fracs_running)), (i + 3, np.mean(fracs_running)), xycoords='data') ge.set_plot(ax, xticks=[], xlabel='\nrecording', ylabel=' frac. running (%)') ymax, i = ax.get_ylim()[1], -1 for c, s in enumerate(np.unique(subjects)): s_cond = np.array(subjects) == s ge.annotate(ax, s, (1 + i, ymax), rotation=90, color=plt.cm.tab10(c % 10), xycoords='data', size='x-small') i += np.sum(s_cond) + 1 return fig, ax
def summary_fig(results): other_keys = [] for key in results: if (key not in [ 'Ntot', 'significant', 'x-center', 'y-center', 'value' ]) and ('-bins' not in key): other_keys.append(key) fig, AX = ge.figure(axes=(2 + len(other_keys), 1), right=2, figsize=(1., 1.1)) if ('x-center' in results) and ('y-center' in results): ge.hist2d(results['x-center'], results['y-center'], bins=(results['x-center-bins'], results['y-center-bins']), ax=AX[0], xlabel='x-center ($^{o}$)', ylabel='y-center ($^{o}$)', title='max. resp.') elif ('x-center' in results): ge.hist(results['x-center'], bins=results['x-center-bins'], ax=AX[0], xlabel='x-center ($^{o}$)') elif ('y-center' in results): ge.hist(results['y-center'], bins=results['y-center-bins'], ax=AX[0], xlabel='y-center ($^{o}$)') else: AX[0].axis('off') for i, key in enumerate(other_keys): ge.hist(results[key], bins=results[key + '-bins'], ax=AX[i + 1], xlabel=key, title='max resp') AX[i + 1].set_xlabel(key, fontsize=8) ge.annotate(AX[-1], 'n=%i/%i resp. cells' % (np.sum(results['significant']), results['Ntot']), (0.5, .0), ha='center', va='top') frac_resp = np.sum(results['significant']) / results['Ntot'] data = np.array([100 * frac_resp, 100 * (1 - frac_resp)]) ge.pie(data, COLORS=[plt.cm.tab10(2), plt.cm.tab10(3)], pie_labels=[' %.1f%%' % (100 * d / data.sum()) for d in data], ext_labels=['', ''], ax=AX[-1]) return fig
def plot_raw_data(self): self.fig, ax = ge.figure(axes_extents=[[[6, 4]]], bottom=0.1, right=3., top=0.5) Tbar = 1 # by default if (self.xmin.text() == '') or (self.xmax.text() == ''): tlim = [0, 20] else: tlim = [float(self.xmin.text()), float(self.xmax.text())] if self.xbar.text() != '': Tbar = float(self.xbar.text()) settings = {} for mod in self.modalities: if getattr(self, mod + 'Plot').value() > 0: settings[mod] = dict(fig_fraction=getattr(self, mod + 'Plot').value()) for key in ['CaImaging', 'CaImagingSum']: if (key in settings) and (self.sqbox.text() in [ 'dF/F', 'Fluorescence', 'Neuropil', 'Deconvolved' ]): settings[key]['subquantity'] = self.sqbox.text() if 'CaImaging' in settings: settings['CaImaging']['roiIndices'] = self.roiIndices self.data.plot_raw_data(tlim, settings=settings, Tbar=Tbar, ax=ax) if self.annot.isChecked(): ge.annotate( self.fig, "%s, %s, %s, %s" % (self.data.metadata['subject_ID'], self.data.protocols[self.pbox.currentIndex() - 1][:20], self.data.metadata['filename'].split('\\')[-2], self.data.metadata['filename'].split('\\')[-1]), (1, 1), color='k', ha='right', va='top', size='x-small') ge.show()
def __init__(self, figsize=(.5,1.), wspace=0.4, top=2.): pattern = [[2,1],[2,1],[2,1],[2,1], # patches [1,1], # -- space -- [3,1], # looming [1,1], # -- space -- [2,1],[2,1],[2,1],[2,1], # patches [1,1], # -- space -- [2,1],[2,1],[2,1],[2,1]] self.fig, self.AX = ge.figure(axes_extents=[pattern], figsize=(.5,1.), wspace=wspace, top=top, reshape_axes=False) for iax in [4,6,11]: self.AX[0][iax].axis('off') ge.annotate(self.AX[0][1], 'static-patches\n\n', (1,1), ha='center') ge.annotate(self.AX[0][5], 'looming-stim\n\n', (.5,1), ha='center') ge.annotate(self.AX[0][8], 'drifting-gratings\n\n', (1,1), ha='center') ge.annotate(self.AX[0][13], 'moving-dots\n\n', (1,1), ha='center')
def make_proportion_fig(data, rois_of_interest_contour, rois_of_interest_motion, rois_of_interest_contour_only): fig, ax = ge.figure(figsize=(1.2, 1), top=1, bottom=2) n = 0 ticks = [] for key in list(rois_of_interest_contour.keys())[::2]: ax.bar([n], [100. * len(rois_of_interest_contour[key]) / data.nROIs], color=ge.blue) ticks.append(key) n += 1 print(list(rois_of_interest_motion.keys())[::2]) for key in list(rois_of_interest_motion.keys())[::2]: ax.bar([n], [100. * len(rois_of_interest_motion[key]) / data.nROIs], color=ge.orange) ticks.append(key) n += 1 for key in rois_of_interest_contour_only: ax.bar([n], [100. * len(rois_of_interest_contour_only[key]) / data.nROIs], color=ge.blue) ticks.append(key) n += 1 ge.annotate(ax, 'contour', (0, .95), size='small', color=ge.blue) ge.annotate(ax, 'motion', (0.5, .95), size='small', color=ge.orange, ha='center') ge.annotate(ax, 'contour\nonly', (1, .95), size='small', color=ge.blue, ha='right', va='top') ge.set_plot(ax, xticks=np.arange(n), xticks_labels=ticks, xticks_rotation=90, ylabel='responsive ROI (%) ') return fig, ax
def plot_row_column_of_quantity(self): single_cond = self.build_single_conditions() COL_CONDS = self.build_column_conditions() ROW_CONDS = self.build_row_conditions() COLOR_CONDS = self.build_color_conditions() if (len(COLOR_CONDS) > 1) and (self.color.text() != ''): COLORS = [ getattr(ge, self.color.text())((c % 10) / 10.) for c in np.arange(len(COLOR_CONDS)) ] elif (len(COLOR_CONDS) > 1): COLORS = [ ge.tab10((c % 10) / 10.) for c in np.arange(len(COLOR_CONDS)) ] elif self.color.text() != '': COLORS = [getattr(ge, self.color.text())] else: COLORS = ['k'] if self.fig_presets.currentText() == 'raw-traces-preset': fig, AX = ge.figure(axes=(len(COL_CONDS), len(ROW_CONDS)), reshape_axes=False, top=0.4, bottom=0.4, left=0.7, right=0.7, wspace=0.5, hspace=0.5) else: fig, AX = ge.figure(axes=(len(COL_CONDS), len(ROW_CONDS)), reshape_axes=False) self.ylim = [np.inf, -np.inf] for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array( single_cond & col_cond & row_cond & color_cond)[:self.EPISODES['resp'].shape[0]] if self.EPISODES['resp'][cond, :].shape[0] > 0: my = self.EPISODES['resp'][cond, :].mean(axis=0) if self.withSTDbox.isChecked(): sy = self.EPISODES['resp'][cond, :].std(axis=0) ge.plot(self.EPISODES['t'], my, sy=sy, ax=AX[irow][icol], color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my - sy)]), max([self.ylim[1], np.max(my + sy)]) ] else: AX[irow][icol].plot(self.EPISODES['t'], my, color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my)]), max([self.ylim[1], np.max(my)]) ] if self.screen.isChecked() and not (self.parent.visual_stim is not None): print('initializing stim [...]') self.parent.load_VisualStim() if self.screen.isChecked(): inset = ge.inset(AX[irow][icol], [.8, .9, .3, .25]) self.parent.visual_stim.show_frame(\ self.EPISODES['index_from_start'][cond][0], ax=inset, parent=self.parent, enhance=True, label=None) if self.withStatTest.isChecked(): for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array( single_cond & col_cond & row_cond & color_cond)[:self.EPISODES['resp'].shape[0]] test = stat_test_for_evoked_responses( self.EPISODES, cond, interval_pre=[self.t0pre, self.t1pre], interval_post=[self.t0post, self.t1post], test='wilcoxon') AX[irow][icol].plot([self.t0pre, self.t1pre], self.ylim[0] * np.ones(2), 'k-', lw=2) AX[irow][icol].plot([self.t0post, self.t1post], self.ylim[0] * np.ones(2), 'k-', lw=2) ps, size = pval_to_star(test) AX[irow][icol].annotate( ps, ((self.t1pre + self.t0post) / 2., self.ylim[0]), va='top', ha='center', size=size, xycoords='data') if (self.ymin.text() != '') and (self.ymax.text() != ''): self.ylim = [float(self.ymin.text()), float(self.ymax.text())] if (self.xmin.text() != '') and (self.xmax.text() != ''): self.xlim = [float(self.xmin.text()), float(self.xmax.text())] else: self.xlim = [self.EPISODES['t'][0], self.EPISODES['t'][-1]] for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): ge.set_plot(AX[irow][icol], spines=(['left', 'bottom'] if self.axis.isChecked() else []), ylim=self.ylim, xlim=self.xlim, xlabel=(self.xbarlabel.text() if self.axis.isChecked() else ''), ylabel=(self.ybarlabel.text() if self.axis.isChecked() else '')) if self.stim.isChecked(): AX[irow][icol].fill_between( [0, np.mean(self.EPISODES['time_duration'])], self.ylim[0] * np.ones(2), self.ylim[1] * np.ones(2), color='grey', alpha=.2, lw=0) if not self.axis.isChecked(): ge.draw_bar_scales(AX[0][0], Xbar=(0. if self.xbar.text() == '' else float( self.xbar.text())), Xbar_label=self.xbarlabel.text(), Ybar=(0. if self.ybar.text() == '' else float( self.ybar.text())), Ybar_label=self.ybarlabel.text(), Xbar_fraction=0.1, Xbar_label_format='%.1f', Ybar_fraction=0.2, Ybar_label_format='%.1f', loc='top-left') if self.label.text() != '': ge.annotate(fig, ' '+self.label.text()+\ (1+int(self.nlabel.text()))*'\n', (0,0), color=COLORS[0], ha='left', va='bottom') if self.annot.isChecked(): S = '' if hasattr(self, 'roiPick'): S += 'roi #%s' % self.roiPick.text() for i, key in enumerate(self.varied_parameters.keys()): if 'single-value' in getattr(self, '%s_plot' % key).currentText(): S += ', %s=%.2f' % (key, getattr( self, '%s_values' % key).currentText()) ge.annotate(fig, S, (0, 0), color='k', ha='left', va='bottom') return fig, AX
def analysis_pdf(datafile, Nmax=1000000): data = MultimodalData(datafile) stim_duration = data.metadata['Protocol-1-presentation-duration'] interval_post = [1. / 2. * stim_duration, stim_duration] interval_pre = [interval_post[0] - interval_post[1], 0] try: # find the protocol with the many-standards iprotocol_MS = np.argwhere([('many-standards' in p) for p in data.protocols])[0][0] # find the protocol with the oddball-1 iprotocol_O1 = np.argwhere([('oddball-1' in p) for p in data.protocols])[0][0] # find the protocol with the oddball-2 iprotocol_O2 = np.argwhere([('oddball-2' in p) for p in data.protocols])[0][0] # mismatch negativity angles MM_angles = [ data.metadata['Protocol-%i-angle-redundant (deg)' % (1 + iprotocol_O1)], data.metadata['Protocol-%i-angle-deviant (deg)' % (1 + iprotocol_O1)] ] # DATA = {'stim_duration': stim_duration} DATA[str(int(MM_angles[0]))] = { 'iprotocol_control': iprotocol_MS, 'control': [], 'redundant': [], 'deviant': [], 'responsive': [] } DATA[str(int(MM_angles[1]))] = { 'iprotocol_control': iprotocol_MS, 'control': [], 'redundant': [], 'deviant': [], 'responsive': [] } DATA[str( int(data.metadata[ 'Protocol-%i-angle-redundant (deg)' % (1 + iprotocol_O1)]))]['iprotocol_redundant'] = iprotocol_O1 DATA[str( int(data.metadata[ 'Protocol-%i-angle-deviant (deg)' % (1 + iprotocol_O1)]))]['iprotocol_deviant'] = iprotocol_O1 DATA[str( int(data.metadata[ 'Protocol-%i-angle-redundant (deg)' % (1 + iprotocol_O2)]))]['iprotocol_redundant'] = iprotocol_O2 DATA[str( int(data.metadata[ 'Protocol-%i-angle-deviant (deg)' % (1 + iprotocol_O2)]))]['iprotocol_deviant'] = iprotocol_O2 # find the angle for the redundant and deviant conditions print(data.metadata['Protocol-3-angle-redundant (deg)'], data.metadata['Protocol-3-angle-deviant (deg)']) Nresp, Nresp_selective, SIs = 0, 0, [] pdf_OS = PdfPages( os.path.join( summary_pdf_folder(datafile), '%s-orientation_selectivity.pdf' % data.protocols[iprotocol_MS])) pdf_MSO = PdfPages( os.path.join( summary_pdf_folder(datafile), '%s-mismatch_selective_only.pdf' % data.protocols[iprotocol_MS])) pdf_MA = PdfPages( os.path.join(summary_pdf_folder(datafile), '%s-mismatch_all.pdf' % data.protocols[iprotocol_MS])) for roi in np.arange(data.iscell.sum())[:Nmax]: print(' - MMN analysis for ROI #%i / %i' % (roi + 1, data.iscell.sum())) ## ORIENTATION SELECTIVITY ANALYSIS fig, SI, responsive, responsive_angles = ODS.OS_ROI_analysis( data, roiIndex=roi, iprotocol=iprotocol_MS, stat_test_props=dict(interval_pre=interval_pre, interval_post=interval_post, test='wilcoxon', positive=True), with_responsive_angles=True) pdf_OS.savefig() # saves the current figure into a pdf page plt.close() if responsive: Nresp += 1 SIs.append(SI) EPISODES = EpisodeResponse( data, protocol_id=None, # means all quantity='CaImaging', subquantity='dF/F', roiIndex=roi) fig, AX = ge.figure(axes=(2, 1), wspace=3., right=10.) responsive_for_at_least_one = False ge.annotate(fig, 'ROI #%i' % (roi + 1), (0.02, 0.98), va='top') for angle, ax in zip(MM_angles, AX): DATA[str(int(angle))]['responsive'].append( False) # False by default ge.title(ax, '$\\theta$=%.1f$^{o}$' % angle) for ik, key, color in zip(range(3), ['control', 'redundant', 'deviant'], ['k', ge.blue, ge.red]): cond = data.get_stimulus_conditions([ np.array(DATA[str(int(angle))]['iprotocol_%s' % key]), np.array([float(angle)]) ], ['protocol_id', 'angle'], None)[0] ge.plot(EPISODES.t, EPISODES.resp[cond, :].mean(axis=0), sy=EPISODES.resp[cond, :].std(axis=0), color=color, ax=ax, no_set=True) ge.annotate(ax, ik * '\n' + '%s, n=%i' % (key, np.sum(cond)), (0.98, 1.), color=color, va='top', size='small') # storing for population analysis: DATA[str(int(angle))][key].append( EPISODES.resp[cond, :].mean(axis=0)) if angle in responsive_angles: responsive_for_at_least_one = True DATA[str(int( angle))]['responsive'][-1] = True # shift to True ge.set_plot(ax, xlabel='time (s)', ylabel='dF/F') pdf_MA.savefig() if responsive_for_at_least_one: pdf_MSO.savefig() plt.close() for angle in MM_angles: fig, AX = modulation_summary_panel(EPISODES.t, DATA[str(int(angle))], title='$\\theta$=%.1f$^{o}$' % angle) pdf_MA.savefig() plt.close() fig, AX = modulation_summary_panel(EPISODES.t, DATA[str(int(angle))], title='$\\theta$=%.1f$^{o}$' % angle, responsive_only=True) pdf_MSO.savefig() plt.close() # orientation selectivity summary ODS.summary_fig(Nresp, data.iscell.sum(), SIs, label='Orient. Select. Index') pdf_OS.savefig() # saves the current figure into a pdf page plt.close() # modulation summary for pdf in [pdf_OS, pdf_MSO, pdf_MA]: pdf.close() print('[ok] mismatch negativity analysis saved in: "%s" ' % summary_pdf_folder(datafile)) except BaseException as be: print('\n', be) print('---------------------------------------') print(' /!\ Pb with mismatch negativity analysis /!\ ')
def plot_trial_average( self, # episodes props protocol_id=0, quantity='Photodiode-Signal', subquantity='dF/F', roiIndex=0, dt_sampling=1, # ms interpolation='linear', baseline_substraction=False, prestim_duration=None, condition=None, COL_CONDS=None, column_keys=[], column_key='', ROW_CONDS=None, row_keys=[], row_key='', COLOR_CONDS=None, color_keys=[], color_key='', fig_preset='', xbar=0., xbarlabel='', ybar=0., ybarlabel='', with_std=True, with_screen_inset=False, with_stim=True, with_axis=False, with_stat_test=False, stat_test_props={}, color='k', label='', ylim=None, xlim=None, fig=None, AX=None, verbose=False): # ----- building episodes ------ self.roiIndices = [roiIndex] self.CaImaging_key = subquantity self.EPISODES = build_episodes( self, protocol_id=protocol_id, quantity=quantity, prestim_duration=prestim_duration, dt_sampling=dt_sampling, baseline_substraction=baseline_substraction, verbose=verbose) # this sets "self.Pcond" if with_screen_inset and (self.visual_stim is None): print('initializing stim [...]') self.init_visual_stim() if condition is None: condition = np.ones(np.sum(self.Pcond), dtype=bool) elif len(condition) == len(self.Pcond): condition = condition[self.Pcond] # ----- building episodes ------ if column_key != '': COL_CONDS = self.build_conditions([ np.sort( np.unique( self.nwbfile.stimulus[column_key].data[self.Pcond])) ], [column_key]) elif column_keys != '': COL_CONDS = self.build_conditions([ np.sort(np.unique(self.nwbfile.stimulus[key].data[self.Pcond])) for key in column_keys ], column_keys) elif (COL_CONDS is None): COL_CONDS = [np.ones(np.sum(self.Pcond), dtype=bool)] if row_key != '': ROW_CONDS = self.build_conditions([ np.sort( np.unique(self.nwbfile.stimulus[row_key].data[self.Pcond])) ], [row_key]) elif row_keys != '': ROW_CONDS = self.build_conditions([ np.sort(np.unique(self.nwbfile.stimulus[key].data[self.Pcond])) for key in row_keys ], row_keys) elif (ROW_CONDS is None): ROW_CONDS = [np.ones(np.sum(self.Pcond), dtype=bool)] if COLOR_CONDS is None: COLOR_CONDS = [np.ones(np.sum(self.Pcond), dtype=bool)] # if (len(COLOR_CONDS)>1) and (self.color.text()!=''): # COLORS = [getattr(ge, self.color.text())((c%10)/10.) for c in np.arange(len(COLOR_CONDS))] # elif (len(COLOR_CONDS)>1): # COLORS = [ge.tab10((c%10)/10.) for c in np.arange(len(COLOR_CONDS))] # elif self.color.text()!='': # COLORS = [getattr(ge, self.color.text())] # else: COLORS = [color] if (fig is None) and (AX is None) and (fig_preset == 'raw-traces-preset'): fig, AX = ge.figure(axes=(len(COL_CONDS), len(ROW_CONDS)), reshape_axes=False, top=0.4, bottom=0.4, left=0.7, right=0.7, wspace=0.5, hspace=0.5) elif (fig is None) and (AX is None): fig, AX = ge.figure(axes=(len(COL_CONDS), len(ROW_CONDS)), reshape_axes=False) self.ylim = [np.inf, -np.inf] for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array( condition & col_cond & row_cond & color_cond)[:self.EPISODES['resp'].shape[0]] if self.EPISODES['resp'][cond, :].shape[0] > 0: my = self.EPISODES['resp'][cond, :].mean(axis=0) if with_std: sy = self.EPISODES['resp'][cond, :].std(axis=0) ge.plot(self.EPISODES['t'], my, sy=sy, ax=AX[irow][icol], color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my - sy)]), max([self.ylim[1], np.max(my + sy)]) ] else: AX[irow][icol].plot(self.EPISODES['t'], my, color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my)]), max([self.ylim[1], np.max(my)]) ] if with_screen_inset: inset = ge.inset(AX[irow][icol], [.8, .9, .3, .25]) self.visual_stim.show_frame(\ self.EPISODES['index_from_start'][cond][0], ax=inset, enhance=True, label=None) if with_stat_test: for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array( single_cond & col_cond & row_cond & color_cond)[:self.EPISODES['resp'].shape[0]] test = stat_test_for_evoked_responses( self.EPISODES, cond, **stat_test_props) AX[irow][icol].plot(stat_test_props['interval_pre'], self.ylim[0] * np.ones(2), 'k-', lw=1) AX[irow][icol].plot(stat_test_props['interval_post'], self.ylim[0] * np.ones(2), 'k-', lw=1) ps, size = pval_to_star(test) AX[irow][icol].annotate( ps, ((stat_test_props['interval_post'][0] + stat_test_props['interval_pre'][1]) / 2., self.ylim[0]), va='top', ha='center', size=size, xycoords='data') if xlim is None: self.xlim = [self.EPISODES['t'][0], self.EPISODES['t'][-1]] else: self.xlim = xlim if ylim is not None: self.ylim = ylim for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): ge.set_plot( AX[irow][icol], spines=(['left', 'bottom'] if with_axis else []), # xlabel=(self.xbarlabel.text() if with_axis else ''), # ylabel=(self.ybarlabel.text() if with_axis else ''), ylim=self.ylim, xlim=self.xlim) if with_stim: AX[irow][icol].fill_between( [0, np.mean(self.EPISODES['time_duration'])], self.ylim[0] * np.ones(2), self.ylim[1] * np.ones(2), color='grey', alpha=.2, lw=0) if not with_axis: ge.draw_bar_scales(AX[0][0], Xbar=xbar, Xbar_label=xbarlabel, Ybar=ybar, Ybar_label=ybarlabel, Xbar_fraction=0.1, Xbar_label_format='%.1f', Ybar_fraction=0.2, Ybar_label_format='%.1f', loc='top-left') if label != '': ge.annotate(fig, label, (0, 0), color=color, ha='left', va='bottom') # if self.annot.isChecked(): # S='' # if hasattr(self, 'roiPick'): # S+='roi #%s' % self.roiPick.text() # for i, key in enumerate(self.varied_parameters.keys()): # if 'single-value' in getattr(self, '%s_plot' % key).currentText(): # S += ', %s=%.2f' % (key, getattr(self, '%s_values' % key).currentText()) # ge.annotate(fig, S, (0,0), color='k', ha='left', va='bottom') return fig, AX
def analysis_fig(data, running_speed_threshold=0.1): MODALITIES, QUANTITIES, TIMES, UNITS, COLORS = find_modalities(data) n = len(MODALITIES) + int(len(MODALITIES) * (len(MODALITIES) - 1) / 2) plt.style.use('ggplot') fig, AX = plt.subplots(n, 5, figsize=(11.4, 2.5 * n)) if n == 1: AX = [AX] plt.subplots_adjust(left=0.06, right=0.98, bottom=0.3 / n, top=0.9, wspace=.5, hspace=.6) for i, mod, quant, times, unit, color in zip(range(len(TIMES)), MODALITIES, QUANTITIES, TIMES, UNITS, COLORS): AX[i][0].set_title(mod, fontsize=10, color=color) quantity = (quant.data[:] if times is None else quant) if mod == 'GazeMovement': nsamples = data.nwbfile.processing['Pupil'].data_interfaces[ 'cx'].num_samples subsampling = np.max([1, int(nsamples / 1000)]) cx = data.nwbfile.processing['Pupil'].data_interfaces[ 'cx'].data[:][::subsampling] cy = data.nwbfile.processing['Pupil'].data_interfaces[ 'cy'].data[:][::subsampling] ge.scatter(cx - np.mean(cx), cy - np.mean(cy), ax=AX[i][0], color=color, ms=1, lw=0.05) ge.set_plot(AX[i][0], xlabel='x (mm)', ylabel='y (mm)') AX[i][0].axis('equal') else: AX[i][0].axis('off') if mod == 'Running-Speed': inset = AX[i][0].inset_axes([0.2, 0.2, 0.6, 0.6]) frac_running = np.sum( quantity > running_speed_threshold) / len(quantity) D = np.array([100 * frac_running, 100 * (1 - frac_running)]) ge.pie( [100 * frac_running, 100 * (1 - frac_running)], ax=inset, # pie_labels = ['%.1f%%\n' % (100*d/D.sum()) for d in D], COLORS=[color, 'lightgrey'], ext_labels=[ 'run \n%.1f%% ' % (100 * frac_running), ' rest \n%.1f%% ' % (100 * (1 - frac_running)) ]) ge.annotate(AX[0][0], 'thresh=%.1fcm/s' % running_speed_threshold, (0.5, 0), ha='center', va='top') AX[i][1].hist(quantity, bins=10, weights=100 * np.ones(len(quantity)) / len(quantity), color=color) AX[i][1].set_xlabel(unit, fontsize=10) AX[i][1].set_ylabel('occurence (%)', fontsize=10) quantity = (quant.data[:] if times is None else quant) AX[i][2].hist(quantity, bins=10, weights=100 * np.ones(len(quantity)) / len(quantity), log=True, color=color) AX[i][2].set_xlabel(unit, fontsize=10) AX[i][2].set_ylabel('occurence (%)', fontsize=10) CC, ts = autocorrel_on_NWB_quantity( Q1=(quant if times is None else None), q1=(quantity if times is not None else None), t_q1=times, tmax=180) AX[i][3].plot(ts / 60., CC, '-', color=color, lw=2) AX[i][3].set_xlabel('time (min)', fontsize=9) AX[i][3].set_ylabel('auto correl.', fontsize=9) CC, ts = autocorrel_on_NWB_quantity( Q1=(quant if times is None else None), q1=(quantity if times is not None else None), t_q1=times, tmax=20) AX[i][4].plot(ts, CC, '-', color=color, lw=2) AX[i][4].set_xlabel('time (s)', fontsize=9) AX[i][4].set_ylabel('auto correl.', fontsize=9) for i1 in range(len(UNITS)): m1, q1, times1, unit1 = MODALITIES[i1], QUANTITIES[i1], TIMES[ i1], UNITS[i1] for i2 in range(i1 + 1, len(UNITS)): i += 1 m2, q2, times2, unit2 = MODALITIES[i2], QUANTITIES[i2], TIMES[ i2], UNITS[i2] AX[i][0].set_title(m1 + ' vs ' + m2 + 10 * ' ', fontsize=10) if times1 is None: Q1, qq1 = q1, None else: Q1, qq1 = None, q1 if times2 is None: Q2, qq2 = q2, None else: Q2, qq2 = None, q2 hist, be1, be2 = hist2D_on_NWB_quantity(Q1=Q1, Q2=Q2, q1=qq1, t_q1=times1, q2=qq2, t_q2=times2, bins=40) hist = np.log(np.clip(hist, np.min(hist[hist > 0]), np.max(hist))) ge.matrix(hist, x=be1, y=be2, colormap=plt.cm.binary, ax=AX[i][0], aspect='auto') AX[i][0].grid(False) AX[i][0].set_xlabel(unit2, fontsize=8) AX[i][0].set_ylabel(unit1, fontsize=8) ge.annotate(AX[i][0], ' log distrib.', (0, 1), va='top', size='x-small') mean_q1, var_q1, mean_q2, var_q2 = crosshistogram_on_NWB_quantity( Q1=Q1, Q2=Q2, q1=qq1, t_q1=times1, q2=qq2, t_q2=times2, Npoints=30) AX[i][1].errorbar(mean_q1, mean_q2, xerr=var_q1, yerr=var_q2, color='k') AX[i][1].set_xlabel(unit1, fontsize=10) AX[i][1].set_ylabel(unit2, fontsize=10) mean_q1, var_q1, mean_q2, var_q2 = crosshistogram_on_NWB_quantity( Q1=Q2, Q2=Q1, q1=qq2, t_q1=times2, q2=qq1, t_q2=times1, Npoints=30) AX[i][2].errorbar(mean_q1, mean_q2, xerr=var_q1, yerr=var_q2, color='k') AX[i][2].set_xlabel(unit2, fontsize=10) AX[i][2].set_ylabel(unit1, fontsize=10) CCF, tshift = crosscorrel_on_NWB_quantity(Q1=Q2, Q2=Q1, q1=qq2, t_q1=times2, q2=qq1, t_q2=times1,\ tmax=180) AX[i][3].plot(tshift / 60, CCF, 'k-') AX[i][3].set_xlabel('time (min)', fontsize=10) AX[i][3].set_ylabel('cross correl.', fontsize=10) CCF, tshift = crosscorrel_on_NWB_quantity(Q1=Q2, Q2=Q1, q1=qq2, t_q1=times2, q2=qq1, t_q2=times1,\ tmax=20) AX[i][4].plot(tshift, CCF, 'k-') AX[i][4].set_xlabel('time (s)', fontsize=10) AX[i][4].set_ylabel('cross correl.', fontsize=10) return fig
def OS_ROI_analysis(FullData, roiIndex=0, iprotocol=0, subprotocol_id=0, verbose=False, response_significance_threshold=0.01, with_responsive_angles=False, stat_test_props=dict(interval_pre=[-2, 0], interval_post=[1, 3], test='wilcoxon', positive=True)): """ orientation selectivity ROI analysis """ EPISODES = EpisodeResponse(FullData, protocol_id=iprotocol, quantity='CaImaging', subquantity='dF/F', roiIndex=roiIndex) fig, AX = FullData.plot_trial_average( EPISODES=EPISODES, quantity='CaImaging', subquantity='dF/F', roiIndex=roiIndex, column_key='angle', ybar=1., ybarlabel='1dF/F', xbar=1., xbarlabel='1s', fig_preset='raw-traces-preset+right-space', with_annotation=True, with_stat_test=True, stat_test_props=stat_test_props, verbose=verbose) ax = ge.inset(fig, (0.88, 0.4, 0.1, 0.4)) angles, y, sy, responsive_angles = [], [], [], [] responsive = False for i, angle in enumerate(EPISODES.varied_parameters['angle']): stats = EPISODES.stat_test_for_evoked_responses( episode_cond=EPISODES.find_episode_cond('angle', i), **stat_test_props) angles.append(angle) y.append(np.mean(stats.y)) # means "post" sy.append(np.std(stats.y)) # std "post" if stats.significant(threshold=response_significance_threshold): responsive = True responsive_angles.append(angle) ge.plot(angles, np.array(y), sy=np.array(sy), ax=ax, axes_args=dict(ylabel='<post dF/F> ', xlabel='angle ($^{o}$)', xticks=angles, size='small'), m='o', ms=2, lw=1) SI = orientation_selectivity_index(angles, y) ge.annotate(fig, 'SI=%.2f ' % SI, (1, 0.97), va='top', ha='right', xycoords='figure fraction', weight='bold', fontsize=8, color=('k' if responsive else 'lightgray')) ge.annotate(fig, ('responsive' if responsive else 'unresponsive'), (0.78, 0.98), ha='left', va='top', xycoords='figure fraction', weight='bold', fontsize=8, color=(plt.cm.tab10(2) if responsive else plt.cm.tab10(3))) if with_responsive_angles: return fig, SI, responsive, responsive_angles else: return fig, SI, responsive
def plot_row_column_of_quantity(self): self.Pcond = self.data.get_protocol_cond(self.pbox.currentIndex() - 1) single_cond = self.build_single_conditions() COL_CONDS = self.build_column_conditions() ROW_CONDS = self.build_row_conditions() COLOR_CONDS = self.build_color_conditions() if (len(COLOR_CONDS) > 1) and (self.color.text() != ''): COLORS = [ getattr(ge, self.color.text())((c % 10) / 10.) for c in np.arange(len(COLOR_CONDS)) ] elif (len(COLOR_CONDS) > 1): COLORS = [ ge.tab10((c % 10) / 10.) for c in np.arange(len(COLOR_CONDS)) ] elif self.color.text() != '': COLORS = [getattr(ge, self.color.text())] else: COLORS = ['k'] fig, AX = ge.figure( axes=(len(COL_CONDS), len(ROW_CONDS)), **dv_tools.FIGURE_PRESETS[self.fig_presets.currentText()]) self.ylim = [np.inf, -np.inf] for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array(single_cond & col_cond & row_cond & color_cond)[:self.EPISODES.resp.shape[0]] if self.EPISODES.resp[cond, :].shape[0] > 0: my = self.EPISODES.resp[cond, :].mean(axis=0) if self.withSTDbox.isChecked(): sy = self.EPISODES.resp[cond, :].std(axis=0) ge.plot(self.EPISODES.t, my, sy=sy, ax=AX[irow][icol], color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my - sy)]), max([self.ylim[1], np.max(my + sy)]) ] else: AX[irow][icol].plot(self.EPISODES.t, my, color=COLORS[icolor], lw=1) self.ylim = [ min([self.ylim[0], np.min(my)]), max([self.ylim[1], np.max(my)]) ] if self.annot.isChecked(): # column label if (len(COL_CONDS) > 1) and (irow == 0) and (icolor == 0): s = '' for i, key in enumerate( self.varied_parameters.keys()): if 'column' in getattr( self, '%s_plot' % key).currentText(): s += format_key_value( key, getattr(self.EPISODES, key)[cond][0] ) + 4 * ' ' # should have a unique value ge.annotate(AX[irow][icol], s, (1, 1), ha='right', va='bottom') # row label if (len(ROW_CONDS) > 1) and (icol == 0) and (icolor == 0): s = '' for i, key in enumerate( self.varied_parameters.keys()): if 'row' in getattr(self, '%s_plot' % key).currentText(): s += format_key_value( key, getattr(self.EPISODES, key)[cond][0] ) + 4 * ' ' # should have a unique value ge.annotate(AX[irow][icol], s, (0, 0), ha='right', va='bottom', rotation=90) # n per cond ge.annotate(AX[irow][icol], ' n=%i' % np.sum(cond) + '\n' * icolor, (.99, 0), color=COLORS[icolor], size='xx-small', ha='left', va='bottom') if self.screen.isChecked() and not (self.data.visual_stim is not None): print('initializing stim [...]') self.data.init_visual_stim() if self.screen.isChecked(): inset = ge.inset(AX[irow][icol], [.8, .9, .3, .25]) self.data.visual_stim.show_frame(\ self.EPISODES.index_from_start[cond][0], ax=inset, enhance=True, label=None) if self.withStatTest.isChecked(): for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array( single_cond & col_cond & row_cond & color_cond)[:self.EPISODES.resp.shape[0]] results = self.EPISODES.stat_test_for_evoked_responses( episode_cond=cond, interval_pre=[self.t0pre, self.t1pre], interval_post=[self.t0post, self.t1post], test='wilcoxon') ps, size = results.pval_annot() AX[irow][icol].annotate( ps, ((self.t1pre + self.t0post) / 2., self.ylim[0]), va='top', ha='center', size=size, xycoords='data') AX[irow][icol].plot([self.t0pre, self.t1pre], self.ylim[0] * np.ones(2), 'k-', lw=2) AX[irow][icol].plot([self.t0post, self.t1post], self.ylim[0] * np.ones(2), 'k-', lw=2) # color label if self.annot.isChecked() and (len(COLOR_CONDS) > 1): for icolor, color_cond in enumerate(COLOR_CONDS): cond = np.array(single_cond & color_cond)[:self.EPISODES.resp.shape[0]] for i, key in enumerate(self.varied_parameters.keys()): if 'color' in getattr(self, '%s_plot' % key).currentText(): s = format_key_value( key, getattr(self.EPISODES, key)[cond][0]) ge.annotate(fig, s, (1. - icolor / (len(COLOR_CONDS) + 2), 0), color=COLORS[icolor], ha='right', va='bottom') if (self.ymin.text() != '') and (self.ymax.text() != ''): self.ylim = [float(self.ymin.text()), float(self.ymax.text())] if (self.xmin.text() != '') and (self.xmax.text() != ''): self.xlim = [float(self.xmin.text()), float(self.xmax.text())] else: self.xlim = [self.EPISODES.t[0], self.EPISODES.t[-1]] for irow, row_cond in enumerate(ROW_CONDS): for icol, col_cond in enumerate(COL_CONDS): ge.set_plot(AX[irow][icol], spines=(['left', 'bottom'] if self.axis.isChecked() else []), ylim=self.ylim, xlim=self.xlim, xlabel=(self.xbarlabel.text() if self.axis.isChecked() else ''), ylabel=(self.ybarlabel.text() if self.axis.isChecked() else '')) if self.stim.isChecked(): AX[irow][icol].fill_between( [0, np.mean(self.EPISODES.time_duration)], self.ylim[0] * np.ones(2), self.ylim[1] * np.ones(2), color='grey', alpha=.2, lw=0) if not self.axis.isChecked(): ge.draw_bar_scales(AX[0][0], Xbar=(0. if self.xbar.text() == '' else float( self.xbar.text())), Xbar_label=self.xbarlabel.text(), Ybar=(0. if self.ybar.text() == '' else float( self.ybar.text())), Ybar_label=self.ybarlabel.text() + ' ', Xbar_fraction=0.1, Xbar_label_format='%.1f', Ybar_fraction=0.2, Ybar_label_format='%.1f', loc='top-left') if self.label.text() != '': ge.annotate(fig, ' '+self.label.text()+\ (1+int(self.nlabel.text()))*'\n', (0,0), color=COLORS[0], ha='left', va='bottom') if self.annot.isChecked(): S = '' if hasattr(self, 'roiPick'): S += 'roi #%s, ' % self.roiPick.text() for i, key in enumerate(self.varied_parameters.keys()): if 'single-value' in getattr(self, '%s_plot' % key).currentText(): S += '%s=%s, ' % (key, getattr( self, '%s_values' % key).currentText()) ge.annotate(fig, S, (0, 0), color='k', ha='left', va='bottom') if self.annot.isChecked(): ge.annotate( fig, "%s, %s, %s, %s" % (self.data.metadata['subject_ID'], self.data.protocols[self.pbox.currentIndex() - 1][:20], self.data.metadata['filename'].split('\\')[-2], self.data.metadata['filename'].split('\\')[-1]), (0, 1), color='k', ha='left', va='top', size='x-small') return fig, AX
def ROI_analysis(FullData, roiIndex=0, iprotocol=0, verbose=False, response_significance_threshold=0.01, radius_threshold_for_center=20., with_responsive_angles=False, stat_test_props=dict(interval_pre=[-2, 0], interval_post=[1, 3], test='wilcoxon', positive=True), Npanels=4): """ direction selectivity ROI analysis """ EPISODES = EpisodeResponse(FullData, protocol_id=iprotocol, quantity='CaImaging', subquantity='dF/F', roiIndex=roiIndex) ROW_KEYS, ROW_VALUES, ROW_INDICES, Nfigs, ROW_BINS = [], [], [], 1, [] for key in ['x-center', 'y-center', 'contrast']: if key in EPISODES.varied_parameters: ROW_KEYS.append(key) ROW_VALUES.append(EPISODES.varied_parameters[key]) ROW_INDICES.append(np.arange(len(EPISODES.varied_parameters[key]))) Nfigs *= len(EPISODES.varied_parameters[key]) x = np.unique(EPISODES.varied_parameters[key]) ROW_BINS.append( np.concatenate([[x[0] - .5 * (x[1] - x[0])], .5 * (x[1:] + x[:-1]), [x[-1] + .5 * (x[-1] - x[-2])]])) fig, AX = FullData.plot_trial_average(EPISODES=EPISODES, protocol_id=iprotocol, quantity='CaImaging', subquantity='dF/F', roiIndex=roiIndex, column_key='radius', row_keys=ROW_KEYS, color_key='angle', ybar=1., ybarlabel='1dF/F', xbar=1., xbarlabel='1s', fig_preset='raw-traces-preset', with_annotation=True, with_std=False, with_stat_test=True, stat_test_props=stat_test_props, verbose=verbose) # now computing the size-response curve for all conditions if 'angle' in EPISODES.varied_parameters: ROW_KEYS.append('angle') ROW_VALUES.append(EPISODES.varied_parameters['angle']) ROW_INDICES.append(np.arange(len(EPISODES.varied_parameters['angle']))) Nfigs *= len(EPISODES.varied_parameters['angle']) x = np.unique(EPISODES.varied_parameters['angle']) ROW_BINS.append( np.concatenate([[x[0] - .5 * (x[1] - x[0])], .5 * (x[1:] + x[:-1]), [x[-1] + .5 * (x[-1] - x[-2])]])) fig2, AX = ge.figure(axes=(Npanels, int(Nfigs / Npanels)), hspace=1.5) full_resp = {'value': [], 'significant': [], 'radius': []} for key, bins in zip(ROW_KEYS, ROW_BINS): full_resp[key] = [] full_resp[key + '-bins'] = bins iax, ylims = 0, [10, -10] max_response_level, max_response_curve, imax_response_curve = 0, None, -1 for indices in itertools.product(*ROW_INDICES): title = '' for key, index in zip(ROW_KEYS, indices): title += format_key_value( key, EPISODES.varied_parameters[key] [index]) + ', ' # should have a unique value ge.title(ge.flat(AX)[iax], title, size='small') resp, radii, significants = [0], [0], [False] for ia, radius in enumerate(EPISODES.varied_parameters['radius']): # stat test "pre" vs "post" stats = EPISODES.stat_test_for_evoked_responses( episode_cond=EPISODES.find_episode_cond( ROW_KEYS + ['radius'], list(indices) + [ia]), **stat_test_props) resp.append(np.mean(stats.y - stats.x)) # "post"-"pre" radii.append(radius) ge.annotate(ge.flat(AX)[iax], ' ' + stats.pval_annot()[0], (radius, resp[-1]), size='x-small', rotation=90, ha='center', xycoords='data') significants.append( stats.significant(threshold=response_significance_threshold)) # store all in full resp for key, index in zip(ROW_KEYS, indices): full_resp[key].append(EPISODES.varied_parameters[key][index]) full_resp['radius'].append(radius) full_resp['value'].append(np.mean(stats.y - stats.x)) full_resp['significant'].append( stats.significant(threshold=response_significance_threshold)) # check if max resp center_cond = np.array(significants) & (np.array(radii) < radius_threshold_for_center) if np.sum(center_cond) and (np.max(np.array(resp)[center_cond]) > max_response_level): max_response_level = np.max(np.array(resp)[center_cond]) max_response_curve = np.array(resp) imax_response_curve = iax ylims = [ np.min([np.min(resp), ylims[0]]), np.max([np.max(resp), ylims[1]]) ] ge.flat(AX)[iax].plot(radii, resp, 'ko-', ms=4) iax += 1 for iax, ax in enumerate(ge.flat(AX)): ge.set_plot(ax, ylim=[ ylims[0] - .05 * (ylims[1] - ylims[0]), ylims[1] + .05 * (ylims[1] - ylims[0]) ], ylabel=('$\delta$ dF/F' if (iax % Npanels == 0) else ''), xlabel=('size ($^{o}$)' if (int(iax / Npanels) == (int(Nfigs / Npanels) - 1)) else '')) ax.fill_between([0, radius_threshold_for_center], ylims[0] * np.ones(2), ylims[1] * np.ones(2), color='k', alpha=0.05, lw=0) if iax == imax_response_curve: ax.fill_between(radii, ylims[0] * np.ones(len(radii)), ylims[1] * np.ones(len(radii)), color='k', alpha=0.1, lw=0) x = np.unique(EPISODES.varied_parameters['radius']) full_resp['radius-bins'] = np.concatenate([[x[0] - .5 * (x[1] - x[0])], .5 * (x[1:] + x[:-1]), [x[-1] + .5 * (x[-1] - x[-2])]]) for key in full_resp: full_resp[key] = np.array(full_resp[key]) return fig, fig2, radii, max_response_curve, imax_response_curve, full_resp
def DS_ROI_analysis(FullData, roiIndex=0, iprotocol=0, verbose=False, response_significance_threshold=0.01, with_responsive_angles=False, fig=None, AX=None, CaImaging_options=dict(quantity='CaImaging', subquantity='dF/F'), stat_test_props=dict(interval_pre=[-2, 0], interval_post=[1, 3], test='wilcoxon'), inset_coords=(0.92, 0.4, 0.07, 0.4)): """ direction selectivity ROI analysis """ EPISODES = EpisodeResponse(FullData, protocol_id=iprotocol, roiIndex=roiIndex, verbose=verbose, **CaImaging_options) fig, AX = FullData.plot_trial_average( EPISODES=EPISODES, protocol_id=iprotocol, roiIndex=roiIndex, column_key='angle', ybar=1., ybarlabel='1dF/F', xbar=1., xbarlabel='1s', fig=fig, AX=AX, no_set=False, fig_preset='raw-traces-preset+right-space', with_annotation=True, with_stat_test=True, stat_test_props=stat_test_props, verbose=verbose, **CaImaging_options) ax = ge.inset(fig, inset_coords) angles, y, sy, responsive_angles = [], [], [], [] responsive = False for i, angle in enumerate(EPISODES.varied_parameters['angle']): means_pre = EPISODES.compute_stats_over_repeated_trials( 'angle', i, interval_cond=EPISODES.compute_interval_cond( stat_test_props['interval_pre']), quantity='mean') means_post = EPISODES.compute_stats_over_repeated_trials( 'angle', i, interval_cond=EPISODES.compute_interval_cond( stat_test_props['interval_post']), quantity='mean') stats = EPISODES.stat_test_for_evoked_responses( episode_cond=EPISODES.find_episode_cond('angle', i), **stat_test_props) angles.append(angle) y.append(np.mean(means_post)) sy.append(np.std(means_post)) if stats.significant(response_significance_threshold): responsive = True responsive_angles.append(angle) ge.plot(angles, np.array(y), sy=np.array(sy), ax=ax, axes_args=dict(ylabel='<post dF/F> ', xlabel='angle ($^{o}$)', xticks=np.array(angles)[::int(len(angles) / 4)], size='small'), m='o', ms=2, lw=1) SI = orientation_selectivity_index(angles, y) ge.annotate(ax, 'SI=%.2f\n ' % SI, (1, 1), ha='right', weight='bold', fontsize=8, color=('k' if responsive else 'lightgray')) ge.annotate(ax, ('responsive' if responsive else 'unresponsive'), (0., 1), ha='left', weight='bold', fontsize=8, color=(plt.cm.tab10(2) if responsive else plt.cm.tab10(3))) if with_responsive_angles: return fig, SI, responsive, responsive_angles else: return fig, SI, responsive
def analysis_fig(data, roiIndex=0): MODALITIES, QUANTITIES, TIMES, UNITS, COLORS = find_modalities(data) plt.style.use('ggplot') fig, AX = plt.subplots(2 + len(MODALITIES), 5, figsize=(11.4, 2.3 * (2 + len(MODALITIES)))) plt.subplots_adjust(left=0.05, right=0.98, bottom=0.3 / (2 + len(MODALITIES)), top=0.94, wspace=.5, hspace=.5) if len(MODALITIES) == 0: AX = [AX] index = np.arange(len(data.iscell))[data.iscell][roiIndex] AX[0][0].annotate('ROI#%i' % (roiIndex + 1), (0.5, 0.5), weight='bold', fontsize=10, va='center', ha='center') AX[0][0].axis('off') AX[0][-1].axis('off') data.show_CaImaging_FOV(key='meanImgE', cmap='viridis', ax=AX[0][1], roiIndex=roiIndex) data.show_CaImaging_FOV(key='meanImgE', cmap='viridis', ax=AX[0][2], roiIndex=roiIndex, with_roi_zoom=True) try: data.show_CaImaging_FOV(key='meanImg_chan2', cmap='viridis', ax=AX[0][3], roiIndex=roiIndex, NL=3, with_roi_zoom=True) AX[0][3].annotate('red cell: %s' % ('yes' if bool(data.redcell[index]) else 'no'), (0.5, 0.), xycoords='axes fraction', fontsize=8, va='top', ha='center') except KeyError: AX[0][3].axis('off') AX[0][3].annotate('no red channel', (0.5, 0.5), xycoords='axes fraction', fontsize=9, va='center', ha='center') AX[1][0].hist(data.Fluorescence.data[index, :], bins=30, weights=100 * np.ones(len(data.dFoF[index, :])) / len(data.dFoF[index, :])) AX[1][0].set_xlabel('Fluo. (a.u.)', fontsize=10) AX[1][1].hist(data.dFoF[index, :], bins=30, weights=100 * np.ones(len(data.dFoF[index, :])) / len(data.dFoF[index, :])) AX[1][1].set_xlabel('dF/F', fontsize=10) AX[1][2].hist(data.dFoF[index, :], log=True, bins=30, weights=100 * np.ones(len(data.dFoF[index, :])) / len(data.dFoF[index, :])) AX[1][2].set_xlabel('dF/F', fontsize=10) for ax in AX[1][:3]: ax.set_ylabel('occurence (%)', fontsize=10) CC, ts = autocorrel_on_NWB_quantity(Q1=None, q1=data.dFoF[index, :], t_q1=data.Neuropil.timestamps[:], tmax=180) AX[1][3].plot(ts / 60., CC, '-', lw=2) AX[1][3].set_xlabel('time (min)', fontsize=10) AX[1][3].set_ylabel('auto correl.', fontsize=10) CC, ts = autocorrel_on_NWB_quantity(Q1=None, q1=data.dFoF[index, :], t_q1=data.Neuropil.timestamps[:], tmax=10) AX[1][4].plot(ts, CC, '-', lw=2) AX[1][4].set_xlabel('time (s)', fontsize=10) AX[1][4].set_ylabel('auto correl.', fontsize=10) for i, mod, quant, times, unit, color in zip(range(len(TIMES)), MODALITIES, QUANTITIES, TIMES, UNITS, COLORS): AX[2 + i][0].set_title(mod, fontsize=10, color=color) if times is None: Q, qq = quant, None else: Q, qq = None, quant try: hist, be1, be2 = hist2D_on_NWB_quantity( Q1=Q, Q2=None, q1=qq, t_q1=times, q2=data.dFoF[index, :], t_q2=data.Neuropil.timestamps[:], bins=(np.linspace(data.dFoF[index, :].min(), data.dFoF[index, :].max(), 50), 50)) hist = np.log(np.clip(hist, np.min(hist[hist > 0]), np.max(hist))) ge.matrix(hist, x=be1, y=be2, colormap=plt.cm.binary, ax=AX[2 + i][0], aspect='auto') AX[2 + i][0].grid(False) AX[2 + i][0].set_ylabel(unit, fontsize=8) AX[2 + i][0].set_xlabel('dF/F', fontsize=8) ge.annotate(AX[2 + i][0], ' log distrib.', (0, 1), va='top', size='x-small') mean_q1, var_q1, mean_q2, var_q2 = crosshistogram_on_NWB_quantity( Q1=Q, Q2=None, q1=qq, t_q1=times, q2=data.dFoF[index, :], t_q2=data.Neuropil.timestamps[:], Npoints=30) AX[2 + i][1].errorbar(mean_q1, mean_q2, xerr=var_q1, yerr=var_q2, color=color) AX[2 + i][1].set_xlabel(unit, fontsize=10) AX[2 + i][1].set_ylabel('dF/F', fontsize=10) mean_q1, var_q1, mean_q2, var_q2 = crosshistogram_on_NWB_quantity( Q2=Q, Q1=None, q2=qq, t_q2=times, q1=data.dFoF[index, :], t_q1=data.Neuropil.timestamps[:], Npoints=30) AX[2 + i][2].errorbar(mean_q1, mean_q2, xerr=var_q1, yerr=var_q2, color=color) AX[2 + i][2].set_ylabel(unit, fontsize=10) AX[2 + i][2].set_xlabel('dF/F', fontsize=10) CCF, tshift = crosscorrel_on_NWB_quantity( Q1=Q, Q2=None, q1=qq, t_q1=times, q2=data.dFoF[index, :], t_q2=data.Neuropil.timestamps[:], tmax=180) AX[2 + i][3].plot(tshift / 60, CCF, '-', color=color) AX[2 + i][3].set_xlabel('time (min)', fontsize=10) AX[2 + i][3].set_ylabel('cross correl.', fontsize=10) CCF, tshift = crosscorrel_on_NWB_quantity( Q1=Q, Q2=None, q1=qq, t_q1=times, q2=data.dFoF[index, :], t_q2=data.Neuropil.timestamps[:], tmax=20) AX[2 + i][4].plot(tshift, CCF, '-', color=color) AX[2 + i][4].set_xlabel('time (s)', fontsize=10) AX[2 + i][4].set_ylabel('cross correl.', fontsize=10) except BaseException as be: print(mod, ' -->', be) return fig
def ROI_analysis(FullData, roiIndex=0, iprotocol_center=0, iprotocol_surround=1, verbose=False, response_significance_threshold=0.01, radius_threshold_for_center=20., with_responsive_angles = False, stat_test_props=dict(interval_pre=[-2,0], interval_post=[1,3], test='wilcoxon', positive=True), Npanels=4): """ ROI analysis for secondary RF """ EPISODES_CENTER = EpisodeResponse(FullData, protocol_id=iprotocol_center, quantity='CaImaging', subquantity='dF/F', prestim_duration=2., roiIndex = roiIndex) EPISODES_SURROUND = EpisodeResponse(FullData, protocol_id=iprotocol_surround, quantity='CaImaging', subquantity='dF/F', prestim_duration=2., roiIndex = roiIndex) FIGS = [] for iangle, angle in enumerate(EPISODES_CENTER.varied_parameters['angle']): fig, AX = FullData.plot_trial_average(EPISODES=EPISODES_CENTER, condition=EPISODES_CENTER.find_episode_cond('angle', iangle), protocol_id=iprotocol_center, quantity='CaImaging', subquantity='dF/F', roiIndex = roiIndex, column_key='x-center', row_key='y-center', ybar=1., ybarlabel='1dF/F', xbar=1., xbarlabel='1s', fig_preset='raw-traces-preset', with_std=False, with_annotation=True, verbose=verbose, color=ge.blue) ge.annotate(fig, 'center ', (0.5, 0), color=ge.blue, ha='right') FullData.plot_trial_average(EPISODES=EPISODES_SURROUND, condition=EPISODES_SURROUND.find_episode_cond('angle', iangle), protocol_id=iprotocol_surround, quantity='CaImaging', subquantity='dF/F', roiIndex = roiIndex, column_key='x-center', row_key='y-center', with_std=False, with_stim=False, verbose=verbose, AX=AX, color=ge.red) ge.annotate(fig, ' surround', (0.5, 0), color=ge.red) ge.annotate(fig, format_key_value('angle', angle)+' ', (1., 0), ha='right') # just for the axis extent _, AX2 = FullData.plot_trial_average(EPISODES=EPISODES_SURROUND, condition=EPISODES_SURROUND.find_episode_cond('angle', iangle), protocol_id=iprotocol_surround, quantity='CaImaging', subquantity='dF/F', roiIndex = roiIndex, column_key='x-center', row_key='y-center') ylims = [0,1] for ax, ax2 in zip(ge.flat(AX), ge.flat(AX2)): ylims = [np.min([ylims[0], ax.get_ylim()[0], ax2.get_ylim()[0]]), np.max([ylims[1], ax.get_ylim()[1], ax2.get_ylim()[1]])] for ax in ge.flat(AX): ax.set_ylim(ylims) FIGS.append(fig) # fig2, AX = ge.figure(axes=(Npanels, int(Nfigs/Npanels)), hspace=1.5) # full_resp = {'value':[], 'significant':[], 'radius':[]} # for key, bins in zip(ROW_KEYS, ROW_BINS): # full_resp[key] = [] # full_resp[key+'-bins'] = bins # iax, ylims = 0, [10, -10] # max_response_level, max_response_curve, imax_response_curve = 0, None, -1 # for indices in itertools.product(*ROW_INDICES): # title = '' # for key, index in zip(ROW_KEYS, indices): # title+=format_key_value(key, EPISODES.varied_parameters[key][index])+', ' # should have a unique value # ge.title(ge.flat(AX)[iax], title, size='small') # resp, radii, significants = [0], [0], [False] # for ia, radius in enumerate(EPISODES.varied_parameters['radius']): # # stat test "pre" vs "post" # stats = EPISODES.stat_test_for_evoked_responses(episode_cond=EPISODES.find_episode_cond(ROW_KEYS+['radius'], list(indices)+[ia]), # **stat_test_props) # resp.append(np.mean(stats.y-stats.x)) # "post"-"pre" # radii.append(radius) # ge.annotate(ge.flat(AX)[iax], ' '+stats.pval_annot()[0], (radius, resp[-1]), # size='x-small', rotation=90, ha='center', xycoords='data') # significants.append(stats.significant(threshold=response_significance_threshold)) # # store all in full resp # for key, index in zip(ROW_KEYS, indices): # full_resp[key].append(EPISODES.varied_parameters[key][index]) # full_resp['radius'].append(radius) # full_resp['value'].append(np.mean(stats.y-stats.x)) # full_resp['significant'].append(stats.significant(threshold=response_significance_threshold)) # # check if max resp # center_cond = np.array(significants) & (np.array(radii)<radius_threshold_for_center) # if np.sum(center_cond) and (np.max(np.array(resp)[center_cond])>max_response_level): # max_response_level = np.max(np.array(resp)[center_cond]) # max_response_curve = np.array(resp) # imax_response_curve = iax # ylims = [np.min([np.min(resp), ylims[0]]), np.max([np.max(resp), ylims[1]])] # ge.flat(AX)[iax].plot(radii, resp, 'ko-', ms=4) # iax += 1 # for iax, ax in enumerate(ge.flat(AX)): # ge.set_plot(ax, ylim=[ylims[0]-.05*(ylims[1]-ylims[0]), ylims[1]+.05*(ylims[1]-ylims[0])], # ylabel=('$\delta$ dF/F' if (iax%Npanels==0) else ''), # xlabel=('size ($^{o}$)' if (int(iax/Npanels)==(int(Nfigs/Npanels)-1)) else '')) # ax.fill_between([0, radius_threshold_for_center], ylims[0]*np.ones(2), ylims[1]*np.ones(2), color='k', alpha=0.05, lw=0) # if iax==imax_response_curve: # ax.fill_between(radii, ylims[0]*np.ones(len(radii)), ylims[1]*np.ones(len(radii)), color='k', alpha=0.1, lw=0) # x = np.unique(EPISODES.varied_parameters['radius']) # full_resp['radius-bins'] = np.concatenate([[x[0]-.5*(x[1]-x[0])], .5*(x[1:]+x[:-1]), [x[-1]+.5*(x[-1]-x[-2])]]) # for key in full_resp: # full_resp[key] = np.array(full_resp[key]) # return fig, fig2, radii, max_response_curve, imax_response_curve, full_resp # return fig, None, None, None, None, None return FIGS
def modulation_summary_panel(t, data, title='', pre_interval=[-1, 0], post_interval=[1, 2], responsive_only=False): if responsive_only: fig, AX = ge.figure(axes=(4, 1), wspace=2) valid_cells = np.array(data['responsive']) # pie plot for responsiveness AX[0].pie([ 100 * np.sum(valid_cells) / len(valid_cells), 100 * (1 - np.sum(valid_cells) / len(valid_cells)) ], explode=(0, 0.1), colors=[plt.cm.tab10(2), plt.cm.tab10(3)], labels=['resp. ', ' unresp.'], autopct='%1.1f%%', shadow=True, startangle=90) iax = 1 else: fig, AX = ge.figure(axes=(3, 1), wspace=2) iax = 0 valid_cells = np.ones(len(data['control']), dtype=bool) ge.annotate(fig, '%s, n=%i ROIs' % (title, np.sum(valid_cells)), (0.05, 0.98), va='top') pre_cond = (t > pre_interval[0]) & (t < pre_interval[1]) post_cond = (t > post_interval[0]) & (t < post_interval[1]) evoked_levels = {} if np.sum(valid_cells) > 1: for ik, key, color in zip(range(3), ['redundant', 'control', 'deviant'], [ge.blue, 'k', ge.red]): y = np.array(data[key])[valid_cells, :] ge.plot(t, y.mean(axis=0), sy=y.std(axis=0), color=color, ax=AX[iax], no_set=True) y_bsl = y - np.mean(y[:, pre_cond], axis=1).reshape( (np.sum(valid_cells), 1)) ge.plot(t, y_bsl.mean(axis=0), sy=y_bsl.std(axis=0), color=color, ax=AX[iax + 1], no_set=True) # bar plot evoked_levels[key] = np.mean(y_bsl[:, post_cond], axis=1) AX[iax + 2].bar([ik], np.mean(evoked_levels[key]), yerr=np.std(evoked_levels[key]), lw=2, color=color) # adaptation effect (control vs redundant conditions) test = ttest_rel(evoked_levels['redundant'], evoked_levels['control']) AX[iax + 2].plot([0, 1], AX[iax + 2].get_ylim()[1] * np.ones(2), 'k-', lw=1) ge.annotate(AX[iax + 2], ge.from_pval_to_star(test.pvalue), (0.5, AX[iax + 2].get_ylim()[1]), ha='center', xycoords='data') # surprise effect (control vs deviant conditions) test = ttest_rel(evoked_levels['deviant'], evoked_levels['control']) AX[iax + 2].plot([1, 2], AX[iax + 2].get_ylim()[1] * np.ones(2), 'k-', lw=1) ge.annotate(AX[iax + 2], ge.from_pval_to_star(test.pvalue), (1.5, AX[iax + 2].get_ylim()[1]), ha='center', xycoords='data') # pre / post intervals ylim1 = AX[iax].get_ylim()[0] AX[iax].plot(pre_interval, ylim1 * np.ones(2), lw=1, color='dimgrey') AX[iax].plot(post_interval, ylim1 * np.ones(2), lw=1, color='dimgrey') ge.set_plot(AX[iax], xlabel='time (s)', ylabel='dF/F') ge.set_plot(AX[iax + 1], xlabel='time (s)', ylabel='$\Delta$ dF/F') ge.title(AX[iax + 1], 'baseline corrected', size='x-small') ge.set_plot(AX[iax + 2], xlabel='', ylabel='evoked $\Delta$ dF/F', xticks=[0, 1, 2], xticks_labels=['red.', 'ctrl', 'dev.'], xticks_rotation=70) return fig, AX
def interaction_fig(responses, static_patch_label='...', moving_dots_label='...', mixed_label='...', random=False, Ybar=0.2, Ybar_label='0.2dF/F', tmin=-3): fig, AX = ge.figure(axes=(3, 1), figsize=(1., 1), wspace=0.5, right=8, top=2) ax = ge.inset(fig, [.9, .4, .07, .5]) ax.bar([0], [responses['linear-integral']], color=ge.red) ax.bar([1], [responses['mixed-integral']], color='k') ge.set_plot(ax, ['left'], ylabel='integ. (resp.s)') # static-patch cond = responses['t_contour'] > tmin / 2. AX[0].plot(responses['t_contour'][cond], responses['contour'][cond], color='k') ge.set_plot(AX[0], [], title=static_patch_label) # mv Dots cond = responses['t_motion'] > tmin AX[1].plot(responses['t_motion'][cond], responses['motion' if not random else 'random'][cond], color='k') ge.set_plot(AX[1], [], title=moving_dots_label) # mixed interaction_panel( responses, ax=AX[2], title=mixed_label, mixed_key='mixed' if not random else 'mixed-random', linear_key='linear' if not random else 'linear-random', with_episodes_highlights= False, # only after that we have set common lims tmin=tmin) ge.set_common_ylims(AX) ge.set_common_xlims(AX) AX[0].fill_between([0, responses['patch-duration']], AX[0].get_ylim()[0] * np.ones(2), AX[0].get_ylim()[1] * np.ones(2), color=ge.blue, alpha=.3, lw=0) AX[1].fill_between([0, responses['mvDot-duration']], AX[1].get_ylim()[0] * np.ones(2), AX[1].get_ylim()[1] * np.ones(2), color=ge.orange, alpha=.1, lw=0) AX[2].plot( responses['delay'] + np.arange(2) * responses['integral_window'], AX[2].get_ylim()[1] * np.ones(2), 'k-') AX[2].fill_between(responses['delay'] + np.arange(2) * responses['patch-duration'], AX[2].get_ylim()[0] * np.ones(2), AX[2].get_ylim()[1] * np.ones(2), color=ge.blue, alpha=.3, lw=0) AX[2].fill_between([0, responses['mvDot-duration']], AX[2].get_ylim()[0] * np.ones(2), AX[2].get_ylim()[1] * np.ones(2), color=ge.orange, alpha=.1, lw=0) for ax in AX: ge.draw_bar_scales(ax, Xbar=1, Xbar_label='1s', Ybar=Ybar, Ybar_label=Ybar_label) ge.annotate(fig, ' n=%iROIs' % responses['nROIs'], (0.02, 0.02)) return fig, AX, ax
def analysis_pdf(datafile, iprotocol=0, stat_test_props=dict(interval_pre=[-2, 0], interval_post=[1, 3], test='wilcoxon', positive=True), response_significance_threshold=0.05, quantity='dFoF', verbose=True, Nmax=1000000): data = Data(datafile, metadata_only=True) print(' - computing episodes [...]') EPISODES = EpisodeResponse(datafile, protocol_id=iprotocol, quantities=['dFoF']) pdf_filename = os.path.join( summary_pdf_folder(datafile), '%s-spatial_selectivity.pdf' % data.protocols[iprotocol]) results = {'Ntot': EPISODES.data.nROIs, 'significant': []} fig, AX = ge.figure(axes=(3, 1)) with PdfPages(pdf_filename) as pdf: print( ' - spatial-selectivity analysis for summed ROI fluo (n=%i rois)' % EPISODES.data.nROIs) fig, AX = EPISODES.plot_trial_average( quantity=quantity, roiIndices='all', roiIndex=None, column_key='x-center', row_key='y-center', # color_key='angle', ybar=0.2, ybarlabel='0.2dF/F', xbar=1., xbarlabel='1s', with_annotation=True, with_std=True, with_stat_test=True, stat_test_props=stat_test_props, with_screen_inset=True, verbose=verbose) pdf.savefig(fig) plt.close(fig) # Add figure to pdf and close for roi in np.arange(EPISODES.data.nROIs)[:Nmax]: print(' - spatial-selectivity analysis for ROI #%i / %i' % (roi + 1, EPISODES.data.nROIs)) resp = EPISODES.compute_summary_data( stat_test_props, exclude_keys=['repeat'], response_args=dict(roiIndex=roi), response_significance_threshold=response_significance_threshold ) fig, AX = EPISODES.plot_trial_average( quantity=quantity, roiIndex=roi, column_key='x-center', row_key='y-center', color_key='angle', ybar=0.2, ybarlabel='0.2dF/F', xbar=1., xbarlabel='1s', with_annotation=True, with_std=False, with_stat_test=True, stat_test_props=stat_test_props, with_screen_inset=True, verbose=verbose) pdf.savefig(fig) plt.close(fig) # Add figure to pdf and close significant_cond, label = ( resp['significant'] == True), ' -> max resp.: ' if np.sum(significant_cond) > 0: imax = np.argmax(resp['value'][significant_cond]) for key in resp: if ('-bins' not in key): if (key not in results): results[key] = [] # initialize if not done results[key].append(resp[key][significant_cond][imax]) label += format_key_value( key, resp[key][significant_cond] [imax]) + ', ' # should have a unique value print(label) ge.annotate( fig, label + '\n\n', (0, 0), size='x-small') #, ha='right', va='top'), rotation=90) else: ge.annotate( fig, label + ' N/A (no significant resp.)\n\n', (0, 0), size='x-small') #, ha='right', va='top', rotation=90) # the adding the bins for key in resp: if ('-bins' in key): results[key] = resp[key] fig = summary_fig(results) pdf.savefig(fig) # saves the current figure into a pdf page plt.close(fig) print('[ok] spatial-selectivity analysis saved as: "%s" ' % pdf_filename)
def population_tuning_fig(full_resp): Ncells = len(np.unique(full_resp['roi'])) Neps = len(full_resp['roi']) / Ncells angles = np.unique(full_resp['angle_from_pref']) fig, AX = ge.figure(axes=(3, 1), figsize=(1.5, 1.5)) for ax in AX: ge.annotate(ax, 'n=%i resp. cells (%.0f%% of rois)' % (Ncells, 100. * Ncells / full_resp['Nroi_tot']), (1, 1), va='top', ha='right') ge.plot(angles, np.mean(full_resp['per_cell_post'], axis=0), sy=np.std(full_resp['per_cell_post'], axis=0), color='grey', ms=2, m='o', ax=AX[0], no_set=True, lw=1) ge.set_plot(AX[0], xlabel='angle ($^{o}$) w.r.t. pref. orient.', ylabel='post level (dF/F)', xticks=[0, 90, 180, 270]) ge.plot(angles, np.mean(full_resp['per_cell'], axis=0), sy=np.std(full_resp['per_cell'], axis=0), color='grey', ms=2, m='o', ax=AX[1], no_set=True, lw=1) ge.set_plot(AX[1], xlabel='angle ($^{o}$) w.r.t. pref. orient.', ylabel='evoked resp. ($\delta$ dF/F)', xticks=[0, 90, 180, 270]) ge.plot(angles, np.mean(full_resp['per_cell'].T / np.max(full_resp['per_cell'], axis=1).T, axis=1), sy=np.std(full_resp['per_cell'].T / np.max(full_resp['per_cell'], axis=1).T, axis=1), color='grey', ms=2, m='o', ax=AX[2], no_set=True, lw=1) ge.set_plot(AX[2], xlabel='angle ($^{o}$) w.r.t. pref. orient.', ylabel='norm. resp ($\delta$ dF/F)', yticks=[0, 0.5, 1], xticks=[0, 90, 180, 270]) return fig
def tuning_modulation_fig(curves, full_resp=None): # running vs still --- raw evoked response fig, ax = ge.figure(figsize=(1.5, 1.5), right=6) ge.plot(curves['angles'], curves['all'], label='all', color='grey', ax=ax, no_set=True, lw=2, alpha=.5) ge.plot(curves['angles'], curves['running_mean'], color=ge.orange, ms=4, m='o', ax=ax, lw=2, label='running', no_set=True) ge.plot(curves['angles'], curves['still_mean'], color=ge.blue, ms=4, m='o', ax=ax, lw=2, label='still', no_set=True) ge.legend(ax, ncol=3, loc=(.3, 1.)) ge.set_plot(ax, xlabel='angle ($^{o}$) w.r.t. pref. orient.', ylabel='evoked resp, ($\delta$ dF/F) ', xticks=[0, 90, 180, 270]) if (full_resp is not None) and ('speed_level' in full_resp) and ('pupil_level' in full_resp): inset = ge.inset(fig, [.8, .5, .16, .28]) ge.scatter(full_resp['pupil_level'][full_resp['running_cond']], full_resp['speed_level'][full_resp['running_cond']], ax=inset, no_set=True, color=ge.orange) ge.scatter(full_resp['pupil_level'][~full_resp['running_cond']], full_resp['speed_level'][~full_resp['running_cond']], ax=inset, no_set=True, color=ge.blue) ge.annotate(ax, 'n=%i cells\n' % full_resp['Ncells'], (0., 1.), ha='center') ge.set_plot(inset, xlabel='pupil size (mm)', ylabel='run. speed (cm/s) ', title='episodes (n=%i) ' % full_resp['Neps']) ge.annotate(inset, 'n=%i' % (np.sum(full_resp['running_cond']) / full_resp['Ncells']), (0., 1.), va='top', color=ge.orange) ge.annotate(inset, '\nn=%i' % (np.sum(~full_resp['running_cond']) / full_resp['Ncells']), (0., 1.), va='top', color=ge.blue) if len(curves['constricted_mean']) > 0: # constricted vs dilated --- raw evoked response fig2, ax = ge.figure(figsize=(1.5, 1.5), right=6) ge.plot(curves['angles'], curves['all'], label='all', color='grey', ax=ax, no_set=True, lw=2, alpha=.5) ge.plot(curves['angles'], curves['constricted_mean'], color=ge.green, ms=4, m='o', ax=ax, lw=2, label='constricted', no_set=True) ge.plot(curves['angles'], curves['dilated_mean'], color=ge.purple, ms=4, m='o', ax=ax, lw=2, label='dilated', no_set=True) ge.legend(ax, ncol=3, loc=(.1, 1.)) ge.set_plot(ax, xlabel='angle ($^{o}$) w.r.t. pref. orient.', ylabel='evoked resp, ($\delta$ dF/F) ', xticks=[0, 90, 180, 270]) if (full_resp is not None) and ('speed_level' in full_resp) and ('pupil_level' in full_resp): inset2 = ge.inset(fig2, [.8, .5, .16, .28]) ge.scatter(full_resp['pupil_level'][full_resp['dilated_cond']], full_resp['speed_level'][full_resp['dilated_cond']], ax=inset2, no_set=True, color=ge.purple) ge.scatter(full_resp['pupil_level'][full_resp['constricted_cond']], full_resp['speed_level'][full_resp['constricted_cond']], ax=inset2, no_set=True, color=ge.green) ge.annotate(ax, 'n=%i cells\n' % len(np.unique(full_resp['roi'])), (0., 1.), ha='right') ge.set_plot(inset2, xlabel='pupil size (mm)', ylabel='run. speed (cm/s) ', ylim=inset.get_ylim(), title='episodes (n=%i) ' % full_resp['Neps']) ge.annotate( inset2, 'n=%i' % (np.sum(full_resp['constricted_cond']) / full_resp['Ncells']), (0., 1.), va='top', color=ge.green) ge.annotate( inset2, '\nn=%i' % (np.sum(full_resp['dilated_cond']) / full_resp['Ncells']), (0., 1.), va='top', color=ge.purple) else: fig2 = None return fig, fig2