code: """High-pass filter and locally detrend the EEG signal."""
  import logging
  
  import mne
  import numpy as np
  
  from pyprep.utils import _eeglab_create_highpass, _eeglab_fir_filter
  
  
  def removeTrend(
      EEG,
      sample_rate,
      detrendType="high pass",
      detrendCutoff=1.0,
      detrendChannels=None,
      matlab_strict=False,
  ):
      """Remove trends (i.e., slow drifts in baseline) from an array of EEG data.
  
      Parameters
      ----------
      EEG : np.ndarray
          A 2-D array of EEG data to detrend.
      sample_rate : float
          The sample rate (in Hz) of the input EEG data.
      detrendType : str, optional
          Type of detrending to be performed: must be one of 'high pass',
          'high pass sinc, or 'local detrend'. Defaults to 'high pass'.
      detrendCutoff : float, optional
          The high-pass cutoff frequency (in Hz) to use for detrending. Defaults
          to 1.0 Hz.
      detrendChannels : {list, None}, optional
          List of the indices of all channels that require detrending/filtering.
          If ``None``, all channels are used (default).
      matlab_strict : bool, optional
          Whether or not detrending should strictly follow MATLAB PREP's internal
          math, ignoring any improvements made in PyPREP over the original code
          (see :ref:`matlab-diffs` for more details). Defaults to ``False``.
  
      Returns
      -------
      EEG : np.ndarray
          A 2-D array containing the filtered/detrended EEG data.
  
      Notes
      -----
      High-pass filtering is implemented using the MNE filter function
      :func:``mne.filter.filter_data`` unless `matlab_strict` is ``True``, in
      which case it is performed using a minimal re-implementation of EEGLAB's
      ``pop_eegfiltnew``. Local detrending is performed using a Python
      re-implementation of the ``runline`` function from the Chronux package for
      MATLAB [1]_.
  
      References
      ----------
      .. [1] http://chronux.org/
  
      """
      if len(EEG.shape) == 1:
          EEG = np.reshape(EEG, (1, EEG.shape[0]))
  
      if detrendType.lower() == "high pass":
          if matlab_strict:
              picks = detrendChannels if detrendChannels else range(EEG.shape[0])
              filt = _eeglab_create_highpass(detrendCutoff, sample_rate)
              EEG[picks, :] = _eeglab_fir_filter(EEG[picks, :], filt)
          else:
              EEG = mne.filter.filter_data(
                  EEG,
                  sfreq=sample_rate,
                  l_freq=detrendCutoff,
                  h_freq=None,
                  picks=detrendChannels,
              )
  
      elif detrendType.lower() == "high pass sinc":
          fOrder = np.round(14080 * sample_rate / 512)
          fOrder = int(fOrder + fOrder % 2)
          EEG = mne.filter.filter_data(
              data=EEG,
              sfreq=sample_rate,
              l_freq=1,
              h_freq=None,
              picks=detrendChannels,
              filter_length=fOrder,
              fir_window="blackman",
          )
  
      elif detrendType.lower() == "local detrend":
          if detrendChannels is None:
              detrendChannels = np.arange(0, EEG.shape[0])
          windowSize = 1.5 / detrendCutoff
          windowSize = np.minimum(windowSize, EEG.shape[1])
          stepSize = 0.02
          EEG = np.transpose(EEG)
          n = np.round(sample_rate * windowSize)
          dn = np.round(sample_rate * stepSize)
  
          if dn > n or dn < 1:
              logging.error(
                  "Step size should be less than the window size and "
                  "contain at least 1 sample"
              )
          if n == EEG.shape[0]:
              # data = scipy.signal.detrend(EEG, axis=0)
              pass
          else:
              for ch in detrendChannels:
                  EEG[:, ch] = runline(EEG[:, ch], int(n), int(dn))
          EEG = np.transpose(EEG)
  
      else:
          logging.warning(
              "No filtering/detreding performed since the detrend type did not match"
          )
  
      return EEG
  
  
  def runline(y, n, dn):
      """Perform local linear regression on a channel of EEG data.
  
      A re-implementation of the ``runline`` function from the Chronux package
      for MATLAB [1]_.
  
      Parameters
      ----------
      y : np.ndarray
          A 1-D array of data from a single EEG channel.
      n : int
          Length of the detrending window.
      dn : int
          Length of the window step size.
  
      Returns
      -------
      y: np.ndarray
         The detrended signal for the given EEG channel.
  
      References
      ----------
      .. [1] http://chronux.org/
  
      """
      nt = y.shape[0]
      y_line = np.zeros((nt, 1))
      norm = np.zeros((nt, 1))
      nwin = int(np.ceil((nt - n) / dn))
      yfit = np.zeros((nwin, n))
      xwt = (np.arange(1, n + 1) - n / 2) / (n / 2)
      wt = np.power(1 - np.power(np.absolute(xwt), 3), 3)
      for j in range(0, nwin):
          tseg = y[dn * j : dn * j + n]
          y1 = np.mean(tseg)
          y2 = np.mean(np.multiply(np.arange(1, n + 1), tseg)) * (2 / (n + 1))
          a = np.multiply(np.subtract(y2, y1), 6 / (n - 1))
          b = np.subtract(y1, a * (n + 1) / 2)
          yfit[j, :] = np.multiply(np.arange(1, n + 1), a) + b
          y_line[j * dn : j * dn + n] = y_line[j * dn : j * dn + n] + np.reshape(
              np.multiply(yfit[j, :], wt), (n, 1)
          )
          norm[j * dn : j * dn + n] = norm[j * dn : j * dn + n] + np.reshape(wt, (n, 1))
  
      for i in range(0, len(norm)):
          if norm[i] > 0:
              y_line[i] = y_line[i] / norm[i]
      indx = (nwin - 1) * dn + n - 1
      npts = len(y) - indx + 1
      y_line[indx - 1 :] = np.reshape(
          (np.multiply(np.arange(n + 1, n + npts + 1), a) + b), (npts, 1)
      )
      for i in range(0, len(y_line)):
          y[i] = y[i] - y_line[i]
      return y
   """
  =================
  Run RANSAC
  =================
  
  
  In this example we show how to run the RANSAC of ``pyprep``.
  
  .. currentmodule:: pyprep
  """  # noqa: D205 D400
  
  # Authors: Yorguin Mantilla <yjmantilla@gmail.com>
  #
  # License: MIT
  # Based On: use_noisy_module.py
  
  ###############################################################################
  # First we import what we need for this example.
  import numpy as np
  import mne
  from scipy import signal as signal
  from time import perf_counter
  
  from pyprep.find_noisy_channels import NoisyChannels
  
  ###############################################################################
  # Now let's make some arbitrary MNE raw object for demonstration purposes.
  # We will think of good channels as sine waves and bad channels correlated with
  # each other as sawtooths. The RANSAC will be biased towards sines in its
  # prediction (they are the majority) so it will identify the sawtooths as bad.
  # We will need to set a montage because the RANSAC needs to interpolate.
  
  sfreq = 1000.0
  
  # We need a montage, because RANSAC uses spherical splines for interpolation
  montage = mne.channels.make_standard_montage("standard_1020")
  
  ch_names = montage.ch_names
  
  n_chans = len(ch_names)
  
  info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=["eeg"] * n_chans)
  
  time = np.arange(0, 30, 1.0 / sfreq)  # 30 seconds of recording
  n_bad_chans = 3
  
  rng = np.random.default_rng(42)
  bad_channels = rng.choice(np.arange(n_chans), n_bad_chans, replace=False)
  bad_channels = [int(i) for i in bad_channels]
  bad_ch_names = [ch_names[i] for i in bad_channels]
  
  # The frequency components to use in the signal for good and bad channels
  freq_good = 20
  freq_bad = 20
  
  # Generate the data
  X = [
      signal.sawtooth(2 * np.pi * freq_bad * time)
      if i in bad_channels
      else np.sin(2 * np.pi * freq_good * time)
      for i in range(n_chans)
  ]
  # Scale the signal amplitude and add noise.
  X = 2e-5 * np.array(X) + 1e-5 * rng.random((n_chans, time.shape[0]))
  
  raw = mne.io.RawArray(X, info)
  
  raw.set_montage(montage, verbose=False)
  
  
  ###############################################################################
  # Assign the mne object to the :class:`NoisyChannels` class. The resulting object
  # will be the place where all following methods are performed.
  
  nd = NoisyChannels(raw, random_state=1337)
  nd2 = NoisyChannels(raw, random_state=1337)
  
  ###############################################################################
  # Find all bad channels using channel-wise RANSAC and print a summary
  start_time = perf_counter()
  nd.find_bad_by_ransac(channel_wise=True)
  print("--- %s seconds ---" % (perf_counter() - start_time))
  
  # Repeat channel-wise RANSAC using a single channel at a time. This is slower
  # but needs less memory.
  start_time = perf_counter()
  nd2.find_bad_by_ransac(channel_wise=True, max_chunk_size=1)
  print("--- %s seconds ---" % (perf_counter() - start_time))
  
  ###############################################################################
  # Now the bad channels are saved in `bads` and we can continue processing our
  # `raw` object. For more information, we can access attributes of the ``nd``
  # instance:
  
  # Check channels that go bad together by correlation (RANSAC)
  print(nd.bad_by_ransac)
  assert set(bad_ch_names) == set(nd.bad_by_ransac)
  
  # Check that the channel wise RANSAC yields identical results
  print(nd2.bad_by_ransac)
  assert set(bad_ch_names) == set(nd2.bad_by_ransac)
  
apis: numpy.multiply numpy.transpose numpy.ceil numpy.zeros numpy.subtract numpy.reshape numpy.arange numpy.absolute numpy.round numpy.mean numpy.minimum
apis: numpy.random.default_rng numpy.arange numpy.array numpy.sin scipy.signal.sawtooth