示例#1
0
eigvals = np.zeros((st.nclusters, stimdim, fl))
eigvecs = np.zeros((st.nclusters, stimdim, fl, fl))

cross_corrs = np.zeros(st.nclusters)

for i, cl in enumerate(st.clusters):
    sta = data['stas'][i]

    spikes = st.binnedspiketimes(i)

    import time
    start = time.time()

    # Calculate the contrast for each cell's receptive field
    stimulus[-1, :] = st.contrast_signal_cell(i)

    sp_tr, sp_te, stim_tr, stim_te = train_test_split(spikes, stimulus,
                                                      test_size=val_split_size,
                                                      split_pos=val_split_pos)

    res = gqm.minimize_loglikelihood(np.zeros((stimdim, fl)),
                                     np.zeros((stimdim, fl, fl)), 0,
                                     stim_tr,
                                     st.frame_duration,
                                     sp_tr,
                                     minimize_disp=True,
                                     method='BFGS')
    elapsed = time.time()-start

    print(f'Time elapsed: {elapsed/60:6.1f} mins for cell {i}')
示例#2
0
t = np.linspace(0, st.filter_length * st.frame_duration * 1000,
                st.filter_length)

plotlabels = ['Contrast']

# Temporary hack until FFF gets its own class.
fff.readpars()
if fff.param_file['Nblinks'] == 1:
    t_fff = np.linspace(0, st.filter_length * st.frame_duration * 1000,
                        st.filter_length * 2)
else:
    t_fff = t

for i, cluster in enumerate(st.clusters):

    stimulus = st.contrast_signal_cell(i).squeeze()

    res = glm.minimize_loglhd(np.zeros(st.filter_length),
                              0,
                              stimulus,
                              st.frame_duration,
                              all_spikes[i, :],
                              usegrad=True,
                              method='BFGS')
    if not res['success']:
        print(i, 'did not complete successfully.')
    kall[i, :] = res['x'][:-1]
    muall[i] = res['x'][-1]

    frs[i, :] = glm.glm_fr(kall[i, :], muall[i], st.frame_duration)(stimulus)
    cross_corrs[i] = np.corrcoef(all_spikes[i, :], frs[i, :])[0, 1]
