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_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 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.05, radius_threshold_for_center=20., with_responsive_angles=False, stat_test_props=dict(interval_pre=[-1.5, 0], interval_post=[0.5, 2.], test='ttest', positive=True), Npanels=4): """ direction selectivity ROI analysis """ EPISODES = EpisodeResponse( FullData, protocol_id=iprotocol, quantity='CaImaging', subquantity='dF/F', prestim_duration=-stat_test_props['interval_pre'][0], roiIndex=roiIndex) fig, AX = FullData.plot_trial_average( EPISODES=EPISODES, protocol_id=iprotocol, quantity='CaImaging', subquantity='dF/F', roiIndex=roiIndex, column_key='contrast', row_key='angle', ybar=1., ybarlabel='1dF/F', xbar=1., xbarlabel='1s', fig_preset='raw-traces-preset+right-space', with_annotation=True, with_std=True, with_stat_test=True, stat_test_props=stat_test_props, verbose=verbose) AXI, ylims, CURVES = [], [10, -10], [] max_response_curve, imax_response_curve = np.zeros( len(EPISODES.varied_parameters['contrast']) + 1), -1 for ia, angle in enumerate(EPISODES.varied_parameters['angle']): resp, contrasts, significants = [0], [0], [False] for ic, contrast in enumerate(EPISODES.varied_parameters['contrast']): # stat test "pre" vs "post" stats = EPISODES.stat_test_for_evoked_responses( episode_cond=EPISODES.find_episode_cond(['angle', 'contrast'], [ia, ic]), **stat_test_props) resp.append(np.mean(stats.y - stats.x)) # "post"-"pre" contrasts.append(contrast) significants.append( stats.significant(threshold=response_significance_threshold)) AXI.append(AX[ia][-1].inset_axes([1.8, .2, .7, .6])) ge.plot(contrasts, resp, ax=AXI[-1], no_set=True, ms=3, m='o') ylims = [ np.min([np.min(resp), ylims[0]]), np.max([np.max(resp), ylims[1]]) ] if (np.sum(significants) > 0) and np.max(resp) > np.max(max_response_curve): imax_response_curve = ia max_response_curve = np.array(resp) for ia, axi in enumerate(AXI): ge.set_plot(axi, xlabel='contrast', ylabel='$\delta$ dF/F', ylim=[ ylims[0] - .05 * (ylims[1] - ylims[0]), ylims[1] + .05 * (ylims[1] - ylims[0]) ]) if ia == imax_response_curve: axi.fill_between(contrasts, ylims[0] * np.ones(len(contrasts)), ylims[1] * np.ones(len(contrasts)), color='k', alpha=0.1) return fig, contrasts, max_response_curve
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 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 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
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 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 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 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 /!\ ')