Repository: mne-tools/mne-python

Issue:
Inconsistent topoplot layout across different TFR plotting functions
#### Describe the bug
@virvw reported some weird-looking topomap figures when plotting TFR data. While I couldn't **exactly** replicate the issues, I **do** find inconsistencies in the figures produced by `plot_joint()`, `plot_topo()`, and `plot_topomap()` using `master`.

#### Steps to reproduce

Load data & calculate power 
```python
import os.path as op
import numpy as np
import matplotlib

import mne
from mne.time_frequency import tfr_morlet
from mne.datasets import somato


matplotlib.use('Qt5Agg')

data_path = somato.data_path()
subject = '01'
task = 'somato'
raw_fname = op.join(data_path, 'sub-{}'.format(subject), 'meg',
                    'sub-{}_task-{}_meg.fif'.format(subject, task))

raw = mne.io.read_raw_fif(raw_fname)
events = mne.find_events(raw, stim_channel='STI 014')
picks = mne.pick_types(raw.info, meg='grad', eeg=False, eog=True, stim=False)

# Construct Epochs
event_id, tmin, tmax = 1, -1., 3.
baseline = (None, 0)
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    baseline=baseline, reject=dict(grad=4000e-13, eog=350e-6),
                    preload=True)
epochs.resample(200., npad='auto')

freqs = np.logspace(*np.log10([6, 35]), num=8)
n_cycles = freqs / 2
power, _ = tfr_morlet(epochs, freqs=freqs, n_cycles=n_cycles, use_fft=True,
                      return_itc=True, decim=3, n_jobs=1)
```

Now, let's plot the data. 

### First, via `plot_joint`
```python
power.plot_joint()
```
<img width="752" alt="Screenshot 2020-07-22 at 16 53 13" src="https://user-images.githubusercontent.com/2046265/88196470-82588000-cc41-11ea-9860-198ac011f72a.png">

When selecting a ROI in that plot, a new window pops up:
<img width="752" alt="Screenshot 2020-07-22 at 16 53 24" src="https://user-images.githubusercontent.com/2046265/88196524-9603e680-cc41-11ea-823f-97dbea1718db.png">

➜ Looks all good so far, if one ignores that the field is chopped off at the back of the head a little.

### Now, let's use `plot_topo`

```python
power.plot_topo()
```
Then, select one of the sensors, and a ROI in the popup. This will produce a figure like this:
<img width="752" alt="Screenshot 2020-07-22 at 16 54 03" src="https://user-images.githubusercontent.com/2046265/88196988-26422b80-cc42-11ea-966b-250a378b6d20.png">

➜ Not only is the topoplot much smaller than in the previous figure, but the colorbar is narrower as well.

### Lastly, let's use `power.plot_topomap()`
```python
power.plot_topomap()
```
<img width="312" alt="Screenshot 2020-07-22 at 16 54 29" src="https://user-images.githubusercontent.com/2046265/88197249-7ae5a680-cc42-11ea-801f-5249d7b1fd93.png">

➜ The entire figure is much smaller than the ones produced with the other methods, and both the topoplot as well as the colorbar are so small that one can barely read this plot at all.


Discussion:
@hoechenberger @larsoner @drammock would you have time to look into this one? I would like to see it fixed for next release
I could have a look this Friday / weekend
> ➜ The entire figure is much smaller than the ones produced with the other methods, and both the topoplot as well as the colorbar are so small that one can barely read this plot at all.

… and we don't see the helmet shape in the smaller figures.
Keep in mind that `plot_topo` should produce different looking plots than `plot_topomap` -- the former uses `layout`s that are different from the physically mapped `topomap` plots, at least for Neuromag MEG data (for things like EEG they might be the same or quite similar).

The head being tiny, however, is a bug that we should fix. Any progress on this @hoechenberger ?

Resolving patch:
diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py
--- a/mne/time_frequency/tfr.py
+++ b/mne/time_frequency/tfr.py
@@ -1465,6 +1465,7 @@ def plot_joint(self, timefreqs=None, picks=None, baseline=None,
                              k not in ('axes', 'show', 'colorbar')}
         topomap_args_pass['outlines'] = topomap_args.get('outlines', 'skirt')
         topomap_args_pass["contours"] = topomap_args.get('contours', 6)
+        topomap_args_pass['ch_type'] = ch_type
 
         ##############
         # Image plot #
@@ -1605,8 +1606,10 @@ def plot_joint(self, timefreqs=None, picks=None, baseline=None,
         plt_show(show)
         return fig
 
+    @verbose
     def _onselect(self, eclick, erelease, baseline=None, mode=None,
-                  cmap=None, source_plot_joint=False, topomap_args=None):
+                  cmap=None, source_plot_joint=False, topomap_args=None,
+                  verbose=None):
         """Handle rubber band selector in channel tfr."""
         from ..viz.topomap import plot_tfr_topomap, plot_topomap, _add_colorbar
         if abs(eclick.x - erelease.x) < .1 or abs(eclick.y - erelease.y) < .1:
@@ -1660,13 +1663,13 @@ def _onselect(self, eclick, erelease, baseline=None, mode=None,
                                  baseline=baseline, mode=mode, cmap=None,
                                  title=ch_type, vmin=None, vmax=None, axes=ax)
 
