code: def _check_channels_ordered(
      info, pair_vals, *, throw_errors=True, check_bads=True
  ):
      """Check channels follow expected fNIRS format.
  
      If the channels are correctly ordered then an array of valid picks
      will be returned.
  
      If throw_errors is True then any errors in fNIRS formatting will be
      thrown to inform the user. If throw_errors is False then an empty array
      will be returned if the channels are not sufficiently formatted.
      """
      # Every second channel should be same SD pair
      # and have the specified light frequencies.
  
      # All wavelength based fNIRS data.
      picks_wave = _picks_to_idx(
          info,
          ["fnirs_cw_amplitude", "fnirs_od"],
          exclude=[],
          allow_empty=True,
      )
      # All chromophore fNIRS data
      picks_chroma = _picks_to_idx(
          info, ["hbo", "hbr"], exclude=[], allow_empty=True
      )
  
      if (len(picks_wave) > 0) & (len(picks_chroma) > 0):
          picks = _throw_or_return_empty(
              "MNE does not support a combination of amplitude, optical "
              "density, and haemoglobin data in the same raw structure.",
              throw_errors,
          )
  
      # All continuous wave fNIRS data
      if len(picks_wave):
          error_word = "frequencies"
          use_RE = _S_D_F_RE
          picks = picks_wave
      else:
          error_word = "chromophore"
          use_RE = _S_D_H_RE
          picks = picks_chroma
  
      pair_vals = np.array(pair_vals)
      if pair_vals.shape != (2,):
          raise ValueError(
              f"Exactly two {error_word} must exist in info, got "
              f"{list(pair_vals)}"
          )
      # In principle we do not need to require that these be sorted --
      # all we need to do is change our sorted() below to make use of a
      # pair_vals.index(...) in a sort key -- but in practice we always want
      # (hbo, hbr) or (lower_freq, upper_freq) pairings, both of which will
      # work with a naive string sort, so let's just enforce sorted-ness here
      is_str = pair_vals.dtype.kind == "U"
      pair_vals = list(pair_vals)
      if is_str:
          if pair_vals != ["hbo", "hbr"]:
              raise ValueError(
                  f'The {error_word} in info must be ["hbo", "hbr"], but got '
                  f"{pair_vals} instead"
              )
      elif not np.array_equal(np.unique(pair_vals), pair_vals):
          raise ValueError(
              f"The {error_word} in info must be unique and sorted, but got "
              f"got {pair_vals} instead"
          )
  
      if len(picks) % 2 != 0:
          picks = _throw_or_return_empty(
              "NIRS channels not ordered correctly. An even number of NIRS "
              f"channels is required. {len(info.ch_names)} channels were"
              f"provided",
              throw_errors,
          )
  
      # Ensure wavelength info exists for waveform data
      all_freqs = [info["chs"][ii]["loc"][9] for ii in picks_wave]
      if np.any(np.isnan(all_freqs)):
          picks = _throw_or_return_empty(
              f"NIRS channels is missing wavelength information in the "
              f'info["chs"] structure. The encoded wavelengths are {all_freqs}.',
              throw_errors,
          )
  
      # Validate the channel naming scheme
      for pick in picks:
          ch_name_info = use_RE.match(info["chs"][pick]["ch_name"])
          if not bool(ch_name_info):
              picks = _throw_or_return_empty(
                  "NIRS channels have specified naming conventions. "
                  "The provided channel name can not be parsed: "
                  f"{repr(info.ch_names[pick])}",
                  throw_errors,
              )
              break
          value = ch_name_info.groups()[2]
          if len(picks_wave):
              value = value
          else:  # picks_chroma
              if value not in ["hbo", "hbr"]:
                  picks = _throw_or_return_empty(
                      "NIRS channels have specified naming conventions."
                      "Chromophore data must be labeled either hbo or hbr. "
                      f"The failing channel is {info['chs'][pick]['ch_name']}",
                      throw_errors,
                  )
                  break
  
      # Reorder to be paired (naive sort okay here given validation above)
      picks = picks[
          np.argsort([info["ch_names"][pick] for pick in picks])
      ]
  
      # Validate our paired ordering
      for ii, jj in zip(picks[::2], picks[1::2]):
          ch1_name = info["chs"][ii]["ch_name"]
          ch2_name = info["chs"][jj]["ch_name"]
          ch1_re = use_RE.match(ch1_name)
          ch2_re = use_RE.match(ch2_name)
          ch1_S, ch1_D, ch1_value = ch1_re.groups()[:3]
          ch2_S, ch2_D, ch2_value = ch2_re.groups()[:3]
          if len(picks_wave):
              ch1_value, ch2_value = float(ch1_value), float(ch2_value)
          if (
              (ch1_S != ch2_S)
              or (ch1_D != ch2_D)
              or (ch1_value != pair_vals[0])
              or (ch2_value != pair_vals[1])
          ):
              picks = _throw_or_return_empty(
                  "NIRS channels not ordered correctly. Channels must be "
                  "ordered as source detector pairs with alternating"
                  f" {error_word} {pair_vals[0]} & {pair_vals[1]}, but got "
                  f"S{ch1_S}_D{ch1_D} pair "
                  f"{repr(ch1_name)} and {repr(ch2_name)}",
                  throw_errors,
              )
              break
  
      if check_bads:
          for ii, jj in zip(picks[::2], picks[1::2]):
              want = [info.ch_names[ii], info.ch_names[jj]]
              got = list(set(info["bads"]).intersection(want))
              if len(got) == 1:
                  raise RuntimeError(
                      f"NIRS bad labelling is not consistent, found {got} but "
                      f"needed {want}"
                  )
      return picks
  
file_path: mne-python/mne/preprocessing/nirs/nirs.py
imports: import re
  import numpy
  from ..._fiff.pick import _picks_to_idx, pick_types
  from ...utils import _check_option, _validate_type, fill_doc
label_desc: Use image node_id 5 for calling a global function with example usage: _check_channels_ordered(info, pair_vals) and returns: picks