Skip to main content

InvCMNE

Namespace: INVLIB  ·  Library: Inverse Library

#include <inv/inv_cmne.h>

class INVLIB::InvCMNE

Contextual Minimum Norm Estimate (CMNE) inverse solver.

Implements the algorithm from: Dinh et al. "Contextual Minimum-Norm Estimates (CMNE): A Deep Learning Method for Source Estimation in Neuroimaging", 2021.

CMNE inverse solver

src/examples/ex_inv_api/main.cpp
// Contextual MNE: dSPM with a fixed-orientation kernel, then rectified and z-scored per source. Without an
// ONNX LSTM model the result is the paper's control estimate.
InvCMNESettings cmneSettings;
cmneSettings.lambda2 = lambda2;
cmneSettings.lookBack = 20;
const MatrixXd fixedGain = fixedFwd.sol->data;
const MatrixXd sourceCov = MatrixXd::Identity(fixedGain.cols(), fixedGain.cols());
const InvCMNEResult cmne = InvCMNE::compute(goodData, fixedGain, inverse.noise_cov->data, sourceCov, cmneSettings);

Static Methods​

compute(matEvoked, matGain, matNoiseCov, matSrcCov, settings)​

Compute CMNE inverse solution.

Parameters:

  • matEvoked : const Eigen::MatrixXd & Evoked data (n_channels x n_times).

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

  • matNoiseCov : const Eigen::MatrixXd & Noise covariance (n_channels x n_channels).

  • matSrcCov : const Eigen::MatrixXd & Source covariance (n_sources x n_sources, diagonal).

  • settings : const InvCMNESettings & CMNE settings.

Returns:


applyCmne(matDspmData, onnxModelPath, sensing, prediction, cmne)​

Contextual estimate of Eqs.

9-13, as cmne.apply_cmne with normalised weights.

The model must be exported by cmne.export_onnx: look-back, source count and rectification are read from its cmne_config metadata.

Parameters:

  • matDspmData : const Eigen::MatrixXd & Signed dSPM estimate (n_sources x n_times).

  • onnxModelPath : const QString & Path to the ONNX model.

  • sensing : Eigen::MatrixXd & q_t (Eq. 9).

  • prediction : Eigen::MatrixXd & LSTM prediction (q_t for the first k samples).

  • cmne : Eigen::MatrixXd & Contextual estimate b_t.

Returns:

  • bool — False if the model cannot be loaded, does not fit the data, or there are no more than k samples.

controlEstimate(matDspmData, lookBack)​

Control estimate of the paper (cmne.control_estimate): q_t times the mean of q over the previous lookBack samples, without an LSTM.

Parameters:

  • matDspmData : const Eigen::MatrixXd & Signed dSPM estimate (n_sources x n_times).

  • lookBack : int Window length k.

Returns:

  • Eigen::MatrixXd — Control estimate (n_sources x n_times).

zScoreRectify(matStcData)​

Rectify and z-score each source over time (Eq.

9).

Parameters:

  • matStcData : const Eigen::MatrixXd & Source data (n_sources x n_times).

Returns:

  • Eigen::MatrixXd — |x| standardised per row; constant rows are centred only.

trainLstm(fwdPath, covPath, epochsPath, outOnnxPath, settings, gtStcPrefix, hiddenSize, numLayers, trainEpochs, learningRate, batchSize, finetuneOnnxPath, pythonExe)​

Train the CMNE LSTM model by invoking the Python training script.

This is a convenience wrapper that calls scripts/ml/training/train_cmne_lstm.py via PythonRunner. The heavy lifting (PyTorch LSTM training + ONNX export) happens in Python; C++ only launches the process and streams its output.

Parameters:

  • fwdPath : const QString & Path to forward solution FIFF file.

  • covPath : const QString & Path to noise covariance FIFF file.

  • epochsPath : const QString & Path to epochs FIFF file.

  • outOnnxPath : const QString & Desired output path for the ONNX model.

  • settings : const InvCMNESettings & CMNE settings (look-back, method, SNR are forwarded).

  • gtStcPrefix : const QString & Ground-truth STC prefix (optional; empty = simulation mode).

  • hiddenSize : int LSTM hidden dimension (default 256).

  • numLayers : int LSTM layers (default 1).

  • trainEpochs : int Number of training epochs (default 50).

  • learningRate : double Learning rate (default 1e-3).

  • batchSize : int Batch size (default 64).

  • finetuneOnnxPath : const QString & Existing ONNX model to fine-tune from (optional).

  • pythonExe : const QString & Python interpreter (default "python3").

Returns:


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 275
cmneSettings.lookBack = 20;
const MatrixXd fixedGain = fixedFwd.sol->data;
const MatrixXd sourceCov = MatrixXd::Identity(fixedGain.cols(), fixedGain.cols());
const InvCMNEResult cmne = InvCMNE::compute(goodData, fixedGain, inverse.noise_cov->data, sourceCov, cmneSettings);
// Every row of the dSPM kernel maps sensor noise with the noise covariance to unit variance.
const MatrixXd& kDspm = cmne.matKernelDspm;
const VectorXd unitNoise = (kDspm * inverse.noise_cov->data * kDspm.transpose()).diagonal();
ok &= expect(kDspm.rows() == 70 && (unitNoise.array() - 1.0).abs().maxCoeff() < 1e-6 && cmne.stcCmne.data.rows() == 70 && cmne.stcCmne.data.cols() == 421,
"InvCMNE: dSPM kernel has unit noise variance per source, CMNE estimate for all 421 samples");

Authors of this file​