Repository: mne-tools/mne-python

Issue:
BUG: Viz Topomap Produces ValueError Always Due to Cardinal Dig
## Describe the bug

In `mne.viz.topomap(data, info)`, I get an error in the latest version:

```
ValueError: Number of channels in the Info object and the data array does not match. Pick Info with e.g. mne.pick_info and mne.io.pick.channel_indices_by_type.
```

#### Steps to reproduce
If I run the following code:

```
from pprint import pprint

montage = mne.channels.make_standard_montage("standard_1020")
raw.set_montage(montage)
info = raw.info
pprint(info['dig'])
```

You'll notice that we have extra DigPoints.

#### Expected results
It should work as before (I think ~v0.19?) where it just plotted the topomap as long as the data shape matched.

If you use `mne.viz.plot_sensors`, it works as expected and only plots the EEG sensors.



Discussion:
@adam2392 this is not enough for us to reproduce the bug locally. Can you include an example that we can copy-paste to see it locally? For example you can create a dummy `Raw` with something like:
```Python
import numpy as np
import mne
data = np.random.RandomState(0).randn(2, 1000)
info = mne.create_info(['Cz', 'Fz'], 1000., 'eeg')
raw = mne.io.RawArray(data, info)
montage = mne.channels.make_standard_montage("standard_1020")
raw.set_montage(montage)
```
This does not crash. Can you adapt it to your use case so that it does?

Alternatively you can upload the raw data somewhere and give us a link.
Ah okay, so the issue arises only when there is a channel marked in the `bads` list. If you have 20 EEG channels total, and one is marked in the `bads` list, and you pass in a vector 20x1, then it breaks.

I suppose in a way this would "be expected", but would it be beneficial to make the error possibly more informative? 


> Ah okay, so the issue arises only when there is a channel marked in the bads list. If you have 20 EEG channels total, and one is marked in the bads list, and you pass in a vector 20x1, then it breaks.

I'm not quite following. Can you modify my code snippet above to produce the breaking behavior? That will help me understand where you're hitting the error and what the situation is (where bads come in, data sizes, channels, etc.).
@adam2392 - you are correct, @larsoner see the snippet below:
```python
import numpy as np
import mne

ch_names = list('abcde')
ch_pos = np.array([[0, 0, 1], [1, 0, 0], [-1, 0, 0],
                   [0, -1, 0], [0, 1, 0]])
ch_pos_dict = {name: pos for name, pos in zip(ch_names, ch_pos)}
dig = mne.channels.make_dig_montage(ch_pos_dict, coord_frame='head')

data = np.random.random(5)
info = mne.create_info(ch_names, 250, ['eeg'] * 5)
info.set_montage(dig)
info['bads'] = ['a']

ax, _ = mne.viz.plot_topomap(data, info)
```

I'm not sure whether this should be expected. It is kind of surprising, but its not unreasonable. I don't have a strong opinion here.

Resolving patch:
diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py
--- a/mne/viz/topomap.py
+++ b/mne/viz/topomap.py
@@ -707,7 +707,7 @@ def _plot_topomap(data, pos, vmin=None, vmax=None, cmap=None, sensors=True,
     logger.debug('Plotting topomap for data shape %s' % (data.shape,))
 
     if isinstance(pos, Info):  # infer pos from Info object
-        picks = _pick_data_channels(pos)  # pick only data channels
+        picks = _pick_data_channels(pos, exclude=())  # pick only data channels
         pos = pick_info(pos, picks)
 
         # check if there is only 1 channel type, and n_chans matches the data
@@ -719,8 +719,9 @@ def _plot_topomap(data, pos, vmin=None, vmax=None, cmap=None, sensors=True,
             raise ValueError("Multiple channel types in Info structure. " +
                              info_help)
         elif len(pos["chs"]) != data.shape[0]:
-            raise ValueError("Number of channels in the Info object and "
-                             "the data array does not match. " + info_help)
+            raise ValueError("Number of channels in the Info object (%s) and "
+                             "the data array (%s) do not match. "
+                             % (len(pos['chs']), data.shape[0]) + info_help)
         else:
             ch_type = ch_type.pop()
 


Test patch:
diff --git a/mne/viz/tests/test_topomap.py b/mne/viz/tests/test_topomap.py
--- a/mne/viz/tests/test_topomap.py
+++ b/mne/viz/tests/test_topomap.py
@@ -21,11 +21,11 @@
                  compute_proj_evoked, find_layout, pick_types, create_info,
                  EvokedArray)
 from mne.io.proj import make_eeg_average_ref_proj, Projection
-from mne.io import read_raw_fif, read_info
+from mne.io import read_raw_fif, read_info, RawArray
 from mne.io.constants import FIFF
 from mne.io.pick import pick_info, channel_indices_by_type
 from mne.io.compensator import get_current_comp
-from mne.channels import read_layout, make_standard_montage
+from mne.channels import read_layout, make_standard_montage, make_dig_montage
 from mne.datasets import testing
 from mne.time_frequency.tfr import AverageTFR
 from mne.utils import run_tests_if_main
@@ -482,4 +482,18 @@ def test_plot_topomap_neuromag122():
         plot_projs_topomap([proj], evoked.info, layout=layout, **fast_test)
 
 
+def test_plot_topomap_bads():
+    """Test plotting topomap with bad channels (gh-7213)."""
+    import matplotlib.pyplot as plt
+    data = np.random.RandomState(0).randn(3, 1000)
+    raw = RawArray(data, create_info(3, 1000., 'eeg'))
+    ch_pos_dict = {name: pos for name, pos in zip(raw.ch_names, np.eye(3))}
+    raw.info.set_montage(make_dig_montage(ch_pos_dict, coord_frame='head'))
+    for count in range(3):
+        raw.info['bads'] = raw.ch_names[:count]
+        raw.info._check_consistency()
+        plot_topomap(data[:, 0], raw.info)
+    plt.close('all')
+
+
 run_tests_if_main()