def omb_contrastmotion2dnonlin(exp,
                               stim,
                               nbins_nlt=9,
                               cmap='Greys',
                               plot3d=False):
    """
    Calculate and plot the 2D nonlinearities for the OMB stimulus. The
    magnitude of the stimulus projection on quadratic motion filters
    from GQM is used for the motion.

    Parameters:
    ------
        nbins_nlt:
            Number of bins to be used for dividing the generator signals
            into ranges with equal number of samples.
        plot3d:
            Whether to additionally create a 3D version of the nonlinearity.
    """

    st = OMB(exp, stim)

    # Motion and contrast
    data_cm = np.load(
        os.path.join(st.exp_dir, 'data_analysis', st.stimname,
                     'GQM_motioncontrast', f'{stim}_GQM_motioncontrast.npz'))

    qall = data_cm['Qall']
    kall = data_cm['kall']
    muall = data_cm['muall']
    cross_corrs = data_cm['cross_corrs']

    allspikes = st.allspikes()

    stim_mot = st.bgsteps.copy()

    # Bin dimension should be one greater than nonlinearity for pcolormesh
    # compatibility. Otherwise the last row and column of nonlinearity is not
    # plotted.
    all_bins_c = np.zeros((st.nclusters, nbins_nlt + 1))
    all_bins_r = np.zeros((st.nclusters, nbins_nlt + 1))
    nonlinearities = np.zeros((st.nclusters, nbins_nlt, nbins_nlt))

    label = '2D-nonlin_magQ_motion_kcontrast'

    savedir = os.path.join(st.stim_dir, label)
    os.makedirs(savedir, exist_ok=True)

    for i in range(st.nclusters):
        stim_con = st.contrast_signal_cell(i).squeeze()

        # Project the motion stimulus onto the quadratic filter
        generator_x = gqm.conv2d(qall[i, 0, :], stim_mot[0, :])
        generator_y = gqm.conv2d(qall[i, 1, :], stim_mot[1, :])

        # Calculate the magnitude of the vector formed by motion generators
        generators = np.vstack([generator_x, generator_y])
        r = np.sqrt(np.sum(generators**2, axis=0))

        # Project the contrast stimulus onto the linear filter
        generator_c = np.convolve(stim_con, kall[i, 2, :],
                                  'full')[:-st.filter_length + 1]
        spikes = allspikes[i, :]

        nonlinearity, bins_c, bins_r = nlt.calc_nonlin_2d(spikes,
                                                          generator_c,
                                                          r,
                                                          nr_bins=nbins_nlt)
        nonlinearity /= st.frame_duration

        all_bins_c[i, :] = bins_c
        all_bins_r[i, :] = bins_r
        nonlinearities[i, ...] = nonlinearity

        X, Y = np.meshgrid(bins_c, bins_r, indexing='ij')

        fig = plt.figure()

        gs = gsp.GridSpec(5, 5)
        axmain = plt.subplot(gs[1:, :-1])
        axx = plt.subplot(gs[0, :-1], sharex=axmain)
        axy = plt.subplot(gs[1:, -1], sharey=axmain)

        # Normally subplots turns off shared axis tick labels but
        # Gridspec does not do this
        plt.setp(axx.get_xticklabels(), visible=False)
        plt.setp(axy.get_yticklabels(), visible=False)

        im = axmain.pcolormesh(X, Y, nonlinearity, cmap=cmap)
        plf.integerticks(axmain)

        cb = plt.colorbar(im)
        cb.outline.set_linewidth(0)
        cb.ax.set_xlabel('spikes/s')
        cb.ax.xaxis.set_label_position('top')

        plf.integerticks(cb.ax, 4, which='y')
        plf.integerticks(axx, 1, which='y')
        plf.integerticks(axy, 1, which='x')

        barkwargs = dict(alpha=.3, facecolor='k', linewidth=.5, edgecolor='w')

        axx.bar(nlt.bin_midpoints(bins_c),
                nonlinearity.mean(axis=1),
                width=np.ediff1d(bins_c),
                **barkwargs)
        axy.barh(nlt.bin_midpoints(bins_r),
                 nonlinearity.mean(axis=0),
                 height=np.ediff1d(bins_r),
                 **barkwargs)
        plf.spineless(axx, 'b')
        plf.spineless(axy, 'l')

        axmain.set_xlabel('Projection onto linear contrast filter')
        axmain.set_ylabel(
            'Magnitude of projection onto quadratic motion filters')
        fig.suptitle(
            f'{st.exp_foldername}\n{st.stimname}\n{st.clids[i]} '
            f'2D nonlinearity nsp: {st.allspikes()[i, :].sum():<5.0f}')

        plt.subplots_adjust(top=.85)
        fig.savefig(os.path.join(savedir, st.clids[i]), bbox_inches='tight')
        plt.show()

        if plot3d:
            if i == 0:
                from mpl_toolkits import mplot3d
            from matplotlib.ticker import MaxNLocator
            #%%
            fig = plt.figure()
            ax = plt.axes(projection='3d')
            ax.plot_surface(X,
                            Y,
                            nonlinearity,
                            cmap='YlGn',
                            edgecolors='k',
                            linewidths=0.2)
            ax.set_xlabel('Projection onto linear contrast filter')
            ax.set_ylabel(
                'Magnitude of projection onto quadratic motion filters')

            ax.set_zlabel(r'Firing rate [sp/s]')
            ax.view_init(elev=30, azim=-135)

            ax.xaxis.set_major_locator(MaxNLocator(integer=True))
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))
            ax.zaxis.set_major_locator(MaxNLocator(integer=True))

    keystosave = ['nonlinearities', 'all_bins_c', 'all_bins_r', 'nbins_nlt']
    datadict = {}

    for key in keystosave:
        datadict.update({key: locals()[key]})
    npzfpath = os.path.join(savedir, f'{st.stimnr}_{label}.npz')
    np.savez(npzfpath, **datadict)
