(X, sfreq, idx_fb, peaks)
return y
Filter bank design for decomposing EEG data into sub-band components [1]_

    Parameters
    ----------
    X: ndarray of shape (n_trials, n_channels, n_samples) or (n_channels, n_samples)
        EEG data to be processed

    sfreq: int
        Sampling frequency of the data.

    idx_fb: int
        Index of filters in filter bank analysis

    peaks : list of len (n_classes)
        Frequencies corresponding to the SSVEP components.

    Returns
    -------
    y: ndarray of shape (n_trials, n_channels, n_samples)
        Sub-band components decomposed by a filter bank

    Reference:
      .. [1] M. Nakanishi, Y. Wang, X. Chen, Y. -T. Wang, X. Gao, and T.-P. Jung,
          "Enhancing detection of SSVEPs for a high-speed brain speller using
           task-related component analysis",
          IEEE Trans. Biomed. Eng, 65(1):104-112, 2018.

    Code based on the Matlab implementation from authors of [1]_
    (https://github.com/mnakanishi/TRCA-SSVEP).
Filter bank design for decomposing EEG data into sub-band components [1]_
Filter bank design for decomposing EEG data into sub - band components [ 1 ] _
def filterbank(X, sfreq, idx_fb, peaks):
    """
    Filter bank design for decomposing EEG data into sub-band components [1]_

    Parameters
    ----------
    X: ndarray of shape (n_trials, n_channels, n_samples) or (n_channels, n_samples)
        EEG data to be processed

    sfreq: int
        Sampling frequency of the data.

    idx_fb: int
        Index of filters in filter bank analysis

    peaks : list of len (n_classes)
        Frequencies corresponding to the SSVEP components.

    Returns
    -------
    y: ndarray of shape (n_trials, n_channels, n_samples)
        Sub-band components decomposed by a filter bank

    Reference:
      .. [1] M. Nakanishi, Y. Wang, X. Chen, Y. -T. Wang, X. Gao, and T.-P. Jung,
          "Enhancing detection of SSVEPs for a high-speed brain speller using
           task-related component analysis",
          IEEE Trans. Biomed. Eng, 65(1):104-112, 2018.

    Code based on the Matlab implementation from authors of [1]_
    (https://github.com/mnakanishi/TRCA-SSVEP).
    """

    # Calibration data comes in batches of trials
    if X.ndim == 3:
        num_chans = X.shape[1]
        num_trials = X.shape[0]

    # Testdata come with only one trial at the time
    elif X.ndim == 2:
        num_chans = X.shape[0]
        num_trials = 1

    sfreq = sfreq / 2

    min_freq = np.min(peaks)
    max_freq = np.max(peaks)

    if max_freq < 40:
        top = 100
    else:
        top = 115
    # Check for Nyquist
    if top >= sfreq:
        top = sfreq - 10

    diff = max_freq - min_freq
    # Lowcut frequencies for the pass band (depends on the frequencies of SSVEP)
    # No more than 3dB loss in the passband

    passband = [min_freq - 2 + x * diff for x in range(7)]

    # At least 40db attenuation in the stopband
    if min_freq - 4 > 0:
        stopband = [
            min_freq - 4 + x * (diff - 2) if x < 3 else min_freq - 4 + x * diff
            for x in range(7)
        ]
    else:
        stopband = [2 + x * (diff - 2) if x < 3 else 2 + x * diff for x in range(7)]

    Wp = [passband[idx_fb] / sfreq, top / sfreq]
    Ws = [stopband[idx_fb] / sfreq, (top + 7) / sfreq]

    N, Wn = scp.cheb1ord(Wp, Ws, 3, 40)  # Chebyshev type I filter order selection.

    B, A = scp.cheby1(N, 0.5, Wn, btype="bandpass")  # Chebyshev type I filter design

    y = np.zeros(X.shape)
    if num_trials == 1:  # For testdata
        for ch_i in range(num_chans):
            try:
                # The arguments 'axis=0, padtype='odd', padlen=3*(max(len(B),len(A))-1)' correspond
                # to Matlab filtfilt (https://dsp.stackexchange.com/a/47945)
                y[ch_i, :] = scp.filtfilt(
                    B,
                    A,
                    X[ch_i, :],
                    axis=0,
                    padtype="odd",
                    padlen=3 * (max(len(B), len(A)) - 1),
                )
            except Exception as e:
                print(e)
                print(num_chans)
    else:
        for trial_i in range(num_trials):  # Filter each trial sequentially
            for ch_i in range(num_chans):  # Filter each channel sequentially
                y[trial_i, ch_i, :] = scp.filtfilt(
                    B,
                    A,
                    X[trial_i, ch_i, :],
                    axis=0,
                    padtype="odd",
                    padlen=3 * (max(len(B), len(A)) - 1),
                )
    return y
def filterbank ( X , sfreq , idx_fb , peaks ) : # Calibration data comes in batches of trials if X . ndim == 3 : num_chans = X . shape [ 1 ] num_trials = X . shape [ 0 ] # Testdata come with only one trial at the time elif X . ndim == 2 : num_chans = X . shape [ 0 ] num_trials = 1 sfreq = sfreq / 2 min_freq = np . min ( peaks ) max_freq = np . max ( peaks ) if max_freq < 40 : top = 100 else : top = 115 # Check for Nyquist if top >= sfreq : top = sfreq - 10 diff = max_freq - min_freq # Lowcut frequencies for the pass band (depends on the frequencies of SSVEP) # No more than 3dB loss in the passband passband = [ min_freq - 2 + x * diff for x in range ( 7 ) ] # At least 40db attenuation in the stopband if min_freq - 4 > 0 : stopband = [ min_freq - 4 + x * ( diff - 2 ) if x < 3 else min_freq - 4 + x * diff for x in range ( 7 ) ] else : stopband = [ 2 + x * ( diff - 2 ) if x < 3 else 2 + x * diff for x in range ( 7 ) ] Wp = [ passband [ idx_fb ] / sfreq , top / sfreq ] Ws = [ stopband [ idx_fb ] / sfreq , ( top + 7 ) / sfreq ] N , Wn = scp . cheb1ord ( Wp , Ws , 3 , 40 ) # Chebyshev type I filter order selection. B , A = scp . cheby1 ( N , 0.5 , Wn , btype = "bandpass" ) # Chebyshev type I filter design y = np . zeros ( X . shape ) if num_trials == 1 : # For testdata for ch_i in range ( num_chans ) : try : # The arguments 'axis=0, padtype='odd', padlen=3*(max(len(B),len(A))-1)' correspond # to Matlab filtfilt (https://dsp.stackexchange.com/a/47945) y [ ch_i , : ] = scp . filtfilt ( B , A , X [ ch_i , : ] , axis = 0 , padtype = "odd" , padlen = 3 * ( max ( len ( B ) , len ( A ) ) - 1 ) , ) except Exception as e : print ( e ) print ( num_chans ) else : for trial_i in range ( num_trials ) : # Filter each trial sequentially for ch_i in range ( num_chans ) : # Filter each channel sequentially y [ trial_i , ch_i , : ] = scp . filtfilt ( B , A , X [ trial_i , ch_i , : ] , axis = 0 , padtype = "odd" , padlen = 3 * ( max ( len ( B ) , len ( A ) ) - 1 ) , ) return y