code: def compute_source_morph(
      src,
      subject_from=None,
      subject_to="fsaverage",
      subjects_dir=None,
      zooms="auto",
      niter_affine=(100, 100, 10),
      niter_sdr=(5, 5, 3),
      spacing=5,
      smooth=None,
      warn=True,
      xhemi=False,
      sparse=False,
      src_to=None,
      precompute=False,
      verbose=None,
  ):
      """Create a SourceMorph from one subject to another.
  
      Method is based on spherical morphing by FreeSurfer for surface
      cortical estimates :footcite:`GreveEtAl2013` and
      Symmetric Diffeomorphic Registration for volumic data
      :footcite:`AvantsEtAl2008`.
  
      Parameters
      ----------
      src : instance of SourceSpaces | instance of SourceEstimate
          The SourceSpaces of subject_from (can be a
          SourceEstimate if only using a surface source space).
      subject_from : str | None
          Name of the original subject as named in the SUBJECTS_DIR.
          If None (default), then ``src[0]['subject_his_id]'`` will be used.
      subject_to : str | None
          Name of the subject to which to morph as named in the SUBJECTS_DIR.
          Default is ``'fsaverage'``. If None, ``src_to[0]['subject_his_id']``
          will be used.
  
          .. versionchanged:: 0.20
             Support for subject_to=None.
      %(subjects_dir)s
      zooms : float | tuple | str | None
          The voxel size of volume for each spatial dimension in mm.
          If spacing is None, MRIs won't be resliced, and both volumes
          must have the same number of spatial dimensions.
          Can also be ``'auto'`` to use ``5.`` if ``src_to is None`` and
          the zooms from ``src_to`` otherwise.
  
          .. versionchanged:: 0.20
             Support for 'auto' mode.
      niter_affine : tuple of int
          Number of levels (``len(niter_affine)``) and number of
          iterations per level - for each successive stage of iterative
          refinement - to perform the affine transform.
          Default is niter_affine=(100, 100, 10).
      niter_sdr : tuple of int
          Number of levels (``len(niter_sdr)``) and number of
          iterations per level - for each successive stage of iterative
          refinement - to perform the Symmetric Diffeomorphic Registration (sdr)
          transform. Default is niter_sdr=(5, 5, 3).
      spacing : int | list | None
          The resolution of the icosahedral mesh (typically 5).
          If None, all vertices will be used (potentially filling the
          surface). If a list, then values will be morphed to the set of
          vertices specified in in ``spacing[0]`` and ``spacing[1]``.
          This will be ignored if ``src_to`` is supplied.
  
          .. versionchanged:: 0.21
             src_to, if provided, takes precedence.
      smooth : int | str | None
          Number of iterations for the smoothing of the surface data.
          If None, smooth is automatically defined to fill the surface
          with non-zero values. Can also be ``'nearest'`` to use the nearest
          vertices on the surface.
  
          .. versionchanged:: 0.20
             Added support for 'nearest'.
      warn : bool
          If True, warn if not all vertices were used. The default is warn=True.
      xhemi : bool
          Morph across hemisphere. Currently only implemented for
          ``subject_to == subject_from``. See notes below.
          The default is xhemi=False.
      sparse : bool
          Morph as a sparse source estimate. Works only with (Vector)
          SourceEstimate. If True the only parameters used are subject_to and
          subject_from, and spacing has to be None. Default is sparse=False.
      src_to : instance of SourceSpaces | None
          The destination source space.
  
          - For surface-based morphing, this is the preferred over ``spacing``
            for providing the vertices.
          - For volumetric morphing, this should be passed so that 1) the
            resultingmorph volume is properly constrained to the brain volume,
            and 2) STCs from multiple subjects morphed to the same destination
            subject/source space have the vertices.
          - For mixed (surface + volume) morphing, this is required.
  
          .. versionadded:: 0.20
      precompute : bool
          If True (default False), compute the sparse matrix representation of
          the volumetric morph (if present). This takes a long time to
          compute, but can make morphs faster when thousands of points are used.
          See :meth:`mne.SourceMorph.compute_vol_morph_mat` (which can be called
          later if desired) for more information.
  
          .. versionadded:: 0.22
      %(verbose)s
  
      Returns
      -------
      morph : instance of SourceMorph
          The :class:`mne.SourceMorph` object.
  
      Notes
      -----
      This function can be used to morph surface data between hemispheres by
      setting ``xhemi=True``. The full cross-hemisphere morph matrix maps left
      to right and right to left. A matrix for cross-mapping only one hemisphere
      can be constructed by specifying the appropriate vertices, for example, to
      map the right hemisphere to the left::
  
          vertices_from=[[], vert_rh], vertices_to=[vert_lh, []]
  
      Cross-hemisphere mapping requires appropriate ``sphere.left_right``
      morph-maps in the subject's directory. These morph maps are included
      with the ``fsaverage_sym`` FreeSurfer subject, and can be created for other
      subjects with the ``mris_left_right_register`` FreeSurfer command. The
      ``fsaverage_sym`` subject is included with FreeSurfer > 5.1 and can be
      obtained as described `here
      <https://surfer.nmr.mgh.harvard.edu/fswiki/Xhemi>`_. For statistical
      comparisons between hemispheres, use of the symmetric ``fsaverage_sym``
      model is recommended to minimize bias :footcite:`GreveEtAl2013`.
  
      .. versionadded:: 0.17.0
  
      .. versionadded:: 0.21.0
         Support for morphing mixed source estimates.
  
      References
      ----------
      .. footbibliography::
      """
      src_data, kind, src_subject = _get_src_data(src)
      subject_from = _check_subject_src(subject_from, src_subject)
      del src
      _validate_type(src_to, (SourceSpaces, None), "src_to")
      _validate_type(subject_to, (str, None), "subject_to")
      if src_to is None and subject_to is None:
          raise ValueError(
              "subject_to cannot be None when src_to is None"
          )
      subject_to = _check_subject_src(subject_to, src_to, "subject_to")
  
      # Params
      warn = False if sparse else warn
  
      if kind not in "surface" and xhemi:
          raise ValueError(
              "Inter-hemispheric morphing can only be used "
              "with surface source estimates."
          )
      if sparse and kind != "surface":
          raise ValueError(
              "Only surface source estimates can compute a "
              "sparse morph."
          )
  
      subjects_dir = str(
          get_subjects_dir(subjects_dir, raise_error=True)
      )
      shape = affine = pre_affine = sdr_morph = morph_mat = None
      vertices_to_surf, vertices_to_vol = list(), list()
  
      if kind in ("volume", "mixed"):
          _check_dep(nibabel="2.1.0", dipy="0.10.1")
          nib = _import_nibabel("work with a volume source space")
  
          logger.info("Volume source space(s) present...")
  
          # load moving MRI
          mri_subpath = op.join("mri", "brain.mgz")
          mri_path_from = op.join(
              subjects_dir, subject_from, mri_subpath
          )
  
          logger.info('    Loading %s as "from" volume' % mri_path_from)
          with warnings.catch_warnings():
              mri_from = nib.load(mri_path_from)
  
          # eventually we could let this be some other volume, but for now
          # let's KISS and use `brain.mgz`, too
          mri_path_to = op.join(subjects_dir, subject_to, mri_subpath)
          if not op.isfile(mri_path_to):
              raise OSError("cannot read file: %s" % mri_path_to)
          logger.info('    Loading %s as "to" volume' % mri_path_to)
          with warnings.catch_warnings():
              mri_to = nib.load(mri_path_to)
  
          # deal with `src_to` subsampling
          zooms_src_to = None
          if src_to is None:
              if kind == "mixed":
                  raise ValueError(
                      "src_to must be provided when using a "
                      "mixed source space"
                  )
          else:
              surf_offset = 2 if src_to.kind == "mixed" else 0
              # All of our computations are in RAS (like img.affine), so we need
              # to get the transformation from RAS to the source space
              # subsampling of vox (src), not MRI (FreeSurfer surface RAS) to src
              src_ras_t = np.dot(
                  src_to[-1]["mri_ras_t"]["trans"],
                  src_to[-1]["src_mri_t"]["trans"],
              )
              src_ras_t[:3] *= 1e3
              src_data["to_vox_map"] = (src_to[-1]["shape"], src_ras_t)
              vertices_to_vol = [
                  s["vertno"] for s in src_to[surf_offset:]
              ]
              zooms_src_to = (
                  np.diag(src_to[-1]["src_mri_t"]["trans"])[:3] * 1000
              )
              zooms_src_to = tuple(zooms_src_to)
  
          # pre-compute non-linear morph
          zooms = _check_zooms(mri_from, zooms, zooms_src_to)
          (
              shape,
              zooms,
              affine,
              pre_affine,
              sdr_morph,
          ) = _compute_morph_sdr(
              mri_from, mri_to, niter_affine, niter_sdr, zooms
          )
  
      if kind in ("surface", "mixed"):
          logger.info("surface source space present ...")
          vertices_from = src_data["vertices_from"]
          if sparse:
              if spacing is not None:
                  raise ValueError(
                      "spacing must be set to None if " "sparse=True."
                  )
              if xhemi:
                  raise ValueError(
                      "xhemi=True can only be used with " "sparse=False"
                  )
              vertices_to_surf, morph_mat = _compute_sparse_morph(
                  vertices_from, subject_from, subject_to, subjects_dir
              )
          else:
              if src_to is not None:
                  assert src_to.kind in ("surface", "mixed")
                  vertices_to_surf = [
                      s["vertno"].copy() for s in src_to[:2]
                  ]
              else:
                  vertices_to_surf = grade_to_vertices(
                      subject_to, spacing, subjects_dir, 1
                  )
              morph_mat = _compute_morph_matrix(
                  subject_from=subject_from,
                  subject_to=subject_to,
                  vertices_from=vertices_from,
                  vertices_to=vertices_to_surf,
                  subjects_dir=subjects_dir,
                  smooth=smooth,
                  warn=warn,
                  xhemi=xhemi,
              )
              n_verts = sum(len(v) for v in vertices_to_surf)
              assert morph_mat.shape[0] == n_verts
  
      vertices_to = vertices_to_surf + vertices_to_vol
      if src_to is not None:
          assert len(vertices_to) == len(src_to)
      morph = SourceMorph(
          subject_from,
          subject_to,
          kind,
          zooms,
          niter_affine,
          niter_sdr,
          spacing,
          smooth,
          xhemi,
          morph_mat,
          vertices_to,
          shape,
          affine,
          pre_affine,
          sdr_morph,
          src_data,
          None,
      )
      if precompute:
          morph.compute_vol_morph_mat()
      logger.info("[done]")
      return morph
  
imports: import copy
  import os.path
  import warnings
  import numpy
  from scipy import sparse
  from .fixes import _get_img_fdata
  from .morph_map import read_morph_map
  from .parallel import parallel_func
  from .source_estimate import _BaseSourceEstimate, _BaseSurfaceSourceEstimate, _BaseVolSourceEstimate, _get_ico_tris
  from .source_space._source_space import SourceSpaces, _ensure_src, _grid_interp
  from .surface import _compute_nearest, mesh_edges, read_surface
  from .utils import BunchConst, ProgressBar, _check_fname, _check_option, _custom_lru_cache, _ensure_int, _import_h5io_funcs, _import_nibabel, _validate_type, check_version, fill_doc, get_subjects_dir, logger, use_log_level, verbose, warn
  from .utils import warn
label_desc: Use image node_id 1 for calling a global function with example usage: compute_source_morph(src, subject_from, subject_to, subjects_dir, zooms, niter_affine, niter_sdr, spacing, smooth, warn, xhemi, sparse, src_to, precompute, verbose) and returns: morph