Repository: mne-tools/mne-python

Issue:
mne.source_estimate.MixedSourceEstimate.plot_surface(...) crashes
#### Steps and/or code to reproduce
Sorry for not providing a fully reproducible code, but I think the problem is quite clear here. I tried to plot sources with a MixedSourceEstimate using 
```
stc.plot_surface(views='lat', hemi='split', src=mne.SourceSpaces(src[:2]), subject='sample',
                             subjects_dir=atlas_dir, colorbar=False, clim=clim, colormap=colormap)
```
and I got:
```
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-72-14b84a8a0864> in <module>
---->   7                              subjects_dir=atlas_dir, #initial_time=max_t, colorbar=False, clim=clim, colormap=colormap)
     10 screenshot = brain.screenshot()
     11 brain.close()

~/mne-python/mne/source_estimate.py in plot_surface(self, src, subject, surface, hemi, colormap, time_label, smoothing_steps, transparent, alpha, time_viewer, config_opts, subjects_dir, figure, views, colorbar, clim)
   2240                                      config_opts=config_opts,
   2241                                      subjects_dir=subjects_dir, figure=figure,
-> 2242                                      views=views, colorbar=colorbar, clim=clim)
   2243 
   2244 

TypeError: plot_source_estimates() got an unexpected keyword argument 'config_opts'
```
And sure enough, on the current dev code at line 2257 of mne/source_estimate.py:
```
        return plot_source_estimates(stc, subject, surface=surface, hemi=hemi,
                                     colormap=colormap, time_label=time_label,
                                     smoothing_steps=smoothing_steps,
                                     transparent=transparent, alpha=alpha,
                                     time_viewer=time_viewer,
                                     config_opts=config_opts,
                                     subjects_dir=subjects_dir, figure=figure,
                                     views=views, colorbar=colorbar, clim=clim)
```
and at line 1540 of mne/viz/_3d.py
```
def plot_source_estimates(stc, subject=None, surface='inflated', hemi='lh',
                          colormap='auto', time_label='auto',
                          smoothing_steps=10, transparent=True, alpha=1.0,
                          time_viewer=False, subjects_dir=None, figure=None,
                          views='lat', colorbar=True, clim='auto',
                          cortex="classic", size=800, background="black",
                          foreground="white", initial_time=None,
                          time_unit='s', backend='auto', spacing='oct6',
                          title=None, verbose=None):
```
Unless I am missing something, this code is broken...


Discussion:
It probably has not been used for some time (and is obviously untested!). Are you up for making a PR to fix it?
I can most probably have a look at it and if it goes well propose something. But I am on short deadlines for the next two weeks so it would go after that.

