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))
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)))
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)
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()
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'])