Repository: mne-tools/mne-python

Issue:
BUG topomap grads
```
import numpy as np
import mne
from mne.datasets import sample
data_path = sample.data_path()
raw = mne.io.read_raw_fif(data_path + '/MEG/sample/sample_audvis_raw.fif')
info = raw.load_data().pick('grad').info
data = np.random.randn(204)
mne.viz.plot_topomap(data, info)
```

produces 
![Figure_1](https://user-images.githubusercontent.com/161052/76150213-29c88200-60a8-11ea-917f-73613c1a3d1b.png)





Discussion:
That's an artifact of `extrapolate='box'` - it should look better with `extrapolate='head'` or `extrapolate='local'`.
head:
![Figure_head](https://user-images.githubusercontent.com/161052/76159641-efe89180-6122-11ea-8ef3-a7ee39f07752.png)

local:
![Figure_local](https://user-images.githubusercontent.com/161052/76159642-f119be80-6122-11ea-9f4e-6f2cdb8afa6b.png)

so not much success. 

@larsoner any suggestion?
Ah, I misunderstood your initial issue. I thought the circle shows what is wrong, but it is the head outline. It is weird indeed, I'll take a look at this.
It seems that `_pair_grad_sensors` does not take `sphere` as an argument and no sphere-placement is done in general with grad ch type. I'll try fixing that later today.
indeed the bug only appears with grad not mag.

thanks for taking a look

>

@agramfort @larsoner 
I'm not sure what should be considered the source of this bug (apart from ignoring `sphere` argument):
* with 'grad', channel positions in info are ignored, only the layout is used
* layout for `'Vectorview-grad'` is not zero-centered, see below:

![image](https://user-images.githubusercontent.com/8452354/76165955-5ab5bf00-615b-11ea-9a96-6e22cf52928e.png)

one should use the same thing as for mag. One should not use layout also in
this case.

>


Resolving patch:
diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py
--- a/mne/viz/topomap.py
+++ b/mne/viz/topomap.py
@@ -760,7 +760,8 @@ def _plot_topomap(data, pos, vmin=None, vmax=None, cmap=None, sensors=True,
 
         if any(type_ in ch_type for type_ in ('planar', 'grad')):
             # deal with grad pairs
-            picks, pos = _pair_grad_sensors(pos, find_layout(pos))
+            picks = _pair_grad_sensors(pos, topomap_coords=False)
+            pos = _find_topomap_coords(pos, picks=picks[::2], sphere=sphere)
             data = _merge_grad_data(data[picks]).reshape(-1)
         else:
             picks = list(range(data.shape[0]))


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
@@ -234,6 +234,18 @@ def test_plot_topomap_basic():
     with pytest.raises(ValueError, match=error_msg):
         plot_topomap(data, info, extrapolate='head', border='fancy')
 
+    # test channel placement when only 'grad' are picked:
+    # ---------------------------------------------------
+    info_grad = evoked.copy().pick('grad').info
+    n_grads = len(info_grad['ch_names'])
+    data = np.random.randn(n_grads)
+    img, _ = plot_topomap(data, info_grad)
+
+    # check that channels are scattered around x == 0
+    pos = img.axes.collections[-1].get_offsets()
+    prop_channels_on_the_right = (pos[:, 0] > 0).mean()
+    assert prop_channels_on_the_right < 0.6
+
     # other:
     # ------
     plt_topomap = partial(evoked.plot_topomap, **fast_test)