def omb_contrastmotion2dnonlin_Qcomps(exp, stim, nbins_nlt=9, cmap='Greys'):
    """
    Calculate and plot the 2D nonlinearities for the OMB stimulus. Multiple
    components of the matrix Q for the motion.

    Parameters:
    ------
        nbins_nlt:
            Number of bins to be used for dividing the generator signals
            into ranges with equal number of samples.
    """

    st = OMB(exp, stim)

    # Motion and contrast
    data_cm = np.load(os.path.join(st.exp_dir, 'data_analysis',
                                   st.stimname, 'GQM_motioncontrast_val',
                                   f'{stim}_GQM_motioncontrast_val.npz'))

    qall = data_cm['Qall']
    kall = data_cm['kall']
    muall = data_cm['muall']

    eigvecs = data_cm['eigvecs']
    eigvals = data_cm['eigvals']

    eiginds = [-1, 0]  # activating, suppressing #HINT

    cross_corrs = data_cm['cross_corrs']

    allspikes = st.allspikes()

    stim_mot = st.bgsteps.copy()

    # Bin dimension should be one greater than nonlinearity for pcolormesh
    # compatibility. Otherwise the last row and column of nonlinearity is not
    # plotted.
    all_bins_c = np.zeros((st.nclusters, nbins_nlt+1))
    all_bins_r = np.zeros((st.nclusters, nbins_nlt+1))
    nonlinearities = np.zeros((st.nclusters, nbins_nlt, nbins_nlt))

    label = '2D-nonlin_Qallcomps_motion_kcontrast'

    row_labels = ['Activating', 'Suppresive']
    column_labels = ['X', 'Y', r'$\sqrt{X^2 + Y^2}$']

    savedir = os.path.join(st.stim_dir, label)
    os.makedirs(savedir, exist_ok=True)

    for i in range(st.nclusters):
        stim_con = st.contrast_signal_cell(i).squeeze()

        n = 3  # x, y, xy
        m = 2  # activating, suppressing
        fig = plt.figure(figsize=(n*5, m*5), constrained_layout=True)
        gs = fig.add_gridspec(m, n)
        axes = []
        for _, eachgs in enumerate(gs):
            subgs = eachgs.subgridspec(2, 3, width_ratios=[4, 1, .2], height_ratios=[1, 4])
            mainax = fig.add_subplot(subgs[1, 0])
            axx = fig.add_subplot(subgs[0, 0], sharex=mainax)
            axy = fig.add_subplot(subgs[1, 1], sharey=mainax)
            cbax = fig.add_subplot(subgs[1, 2])
            axes.append([axx, mainax, axy, cbax])

        for k, eigind in enumerate(eiginds):
            generator_x = np.convolve(eigvecs[i, 0, :, eigind],
                                      stim_mot[0, :], 'full')[:-st.filter_length+1]
            generator_y = np.convolve(eigvecs[i, 1, :, eigind],
                                      stim_mot[1, :], 'full')[:-st.filter_length+1]

            # Calculate the magnitude of the vector formed by motion generators
            generators = np.vstack([generator_x, generator_y])
            generator_xy = np.sqrt(np.sum(generators**2, axis=0))

            # Project the contrast stimulus onto the linear filter
            generator_c = np.convolve(stim_con,
                                      kall[i, 2, :],
                                      'full')[:-st.filter_length+1]
            spikes = allspikes[i, :]

            generators_motion = [generator_x, generator_y, generator_xy]

            for l, direction in enumerate(column_labels):
                nonlinearity, bins_c, bins_r = nlt.calc_nonlin_2d(spikes,
                                                                  generator_c,
                                                                  generators_motion[l],
                                                                  nr_bins=nbins_nlt)
                nonlinearity /= st.frame_duration

                all_bins_c[i, :] = bins_c
                all_bins_r[i, :] = bins_r
                nonlinearities[i, ...] = nonlinearity

                X, Y = np.meshgrid(bins_c, bins_r, indexing='ij')

                subaxes = axes[k*n+l]

                axmain = subaxes[1]
                axx = subaxes[0]
                axy = subaxes[2]
                cbax = subaxes[3]

                # Normally subplots turns off shared axis tick labels but
                # Gridspec does not do this
                plt.setp(axx.get_xticklabels(), visible=False)
                plt.setp(axy.get_yticklabels(), visible=False)

                im = axmain.pcolormesh(X, Y, nonlinearity, cmap=cmap)
                plf.integerticks(axmain, 6, which='xy')

                cb = plt.colorbar(im, cax=cbax)
                cb.outline.set_linewidth(0)
                cb.ax.set_xlabel('spikes/s')
                cb.ax.xaxis.set_label_position('top')

                plf.integerticks(cb.ax, 4, which='y')
                plf.integerticks(axx, 1, which='y')
                plf.integerticks(axy, 1, which='x')

                barkwargs = dict(alpha=.3, facecolor='k',
                                 linewidth=.5, edgecolor='w')

                axx.bar(nlt.bin_midpoints(bins_c), nonlinearity.mean(axis=1),
                        width=np.ediff1d(bins_c), **barkwargs)
                axy.barh(nlt.bin_midpoints(bins_r), nonlinearity.mean(axis=0),
                         height=np.ediff1d(bins_r), **barkwargs)
                plf.spineless(axx, 'b')
                plf.spineless(axy, 'l')

                if k == 0 and l == 0:
                    axmain.set_xlabel('Projection onto linear contrast filter')
                    axmain.set_ylabel(f'Projection onto Q component')
                if k == 0:
                    axx.set_title(direction)
                if l == 0:
                    axmain.text(-.3, .5, row_labels[k],
                                va='center',
                                rotation=90,
                                transform=axmain.transAxes)

        fig.suptitle(f'{st.exp_foldername}\n{st.stimname}\n{st.clids[i]} '
                     f'2D nonlinearity nsp: {st.allspikes()[i, :].sum():<5.0f}')

        plt.subplots_adjust(top=.85)
        fig.savefig(os.path.join(savedir, st.clids[i]), bbox_inches='tight')
        plt.show()

    keystosave = ['nonlinearities', 'all_bins_c', 'all_bins_r', 'nbins_nlt']
    datadict = {}

    for key in keystosave:
        datadict.update({key: locals()[key]})
    npzfpath = os.path.join(savedir, f'{st.stimnr}_{label}.npz')
    np.savez(npzfpath, **datadict)