code: def _assemble_kernel(
      inv, label, method, pick_ori, use_cps=True, verbose=None
  ):
      """Assemble the kernel.
  
      Simple matrix multiplication followed by combination of the current
      components. This does all the data transformations to compute the weights
      for the eigenleads.
  
      Parameters
      ----------
      inv : instance of InverseOperator
          The inverse operator to use. This object contains the matrices that
          will be multiplied to assemble the kernel.
      label : Label | None
          Restricts the source estimates to a given label. If None,
          source estimates will be computed for the entire source space.
      method : "MNE" | "dSPM" | "sLORETA" | "eLORETA"
          Use minimum norm, dSPM, sLORETA, or eLORETA.
      pick_ori : None | "normal" | "vector"
          Which orientation to pick (only matters in the case of 'normal').
      %(use_cps_restricted)s
  
      Returns
      -------
      K : array, shape (n_vertices, n_channels) | (3 * n_vertices, n_channels)
          The kernel matrix. Multiply this with the data to obtain the source
          estimate.
      noise_norm : array, shape (n_vertices, n_samples) | (3 * n_vertices, n_samples)
          Normalization to apply to the source estimate in order to obtain dSPM
          or sLORETA solutions.
      vertices : list of length 2
          Vertex numbers for lh and rh hemispheres that correspond to the
          vertices in the source estimate. When the label parameter has been
          set, these correspond to the vertices in the label. Otherwise, all
          vertex numbers are returned.
      source_nn : array, shape (3 * n_vertices, 3)
          The direction in cartesian coordicates of the direction of the source
          dipoles.
      """  # noqa: E501
      eigen_leads = inv["eigen_leads"]["data"]
      source_cov = inv["source_cov"]["data"]
      if method in ("dSPM", "sLORETA"):
          noise_norm = inv["noisenorm"][:, np.newaxis]
      else:
          noise_norm = None
  
      src = inv["src"]
      vertno = _get_vertno(src)
      source_nn = inv["source_nn"]
  
      if label is not None:
          vertno, src_sel = label_src_vertno_sel(label, src)
  
          if method not in ["MNE", "eLORETA"]:
              noise_norm = noise_norm[src_sel]
  
          if inv["source_ori"] == FIFF.FIFFV_MNE_FREE_ORI:
              src_sel = 3 * src_sel
              src_sel = np.c_[src_sel, src_sel + 1, src_sel + 2]
              src_sel = src_sel.ravel()
  
          eigen_leads = eigen_leads[src_sel]
          source_cov = source_cov[src_sel]
          source_nn = source_nn[src_sel]
  
      # vector or normal, might need to rotate
      if (
          pick_ori == "normal"
          and all(s["type"] == "surf" for s in src)
          and np.allclose(
              inv["source_nn"].reshape(inv["nsource"], 3, 3),
              np.eye(3),
              atol=1e-6,
          )
      ):
          offset = 0
          eigen_leads = np.reshape(
              eigen_leads, (-1, 3, eigen_leads.shape[1])
          ).copy()
          source_nn = np.reshape(source_nn, (-1, 3, 3)).copy()
          for s, v in zip(src, vertno):
              sl = slice(offset, offset + len(v))
              source_nn[sl] = _normal_orth(_get_src_nn(s, use_cps, v))
              eigen_leads[sl] = np.matmul(
                  source_nn[sl], eigen_leads[sl]
              )
              # No need to rotate source_cov because it should be uniform
              # (loose=1., and depth weighting is uniform across columns)
              offset = sl.stop
          eigen_leads.shape = (-1, eigen_leads.shape[2])
          source_nn.shape = (-1, 3)
  
      if pick_ori == "normal":
          if not inv["source_ori"] == FIFF.FIFFV_MNE_FREE_ORI:
              raise ValueError(
                  "Picking normal orientation can only be done "
                  "with a free orientation inverse operator."
              )
  
          is_loose = 0 < inv["orient_prior"]["data"][0] <= 1
          if not is_loose:
              raise ValueError(
                  "Picking normal orientation can only be done "
                  "when working with loose orientations."
              )
  
      trans = np.dot(
          inv["eigen_fields"]["data"],
          np.dot(inv["whitener"], inv["proj"]),
      )
      trans *= inv["reginv"][:, None]
  
      #
      #   Transformation into current distributions by weighting the eigenleads
      #   with the weights computed above
      #
      K = np.dot(eigen_leads, trans)
      if inv["eigen_leads_weighted"]:
          #
          #     R^0.5 has been already factored in
          #
          logger.info("    Eigenleads already weighted ... ")
      else:
          #
          #     R^0.5 has to be factored in
          #
          logger.info("    Eigenleads need to be weighted ...")
          K *= np.sqrt(source_cov)[:, np.newaxis]
  
      if pick_ori == "normal":
          K = K[2::3]
  
      return K, noise_norm, vertno, source_nn
  
imports: from copy import deepcopy
  from math import sqrt
  import numpy
  from scipy import linalg
  from scipy.stats import chi2
  from .._fiff.constants import FIFF
  from .._fiff.matrix import _read_named_matrix, _transpose_named_matrix, write_named_matrix
  from .._fiff.open import fiff_open
  from .._fiff.pick import channel_type, pick_channels, pick_info, pick_types
  from .._fiff.proj import _electrode_types, _needs_eeg_average_ref_proj, _read_proj, _write_proj, make_projector
  from .._fiff.tag import find_tag
  from .._fiff.tree import dir_tree_find
  from .._fiff.write import end_block, start_and_end_file, start_block, write_coord_trans, write_float, write_float_matrix, write_int, write_string
  from ..cov import Covariance, _read_cov, _write_cov, compute_whitener, prepare_noise_cov
  from ..epochs import BaseEpochs, EpochsArray
  from ..evoked import Evoked, EvokedArray
  from ..fixes import _safe_svd
  from ..forward import _read_forward_meas_info, _select_orient_forward, compute_depth_prior, compute_orient_prior, convert_forward_solution, is_fixed_orient
  from ..forward.forward import _triage_loose, write_forward_meas_info
  from ..html_templates import _get_html_template
  from ..io import BaseRaw
  from ..source_estimate import _get_src_type, _make_stc
  from ..source_space._source_space import _get_src_nn, _get_vertno, _read_source_spaces_from_tree, _write_source_spaces_to_fid, find_source_space_hemi, label_src_vertno_sel
  from ..surface import _normal_orth
  from ..time_frequency.tfr import _check_tfr_complex
  from ..transforms import _ensure_trans, transform_surface_to
  from ..utils import _check_compensation_grade, _check_depth, _check_fname, _check_option, _check_src_normal, _validate_type, _verbose_safe_false, check_fname, logger, repr_html, verbose, warn
  from ._eloreta import _compute_eloreta
label_desc: Use image node_id 9 for calling a global function with example usage: _assemble_kernel(inv, label, method, pick_ori, use_cps, verbose) and returns: K,  noise_norm,  vertno,  source_nn