code: def test_volume_source_morph_round_trip(
      tmp_path,
      subject_from,
      subject_to,
      lower,
      upper,
      dtype,
      morph_mat,
      monkeypatch,
  ):
      """Test volume source estimate morph round-trips well."""
      nib = pytest.importorskip("nibabel")
      pytest.importorskip("h5io")
      pytest.importorskip("dipy")
      from nibabel.processing import resample_from_to
  
      src = dict()
      if morph_mat:
          # ~1.5 minutes with pos=7. (4157 morphs!) for sample, so only test
          # morph_mat computation mode with a few labels
          label_names = sorted(get_volume_labels_from_aseg(fname_aseg))[
              1:2
          ]
          if "sample" in (subject_from, subject_to):
              src["sample"] = setup_volume_source_space(
                  "sample",
                  subjects_dir=subjects_dir,
                  volume_label=label_names,
                  mri=fname_aseg,
              )
              assert sum(s["nuse"] for s in src["sample"]) == 12
          if "fsaverage" in (subject_from, subject_to):
              src["fsaverage"] = setup_volume_source_space(
                  "fsaverage",
                  subjects_dir=subjects_dir,
                  volume_label=label_names[:3],
                  mri=fname_aseg_fs,
              )
              assert sum(s["nuse"] for s in src["fsaverage"]) == 16
      else:
          assert not morph_mat
          if "sample" in (subject_from, subject_to):
              src["sample"] = mne.read_source_spaces(fname_vol)
              src["sample"][0]["subject_his_id"] = "sample"
              assert src["sample"][0]["nuse"] == 4157
          if "fsaverage" in (subject_from, subject_to):
              # Created to save space with:
              #
              # bem = op.join(op.dirname(mne.__file__), 'data', 'fsaverage',
              #               'fsaverage-inner_skull-bem.fif')
              # src_fsaverage = mne.setup_volume_source_space(
              #     'fsaverage', pos=7., bem=bem, mindist=0,
              #     subjects_dir=subjects_dir, add_interpolator=False)
              # mne.write_source_spaces(fname_fs_vol, src_fsaverage,
              #                         overwrite=True)
              #
              # For speed we do it without the interpolator because it's huge.
              src["fsaverage"] = mne.read_source_spaces(fname_fs_vol)
              src["fsaverage"][0].update(
                  vol_dims=np.array([23, 29, 25]), seg_name="brain"
              )
              _add_interpolator(src["fsaverage"])
              assert src["fsaverage"][0]["nuse"] == 6379
      src_to, src_from = src[subject_to], src[subject_from]
      del src
      # No SDR just for speed once everything works
      kwargs = dict(
          niter_sdr=(),
          niter_affine=(1,),
          subjects_dir=subjects_dir,
          verbose=True,
      )
      morph_from_to = compute_source_morph(
          src=src_from, src_to=src_to, subject_to=subject_to, **kwargs
      )
      morph_to_from = compute_source_morph(
          src=src_to, src_to=src_from, subject_to=subject_from, **kwargs
      )
      nuse = sum(s["nuse"] for s in src_from)
      assert nuse > 10
      use = np.linspace(0, nuse - 1, 10).round().astype(int)
      data = np.eye(nuse)[:, use]
      if dtype is complex:
          data = data * 1j
      vertices = [s["vertno"] for s in src_from]
      stc_from = VolSourceEstimate(data, vertices, 0, 1)
      with catch_logging() as log:
          stc_from_rt = morph_to_from.apply(
              morph_from_to.apply(stc_from, verbose="debug")
          )
      log = log.getvalue()
      assert "individual volume morph" in log
      maxs = np.argmax(stc_from_rt.data, axis=0)
      src_rr = np.concatenate([s["rr"][s["vertno"]] for s in src_from])
      dists = 1000 * np.linalg.norm(src_rr[use] - src_rr[maxs], axis=1)
      mu = np.mean(dists)
      # fsaverage=5.99; 7.97 without additional src_ras_t fix
      # fsaverage=7.97; 25.4 without src_ras_t fix
      assert lower <= mu < upper, f"round-trip distance {mu}"
      # check that pre_affine is close to identity when subject_to==subject_from
      if subject_to == subject_from:
          for morph in (morph_to_from, morph_from_to):
              assert_allclose(
                  morph.pre_affine.affine, np.eye(4), atol=1e-2
              )
      # check that power is more or less preserved (labelizing messes with this)
      if morph_mat:
          if subject_to == "fsaverage":
              limits = (18, 18.5)
          else:
              limits = (7, 7.5)
      else:
          limits = (1, 1.2)
      stc_from_unit = stc_from.copy().crop(0, 0)
      stc_from_unit._data.fill(1.0)
      stc_from_unit_rt = morph_to_from.apply(
          morph_from_to.apply(stc_from_unit)
      )
      assert_power_preserved(
          stc_from_unit, stc_from_unit_rt, limits=limits
      )
      if morph_mat:
          fname = tmp_path / "temp-morph.h5"
          morph_to_from.save(fname)
          morph_to_from = read_source_morph(fname)
          assert morph_to_from.vol_morph_mat is None
          morph_to_from.compute_vol_morph_mat(verbose=True)
          morph_to_from.save(fname, overwrite=True)
          morph_to_from = read_source_morph(fname)
          assert isinstance(
              morph_to_from.vol_morph_mat, csr_matrix
          ), "csr"
          # equivalence (plus automatic calling)
          assert morph_from_to.vol_morph_mat is None
          monkeypatch.setattr(mne.morph, "_VOL_MAT_CHECK_RATIO", 0.0)
          with catch_logging() as log:
              with pytest.warns(
                  RuntimeWarning, match=r"calling morph\.compute"
              ):
                  stc_from_rt_lin = morph_to_from.apply(
                      morph_from_to.apply(stc_from, verbose="debug")
                  )
          assert isinstance(
              morph_from_to.vol_morph_mat, csr_matrix
          ), "csr"
          log = log.getvalue()
          assert "sparse volume morph matrix" in log
          assert_allclose(stc_from_rt.data, stc_from_rt_lin.data)
          del stc_from_rt_lin
          stc_from_unit_rt_lin = morph_to_from.apply(
              morph_from_to.apply(stc_from_unit)
          )
          assert_allclose(
              stc_from_unit_rt.data, stc_from_unit_rt_lin.data
          )
          del stc_from_unit_rt_lin
      del stc_from, stc_from_rt
      # before and after morph, check the proportion of vertices
      # that are inside and outside the brainmask.mgz
      brain = nib.load(
          subjects_dir / subject_from / "mri" / "brain.mgz"
      )
      mask = _get_img_fdata(brain) > 0
      if subject_from == subject_to == "sample":
          for stc in [stc_from_unit, stc_from_unit_rt]:
              img = stc.as_volume(src_from, mri_resolution=True)
              img = nib.Nifti1Image(  # abs to convert complex
                  np.abs(_get_img_fdata(img)[:, :, :, 0]), img.affine
              )
              img = _get_img_fdata(
                  resample_from_to(img, brain, order=1)
              )
              assert img.shape == mask.shape
              in_ = img[mask].astype(bool).mean()
              out = img[~mask].astype(bool).mean()
              if morph_mat:
                  out_max = 0.001
                  in_min, in_max = 0.005, 0.007
              else:
                  out_max = 0.02
                  in_min, in_max = 0.97, 0.98
              assert out < out_max, f"proportion out of volume {out}"
              assert (
                  in_min < in_ < in_max
              ), f"proportion inside volume {in_}"
  
