Exemple #1
0
    def _generatesteps(self):
        pars = self.pars
        frametimings = self.frametimings
        if self.maxframes is None:
            ntotal = int(pars.stimframes / pars.nblinks)
            if ntotal != frametimings.shape[0]:
                print(
                    f'For {self.exp}\nstimulus {iof.getstimname(self.exp, self.stimnr)} :\n'
                    f'Number of frames specified in the parameters file ({ntotal}'
                    f' frames) and frametimings ({frametimings.shape[0]}) do not'
                    ' agree!'
                    ' The stimulus was possibly interrupted during recording.'
                    ' ntotal is changed to match actual frametimings.')
                ntotal = frametimings.shape[0]
        else:
            ntotal = self.maxframes

        # Make a copy of the initial seed to not change it
        pars.stepseed = pars.initial_stepseed
        randnrs, pars.stepseed = randpy.gasdev(pars.stepseed, ntotal * 2)
        randnrs = np.array(randnrs) * pars.stepsize

        xsteps = randnrs[::2]
        ysteps = randnrs[1::2]

        steps = np.vstack((xsteps, ysteps))

        steps /= pars.bgstixel

        self.bgsteps = steps
        self.ntotal = ntotal
Exemple #2
0
    def _generatetexture_withloops(self):
        pars = self.pars
        self.texpars_withloop = Parameters()
        bgstixel = int(pars.bgstixel)
        filterstd = pars.filterstd
        meanintensity = pars.meanintensity
        filterwidth = int(filterstd / bgstixel * 3)
        noiselim = (np.ceil(
            np.array([pars.squareheight, pars.squarewidth]) /
            bgstixel)).astype(int)
        gfilter = np.zeros((pars.squareheight, pars.squarewidth))
        seed = pars.bggenerationseed

        texture = np.zeros((pars.squareheight, pars.squarewidth))
        noisefield = np.zeros((pars.squareheight, pars.squarewidth))
        norm = 0
        for i in range(noiselim[0]):
            for j in range(noiselim[1]):
                rndnr, seed = randpy.gasdev(seed)
                noisefield[
                    i,
                    j] = meanintensity + meanintensity * pars.bgcontrast * rndnr
                if (i < filterwidth * 2 + 1) and (j < filterwidth * 2 + 1):
                    gfilter[i, j] = np.exp2(-((i - filterwidth)**2 +
                                              (j - filterwidth)**2) /
                                            (2 * (filterstd / bgstixel)**2))
                    norm += gfilter[i, j]
        for i in range(noiselim[0]):
            for j in range(noiselim[1]):
                helper = 0
                for ki in range(filterwidth * 2 + 1):
                    for kj in range(filterwidth * 2 + 1):
                        helper += (noisefield[
                            (i -
                             (ki - filterwidth) + noiselim[0]) % noiselim[0],
                            (j -
                             (kj - filterwidth) + noiselim[1]) % noiselim[1]] *
                                   gfilter[ki, kj])
#                c = 255 * ((helper / norm - meanintensity) * filterstd / bgstixel + meanintensity)
                c = self._normalizetexture(helper, norm, meanintensity,
                                           filterstd, bgstixel)

                for gi in range(bgstixel):
                    for gj in range(bgstixel):
                        texture[i * bgstixel + gi, j * bgstixel + gj] = c
        # This will be the full size 800x800 with repeats
        self.texturewithloopsmaxi = texture
        # Save a smaller version for compatibility
        self.texturewithloops = texture[::bgstixel, ::bgstixel]
Exemple #3
0
    def _generatetexture(self):
        pars = self.pars
        self.texpars = Parameters()
        bgstixel = pars.bgstixel
        filterstd = pars.filterstd
        meanintensity = pars.meanintensity
        filterwidth = filterstd / bgstixel * 3
        noiselim = (np.ceil(
            np.array([pars.squareheight, pars.squarewidth]) /
            bgstixel)).astype(int)

        # Gaussian filter is applied to the noise field by a for loop in the cpp code,
        # and its norm is
        xx, yy = np.meshgrid(np.arange(2 * filterwidth),
                             np.arange(2 * filterwidth))
        gfilter = np.exp2(-((xx - filterwidth)**2 + (yy - filterwidth)**2) /
                          (2 * (filterstd / bgstixel)**2))

        norm = gfilter.sum()
        randnrs = np.reshape(
            randpy.gasdev(pars.bggenerationseed, noiselim[0] * noiselim[1])[0],
            (noiselim[0], noiselim[1]))
        noisefield = (pars.meanintensity +
                      pars.meanintensity * pars.bgcontrast * randnrs)

        texturebasic = snd.convolve(noisefield, gfilter, mode='wrap')
        texturetiled = snd.convolve(np.tile(noisefield, [3, 3]), gfilter)

        texturebasic = self._normalizetexture(texturebasic, norm,
                                              meanintensity, filterstd,
                                              bgstixel)
        texturetiled = self._normalizetexture(texturetiled, norm,
                                              meanintensity, filterstd,
                                              bgstixel)

        self.texture = texturetiled
        self.texturebasic = texturebasic

        self.texture_flipped = np.flipud(texturetiled)
        self.texpars.noiselim = noiselim
        self.texpars.filterwidth = filterwidth
