Repository: mne-tools/mne-python

Issue:
MNE python not passing unit tests
I'm not certain if I should keep bringing issues like this up, but I just downloaded mne-python:

```
$ git log
commit 1742decca63dd6d1bb6517a7b3ce465aebf1943f
Author: Eric Larson <larson.eric.d@gmail.com>
Date:   Sat Sep 23 04:16:35 2017 -0400

    FIX: Add numbers for dipoles (#4596)
```
and failed the following test:

```
==============FAILURES===============
______________ test_inverse_coef___________

    @requires_version('sklearn', '0.17')
    def test_inverse_coef():
        """Test inverse coefficients computation."""
        from sklearn.linear_model import Ridge
    
        rng = np.random.RandomState(0)
        tmin, tmax = 0., 10.
        n_feats, n_targets, n_samples = 64, 2, 10000
        n_delays = int((tmax - tmin) + 1)
    
        def make_data(n_feats, n_targets, n_samples, tmin, tmax):
            X = rng.randn(n_samples, n_feats)
            w = rng.randn(int((tmax - tmin) + 1) * n_feats, n_targets)
            # Delay inputs
            X_del = np.concatenate(
                _delay_time_series(X, tmin, tmax, 1.).transpose(2, 0, 1), axis=1)
            y = np.dot(X_del, w)
            return X, y
    
        # Check coefficient dims, for all estimator types
        X, y = make_data(n_feats, n_targets, n_samples, tmin, tmax)
        tdr = TimeDelayingRidge(tmin, tmax, 1., 0.1, 'laplacian')
        for estimator in (0., 0.01, Ridge(alpha=0.), tdr):
            rf = ReceptiveField(tmin, tmax, 1., estimator=estimator,
                                patterns=True)
            rf.fit(X, y)
            inv_rf = ReceptiveField(tmin, tmax, 1., estimator=estimator,
                                    patterns=True)
            inv_rf.fit(y, X)
    
            assert_array_equal(rf.coef_.shape, rf.patterns_.shape,
                               (n_targets, n_feats, n_delays))
            assert_array_equal(inv_rf.coef_.shape, inv_rf.patterns_.shape,
                               (n_feats, n_targets, n_delays))
    
            # we should have np.dot(patterns.T,coef) ~ np.eye(n)
            c0 = rf.coef_.reshape(n_targets, n_feats * n_delays)
            c1 = rf.patterns_.reshape(n_targets, n_feats * n_delays)
            assert_allclose(np.dot(c0, c1.T), np.eye(c0.shape[0]), atol=0.1)
    
        # Check that warnings are issued when no regularization is applied
        n_feats, n_targets, n_samples = 5, 60, 50
        X, y = make_data(n_feats, n_targets, n_samples, tmin, tmax)
        for estimator in (0., Ridge(alpha=0.)):
            rf = ReceptiveField(tmin, tmax, 1., estimator=estimator, patterns=True)
            with warnings.catch_warnings(record=True) as w:
                rf.fit(y, X)
                assert_equal(len(w), 1)
>               assert_true(str(w[0].message).startswith('scipy.linalg.solve'))

Ridge      = <class 'sklearn.linear_model.ridge.Ridge'>
X          = array([[-0.80024705, -1.89239835, -0.68816083, -0.95247633, -0.192552  ],
    ...78],
       [ 0.54641967, -0.01107107,  0.36206803, -1.1164831 ,  0.84303393]])
c0         = array([[ 1.97758378, -0.29175964,  0.5583115 , ..., -0.27838071,
        -0.94... 0.4569734 ,  2.05897168, ..., -0.21312892,
         1.290712  ,  0.30943939]])
c1         = array([[  3.23013382e-03,  -5.64962896e-04,   1.12283777e-03, ...,
         -5...91205e-03, ...,
         -4.76747798e-04,   1.62203875e-03,   6.01728672e-04]])
estimator  = 0.0
inv_rf     = <ReceptiveField  |  tmin, tmax : (0.000, 10.000), estimator : <class 'mne.deco...g_ridge.TimeDelayingRidge'>, features : [feature_0, ..., feature_1], fit: True>
make_data  = <function make_data at 0x7f2cb0f66488>
n_delays   = 11
n_feats    = 5
n_samples  = 50
n_targets  = 60
rf         = <ReceptiveField  |  tmin, tmax : (0.000, 10.000), estimator : <type 'float'>, features : [feature_0, ..., feature_59], fit: True>
rng        = <mtrand.RandomState object at 0x7f2cb117a7d0>
tdr        = TimeDelayingRidge(alpha=0.1, fit_intercept=True, reg_type='laplacian',
         sfreq=1.0, tmax=10.0, tmin=0.0)
tmax       = 10.0
tmin       = 0.0
w          = [<warnings.WarningMessage object at 0x7f2cb10ea1d0>]
y          = array([[ -0.30096682,   0.49934696,  -1.05234833, ...,  -3.42443654,
         ...4619171,   8.60248944, ...,  -3.6311968 ,
         10.11414418,  -0.36224599]])

mne/decoding/tests/test_receptive_field.py:521: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <nose.tools.trivial.Dummy testMethod=nop>, expr = False, msg = 'False is not true'

    def assertTrue(self, expr, msg=None):
        """Check that the expression is true."""
        if not expr:
            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
>           raise self.failureException(msg)
E           AssertionError: False is not true

expr       = False
msg        = 'False is not true'
self       = <nose.tools.trivial.Dummy testMethod=nop>

/usr/lib/python2.7/unittest/case.py:422: AssertionError

```
My UnitTest results can be summarized as follows:
`Summary:  1 failed, 654 passed, 60 skipped, 2 deselected, 155 warnings in 481.31 seconds`

