def coherency(time_series, csd_method=None): r""" Compute the coherency between the spectra of n-tuple of time series. Input to this function is in the time domain Parameters ---------- time_series: n*t float array an array of n different time series of length t each csd_method: dict, optional. See :func:`get_spectra` documentation for details Returns ------- f : float array The central frequencies for the frequency bands for which the spectra are estimated c : float array This is a symmetric matrix with the coherencys of the signals. The coherency of signal i and signal j is in f[i][j]. Note that f[i][j] = f[j][i].conj() Notes ----- This is an implementation of equation (1) of Sun (2005): .. math:: R_{xy} (\lambda) = \frac{f_{xy}(\lambda)} {\sqrt{f_{xx} (\lambda) \cdot f_{yy}(\lambda)}} F.T. Sun and L.M. Miller and M. D'Esposito (2005). Measuring temporal dynamics of functional networks using phase spectrum of fMRI data. Neuroimage, 28: 227-37. """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) #A container for the coherencys, with the size and shape of the expected #output: c = np.zeros((time_series.shape[0], time_series.shape[0], f.shape[0]), dtype=complex) # Make sure it's complex for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): c[i][j] = coherency_spec(fxy[i][j], fxy[i][i], fxy[j][j]) idx = tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return f, c
def coherency_phase_spectrum(time_series, csd_method=None): r""" Compute the phase spectrum of the cross-spectrum between two time series. The parameters of this function are in the time domain. Parameters ---------- time_series: n*t float array The time series, with t, time, as the last dimension Returns ------- f: mid frequencies of the bands p: an array with the pairwise phase spectrum between the time series, where p[i][j] is the phase spectrum between time series[i] and time_series[j] Notes ----- This is an implementation of equation (3) of Sun et al. (2005) [Sun2005]_: .. math:: \phi(\lambda) = arg [R_{xy} (\lambda)] = arg [f_{xy} (\lambda)] F.T. Sun and L.M. Miller and M. D'Esposito (2005). Measuring temporal dynamics of functional networks using phase spectrum of fMRI data. Neuroimage, 28: 227-37. """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) p = np.zeros((time_series.shape[0], time_series.shape[0], f.shape[0])) for i in xrange(time_series.shape[0]): for j in xrange(i + 1, time_series.shape[0]): p[i][j] = np.angle(fxy[i][j]) p[j][i] = np.angle(fxy[i][j].conjugate()) return f, p
def coherence_bavg(time_series, lb=0, ub=None, csd_method=None): r""" Compute the band-averaged coherence between the spectra of two time series. Input to this function is in the time domain. Parameters ---------- time_series : float array An array of time series, time as the last dimension. lb, ub: float, optional The upper and lower bound on the frequency band to be used in averaging defaults to 1,max(f) csd_method: dict, optional. See :func:`get_spectra` documentation for details Returns ------- c : float This is an upper-diagonal array, where c[i][j] is the band-averaged coherency between time_series[i] and time_series[j] """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) lb_idx, ub_idx = utils.get_bounds(f, lb, ub) if lb == 0: lb_idx = 1 # The lowest frequency band should be f0 c = np.zeros((time_series.shape[0], time_series.shape[0])) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): c[i][j] = _coherence_bavg(fxy[i][j][lb_idx:ub_idx], fxy[i][i][lb_idx:ub_idx], fxy[j][j][lb_idx:ub_idx]) idx = tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return c
def coherency_phase_delay(time_series, lb=0, ub=None, csd_method=None): """ The temporal delay calculated from the coherency phase spectrum. Parameters ---------- time_series: float array The time-series data for which the delay is calculated. lb, ub: float Frequency boundaries (in Hz), for the domain over which the delays are calculated. Defaults to 0-max(f) csd_method : dict, optional. See :func:`get_spectra` Returns ------- f : float array The mid-frequencies for the frequency bands over which the calculation is done. p : float array Pairwise temporal delays between time-series (in seconds). """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) lb_idx, ub_idx = utils.get_bounds(f, lb, ub) if lb_idx == 0: lb_idx = 1 p = np.zeros((time_series.shape[0], time_series.shape[0], f[lb_idx:ub_idx].shape[-1])) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): p[i][j] = _coherency_phase_delay(f[lb_idx:ub_idx], fxy[i][j][lb_idx:ub_idx]) p[j][i] = _coherency_phase_delay(f[lb_idx:ub_idx], fxy[i][j][lb_idx:ub_idx].conjugate()) return f[lb_idx:ub_idx], p
def coherency_phase_delay(time_series, lb=0, ub=None, csd_method=None): """ The temporal delay calculated from the coherency phase spectrum. Parameters ---------- time_series: float array The time-series data for which the delay is calculated. lb, ub: float Frequency boundaries (in Hz), for the domain over which the delays are calculated. Defaults to 0-max(f) csd_method : dict, optional. See :func:`get_spectra` Returns ------- f : float array The mid-frequencies for the frequency bands over which the calculation is done. p : float array Pairwise temporal delays between time-series (in seconds). """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) lb_idx, ub_idx = utils.get_bounds(f, lb, ub) if lb_idx == 0: lb_idx = 1 p = np.zeros((time_series.shape[0], time_series.shape[0], f[lb_idx:ub_idx].shape[-1])) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): p[i][j] = _coherency_phase_delay(f[lb_idx:ub_idx], fxy[i][j][lb_idx:ub_idx]) p[j][i] = _coherency_phase_delay( f[lb_idx:ub_idx], fxy[i][j][lb_idx:ub_idx].conjugate()) return f[lb_idx:ub_idx], p
def coherence_partial(time_series, r, csd_method=None): r""" Compute the band-specific partial coherence between the spectra of two time series. The partial coherence is the part of the coherence between x and y, which cannot be attributed to a common cause, r. Input to this function is in the time domain. Parameters ---------- time_series: float array An array of time-series, with time as the last dimension. r: float array This array represents the temporal sequence of the common cause to be partialed out, sampled at the same rate as time_series csd_method: dict, optional See :func:`get_spectra` documentation for details Returns ------- f: array, The mid-frequencies of the frequency bands in the spectral decomposition c: float array The frequency dependent partial coherence between time_series i and time_series j in c[i][j] and in c[j][i], with r partialed out Notes ----- This is an implementation of equation (2) of Sun (2004): .. math:: Coh_{xy|r} = \frac{|{R_{xy}(\lambda) - R_{xr}(\lambda) R_{ry}(\lambda)}|^2}{(1-|{R_{xr}}|^2)(1-|{R_{ry}}|^2)} F.T. Sun and L.M. Miller and M. D'Esposito (2004). Measuring interregional functional connectivity using coherence and partial coherence analyses of fMRI data Neuroimage, 21: 647-58. """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) # Initialize c according to the size of f: c = np.zeros((time_series.shape[0], time_series.shape[0], f.shape[0]), dtype=complex) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): f, fxx, frr, frx = get_spectra_bi(time_series[i], r, csd_method) f, fyy, frr, fry = get_spectra_bi(time_series[j], r, csd_method) c[i, j] = coherence_partial_spec(fxy[i][j], fxy[i][i], fxy[j][j], frx, fry, frr) idx = tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return f, c
def coherency_bavg(time_series, lb=0, ub=None, csd_method=None): r""" Compute the band-averaged coherency between the spectra of two time series. Input to this function is in the time domain. Parameters ---------- time_series: n*t float array an array of n different time series of length t each lb, ub: float, optional the upper and lower bound on the frequency band to be used in averaging defaults to 1,max(f) csd_method: dict, optional. See :func:`get_spectra` documentation for details Returns ------- c: float array This is an upper-diagonal array, where c[i][j] is the band-averaged coherency between time_series[i] and time_series[j] Notes ----- This is an implementation of equation (A4) of Sun(2005): .. math:: \bar{Coh_{xy}} (\bar{\lambda}) = \frac{\left|{\sum_\lambda{\hat{f_{xy}}}}\right|^2} {\sum_\lambda{\hat{f_{xx}}}\cdot sum_\lambda{\hat{f_{yy}}}} F.T. Sun and L.M. Miller and M. D'Esposito (2005). Measuring temporal dynamics of functional networks using phase spectrum of fMRI data. Neuroimage, 28: 227-37. """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) lb_idx, ub_idx = utils.get_bounds(f, lb, ub) if lb == 0: lb_idx = 1 # The lowest frequency band should be f0 c = np.zeros((time_series.shape[0], time_series.shape[0]), dtype=complex) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): c[i][j] = _coherency_bavg(fxy[i][j][lb_idx:ub_idx], fxy[i][i][lb_idx:ub_idx], fxy[j][j][lb_idx:ub_idx]) idx = tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return c
def coherence_regularized(time_series, epsilon, alpha, csd_method=None): r""" Same as coherence, except regularized in order to overcome numerical imprecisions Parameters ---------- time_series: n-d float array The time series data for which the regularized coherence is calculated epsilon: float Small regularization parameter. Should be much smaller than any meaningful value of coherence you might encounter alpha: float large regularization parameter. Should be much larger than any meaningful value of coherence you might encounter (preferably much larger than 1). csd_method: dict, optional. See :func:`get_spectra` documentation for details Returns ------- f: float array The central frequencies for the frequency bands for which the spectra are estimated c: n-d array This is a symmetric matrix with the coherencys of the signals. The coherency of signal i and signal j is in f[i][j]. Returns ------- frequencies, coherence Notes ----- The regularization scheme is as follows: .. math:: C_{x,y} = \frac{(\alpha f_{xx} + \epsilon)^2} {\alpha^{2}((f_{xx}+\epsilon)(f_{yy}+\epsilon))} """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) #A container for the coherences, with the size and shape of the expected #output: c = np.zeros((time_series.shape[0], time_series.shape[0], f.shape[0]), complex) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): c[i][j] = _coherence_reqularized(fxy[i][j], fxy[i][i], fxy[j][j], epsilon, alpha) idx = tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return f, c
def coherence(time_series, csd_method=None): r"""Compute the coherence between the spectra of an n-tuple of time_series. Parameters of this function are in the time domain. Parameters ---------- time_series: float array an array of different time series with time as the last dimension csd_method: dict, optional See :func:`get_spectra` documentation for details Returns ------- f : float array The central frequencies for the frequency bands for which the spectra are estimated c : float array This is a symmetric matrix with the coherencys of the signals. The coherency of signal i and signal j is in f[i][j]. Notes ----- This is an implementation of equation (2) of [Sun2005]_: .. math:: Coh_{xy}(\lambda) = |{R_{xy}(\lambda)}|^2 = \frac{|{f_{xy}(\lambda)}|^2}{f_{xx}(\lambda) \cdot f_{yy}(\lambda)} .. [Sun2005] F.T. Sun and L.M. Miller and M. D'Esposito(2005). Measuring temporal dynamics of functional networks using phase spectrum of fMRI data. Neuroimage, 28: 227-37. See also -------- :func:`coherence_spec` """ if csd_method is None: csd_method = {'this_method': 'welch'} # The default f, fxy = get_spectra(time_series, csd_method) #A container for the coherences, with the size and shape of the expected #output: c = np.zeros((time_series.shape[0], time_series.shape[0], f.shape[0])) for i in xrange(time_series.shape[0]): for j in xrange(i, time_series.shape[0]): c[i][j] = coherence_spec(fxy[i][j], fxy[i][i], fxy[j][j]) idx = np.tril_indices(time_series.shape[0], -1) c[idx[0], idx[1], ...] = c[idx[1], idx[0], ...].conj() # Make it symmetric return f, c