Exemplo n.º 1
0
def phase_by_time(sig,
                  fs,
                  f_range=None,
                  hilbert_increase_n=False,
                  remove_edges=True,
                  **filter_kwargs):
    """Compute the instantaneous phase of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    hilbert_increase_n : bool, optional, default: False
        If True, zero pad the signal's length to the next power of 2 for the Hilbert transform.
        This is because ``scipy.signal.hilbert`` can be very slow for some lengths of x.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filter's length to the edge with nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    pha : 1d array
        Instantaneous phase time series.

    Examples
    --------
    Compute the instantaneous phase, for the alpha range:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation': {'freq': 10}})
    >>> pha = phase_by_time(sig, fs=500, f_range=(8, 12))
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    pha = np.angle(robust_hilbert(sig, increase_n=hilbert_increase_n))

    if f_range and remove_edges:
        pha = remove_filter_edges(pha, len(filter_kernel))

    return pha
Exemplo n.º 2
0
def amp_by_time(sig, fs, f_range=None, remove_edges=True, **filter_kwargs):
    """Compute the instantaneous amplitude of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filter's length to the edge with nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Instantaneous amplitude time series.

    Examples
    --------
    Compute the instantaneous amplitude, for the alpha range:

    >>> from neurodsp.sim import sim_combined
    >>> sig = sim_combined(n_seconds=10, fs=500,
    ...                    components={'sim_powerlaw': {}, 'sim_oscillation' : {'freq': 10}})
    >>> amp = amp_by_time(sig, fs=500, f_range=(8, 12))
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    amp = np.abs(robust_hilbert(sig))

    if f_range and remove_edges:
        amp = remove_filter_edges(amp, len(filter_kernel))

    return amp
Exemplo n.º 3
0
def amp_by_time(sig,
                fs,
                f_range=None,
                hilbert_increase_n=False,
                remove_edges=True,
                **filter_kwargs):
    """Compute the instantaneous amplitude of a time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float or None, optional default: None
        Filter range, in Hz, as (low, high). If None, no filtering is applied.
    hilbert_increase_n : bool, optional, default: False
        If True, zero pad the signal to length the next power of 2 when doing the Hilbert transform.
        This is because :func:`scipy.signal.hilbert` can be very slow for some lengths of sig.
    remove_edges : bool, optional, default: True
        If True, replace samples that are within half of the filters length to the edge with np.nan.
        This removes edge artifacts from the filtered signal. Only used if `f_range` is defined.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Instantaneous amplitude time series.
    """

    if f_range:
        sig, filter_kernel = filter_signal(sig,
                                           fs,
                                           infer_passtype(f_range),
                                           f_range=f_range,
                                           remove_edges=False,
                                           return_filter=True,
                                           **filter_kwargs)

    amp = np.abs(robust_hilbert(sig, increase_n=hilbert_increase_n))

    if f_range and remove_edges:
        amp = remove_filter_edges(amp, len(filter_kernel))

    return amp
Exemplo n.º 4
0
def amp_by_time(sig,
                fs,
                f_range,
                hilbert_increase_n=False,
                remove_edges=True,
                **filter_kwargs):
    """Calculate the amplitude time series.

    Parameters
    ----------
    sig : 1d array
        Time series.
    fs : float
        Sampling rate, in Hz.
    f_range : tuple of float
        The frequency filtering range, in Hz, as (low, high).
    hilbert_increase_n : bool, optional, default: False
        If True, zeropad the signal to length the next power of 2 when doing the hilbert transform.
        This is because scipy.signal.hilbert can be very slow for some lengths of sig.
    remove_edges : bool, optional, default: True
        If True, replace the samples that are within half a kernel's length to
        the signal edge with np.nan.
    **filter_kwargs
        Keyword parameters to pass to `filter_signal`.

    Returns
    -------
    amp : 1d array
        Time series of amplitude.
    """

    sig_filt, kernel = filter_signal(sig,
                                     fs,
                                     infer_passtype(f_range),
                                     f_range=f_range,
                                     remove_edges=False,
                                     return_filter=True,
                                     **filter_kwargs)

    amp = np.abs(robust_hilbert(sig_filt, increase_n=hilbert_increase_n))

    if remove_edges:
        amp = remove_filter_edges(amp, len(kernel))

    return amp
Exemplo n.º 5
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