Repository: mne-tools/mne-python

Issue:
viz.plot_compare_evokeds incorrect axis labels
Hi, I've started a discussion in the forum that turned out to be a bug.

Please see: https://mne.discourse.group/t/misaligned-viz-plot-compare-evokeds/3834

In short, as last answer by @drammock summarizes:  "`plot_compare_evokeds(..., axes='topo')` tries to create an extra axis that shows only the axis spines, ticklabels, and axis labels. It looks like that “legend axis” is getting plotted on top of the axis for P8"


Discussion:
code to reproduce with sample dataset:

```py
import os
import mne
sample_data_folder = mne.datasets.sample.data_path()
sample_data_evoked_file = os.path.join(
    sample_data_folder, 'MEG', 'sample', 'sample_audvis-ave.fif')
evoked_list = mne.read_evokeds(sample_data_evoked_file)
picks = [f'EEG {n:03}' for n in (30, 31, 40)]
fig = mne.viz.plot_compare_evokeds(evoked_list, picks=picks, axes='topo')
```

looking into this now

Resolving patch:
diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py
--- a/mne/viz/evoked.py
+++ b/mne/viz/evoked.py
@@ -2351,14 +2351,49 @@ def click_func(
                 sphere=sphere)
 
         layout = find_layout(info)
-        # shift everything to the right by 15% of one axes width
-        layout.pos[:, 0] += layout.pos[0, 2] * .15
-        layout.pos[:, 1] += layout.pos[0, 3] * .15
+        # make sure everything fits nicely. our figsize is (18, 14) so margins
+        # of 0.25 inch seem OK
+        w_margin = 0.25 / 18
+        h_margin = 0.25 / 14
+        axes_width = layout.pos[0, 2]
+        axes_height = layout.pos[0, 3]
+        left_edge = layout.pos[:, 0].min()
+        right_edge = layout.pos[:, 0].max() + axes_width
+        bottom_edge = layout.pos[:, 1].min()
+        top_edge = layout.pos[:, 1].max() + axes_height
+        # compute scale. Use less of vertical height (leave room for title)
+        w_scale = (0.95 - 2 * w_margin) / (right_edge - left_edge)
+        h_scale = (0.9 - 2 * h_margin) / (top_edge - bottom_edge)
+        # apply transformation
+        layout.pos[:, 0] = ((layout.pos[:, 0] - left_edge) * w_scale
+                            + w_margin + 0.025)
+        layout.pos[:, 1] = ((layout.pos[:, 1] - bottom_edge) * h_scale
+                            + h_margin + 0.025)
+        # make sure there is room for a legend axis (sometimes not if only a
+        # few channels were picked)
+        data_lefts = layout.pos[:, 0]
+        data_bottoms = layout.pos[:, 1]
+        legend_left = data_lefts.max()
+        legend_bottom = data_bottoms.min()
+        overlap = np.any(np.logical_and(
+            np.logical_and(
+                data_lefts <= legend_left,
+                legend_left <= (data_lefts + axes_width)),
+            np.logical_and(
+                data_bottoms <= legend_bottom,
+                legend_bottom <= (data_bottoms + axes_height)
+            )
+        ))
+        right_edge = legend_left + axes_width
+        n_columns = (right_edge - data_lefts.min()) / axes_width
+        scale_factor = n_columns / (n_columns + 1)
+        if overlap:
+            layout.pos[:, [0, 2]] *= scale_factor
         # `axes` will be a list of (axis_object, channel_index) tuples
         axes = list(iter_topography(
             info, layout=layout, on_pick=click_func,
             fig=fig, fig_facecolor='w', axis_facecolor='w',
-            axis_spinecolor='k', layout_scale=.925, legend=True))
+            axis_spinecolor='k', layout_scale=None, legend=True))
         picks = list(picks)
     del info
 
diff --git a/mne/viz/topo.py b/mne/viz/topo.py
--- a/mne/viz/topo.py
+++ b/mne/viz/topo.py
@@ -81,8 +81,18 @@ def _legend_axis(pos):
     """Add a legend axis to the bottom right."""
     import matplotlib.pyplot as plt
     left, bottom = pos[:, 0].max(), pos[:, 1].min()
+    # check if legend axis overlaps a data axis
+    overlaps = False
+    for _pos in pos:
+        h_overlap = (_pos[0] <= left <= (_pos[0] + _pos[2]))
+        v_overlap = (_pos[1] <= bottom <= (_pos[1] + _pos[3]))
+        if h_overlap and v_overlap:
+            overlaps = True
+            break
+    if overlaps:
+        left += 1.2 * _pos[2]
     wid, hei = pos[-1, 2:]
-    return plt.axes([left, bottom + .05, wid, hei])
+    return plt.axes([left, bottom, wid, hei])
 
 
 def _iter_topography(info, layout, on_pick, fig, fig_facecolor='k',


Test patch: