code: def _apply_rap_music(
      data,
      info,
      times,
      forward,
      noise_cov,
      n_dipoles=2,
      picks=None,
      use_trap=False,
  ):
      """RAP-MUSIC or TRAP-MUSIC for evoked data.
  
      Parameters
      ----------
      data : array, shape (n_channels, n_times)
          Evoked data.
      %(info_not_none)s
      times : array
          Times.
      forward : instance of Forward
          Forward operator.
      noise_cov : instance of Covariance
          The noise covariance.
      n_dipoles : int
          The number of dipoles to estimate. The default value is 2.
      picks : list of int
          Caller ensures this is a list of int.
      use_trap : bool
          Use the TRAP-MUSIC variant if True (default False).
  
      Returns
      -------
      dipoles : list of instances of Dipole
          The dipole fits.
      explained_data : array | None
          Data explained by the dipoles using a least square fitting with the
          selected active dipoles and their estimated orientation.
      """
      info = pick_info(info, picks)
      del picks
      # things are much simpler if we avoid surface orientation
      align = forward["source_nn"].copy()
      if forward["surf_ori"] and not is_fixed_orient(forward):
          forward = convert_forward_solution(forward, surf_ori=False)
      (
          is_free_ori,
          info,
          _,
          _,
          G,
          whitener,
          _,
          _,
      ) = _prepare_beamformer_input(
          info, forward, noise_cov=noise_cov, rank=None
      )
      forward = pick_channels_forward(
          forward, info["ch_names"], ordered=True
      )
      del info
  
      # whiten the data (leadfield already whitened)
      M = np.dot(whitener, data)
      del data
  
      _, eig_vectors = linalg.eigh(np.dot(M, M.T))
      phi_sig = eig_vectors[:, -n_dipoles:]
  
      n_orient = 3 if is_free_ori else 1
      G.shape = (G.shape[0], -1, n_orient)
      gain = forward["sol"]["data"].copy()
      gain.shape = G.shape
      n_channels = G.shape[0]
      A = np.empty((n_channels, n_dipoles))
      gain_dip = np.empty((n_channels, n_dipoles))
      oris = np.empty((n_dipoles, 3))
      poss = np.empty((n_dipoles, 3))
  
      G_proj = G.copy()
      phi_sig_proj = phi_sig.copy()
  
      idxs = list()
      for k in range(n_dipoles):
          subcorr_max = -1.0
          source_idx, source_ori, source_pos = 0, [0, 0, 0], [0, 0, 0]
          for i_source in range(G.shape[1]):
              Gk = G_proj[:, i_source]
              subcorr, ori = _compute_subcorr(Gk, phi_sig_proj)
              if subcorr > subcorr_max:
                  subcorr_max = subcorr
                  source_idx = i_source
                  source_ori = ori
                  source_pos = forward["source_rr"][i_source]
                  if n_orient == 3 and align is not None:
                      surf_normal = forward["source_nn"][
                          3 * i_source + 2
                      ]
                      # make sure ori is aligned to the surface orientation
                      source_ori *= (
                          np.sign(source_ori @ surf_normal) or 1.0
                      )
                  if n_orient == 1:
                      source_ori = forward["source_nn"][i_source]
  
          idxs.append(source_idx)
          if n_orient == 3:
              Ak = np.dot(G[:, source_idx], source_ori)
          else:
              Ak = G[:, source_idx, 0]
          A[:, k] = Ak
          oris[k] = source_ori
          poss[k] = source_pos
  
          logger.info(f"source {k + 1} found: p = {source_idx}")
          if n_orient == 3:
              logger.info("ori = {} {} {}".format(*tuple(oris[k])))
  
          projection = _compute_proj(A[:, : k + 1])
          G_proj = np.einsum("ab,bso->aso", projection, G)
          phi_sig_proj = np.dot(projection, phi_sig)
          if use_trap:
              phi_sig_proj = phi_sig_proj[:, -(n_dipoles - k) :]
      del G, G_proj
  
      sol = linalg.lstsq(A, M)[0]
      if n_orient == 3:
          X = sol[:, np.newaxis] * oris[:, :, np.newaxis]
          X.shape = (-1, len(times))
      else:
          X = sol
  
      gain_active = gain[:, idxs]
      if n_orient == 3:
          gain_dip = (oris * gain_active).sum(-1)
          idxs = np.array(idxs)
          active_set = np.array(
              [[3 * idxs, 3 * idxs + 1, 3 * idxs + 2]]
          ).T.ravel()
      else:
          gain_dip = gain_active[:, :, 0]
          active_set = idxs
      gain_active = whitener @ gain_active.reshape(gain.shape[0], -1)
      assert gain_active.shape == (n_channels, X.shape[0])
  
      explained_data = gain_dip @ sol
      M_estimate = whitener @ explained_data
      _log_exp_var(M, M_estimate)
      tstep = np.median(np.diff(times)) if len(times) > 1 else 1.0
      dipoles = _make_dipoles_sparse(
          X,
          active_set,
          forward,
          times[0],
          tstep,
          M,
          gain_active,
          active_is_idx=True,
      )
      for dipole, ori in zip(dipoles, oris):
          signs = np.sign((dipole.ori * ori).sum(-1, keepdims=True))
          dipole.ori *= signs
          dipole.amplitude *= signs[:, 0]
      logger.info("[done]")
      return dipoles, explained_data
  
file_path: mne-python/mne/beamformer/_rap_music.py
imports: import numpy
  from scipy import linalg
  from .._fiff.pick import pick_channels_forward, pick_info
  from ..fixes import _safe_svd
  from ..forward import convert_forward_solution, is_fixed_orient
  from ..inverse_sparse.mxne_inverse import _make_dipoles_sparse
  from ..minimum_norm.inverse import _log_exp_var
  from ..utils import _check_info_inv, fill_doc, logger, verbose
  from ._compute_beamformer import _prepare_beamformer_input
label_desc: Use image node_id 1 for calling a global function with example usage: _apply_rap_music(data, info, times, forward, noise_cov, n_dipoles, picks, use_trap) and returns: dipoles,  explained_data