<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def filter_(data, axis='time', low_cut=None, high_cut=None, order=4, ftype='butter', Rs=None, notchfreq=50, notchquality=25):
 """Design filter and apply it. Parameters ftype : str 'butter', 'cheby1', 'cheby2', 'ellip', 'bessel', 'diff', or 'notch' axis : str, optional axis to apply the filter on. low_cut : float, optional (not for notch) low cutoff for high-pass filter high_cut : float, optional (not for notch) high cutoff for low-pass filter order : int, optional (not for notch) filter order data : instance of Data (not for notch) the data to filter. notchfreq : float (only for notch) frequency to apply notch filter to (+ harmonics) notchquality : int (only for notch) Quality factor (see scipy.signal.iirnotch) Returns ------- filtered_data : instance of DataRaw filtered data Notes ----- You can specify any filter type as defined by iirfilter. If you specify low_cut only, it generates a high-pass filter. If you specify high_cut only, it generates a low-pass filter. If you specify both, it generates a band-pass filter. low_cut and high_cut should be given as ratio of the Nyquist. But if you specify s_freq, then the ratio will be computed automatically. Raises ------ ValueError if the cutoff frequency is larger than the Nyquist frequency. """

    nyquist = data.s_freq / 2.

    btype = None
    if low_cut is not None and high_cut is not None:
        if low_cut > nyquist or high_cut > nyquist:
            raise ValueError('cutoff has to be less than Nyquist '
                             'frequency')
        btype = 'bandpass'
        Wn = (low_cut / nyquist,
              high_cut / nyquist)

    elif low_cut is not None:
        if low_cut > nyquist:
            raise ValueError('cutoff has to be less than Nyquist '
                             'frequency')
        btype = 'highpass'
        Wn = low_cut / nyquist

    elif high_cut is not None:
        if high_cut > nyquist:
            raise ValueError('cutoff has to be less than Nyquist '
                             'frequency')
        btype = 'lowpass'
        Wn = high_cut / nyquist

    if btype is None and ftype != 'notch':
        raise TypeError('You should specify at least low_cut or high_cut')

    if Rs is None:
        Rs = 40

    if ftype == 'notch':
        b_a = [iirnotch(w0 / nyquist, notchquality) for w0 in arange(notchfreq, nyquist, notchfreq)]

    else:
        lg.debug('order {0: 2}, Wn {1}, btype {2}, ftype {3}'
                 ''.format(order, str(Wn), btype, ftype))
        b_a = [iirfilter(order, Wn, btype=btype, ftype=ftype, rs=Rs), ]

    fdata = data._copy()
    for i in range(data.number_of('trial')):
        x = data.data[i]
        for b, a in b_a:
            x = filtfilt(b, a, x, axis=data.index_of(axis))
        fdata.data[i] = x

    return fdata