mne-tools / mne-python

MNE: Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python
https://mne.tools
BSD 3-Clause "New" or "Revised" License
2.72k stars 1.32k forks source link

Consider adding (correct) proportion of variance explained by ICA components to Report #12157

Open hoechenberger opened 1 year ago

hoechenberger commented 1 year ago

We removed it because the calculation was incorrect. The correct approach may be too time-consuming, though

See https://github.com/mne-tools/mne-python/pull/12156#issuecomment-1787746407 for discussion

larsoner commented 1 year ago

But thinking about it even more... in principle I think this would make it quite fast and also work:

  1. Compute the empirical covariance of inst (raw, epochs, evoked) -- should be fast enough (and not even require preloading!)
  2. Apply ICA to the computed covariance rather than inst -- should be very fast, I think you "just" have to apply the ICA spatial operator to the left and (transposed to the) right of the covariance
  3. Use the reduction in covariance power to compute the reduction in variance of the signal (I think this is doable mathematically but I should double-check)

You lose some accuracy with this approach but assuming that's acceptable it would make this usable. We could enable it adding a new mode="cov" | "individual" | "joint" (default) where mode="cov" will estimate var exp jointly across all components applied at once but using the possibly-memory-saving cov method, "individual" uses the cov-based method and operates on individual components, and "joint" is current behavior (actually apply to the instance).

This would also take care of an old comment by @agramfort where he worried about memory usage with the current method as inst.copy() must be done under the hood.

hoechenberger commented 1 year ago

You lose some accuracy with this approach but assuming that's acceptable it would make this usable.

A rough estimate is fair enough for me. It just really helps when you look at an ICA component and can immediately see, "oh, this one explains quite a large amount of variance!" – or "well, this one doesn't seem to be too important, let's not waste my time trying to figure out whether it's brain or an artifact"

hoechenberger commented 1 year ago

We could still keep the existing algorithm and add a kwarg to allow selection of the method used for variance explained estimation

def get_explained_variance_ratio(
    ...
    method: Literal["eeglab", "cov"] = "cov"
):
    ...
hoechenberger commented 1 year ago

We could still keep the existing algorithm and add a kwarg to allow selection of the method

Sorry, you already proposed that, I missed that on my first read!