Here is my sys_info:

```
>>> mne.sys_info()
Platform:      Linux-4.4.0-93-generic-x86_64-with-Ubuntu-16.04-xenial
Python:        2.7.12 (default, Nov 19 2016, 06:48:10)  [GCC 5.4.0 20160609]
Executable:    /usr/bin/python
CPU:           x86_64: 12 cores
Memory:        62.8 GB

mne:           0.15.dev0
numpy:         1.12.0 {lapack=openblas, blas=openblas}
scipy:         0.17.1
matplotlib:    2.0.0b3+1814.g3cb79ed

sklearn:       0.18
nibabel:       2.1.0
mayavi:        Not found
pycuda:        2016.1.2
skcuda:        0.5.2
pandas:        0.18.1
>>> 
```

I seem to fail the `make test` fairly regularly when I download the current version. Is my setup unusual?  Is there some reasonable/minor change I should make to make my system more standard? Is it helpful for me to send these reports? 


Discussion:
it passes for me

In [2]: mne.sys_info()
Platform:      Darwin-16.7.0-x86_64-i386-64bit
Python:        3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017,
13:14:59)  [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]
Executable:    /Users/alex/anaconda/envs/mne/bin/python
CPU:           i386: 8 cores
Memory:        16.0 GB

mne:           0.15.dev0
numpy:         1.13.1 {blas=mkl_intel_lp64, lapack=mkl_intel_lp64}
scipy:         0.19.1
matplotlib:    2.0.2

sklearn:       0.19.0
nibabel:       2.1.0
mayavi:        4.5.0
pycuda:        Not found
skcuda:        Not found
pandas:        0.20.3

can you try with mkl numpy? is it a numerical diff due to openblas?

On OSX I could not do the exact environment due to conflicts:
```
conda create -n py27openblas python=2.7 numpy=1.12.0 scipy=0.17.1 scikit-learn=0.18 nomkl openblas
```
But when using SciPy 0.19 I can't replicate. I'll give Linux (where I probably can replicate the same env) tomorrow.
I also can't make this environment in Linux using Anaconda due to unsatisfiable dependencies. I must use `numpy=1.11` to get it to build. I can get one with this config:
```
mne:           0.15.dev0
numpy:         1.11.2 {lapack=openblas, blas=openblas}
scipy:         0.17.1
matplotlib:    2.0.2

sklearn:       0.18.1
```
But it passes.

I was finally able to reproduce it by using my system's Python (which I noticed you were using), PR forthcoming.