def randomizestripes(label, exp_name='20180124', stim_nrs=6):
    exp_dir = iof.exp_dir_fixer(exp_name)

    if isinstance(stim_nrs, int):
        stim_nrs = [stim_nrs]

    for stim_nr in stim_nrs:
        stimname = iof.getstimname(exp_name, stim_nr)

        clusters, metadata = asc.read_spikesheet(exp_dir)

        parameters = asc.read_parameters(exp_dir, stim_nr)

        scr_width = metadata['screen_width']
        px_size = metadata['pixel_size(um)']

        stx_w = parameters['stixelwidth']
        stx_h = parameters['stixelheight']

        if (stx_h/stx_w) < 2:
            raise ValueError('Make sure the stimulus is stripeflicker.')

        sy = scr_width/stx_w
#        sy = sy*4
        sy = int(sy)

        nblinks = parameters['Nblinks']
        try:
            bw = parameters['blackwhite']
        except KeyError:
            bw = False

        try:
            seed = parameters['seed']
            initialseed = parameters['seed']
        except KeyError:
            seed = -10000
            initialseed = -10000

        if nblinks == 1:
            ft_on, ft_off = asc.readframetimes(exp_dir, stim_nr,
                                               returnoffsets=True)
            # Initialize empty array twice the size of one of them, assign
            # value from on or off to every other element.
            frametimings = np.empty(ft_on.shape[0]*2, dtype=float)
            frametimings[::2] = ft_on
            frametimings[1::2] = ft_off
            # Set filter length so that temporal filter is ~600 ms.
            # The unit here is number of frames.
            filter_length = 40
        elif nblinks == 2:
            frametimings = asc.readframetimes(exp_dir, stim_nr)
            filter_length = 20
        else:
            raise ValueError('Unexpected value for nblinks.')

        # Omit everything that happens before the first 10 seconds
        cut_time = 10

        frame_duration = np.average(np.ediff1d(frametimings))
        total_frames = int(frametimings.shape[0]/4)

        all_spiketimes = []
        # Store spike triggered averages in a list containing correct
        # shaped arrays
        stas = []

        for i in range(len(clusters[:, 0])):
            spikes_orig = asc.read_raster(exp_dir, stim_nr,
                                         clusters[i, 0], clusters[i, 1])
            spikesneeded = spikes_orig.shape[0]*1000

            spiketimes = np.random.random_sample(spikesneeded)*spikes_orig.max()
            spiketimes = np.sort(spiketimes)
            spikes = asc.binspikes(spiketimes, frametimings)
            all_spiketimes.append(spikes)
            stas.append(np.zeros((sy, filter_length)))

        if bw:
            randnrs, seed = randpy.ran1(seed, sy*total_frames)
#            randnrs = mersennetw(sy*total_frames, seed1=seed)
            randnrs = [1 if i > .5 else -1 for i in randnrs]
        else:
            randnrs, seed = randpy.gasdev(seed, sy*total_frames)

        stimulus = np.reshape(randnrs, (sy, total_frames), order='F')
        del randnrs

        for k in range(filter_length, total_frames-filter_length+1):
            stim_small = stimulus[:, k-filter_length+1:k+1][:, ::-1]
            for j in range(clusters.shape[0]):
                spikes = all_spiketimes[j]
                if spikes[k] != 0 and frametimings[k]>cut_time:
                    stas[j] += spikes[k]*stim_small

        max_inds = []

        spikenrs = np.array([spikearr.sum() for spikearr in all_spiketimes])

        quals = np.array([])

        for i in range(clusters.shape[0]):
            stas[i] = stas[i]/spikenrs[i]
            # Find the pixel with largest absolute value
            max_i = np.squeeze(np.where(np.abs(stas[i])
                                        == np.max(np.abs(stas[i]))))
            # If there are multiple pixels with largest value,
            # take the first one.
            if max_i.shape != (2,):
                try:
                    max_i = max_i[:, 0]
                # If max_i cannot be found just set it to zeros.
                except IndexError:
                    max_i = np.array([0, 0])

            max_inds.append(max_i)

            quals = np.append(quals, asc.staquality(stas[i]))

#        savefname = str(stim_nr)+'_data'
#        savepath = pjoin(exp_dir, 'data_analysis', stimname)
#
#        exp_name = os.path.split(exp_dir)[-1]
#
#        if not os.path.isdir(savepath):
#            os.makedirs(savepath, exist_ok=True)
#        savepath = os.path.join(savepath, savefname)
#
#        keystosave = ['stas', 'max_inds', 'clusters', 'sy',
#                      'frame_duration', 'all_spiketimes', 'stimname',
#                      'total_frames', 'stx_w', 'spikenrs', 'bw',
#                      'quals', 'nblinks', 'filter_length', 'exp_name']
#        data_in_dict = {}
#        for key in keystosave:
#            data_in_dict[key] = locals()[key]
#
#        np.savez(savepath, **data_in_dict)
#        print(f'Analysis of {stimname} completed.')


        clusterids = plf.clusters_to_ids(clusters)

#        assert(initialseed.ty)
        correction = corrector(sy, total_frames, filter_length, initialseed)
        correction = np.outer(correction, np.ones(filter_length))

        t = np.arange(filter_length)*frame_duration*1000
        vscale = int(stas[0].shape[0] * stx_w*px_size/1000)
        for i in range(clusters.shape[0]):
            sta = stas[i]-correction

            vmax = 0.03
            vmin = -vmax
            plt.figure(figsize=(6, 15))
            ax = plt.subplot(111)
            im = ax.imshow(sta, cmap='RdBu', vmin=vmin, vmax=vmax,
                           extent=[0, t[-1], -vscale, vscale], aspect='auto')
            plt.xlabel('Time [ms]')
            plt.ylabel('Distance [mm]')

            plf.spineless(ax)
            plf.colorbar(im, ticks=[vmin, 0, vmax], format='%.2f', size='2%')
            plt.suptitle('{}\n{}\n'
                         '{} Rating: {}\n'
                         'nrofspikes {:5.0f}'.format(exp_name,
                                                       stimname,
                                                       clusterids[i],
                                                       clusters[i][2],
                                                       spikenrs[i]))
            plt.subplots_adjust(top=.90)
            savepath = os.path.join(exp_dir, 'data_analysis',
                                    stimname, 'STAs_randomized')
            svgpath = pjoin(savepath, label)
            if not os.path.isdir(svgpath):
                os.makedirs(svgpath, exist_ok=True)
            plt.savefig(os.path.join(svgpath, clusterids[i]+'.svg'),
                        bbox_inches='tight')
            plt.close()

    os.system(f"convert -delay 25 {svgpath}/*svg {savepath}/animated_{label}.gif")
