code: def mixed_norm(
      evoked,
      forward,
      noise_cov,
      alpha="sure",
      loose="auto",
      depth=0.8,
      maxit=3000,
      tol=1e-4,
      active_set_size=10,
      debias=True,
      time_pca=True,
      weights=None,
      weights_min=0.0,
      solver="auto",
      n_mxne_iter=1,
      return_residual=False,
      return_as_dipoles=False,
      dgap_freq=10,
      rank=None,
      pick_ori=None,
      sure_alpha_grid="auto",
      random_state=None,
      verbose=None,
  ):
      """Mixed-norm estimate (MxNE) and iterative reweighted MxNE (irMxNE).
  
      Compute L1/L2 mixed-norm solution :footcite:`GramfortEtAl2012` or L0.5/L2
      :footcite:`StrohmeierEtAl2016` mixed-norm solution on evoked data.
  
      Parameters
      ----------
      evoked : instance of Evoked or list of instances of Evoked
          Evoked data to invert.
      forward : dict
          Forward operator.
      noise_cov : instance of Covariance
          Noise covariance to compute whitener.
      alpha : float | str
          Regularization parameter. If float it should be in the range [0, 100):
          0 means no regularization, 100 would give 0 active dipole.
          If ``'sure'`` (default), the SURE method from
          :footcite:`DeledalleEtAl2014` will be used.
  
          .. versionchanged:: 0.24
            The default was changed to ``'sure'``.
      %(loose)s
      %(depth)s
      maxit : int
          Maximum number of iterations.
      tol : float
          Tolerance parameter.
      active_set_size : int | None
          Size of active set increment. If None, no active set strategy is used.
      debias : bool
          Remove coefficient amplitude bias due to L1 penalty.
      time_pca : bool or int
          If True the rank of the concatenated epochs is reduced to
          its true dimension. If is 'int' the rank is limited to this value.
      weights : None | array | SourceEstimate
          Weight for penalty in mixed_norm. Can be None, a
          1d array with shape (n_sources,), or a SourceEstimate (e.g. obtained
          with wMNE, dSPM, or fMRI).
      weights_min : float
          Do not consider in the estimation sources for which weights
          is less than weights_min.
      solver : 'cd' | 'bcd' | 'auto'
          The algorithm to use for the optimization. 'cd' uses
          coordinate descent, and 'bcd' applies block coordinate descent.
          'cd' is only available for fixed orientation.
      n_mxne_iter : int
          The number of MxNE iterations. If > 1, iterative reweighting
          is applied.
      return_residual : bool
          If True, the residual is returned as an Evoked instance.
      return_as_dipoles : bool
          If True, the sources are returned as a list of Dipole instances.
      dgap_freq : int or np.inf
          The duality gap is evaluated every dgap_freq iterations. Ignored if
          solver is 'cd'.
      %(rank_none)s
  
          .. versionadded:: 0.18
      %(pick_ori)s
      sure_alpha_grid : array | str
          If ``'auto'`` (default), the SURE is evaluated along 15 uniformly
          distributed alphas between alpha_max and 0.1 * alpha_max. If array, the
          grid is directly specified. Ignored if alpha is not "sure".
  
          .. versionadded:: 0.24
      random_state : int | None
          The random state used in a random number generator for delta and
          epsilon used for the SURE computation. Defaults to None.
  
          .. versionadded:: 0.24
      %(verbose)s
  
      Returns
      -------
      stc : SourceEstimate | list of SourceEstimate
          Source time courses for each evoked data passed as input.
      residual : instance of Evoked
          The residual a.k.a. data not explained by the sources.
          Only returned if return_residual is True.
  
      See Also
      --------
      tf_mixed_norm
  
      References
      ----------
      .. footbibliography::
      """
      _validate_type(alpha, ("numeric", str), "alpha")
      if isinstance(alpha, str):
          _check_option("alpha", alpha, ("sure",))
      elif not 0.0 <= alpha < 100:
          raise ValueError(
              'If not equal to "sure" alpha must be in [0, 100). '
              "Got alpha = %s" % alpha
          )
      if n_mxne_iter < 1:
          raise ValueError(
              "MxNE has to be computed at least 1 time. "
              "Requires n_mxne_iter >= 1, got %d" % n_mxne_iter
          )
      if dgap_freq <= 0.0:
          raise ValueError(
              "dgap_freq must be a positive integer."
              " Got dgap_freq = %s" % dgap_freq
          )
      if not (
          isinstance(sure_alpha_grid, (np.ndarray, list))
          or sure_alpha_grid == "auto"
      ):
          raise ValueError(
              'If not equal to "auto" sure_alpha_grid must be an '
              "array. Got %s" % type(sure_alpha_grid)
          )
      if (
          isinstance(sure_alpha_grid, str) and sure_alpha_grid != "auto"
      ) and (isinstance(alpha, str) and alpha != "sure"):
          raise Exception(
              "If sure_alpha_grid is manually specified, alpha must "
              'be "sure". Got %s' % alpha
          )
      pca = True
      if not isinstance(evoked, list):
          evoked = [evoked]
  
      _check_reference(evoked[0])
  
      all_ch_names = evoked[0].ch_names
      if not all(
          all_ch_names == evoked[i].ch_names
          for i in range(1, len(evoked))
      ):
          raise Exception(
              "All the datasets must have the same good channels."
          )
  
      (
          forward,
          gain,
          gain_info,
          whitener,
          source_weighting,
          mask,
      ) = _prepare_gain(
          forward,
          evoked[0].info,
          noise_cov,
          pca,
          depth,
          loose,
          rank,
          weights,
          weights_min,
      )
      _check_ori(pick_ori, forward)
  
      sel = [all_ch_names.index(name) for name in gain_info["ch_names"]]
      M = np.concatenate([e.data[sel] for e in evoked], axis=1)
  
      # Whiten data
      logger.info("Whitening data matrix.")
      M = np.dot(whitener, M)
  
      if time_pca:
          U, s, Vh = _safe_svd(M, full_matrices=False)
          if not isinstance(time_pca, bool) and isinstance(
              time_pca, int
          ):
              U = U[:, :time_pca]
              s = s[:time_pca]
              Vh = Vh[:time_pca]
          M = U * s
  
      # Scaling to make setting of tol and alpha easy
      tol *= sum_squared(M)
      n_dip_per_pos = 1 if is_fixed_orient(forward) else 3
      alpha_max = norm_l2inf(
          np.dot(gain.T, M), n_dip_per_pos, copy=False
      )
      alpha_max *= 0.01
      gain /= alpha_max
      source_weighting /= alpha_max
  
      # Alpha selected automatically by SURE minimization
      if alpha == "sure":
          alpha_grid = sure_alpha_grid
          if (
              isinstance(sure_alpha_grid, str)
              and sure_alpha_grid == "auto"
          ):
              alpha_grid = np.geomspace(100, 10, num=15)
          X, active_set, best_alpha_ = _compute_mxne_sure(
              M,
              gain,
              alpha_grid,
              sigma=1,
              random_state=random_state,
              n_mxne_iter=n_mxne_iter,
              maxit=maxit,
              tol=tol,
              n_orient=n_dip_per_pos,
              active_set_size=active_set_size,
              debias=debias,
              solver=solver,
              dgap_freq=dgap_freq,
              verbose=verbose,
          )
          logger.info("Selected alpha: %s" % best_alpha_)
      else:
          if n_mxne_iter == 1:
              X, active_set, E = mixed_norm_solver(
                  M,
                  gain,
                  alpha,
                  maxit=maxit,
                  tol=tol,
                  active_set_size=active_set_size,
                  n_orient=n_dip_per_pos,
                  debias=debias,
                  solver=solver,
                  dgap_freq=dgap_freq,
                  verbose=verbose,
              )
          else:
              X, active_set, E = iterative_mixed_norm_solver(
                  M,
                  gain,
                  alpha,
                  n_mxne_iter,
                  maxit=maxit,
                  tol=tol,
                  n_orient=n_dip_per_pos,
                  active_set_size=active_set_size,
                  debias=debias,
                  solver=solver,
                  dgap_freq=dgap_freq,
                  verbose=verbose,
              )
  
      if time_pca:
          X = np.dot(X, Vh)
          M = np.dot(M, Vh)
  
      gain_active = gain[:, active_set]
      if mask is not None:
          active_set_tmp = np.zeros(len(mask), dtype=bool)
          active_set_tmp[mask] = active_set
          active_set = active_set_tmp
          del active_set_tmp
  
      if active_set.sum() == 0:
          warn("No active dipoles found. alpha is too big.")
          M_estimate = np.zeros_like(M)
      else:
          # Reapply weights to have correct unit
          X = _reapply_source_weighting(X, source_weighting, active_set)
          source_weighting[source_weighting == 0] = 1  # zeros
          gain_active /= source_weighting[active_set]
          del source_weighting
          M_estimate = np.dot(gain_active, X)
  
      outs = list()
      residual = list()
      cnt = 0
      for e in evoked:
          tmin = e.times[0]
          tstep = 1.0 / e.info["sfreq"]
          Xe = X[:, cnt : (cnt + len(e.times))]
          if return_as_dipoles:
              out = _make_dipoles_sparse(
                  Xe,
                  active_set,
                  forward,
                  tmin,
                  tstep,
                  M[:, cnt : (cnt + len(e.times))],
                  gain_active,
              )
          else:
              out = _make_sparse_stc(
                  Xe,
                  active_set,
                  forward,
                  tmin,
                  tstep,
                  pick_ori=pick_ori,
              )
          outs.append(out)
          cnt += len(e.times)
  
          if return_residual:
              residual.append(
                  _compute_residual(
                      forward, e, Xe, active_set, gain_info
                  )
              )
  
      _log_exp_var(M, M_estimate, prefix="")
      logger.info("[done]")
  
      if len(outs) == 1:
          out = outs[0]
          if return_residual:
              residual = residual[0]
      else:
          out = outs
  
      if return_residual:
          out = out, residual
  
      return out
  
imports: import numpy
  from .._fiff.proj import deactivate_proj
  from ..dipole import Dipole
  from ..fixes import _safe_svd
  from ..forward import is_fixed_orient
  from ..minimum_norm.inverse import _check_reference, _log_exp_var, _prepare_forward, combine_xyz
  from ..source_estimate import SourceEstimate, _BaseSourceEstimate, _make_stc
  from ..utils import _check_depth, _check_option, _validate_type, check_random_state, logger, sum_squared, verbose, warn
  from .mxne_optim import _Phi, groups_norm2, iterative_mixed_norm_solver, iterative_tf_mixed_norm_solver, mixed_norm_solver, norm_epsilon_inf, norm_l2inf, tf_mixed_norm_solver
label_desc: Use image node_id 10 for calling a global function with example usage: mixed_norm(evoked, forward, noise_cov, alpha, loose, depth, maxit, tol, active_set_size, debias, time_pca, weights, weights_min, solver, n_mxne_iter, return_residual, return_as_dipoles, dgap_freq, rank, pick_ori, sure_alpha_grid, random_state, verbose) and returns: out