code: def _validate_fig_and_axes(
      fig, axes, group_by, evoked, colorbar, clear=False
  ):
      """Check user-provided fig/axes compatibility with plot_epochs_image."""
      from matplotlib.pyplot import Axes, figure, subplot2grid
  
      n_axes = 1 + int(evoked) + int(colorbar)
      ax_names = ("image", "evoked", "colorbar")
      ax_names = np.array(ax_names)[np.where([True, evoked, colorbar])]
      prefix = f"Since evoked={evoked} and colorbar={colorbar}, "
  
      # got both fig and axes
      if fig is not None and axes is not None:
          raise ValueError(
              f'At least one of "fig" or "axes" must be None; got fig={fig}, axes={axes}.'
          )
  
      # got fig=None and axes=None: make fig(s) and axes
      if fig is None and axes is None:
          axes = dict()
          colspan = 9 if colorbar else 10
          rowspan = 2 if evoked else 3
          shape = (3, 10)
          for this_group in group_by:
              this_fig = figure(layout="constrained")
              _set_window_title(this_fig, this_group)
              subplot2grid(
                  shape,
                  (0, 0),
                  colspan=colspan,
                  rowspan=rowspan,
                  fig=this_fig,
              )
              if evoked:
                  subplot2grid(
                      shape,
                      (2, 0),
                      colspan=colspan,
                      rowspan=1,
                      fig=this_fig,
                  )
              if colorbar:
                  subplot2grid(
                      shape,
                      (0, 9),
                      colspan=1,
                      rowspan=rowspan,
                      fig=this_fig,
                  )
              axes[this_group] = this_fig.axes
  
      # got a Figure instance
      if fig is not None:
          # If we're re-plotting into a fig made by a previous call to
          # `plot_image`, be forgiving of presence/absence of sensor inset axis.
          if len(fig.axes) not in (n_axes, n_axes + 1):
              raise ValueError(
                  f'{prefix}"fig" must contain {n_axes} axes, got {len(fig.axes)}.'
              )
          if len(list(group_by)) != 1:
              raise ValueError(
                  'When "fig" is not None, "group_by" can only '
                  "have one group (got {}: {}).".format(
                      len(group_by), ", ".join(group_by)
                  )
              )
          key = list(group_by)[0]
          if clear:  # necessary if re-plotting into previous figure
              _ = [ax.clear() for ax in fig.axes]
              if len(fig.axes) > n_axes:  # get rid of sensor inset
                  fig.axes[-1].remove()
              _set_window_title(fig, key)
          axes = {key: fig.axes}
  
      # got an Axes instance, be forgiving (if evoked and colorbar are False)
      if isinstance(axes, Axes):
          axes = [axes]
  
      # got an ndarray; be forgiving
      if isinstance(axes, np.ndarray):
          axes = axes.ravel().tolist()
  
      # got a list of axes, make it a dict
      if isinstance(axes, list):
          if len(axes) != n_axes:
              raise ValueError(
                  f'{prefix}"axes" must be length {n_axes}, got {len(axes)}.'
              )
          # for list of axes to work, must be only one group
          if len(list(group_by)) != 1:
              raise ValueError(
                  "When axes is a list, can only plot one group "
                  "(got {} groups: {}).".format(
                      len(group_by), ", ".join(group_by)
                  )
              )
          key = list(group_by)[0]
          axes = {key: axes}
  
      # got a dict of lists of axes, make it dict of dicts
      if isinstance(axes, dict):
          # in theory a user could pass a dict of axes but *NOT* pass a group_by
          # dict, but that is forbidden in the docstring so it shouldn't happen.
          # The next test could fail in that case because we've constructed a
          # group_by dict and the user won't have known what keys we chose.
          if set(axes) != set(group_by):
              raise ValueError(
                  f'If "axes" is a dict its keys ({list(axes)}) must match the keys in '
                  f'"group_by" ({list(group_by)}).'
              )
          for this_group, this_axes_list in axes.items():
              if len(this_axes_list) != n_axes:
                  raise ValueError(
                      f'{prefix}each value in "axes" must be a list of {n_axes} axes, got'
                      f" {len(this_axes_list)}."
                  )
              # NB: next line assumes all axes in each list are in same figure
              group_by[this_group]["fig"] = this_axes_list[
                  0
              ].get_figure()
              group_by[this_group]["axes"] = {
                  key: axis
                  for key, axis in zip(ax_names, this_axes_list)
              }
      return group_by
  
file_path: mne-python/mne/viz/epochs.py
imports: from collections import Counter
  from copy import deepcopy
  import numpy
  from scipy.ndimage import gaussian_filter1d
  from .._fiff.meas_info import create_info
  from .._fiff.pick import _DATA_CH_TYPES_SPLIT, _VALID_CHANNEL_TYPES, _picks_to_idx
  from ..defaults import _handle_default
  from ..fixes import _sharex
  from ..utils import _check_option, fill_doc, legacy, logger, verbose, warn
  from ..utils.spectrum import _split_psd_kwargs
  from .raw import _setup_channel_selections
  from .utils import DraggableColorbar, _check_cov, _compute_scalings, _get_channel_plotting_order, _handle_decim, _handle_precompute, _make_combine_callable, _make_event_color_dict, _set_title_multiple_electrodes, _set_window_title, _setup_cmap, _setup_vmin_vmax, _validate_type, plt_show
label_desc: Use image node_id 2 for calling a global function with example usage: _validate_fig_and_axes(fig, axes, group_by, evoked, colorbar, clear) and returns: group_by