Example #1
0
def smooth_ttest_results(tmin, tstep, subjects_dir, inverse_method='dSPM', n_jobs=1):
    for cond_id, cond_name in enumerate(events_id.keys()):
        for patient in get_patients():
            results_file_name = op.join(LOCAL_ROOT_DIR, 'permutation_ttest_results', '{}_{}_{}_clusters.npy'.format(patient, cond_name, inverse_method))
            if op.isfile(results_file_name):
                data = np.load(results_file_name)
                print('smoothing {} {}'.format(patient, cond_name))
                fsave_vertices = [np.arange(10242), np.arange(10242)]
                stc = _make_stc(data, fsave_vertices, tmin=tmin, tstep=tstep, subject='fsaverage')
                vertices_to = mne.grade_to_vertices('fsaverage', grade=None, subjects_dir=subjects_dir)
                print(stc.data.shape, vertices_to[0].shape)
                stc_smooth = mne.morph_data('fsaverage', 'fsaverage', stc, n_jobs=n_jobs, grade=vertices_to, subjects_dir=subjects_dir)
                stc_smooth.save(op.join(LOCAL_ROOT_DIR, 'results_for_blender', '{}_{}_{}'.format(patient, cond_name, inverse_method)), ftype='h5')
            else:
                print('no results for {} {}'.format(patient, cond_name))
Example #2
0
def calc_labels_avg(events_id, tmin, inverse_method='dSPM', do_plot=False):
    d = np.load(op.join(LOCAL_ROOT_DIR, 'fsaverage_labels_indices.npz'))
    labels_vertices, labels_names = d['labels_vertices'], d['labels_names']

    if do_plot:
        plt.close('all')
        plt.figure()

    res_fol = op.join(LOCAL_ROOT_DIR, 'permutation_ttest_results')
    for cond_id, cond_name in enumerate(events_id.keys()):
        for patient in get_patients():
            blender_fol = blender_template.format(patient=patient, cond_name=cond_name)
            results_file_name = op.join(res_fol, '{}_{}_{}.npz'.format(patient, cond_name, inverse_method))
            clusters_file_name = op.join(res_fol, '{}_{}_{}_clusters.npy'.format(patient, cond_name, inverse_method))
            if op.isfile(results_file_name) and op.isfile(clusters_file_name):
                print('{}, {}'.format(patient, cond_name))
                clusters = np.load(clusters_file_name)
                ttest_res = np.load(results_file_name)
                for data, data_name in zip([ttest_res['T_obs'].T, clusters], ['ttest_res', 'clusters']):
                    fsave_vertices = utils.fsaverage_vertices()
                    stc = _make_stc(data, fsave_vertices, tmin=tmin, tstep=tstep, subject='fsaverage')
                    labels_data = np.zeros((len(labels_vertices), stc.data.shape[1], 2))
                    for ind, (vertidx, label_name) in enumerate(zip(labels_vertices, labels_names)):
                        if vertidx is not None:
                            labels_data[ind] = utils.get_max_min(stc.data[vertidx, :])
                        if do_plot:
                            plt.plot(labels_data[ind, :, 0], label='{} p<c'.format(label_name))
                            plt.plot(labels_data[ind, :, 1], label='{} p>c'.format(label_name))
                    for hemi in ['rh', 'lh']:
                        indices = [ind for ind, l in enumerate(labels_names) if hemi in l]
                        labels = [str(l) for l in labels_names if hemi in l]
                        np.savez(op.join(blender_fol, 'labels_data_{}_{}.npz'.format(hemi, data_name)),
                            data=labels_data[indices], names=labels, conditions=['p<c', 'p>c'])

                    if do_plot:
                        plt.legend()
                        plt.xlabel('time (ms)')
                        plt.title('{} {}'.format(patient, cond_name))
                        plt.show()
                        print('show!')

                # Make clusters to be the default files for blender
                for hemi in ['rh', 'lh']:
                    utils.copy_file(op.join(blender_fol, 'labels_data_{}_clusters.npz'.format(hemi)),
                                    op.join(blender_fol, 'labels_data_{}.npz'.format(hemi)))
