code: def convert_forward_solution(
      fwd,
      surf_ori=False,
      force_fixed=False,
      copy=True,
      use_cps=True,
      *,
      verbose=None,
  ):
      """Convert forward solution between different source orientations.
  
      Parameters
      ----------
      fwd : Forward
          The forward solution to modify.
      surf_ori : bool, optional (default False)
          Use surface-based source coordinate system? Note that force_fixed=True
          implies surf_ori=True.
      force_fixed : bool, optional (default False)
          If True, force fixed source orientation mode.
      copy : bool
          Whether to return a new instance or modify in place.
      %(use_cps)s
      %(verbose)s
  
      Returns
      -------
      fwd : Forward
          The modified forward solution.
      """
      fwd = fwd.copy() if copy else fwd
  
      if force_fixed is True:
          surf_ori = True
  
      if (
          any([src["type"] == "vol" for src in fwd["src"]])
          and force_fixed
      ):
          raise ValueError(
              "Forward operator was generated with sources from a "
              "volume source space. Conversion to fixed orientation is not "
              "possible. Consider using a discrete source space if you have "
              "meaningful normal orientations."
          )
  
      if surf_ori and use_cps:
          if any(s.get("patch_inds") is not None for s in fwd["src"]):
              logger.info(
                  "    Average patch normals will be employed in "
                  "the rotation to the local surface coordinates.."
                  ".."
              )
          else:
              use_cps = False
              logger.info(
                  "    No patch info available. The standard source "
                  "space normals will be employed in the rotation "
                  "to the local surface coordinates...."
              )
  
      # We need to change these entries (only):
      # 1. source_nn
      # 2. sol['data']
      # 3. sol['ncol']
      # 4. sol_grad['data']
      # 5. sol_grad['ncol']
      # 6. source_ori
  
      if is_fixed_orient(fwd, orig=True) or (
          force_fixed and not use_cps
      ):
          # Fixed
          fwd["source_nn"] = np.concatenate(
              [_get_src_nn(s, use_cps) for s in fwd["src"]], axis=0
          )
          if not is_fixed_orient(fwd, orig=True):
              logger.info(
                  "    Changing to fixed-orientation forward "
                  "solution with surface-based source orientations..."
              )
              fix_rot = _block_diag(fwd["source_nn"].T, 1)
              # newer versions of numpy require explicit casting here, so *= no
              # longer works
              fwd["sol"]["data"] = (fwd["_orig_sol"] * fix_rot).astype(
                  "float32"
              )
              fwd["sol"]["ncol"] = fwd["nsource"]
              if fwd["sol_grad"] is not None:
                  x = sparse.block_diag([fix_rot] * 3)
                  fwd["sol_grad"]["data"] = (
                      fwd["_orig_sol_grad"] * x
                  )  # dot prod
                  fwd["sol_grad"]["ncol"] = 3 * fwd["nsource"]
          fwd["source_ori"] = FIFF.FIFFV_MNE_FIXED_ORI
          fwd["surf_ori"] = True
  
      elif surf_ori:  # Free, surf-oriented
          #   Rotate the local source coordinate systems
          fwd["source_nn"] = np.kron(
              np.ones((fwd["nsource"], 1)), np.eye(3)
          )
          logger.info(
              "    Converting to surface-based source orientations..."
          )
          #   Actually determine the source orientations
          pp = 0
          for s in fwd["src"]:
              if s["type"] in ["surf", "discrete"]:
                  nn = _get_src_nn(s, use_cps)
                  stop = pp + 3 * s["nuse"]
                  fwd["source_nn"][pp:stop] = _normal_orth(nn).reshape(
                      -1, 3
                  )
                  pp = stop
                  del nn
              else:
                  pp += 3 * s["nuse"]
  
          #   Rotate the solution components as well
          if force_fixed:
              fwd["source_nn"] = fwd["source_nn"][2::3, :]
              fix_rot = _block_diag(fwd["source_nn"].T, 1)
              # newer versions of numpy require explicit casting here, so *= no
              # longer works
              fwd["sol"]["data"] = (fwd["_orig_sol"] * fix_rot).astype(
                  "float32"
              )
              fwd["sol"]["ncol"] = fwd["nsource"]
              if fwd["sol_grad"] is not None:
                  x = sparse.block_diag([fix_rot] * 3)
                  fwd["sol_grad"]["data"] = (
                      fwd["_orig_sol_grad"] * x
                  )  # dot prod
                  fwd["sol_grad"]["ncol"] = 3 * fwd["nsource"]
              fwd["source_ori"] = FIFF.FIFFV_MNE_FIXED_ORI
              fwd["surf_ori"] = True
          else:
              surf_rot = _block_diag(fwd["source_nn"].T, 3)
              fwd["sol"]["data"] = fwd["_orig_sol"] * surf_rot
              fwd["sol"]["ncol"] = 3 * fwd["nsource"]
              if fwd["sol_grad"] is not None:
                  x = sparse.block_diag([surf_rot] * 3)
                  fwd["sol_grad"]["data"] = (
                      fwd["_orig_sol_grad"] * x
                  )  # dot prod
                  fwd["sol_grad"]["ncol"] = 9 * fwd["nsource"]
              fwd["source_ori"] = FIFF.FIFFV_MNE_FREE_ORI
              fwd["surf_ori"] = True
  
      else:  # Free, cartesian
          logger.info("    Cartesian source orientations...")
          fwd["source_nn"] = np.tile(np.eye(3), (fwd["nsource"], 1))
          fwd["sol"]["data"] = fwd["_orig_sol"].copy()
          fwd["sol"]["ncol"] = 3 * fwd["nsource"]
          if fwd["sol_grad"] is not None:
              fwd["sol_grad"]["data"] = fwd["_orig_sol_grad"].copy()
              fwd["sol_grad"]["ncol"] = 9 * fwd["nsource"]
          fwd["source_ori"] = FIFF.FIFFV_MNE_FREE_ORI
          fwd["surf_ori"] = False
  
      logger.info("    [done]")
  
      return fwd
  