#x = sigtest(spikes, stimulus, filter_length)
#x_min, x_max = confidence_interval_2d(x)
#%%
#ax = plt.gca()
#ax.fill_between(np.arange(filter_length),
#                 x.min(axis=1), x.max(axis=1),
#                 color='grey', alpha=.5)
#ax.fill_between(np.arange(filter_length), x_min, x_max,
#                color='red', alpha=.5)
#ax.plot(eigvals, 'ok')
#%%
exp, stimnr = '20180710', 1

ff = Stimulus(exp, stimnr)
stimulus = np.array(randpy.gasdev(-1000, ff.frametimings.shape[0])[0])

st = OMB(exp, 8)
ff = st
stimulus = st.bgsteps[0, :]

allspikes = ff.allspikes()

i = 0
spikes = allspikes[i, :]
filter_length = ff.filter_length

rw = asc.rolling_window(stimulus, filter_length, preserve_dim=True)
sta = (spikes @ rw) / spikes.sum()
#%%
# I am not projecting out the STA like Equation 4 in Schwartz et al.2006,J.Vision
def stripeflickeranalysis(exp_name, stim_nrs):
    exp_dir = iof.exp_dir_fixer(exp_name)

    if isinstance(stim_nrs, int):
        stim_nrs = [stim_nrs]

    for stim_nr in stim_nrs:
        stimname = iof.getstimname(exp_name, stim_nr)

        clusters, metadata = asc.read_spikesheet(exp_dir)

        parameters = asc.read_parameters(exp_dir, stim_nr)

        scr_width = metadata['screen_width']
        px_size = metadata['pixel_size(um)']

        stx_w = parameters['stixelwidth']
        stx_h = parameters['stixelheight']

        if (stx_h / stx_w) < 2:
            raise ValueError('Make sure the stimulus is stripeflicker.')

        sy = scr_width / stx_w
        if sy % 1 == 0:
            sy = int(sy)
        else:
            raise ValueError('sy is not an integer')

        nblinks = parameters['Nblinks']
        try:
            bw = parameters['blackwhite']
        except KeyError:
            bw = False

        try:
            seed = parameters['seed']
        except KeyError:
            seed = -10000

        if nblinks == 1:
            ft_on, ft_off = asc.readframetimes(exp_dir,
                                               stim_nr,
                                               returnoffsets=True)
            # Initialize empty array twice the size of one of them, assign
            # value from on or off to every other element.
            frametimings = np.empty(ft_on.shape[0] * 2, dtype=float)
            frametimings[::2] = ft_on
            frametimings[1::2] = ft_off
            # Set filter length so that temporal filter is ~600 ms.
            # The unit here is number of frames.
            filter_length = 40
        elif nblinks == 2:
            frametimings = asc.readframetimes(exp_dir, stim_nr)
            filter_length = 20
        else:
            raise ValueError('Unexpected value for nblinks.')

        # Omit everything that happens before the first 10 seconds
        cut_time = 10

        frame_duration = np.average(np.ediff1d(frametimings))
        total_frames = frametimings.shape[0]

        all_spiketimes = []
        # Store spike triggered averages in a list containing correct
        # shaped arrays
        stas = []

        for i in range(len(clusters[:, 0])):
            spiketimes = asc.read_raster(exp_dir, stim_nr, clusters[i, 0],
                                         clusters[i, 1])
            spikes = asc.binspikes(spiketimes, frametimings)
            all_spiketimes.append(spikes)
            stas.append(np.zeros((sy, filter_length)))

        if bw:
            randnrs, seed = randpy.ran1(seed, sy * total_frames)
            randnrs = [1 if i > .5 else -1 for i in randnrs]
        else:
            randnrs, seed = randpy.gasdev(seed, sy * total_frames)

        stimulus = np.reshape(randnrs, (sy, total_frames), order='F')
        del randnrs

        for k in range(filter_length, total_frames - filter_length + 1):
            stim_small = stimulus[:, k - filter_length + 1:k + 1][:, ::-1]
            for j in range(clusters.shape[0]):
                spikes = all_spiketimes[j]
                if spikes[k] != 0 and frametimings[k] > cut_time:
                    stas[j] += spikes[k] * stim_small

        max_inds = []
        spikenrs = np.array([spikearr.sum() for spikearr in all_spiketimes])

        quals = np.array([])

        for i in range(clusters.shape[0]):
            stas[i] = stas[i] / spikenrs[i]
            # Find the pixel with largest absolute value
            max_i = np.squeeze(
                np.where(np.abs(stas[i]) == np.max(np.abs(stas[i]))))
            # If there are multiple pixels with largest value,
            # take the first one.
            if max_i.shape != (2, ):
                try:
                    max_i = max_i[:, 0]
                # If max_i cannot be found just set it to zeros.
                except IndexError:
                    max_i = np.array([0, 0])

            max_inds.append(max_i)

            quals = np.append(quals, asc.staquality(stas[i]))

        savefname = str(stim_nr) + '_data'
        savepath = pjoin(exp_dir, 'data_analysis', stimname)

        exp_name = os.path.split(exp_dir)[-1]

        if not os.path.isdir(savepath):
            os.makedirs(savepath, exist_ok=True)
        savepath = os.path.join(savepath, savefname)

        keystosave = [
            'stas', 'max_inds', 'clusters', 'sy', 'frame_duration',
            'all_spiketimes', 'stimname', 'total_frames', 'stx_w', 'spikenrs',
            'bw', 'quals', 'nblinks', 'filter_length', 'exp_name'
        ]
        data_in_dict = {}
        for key in keystosave:
            data_in_dict[key] = locals()[key]

        np.savez(savepath, **data_in_dict)
        print(f'Analysis of {stimname} completed.')