Example #3
0
    def make_stc(self, summary='sum', weight_by_degree=True):
        """Obtain a summary of the connectivity as a SourceEstimate object.

        Parameters
        ----------
        summary : 'degree' | 'mean'
            How to summarize the adjacency data:

                'sum' : sum the strenghts of both the incoming and outgoing
                        connections for each source.
                'degree': count the number of incoming and outgoing
                          connections for each source.

            Defaults to ``'sum'``.

        weight_by_degree : bool
            Whether to weight the summary by the number of possible
            connections. Defaults to ``True``.

        Returns
        -------
        stc : instance of SourceEstimate
            The summary of the connectivity.
        """
        if self.vertices is None:
            raise ValueError('Stc needs vertices!')

        if summary == 'degree':
            vert_inds, data = np.unique(self.pairs, return_counts=True)

            n_vert_lh = len(self.vertices[0])
            lh_inds = vert_inds < n_vert_lh
            vertices = [
                self.vertices[0][vert_inds[lh_inds]],
                self.vertices[1][vert_inds[~lh_inds] - n_vert_lh]
            ]

        elif summary == 'sum':
            A = self.get_adjacency()
            vert_inds = np.arange(
                len(self.vertices[0]) + len(self.vertices[1]))
            vertices = self.vertices
            data = A.sum(axis=0).T + A.sum(axis=1)

            # For undirected connectivity objects, all connections have been
            # counted twice.
            if not self.directed:
                data = data / 2.

        else:
            raise ValueError('The summary parameter must be "degree", or '
                             '"sum".')

        data = np.asarray(data, dtype=np.float).ravel()

        if weight_by_degree:
            degree = self.source_degree[:, vert_inds].sum(axis=0)
            # Prevent division by zero
            zero_mask = degree == 0
            data[~zero_mask] /= degree[~zero_mask]
            data[zero_mask] = 0

        return _make_stc(data[:, np.newaxis],
                         vertices=vertices,
                         tmin=0,
                         tstep=1,
                         subject=self.subject)
