Skip to main content

InvMxne

Namespace: INVLIB  ·  Library: Inverse Library

Python equivalent

mne.inverse_sparse.mixed_norm in MNE-Python.

#include <inv/inv_mxne.h>

class INVLIB::InvMxne

Mixed-Norm Estimate (MxNE) sparse inverse solver.

Minimizes: 0.5 * ||M - G*X||^2_F + alpha * sum_i ||X_i||_2, the objective of mne.inverse_sparse.mixed_norm (without debiasing) using an Iteratively Reweighted Least Squares (IRLS) approach for the L21-norm (group lasso).

MxNE sparse inverse solver.

src/examples/ex_inv_api/main.cpp
// Whitened data and a gain per nAm make the noise level 1, as mne.inverse_sparse.mixed_norm does.
const auto [whitener, rank] = computeWhitener(*inverse.noise_cov); // rank 360: 364 channels minus 4 projectors
QFile fixedFile(fwdFile.fileName());
const MNEForwardSolution fixedFwd = MNEForwardSolution(fixedFile, true, true).pick_regions({v1}).pick_channels(inverse.noise_cov->names);
const MatrixXd gain = whitener * fixedFwd.sol->data * 1e-9;
const MatrixXd measured = whitener * evoked.pick_channels(inverse.noise_cov->names).data.middleCols(170, 40); // 83-148 ms
const double alphaMax = (gain.transpose() * measured).rowwise().norm().maxCoeff();
const InvMxneResult mxne = InvMxne::compute(gain, measured, 0.5 * alphaMax, 1000, 1e-10);

Static Methods​

compute(matGain, matData, alpha, nIterations, tolerance)​

Compute the MxNE inverse solution.

Parameters:

  • matGain : const Eigen::MatrixXd & Forward gain matrix (n_channels x n_sources).

  • matData : const Eigen::MatrixXd & Measurement data (n_channels x n_times).

  • alpha : double Regularization parameter.

  • nIterations : int Maximum number of IRLS iterations.

  • tolerance : double Convergence tolerance on weight change.

Returns:

  • InvMxneResult — The MxNE result containing the sparse source estimate.

Example​

Used in examples​

ex_inv_api​

Inverse library: minimum-norm estimates, resolution matrices, label time courses, sparse solvers.

src/examples/ex_inv_api/main.cpp, line 240
const MatrixXd gain = whitener * fixedFwd.sol->data * 1e-9;
const MatrixXd measured = whitener * evoked.pick_channels(inverse.noise_cov->names).data.middleCols(170, 40); // 83-148 ms
const double alphaMax = (gain.transpose() * measured).rowwise().norm().maxCoeff();
const InvMxneResult mxne = InvMxne::compute(gain, measured, 0.5 * alphaMax, 1000, 1e-10);
// mne mixed_norm_solver(M, G, 0.5 * alpha_max, n_orient=1, debias=False): sources 8, 30, 37 with 21.37, 1.019, 4.455 nAm
ok &= expect(rank == 360 && near(alphaMax, 14.508623946749108, 1e-4) && mxne.activeVertices == QVector<int>({8, 30, 37}) && near(mxne.stc.data.row(0).norm(), 21.373078745157443, 1e-3) && near(mxne.stc.data.row(2).norm(), 4.455019654645694, 1e-3),
"computeWhitener/InvMxne: whitened rank 360, MxNE picks the 3 V1 sources mne.inverse_sparse finds");

Authors of this file​