class_docstr: Constant overlap-add processing helper.
  
  Parameters
  ----------
  process : callable
      A function that takes a chunk of input data with shape
      ``(n_channels, n_samples)`` and processes it.
  store : callable | ndarray
      A function that takes a completed chunk of output data.
      Can also be an ``ndarray``, in which case it is treated as the
      output data in which to store the results.
  n_total : int
      The total number of samples.
  n_samples : int
      The number of samples per window.
  n_overlap : int
      The overlap between windows.
  window : str
      The window to use. Default is "hann".
  tol : float
      The tolerance for COLA checking.
  
  Notes
  -----
  This will process data using overlapping windows to achieve a constant
  output value. For example, for ``n_total=27``, ``n_samples=10``,
  ``n_overlap=5`` and ``window='triang'``::
  
      1 _____               _______
        |    \   /\   /\   /
        |     \ /  \ /  \ /
        |      x    x    x
        |     / \  / \  / \
        |    /   \/   \/   \
      0 +----|----|----|----|----|-
        0    5   10   15   20   25
  
  This produces four windows: the first three are the requested length
  (10 samples) and the last one is longer (12 samples). The first and last
  window are asymmetric.
code: def __init__(
      self,
      process,
      store,
      n_total,
      n_samples,
      n_overlap,
      sfreq,
      window="hann",
      tol=1e-10,
      *,
      verbose=None,
  ):
      n_samples = _ensure_int(n_samples, "n_samples")
      n_overlap = _ensure_int(n_overlap, "n_overlap")
      n_total = _ensure_int(n_total, "n_total")
      if n_samples <= 0:
          raise ValueError(f"n_samples must be > 0, got {n_samples}")
      if n_overlap < 0:
          raise ValueError(f"n_overlap must be >= 0, got {n_overlap}")
      if n_total < 0:
          raise ValueError(f"n_total must be >= 0, got {n_total}")
      self._n_samples = int(n_samples)
      self._n_overlap = int(n_overlap)
      del n_samples, n_overlap
      if n_total < self._n_samples:
          raise ValueError(
              "Number of samples per window (%d) must be at "
              "most the total number of samples (%s)"
              % (self._n_samples, n_total)
          )
      if not callable(process):
          raise TypeError(
              f"process must be callable, got type {type(process)}"
          )
      self._process = process
      self._step = self._n_samples - self._n_overlap
      self._store = _check_store(store)
      self._idx = 0
      self._in_buffers = self._out_buffers = None
  
      # Create our window boundaries
      window_name = window if isinstance(window, str) else "custom"
      self._window = get_window(
          window, self._n_samples, fftbins=(self._n_samples - 1) % 2
      )
      self._window /= _check_cola(
          self._window,
          self._n_samples,
          self._step,
          window_name,
          tol=tol,
      )
      self.starts = np.arange(
          0, n_total - self._n_samples + 1, self._step
      )
      self.stops = self.starts + self._n_samples
      delta = n_total - self.stops[-1]
      self.stops[-1] = n_total
      sfreq = float(sfreq)
      pl = "s" if len(self.starts) != 1 else ""
      logger.info(
          "    Processing %4d data chunk%s of (at least) %0.1f s "
          "with %0.1f s overlap and %s windowing"
          % (
              len(self.starts),
              pl,
              self._n_samples / sfreq,
              self._n_overlap / sfreq,
              window_name,
          )
      )
      del window, window_name
      if delta > 0:
          logger.info(
              f"    The final {delta / sfreq} s will be lumped into the final window"
          )
  
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 1 to create a new _COLA object  with example: obj = _COLA(process, store, n_total, n_samples, n_overlap, sfreq, window, tol)