Example #4
0
def plot_results_src_space(fourier_ica_obj, W_orig, A_orig,
                           src_loc_data, vertno,
                           sfreq=None, flow=None, fhigh=None,
                           tpre=None, win_length_sec=None,
                           fnout=None, tICA=False,
                           stim_name=[], n_jobs=4,
                           morph2fsaverage=False,
                           subject='fsaverage',
                           subjects_dir=None,
                           temporal_envelope=[],
                           time_range=[None, None],
                           global_scaling=False,
                           classification={},
                           percentile=97, show=True):

    """
    Generate plot containing all results achieved by
    applying FourierICA in source space, i.e., plot
    spatial and spectral profiles.

        Parameters
        ----------

    """

    # ------------------------------------------
    # import necessary modules
    # ------------------------------------------
    from matplotlib import pyplot as plt
    from matplotlib import gridspec as grd
    from mayavi import mlab
    from mne.baseline import rescale
    from mne.source_estimate import _make_stc
    from mne.time_frequency._stockwell import _induced_power_stockwell
    from os import environ, makedirs, rmdir, remove
    from os.path import exists, join
    from scipy import fftpack, misc
    import types


    # -------------------------------------------
    # check input parameter
    # -------------------------------------------
    if tpre == None:
        tpre = fourier_ica_obj.tpre
    if flow == None:
        flow = fourier_ica_obj.flow
    if not fhigh:
        fhigh = fourier_ica_obj.fhigh
    if not sfreq:
        sfreq = fourier_ica_obj.sfreq
    if not win_length_sec:
        win_length_sec = fourier_ica_obj.win_length_sec


    win_ntsl = int(np.floor(sfreq * win_length_sec))
    startfftind = int(np.floor(flow * win_length_sec))
    ncomp, nvoxel = W_orig.shape
    nfreq, nepochs, nvoxel = src_loc_data.shape

    if time_range == [None, None]:
        time_range = [tpre, tpre + win_length_sec]


    # -------------------------------------------
    # generate spatial profiles
    # (using magnitude and phase)
    # -------------------------------------------
    if not subjects_dir:
        subjects_dir = environ.get('SUBJECTS_DIR')

    if isinstance(A_orig[0, 0], types.ComplexType):
        A_orig_mag = np.abs(A_orig)
    else:
        A_orig_mag = A_orig


    # create temporary directory to save plots
    # of spatial profiles
    temp_plot_dir = join(subjects_dir, subject, 'temp_plots')
    if not exists(temp_plot_dir):
        makedirs(temp_plot_dir)


    # -------------------------------------------
    # check if temporal envelope is already
    # given or should be estimated
    # -------------------------------------------
    if not np.any(temporal_envelope):
        # -------------------------------------------
        # get independent components
        # -------------------------------------------
        act = np.zeros((ncomp, nepochs, nfreq), dtype=np.complex)
        if tICA:
            win_ntsl = nfreq

        temporal_envelope = np.zeros((nepochs, ncomp, win_ntsl))
        fft_act = np.zeros((ncomp, win_ntsl), dtype=np.complex)

        for iepoch in range(nepochs):
            src_loc_zero_mean = (src_loc_data[:, iepoch, :] - np.dot(np.ones((nfreq, 1)), fourier_ica_obj.dmean)) / \
                                np.dot(np.ones((nfreq, 1)), fourier_ica_obj.dstd)

            act[:ncomp, iepoch, :] = np.dot(W_orig, src_loc_zero_mean.transpose())
            act[ncomp:, iepoch, :] = np.dot(W_orig, src_loc_zero_mean.transpose())

            if tICA:
                temporal_envelope[iepoch, :, :] = act[:, iepoch, :].real

            else:
                # -------------------------------------------
                # generate temporal profiles
                # -------------------------------------------
                # apply inverse STFT to get temporal envelope
                fft_act[:, startfftind:(startfftind+nfreq)] = act[:, iepoch, :]
                temporal_envelope[iepoch, :, :] = fftpack.ifft(fft_act, n=win_ntsl, axis=1).real


    # check if classsification was done
    key_borders = []
    if np.any(classification):
        idx_sort = []
        keys = classification.keys()
        for key in classification:
            idx_sort += classification[key]
            key_borders.append(len(classification[key]))

        key_borders = np.insert(key_borders, 0, 1)
        key_borders = np.cumsum(key_borders)[:-1]

    else:
        idx_sort = np.arange(ncomp)


    # average temporal envelope
    if not isinstance(temporal_envelope, list):
        temporal_envelope = [[temporal_envelope]]

    ntemp = len(temporal_envelope)
    temporal_envelope_mean = np.empty((ntemp, 0)).tolist()

    for itemp in range(ntemp):
        temporal_envelope_mean[itemp].append(np.mean(temporal_envelope[itemp][0], axis=0)[:, 5:-5])

    # scale temporal envelope between 0 and 1
    min_val = np.min(temporal_envelope_mean)
    max_val = np.max(temporal_envelope_mean)
    scale_fact = 1.0 / (max_val - min_val)

    for itemp in range(ntemp):
        temporal_envelope_mean[itemp][0] = np.clip(scale_fact * temporal_envelope_mean[itemp][0] - scale_fact * min_val, 0., 1.)

    ylim_temp = [-0.05, 1.05]


    # -------------------------------------------
    # loop over all components to generate
    # spatial profiles
    # Note: This will take a while
    # -------------------------------------------
    for icomp in range(ncomp):

        # generate stc-object from current component
        A_cur = A_orig_mag[:, icomp]

        src_loc = _make_stc(A_cur[:, np.newaxis], vertices=vertno, tmin=0, tstep=1,
                            subject=subject)

        # define current range (Xth percentile)
        fmin = np.percentile(A_cur, percentile)
        fmax = np.max(A_cur)
        fmid = 0.5 * (fmin + fmax)
        clim = {'kind': 'value',
                'lims': [fmin, fmid, fmax]}


        # plot spatial profiles
        brain = src_loc.plot(surface='inflated', hemi='split', subjects_dir=subjects_dir,
                             config_opts={'cortex': 'bone'}, views=['lateral', 'medial'],
                             time_label=' ', colorbar=False, clim=clim)

        # save results
        fn_base = "IC%02d_spatial_profile.png" % (icomp+1)
        fnout_img = join(temp_plot_dir, fn_base)
        brain.save_image(fnout_img)


    # close mlab figure
    mlab.close(all=True)


    # -------------------------------------------
    # loop over all components to generate
    # spectral profiles
    # -------------------------------------------
    average_power_all = np.empty((ntemp, 0)).tolist()
    vmin = np.zeros(ncomp)
    vmax = np.zeros(ncomp)

    for itemp in range(ntemp):
        for icomp in range(ncomp):

            nepochs = temporal_envelope[itemp][0].shape[0]
            times = np.arange(win_ntsl)/sfreq + tpre
            idx_start = np.argmin(np.abs(times - time_range[0]))
            idx_end = np.argmin(np.abs(times - time_range[1]))

            data_stockwell = temporal_envelope[itemp][0][:, icomp, idx_start:idx_end].\
                reshape((nepochs, 1, idx_end-idx_start))


            power_data, _, freqs = _induced_power_stockwell(data_stockwell, sfreq=sfreq, fmin=flow,
                                                            fmax=fhigh, width=1.0, decim=1,
                                                            return_itc=False, n_jobs=4)



            # perform baseline correction
            if time_range[0] < 0:
                power_data = rescale(power_data, times[idx_start:idx_end], (None, 0), 'mean')
                imax = np.argmin(np.abs(times[idx_start:idx_end]))
                power_data /= np.sqrt(np.std(power_data[..., :imax], axis=-1)[..., None])

            average_power = power_data.reshape((power_data.shape[1], power_data.shape[2]))
            average_power_all[itemp].append(average_power)

            # define thresholds
            if time_range[0] < 0:
                # vmax[icomp] = np.max((np.nanmax(average_power), vmax[icomp]))  # np.percentile(average_power_all, 99.9)
                # vmin[icomp] = np.min((np.nanmin(average_power), vmin[icomp]))  # np.percentile(average_power_all, 0.1)
                vmax[icomp] = np.max((np.percentile(average_power, 99), vmax[icomp]))  # np.percentile(average_power_all, 99.9)
                vmin[icomp] = np.min((np.percentile(average_power, 1), vmin[icomp]))  # np.percentile(average_power_all, 0.1)


                if np.abs(vmax[icomp]) > np.abs(vmin[icomp]):
                    vmin[icomp] = - np.abs(vmax[icomp])
                else:
                    vmax[icomp] = np.abs(vmin[icomp])

            else:
                vmin[icomp] = None
                vmax[icomp] = None


    # ------------------------------------------
    # loop over all activations
    # ------------------------------------------
    plt.ioff()
    nimg = 1

    # loop over all images
    for iimg in range(nimg):

        fig = plt.figure('FourierICA plots', figsize=(11 + ntemp*10, 60))
        idx_class = 0

        # estimate how many plots on current image
        istart_plot = int(ncomp*iimg)
        nplot = [ncomp]
        gs = grd.GridSpec(ncomp*20+len(key_borders)*10, (ntemp+1)*10, wspace=0.1, hspace=0.05,
                          left=0.04, right=0.96, bottom=0.04, top=0.96)

        for icomp in range(istart_plot, nplot[iimg]):


            if (icomp + 1) in key_borders:
                p_text = fig.add_subplot(gs[20*(icomp-istart_plot)+idx_class*10:20*(icomp-istart_plot)+8+idx_class*10, 0:10])
                idx_class += 1
                p_text.text(0, 0, keys[idx_class-1], fontsize=25)
                adjust_spines(p_text, [])


            # ----------------------------------------------
            # plot spatial profiles (magnitude)
            # ----------------------------------------------
            # spatial profile
            fn_base = "IC%02d_spatial_profile.png" % (idx_sort[icomp]+1)
            fnin_img = join(temp_plot_dir, fn_base)
            spat_tmp = misc.imread(fnin_img)
            remove(fnin_img)

            # rearrange image
            x_size, y_size, _ = spat_tmp.shape
            x_half, y_half = x_size/2, y_size/2
            x_frame = int(0.15*x_half)
            y_frame = int(0.05*y_half)
            spatial_profile = np.concatenate((spat_tmp[x_frame:(x_half-x_frame), y_frame:(y_half-y_frame), :],
                                              spat_tmp[(x_half+x_frame):-x_frame, y_frame:(y_half-y_frame), :],
                                              spat_tmp[(x_half+x_frame):-x_frame, (y_half+y_frame):-y_frame, :],
                                              spat_tmp[x_frame:(x_half-x_frame), (y_half+y_frame):-y_frame, :]), axis=1)


            p1 = fig.add_subplot(gs[20*(icomp-istart_plot)+idx_class*10:20*(icomp-istart_plot)+15+idx_class*10, 0:10])
            p1.imshow(spatial_profile)
            p1.yaxis.set_ticks([])
            p1.xaxis.set_ticks([])
            y_name = "IC#%02d" % (idx_sort[icomp]+1)
            p1.set_ylabel(y_name)


            # ----------------------------------------------
            # temporal/spectral profile
            # ----------------------------------------------
            for itemp in range(ntemp):

                if icomp == 0 and len(stim_name):
                    p_text = fig.add_subplot(gs[20*(icomp-istart_plot)+(idx_class-1)*10: \
                        20*(icomp-istart_plot)+8+(idx_class-1)*10, (itemp+1)*10+4:(itemp+2)*10-1])
                    p_text.text(0, 0, "  " + stim_name[itemp], fontsize=30)
                    adjust_spines(p_text, [])


                times = (np.arange(win_ntsl)/sfreq + tpre)[5:-5]
                idx_start = np.argmin(np.abs(times - time_range[0]))
                idx_end = np.argmin(np.abs(times - time_range[1]))
                average_power = average_power_all[itemp][idx_sort[icomp]]
                extent = (times[idx_start], times[idx_end], freqs[0], freqs[-1])
                p2 = plt.subplot(gs[20*(icomp-istart_plot)+idx_class*10:20*(icomp-istart_plot)+15+idx_class*10,
                                 (itemp+1)*10+1:(itemp+2)*10-1])

                if global_scaling:
                    vmin_cur, vmax_cur = np.min(vmin), np.max(vmax)
                else:
                    vmin_cur, vmax_cur = vmin[icomp], vmax[icomp]

                p2.imshow(average_power, extent=extent, aspect="auto", origin="lower",
                          picker=False, cmap='RdBu_r', vmin=vmin_cur, vmax=vmax_cur)    # cmap='RdBu', vmin=vmin, vmax=vmax)
                p2.set_xlabel("time [s]")
                p2.set_ylabel("freq. [Hz]")
                ax = p2.twinx()
                ax.set_xlim(times[idx_start], times[idx_end])
                ax.set_ylim(ylim_temp)
                ax.set_ylabel("ampl. [a.u.]")
                ax.plot(times[idx_start:idx_end], temporal_envelope_mean[itemp][0][idx_sort[icomp], idx_start:idx_end],
                        color='black', linewidth=3.0)


        # save image
        if fnout:
            fnout_complete = '%s%02d.png' % (fnout, iimg+1)
            plt.savefig(fnout_complete, format='png', dpi=300)

        # show image if requested
        if show:
            plt.show()

        plt.close('FourierICA plots')

    # remove temporary directory for
    # spatial profile plots
    if exists(temp_plot_dir):
        rmdir(temp_plot_dir)

    plt.ion()