Exemple #7
0
def OMBanalyzer(exp_name, stimnr, plotall=False, nr_bins=20):
    """
    Analyze responses to object moving background stimulus. STA and STC
    are calculated.

    Note that there are additional functions that make use of the
    OMB class. This function was written before the OMB class existed
    """
    # TODO
    # Add iteration over multiple stimuli

    exp_dir = iof.exp_dir_fixer(exp_name)
    exp_name = os.path.split(exp_dir)[-1]
    stimname = iof.getstimname(exp_dir, stimnr)

    parameters = asc.read_parameters(exp_name, stimnr)
    assert parameters['stimulus_type'] == 'objectsmovingbackground'
    stimframes = parameters.get('stimFrames', 108000)
    preframes = parameters.get('preFrames', 200)
    nblinks = parameters.get('Nblinks', 2)

    seed = parameters.get('seed', -10000)
    seed2 = parameters.get('objseed', -1000)

    stepsize = parameters.get('stepsize', 2)

    ntotal = int(stimframes / nblinks)

    clusters, metadata = asc.read_spikesheet(exp_name)

    refresh_rate = metadata['refresh_rate']
    filter_length, frametimings = asc.ft_nblinks(exp_name, stimnr, nblinks,
                                                 refresh_rate)
    frame_duration = np.ediff1d(frametimings).mean()
    frametimings = frametimings[:-1]

    if ntotal != frametimings.shape[0]:
        print(f'For {exp_name}\nstimulus {stimname} :\n'
              f'Number of frames specified in the parameters file ({ntotal}'
              f' frames) and frametimings ({frametimings.shape[0]}) do not'
              ' agree!'
              ' The stimulus was possibly interrupted during recording.'
              ' ntotal is changed to match actual frametimings.')
        ntotal = frametimings.shape[0]

    # Generate the numbers to be used for reconstructing the motion
    # ObjectsMovingBackground.cpp line 174, steps are generated in an
    # alternating fashion. We can generate all of the numbers at once
    # (total lengths is defined by stimFrames) and then assign
    # to x and y directions. Although there is more
    # stuff around line 538
    randnrs, seed = randpy.gasdev(seed, ntotal * 2)
    randnrs = np.array(randnrs) * stepsize

    xsteps = randnrs[::2]
    ysteps = randnrs[1::2]

    clusterids = plf.clusters_to_ids(clusters)

    all_spikes = np.empty((clusters.shape[0], ntotal))
    for i, (cluster, channel, _) in enumerate(clusters):
        spiketimes = asc.read_raster(exp_name, stimnr, cluster, channel)
        spikes = asc.binspikes(spiketimes, frametimings)
        all_spikes[i, :] = spikes

    # Collect STA for x and y movement in one array
    stas = np.zeros((clusters.shape[0], 2, filter_length))
    stc_x = np.zeros((clusters.shape[0], filter_length, filter_length))
    stc_y = np.zeros((clusters.shape[0], filter_length, filter_length))
    t = np.arange(filter_length) * 1000 / refresh_rate * nblinks
    for k in range(filter_length, ntotal - filter_length + 1):
        x_mini = xsteps[k - filter_length + 1:k + 1][::-1]
        y_mini = ysteps[k - filter_length + 1:k + 1][::-1]
        for i, (cluster, channel, _) in enumerate(clusters):
            if all_spikes[i, k] != 0:
                stas[i, 0, :] += all_spikes[i, k] * x_mini
                stas[i, 1, :] += all_spikes[i, k] * y_mini
                # Calculate non-centered STC (Cantrell et al., 2010)
                stc_x[i, :, :] += all_spikes[i, k] * calc_covar(x_mini)
                stc_y[i, :, :] += all_spikes[i, k] * calc_covar(y_mini)

    eigvals_x = np.zeros((clusters.shape[0], filter_length))
    eigvals_y = np.zeros((clusters.shape[0], filter_length))
    eigvecs_x = np.zeros((clusters.shape[0], filter_length, filter_length))
    eigvecs_y = np.zeros((clusters.shape[0], filter_length, filter_length))

    bins_x = np.zeros((clusters.shape[0], nr_bins))
    bins_y = np.zeros((clusters.shape[0], nr_bins))
    spikecount_x = np.zeros(bins_x.shape)
    spikecount_y = np.zeros(bins_x.shape)
    generators_x = np.zeros(all_spikes.shape)
    generators_y = np.zeros(all_spikes.shape)
    # Normalize STAs and STCs with respect to spike numbers
    for i in range(clusters.shape[0]):
        totalspikes = all_spikes.sum(axis=1)[i]
        stas[i, :, :] = stas[i, :, :] / totalspikes
        stc_x[i, :, :] = stc_x[i, :, :] / totalspikes
        stc_y[i, :, :] = stc_y[i, :, :] / totalspikes
        try:
            eigvals_x[i, :], eigvecs_x[i, :, :] = np.linalg.eigh(
                stc_x[i, :, :])
            eigvals_y[i, :], eigvecs_y[i, :, :] = np.linalg.eigh(
                stc_y[i, :, :])
        except np.linalg.LinAlgError:
            continue
        # Calculate the generator signals and nonlinearities
        generators_x[i, :] = np.convolve(eigvecs_x[i, :, -1],
                                         xsteps,
                                         mode='full')[:-filter_length + 1]
        generators_y[i, :] = np.convolve(eigvecs_y[i, :, -1],
                                         ysteps,
                                         mode='full')[:-filter_length + 1]
        spikecount_x[i, :], bins_x[i, :] = nlt.calc_nonlin(
            all_spikes[i, :], generators_x[i, :], nr_bins)
        spikecount_y[i, :], bins_y[i, :] = nlt.calc_nonlin(
            all_spikes[i, :], generators_y[i, :], nr_bins)
    savepath = os.path.join(exp_dir, 'data_analysis', stimname)
    if not os.path.isdir(savepath):
        os.makedirs(savepath, exist_ok=True)

    # Calculated based on last eigenvector
    magx = eigvecs_x[:, :, -1].sum(axis=1)
    magy = eigvecs_y[:, :, -1].sum(axis=1)
    r_ = np.sqrt(magx**2 + magy**2)
    theta_ = np.arctan2(magy, magx)
    # To draw the vectors starting from origin, insert zeros every other element
    r = np.zeros(r_.shape[0] * 2)
    theta = np.zeros(theta_.shape[0] * 2)
    r[1::2] = r_
    theta[1::2] = theta_
    plt.polar(theta, r)
    plt.gca().set_xticks(np.pi / 180 * np.array([0, 90, 180, 270]))
    plt.title(f'Population plot for motion STAs\n{exp_name}')
    plt.savefig(os.path.join(savepath, 'population.svg'))
    if plotall:
        plt.show()
    plt.close()

    for i in range(stas.shape[0]):
        stax = stas[i, 0, :]
        stay = stas[i, 1, :]
        ax1 = plt.subplot(211)
        ax1.plot(t, stax, label=r'STA$_{\rm X}$')
        ax1.plot(t, stay, label=r'STA$_{\rm Y}$')
        ax1.plot(t, eigvecs_x[i, :, -1], label='Eigenvector_X 0')
        ax1.plot(t, eigvecs_y[i, :, -1], label='Eigenvector_Y 0')
        plt.legend(fontsize='x-small')

        ax2 = plt.subplot(4, 4, 9)
        ax3 = plt.subplot(4, 4, 13)
        ax2.set_yticks([])
        ax2.set_xticklabels([])
        ax3.set_yticks([])
        ax2.set_title('Eigenvalues', size='small')
        ax2.plot(eigvals_x[i, :],
                 'o',
                 markerfacecolor='C0',
                 markersize=4,
                 markeredgewidth=0)
        ax3.plot(eigvals_y[i, :],
                 'o',
                 markerfacecolor='C1',
                 markersize=4,
                 markeredgewidth=0)
        ax4 = plt.subplot(2, 3, 5)
        ax4.plot(bins_x[i, :], spikecount_x[i, :] / frame_duration)
        ax4.plot(bins_y[i, :], spikecount_y[i, :] / frame_duration)
        ax4.set_ylabel('Firing rate [Hz]')
        ax4.set_title('Nonlinearities', size='small')
        plf.spineless([ax1, ax2, ax3, ax4], 'tr')
        ax5 = plt.subplot(2, 3, 6, projection='polar')
        ax5.plot(theta, r, color='k', alpha=.3)
        ax5.plot(theta[2 * i:2 * i + 2], r[2 * i:2 * i + 2], lw=3)
        ax5.set_xticklabels(['0', '', '', '', '180', '', '270', ''])
        ax5.set_title('Vector sum of X and Y STCs', size='small')
        plt.suptitle(f'{exp_name}\n{stimname}\n{clusterids[i]}')
        plt.subplots_adjust(hspace=.4)
        plt.savefig(os.path.join(savepath, clusterids[i] + '.svg'),
                    bbox_inches='tight')
        if plotall:
            plt.show()
        plt.close()

    keystosave = [
        'nblinks', 'all_spikes', 'clusters', 'frame_duration', 'eigvals_x',
        'eigvals_y', 'eigvecs_x', 'eigvecs_y', 'filter_length', 'magx', 'magy',
        'ntotal', 'r', 'theta', 'stas', 'stc_x', 'stc_y', 'bins_x', 'bins_y',
        'nr_bins', 'spikecount_x', 'spikecount_y', 'generators_x',
        'generators_y', 't'
    ]
    datadict = {}

    for key in keystosave:
        datadict[key] = locals()[key]

    npzfpath = os.path.join(savepath, str(stimnr) + '_data')
    np.savez(npzfpath, **datadict)
