Пример #1
0
def summary_fig(radii, curves, Ntot):

    fig, ax = ge.figure(right=8, figsize=(1.5, 1.5))
    ge.title(ax, 'n=%i ROIS' % len(curves))

    axi = ge.inset(fig, [.73, .35, .3, .4])
    axi.pie([100 * len(curves) / Ntot, 100 * (1 - len(curves) / Ntot)],
            explode=(0, 0.1),
            colors=[plt.cm.tab10(2), plt.cm.tab10(3)],
            labels=['responsive at low radius\n\n\n', ''],
            autopct='%1.1f%%',
            shadow=True,
            startangle=90)
    axi.axis(
        'equal')  # Equal aspect ratio ensures that pie is drawn as a circle.

    curves = np.array(curves)
    ge.scatter(x=radii,
               y=np.mean(curves, axis=0),
               sy=np.std(curves, axis=0),
               no_set=True,
               ms=5,
               ax=ax,
               lw=2)
    ge.set_plot(ax, xlabel='size ($^{o}$)', ylabel='$\delta$ dF/F')
    return fig
Пример #2
0
    def show_CaImaging_FOV(self,
                           key='meanImg',
                           NL=1,
                           cmap='viridis',
                           ax=None,
                           roiIndex=None,
                           with_roi_zoom=False):

        if ax is None:
            fig, ax = ge.figure()
        else:
            fig = None

        img = self.nwbfile.processing['ophys'].data_interfaces[
            'Backgrounds_0'].images[key][:]
        img = (img - img.min()) / (img.max() - img.min())
        img = np.power(img, 1 / NL)
        ax.imshow(img,
                  vmin=0,
                  vmax=1,
                  cmap=cmap,
                  aspect='equal',
                  interpolation='none')
        ax.axis('off')

        if roiIndex is not None:
            indices = np.arange(self.pixel_masks_index[roiIndex],
                                self.pixel_masks_index[roiIndex + 1])
            x = np.mean([self.pixel_masks[ii][1] for ii in indices])
            sx = np.std([self.pixel_masks[ii][1] for ii in indices])
            y = np.mean([self.pixel_masks[ii][0] for ii in indices])
            sy = np.std([self.pixel_masks[ii][1] for ii in indices])
            # ellipse = plt.Circle((x, y), sx, sy)
            ellipse = plt.Circle((x, y),
                                 1.5 * (sx + sy),
                                 edgecolor='r',
                                 facecolor='none',
                                 lw=3)
            ax.add_patch(ellipse)
            if with_roi_zoom:
                ax.set_xlim([x - 10 * sx, x + 10 * sx])
                ax.set_ylim([y - 10 * sy, y + 10 * sy])

        ge.title(ax, key)

        return fig, ax
Пример #3
0
                                          subsampling=30,
                                          color=ge.purple),
                                     'Pupil':
                                     dict(fig_fraction=2,
                                          subsampling=10,
                                          color=ge.red),
                                     'CaImagingRaster':
                                     dict(fig_fraction=5,
                                          subsampling=1,
                                          roiIndices='all',
                                          normalization='per-line',
                                          quantity='CaImaging',
                                          subquantity='Fluorescence')
                                 },
                                 Tbar=10)
    ge.title(ax, 'Full data')

    fig, ax = data.plot_raw_data(tlim,
                                 settings={
                                     'Locomotion':
                                     dict(fig_fraction=2,
                                          subsampling=30,
                                          color=ge.blue),
                                     'FaceMotion':
                                     dict(fig_fraction=2,
                                          subsampling=30,
                                          color=ge.purple),
                                     'Pupil':
                                     dict(fig_fraction=2,
                                          subsampling=10,
                                          color=ge.red),
Пример #4
0
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 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 /!\  ')