예제 #1
0
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs):
    """Simulate a power law time series, with a specified exponent.

    Parameters
    ----------
    n_seconds : float
        Simulation time, in seconds.
    fs : float
        Sampling rate of simulated signal, in Hz.
    exponent : float, optional, default: -2
        Desired power-law exponent, of the form P(f)=f^exponent.
    f_range : list of [float, float] or None, optional
        Frequency range to filter simulated data, as [f_lo, f_hi], in Hz.
    **filter_kwargs : kwargs, optional
        Keyword arguments to pass to `filter_signal`.

    Returns
    -------
    sig: 1d array
        Time-series with the desired power law exponent.
    """

    # Get the number of samples to simulate for the signal
    #   If filter is to be filtered, with FIR, add extra to compensate for edges
    if f_range and filter_kwargs.get('filter_type', None) != 'iir':

        pass_type = infer_passtype(f_range)
        filt_len = compute_filter_length(fs, pass_type,
                                         *check_filter_definition(pass_type, f_range),
                                         n_seconds=filter_kwargs.get('n_seconds', None),
                                         n_cycles=filter_kwargs.get('n_cycles', 3))

        n_samples = int(n_seconds * fs) + filt_len + 1

    else:
        n_samples = int(n_seconds * fs)

    sig = _create_powerlaw(n_samples, fs, exponent)

    if f_range is not None:
        sig = filter_signal(sig, fs, infer_passtype(f_range), f_range,
                            remove_edges=True, **filter_kwargs)
        # Drop the edges, that were compensated for, if not using IIR (using FIR)
        if not filter_kwargs.get('filter_type', None) == 'iir':
            sig, _ = remove_nans(sig)

    return sig
