def apply_solver(evoked, forward, noise_cov, loose=0.2, depth=0.8, K=2000): all_ch_names = evoked.ch_names # put the forward solution in fixed orientation if it's not already if loose is None and not is_fixed_orient(forward): forward = deepcopy(forward) forward = mne.convert_forward_solution(forward, force_fixed=True) gain, gain_info, whitener, source_weighting, mask = _prepare_gain( forward, evoked.info, noise_cov, pca=False, depth=depth, loose=loose, weights=None, weights_min=None) n_locations = gain.shape[1] sel = [all_ch_names.index(name) for name in gain_info['ch_names']] M = evoked.data[sel] # Whiten data M = np.dot(whitener, M) n_orient = 1 if is_fixed_orient(forward) else 3 # The value of lambda for which the solution will be all zero lambda_max = norm_l2inf(np.dot(gain.T, M), n_orient) lambda_ref = 0.1 * lambda_max out = mm_mixed_norm_bayes(M, gain, lambda_ref, n_orient=n_orient, K=K, return_lpp=True) (Xs, active_sets), _, _, _, _ = out solution_support = np.zeros((K, n_locations)) stcs, obj_fun = [], [] for k in range(K): X = np.zeros((n_locations, Xs[k].shape[1])) X[active_sets[k]] = Xs[k] block_norms_new = compute_block_norms(X, n_orient) block_norms_new = (block_norms_new > 0.05 * block_norms_new.max()) solution_support[k, :] = block_norms_new stc = _make_sparse_stc(Xs[k], active_sets[k], forward, tmin=0., tstep=1. / evoked.info['sfreq']) stcs.append(stc) obj_fun.append( energy_l2half_reg(M, gain, stc.data, active_sets[k], lambda_ref, n_orient)) return solution_support, stcs, obj_fun
def apply_solver_isdr(solver, evoked, forward, noise_cov, loose=0.2, depth=0.8): # Import the necessary private functions from mne.inverse_sparse.mxne_inverse import \ (_prepare_gain, _check_loose_forward, is_fixed_orient, _reapply_source_weighting, _make_sparse_stc) all_ch_names = evoked.ch_names loose, forward = _check_loose_forward(loose, forward) # put the forward solution in fixed orientation if it's not already if loose == 0. and not is_fixed_orient(forward): forward = mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=True, use_cps=True) # Handle depth weighting and whitening (here is no weights) gain, gain_info, whitener, source_weighting, mask = _prepare_gain( forward, evoked.info, noise_cov, pca=False, depth=depth, loose=loose, weights=None, weights_min=None) print source_weighting # Select channels of interest sel = [all_ch_names.index(name) for name in gain_info['ch_names']] M = evoked.data[sel] # Whiten data M = np.dot(whitener, M).astype(np.double) active_set = np.zeros(gain.shape[1], dtype=bool) gain = gain[:, :].astype(np.double) n_orient = 1 if is_fixed_orient(forward) else 3 SC = np.eye(np.shape(gain)[1]).astype(np.int32) GA = gain.copy().astype(np.double) X, n_active_set, coef = solver_isdr(M, gain, GA, SC) active_set[n_active_set] = True #X = _reapply_source_weighting(X, source_weighting, active_set, n_orient) #Z = np.zeros((np.shape(gain)[1], np.shape(M)[1])) #Z[np.array(n_active_set), :] = X[:np.shape(M)[1], :len(n_active_set)].T #stc = _make_sparse_stc(Z, active_set, forward, tmin=evoked.times[0], tstep=1. / evoked.info['sfreq']) return X #stc
def apply_solver(solver, evoked, forward, noise_cov, loose=0.2, depth=0.8): """Call a custom solver on evoked data. This function does all the necessary computation: - to select the channels in the forward given the available ones in the data - to take into account the noise covariance and do the spatial whitening - to apply loose orientation constraint as MNE solvers - to apply a weigthing of the columns of the forward operator as in the weighted Minimum Norm formulation in order to limit the problem of depth bias. Parameters ---------- solver : callable The solver takes 3 parameters: data M, gain matrix G, number of dipoles orientations per location (1 or 3). A solver shall return 2 variables: X which contains the time series of the active dipoles and an active set which is a boolean mask to specify what dipoles are present in X. evoked : instance of mne.Evoked The evoked data forward : instance of Forward The forward solution. noise_cov : instance of Covariance The noise covariance. loose : float in [0, 1] | 'auto' Value that weights the source variances of the dipole components that are parallel (tangential) to the cortical surface. If loose is 0 then the solution is computed with fixed orientation. If loose is 1, it corresponds to free orientations. The default value ('auto') is set to 0.2 for surface-oriented source space and set to 1.0 for volumic or discrete source space. depth : None | float in [0, 1] Depth weighting coefficients. If None, no depth weighting is performed. Returns ------- stc : instance of SourceEstimate The source estimates. """ # Import the necessary private functions from mne.inverse_sparse.mxne_inverse import \ (_prepare_gain, is_fixed_orient, _reapply_source_weighting, _make_sparse_stc) all_ch_names = evoked.ch_names # Handle depth weighting and whitening (here is no weights) forward, gain, gain_info, whitener, source_weighting, mask = _prepare_gain( forward, evoked.info, noise_cov, pca=False, depth=depth, loose=loose, weights=None, weights_min=None, rank=None) # Select channels of interest sel = [all_ch_names.index(name) for name in gain_info['ch_names']] M = evoked.data[sel] # Whiten data M = np.dot(whitener, M) n_orient = 1 if is_fixed_orient(forward) else 3 X, active_set = solver(M, gain, n_orient) X = _reapply_source_weighting(X, source_weighting, active_set) stc = _make_sparse_stc(X, active_set, forward, tmin=evoked.times[0], tstep=1. / evoked.info['sfreq']) return stc
def apply_solver(solver, evoked, forward, noise_cov, loose=0.2, depth=0.8): """Function to call a custom solver on evoked data This function does all the necessary computation: - to select the channels in the forward given the available ones in the data - to take into account the noise covariance and do the spatial whitening - to apply loose orientation constraint as MNE solvers - to apply a weigthing of the columns of the forward operator as in the weighted Minimum Norm formulation in order to limit the problem of depth bias. Parameters ---------- solver : callable The solver takes 3 parameters: data M, gain matrix G, number of dipoles orientations per location (1 or 3). A solver shall return 2 variables: X which contains the time series of the active dipoles and an active set which is a boolean mask to specify what dipoles are present in X. evoked : instance of mne.Evoked The evoked data forward : instance of Forward The forward solution. noise_cov : instance of Covariance The noise covariance. loose : None | float in [0, 1] Value that weights the source variances of the dipole components defining the tangent space of the cortical surfaces. Requires surface- based, free orientation forward solutions. depth : None | float in [0, 1] Depth weighting coefficients. If None, no depth weighting is performed. Returns ------- stc : instance of SourceEstimate The source estimates. """ # Import the necessary private functions from mne.inverse_sparse.mxne_inverse import \ (_prepare_gain, _to_fixed_ori, is_fixed_orient, _reapply_source_weighting, _make_sparse_stc) all_ch_names = evoked.ch_names # put the forward solution in fixed orientation if it's not already if loose is None and not is_fixed_orient(forward): forward = forward.copy() _to_fixed_ori(forward) # Handle depth weighting and whitening (here is no weights) gain, gain_info, whitener, source_weighting, mask = _prepare_gain( forward, evoked.info, noise_cov, pca=False, depth=depth, loose=loose, weights=None, weights_min=None) # Select channels of interest sel = [all_ch_names.index(name) for name in gain_info['ch_names']] M = evoked.data[sel] # Whiten data M = np.dot(whitener, M) n_orient = 1 if is_fixed_orient(forward) else 3 X, active_set = solver(M, gain, n_orient) X = _reapply_source_weighting(X, source_weighting, active_set, n_orient) stc = _make_sparse_stc(X, active_set, forward, tmin=evoked.times[0], tstep=1. / evoked.info['sfreq']) return stc