Example #1
0
def test_morletT():
    """
    Confirm that function output size is consistent with inputs
    """
    # Load data
    data = np.load(os.path.dirname(pacpy.__file__) + '/tests/exampledata.npy')
    f0s = np.arange(80, 4, 150)
    tf = morletT(data, f0s)
    assert np.shape(tf) == (len(f0s), len(data))
Example #2
0
def otc(x,
        f_hi,
        f_step,
        fs=1000,
        w=7,
        event_prc=95,
        t_modsig=None,
        t_buffer=.01):
    """
    Calculate the oscillation-triggered coupling measure of phase-amplitude
    coupling from Dvorak, 2014.

    Parameters
    ----------
    x : array-like, 1d
        The time series
    f_hi : (low, high), Hz
        The low frequency filtering range
    f_step : float, Hz
        The width of each frequency bin in the time-frequency representation
    fs : float
        Sampling rate
    w : float
        Length of the filter in terms of the number of cycles of the
        oscillation whose frequency is the center of the bandpass filter
    event_prc : float (in range 0-100)
        The percentile threshold of the power signal of an oscillation
        for an event to be declared
    t_modsig : (min, max)
        Time (seconds) around an event to extract to define the modulation
        signal
    t_buffer : float
        Minimum time (seconds) in between high frequency events

    Returns
    -------
    pac : float
        phase-amplitude coupling value
    tf : 2-dimensional array
        time-frequency representation of input signal
    a_events : array
        samples at which a high frequency event occurs
    mod_sig : array
        modulation signal (see Dvorak, 2014)

    Algorithm (may be changed in the future)
    ---------
    * Calculate time-frequency representation
    * Define time locking events
    * Calculate modulatory signal for each center frequency
    * Calculate modulation strength for each frequency
    * Identify frequency with the max modulation strength, and set PAC
      equal to that maximal modulation strength

    """

    # Arg check
    _x_sanity(x, None)
    _range_sanity(None, f_hi)
    # Set default time range for modulatory signal
    if t_modsig is None:
        t_modsig = (-1, 1)
    if f_step <= 0:
        raise ValueError('Frequency band width must be a positive number.')
    if t_modsig[0] > t_modsig[1]:
        raise ValueError('Invalid time range for modulation signal.')

    # Calculate the time-frequency representation
    f0s = np.arange(f_hi[0], f_hi[1], f_step)
    tf = morletT(x, f0s, w=w, fs=fs)

    # Find the high frequency activity event times
    F = len(f0s)
    a_events = np.zeros(F, dtype=object)
    for f in range(F):
        a_events[f] = _peaktimes(zscore(np.abs(tf[f])),
                                 prc=event_prc,
                                 t_buffer=t_buffer)

    # Calculate the modulation signal
    samp_modsig = np.arange(t_modsig[0] * fs, t_modsig[1] * fs)
    samp_modsig = samp_modsig.astype(int)
    S = len(samp_modsig)
    mod_sig = np.zeros([F, S])

    # For each frequency in the time-frequency representation, calculate a modulation signal
    for f in range(F):
        # Exclude high frequency events that are too close to the signal
        # boundaries to extract an entire modulation signal
        mask = np.ones(len(a_events[f]), dtype=bool)
        mask[a_events[f] <= samp_modsig[-1]] = False
        mask[a_events[f] >= (len(x) - samp_modsig[-1])] = False
        a_events[f] = a_events[f][mask]

        # Calculate the average LFP around each high frequency event
        E = len(a_events[f])
        for e in range(E):
            cur_ecog = x[a_events[f][e] + samp_modsig]
            mod_sig[f] = mod_sig[f] + cur_ecog / E

    # Calculate modulation strength, the range of the modulation signal
    mod_strength = np.zeros(F)
    for f in range(F):
        mod_strength = np.max(mod_sig[f]) - np.min(mod_sig[f])

    # Calculate PAC
    pac = np.max(mod_strength)

    return pac, tf, a_events, mod_sig