imports: import os
  import re
  import shutil
  import tempfile
  from copy import deepcopy
  from os import PathLike
  from os import path
  from pathlib import Path
  from time import time
  import numpy
  from scipy import sparse
  from .._fiff.constants import FIFF
  from .._fiff.matrix import _read_named_matrix, _transpose_named_matrix, write_named_matrix
  from .._fiff.meas_info import Info, _make_ch_names_mapping, _read_bad_channels, _read_extended_ch_info, _write_bad_channels, _write_ch_infos, write_info
  from .._fiff.open import fiff_open
  from .._fiff.pick import pick_channels, pick_channels_forward, pick_info, pick_types
  from .._fiff.tag import find_tag, read_tag
  from .._fiff.tree import dir_tree_find
  from .._fiff.write import end_block, start_and_end_file, start_block, write_coord_trans, write_id, write_int, write_string
  from ..epochs import BaseEpochs
  from ..evoked import Evoked, EvokedArray
  from ..html_templates import _get_html_template
  from ..io import BaseRaw, RawArray
  from ..label import Label
  from ..source_estimate import _BaseSourceEstimate, _BaseVectorSourceEstimate
  from ..source_space._source_space import _get_src_nn, _read_source_spaces_from_tree, _set_source_space_vertices, _src_kind_dict, _write_source_spaces_to_fid, find_source_space_hemi
  from ..surface import _normal_orth
  from ..transforms import invert_transform, transform_surface_to, write_trans
  from ..utils import _check_compensation_grade, _check_fname, _check_option, _check_stc_units, _import_h5io_funcs, _on_missing, _stamp_to_dt, _validate_type, check_fname, fill_doc, get_subjects_dir, has_mne_c, logger, repr_html, run_subprocess, verbose, warn
label_desc: Use image node_id 8 for calling a global function with example usage: convert_forward_solution(fwd, surf_ori, force_fixed, copy, use_cps) and returns: fwd