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))
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
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