Exemple #8
0
def loadstim(exp, stim_nr, maxframenr=10000):
    """
    Recreate the stimulus based on the seed for a given stimulus type.

    Each type of stimulus requires a different way of handling the
    random numbers from the PRNG.
    """
    sortedstim = asc.stimulisorter(exp)
    clusters, metadata = asc.read_spikesheet(exp)
    pars = asc.read_parameters(exp, stim_nr)

    for key, val in sortedstim.items():
        if stim_nr in val:
            stimtype = key
    if stimtype in ['fff', 'stripeflicker', 'checkerflicker', 'frozennoise']:
        seed = pars.get('seed', -10000)
        bw = pars.get('blackwhite', False)
        filter_length, frametimings = asc.ft_nblinks(exp, stim_nr)
        total_frames = frametimings.shape[0]

        if stimtype == 'fff':
            if bw:
                randnrs, seed = randpy.ranb(seed, total_frames)
                # Since ranb returns zeros and ones, we need to convert
                # the zeros into -1s.
                stimulus = np.array(randnrs) * 2 - 1
            else:
                randnrs, seed = randpy.gasdev(seed, total_frames)
                stimulus = np.array(randnrs)
        elif stimtype in ['checkerflicker', 'frozennoise']:
            scr_width = metadata['screen_width']
            scr_height = metadata['screen_height']
            stx_h = pars['stixelheight']
            stx_w = pars['stixelwidth']
            # Check whether any parameters are given for margins, calculate
            # screen dimensions.
            marginkeys = ['tmargin', 'bmargin', 'rmargin', 'lmargin']
            margins = []
            for key in marginkeys:
                margins.append(pars.get(key, 0))
            # Subtract bottom and top from vertical dimension; left and right
            # from horizontal dimension
            scr_width = scr_width - sum(margins[2:])
            scr_height = scr_height - sum(margins[:2])
            sx, sy = scr_height / stx_h, scr_width / stx_w
            # Make sure that the number of stimulus pixels are integers
            # Rounding down is also possible but might require
            # other considerations.
            if sx % 1 == 0 and sy % 1 == 0:
                sx, sy = int(sx), int(sy)
            else:
                raise ValueError('sx and sy must be integers')

            # HINT: fixing stimulus length for now because of memory
            # capacity
            total_frames = maxframenr

            randnrs, seed = randpy.ranb(seed, sx * sy * total_frames)
            # Reshape and change 0's to -1's
            stimulus = np.reshape(randnrs,
                                  (sx, sy, total_frames), order='F') * 2 - 1
        return stimulus
    if stimtype == 'OMB':
        stimframes = pars.get('stimFrames', 108000)
        preframes = pars.get('preFrames', 200)
        nblinks = pars.get('Nblinks', 2)

        seed = pars.get('seed', -10000)
        seed2 = pars.get('objseed', -1000)

        stepsize = pars.get('stepsize', 2)

        ntotal = int(stimframes / nblinks)

        clusters, metadata = asc.read_spikesheet(exp)

        refresh_rate = metadata['refresh_rate']
        filter_length, frametimings = asc.ft_nblinks(exp, stim_nr, nblinks,
                                                     refresh_rate)
        frame_duration = np.ediff1d(frametimings).mean()
        frametimings = frametimings[:-1]
        if ntotal != frametimings.shape[0]:
            print(
                f'For {exp}\nstimulus {iof.getstimname(exp, stim_nr)} :\n'
                f'Number of frames specified in the parameters file ({ntotal}'
                f' frames) and frametimings ({frametimings.shape[0]}) do not'
                ' agree!'
                ' The stimulus was possibly interrupted during recording.'
                ' ntotal is changed to match actual frametimings.')
            ntotal = frametimings.shape[0]

        randnrs, seed = randpy.gasdev(seed, ntotal * 2)
        randnrs = np.array(randnrs) * stepsize

        xsteps = randnrs[::2]
        ysteps = randnrs[1::2]

        return np.vstack((xsteps, ysteps))
    return None
