class_docstr: Morph source space data from one subject to another.
  
  .. note::
      This class should not be instantiated directly via
      ``mne.SourceMorph(...)``. Instead, use one of the functions
      listed in the See Also section below.
  
  Parameters
  ----------
  subject_from : str | None
      Name of the subject from which to morph as named in the SUBJECTS_DIR.
  subject_to : str | array | list of array
      Name of the subject on which to morph as named in the SUBJECTS_DIR.
      The default is 'fsaverage'. If morphing a volume source space,
      subject_to can be the path to a MRI volume. Can also be a list of
      two arrays if morphing to hemisphere surfaces.
  kind : str | None
      Kind of source estimate. E.g. ``'volume'`` or ``'surface'``.
  zooms : float | tuple
      See :func:`mne.compute_source_morph`.
  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.
  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 :footcite:`AvantsEtAl2008`.
  spacing : int | list | None
      See :func:`mne.compute_source_morph`.
  smooth : int | str | None
      See :func:`mne.compute_source_morph`.
  xhemi : bool
      Morph across hemisphere.
  morph_mat : scipy.sparse.csr_matrix
      The sparse surface morphing matrix for spherical surface
      based morphing :footcite:`GreveEtAl2013`.
  vertices_to : list of ndarray
      The destination surface vertices.
  shape : tuple
      The volume MRI shape.
  affine : ndarray
      The volume MRI affine.
  pre_affine : instance of dipy.align.AffineMap
      The transformation that is applied before the before ``sdr_morph``.
  sdr_morph : instance of dipy.align.DiffeomorphicMap
      The class that applies the the symmetric diffeomorphic registration
      (SDR) morph.
  src_data : dict
      Additional source data necessary to perform morphing.
  vol_morph_mat : scipy.sparse.csr_matrix | None
      The volumetric morph matrix, if :meth:`compute_vol_morph_mat`
      was used.
  %(verbose)s
  
  See Also
  --------
  compute_source_morph
  read_source_morph
  
  Notes
  -----
  .. versionadded:: 0.17
  
  References
  ----------
  .. footbibliography::