-    @fill_doc
+    @verbose
     def plot_topo(self, picks=None, baseline=None, mode='mean', tmin=None,
                   tmax=None, fmin=None, fmax=None, vmin=None, vmax=None,
                   layout=None, cmap='RdBu_r', title=None, dB=False,
                   colorbar=True, layout_scale=0.945, show=True,
                   border='none', fig_facecolor='k', fig_background=None,
-                  font_color='w', yscale='auto'):
+                  font_color='w', yscale='auto', verbose=None):
         """Plot TFRs in a topography with images.
 
         Parameters
@@ -1742,6 +1745,7 @@ def plot_topo(self, picks=None, baseline=None, mode='mean', tmin=None,
             The scale of y (frequency) axis. 'linear' gives linear y axis,
             'log' leads to log-spaced y axis and 'auto' detects if frequencies
             are log-spaced and only then sets the y axis to 'log'.
+        %(verbose)s
 
         Returns
         -------
diff --git a/mne/viz/topomap.py b/mne/viz/topomap.py
--- a/mne/viz/topomap.py
+++ b/mne/viz/topomap.py
@@ -799,7 +799,7 @@ def _plot_topomap(data, pos, vmin=None, vmax=None, cmap=None, sensors=True,
     import matplotlib.pyplot as plt
     from matplotlib.widgets import RectangleSelector
     data = np.asarray(data)
-    logger.debug('Plotting topomap for data shape %s' % (data.shape,))
+    logger.debug(f'Plotting topomap for {ch_type} data shape {data.shape}')
 
     if isinstance(pos, Info):  # infer pos from Info object
         picks = _pick_data_channels(pos, exclude=())  # pick only data channels
@@ -963,7 +963,10 @@ def _show_names(x):
     plt.subplots_adjust(top=.95)
 
     if onselect is not None:
+        lim = ax.dataLim
+        x0, y0, width, height = lim.x0, lim.y0, lim.width, lim.height
         ax.RS = RectangleSelector(ax, onselect=onselect)
+        ax.set(xlim=[x0, x0 + width], ylim=[y0, y0 + height])
     plt_show(show)
     return im, cont, interp
 
@@ -1382,21 +1385,17 @@ def plot_tfr_topomap(tfr, tmin=None, tmax=None, fmin=None, fmax=None,
     vmin, vmax = _setup_vmin_vmax(data, vmin, vmax, norm)
     cmap = _setup_cmap(cmap, norm=norm)
 
-    if axes is None:
-        fig = plt.figure(figsize=(size, size))
-        ax = fig.gca()
-    else:
-        fig = axes.figure
-        ax = axes
+    axes = plt.subplots(figsize=(size, size))[1] if axes is None else axes
+    fig = axes.figure
 
-    _hide_frame(ax)
+    _hide_frame(axes)
 
     locator = None
     if not isinstance(contours, (list, np.ndarray)):
         locator, contours = _set_contour_locator(vmin, vmax, contours)
 
     if title is not None:
-        ax.set_title(title)
+        axes.set_title(title)
     fig_wrapper = list()
     selection_callback = partial(_onselect, tfr=tfr, pos=pos, ch_type=ch_type,
                                  itmin=itmin, itmax=itmax, ifmin=ifmin,
@@ -1406,16 +1405,16 @@ def plot_tfr_topomap(tfr, tmin=None, tmax=None, fmin=None, fmax=None,
         _, contours = _set_contour_locator(vmin, vmax, contours)
 
     im, _ = plot_topomap(data[:, 0], pos, vmin=vmin, vmax=vmax,
-                         axes=ax, cmap=cmap[0], image_interp='bilinear',
+                         axes=axes, cmap=cmap[0], image_interp='bilinear',
                          contours=contours, names=names, show_names=show_names,
                          show=False, onselect=selection_callback,
-                         sensors=sensors, res=res,
+                         sensors=sensors, res=res, ch_type=ch_type,
                          outlines=outlines, sphere=sphere)
 
     if colorbar:
         from matplotlib import ticker
         unit = _handle_default('units', unit)['misc']
-        cbar, cax = _add_colorbar(ax, im, cmap, title=unit, format=cbar_fmt)
+        cbar, cax = _add_colorbar(axes, im, cmap, title=unit, format=cbar_fmt)
         if locator is None:
             locator = ticker.MaxNLocator(nbins=5)
         cbar.locator = locator


Test patch:
diff --git a/mne/time_frequency/tests/test_tfr.py b/mne/time_frequency/tests/test_tfr.py
--- a/mne/time_frequency/tests/test_tfr.py
+++ b/mne/time_frequency/tests/test_tfr.py
@@ -12,7 +12,7 @@
                  Info, Transform)
 from mne.io import read_raw_fif
 from mne.utils import (_TempDir, run_tests_if_main, requires_h5py,
-                       requires_pandas, grand_average)
+                       requires_pandas, grand_average, catch_logging)
 from mne.time_frequency.tfr import (morlet, tfr_morlet, _make_dpss,
                                     tfr_multitaper, AverageTFR, read_tfrs,
                                     write_tfrs, combine_tfr, cwt, _compute_tfr,
@@ -548,9 +548,13 @@ def test_plot_joint():
     topomap_args = {'res': 8, 'contours': 0, 'sensors': False}
 
     for combine in ('mean', 'rms', None):
-        tfr.plot_joint(title='auto', colorbar=True,
-                       combine=combine, topomap_args=topomap_args)
+        with catch_logging() as log:
+            tfr.plot_joint(title='auto', colorbar=True,
+                           combine=combine, topomap_args=topomap_args,
+                           verbose='debug')
         plt.close('all')
+        log = log.getvalue()
+        assert 'Plotting topomap for grad data' in log
 
     # check various timefreqs
     for timefreqs in (