contrast = pars.get('contrast', 1)
squareheight, squarewidth = (800, 800)
#%%
filterwidth = filterstd / bgstixel * 3
noiselim = (np.ceil(np.array([squareheight, squarewidth]) /
                    bgstixel)).astype(int)

# Gaussian filter is applied to the noise field by a for loop in the cpp code,
# and its norm is
xx, yy = np.meshgrid(np.arange(2 * filterwidth), np.arange(2 * filterwidth))
gfilter = np.exp2(-((xx - filterwidth)**2 + (yy - filterwidth)**2) /
                  (2 * (filterstd / bgstixel)**2))

norm = gfilter.sum()
randnrs = np.reshape(
    randpy.gasdev(bggenerationseed, noiselim[0] * noiselim[1])[0],
    (noiselim[0], noiselim[1]))
noisefield = meanintensity + meanintensity * bgcontrast * randnrs
#noisefield = np.flipud(noisefield) # Flip the texture to match the stimulator
#%%
#filtered = gaussian_filter(noisefield, np.sqrt(filterstd))
#post_tiled = np.tile(filtered, [3,3]) # Filter first, then tile

# First tile the noise field, then filter.
tiled = gaussian_filter(np.tile(noisefield, [3, 3]), np.sqrt(filterstd))

import scipy.ndimage as snd

tiled2 = snd.convolve(np.tile(noisefield, [3, 3]), gfilter)
tiled2 = ((tiled2 / norm - meanintensity) * filterstd / bgstixel +
          meanintensity)
