code: def compute_rank(
      inst,
      rank=None,
      scalings=None,
      info=None,
      tol="auto",
      proj=True,
      tol_kind="absolute",
      on_rank_mismatch="ignore",
      verbose=None,
  ):
      """Compute the rank of data or noise covariance.
  
      This function will normalize the rows of the data (typically
      channels or vertices) such that non-zero singular values
      should be close to one.
  
      Parameters
      ----------
      inst : instance of Raw, Epochs, or Covariance
          Raw measurements to compute the rank from or the covariance.
      %(rank_none)s
      scalings : dict | None (default None)
          Defaults to ``dict(mag=1e15, grad=1e13, eeg=1e6)``.
          These defaults will scale different channel types
          to comparable values.
      %(info)s Only necessary if ``inst`` is a :class:`mne.Covariance`
          object (since this does not provide ``inst.info``).
      %(tol_rank)s
      proj : bool
          If True, all projs in ``inst`` and ``info`` will be applied or
          considered when ``rank=None`` or ``rank='info'``.
      %(tol_kind_rank)s
      %(on_rank_mismatch)s
      %(verbose)s
  
      Returns
      -------
      rank : dict
          Estimated rank of the data for each channel type.
          To get the total rank, you can use ``sum(rank.values())``.
  
      Notes
      -----
      .. versionadded:: 0.18
      """
      from .cov import Covariance
      from .epochs import BaseEpochs
      from .io import BaseRaw
  
      rank = _check_rank(rank)
      scalings = _handle_default("scalings_cov_rank", scalings)
      _check_on_missing(on_rank_mismatch, "on_rank_mismatch")
  
      if isinstance(inst, Covariance):
          inst_type = "covariance"
          if info is None:
              raise ValueError(
                  "info cannot be None if inst is a Covariance."
              )
          # Reset bads as it's already taken into account in inst['names']
          info = info.copy()
          info["bads"] = []
          inst = pick_channels_cov(
              inst,
              set(inst["names"]) & set(info["ch_names"]),
              exclude=[],
              ordered=False,
          )
          if info["ch_names"] != inst["names"]:
              info = pick_info(
                  info,
                  [
                      info["ch_names"].index(name)
                      for name in inst["names"]
                  ],
              )
      else:
          info = inst.info
          inst_type = "data"
      logger.info(
          "Computing rank from %s with rank=%r" % (inst_type, rank)
      )
  
      _validate_type(rank, (str, dict, None), "rank")
      if isinstance(rank, str):  # string, either 'info' or 'full'
          rank_type = "info"
          info_type = rank
          rank = dict()
      else:  # None or dict
          rank_type = "estimated"
          if rank is None:
              rank = dict()
  
      simple_info = _simplify_info(info)
      picks_list = _picks_by_type(
          info, meg_combined=True, ref_meg=False, exclude="bads"
      )
      for ch_type, picks in picks_list:
          est_verbose = None
          if ch_type in rank:
              # raise an error of user-supplied rank exceeds number of channels
              if rank[ch_type] > len(picks):
                  raise ValueError(
                      f"rank[{repr(ch_type)}]={rank[ch_type]} exceeds the number"
                      f" of channels ({len(picks)})"
                  )
              # special case: if whitening a covariance, check the passed rank
              # against the estimated one
              est_verbose = False
              if not (
                  on_rank_mismatch != "ignore"
                  and rank_type == "estimated"
                  and ch_type == "meg"
                  and isinstance(inst, Covariance)
                  and not inst["diag"]
              ):
                  continue
          ch_names = [info["ch_names"][pick] for pick in picks]
          n_chan = len(ch_names)
          if proj:
              proj_op, n_proj, _ = make_projector(
                  info["projs"], ch_names
              )
          else:
              proj_op, n_proj = None, 0
          if rank_type == "info":
              # use info
              this_rank = _info_rank(info, ch_type, picks, info_type)
              if info_type != "full":
                  this_rank -= n_proj
                  logger.info(
                      "    %s: rank %d after %d projector%s applied to "
                      "%d channel%s"
                      % (
                          ch_type.upper(),
                          this_rank,
                          n_proj,
                          _pl(n_proj),
                          n_chan,
                          _pl(n_chan),
                      )
                  )
              else:
                  logger.info(
                      "    %s: rank %d from info"
                      % (ch_type.upper(), this_rank)
                  )
          else:
              # Use empirical estimation
              assert rank_type == "estimated"
              if isinstance(inst, (BaseRaw, BaseEpochs)):
                  if isinstance(inst, BaseRaw):
                      data = inst.get_data(
                          picks, reject_by_annotation="omit"
                      )
                  else:  # isinstance(inst, BaseEpochs):
                      data = np.concatenate(
                          inst.get_data(picks), axis=1
                      )
                  if proj:
                      data = np.dot(proj_op, data)
                  this_rank = _estimate_rank_meeg_signals(
                      data,
                      pick_info(simple_info, picks),
                      scalings,
                      tol,
                      False,
                      tol_kind,
                  )
              else:
                  assert isinstance(inst, Covariance)
                  if inst["diag"]:
                      this_rank = (
                          inst["data"][picks] > 0
                      ).sum() - n_proj
                  else:
                      data = inst["data"][picks][:, picks]
                      if proj:
                          data = np.dot(
                              np.dot(proj_op, data), proj_op.T
                          )
  
                      this_rank, sing = _estimate_rank_meeg_cov(
                          data,
                          pick_info(simple_info, picks),
                          scalings,
                          tol,
                          return_singular=True,
                          verbose=est_verbose,
                      )
                      if ch_type in rank:
                          ratio = (
                              sing[this_rank - 1]
                              / sing[rank[ch_type] - 1]
                          )
                          if ratio > 100:
                              msg = (
                                  f"The passed rank[{repr(ch_type)}]="
                                  f"{rank[ch_type]} exceeds the estimated rank "
                                  f"of the noise covariance ({this_rank}) "
                                  f"leading to a potential increase in "
                                  f"noise during whitening by a factor "
                                  f"of {np.sqrt(ratio):0.1g}. Ensure that the "
                                  f"rank correctly corresponds to that of the "
                                  f"given noise covariance matrix."
                              )
                              _on_missing(
                                  on_rank_mismatch,
                                  msg,
                                  "on_rank_mismatch",
                              )
                          continue
              this_info_rank = _info_rank(info, ch_type, picks, "info")
              logger.info(
                  "    %s: rank %d computed from %d data channel%s "
                  "with %d projector%s"
                  % (
                      ch_type.upper(),
                      this_rank,
                      n_chan,
                      _pl(n_chan),
                      n_proj,
                      _pl(n_proj),
                  )
              )
              if this_rank > this_info_rank:
                  warn(
                      "Something went wrong in the data-driven estimation of "
                      "the data rank as it exceeds the theoretical rank from "
                      'the info (%d > %d). Consider setting rank to "auto" or '
                      "setting it explicitly as an integer."
                      % (this_rank, this_info_rank)
                  )
          if ch_type not in rank:
              rank[ch_type] = int(this_rank)
  
      return rank
  
file_path: mne-python/mne/rank.py
imports: import numpy
  from scipy import linalg
  from ._fiff.meas_info import Info, _simplify_info
  from ._fiff.pick import _picks_by_type, _picks_to_idx, pick_channels_cov, pick_info
  from ._fiff.proj import make_projector
  from .defaults import _handle_default
  from .utils import _apply_scaling_cov, _check_on_missing, _check_rank, _compute_row_norms, _on_missing, _pl, _scaled_array, _undo_scaling_cov, _validate_type, fill_doc, logger, verbose, warn
label_desc: Use image node_id 9 for calling a global function with example usage: compute_rank(inst, rank, scalings, info, tol, proj, tol_kind, on_rank_mismatch, verbose) and returns: rank