Resolving patch:
diff --git a/mne/source_estimate.py b/mne/source_estimate.py
--- a/mne/source_estimate.py
+++ b/mne/source_estimate.py
@@ -2200,7 +2200,7 @@ def plot_surface(self, src, subject=None, surface='inflated', hemi='lh',
                      colormap='auto', time_label='time=%02.f ms',
                      smoothing_steps=10,
                      transparent=None, alpha=1.0, time_viewer=False,
-                     config_opts=None, subjects_dir=None, figure=None,
+                     subjects_dir=None, figure=None,
                      views='lat', colorbar=True, clim='auto'):
         """Plot surface source estimates with PySurfer.
 
@@ -2238,9 +2238,6 @@ def plot_surface(self, src, subject=None, surface='inflated', hemi='lh',
             Alpha value to apply globally to the overlay.
         time_viewer : bool
             Display time viewer GUI.
-        config_opts : dict
-            Keyword arguments for Brain initialization.
-            See pysurfer.viz.Brain.
         %(subjects_dir)s
         figure : instance of mayavi.mlab.Figure | None
             If None, the last figure will be cleaned and a new figure will
@@ -2272,7 +2269,6 @@ def plot_surface(self, src, subject=None, surface='inflated', hemi='lh',
                                      smoothing_steps=smoothing_steps,
                                      transparent=transparent, alpha=alpha,
                                      time_viewer=time_viewer,
-                                     config_opts=config_opts,
                                      subjects_dir=subjects_dir, figure=figure,
                                      views=views, colorbar=colorbar, clim=clim)
 
diff --git a/mne/viz/_3d.py b/mne/viz/_3d.py
--- a/mne/viz/_3d.py
+++ b/mne/viz/_3d.py
@@ -1650,6 +1650,9 @@ def plot_source_estimates(stc, subject=None, surface='inflated', hemi='lh',
     _check_option('backend', backend, ['auto', 'matplotlib', 'mayavi'])
     plot_mpl = backend == 'matplotlib'
     if not plot_mpl:
+        if not check_version('surfer', '0.9'):
+            raise RuntimeError('This function requires pysurfer version '
+                               '>= 0.9')
         try:
             from mayavi import mlab  # noqa: F401
         except ImportError:
@@ -1698,6 +1701,8 @@ def plot_source_estimates(stc, subject=None, surface='inflated', hemi='lh',
         data = getattr(stc, hemi + '_data')
         vertices = stc.vertices[hemi_idx]
         if len(data) > 0:
+            if transparent is None:
+                transparent = True
             kwargs = {
                 "array": data, "colormap": colormap,
                 "vertices": vertices,
diff --git a/mne/viz/_brain/surface.py b/mne/viz/_brain/surface.py
--- a/mne/viz/_brain/surface.py
+++ b/mne/viz/_brain/surface.py
@@ -9,6 +9,7 @@
 from os import path as path
 
 import numpy as np
+from ...utils import check_version
 
 
 class Surface(object):
@@ -66,6 +67,10 @@ class Surface(object):
 
     def __init__(self, subject_id, hemi, surf, subjects_dir=None, offset=None,
                  units='mm'):
+
+        if not check_version('surfer', '0.9'):
+            raise RuntimeError('This function requires ' +
+                               'pysurfer (surfer >= 0.9)')
         from surfer.utils import _check_units, _get_subjects_dir
 
         hemis = ('lh', 'rh')


Test patch:
diff --git a/mne/viz/tests/test_3d.py b/mne/viz/tests/test_3d.py
--- a/mne/viz/tests/test_3d.py
+++ b/mne/viz/tests/test_3d.py
@@ -20,7 +20,7 @@
                  VolSourceEstimate, make_sphere_model, use_coil_def,
                  setup_volume_source_space, read_forward_solution,
                  VolVectorSourceEstimate, convert_forward_solution,
-                 compute_source_morph)
+                 compute_source_morph, MixedSourceEstimate)
 from mne.io import (read_raw_ctf, read_raw_bti, read_raw_kit, read_info,
                     read_raw_nirx)
 from mne.io._digitization import write_dig
@@ -55,6 +55,8 @@
 
 fwd_fname = op.join(data_dir, 'MEG', 'sample',
                     'sample_audvis_trunc-meg-vol-7-fwd.fif')
+fwd_fname2 = op.join(data_dir, 'MEG', 'sample',
+                     'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif')
 
 base_dir = op.join(io_dir, 'bti', 'tests', 'data')
 pdf_fname = op.join(base_dir, 'test_pdf_linux')
@@ -640,4 +642,26 @@ def test_brain_colorbar(orientation, diverging, lims):
     plt.close('all')
 
 
+@requires_pysurfer
+@testing.requires_testing_data
+@traits_test
+def test_mixed_sources_plot_surface():
+    """Test plot_surface() for  mixed source space."""
+    src = read_source_spaces(fwd_fname2)
+    N = np.sum([s['nuse'] for s in src])  # number of sources
+
+    T = 2  # number of time points
+    S = 3  # number of source spaces
+
+    rng = np.random.RandomState(0)
+    data = rng.randn(N, T)
+    vertno = S * [np.arange(N // S)]
+
+    stc = MixedSourceEstimate(data, vertno, 0, 1)
+
+    stc.plot_surface(views='lat', hemi='split', src=src,
+                     subject='fsaverage', subjects_dir=subjects_dir,
+                     colorbar=False)
+
+
 run_tests_if_main()