Exemple #10
0
def fffanalyzer(exp_name, stimnrs):
    """
    Analyzes and plots data from full field flicker
    stimulus.
    """
    exp_dir = iof.exp_dir_fixer(exp_name)
    exp_name = os.path.split(exp_dir)[-1]

    if isinstance(stimnrs, int):
        stimnrs = [stimnrs]

    for stimnr in stimnrs:
        stimnr = str(stimnr)

        stimname = iof.getstimname(exp_name, stimnr)

        clusters, metadata = asc.read_spikesheet(exp_dir)

        parameters = asc.read_parameters(exp_dir, stimnr)

        clusterids = plf.clusters_to_ids(clusters)

        refresh_rate = metadata['refresh_rate']

        if parameters['stixelheight'] < 600 or parameters['stixelwidth'] < 800:
            raise ValueError('Make sure the stimulus is full field flicker.')

        nblinks = parameters['Nblinks']

        bw = parameters.get('blackwhite', False)

        seed = parameters.get('seed', -10000)

        filter_length, frametimings = asc.ft_nblinks(exp_dir, stimnr)

        frame_duration = np.average(np.ediff1d(frametimings))
        total_frames = frametimings.shape[0]

        all_spiketimes = []
        # Store spike triggered averages in a list containing correct shaped
        # arrays
        stas = []
        # Make a list for covariances of the spike triggered ensemble
        covars = []
        for i in range(len(clusters[:, 0])):
            spiketimes = asc.read_raster(exp_dir, stimnr,
                                         clusters[i, 0], clusters[i, 1])
            spikes = asc.binspikes(spiketimes, frametimings)
            all_spiketimes.append(spikes)
            stas.append(np.zeros(filter_length))
            covars.append(np.zeros((filter_length, filter_length)))

        if bw:
            randnrs, seed = randpy.ranb(seed, total_frames)
            # Since ranb returns zeros and ones, we need to convert the zeros
            # into -1s.
            stimulus = np.array(randnrs) * 2 - 1
        else:
            randnrs, seed = randpy.gasdev(seed, total_frames)
            stimulus = np.array(randnrs)

        for k in range(filter_length, total_frames-filter_length+1):
            stim_small = stimulus[k-filter_length+1:k+1][::-1]
            for j in range(clusters.shape[0]):
                spikes = all_spiketimes[j]
                if spikes[k] != 0:
                    stas[j] += spikes[k]*stim_small
                    # This trick is needed to use .T for tranposing
                    stim_small_n = stim_small[np.newaxis, :]
                    # Calculate the covariance as the weighted outer product
                    # of small stimulus(i.e. snippet) with itself
                    # This is non-centered STC (a la Cantrell et al., 2010)
                    covars[j] += spikes[k]*(np.dot(stim_small_n.T,
                                                   stim_small_n))
        spikenrs = np.array([spikearr.sum() for spikearr in all_spiketimes])

        plotpath = os.path.join(exp_dir, 'data_analysis',
                                stimname, 'filters')
        if not os.path.isdir(plotpath):
            os.makedirs(plotpath, exist_ok=True)

        t = np.arange(filter_length)*frame_duration*1000

        eigvals = [np.zeros((filter_length)) for i in range(clusters.shape[0])]
        eigvecs = [np.zeros((filter_length,
                             filter_length)) for i in range(clusters.shape[0])]

        for i in range(clusters.shape[0]):
            stas[i] = stas[i]/spikenrs[i]
            covars[i] = covars[i]/spikenrs[i]
            try:
                eigvals[i], eigvecs[i] = np.linalg.eigh(covars[i])
            except np.linalg.LinAlgError:
                eigvals[i] = np.full((filter_length), np.nan)
                eigvecs[i] = np.full((filter_length, filter_length), np.nan)
            fig = plt.figure(figsize=(9, 6))
            ax = plt.subplot(111)
            ax.plot(t, stas[i], label='STA')
            ax.plot(t, eigvecs[i][:, 0], label='STC component 1', alpha=.5)
            ax.plot(t, eigvecs[i][:, -1], label='STC component 2', alpha=.5)
            # Add eigenvalues as inset
            ax2 = fig.add_axes([.65, .15, .2, .2])
            # Highlight the first and second components which are plotted
            ax2.plot(0, eigvals[i][0], 'o',
                     markersize=7, markerfacecolor='C1', markeredgewidth=0)
            ax2.plot(filter_length-1, eigvals[i][-1], 'o',
                     markersize=7, markerfacecolor='C2', markeredgewidth=0)
            ax2.plot(eigvals[i], 'ko', alpha=.5, markersize=4,
                     markeredgewidth=0)
            ax2.set_axis_off()
            plf.spineless(ax)
            ax.set_xlabel('Time[ms]')
            ax.set_title(f'{exp_name}\n{stimname}\n{clusterids[i]} Rating:'
                         f' {clusters[i, 2]} {int(spikenrs[i])} spikes')
            plt.savefig(os.path.join(plotpath, clusterids[i])+'.svg',
                        format='svg', dpi=300)
            plt.close()

        savepath = os.path.join(os.path.split(plotpath)[0], stimnr+'_data')

        keystosave = ['stas', 'clusters', 'frame_duration', 'all_spiketimes',
                      'stimname', 'total_frames', 'spikenrs', 'bw', 'nblinks',
                      'filter_length', 'exp_name', 'covars', 'eigvals',
                      'eigvecs']
        data_in_dict = {}
        for key in keystosave:
            data_in_dict[key] = locals()[key]

        np.savez(savepath, **data_in_dict)
        print(f'Analysis of {stimname} completed.')
Exemple #11
0
                              'noise is implemented.')

bgcontrast = pars.get('bgcontrast', 0.3)
bggenerationseed = -10000
filterstd = pars.get('filterstdv', bgstixel)
meanintensity = pars.get('meanintensity', 0.5)
contrast = pars.get('contrast', 1)
squareheight, squarewidth = (800, 800)

ntotal = int(stimframes / nblinks)
refresh_rate = metadata['refresh_rate']

_, frametimings = asc.ft_nblinks(exp, stimnr, nblinks,
                                             refresh_rate)
