Skip to content

Coherent Maximum Entropy on the Mean

Solver ID: cMEM

Usage

from invert import Solver

# fwd = ...    (mne.Forward object)
# evoked = ... (mne.Evoked object)

solver = Solver("cMEM")
solver.make_inverse_operator(fwd)
stc = solver.apply_inverse_operator(evoked)
stc.plot()

Overview

Maximum-entropy-on-the-mean approach using graphical models and parcel-wise optimization (data-driven parcellation) to estimate source activity.

References

  1. Amblard, C., Lapalme, E., & Bhatt, P. (2004). Biomagnetic source detection by maximum entropy and graphical models. IEEE Transactions on Biomedical Engineering, 51(3), 427–442.

API Reference

Bases: BaseSolver

Coherent Maximum Entropy on the Mean (cMEM) source localization solver.

Parameters:

Name Type Description Default
name str

Name of the solver.

'cMEM'
num_parcels int

Number of parcels for data-driven parcellation.

200
max_iter int

Maximum optimization iterations per time point.

100
batch_size int

Batch size for time-point processing.

100
References

Amblard, C., Lapalme, E., & Bhatt, P. (2004). Biomagnetic source detection by maximum entropy and graphical models. IEEE Transactions on Biomedical Engineering, 51(3), 427-442.

Source code in invert/solvers/bayesian/cmem.py
class SolverCMEM(BaseSolver):
    """Coherent Maximum Entropy on the Mean (cMEM) source localization solver.

    Parameters
    ----------
    name : str
        Name of the solver.
    num_parcels : int
        Number of parcels for data-driven parcellation.
    max_iter : int
        Maximum optimization iterations per time point.
    batch_size : int
        Batch size for time-point processing.

    References
    ----------
    Amblard, C., Lapalme, E., & Bhatt, P. (2004). Biomagnetic source
    detection by maximum entropy and graphical models. IEEE
    Transactions on Biomedical Engineering, 51(3), 427-442.
    """

    meta = SolverMeta(
        acronym="cMEM",
        full_name="Coherent Maximum Entropy on the Mean",
        category="Bayesian",
        description=(
            "Maximum-entropy-on-the-mean approach using graphical models and "
            "parcel-wise optimization (data-driven parcellation) to estimate "
            "source activity."
        ),
        references=[
            "Amblard, C., Lapalme, E., & Bhatt, P. (2004). Biomagnetic source detection by maximum entropy and graphical models. IEEE Transactions on Biomedical Engineering, 51(3), 427–442.",
        ],
    )

    def __init__(
        self,
        name="cMEM",
        num_parcels=200,
        max_iter=100,
        batch_size=100,
        **kwargs,
    ):
        self.name = name
        self.num_parcels = num_parcels
        self.max_iter = max_iter
        self.batch_size = batch_size
        return super().__init__(**kwargs)

    def make_inverse_operator(
        self,
        forward,
        mne_obj,
        *args,
        alpha="auto",
        adjacency=None,
        positions=None,
        **kwargs,
    ):
        """Calculate inverse operator.

        Parameters
        ----------
        forward : mne.Forward
            The mne-python Forward model instance.
        mne_obj : [mne.Evoked, mne.Epochs, mne.io.Raw]
            The MNE data object.
        alpha : float
            The regularization parameter.
        adjacency : numpy.ndarray, optional
            Source adjacency matrix (n, n).
        positions : numpy.ndarray, optional
            Source positions (n, 3).

        Return
        ------
        self : object returns itself for convenience
        """
        super().make_inverse_operator(forward, *args, alpha=alpha, **kwargs)
        data = self.unpack_data_obj(mne_obj)

        J, parcels = _cmem(
            data,
            self.leadfield,
            A=adjacency,
            P=positions,
            num_parcels=self.num_parcels,
            max_iter=self.max_iter,
            batch_size=self.batch_size,
        )

        self.parcels = parcels
        # Store source estimate directly; wrap in InverseOperator for API compat
        self.inverse_operators = [
            InverseOperator(J, self.name),
        ]
        return self

    def apply_inverse_operator(self, mne_obj):
        """Apply the cMEM inverse operator.

        Since cMEM computes the full source time series during
        ``make_inverse_operator``, applying the operator re-runs the
        algorithm on the new data.

        Parameters
        ----------
        mne_obj : [mne.Evoked, mne.Epochs, mne.io.Raw]
            The MNE data object.

        Return
        ------
        stc : mne.SourceEstimate
            The source estimate.
        """
        data = self.unpack_data_obj(mne_obj)

        J, self.parcels = _cmem(
            data,
            self.leadfield,
            num_parcels=self.num_parcels,
            max_iter=self.max_iter,
            batch_size=self.batch_size,
        )

        stc = self.source_to_object(J)
        return stc

