code: def _triage_filter_params(
      x,
      sfreq,
      l_freq,
      h_freq,
      l_trans_bandwidth,
      h_trans_bandwidth,
      filter_length,
      method,
      phase,
      fir_window,
      fir_design,
      bands="scalar",
      reverse=False,
  ):
      """Validate and automate filter parameter selection."""
      _validate_type(phase, "str", "phase")
      if method == "fir":
          _check_option(
              "phase",
              phase,
              _known_phases_fir,
              extra="when FIR filtering",
          )
      else:
          _check_option(
              "phase",
              phase,
              _known_phases_iir,
              extra="when IIR filtering",
          )
      _validate_type(fir_window, "str", "fir_window")
      _check_option("fir_window", fir_window, _known_fir_windows)
      _validate_type(fir_design, "str", "fir_design")
      _check_option("fir_design", fir_design, _known_fir_designs)
  
      # Helpers for reporting
      report_phase = (
          "non-linear phase" if phase == "minimum" else "zero-phase"
      )
      causality = "causal" if phase == "minimum" else "non-causal"
      if phase == "zero-double":
          report_pass = "two-pass forward and reverse"
      else:
          report_pass = "one-pass"
      if l_freq is not None:
          if h_freq is not None:
              kind = "bandstop" if reverse else "bandpass"
          else:
              kind = "highpass"
              assert not reverse
      elif h_freq is not None:
          kind = "lowpass"
          assert not reverse
      else:
          kind = "allpass"
  
      def float_array(c):
          return np.array(c, float).ravel()
  
      if bands == "arr":
          cast = float_array
      else:
          cast = float
      sfreq = float(sfreq)
      if l_freq is not None:
          l_freq = cast(l_freq)
          if np.any(l_freq <= 0):
              raise ValueError(
                  f"highpass frequency {l_freq} must be greater than zero"
              )
      if h_freq is not None:
          h_freq = cast(h_freq)
          if np.any(h_freq >= sfreq / 2.0):
              raise ValueError(
                  f"lowpass frequency {h_freq} must be less than Nyquist ({sfreq / 2.0})"
              )
  
      dB_cutoff = False  # meaning, don't try to compute or report
      if bands == "scalar" or (len(h_freq) == 1 and len(l_freq) == 1):
          if phase == "zero":
              dB_cutoff = "-6 dB"
          elif phase == "zero-double":
              dB_cutoff = "-12 dB"
  
      # we go to the next power of two when in FIR and zero-double mode
      if method == "iir":
          # Ignore these parameters, effectively
          l_stop, h_stop = l_freq, h_freq
      else:  # method == 'fir'
          l_stop = h_stop = None
          logger.info("")
          logger.info("FIR filter parameters")
          logger.info("---------------------")
          logger.info(
              f"Designing a {report_pass}, {report_phase}, {causality} {kind} filter:"
          )
          logger.info(
              f"- {_fir_design_dict[fir_design]} design ({fir_design}) method"
          )
          this_dict = _fir_window_dict[fir_window]
          if fir_design == "firwin":
              logger.info(
                  "- {name:s} window with {ripple:0.4f} passband ripple "
                  "and {attenuation:d} dB stopband attenuation".format(
                      **this_dict
                  )
              )
          else:
              logger.info("- {name:s} window".format(**this_dict))
  
          if l_freq is not None:  # high-pass component
              if isinstance(l_trans_bandwidth, str):
                  if l_trans_bandwidth != "auto":
                      raise ValueError(
                          'l_trans_bandwidth must be "auto" if string, got "'
                          f'{l_trans_bandwidth}"'
                      )
                  l_trans_bandwidth = np.minimum(
                      np.maximum(0.25 * l_freq, 2.0), l_freq
                  )
              l_trans_rep = np.array(l_trans_bandwidth, float)
              if l_trans_rep.size == 1:
                  l_trans_rep = f"{l_trans_rep.item():0.2f}"
              with np.printoptions(precision=2, floatmode="fixed"):
                  msg = (
                      f"- Lower transition bandwidth: {l_trans_rep} Hz"
                  )
                  if dB_cutoff:
                      l_freq_rep = np.array(l_freq, float)
                      if l_freq_rep.size == 1:
                          l_freq_rep = f"{l_freq_rep.item():0.2f}"
                      cutoff_rep = np.array(
                          l_freq - l_trans_bandwidth / 2.0, float
                      )
                      if cutoff_rep.size == 1:
                          cutoff_rep = f"{cutoff_rep.item():0.2f}"
                      # Could be an array
                      logger.info(
                          f"- Lower passband edge: {l_freq_rep}"
                      )
                      msg += f" ({dB_cutoff} cutoff frequency: {cutoff_rep} Hz)"
              logger.info(msg)
              l_trans_bandwidth = cast(l_trans_bandwidth)
              if np.any(l_trans_bandwidth <= 0):
                  raise ValueError(
                      f"l_trans_bandwidth must be positive, got {l_trans_bandwidth}"
                  )
              l_stop = l_freq - l_trans_bandwidth
              if reverse:  # band-stop style
                  l_stop += l_trans_bandwidth
                  l_freq += l_trans_bandwidth
              if np.any(l_stop < 0):
                  raise ValueError(
                      "Filter specification invalid: Lower stop frequency negative ("
                      f"{l_stop:0.2f} Hz). Increase pass frequency or reduce the "
                      "transition bandwidth (l_trans_bandwidth)"
                  )
          if h_freq is not None:  # low-pass component
              if isinstance(h_trans_bandwidth, str):
                  if h_trans_bandwidth != "auto":
                      raise ValueError(
                          'h_trans_bandwidth must be "auto" if '
                          'string, got "%s"' % h_trans_bandwidth
                      )
                  h_trans_bandwidth = np.minimum(
                      np.maximum(0.25 * h_freq, 2.0),
                      sfreq / 2.0 - h_freq,
                  )
              h_trans_rep = np.array(h_trans_bandwidth, float)
              if h_trans_rep.size == 1:
                  h_trans_rep = f"{h_trans_rep.item():0.2f}"
              with np.printoptions(precision=2, floatmode="fixed"):
                  msg = (
                      f"- Upper transition bandwidth: {h_trans_rep} Hz"
                  )
                  if dB_cutoff:
                      h_freq_rep = np.array(h_freq, float)
                      if h_freq_rep.size == 1:
                          h_freq_rep = f"{h_freq_rep.item():0.2f}"
                      cutoff_rep = np.array(
                          h_freq + h_trans_bandwidth / 2.0, float
                      )
                      if cutoff_rep.size == 1:
                          cutoff_rep = f"{cutoff_rep.item():0.2f}"
                      logger.info(
                          f"- Upper passband edge: {h_freq_rep} Hz"
                      )
                      msg += f" ({dB_cutoff} cutoff frequency: {cutoff_rep} Hz)"
              logger.info(msg)
              h_trans_bandwidth = cast(h_trans_bandwidth)
              if np.any(h_trans_bandwidth <= 0):
                  raise ValueError(
                      f"h_trans_bandwidth must be positive, got {h_trans_bandwidth}"
                  )
              h_stop = h_freq + h_trans_bandwidth
              if reverse:  # band-stop style
                  h_stop -= h_trans_bandwidth
                  h_freq -= h_trans_bandwidth
              if np.any(h_stop > sfreq / 2):
                  raise ValueError(
                      f"Effective band-stop frequency ({h_stop}) is too high (maximum "
                      f"based on Nyquist is {sfreq / 2.0})"
                  )
  
          if (
              isinstance(filter_length, str)
              and filter_length.lower() == "auto"
          ):
              filter_length = filter_length.lower()
              h_check = l_check = np.inf
              if h_freq is not None:
                  h_check = min(np.atleast_1d(h_trans_bandwidth))
              if l_freq is not None:
                  l_check = min(np.atleast_1d(l_trans_bandwidth))
              mult_fact = 2.0 if fir_design == "firwin2" else 1.0
              filter_length = "{}s".format(
                  _length_factors[fir_window]
                  * mult_fact
                  / float(min(h_check, l_check)),
              )
              next_pow_2 = False  # disable old behavior
          else:
              next_pow_2 = (
                  isinstance(filter_length, str)
                  and phase == "zero-double"
              )
  
          filter_length = _to_samples(
              filter_length, sfreq, phase, fir_design
          )
  
          # use correct type of filter (must be odd length for firwin and for
          # zero phase)
          if fir_design == "firwin" or phase == "zero":
              filter_length += (filter_length - 1) % 2
  
          logger.info(
              f"- Filter length: {filter_length} samples ({filter_length / sfreq:0.3f} s)"
          )
          logger.info("")
  
          if filter_length <= 0:
              raise ValueError(
                  f"filter_length must be positive, got {filter_length}"
              )
  
          if next_pow_2:
              filter_length = 2 ** int(np.ceil(np.log2(filter_length)))
              if fir_design == "firwin":
                  filter_length += (filter_length - 1) % 2
  
      # If we have data supplied, do a sanity check
      if x is not None:
          x = _check_filterable(x)
          len_x = x.shape[-1]
          if method != "fir":
              filter_length = len_x
          if filter_length > len_x and not (
              l_freq is None and h_freq is None
          ):
              warn(
                  f"filter_length ({filter_length}) is longer than the signal ({len_x}), "
                  "distortion is likely. Reduce filter length or filter a longer signal."
              )
  
      logger.debug("Using filter length: %s" % filter_length)
      return (
          x,
          sfreq,
          l_freq,
          h_freq,
          l_stop,
          h_stop,
          filter_length,
          phase,
          fir_window,
          fir_design,
      )
  
imports: from collections import Counter
  from copy import deepcopy
  from functools import partial
  from math import gcd
  import numpy
  from scipy import fft, signal
  from scipy.stats import f
  from ._fiff.pick import _picks_to_idx
  from ._ola import _COLA
  from .cuda import _fft_multiply_repeated, _fft_resample, _setup_cuda_fft_multiply_repeated, _setup_cuda_fft_resample, _smart_pad
  from .parallel import parallel_func
  from .utils import _check_option, _check_preload, _ensure_int, _pl, _validate_type, logger, sum_squared, verbose, warn
label_desc: Use image node_id 31 for calling a global function with example usage: _triage_filter_params(x, sfreq, l_freq, h_freq, l_trans_bandwidth, h_trans_bandwidth, filter_length, method, phase, fir_window, fir_design, bands, reverse) and returns: x,  sfreq,  l_freq,  h_freq,  l_stop,  h_stop,  filter_length,  phase,  fir_window,  fir_design, np