frame_duration = np.ediff1d(frametimings).mean()
frametimings = frametimings[:-1]
if ntotal != frametimings.shape[0]:
    print(f'For {exp}\nstimulus {iof.getstimname(exp, stimnr)} :\n'
          f'Number of frames specified in the parameters file ({ntotal}'
          f' frames) and frametimings ({frametimings.shape[0]}) do not'
          ' agree!'
          ' The stimulus was possibly interrupted during recording.'
          ' ntotal is changed to match actual frametimings.')
    ntotal = frametimings.shape[0]

randnrs, seed = randpy.gasdev(seed, ntotal*2)
randnrs = np.array(randnrs)*stepsize

xsteps = randnrs[::2]
ysteps = randnrs[1::2]
def stripeflickeranalysis(exp_name, stim_nrs):
    exp_dir = iof.exp_dir_fixer(exp_name)

    if isinstance(stim_nrs, int):
        stim_nrs = [stim_nrs]
    elif len(stim_nrs) == 0:
        return

    for stim_nr in stim_nrs:
        stimname = iof.getstimname(exp_name, stim_nr)

        clusters, metadata = asc.read_spikesheet(exp_dir)

        parameters = asc.read_parameters(exp_dir, stim_nr)

        scr_width = metadata['screen_width']
        px_size = metadata['pixel_size(um)']

        refresh_rate = metadata['refresh_rate']

        stx_w = parameters['stixelwidth']
        stx_h = parameters['stixelheight']

        if (stx_h / stx_w) < 2:
            raise ValueError('Make sure the stimulus is stripeflicker.')

        sy = scr_width / stx_w
        if sy % 1 == 0:
            sy = int(sy)
        else:
            raise ValueError('sy is not an integer')

        nblinks = parameters['Nblinks']

        bw = parameters.get('blackwhite', False)

        seed = parameters.get('seed', -10000)

        filter_length, frametimings = asc.ft_nblinks(exp_dir, stim_nr)

        # Omit everything that happens before the first 10 seconds
        cut_time = 10

        frame_duration = np.average(np.ediff1d(frametimings))
        total_frames = frametimings.shape[0]

        all_spiketimes = []
        # Store spike triggered averages in a list containing correct
        # shaped arrays
        stas = []

        for i in range(len(clusters[:, 0])):
            spiketimes = asc.read_raster(exp_dir, stim_nr, clusters[i, 0],
                                         clusters[i, 1])
            spikes = asc.binspikes(spiketimes, frametimings)
            all_spiketimes.append(spikes)
            stas.append(np.zeros((sy, filter_length)))

        # Add one more element to correct for random noise
        clusters = np.vstack((clusters, [0, 0, 0]))
        all_spiketimes.append(np.ones(frametimings.shape, dtype=int))
        stas.append(np.zeros((sy, filter_length)))

        if bw:
            randnrs, seed = randpy.ranb(seed, sy * total_frames)
        else:
            randnrs, seed = randpy.gasdev(seed, sy * total_frames)

        stimulus = np.reshape(randnrs, (sy, total_frames), order='F')

        if bw:
            # Since ranb returns zeros and ones, we need to convert the zeros
            # into -1s.
            stimulus = stimulus * 2 - 1

        del randnrs

        for k in range(filter_length, total_frames - filter_length + 1):
            stim_small = stimulus[:, k - filter_length + 1:k + 1][:, ::-1]
            for j in range(clusters.shape[0]):
                spikes = all_spiketimes[j]
                if spikes[k] != 0 and frametimings[k] > cut_time:
                    stas[j] += spikes[k] * stim_small

        max_inds = []
        spikenrs = np.array([spikearr.sum() for spikearr in all_spiketimes])

        quals = np.array([])

        # Remove the random noise correction element from clusters
        correction = stas.pop() / spikenrs[-1]
        clusters = clusters[:-1, :]
        all_spiketimes.pop()
        spikenrs = spikenrs[:-1]

        for i in range(clusters.shape[0]):
            stas[i] = stas[i] / spikenrs[i]
            stas[i] = stas[i] - correction
            # Find the pixel with largest absolute value
            max_i = np.squeeze(
                np.where(np.abs(stas[i]) == np.max(np.abs(stas[i]))))
            # If there are multiple pixels with largest value,
            # take the first one.
            if max_i.shape != (2, ):
                try:
                    max_i = max_i[:, 0]
                # If max_i cannot be found just set it to zeros.
                except IndexError:
                    max_i = np.array([0, 0])
            # In case of spike numbers being zero, all elements are NaN
            # imshow and savefig do not play nice with NaN so set all to zero
            if np.all(np.isnan(stas[i])):
                stas[i] = np.zeros(stas[i].shape)
            max_inds.append(max_i)

            quals = np.append(quals, asc.staquality(stas[i]))

        savefname = str(stim_nr) + '_data'
        savepath = pjoin(exp_dir, 'data_analysis', stimname)

        exp_name = os.path.split(exp_dir)[-1]

        if not os.path.isdir(savepath):
            os.makedirs(savepath, exist_ok=True)
        savepath = os.path.join(savepath, savefname)

        keystosave = [
            'stas', 'max_inds', 'clusters', 'sy', 'correction',
            'frame_duration', 'all_spiketimes', 'stimname', 'total_frames',
            'stx_w', 'spikenrs', 'bw', 'quals', 'nblinks', 'filter_length',
            'exp_name'
        ]
        data_in_dict = {}
        for key in keystosave:
            data_in_dict[key] = locals()[key]

        np.savez(savepath, **data_in_dict)
        print(f'Analysis of {stimname} completed.')