__init__

__init__(
    name="cMEM",
    num_parcels=200,
    max_iter=100,
    batch_size=100,
    **kwargs,
)
Source code in invert/solvers/bayesian/cmem.py
def __init__(
    self,
    name="cMEM",
    num_parcels=200,
    max_iter=100,
    batch_size=100,
    **kwargs,
):
    self.name = name
    self.num_parcels = num_parcels
    self.max_iter = max_iter
    self.batch_size = batch_size
    return super().__init__(**kwargs)

make_inverse_operator

make_inverse_operator(
    forward,
    mne_obj,
    *args,
    alpha="auto",
    adjacency=None,
    positions=None,
    **kwargs,
)

Calculate inverse operator.

Parameters:

Name Type Description Default
forward Forward

The mne-python Forward model instance.

required
mne_obj [Evoked, Epochs, Raw]

The MNE data object.

required
alpha float

The regularization parameter.

'auto'
adjacency ndarray

Source adjacency matrix (n, n).

None
positions ndarray

Source positions (n, 3).

None
Return

self : object returns itself for convenience

Source code in invert/solvers/bayesian/cmem.py
def make_inverse_operator(
    self,
    forward,
    mne_obj,
    *args,
    alpha="auto",
    adjacency=None,
    positions=None,
    **kwargs,
):
    """Calculate inverse operator.

    Parameters
    ----------
    forward : mne.Forward
        The mne-python Forward model instance.
    mne_obj : [mne.Evoked, mne.Epochs, mne.io.Raw]
        The MNE data object.
    alpha : float
        The regularization parameter.
    adjacency : numpy.ndarray, optional
        Source adjacency matrix (n, n).
    positions : numpy.ndarray, optional
        Source positions (n, 3).

    Return
    ------
    self : object returns itself for convenience
    """
    super().make_inverse_operator(forward, *args, alpha=alpha, **kwargs)
    data = self.unpack_data_obj(mne_obj)

    J, parcels = _cmem(
        data,
        self.leadfield,
        A=adjacency,
        P=positions,
        num_parcels=self.num_parcels,
        max_iter=self.max_iter,
        batch_size=self.batch_size,
    )

    self.parcels = parcels
    # Store source estimate directly; wrap in InverseOperator for API compat
    self.inverse_operators = [
        InverseOperator(J, self.name),
    ]
    return self

apply_inverse_operator

apply_inverse_operator(mne_obj)

Apply the cMEM inverse operator.

Since cMEM computes the full source time series during make_inverse_operator, applying the operator re-runs the algorithm on the new data.

Parameters:

Name Type Description Default
mne_obj [Evoked, Epochs, Raw]

The MNE data object.

required
Return

stc : mne.SourceEstimate The source estimate.

Source code in invert/solvers/bayesian/cmem.py
def apply_inverse_operator(self, mne_obj):
    """Apply the cMEM inverse operator.

    Since cMEM computes the full source time series during
    ``make_inverse_operator``, applying the operator re-runs the
    algorithm on the new data.

    Parameters
    ----------
    mne_obj : [mne.Evoked, mne.Epochs, mne.io.Raw]
        The MNE data object.

    Return
    ------
    stc : mne.SourceEstimate
        The source estimate.
    """
    data = self.unpack_data_obj(mne_obj)

    J, self.parcels = _cmem(
        data,
        self.leadfield,
        num_parcels=self.num_parcels,
        max_iter=self.max_iter,
        batch_size=self.batch_size,
    )

    stc = self.source_to_object(J)
    return stc