Example #5
0
def _apply_lcmv(data, filters, info, tmin, max_ori_out):
    """Apply LCMV spatial filter to data for source reconstruction.

    Copied directly from MNE to remove dependence on source space in
    filter. This makes the filter much smaller and easier to use 
    multiprocessing here.

    Original authors: 
    Authors: Alexandre Gramfort <*****@*****.**>
              Roman Goj <*****@*****.**>
              Britta Westner <*****@*****.**>

    Original License: BSD (3-clause)
    """
    from mne.source_estimate import _make_stc
    from mne.minimum_norm.inverse import combine_xyz
    if max_ori_out != 'signed':
        raise ValueError('max_ori_out must be "signed", got %s' %
                         (max_ori_out, ))

    if isinstance(data, np.ndarray) and data.ndim == 2:
        data = [data]
        return_single = True
    else:
        return_single = False

    W = filters['weights']

    #subject = _subject_from_forward(filters)
    for i, M in enumerate(data):
        if len(M) != len(filters['ch_names']):
            raise ValueError('data and picks must have the same length')

        if filters['is_ssp']:
            raise RuntimeError('SSP not supported here')

        if filters['whitener'] is not None:
            M = np.dot(filters['whitener'], M)

        # project to source space using beamformer weights
        vector = False
        if filters['is_free_ori']:
            sol = np.dot(W, M)
            if filters['pick_ori'] == 'vector':
                vector = True
            else:
                sol = combine_xyz(sol)
        else:
            # Linear inverse: do computation here or delayed
            if (M.shape[0] < W.shape[0]
                    and filters['pick_ori'] != 'max-power'):
                sol = (W, M)
            else:
                sol = np.dot(W, M)
            if filters['pick_ori'] == 'max-power' and max_ori_out == 'abs':
                sol = np.abs(sol)

        tstep = 1.0 / info['sfreq']
        yield _make_stc(sol,
                        vertices=filters['vertices'],
                        tmin=tmin,
                        tstep=tstep,
                        subject='NN',
                        vector=vector,
                        source_nn=filters['source_nn'])