Example #3
0
def otc(x, f_hi, f_step, fs=1000,
        w=7, event_prc=95, t_modsig=None, t_buffer=.01):
    """
    Calculate the oscillation-triggered coupling measure of phase-amplitude
    coupling from Dvorak, 2014.

    Parameters
    ----------
    x : array-like, 1d
        The time series
    f_hi : (low, high), Hz
        The low frequency filtering range
    f_step : float, Hz
        The width of each frequency bin in the time-frequency representation
    fs : float
        Sampling rate
    w : float
        Length of the filter in terms of the number of cycles of the
        oscillation whose frequency is the center of the bandpass filter
    event_prc : float (in range 0-100)
        The percentile threshold of the power signal of an oscillation
        for an event to be declared
    t_modsig : (min, max)
        Time (seconds) around an event to extract to define the modulation
        signal
    t_buffer : float
        Minimum time (seconds) in between high frequency events

    Returns
    -------
    pac : float
        phase-amplitude coupling value
    tf : 2-dimensional array
        time-frequency representation of input signal
    a_events : array
        samples at which a high frequency event occurs
    mod_sig : array
        modulation signal (see Dvorak, 2014)
        
    Usage
    -----
    >>> import numpy as np
    >>> from scipy.signal import hilbert
    >>> from pacpy.pac import otc
    >>> t = np.arange(0, 10, .001) # Define time array
    >>> lo = np.sin(t * 2 * np.pi * 6) # Create low frequency carrier
    >>> hi = np.sin(t * 2 * np.pi * 100) # Create modulated oscillation
    >>> hi[np.angle(hilbert(lo)) > -np.pi*.5] = 0 # Clip to 1/4 of cycle
    >>> pac, _, _, _ = otc(lo + hi, (80,150), 4) # Calculate PAC
    >>> print pac
    1.96793361799
    """

    # Arg check
    _x_sanity(x, None)
    _range_sanity(None, f_hi)
    # Set default time range for modulatory signal
    if t_modsig is None:
        t_modsig = (-1,1)
    if f_step <= 0:
        raise ValueError('Frequency band width must be a positive number.')
    if t_modsig[0] > t_modsig[1]:
        raise ValueError('Invalid time range for modulation signal.')

    # Calculate the time-frequency representation
    f0s = np.arange(f_hi[0], f_hi[1], f_step)
    tf = morletT(x, f0s, w=w, fs=fs)

    # Find the high frequency activity event times
    F = len(f0s)
    a_events = np.zeros(F, dtype=object)
    for f in range(F):
        a_events[f] = _peaktimes(zscore(np.abs(tf[f])), prc=event_prc, t_buffer=t_buffer)

    # Calculate the modulation signal
    samp_modsig = np.arange(t_modsig[0] * fs, t_modsig[1] * fs)
    samp_modsig = samp_modsig.astype(int)
    S = len(samp_modsig)
    mod_sig = np.zeros([F, S])

    # For each frequency in the time-frequency representation, calculate a modulation signal
    for f in range(F):
        # Exclude high frequency events that are too close to the signal
        # boundaries to extract an entire modulation signal
        mask = np.ones(len(a_events[f]), dtype=bool)
        mask[a_events[f] <= samp_modsig[-1]] = False
        mask[a_events[f] >= (len(x) - samp_modsig[-1])] = False
        a_events[f] = a_events[f][mask]

        # Calculate the average LFP around each high frequency event
        E = len(a_events[f])
        for e in range(E):
            cur_ecog = x[a_events[f][e] + samp_modsig]
            mod_sig[f] = mod_sig[f] + cur_ecog / E

    # Calculate modulation strength, the range of the modulation signal
    mod_strength = np.zeros(F)
    for f in range(F):
        mod_strength = np.max(mod_sig[f]) - np.min(mod_sig[f])

    # Calculate PAC
    pac = np.max(mod_strength)

    return pac, tf, a_events, mod_sig