Resolving patch:
diff --git a/mne/evoked.py b/mne/evoked.py
--- a/mne/evoked.py
+++ b/mne/evoked.py
@@ -291,13 +291,14 @@ def shift_time(self, tshift, relative=True):
     def plot(self, picks=None, exclude='bads', unit=True, show=True, ylim=None,
              xlim='tight', proj=False, hline=None, units=None, scalings=None,
              titles=None, axes=None, gfp=False, window_title=None,
-             spatial_colors=False, zorder='unsorted', selectable=True):
+             spatial_colors=False, zorder='unsorted', selectable=True,
+             verbose=None):
         return plot_evoked(
             self, picks=picks, exclude=exclude, unit=unit, show=show,
             ylim=ylim, proj=proj, xlim=xlim, hline=hline, units=units,
             scalings=scalings, titles=titles, axes=axes, gfp=gfp,
             window_title=window_title, spatial_colors=spatial_colors,
-            zorder=zorder, selectable=selectable)
+            zorder=zorder, selectable=selectable, verbose=verbose)
 
     @copy_function_doc_to_method_doc(plot_evoked_image)
     def plot_image(self, picks=None, exclude='bads', unit=True, show=True,
diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py
--- a/mne/viz/evoked.py
+++ b/mne/viz/evoked.py
@@ -24,7 +24,7 @@
 from .utils import (_draw_proj_checkbox, tight_layout, _check_delayed_ssp,
                     plt_show, _process_times, DraggableColorbar, _setup_cmap,
                     _setup_vmin_vmax, _grad_pair_pick_and_name)
-from ..utils import logger, _clean_names, warn, _pl
+from ..utils import logger, _clean_names, warn, _pl, verbose
 from ..io.pick import pick_info, _DATA_CH_TYPES_SPLIT
 from .topo import _plot_evoked_topo
 from .utils import COLORS, _setup_ax_spines
@@ -492,11 +492,12 @@ def _plot_image(data, ax, this_type, picks, cmap, unit, units, scalings, times,
     ax.set_xlabel('time (ms)')
 
 
+@verbose
 def plot_evoked(evoked, picks=None, exclude='bads', unit=True, show=True,
                 ylim=None, xlim='tight', proj=False, hline=None, units=None,
                 scalings=None, titles=None, axes=None, gfp=False,
                 window_title=None, spatial_colors=False, zorder='unsorted',
-                selectable=True):
+                selectable=True, verbose=None):
     """Plot evoked data using butteryfly plots.
 
     Left click to a line shows the channel name. Selecting an area by clicking
@@ -575,6 +576,10 @@ def plot_evoked(evoked, picks=None, exclude='bads', unit=True, show=True,
 
         .. versionadded:: 0.13.0
 
+    verbose : bool, str, int, or None
+        If not None, override default verbose level (see :func:`mne.verbose`
+        and :ref:`Logging documentation <tut_logging>` for more).
+
     Returns
     -------
     fig : instance of matplotlib.figure.Figure


Test patch:
diff --git a/mne/decoding/tests/test_receptive_field.py b/mne/decoding/tests/test_receptive_field.py
--- a/mne/decoding/tests/test_receptive_field.py
+++ b/mne/decoding/tests/test_receptive_field.py
@@ -518,7 +518,9 @@ def make_data(n_feats, n_targets, n_samples, tmin, tmax):
         with warnings.catch_warnings(record=True) as w:
             rf.fit(y, X)
             assert_equal(len(w), 1)
-            assert_true(str(w[0].message).startswith('scipy.linalg.solve'))
+            assert_true(any(x in str(w[0].message).lower()
+                            for x in ('singular', 'scipy.linalg.solve')),
+                        msg=str(w[0].message))
 
 
 run_tests_if_main()
diff --git a/mne/forward/tests/test_field_interpolation.py b/mne/forward/tests/test_field_interpolation.py
--- a/mne/forward/tests/test_field_interpolation.py
+++ b/mne/forward/tests/test_field_interpolation.py
@@ -218,7 +218,7 @@ def test_as_meg_type_evoked():
     virt_evoked = evoked.copy().pick_channels(ch_names=ch_names[:10:1])
     virt_evoked.info.normalize_proj()
     virt_evoked = virt_evoked.as_type('mag')
-    assert_true(all('_virtual' in ch for ch in virt_evoked.info['ch_names']))
+    assert_true(all('_virt' in ch for ch in virt_evoked.info['ch_names']))
 
     # pick from and to channels
     evoked_from = evoked.copy().pick_channels(ch_names=ch_names[2:10:3])
@@ -243,4 +243,5 @@ def test_as_meg_type_evoked():
     data2 = evoked.as_type('grad').data.ravel()
     assert_true(np.corrcoef(data1, data2)[0, 1] > 0.95)
 
+
 run_tests_if_main()
diff --git a/mne/tests/test_import_nesting.py b/mne/tests/test_import_nesting.py
--- a/mne/tests/test_import_nesting.py
+++ b/mne/tests/test_import_nesting.py
@@ -18,7 +18,8 @@
                            'misc', 'sparse', 'version'])
 scipy_submodules = set(x.split('.')[1] for x in sys.modules.keys()
                        if x.startswith('scipy.') and '__' not in x and
-                       not x.split('.')[1].startswith('_'))
+                       not x.split('.')[1].startswith('_')
+                       and sys.modules[x] is not None)
 bad = scipy_submodules - ok_scipy_submodules
 if len(bad) > 0:
     out.append('Found un-nested scipy submodules: %s' % list(bad))
@@ -53,4 +54,5 @@ def test_module_nesting():
     if proc.returncode:
         raise AssertionError(stdout)
 
+
 run_tests_if_main()
diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py
--- a/mne/viz/tests/test_evoked.py
+++ b/mne/viz/tests/test_evoked.py
@@ -12,14 +12,14 @@
 import warnings
 
 import numpy as np
-from numpy.testing import assert_raises, assert_equal
+from numpy.testing import assert_raises
 from nose.tools import assert_true
 import pytest
 
 from mne import read_events, Epochs, pick_types, read_cov
 from mne.channels import read_layout
 from mne.io import read_raw_fif
-from mne.utils import run_tests_if_main
+from mne.utils import run_tests_if_main, catch_logging
 from mne.viz.evoked import _line_plot_onselect, plot_compare_evokeds
 from mne.viz.utils import _fake_click
 from mne.stats import _parametric_ci
@@ -188,9 +188,9 @@ def test_plot_evoked():
     plt.close('all')
 
     evoked.pick_channels(evoked.ch_names[:4])
-    with warnings.catch_warnings(record=True) as ws:
-        evoked.plot()
-    assert_equal(len(ws), 2)
-    assert_true(all('Need more than one' in str(w.message) for w in ws))
+    with catch_logging() as log_file:
+        evoked.plot(verbose=True)
+    assert_true('Need more than one' in log_file.getvalue())
+
 
 run_tests_if_main()