class_docstr: Plot MEG/EEG fields on head surface and helmet in 3D.
  
  Parameters
  ----------
  evoked : instance of mne.Evoked
      The evoked object.
  surf_maps : list
      The surface mapping information obtained with make_field_map.
  time : float | None
      The time point at which the field map shall be displayed. If None,
      the average peak latency (across sensor types) is used.
  time_label : str | None
      How to print info about the time instant visualized.
  %(n_jobs)s
  fig : instance of Figure3D | None
      If None (default), a new figure will be created, otherwise it will
      plot into the given figure.
  
      .. versionadded:: 0.20
  vmax : float | dict | None
      Maximum intensity. Can be a dictionary with two entries ``"eeg"`` and ``"meg"``
      to specify separate values for EEG and MEG fields respectively. Can be
      ``None`` to use the maximum value of the data.
  
      .. versionadded:: 0.21
      .. versionadded:: 1.4
          ``vmax`` can be a dictionary to specify separate values for EEG and
          MEG fields.
  n_contours : int
      The number of contours.
  
      .. versionadded:: 0.21
  show_density : bool
      Whether to draw the field density as an overlay on top of the helmet/head
      surface. Defaults to ``True``.
  alpha : float | dict | None
      Opacity of the meshes (between 0 and 1). Can be a dictionary with two
      entries ``"eeg"`` and ``"meg"`` to specify separate values for EEG and
      MEG fields respectively. Can be ``None`` to use 1.0 when a single field
      map is shown, or ``dict(eeg=1.0, meg=0.5)`` when both field maps are shown.
  
      .. versionadded:: 1.4
  %(interpolation_brain_time)s
  
      .. versionadded:: 1.6
  %(interaction_scene)s
      Defaults to ``'terrain'``.
  
      .. versionadded:: 1.1
  time_viewer : bool | str
      Display time viewer GUI. Can also be ``"auto"``, which will mean
      ``True`` if there is more than one time point and ``False`` otherwise.
  
      .. versionadded:: 1.6
  %(verbose)s
  
  Notes
  -----
  The figure will publish and subscribe to the following UI events:
  
  * :class:`~mne.viz.ui_events.TimeChange`
  * :class:`~mne.viz.ui_events.Contours`, ``kind="field_strength_meg" | "field_strength_eeg"``
  * :class:`~mne.viz.ui_events.ColormapRange`, ``kind="field_strength_meg" | "field_strength_eeg"``