예제 #2
0
def filter_signal_iir(sig,
                      fs,
                      pass_type,
                      f_range,
                      butterworth_order,
                      print_transitions=False,
                      plot_properties=False,
                      return_filter=False):
    """Apply an IIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    butterworth_order : int
        Order of the butterworth filter, if using an IIR filter.
        See input 'N' in scipy.signal.butter.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the filter coefficients of the IIR filter.

    Returns
    -------
    sig_filt : 1d array
        Filtered time series.
    filter_coefs : tuple of (1d array, 1d array)
        Filter coefficients of the IIR filter, as (b_vals, a_vals).
        Only returned if `return_filter` is True.
    """

    # Design filter
    b_vals, a_vals = design_iir_filter(fs, pass_type, f_range,
                                       butterworth_order)

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(b_vals,
                            a_vals,
                            fs,
                            pass_type,
                            f_range,
                            verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_iir_filter(sig, b_vals, a_vals)

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot frequency response, if desired
    if plot_properties:
        f_db, db = compute_frequency_response(b_vals, a_vals, fs)
        plot_frequency_response(f_db, db)

    if return_filter:
        return sig_filt, (b_vals, a_vals)
    else:
        return sig_filt
예제 #3
0
def filter_signal_iir(sig,
                      fs,
                      pass_type,
                      f_range,
                      butterworth_order,
                      print_transitions=False,
                      plot_properties=False,
                      return_filter=False):
    """Apply an IIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    butterworth_order : int
        Order of the butterworth filter, if using an IIR filter.
        See input 'N' in scipy.signal.butter.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the second order series coefficients of the IIR filter.

    Returns
    -------
    sig_filt : 1d array
        Filtered time series.
    sos : 2d array
        Second order series coefficients of the IIR filter. Has shape of (n_sections, 6).
        Only returned if `return_filter` is True.

    Examples
    --------
    Apply a bandstop IIR filter to a simulated signal:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_iir(sig, fs=500, pass_type='bandstop',
    ...                              f_range=(55, 65), butterworth_order=7)
    """

    # Design filter
    sos = design_iir_filter(fs, pass_type, f_range, butterworth_order)

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(sos,
                            None,
                            fs,
                            pass_type,
                            f_range,
                            verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_iir_filter(sig, sos)

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot frequency response, if desired
    if plot_properties:
        f_db, db = compute_frequency_response(sos, None, fs)
        plot_frequency_response(f_db, db)

    if return_filter:
        return sig_filt, sos
    else:
        return sig_filt
예제 #4
0
def filter_signal_fir(sig, fs, pass_type, f_range, n_cycles=3, n_seconds=None, remove_edges=True,
                      print_transitions=False, plot_properties=False, return_filter=False):
    """Apply an FIR filter to a signal.

    Parameters
    ----------
    sig : array
        Time series to be filtered.
    fs : float
        Sampling rate, in Hz.
    pass_type : {'bandpass', 'bandstop', 'lowpass', 'highpass'}
        Which kind of filter to apply:

        * 'bandpass': apply a bandpass filter
        * 'bandstop': apply a bandstop (notch) filter
        * 'lowpass': apply a lowpass filter
        * 'highpass' : apply a highpass filter
    f_range : tuple of (float, float) or float
        Cutoff frequency(ies) used for filter, specified as f_lo & f_hi.
        For 'bandpass' & 'bandstop', must be a tuple.
        For 'lowpass' or 'highpass', can be a float that specifies pass frequency, or can be
        a tuple and is assumed to be (None, f_hi) for 'lowpass', and (f_lo, None) for 'highpass'.
    n_cycles : float, optional, default: 3
        Length of filter, in number of cycles, defined at the 'f_lo' frequency.
        This parameter is overwritten by `n_seconds`, if provided.
    n_seconds : float, optional
        Length of filter, in seconds. This parameter overwrites `n_cycles`.
    remove_edges : bool, optional
        If True, replace samples within half the kernel length to be np.nan.
    print_transitions : bool, optional, default: False
        If True, print out the transition and pass bandwidths.
    plot_properties : bool, optional, default: False
        If True, plot the properties of the filter, including frequency response and/or kernel.
    return_filter : bool, optional, default: False
        If True, return the filter coefficients of the FIR filter.

    Returns
    -------
    sig_filt : array
        Filtered time series.
    filter_coefs : 1d array
        Filter coefficients of the FIR filter. Only returned if `return_filter` is True.

    Examples
    --------
    Apply a band pass FIR filter to a simulated signal:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_fir(sig, fs=500, pass_type='bandpass', f_range=(1, 25))

    Apply a high pass FIR filter to a signal, with a specified number of cycles:

    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> filt_sig = filter_signal_fir(sig, fs=500, pass_type='highpass', f_range=(2, None), n_cycles=5)
    """

    # Design filter & check that the length is okay with signal
    filter_coefs = design_fir_filter(fs, pass_type, f_range, n_cycles, n_seconds)
    check_filter_length(sig.shape[-1], len(filter_coefs))

    # Check filter properties: compute transition bandwidth & run checks
    check_filter_properties(filter_coefs, 1, fs, pass_type, f_range, verbose=print_transitions)

    # Remove any NaN on the edges of 'sig'
    sig, sig_nans = remove_nans(sig)

    # Apply filter
    sig_filt = apply_fir_filter(sig, filter_coefs)

    # Remove edge artifacts
    if remove_edges:
        sig_filt = remove_filter_edges(sig_filt, len(filter_coefs))

    # Add NaN back on the edges of 'sig', if there were any at the beginning
    sig_filt = restore_nans(sig_filt, sig_nans)

    # Plot filter properties, if specified
    if plot_properties:
        f_db, db = compute_frequency_response(filter_coefs, 1, fs)
        plot_filter_properties(f_db, db, fs, filter_coefs)

    if return_filter:
        return sig_filt, filter_coefs
    else:
        return sig_filt
예제 #5
0
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs):
    """Simulate a power law time series, with a specified exponent.

    Parameters
    ----------
    n_seconds : float
        Simulation time, in seconds.
    fs : float
        Sampling rate of simulated signal, in Hz.
    exponent : float, optional, default: -2
        Desired power-law exponent, of the form P(f)=f^exponent.
    f_range : list of [float, float] or None, optional
        Frequency range to filter simulated data, as [f_lo, f_hi], in Hz.
    **filter_kwargs : kwargs, optional
        Keyword arguments to pass to `filter_signal`.

    Returns
    -------
    sig : 1d array
        Time-series with the desired power law exponent.

    Notes
    -----
    - Powerlaw data with exponents is created by spectrally rotating white noise [1]_.

    References
    ----------
    .. [1] Timmer, J., & Konig, M. (1995). On Generating Power Law Noise.
           Astronomy and Astrophysics, 300, 707–710.

    Examples
    --------
    Simulate a power law signal, with an exponent of -2 (brown noise):

    >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-2.0)

    Simulate a power law signal, with a highpass filter applied at 2 Hz:

    >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-1.5, f_range=(2, None))
    """

    # Compute the number of samples for the simulated time series
    n_samples = compute_nsamples(n_seconds, fs)

    # Get the number of samples to simulate for the signal
    #   If signal is to be filtered, with FIR, add extra to compensate for edges
    if f_range and filter_kwargs.get('filter_type', None) != 'iir':

        pass_type = infer_passtype(f_range)
        filt_len = compute_filter_length(
            fs,
            pass_type,
            *check_filter_definition(pass_type, f_range),
            n_seconds=filter_kwargs.get('n_seconds', None),
            n_cycles=filter_kwargs.get('n_cycles', 3))

        n_samples += filt_len + 1

    # Simulate the powerlaw data
    sig = _create_powerlaw(n_samples, fs, exponent)

    if f_range is not None:
        sig = filter_signal(sig,
                            fs,
                            infer_passtype(f_range),
                            f_range,
                            remove_edges=True,
                            **filter_kwargs)
        # Drop the edges, that were compensated for, if not using FIR filter
        if not filter_kwargs.get('filter_type', None) == 'iir':
            sig, _ = remove_nans(sig)

    return sig