Repository: mne-tools/mne-python

Issue:
Blank Assertion Error when running ICA 
![image](https://user-images.githubusercontent.com/60762465/83919476-ab33bd00-a748-11ea-96ba-7f92decdbeb6.png)



Discussion:
Not sure if the output from running the above came out fully in the above so am pasting it again below: 
![image](https://user-images.githubusercontent.com/60762465/83919538-ca324f00-a748-11ea-8351-865fa1f6441f.png)

copying last part of output since for some reason that is not showing up:

![image](https://user-images.githubusercontent.com/60762465/83919603-efbf5880-a748-11ea-9bc4-1c9cbb2f5138.png)

what version of mne are you using?

mne.sys_info()

gives what?

can you share the file?

>

Thanks for your response. I believe it is version .21: This is the output
from what you suggested:

Platform: Linux-4.19.104+-x86_64-with-Ubuntu-18.04-bionic Python: 3.6.9
(default, Apr 18 2020, 01:56:04) [GCC 8.4.0] Executable: /usr/bin/python3
CPU: x86_64: 2 cores Memory: 12.7 GB mne: 0.21.dev0 numpy: 1.18.4
{blas=openblas, lapack=openblas} scipy: 1.4.1 matplotlib: 3.2.1
{backend=module://ipykernel.pylab.backend_inline} sklearn: 0.22.2.post1
numba: 0.48.0 nibabel: 3.0.2 cupy: Not found pandas: 1.0.4 dipy: Not found
mayavi: Not found pyvista: Not found vtk: Not found

On Fri, Jun 5, 2020 at 4:28 PM Alexandre Gramfort <notifications@github.com>
wrote:

> what version of mne are you using?
>
> mne.sys_info()
>
> gives what?
>
> can you share the file?
>
> >
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/mne-tools/mne-python/issues/7868#issuecomment-639789448>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AOPSSYJQAT62DEM67RSYNI3RVFIPTANCNFSM4NVDVN5A>
> .
>


-- 
Bar Lehmann, LICSW, LCSW, BCN
Pronouns (he, him)

Better State of Mind
<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.better-2Dstate-2Dof-2Dmind.com_&d=DwMFaQ&c=U0G0XJAMhEk_X0GAGzCL7Q&r=Cj9RPhU2oMWLltcCQOdyiRyEy1SYAQSCFx-DVb42LRg&m=7ee_WmUyiOPjHobDC0vMixQZZFyB0J_OXL0Iat3v7j4&s=QlhKoajey2QgZZovEHi_mTU9JFQ8pz4mKclopcug2fs&e=>

Find Us On Psychology Today
<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.psychologytoday.com_us_therapists_better-2Dstate-2Dof-2Dmind-2Dwashington-2Ddc_492202-3Fp-3D1&d=DwMFaQ&c=U0G0XJAMhEk_X0GAGzCL7Q&r=Cj9RPhU2oMWLltcCQOdyiRyEy1SYAQSCFx-DVb42LRg&m=7ee_WmUyiOPjHobDC0vMixQZZFyB0J_OXL0Iat3v7j4&s=REG0Ftd30CRbaVXB_m3pzAIqebNFFfiY-_IsjUkpHqc&e=>
(833) 944-0692

you are using a dev version on 0.21

please upgrade to latest stable version or current master version

Thank you for the suggestion - It is now at version mne: 0.20.5, but the
same issue continues to arise.

On Fri, Jun 5, 2020 at 4:40 PM Alexandre Gramfort <notifications@github.com>
wrote:

> you are using a dev version on 0.21
>
> please upgrade to latest stable version or current master version
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/mne-tools/mne-python/issues/7868#issuecomment-639803485>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AOPSSYNCA3VJBY42IZIPLK3RVFJ3RANCNFSM4NVDVN5A>
> .
>


-- 
Bar Lehmann, LICSW, LCSW, BCN
Pronouns (he, him)

Better State of Mind
<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.better-2Dstate-2Dof-2Dmind.com_&d=DwMFaQ&c=U0G0XJAMhEk_X0GAGzCL7Q&r=Cj9RPhU2oMWLltcCQOdyiRyEy1SYAQSCFx-DVb42LRg&m=7ee_WmUyiOPjHobDC0vMixQZZFyB0J_OXL0Iat3v7j4&s=QlhKoajey2QgZZovEHi_mTU9JFQ8pz4mKclopcug2fs&e=>

Find Us On Psychology Today
<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.psychologytoday.com_us_therapists_better-2Dstate-2Dof-2Dmind-2Dwashington-2Ddc_492202-3Fp-3D1&d=DwMFaQ&c=U0G0XJAMhEk_X0GAGzCL7Q&r=Cj9RPhU2oMWLltcCQOdyiRyEy1SYAQSCFx-DVb42LRg&m=7ee_WmUyiOPjHobDC0vMixQZZFyB0J_OXL0Iat3v7j4&s=REG0Ftd30CRbaVXB_m3pzAIqebNFFfiY-_IsjUkpHqc&e=>
(833) 944-0692

then I need to get the script and the data to replicate

dropbox or google drive or whatever works

>

you are setting n_components = 25 while you only have 19
channels. n_components cannot exceed 19.

feel free to close if it solves the problem

>

That fixed it, thank you very much for your swift and on-point assistance! 
Reopening as I think we should catch and raise an informative error
PR welcome


Resolving patch:
diff --git a/mne/preprocessing/ica.py b/mne/preprocessing/ica.py
--- a/mne/preprocessing/ica.py
+++ b/mne/preprocessing/ica.py
@@ -483,11 +483,39 @@ def fit(self, inst, picks=None, start=None, stop=None, decim=None,
         _check_for_unsupported_ica_channels(
             picks, inst.info, allow_ref_meg=self.allow_ref_meg)
 
+        # Actually start fitting
         t_start = time()
+        if self.current_fit != 'unfitted':
+            self._reset()
+
+        logger.info('Fitting ICA to data using %i channels '
+                    '(please be patient, this may take a while)' % len(picks))
+
+        if self.max_pca_components is None:
+            self.max_pca_components = len(picks)
+            logger.info('Inferring max_pca_components from picks')
+        elif self.max_pca_components > len(picks):
+            raise ValueError(
+                f'ica.max_pca_components ({self.max_pca_components}) cannot '
+                f'be greater than len(picks) ({len(picks)})')
+        # n_components could be float 0 < x <= 1, but that's okay here
+        if self.n_components is not None and self.n_components > len(picks):
+            raise ValueError(
+                f'ica.n_components ({self.n_components}) cannot '
+                f'be greater than len(picks) ({len(picks)})')
+
+        # filter out all the channels the raw wouldn't have initialized
+        self.info = pick_info(inst.info, picks)
+
+        if self.info['comps']:
+            self.info['comps'] = []
+        self.ch_names = self.info['ch_names']
+
         if isinstance(inst, BaseRaw):
             self._fit_raw(inst, picks, start, stop, decim, reject, flat,
                           tstep, reject_by_annotation, verbose)
-        elif isinstance(inst, BaseEpochs):
+        else:
+            assert isinstance(inst, BaseEpochs)
             self._fit_epochs(inst, picks, decim, verbose)
 
         # sort ICA components by explained variance
@@ -500,37 +528,16 @@ def fit(self, inst, picks=None, start=None, stop=None, decim=None,
 
     def _reset(self):
         """Aux method."""
-        del self.pre_whitener_
-        del self.unmixing_matrix_
-        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_
-        del self.n_iter_
-        if hasattr(self, 'drop_inds_'):
-            del self.drop_inds_
-        if hasattr(self, 'reject_'):
-            del self.reject_
+        for key in ('pre_whitener_', 'unmixing_matrix_', 'mixing_matrix_',
+                    'n_components_', 'n_samples_', 'pca_components_',
+                    'pca_explained_variance_', 'pca_mean_', 'n_iter_',
+                    'drop_inds_', 'reject_'):
+            if hasattr(self, key):
+                delattr(self, key)
 
     def _fit_raw(self, raw, picks, start, stop, decim, reject, flat, tstep,
                  reject_by_annotation, verbose):
         """Aux method."""
-        if self.current_fit != 'unfitted':
-            self._reset()
-
-        logger.info('Fitting ICA to data using %i channels '
-                    '(please be patient, this may take a while)' % len(picks))
-
-        if self.max_pca_components is None:
-            self.max_pca_components = len(picks)
-            logger.info('Inferring max_pca_components from picks')
-
-        self.info = pick_info(raw.info, picks)
-        if self.info['comps']:
-            self.info['comps'] = []
-        self.ch_names = self.info['ch_names']
         start, stop = _check_start_stop(raw, start, stop)
 
         reject_by_annotation = 'omit' if reject_by_annotation else None
@@ -558,28 +565,11 @@ def _fit_raw(self, raw, picks, start, stop, decim, reject, flat, tstep,
 
     def _fit_epochs(self, epochs, picks, decim, verbose):
         """Aux method."""
-        if self.current_fit != 'unfitted':
-            self._reset()
-
         if epochs.events.size == 0:
             raise RuntimeError('Tried to fit ICA with epochs, but none were '
                                'found: epochs.events is "{}".'
                                .format(epochs.events))
 
-        logger.info('Fitting ICA to data using %i channels '
-                    '(please be patient, this may take a while)' % len(picks))
-
-        # filter out all the channels the raw wouldn't have initialized
-        self.info = pick_info(epochs.info, picks)
-
-        if self.info['comps']:
-            self.info['comps'] = []
-        self.ch_names = self.info['ch_names']
-
-        if self.max_pca_components is None:
-            self.max_pca_components = len(picks)
-            logger.info('Inferring max_pca_components from picks')
-
         # this should be a copy (picks a list of int)
         data = epochs.get_data()[:, picks]
         # this will be a view
@@ -1018,7 +1008,7 @@ def score_sources(self, inst, target=None, score_func='pearsonr',
                                         reject_by_annotation)
 
             if sources.shape[-1] != target.shape[-1]:
-                raise ValueError('Sources and target do not have the same'
+                raise ValueError('Sources and target do not have the same '
                                  'number of time slices.')
             # auto target selection
             if isinstance(inst, BaseRaw):


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
@@ -122,7 +122,8 @@ def test_ica_full_data_recovery(method):
             else:
                 diff = np.abs(evoked.data[:n_channels] - data2)
                 assert (np.max(diff) > 1e-14)
-    pytest.raises(ValueError, ICA, method='pizza-decomposision')
+    with pytest.raises(ValueError, match='Invalid value'):
+        ICA(method='pizza-decomposision')
 
 
 @pytest.mark.parametrize("method", ["fastica", "picard"])
@@ -264,8 +265,10 @@ def test_ica_core(method):
                               picks_, methods)
 
     # # test init catchers
-    pytest.raises(ValueError, ICA, n_components=3, max_pca_components=2)
-    pytest.raises(ValueError, ICA, n_components=2.3, max_pca_components=2)
+    with pytest.raises(ValueError, match='must be smaller than max_pca'):
+        ICA(n_components=3, max_pca_components=2)
+    with pytest.raises(ValueError, match='explained variance needs values'):
+        ICA(n_components=2.3, max_pca_components=3)
 
     # test essential core functionality
     for n_cov, n_comp, max_n, pcks, method in iter_ica_params:
@@ -273,13 +276,16 @@ def test_ica_core(method):
         ica = ICA(noise_cov=n_cov, n_components=n_comp,
                   max_pca_components=max_n, n_pca_components=max_n,
                   random_state=0, method=method, max_iter=1)
-        pytest.raises(ValueError, ica.__contains__, 'mag')
+        with pytest.raises(ValueError, match='Cannot check for channels of t'):
+            'meg' in ica
 
         print(ica)  # to test repr
 
         # test fit checker
-        pytest.raises(RuntimeError, ica.get_sources, raw)
-        pytest.raises(RuntimeError, ica.get_sources, epochs)
+        with pytest.raises(RuntimeError, match='No fit available'):
+            ica.get_sources(raw)
+        with pytest.raises(RuntimeError, match='No fit available'):
+            ica.get_sources(epochs)
 
         # Test error upon empty epochs fitting
         with pytest.raises(RuntimeError, match='none were found'):
@@ -336,14 +342,14 @@ def test_ica_core(method):
         sources = ica.get_sources(epochs).get_data()
         assert (sources.shape[1] == ica.n_components_)
 
-        pytest.raises(ValueError, ica.score_sources, epochs,
-                      target=np.arange(1))
+        with pytest.raises(ValueError, match='target do not have the same nu'):
+            ica.score_sources(epochs, target=np.arange(1))
 
         # test preload filter
         epochs3 = epochs.copy()
         epochs3.preload = False
-        pytest.raises(RuntimeError, ica.apply, epochs3,
-                      include=[1, 2])
+        with pytest.raises(RuntimeError, match='requires epochs data to be l'):
+            ica.apply(epochs3, include=[1, 2])
 
     # test for bug with whitener updating
     _pre_whitener = ica.pre_whitener_.copy()
@@ -353,12 +359,26 @@ def test_ica_core(method):
 
     # test expl. var threshold leading to empty sel
     ica.n_components = 0.1
-    pytest.raises(RuntimeError, ica.fit, epochs)
+    with pytest.raises(RuntimeError, match='One PCA component captures most'):
+        ica.fit(epochs)
 
     offender = 1, 2, 3,
-    pytest.raises(ValueError, ica.get_sources, offender)
-    pytest.raises(TypeError, ica.fit, offender)
-    pytest.raises(TypeError, ica.apply, offender)
+    with pytest.raises(ValueError, match='Data input must be of Raw'):
+        ica.get_sources(offender)
+    with pytest.raises(TypeError, match='must be an instance of'):
+        ica.fit(offender)
+    with pytest.raises(TypeError, match='must be an instance of'):
+        ica.apply(offender)
+
+    # gh-7868
+    ica.max_pca_components = 3
+    ica.n_components = 0.99
+    with pytest.raises(ValueError, match='pca_components.*cannot be greater'):
+        ica.fit(epochs, picks=[0, 1])
+    ica.max_pca_components = None
+    ica.n_components = 3
+    with pytest.raises(ValueError, match='n_components.*cannot be greater'):
+        ica.fit(epochs, picks=[0, 1])
 
 
 @requires_sklearn