Repository: mne-tools/mne-python

Issue:
max_pca_components no reset during preprocessing.ica.ICA._reset
Hi everyone,

I've found that when refitting an ICA object, the property max_pca_components is not set to its original values during reset. This may lead to unexpected behaviour. 

Example:
- Set "max_pca_components=None", so that the object automatically sets it to use all computed PCs through the line "self.max_pca_components = len(picks)" when fitted with a dataset. 
- Now refit the object with a dataset with different number of sensors. As max_pca_components is not reset to None, the object won't be configured to use all the computed PCs (the previous value is kept), producing unexpected behaviour.

Thank you
Marcos

PS: I'm new on github so I'm not sure how this works. Should I fix this issue by myself and request a pull?



Discussion:
sounds like a bug indeed. Can you provide a code snippet to reproduce the
problem using the sample dataset?

thanks

Indeed sounds like a bug. I can take a look later or assist you in doing
your first PR ;)

2015-05-12 21:57 GMT+02:00 Alexandre Gramfort notifications@github.com:

> sounds like a bug indeed. Can you provide a code snippet to reproduce the
> problem using the sample dataset?
> 
> thanks
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/mne-tools/mne-python/issues/2087#issuecomment-101401703
> .

If you could give me a week, I'll pull a fix proposal :-)
Thanks

Let me do it now, this is rather urgent.

Oh, I see... If you haven't stated jet... I'm cloning the project now. I was excited with the idea of doing my first PR xD
If you've fixed it already, no worries. Next time


Resolving patch:
diff --git a/mne/preprocessing/ica.py b/mne/preprocessing/ica.py
--- a/mne/preprocessing/ica.py
+++ b/mne/preprocessing/ica.py
@@ -330,6 +330,9 @@ def _reset(self):
         del self.mixing_matrix_
         del self.n_components_
         del self.n_samples_
+        del self.pca_components_
+        del self.pca_explained_variance_
+        del self.pca_mean_
         if hasattr(self, 'drop_inds_'):
             del self.drop_inds_
 


Test patch:
diff --git a/mne/preprocessing/tests/test_ica.py b/mne/preprocessing/tests/test_ica.py
--- a/mne/preprocessing/tests/test_ica.py
+++ b/mne/preprocessing/tests/test_ica.py
@@ -48,7 +48,8 @@
 def test_ica_full_data_recovery():
     """Test recovery of full data when no source is rejected"""
     # Most basic recovery
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(0.5)
+    raw = io.Raw(raw_fname).crop(0.5, stop, False)
+    raw.preload_data()
     events = read_events(event_name)
     picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
                        eog=False, exclude='bads')[:10]
@@ -105,7 +106,8 @@ def test_ica_full_data_recovery():
 def test_ica_rank_reduction():
     """Test recovery of full data when no source is rejected"""
     # Most basic recovery
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(0.5)
+    raw = io.Raw(raw_fname).crop(0.5, stop, False)
+    raw.preload_data()
     picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
                        eog=False, exclude='bads')[:10]
     n_components = 5
@@ -129,10 +131,39 @@ def test_ica_rank_reduction():
                     rank_before)
 
 
+@requires_sklearn
+def test_ica_reset():
+    """Test ICA resetting"""
+    raw = io.Raw(raw_fname).crop(0.5, stop, False)
+    raw.preload_data()
+    picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
+                       eog=False, exclude='bads')[:10]
+
+    run_time_attrs = (
+        '_pre_whitener',
+        'unmixing_matrix_',
+        'mixing_matrix_',
+        'n_components_',
+        'n_samples_',
+        'pca_components_',
+        'pca_explained_variance_',
+        'pca_mean_'
+    )
+    with warnings.catch_warnings(record=True):
+        ica = ICA(
+            n_components=3, max_pca_components=3, n_pca_components=3,
+            method='fastica', max_iter=1).fit(raw, picks=picks)
+
+    assert_true(all(hasattr(ica, attr) for attr in run_time_attrs))
+    ica._reset()
+    assert_true(not any(hasattr(ica, attr) for attr in run_time_attrs))
+
+
 @requires_sklearn
 def test_ica_core():
     """Test ICA on raw and epochs"""
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(1.5)
+    raw = io.Raw(raw_fname).crop(1.5, stop, False)
+    raw.preload_data()
     picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
                        eog=False, exclude='bads')
     # XXX. The None cases helped revealing bugs but are time consuming.
@@ -234,7 +265,8 @@ def test_ica_additional():
     """Test additional ICA functionality"""
     tempdir = _TempDir()
     stop2 = 500
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(1.5)
+    raw = io.Raw(raw_fname).crop(1.5, stop, False)
+    raw.preload_data()
     picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
                        eog=False, exclude='bads')
     test_cov = read_cov(test_cov_name)
@@ -502,7 +534,8 @@ def test_run_ica():
 def test_ica_reject_buffer():
     """Test ICA data raw buffer rejection"""
     tempdir = _TempDir()
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(1.5)
+    raw = io.Raw(raw_fname).crop(1.5, stop, False)
+    raw.preload_data()
     picks = pick_types(raw.info, meg=True, stim=False, ecg=False,
                        eog=False, exclude='bads')
     ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4)
@@ -521,7 +554,8 @@ def test_ica_reject_buffer():
 @requires_sklearn
 def test_ica_twice():
     """Test running ICA twice"""
-    raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(1.5)
+    raw = io.Raw(raw_fname).crop(1.5, stop, False)
+    raw.preload_data()
     picks = pick_types(raw.info, meg='grad', exclude='bads')
     n_components = 0.9
     max_pca_components = None