class_docstr_tok: ["Plot","MEG\/EEG","fields","on","head","surface","and","helmet","in","3D",".","Parameters","--","--","--","--","--","evoked",":","instance","of","mne.Evoked","The","evoked","object",".","surf_maps",":","list","The","surface","mapping","information","obtained","with","make_field_map",".","time",":","float","|","None","The","time","point","at","which","the","field","map","shall","be","displayed",".","If","None",",","the","average","peak","latency","(","across","sensor","types",")","is","used",".","time_label",":","str","|","None","How","to","print","info","about","the","time","instant","visualized",".","%","(","n_jobs",")","s","fig",":","instance","of","Figure3D","|","None","If","None","(","default",")",",","a","new","figure","will","be","created",",","otherwise","it","will","plot","into","the","given","figure",".","..","versionadded",":",":","0.20","vmax",":","float","|","dict","|","None","Maximum","intensity",".","Can","be","a","dictionary","with","two","entries","``","``","eeg","''","``","and","``","``","meg","''","``","to","specify","separate","values","for","EEG","and","MEG","fields","respectively",".","Can","be","``","None","``","to","use","the","maximum","value","of","the","data",".","..","versionadded",":",":","0.21","..","versionadded",":",":","1.4","``","vmax","``","can","be","a","dictionary","to","specify","separate","values","for","EEG","and","MEG","fields",".","n_contours",":","int","The","number","of","contours",".","..","versionadded",":",":","0.21","show_density",":","bool","Whether","to","draw","the","field","density","as","an","overlay","on","top","of","the","helmet\/head","surface",".","Defaults","to","``","True","``",".","alpha",":","float","|","dict","|","None","Opacity","of","the","meshes","(","between","0","and","1",")",".","Can","be","a","dictionary","with","two","entries","``","``","eeg","''","``","and","``","``","meg","''","``","to","specify","separate","values","for","EEG","and","MEG","fields","respectively",".","Can","be","``","None","``","to","use","1.0","when","a","single","field","map","is","shown",",","or","``","dict","(","eeg=1.0",",","meg=0.5",")","``","when","both","field","maps","are","shown",".","..","versionadded",":",":","1.4","%","(","interpolation_brain_time",")","s","..","versionadded",":",":","1.6","%","(","interaction_scene",")","s","Defaults","to","``","'terrain","'","``",".","..","versionadded",":",":","1.1","time_viewer",":","bool","|","str","Display","time","viewer","GUI",".","Can","also","be","``","``","auto","''","``",",","which","will","mean","``","True","``","if","there","is","more","than","one","time","point","and","``","False","``","otherwise",".","..","versionadded",":",":","1.6","%","(","verbose",")","s","Notes","--","--","-","The","figure","will","publish","and","subscribe","to","the","following","UI","events",":","*",":","class",":","`","~mne.viz.ui_events.TimeChange","`","*",":","class",":","`","~mne.viz.ui_events.Contours","`",",","``","kind=","''","field_strength_meg","''","|","``","field_strength_eeg","''","``","*",":","class",":","`","~mne.viz.ui_events.ColormapRange","`",",","``","kind=","''","field_strength_meg","''","|","``","field_strength_eeg","''","``"]
code: def __init__(
      self,
      evoked,
      surf_maps,
      *,
      time=None,
      time_label="t = %0.0f ms",
      n_jobs=None,
      fig=None,
      vmax=None,
      n_contours=21,
      show_density=True,
      alpha=None,
      interpolation="nearest",
      interaction="terrain",
      time_viewer="auto",
      verbose=None,
  ):
      from .backends.renderer import _get_3d_backend, _get_renderer
  
      # Setup figure parameters
      self._evoked = evoked
      if time is None:
          types = [t for t in ["eeg", "grad", "mag"] if t in evoked]
          time = np.mean([evoked.get_peak(ch_type=t)[1] for t in types])
      self._current_time = time
      if not evoked.times[0] <= time <= evoked.times[-1]:
          raise ValueError(
              "`time` (%0.3f) must be inside `evoked.times`" % time
          )
      self._time_label = time_label
  
      self._vmax = _validate_type(vmax, (None, "numeric", dict), "vmax")
      self._n_contours = _ensure_int(n_contours, "n_contours")
      self._time_interpolation = _check_option(
          "interpolation",
          interpolation,
          (
              "linear",
              "nearest",
              "zero",
              "slinear",
              "quadratic",
              "cubic",
          ),
      )
      self._interaction = _check_option(
          "interaction", interaction, ["trackball", "terrain"]
      )
  
      surf_map_kinds = [surf_map["kind"] for surf_map in surf_maps]
      if vmax is None:
          self._vmax = {kind: None for kind in surf_map_kinds}
      elif isinstance(vmax, dict):
          for kind in surf_map_kinds:
              if kind not in vmax:
                  raise ValueError(
                      f'No entry for "{kind}" found in the vmax dictionary'
                  )
          self._vmax = vmax
      else:  # float value
          self._vmax = {kind: vmax for kind in surf_map_kinds}
  
      if alpha is None:
          self._alpha = {
              surf_map["kind"]: val
              for surf_map, val in zip(surf_maps, [1.0, 0.5])
          }
      elif isinstance(alpha, dict):
          for kind in surf_map_kinds:
              if kind not in alpha:
                  raise ValueError(
                      f'No entry for "{kind}" found in the alpha dictionary'
                  )
          self._alpha = alpha
      else:  # float value
          self._alpha = {kind: alpha for kind in surf_map_kinds}
  
      self._colors = [(0.6, 0.6, 0.6), (1.0, 1.0, 1.0)]
      self._colormap = mne_analyze_colormap(format="vtk")
      self._colormap_lines = np.concatenate(
          [
              np.tile([0.0, 0.0, 255.0, 255.0], (127, 1)),
              np.tile([0.0, 0.0, 0.0, 255.0], (2, 1)),
              np.tile([255.0, 0.0, 0.0, 255.0], (127, 1)),
          ]
      )
      self._show_density = show_density
  
      from ._brain import Brain
  
      if isinstance(fig, Brain):
          self._renderer = fig._renderer
          self._in_brain_figure = True
          if _get_3d_backend() == "notebook":
              raise NotImplementedError(
                  "Plotting on top of an existing Brain figure "
                  "is currently not supported inside a notebook."
              )
      else:
          self._renderer = _get_renderer(
              fig, bgcolor=(0.0, 0.0, 0.0), size=(600, 600)
          )
          self._in_brain_figure = False
  
      self.plotter = self._renderer.plotter
      self.interaction = interaction
  
      # Prepare the surface maps
      self._surf_maps = [
          self._prepare_surf_map(
              surf_map, color, self._alpha[surf_map["kind"]]
          )
          for surf_map, color in zip(surf_maps, self._colors)
      ]
  
      # Do we want the time viewer?
      if time_viewer == "auto":
          time_viewer = len(evoked.times) > 1
      self.time_viewer = time_viewer
  
      # Configure UI events
      @_auto_weakref
      def current_time_func():
          return self._current_time
  
      self._widgets = dict()
      if self.time_viewer:
          # Draw widgets only if not inside a figure that already has them.
          if (
              not hasattr(self._renderer, "_widgets")
              or "time_slider" not in self._renderer._widgets
          ):
              self._renderer._enable_time_interaction(
                  self,
                  current_time_func=current_time_func,
                  times=evoked.times,
              )
          if (
              not self._in_brain_figure
              or "time_slider" not in fig.widgets
          ):
              # Draw the time label
              self._time_label = time_label
              if time_label is not None:
                  if "%" in time_label:
                      time_label = time_label % np.round(1e3 * time)
                  self._time_label_actor = self._renderer.text2d(
                      x_window=0.01, y_window=0.01, text=time_label
                  )
          self._configure_dock()
  
      subscribe(self, "time_change", self._on_time_change)
      subscribe(self, "colormap_range", self._on_colormap_range)
      subscribe(self, "contours", self._on_contours)
  
      if not self._in_brain_figure:
          self._renderer.set_interaction(interaction)
          self._renderer.set_camera(
              azimuth=10, elevation=60, distance="auto"
          )
          self._renderer.show()
  
imports: from functools import partial
  import numpy
  from scipy.interpolate import interp1d
  from .._fiff.pick import pick_types
  from ..defaults import DEFAULTS
  from ..utils import _auto_weakref, _check_option, _ensure_int, _to_rgb, _validate_type, fill_doc
  from ._3d_overlay import _LayeredMesh
  from .ui_events import ColormapRange, Contours, TimeChange, disable_ui_events, publish, subscribe
  from .utils import mne_analyze_colormap
label_desc: Use image node_id 1 to create a new EvokedField object  with example: obj = EvokedField(evoked, surf_maps)