class_docstr_tok: ["Morph","source","space","data","from","one","subject","to","another",".","..","note",":",":","This","class","should","not","be","instantiated","directly","via","``","mne.SourceMorph","(","...",")","``",".","Instead",",","use","one","of","the","functions","listed","in","the","See","Also","section","below",".","Parameters","--","--","--","--","--","subject_from",":","str","|","None","Name","of","the","subject","from","which","to","morph","as","named","in","the","SUBJECTS_DIR",".","subject_to",":","str","|","array","|","list","of","array","Name","of","the","subject","on","which","to","morph","as","named","in","the","SUBJECTS_DIR",".","The","default","is","'fsaverage","'",".","If","morphing","a","volume","source","space",",","subject_to","can","be","the","path","to","a","MRI","volume",".","Can","also","be","a","list","of","two","arrays","if","morphing","to","hemisphere","surfaces",".","kind",":","str","|","None","Kind","of","source","estimate",".","E.g",".","``","'volume","'","``","or","``","'surface","'","``",".","zooms",":","float","|","tuple","See",":","func",":","`","mne.compute_source_morph","`",".","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",".","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",":","footcite",":","`","AvantsEtAl2008","`",".","spacing",":","int","|","list","|","None","See",":","func",":","`","mne.compute_source_morph","`",".","smooth",":","int","|","str","|","None","See",":","func",":","`","mne.compute_source_morph","`",".","xhemi",":","bool","Morph","across","hemisphere",".","morph_mat",":","scipy.sparse.csr_matrix","The","sparse","surface","morphing","matrix","for","spherical","surface","based","morphing",":","footcite",":","`","GreveEtAl2013","`",".","vertices_to",":","list","of","ndarray","The","destination","surface","vertices",".","shape",":","tuple","The","volume","MRI","shape",".","affine",":","ndarray","The","volume","MRI","affine",".","pre_affine",":","instance","of","dipy.align.AffineMap","The","transformation","that","is","applied","before","the","before","``","sdr_morph","``",".","sdr_morph",":","instance","of","dipy.align.DiffeomorphicMap","The","class","that","applies","the","the","symmetric","diffeomorphic","registration","(","SDR",")","morph",".","src_data",":","dict","Additional","source","data","necessary","to","perform","morphing",".","vol_morph_mat",":","scipy.sparse.csr_matrix","|","None","The","volumetric","morph","matrix",",","if",":","meth",":","`","compute_vol_morph_mat","`","was","used",".","%","(","verbose",")","s","See","Also","--","--","--","--","compute_source_morph","read_source_morph","Notes","--","--","-","..","versionadded",":",":","0.17","References","--","--","--","--","--","..","footbibliography",":",":"]
code: def _morph_vols(self, vols, mesg, subselect=True):
      from dipy.align.reslice import reslice
  
      interp = self.src_data["interpolator"].tocsc()[
          :, np.concatenate(self._vol_vertices_from)
      ]
      n_vols = interp.shape[1] if vols is None else vols.shape[1]
      attrs = ("real", "imag") if np.iscomplexobj(vols) else ("real",)
      dtype = np.complex128 if len(attrs) == 2 else np.float64
      if vols is None:  # sparse -> sparse mode
          img_to = (list(), list(), [0])  # data, indices, indptr
          assert subselect
      else:  # dense -> dense mode
          img_to = None
      if subselect:
          vol_verts = np.concatenate(self._vol_vertices_to)
      else:
          vol_verts = slice(None)
      # morph data
      from_affine = np.dot(
          self.src_data["src_affine_ras"],  # mri_ras_t
          self.src_data["src_affine_vox"],
      )  # vox_mri_t
      from_affine[:3] *= 1000.0
      # equivalent of:
      # _resample_from_to(img_real, from_affine,
      #                   (self.pre_affine.codomain_shape,
      #                   (self.pre_affine.codomain_grid2world))
      src_shape = self.src_data["src_shape_full"][::-1]
      resamp_0 = _grid_interp(
          src_shape,
          self.pre_affine.codomain_shape,
          np.linalg.inv(from_affine)
          @ self.pre_affine.codomain_grid2world,
      )
      # reslice to match what was used during the morph
      # (brain.mgz and whatever was used to create the source space
      #  will not necessarily have the same domain/zooms)
      # equivalent of:
      # pre_affine.transform(img_real)
      resamp_1 = _grid_interp(
          self.pre_affine.codomain_shape,
          self.pre_affine.domain_shape,
          np.linalg.inv(self.pre_affine.codomain_grid2world)
          @ self.pre_affine.affine
          @ self.pre_affine.domain_grid2world,
      )
      resamp_0_1 = resamp_1 @ resamp_0
      resamp_2 = None
      for ii in ProgressBar(list(range(n_vols)), mesg=mesg):
          for attr in attrs:
              # transform from source space to mri_from resolution/space
              if vols is None:
                  img_real = interp[:, ii]
              else:
                  img_real = interp @ getattr(vols[:, ii], attr)
              _debug_img(img_real, from_affine, "From", src_shape)
  
              img_real = resamp_0_1 @ img_real
              if sparse.issparse(img_real):
                  img_real = img_real.toarray()
              img_real = img_real.reshape(
                  self.pre_affine.domain_shape, order="F"
              )
              if self.sdr_morph is not None:
                  img_real = self.sdr_morph.transform(img_real)
              _debug_img(
                  img_real, self.affine, "From-reslice-transform"
              )
  
              # subselect the correct cube if src_to is provided
              if self.src_data["to_vox_map"] is not None:
                  affine = self.affine
                  to_zooms = np.diag(self.src_data["to_vox_map"][1])[:3]
                  # There might be some sparse equivalent to this but
                  # not sure...
                  if not np.allclose(self.zooms, to_zooms, atol=1e-3):
                      img_real, affine = reslice(
                          img_real, self.affine, self.zooms, to_zooms
                      )
                  _debug_img(
                      img_real, affine, "From-reslice-transform-src"
                  )
                  if resamp_2 is None:
                      resamp_2 = _grid_interp(
                          img_real.shape,
                          self.src_data["to_vox_map"][0],
                          np.linalg.inv(affine)
                          @ self.src_data["to_vox_map"][1],
                      )
                  # Equivalent to:
                  # _resample_from_to(
                  #     img_real, affine, self.src_data['to_vox_map'])
                  img_real = resamp_2 @ img_real.ravel(order="F")
                  _debug_img(
                      img_real,
                      self.src_data["to_vox_map"][1],
                      "From-reslice-transform-src-subselect",
                      self.src_data["to_vox_map"][0],
                  )
  
              # This can be used to help debug, but it really should just
              # show the brain filling the volume:
              # img_want = np.zeros(np.prod(img_real.shape))
              # img_want[np.concatenate(self._vol_vertices_to)] = 1.
              # img_want = np.reshape(
              #     img_want, self.src_data['src_shape'][::-1], order='F')
              # _debug_img(img_want, self.src_data['to_vox_map'][1],
              #            'To mask')
              # raise RuntimeError('Check')
  
              # combine real and complex parts
              img_real = img_real.ravel(order="F")[vol_verts]
  
              # initialize output
              if img_to is None and vols is not None:
                  img_to = np.zeros(
                      (img_real.size, n_vols), dtype=dtype
                  )
  
              if vols is None:
                  idx = np.where(img_real)[0]
                  img_to[0].extend(img_real[idx])
                  img_to[1].extend(idx)
                  img_to[2].append(img_to[2][-1] + len(idx))
              else:
                  if attr == "real":
                      img_to[:, ii] = img_to[:, ii] + img_real
                  else:
                      img_to[:, ii] = img_to[:, ii] + 1j * img_real
  
      if vols is None:
          img_to = sparse.csc_matrix(
              img_to, shape=(len(vol_verts), n_vols)
          ).tocsr()
  
      return img_to
  
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 7 for calling the SourceMorph obj's underlying member method code with example usage: obj._morph_vols(vols, mesg, subselect) and returns: img_to