Repository: mne-tools/mne-python

Issue:
adding function to list in viz/topo.py
In working on another problem I noticed something is wrong with this line:

https://github.com/mne-tools/mne-python/blob/b7e8c7791b000258b2ba158ddd89eecbbb35af30/mne/viz/topo.py#L670

it's adding a list `['w']` to a function.  Probably should be

```py
        colors = ['w'] + _get_color_list()
```

but I don't have time to follow up at the moment.  I'm surprised this isn't caught by any of our tests.


Discussion:
Hi! I would like to look into this. However, this is my first time contributing to an open-source community and I'm not super familiar with the API in MNE yet, so I might need some time to figure out the contribution guidelines and how to test this. 

Resolving patch:
diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py
--- a/mne/viz/evoked.py
+++ b/mne/viz/evoked.py
@@ -13,6 +13,7 @@
 
 from copy import deepcopy
 from functools import partial
+from itertools import cycle
 from numbers import Integral
 
 import numpy as np
@@ -863,13 +864,25 @@ def plot_evoked_topo(evoked, layout=None, layout_scale=0.945,
         fig_facecolor = background_color
         axis_facecolor = background_color
         font_color = 'k'
-    if color is None:
+
+    if isinstance(color, (tuple, list)):
+        if len(color) != len(evoked):
+            raise ValueError('Lists of evoked objects and colors'
+                             ' must have the same length')
+    elif color is None:
         if dark_background:
             color = ['w'] + _get_color_list()
         else:
             color = _get_color_list()
         color = color * ((len(evoked) % len(color)) + 1)
         color = color[:len(evoked)]
+    else:
+        if not isinstance(color, str):
+            raise ValueError(
+                'color must be of type tuple, list, str, or None.'
+            )
+        color = cycle([color])
+
     return _plot_evoked_topo(evoked=evoked, layout=layout,
                              layout_scale=layout_scale, color=color,
                              border=border, ylim=ylim, scalings=scalings,
diff --git a/mne/viz/topo.py b/mne/viz/topo.py
--- a/mne/viz/topo.py
+++ b/mne/viz/topo.py
@@ -9,15 +9,14 @@
 
 from copy import deepcopy
 from functools import partial
-from itertools import cycle
 
 import numpy as np
 
 from ..io.pick import channel_type, pick_types
-from ..utils import _clean_names, warn, _check_option, Bunch, fill_doc, _to_rgb
+from ..utils import _clean_names, _check_option, Bunch, fill_doc, _to_rgb
 from ..channels.layout import _merge_ch_data, _pair_grad_sensors, find_layout
 from ..defaults import _handle_default
-from .utils import (_check_delayed_ssp, _get_color_list, _draw_proj_checkbox,
+from .utils import (_check_delayed_ssp, _draw_proj_checkbox,
                     add_background_image, plt_show, _setup_vmin_vmax,
                     DraggableColorbar, _setup_ax_spines,
                     _check_cov, _plot_masked_image)
@@ -662,21 +661,6 @@ def _plot_evoked_topo(evoked, layout=None, layout_scale=0.945,
     if not type(evoked) in (tuple, list):
         evoked = [evoked]
 
-    if type(color) in (tuple, list):
-        if len(color) != len(evoked):
-            raise ValueError('Lists of evoked objects and colors'
-                             ' must have the same length')
-    elif color is None:
-        colors = ['w'] + _get_color_list
-        stop = (slice(len(evoked)) if len(evoked) < len(colors)
-                else slice(len(colors)))
-        color = cycle(colors[stop])
-        if len(evoked) > len(colors):
-            warn('More evoked objects than colors available. You should pass '
-                 'a list of unique colors.')
-    else:
-        color = cycle([color])
-
     noise_cov = _check_cov(noise_cov, evoked[0].info)
     if noise_cov is not None:
         evoked = [whiten_evoked(e, noise_cov) for e in evoked]


Test patch:
diff --git a/mne/viz/tests/test_topo.py b/mne/viz/tests/test_topo.py
--- a/mne/viz/tests/test_topo.py
+++ b/mne/viz/tests/test_topo.py
@@ -132,6 +132,13 @@ def test_plot_topo():
     plot_evoked_topo([evoked, evoked], merge_grads=True,
                      background_color='w')
 
+    plot_evoked_topo([evoked, evoked], merge_grads=True,
+                     background_color='w', color='blue')
+
+    with pytest.raises(ValueError, match='must be .*tuple, list, str,.*'):
+        plot_evoked_topo([evoked, evoked], merge_grads=True,
+                         color=np.array(["blue", "red"]))
+
     picked_evoked = evoked.copy().pick_channels(evoked.ch_names[:3])
     picked_evoked_eeg = evoked.copy().pick_types(meg=False, eeg=True)
     picked_evoked_eeg.pick_channels(picked_evoked_eeg.ch_names[:3])