class_docstr: Interpolate between two points.
  
  Parameters
  ----------
  control_points : array, shape (n_changes,)
      The control points (indices) to use.
  values : callable | array, shape (n_changes, ...)
      Callable that takes the control point and returns a list of
      arrays that must be interpolated.
  interp : str
      Can be 'zero', 'linear', 'hann', or 'cos2' (same as hann).
  
  Notes
  -----
  This will process data using overlapping windows of potentially
  different sizes to achieve a constant output value using different
  2-point interpolation schemes. For example, for linear interpolation,
  and window sizes of 6 and 17, this would look like::
  
      1 _     _
        |\   / '-.           .-'
        | \ /     '-.     .-'
        |  x         |-.-|
        | / \     .-'     '-.
        |/   \_.-'           '-.
      0 +----|----|----|----|---
        0    5   10   15   20   25
docstr: Feed data and get interpolators as a generator.
docstr_tok: ["Feed","data","and","get","interpolators","as","a","generator","."]
code: def feed_generator(self, n_pts):
      """Feed data and get interpolators as a generator."""
      self.n_last = 0
      n_pts = _ensure_int(n_pts, "n_pts")
      original_position = self._position
      stop = self._position + n_pts
      logger.debug(f"Feed {n_pts} ({self._position}-{stop})")
      used = np.zeros(n_pts, bool)
      if self._left is None:  # first one
          logger.debug(f"  Eval @ 0 ({self.control_points[0]})")
          self._left = self.values(self.control_points[0])
          if len(self.control_points) == 1:
              self._right = self._left
      n_used = 0
  
      # Left zero-order hold condition
      if self._position < self.control_points[self._left_idx]:
          n_use = min(
              self.control_points[self._left_idx] - self._position,
              n_pts,
          )
          logger.debug("  Left ZOH %s" % n_use)
          this_sl = slice(None, n_use)
          assert used[this_sl].size == n_use
          assert not used[this_sl].any()
          used[this_sl] = True
          yield [this_sl, self._left, None, None]
          self._position += n_use
          n_used += n_use
          self.n_last += 1
  
      # Standard interpolation condition
      stop_right_idx = np.where(self.control_points >= stop)[0]
      if len(stop_right_idx) == 0:
          stop_right_idx = [len(self.control_points) - 1]
      stop_right_idx = stop_right_idx[0]
      left_idxs = np.arange(self._left_idx, stop_right_idx)
      self.n_last += max(len(left_idxs) - 1, 0)
      for bi, left_idx in enumerate(left_idxs):
          if left_idx != self._left_idx or self._right is None:
              if self._right is not None:
                  assert left_idx == self._left_idx + 1
                  self._left = self._right
                  self._left_idx += 1
                  self._use_interp = None  # need to recreate it
              eval_pt = self.control_points[self._left_idx + 1]
              logger.debug(f"  Eval @ {self._left_idx + 1} ({eval_pt})")
              self._right = self.values(eval_pt)
          assert self._right is not None
          left_point = self.control_points[self._left_idx]
          right_point = self.control_points[self._left_idx + 1]
          if self._use_interp is None:
              interp_span = right_point - left_point
              if self._interp == "zero":
                  self._use_interp = None
              elif self._interp == "linear":
                  self._use_interp = np.linspace(
                      1.0, 0.0, interp_span, endpoint=False
                  )
              else:  # self._interp in ('cos2', 'hann'):
                  self._use_interp = np.cos(
                      np.linspace(
                          0, np.pi / 2.0, interp_span, endpoint=False
                      )
                  )
                  self._use_interp *= self._use_interp
          n_use = min(stop, right_point) - self._position
          if n_use > 0:
              logger.debug(
                  f"  Interp {self._interp} {n_use} ({left_point}-{right_point})"
              )
              interp_start = self._position - left_point
              assert interp_start >= 0
              if self._use_interp is None:
                  this_interp = None
              else:
                  this_interp = self._use_interp[
                      interp_start : interp_start + n_use
                  ]
                  assert this_interp.size == n_use
              this_sl = slice(n_used, n_used + n_use)
              assert used[this_sl].size == n_use
              assert not used[this_sl].any()
              used[this_sl] = True
              yield [this_sl, self._left, self._right, this_interp]
              self._position += n_use
              n_used += n_use
  
      # Right zero-order hold condition
      if self.control_points[self._left_idx] <= self._position:
          n_use = stop - self._position
          if n_use > 0:
              logger.debug("  Right ZOH %s" % n_use)
              this_sl = slice(n_pts - n_use, None)
              assert not used[this_sl].any()
              used[this_sl] = True
              assert self._right is not None
              yield [this_sl, self._right, None, None]
              self._position += n_use
              n_used += n_use
              self.n_last += 1
      assert self._position == stop
      assert n_used == n_pts
      assert used.all()
      assert self._position == original_position + n_pts
  
file_path: mne-python/mne/_ola.py
imports: import numpy
  from scipy.signal import get_window
  from .utils import _ensure_int, logger, verbose
label_desc: Use image node_id 2 for calling the _Interp2 obj's underlying member method code with example usage: obj.feed_generator(n_pts) without return types