code: def construct_iir_filter(
      iir_params,
      f_pass=None,
      f_stop=None,
      sfreq=None,
      btype=None,
      return_copy=True,
      *,
      phase="zero",
      verbose=None,
  ):
      """Use IIR parameters to get filtering coefficients.
  
      This function works like a wrapper for iirdesign and iirfilter in
      scipy.signal to make filter coefficients for IIR filtering. It also
      estimates the number of padding samples based on the filter ringing.
      It creates a new iir_params dict (or updates the one passed to the
      function) with the filter coefficients ('b' and 'a') and an estimate
      of the padding necessary ('padlen') so IIR filtering can be performed.
  
      Parameters
      ----------
      iir_params : dict
          Dictionary of parameters to use for IIR filtering.
  
              * If ``iir_params['sos']`` exists, it will be used as
                second-order sections to perform IIR filtering.
  
                .. versionadded:: 0.13
  
              * Otherwise, if ``iir_params['b']`` and ``iir_params['a']``
                exist, these will be used as coefficients to perform IIR
                filtering.
              * Otherwise, if ``iir_params['order']`` and
                ``iir_params['ftype']`` exist, these will be used with
                `scipy.signal.iirfilter` to make a filter.
                You should also supply ``iir_params['rs']`` and
                ``iir_params['rp']`` if using elliptic or Chebychev filters.
              * Otherwise, if ``iir_params['gpass']`` and
                ``iir_params['gstop']`` exist, these will be used with
                `scipy.signal.iirdesign` to design a filter.
              * ``iir_params['padlen']`` defines the number of samples to pad
                (and an estimate will be calculated if it is not given).
                See Notes for more details.
              * ``iir_params['output']`` defines the system output kind when
                designing filters, either "sos" or "ba". For 0.13 the
                default is 'ba' but will change to 'sos' in 0.14.
  
      f_pass : float or list of float
          Frequency for the pass-band. Low-pass and high-pass filters should
          be a float, band-pass should be a 2-element list of float.
      f_stop : float or list of float
          Stop-band frequency (same size as f_pass). Not used if 'order' is
          specified in iir_params.
      sfreq : float | None
          The sample rate.
      btype : str
          Type of filter. Should be 'lowpass', 'highpass', or 'bandpass'
          (or analogous string representations known to
          :func:`scipy.signal.iirfilter`).
      return_copy : bool
          If False, the 'sos', 'b', 'a', and 'padlen' entries in
          ``iir_params`` will be set inplace (if they weren't already).
          Otherwise, a new ``iir_params`` instance will be created and
          returned with these entries.
      %(phase)s
      %(verbose)s
  
      Returns
      -------
      iir_params : dict
          Updated iir_params dict, with the entries (set only if they didn't
          exist before) for 'sos' (or 'b', 'a'), and 'padlen' for
          IIR filtering.
  
      See Also
      --------
      mne.filter.filter_data
      mne.io.Raw.filter
  
      Notes
      -----
      This function triages calls to :func:`scipy.signal.iirfilter` and
      :func:`scipy.signal.iirdesign` based on the input arguments (see
      linked functions for more details).
  
      .. versionchanged:: 0.14
         Second-order sections are used in filter design by default (replacing
         ``output='ba'`` by ``output='sos'``) to help ensure filter stability
         and reduce numerical error.
  
      Examples
      --------
      iir_params can have several forms. Consider constructing a low-pass
      filter at 40 Hz with 1000 Hz sampling rate.
  
      In the most basic (2-parameter) form of iir_params, the order of the
      filter 'N' and the type of filtering 'ftype' are specified. To get
      coefficients for a 4th-order Butterworth filter, this would be:
  
      >>> iir_params = dict(order=4, ftype='butter', output='sos')  # doctest:+SKIP
      >>> iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low', return_copy=False)  # doctest:+SKIP
      >>> print((2 * len(iir_params['sos']), iir_params['padlen']))  # doctest:+SKIP
      (4, 82)
  
      Filters can also be constructed using filter design methods. To get a
      40 Hz Chebyshev type 1 lowpass with specific gain characteristics in the
      pass and stop bands (assuming the desired stop band is at 45 Hz), this
      would be a filter with much longer ringing:
  
      >>> iir_params = dict(ftype='cheby1', gpass=3, gstop=20, output='sos')  # doctest:+SKIP
      >>> iir_params = construct_iir_filter(iir_params, 40, 50, 1000, 'low')  # doctest:+SKIP
      >>> print((2 * len(iir_params['sos']), iir_params['padlen']))  # doctest:+SKIP
      (6, 439)
  
      Padding and/or filter coefficients can also be manually specified. For
      a 10-sample moving window with no padding during filtering, for example,
      one can just do:
  
      >>> iir_params = dict(b=np.ones((10)), a=[1, 0], padlen=0)  # doctest:+SKIP
      >>> iir_params = construct_iir_filter(iir_params, return_copy=False)  # doctest:+SKIP
      >>> print((iir_params['b'], iir_params['a'], iir_params['padlen']))  # doctest:+SKIP
      (array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]), [1, 0], 0)
  
      For more information, see the tutorials
      :ref:`disc-filtering` and :ref:`tut-filter-resample`.
      """  # noqa: E501
      known_filters = (
          "bessel",
          "butter",
          "butterworth",
          "cauer",
          "cheby1",
          "cheby2",
          "chebyshev1",
          "chebyshev2",
          "chebyshevi",
          "chebyshevii",
          "ellip",
          "elliptic",
      )
      if not isinstance(iir_params, dict):
          raise TypeError(
              "iir_params must be a dict, got %s" % type(iir_params)
          )
      # if the filter has been designed, we're good to go
      Wp = None
      if "sos" in iir_params:
          system = iir_params["sos"]
          output = "sos"
      elif "a" in iir_params and "b" in iir_params:
          system = (iir_params["b"], iir_params["a"])
          output = "ba"
      else:
          output = iir_params.get("output", "sos")
          _check_option("output", output, ("ba", "sos"))
          # ensure we have a valid ftype
          if "ftype" not in iir_params:
              raise RuntimeError(
                  "ftype must be an entry in iir_params if "
                  "b"
                  " "
                  "and "
                  "a"
                  " are not specified"
              )
          ftype = iir_params["ftype"]
          if ftype not in known_filters:
              raise RuntimeError(
                  "ftype must be in filter_dict from scipy.signal (e.g., butter, cheby1, "
                  f"etc.) not {ftype}"
              )
  
          # use order-based design
          f_pass = np.atleast_1d(f_pass)
          if f_pass.ndim > 1:
              raise ValueError(
                  "frequencies must be 1D, got %dD" % f_pass.ndim
              )
          edge_freqs = ", ".join(f"{f:0.2f}" for f in f_pass)
          Wp = f_pass / (float(sfreq) / 2)
          # IT will de designed
          ftype_nice = _ftype_dict.get(ftype, ftype)
          _validate_type(phase, str, "phase")
          _check_option(
              "phase", phase, ("zero", "zero-double", "forward")
          )
          if phase in ("zero-double", "zero"):
              ptype = (
                  "zero-phase (two-pass forward and reverse) non-causal"
              )
          else:
              ptype = "non-linear phase (one-pass forward) causal"
          logger.info("")
          logger.info("IIR filter parameters")
          logger.info("---------------------")
          logger.info(f"{ftype_nice} {btype} {ptype} filter:")
          # SciPy designs forward for -3dB, so forward-backward is -6dB
          if "order" in iir_params:
              singleton = btype in (
                  "low",
                  "lowpass",
                  "high",
                  "highpass",
              )
              use_Wp = Wp.item() if singleton else Wp
              kwargs = dict(
                  N=iir_params["order"],
                  Wn=use_Wp,
                  btype=btype,
                  ftype=ftype,
                  output=output,
              )
              for key in ("rp", "rs"):
                  if key in iir_params:
                      kwargs[key] = iir_params[key]
              system = signal.iirfilter(**kwargs)
              if phase in ("zero", "zero-double"):
                  ptype, pmul = "(effective, after forward-backward)", 2
              else:
                  ptype, pmul = "(forward)", 1
              logger.info(
                  "- Filter order %d %s"
                  % (pmul * iir_params["order"] * len(Wp), ptype)
              )
          else:
              # use gpass / gstop design
              Ws = np.asanyarray(f_stop) / (float(sfreq) / 2)
              if "gpass" not in iir_params or "gstop" not in iir_params:
                  raise ValueError(
                      "iir_params must have at least "
                      "gstop"
                      " and"
                      " "
                      "gpass"
                      " (or "
                      "N"
                      ") entries"
                  )
              system = signal.iirdesign(
                  Wp,
                  Ws,
                  iir_params["gpass"],
                  iir_params["gstop"],
                  ftype=ftype,
                  output=output,
              )
  
      if system is None:
          raise RuntimeError(
              "coefficients could not be created from iir_params"
          )
      # do some sanity checks
      _check_coefficients(system)
  
      # get the gains at the cutoff frequencies
      if Wp is not None:
          if output == "sos":
              cutoffs = signal.sosfreqz(system, worN=Wp * np.pi)[1]
          else:
              cutoffs = signal.freqz(
                  system[0], system[1], worN=Wp * np.pi
              )[1]
          cutoffs = 20 * np.log10(np.abs(cutoffs))
          # 2 * 20 here because we do forward-backward filtering
          if phase in ("zero", "zero-double"):
              cutoffs *= 2
          cutoffs = ", ".join([f"{c:0.2f}" for c in cutoffs])
          logger.info(
              f"- Cutoff{_pl(f_pass)} at {edge_freqs} Hz: {cutoffs} dB"
          )
      # now deal with padding
      if "padlen" not in iir_params:
          padlen = estimate_ringing_samples(system)
      else:
          padlen = iir_params["padlen"]
  
      if return_copy:
          iir_params = deepcopy(iir_params)
  
      iir_params.update(dict(padlen=padlen))
      if output == "sos":
          iir_params.update(sos=system)
      else:
          iir_params.update(b=system[0], a=system[1])
      logger.info("")
      return iir_params
  
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 13 for calling a global function with example usage: construct_iir_filter(iir_params, f_pass, f_stop, sfreq, btype, return_copy) and returns: iir_params