imports: from inspect import signature
  import numpy
  import pytest
  from numpy.testing import assert_allclose, assert_array_equal, assert_array_less
  from scipy.sparse import csr_matrix
  from scipy.sparse import eye
  from scipy.spatial.distance import cdist
  import mne
  from mne import SourceEstimate, SourceMorph, VectorSourceEstimate, VolSourceEstimate, VolVectorSourceEstimate, compute_source_morph, get_volume_labels_from_aseg, grade_to_vertices, make_ad_hoc_cov, make_forward_solution, make_sphere_model, read_evokeds, read_forward_solution, read_freesurfer_lut, read_source_estimate, read_source_morph, setup_volume_source_space
  from mne._freesurfer import _get_atlas_values, _get_mri_info_data
  from mne.datasets import testing
  from mne.fixes import _get_img_fdata
  from mne.minimum_norm import apply_inverse, make_inverse_operator, read_inverse_operator
  from mne.source_space._source_space import _add_interpolator, _grid_interp
  from mne.transforms import quat_to_rot
  from mne.utils import _record_warnings, catch_logging
label_desc: Use image node_id 10 for calling a global function with example usage: test_volume_source_morph_round_trip(tmp_path, subject_from, subject_to, lower, upper, dtype, morph_mat, monkeypatch) without return types