@@ -67,8 +67,8 @@ def coherency(time_series, csd_method=None):
67
67
68
68
f , fxy = get_spectra (time_series , csd_method )
69
69
70
- #A container for the coherencys, with the size and shape of the expected
71
- #output:
70
+ # A container for the coherencys, with the size and shape of the expected
71
+ # output:
72
72
c = np .zeros ((time_series .shape [0 ],
73
73
time_series .shape [0 ],
74
74
f .shape [0 ]), dtype = complex ) # Make sure it's complex
@@ -108,7 +108,6 @@ def coherency_spec(fxy, fxx, fyy):
108
108
--------
109
109
:func:`coherency`
110
110
"""
111
-
112
111
return fxy / np .sqrt (fxx * fyy )
113
112
114
113
@@ -275,7 +274,6 @@ def coherency_regularized(time_series, epsilon, alpha, csd_method=None):
275
274
276
275
277
276
def _coherency_reqularized (fxy , fxx , fyy , epsilon , alpha ):
278
-
279
277
r"""
280
278
A regularized version of the calculation of coherency, which is more
281
279
robust to numerical noise than the standard calculation
@@ -303,9 +301,8 @@ def _coherency_reqularized(fxy, fxx, fyy, epsilon, alpha):
303
301
The coherence values
304
302
305
303
"""
306
-
307
304
return (((alpha * fxy + epsilon )) /
308
- np .sqrt (((alpha ** 2 ) * (fxx + epsilon ) * (fyy + epsilon ))))
305
+ np .sqrt (((alpha ** 2 ) * (fxx + epsilon ) * (fyy + epsilon ))))
309
306
310
307
311
308
def coherence_regularized (time_series , epsilon , alpha , csd_method = None ):
@@ -341,9 +338,6 @@ def coherence_regularized(time_series, epsilon, alpha, csd_method=None):
341
338
This is a symmetric matrix with the coherencys of the signals. The
342
339
coherency of signal i and signal j is in f[i][j].
343
340
344
- Returns
345
- -------
346
- frequencies, coherence
347
341
348
342
Notes
349
343
-----
@@ -360,8 +354,8 @@ def coherence_regularized(time_series, epsilon, alpha, csd_method=None):
360
354
361
355
f , fxy = get_spectra (time_series , csd_method )
362
356
363
- #A container for the coherences, with the size and shape of the expected
364
- #output:
357
+ # A container for the coherences, with the size and shape of the expected
358
+ # output:
365
359
c = np .zeros ((time_series .shape [0 ],
366
360
time_series .shape [0 ],
367
361
f .shape [0 ]), complex )
@@ -378,7 +372,6 @@ def coherence_regularized(time_series, epsilon, alpha, csd_method=None):
378
372
379
373
380
374
def _coherence_reqularized (fxy , fxx , fyy , epsilon , alpha ):
381
-
382
375
r"""A regularized version of the calculation of coherence, which is more
383
376
robust to numerical noise than the standard calculation.
384
377
@@ -406,7 +399,7 @@ def _coherence_reqularized(fxy, fxx, fyy, epsilon, alpha):
406
399
407
400
"""
408
401
return (((alpha * np .abs (fxy ) + epsilon ) ** 2 ) /
409
- ((alpha ** 2 ) * (fxx + epsilon ) * (fyy + epsilon )))
402
+ ((alpha ** 2 ) * (fxx + epsilon ) * (fyy + epsilon )))
410
403
411
404
412
405
def coherency_bavg (time_series , lb = 0 , ub = None , csd_method = None ):
@@ -509,7 +502,6 @@ def _coherency_bavg(fxy, fxx, fyy):
509
502
temporal dynamics of functional networks using phase spectrum of fMRI
510
503
data. Neuroimage, 28: 227-37.
511
504
"""
512
-
513
505
# Average the phases and the magnitudes separately and then recombine:
514
506
515
507
p = np .angle (fxy )
@@ -519,7 +511,7 @@ def _coherency_bavg(fxy, fxx, fyy):
519
511
m_bavg = np .mean (m )
520
512
521
513
# Recombine according to z = r(cos(phi)+sin(phi)i):
522
- return m_bavg * (np .cos (p_bavg ) + np .sin (p_bavg ) * 1j )
514
+ return m_bavg * (np .cos (p_bavg ) + np .sin (p_bavg ) * 1j )
523
515
524
516
525
517
def coherence_bavg (time_series , lb = 0 , ub = None , csd_method = None ):
@@ -546,7 +538,6 @@ def coherence_bavg(time_series, lb=0, ub=None, csd_method=None):
546
538
This is an upper-diagonal array, where c[i][j] is the band-averaged
547
539
coherency between time_series[i] and time_series[j]
548
540
"""
549
-
550
541
if csd_method is None :
551
542
csd_method = {'this_method' : 'welch' } # The default
552
543
@@ -575,7 +566,8 @@ def coherence_bavg(time_series, lb=0, ub=None, csd_method=None):
575
566
def _coherence_bavg (fxy , fxx , fyy ):
576
567
r"""
577
568
Compute the band-averaged coherency between the spectra of two time series.
578
- input to this function is in the frequency domain
569
+
570
+ Input to this function is in the frequency domain
579
571
580
572
Parameters
581
573
----------
@@ -649,7 +641,6 @@ def coherence_partial(time_series, r, csd_method=None):
649
641
functional connectivity using coherence and partial coherence analyses of
650
642
fMRI data Neuroimage, 21: 647-58.
651
643
"""
652
-
653
644
if csd_method is None :
654
645
csd_method = {'this_method' : 'welch' } # The default
655
646
@@ -664,8 +655,12 @@ def coherence_partial(time_series, r, csd_method=None):
664
655
for j in range (i , time_series .shape [0 ]):
665
656
f , fxx , frr , frx = get_spectra_bi (time_series [i ], r , csd_method )
666
657
f , fyy , frr , fry = get_spectra_bi (time_series [j ], r , csd_method )
667
- c [i , j ] = coherence_partial_spec (fxy [i ][j ], fxy [i ][i ],
668
- fxy [j ][j ], frx , fry , frr )
658
+ c [i , j ] = coherence_partial_spec (fxy [i ][j ],
659
+ fxy [i ][i ],
660
+ fxy [j ][j ],
661
+ frx ,
662
+ fry ,
663
+ frr )
669
664
670
665
idx = tril_indices (time_series .shape [0 ], - 1 )
671
666
c [idx [0 ], idx [1 ], ...] = c [idx [1 ], idx [0 ], ...].conj () # Make it symmetric
@@ -702,7 +697,7 @@ def coherence_partial_spec(fxy, fxx, fyy, fxr, fry, frr):
702
697
Rxy = coh (fxy , fxx , fyy )
703
698
704
699
return (((np .abs (Rxy - Rxr * Rry )) ** 2 ) /
705
- ((1 - ((np .abs (Rxr )) ** 2 )) * (1 - ((np .abs (Rry )) ** 2 ))))
700
+ ((1 - ((np .abs (Rxr )) ** 2 )) * (1 - ((np .abs (Rry )) ** 2 ))))
706
701
707
702
708
703
def coherency_phase_spectrum (time_series , csd_method = None ):
@@ -799,8 +794,9 @@ def coherency_phase_delay(time_series, lb=0, ub=None, csd_method=None):
799
794
for j in range (i , time_series .shape [0 ]):
800
795
p [i ][j ] = _coherency_phase_delay (f [lb_idx :ub_idx ],
801
796
fxy [i ][j ][lb_idx :ub_idx ])
802
- p [j ][i ] = _coherency_phase_delay (f [lb_idx :ub_idx ],
803
- fxy [i ][j ][lb_idx :ub_idx ].conjugate ())
797
+ p [j ][i ] = _coherency_phase_delay (
798
+ f [lb_idx :ub_idx ],
799
+ fxy [i ][j ][lb_idx :ub_idx ].conjugate ())
804
800
805
801
return f [lb_idx :ub_idx ], p
806
802
@@ -826,7 +822,6 @@ def _coherency_phase_delay(f, fxy):
826
822
the phase delay (in sec) for each frequency band.
827
823
828
824
"""
829
-
830
825
return np .angle (fxy ) / (2 * np .pi * f )
831
826
832
827
@@ -861,9 +856,7 @@ def correlation_spectrum(x1, x2, Fs=2 * np.pi, norm=False):
861
856
J Wendt, P A Turski, C H Moritz, M A Quigley, M E Meyerand (2000). Mapping
862
857
functionally related regions of brain with functional connectivity MR
863
858
imaging. AJNR American journal of neuroradiology 21:1636-44
864
-
865
859
"""
866
-
867
860
x1 = x1 - np .mean (x1 )
868
861
x2 = x2 - np .mean (x2 )
869
862
x1_f = fftpack .fft (x1 )
@@ -876,18 +869,18 @@ def correlation_spectrum(x1, x2, Fs=2 * np.pi, norm=False):
876
869
(D * n ))
877
870
878
871
if norm :
879
- ccn = ccn / np . sum ( ccn ) * 2 # Only half of the sum is sent back
880
- # because of the freq domain symmetry.
881
- # XXX Does normalization make this
882
- # strictly positive?
872
+ # Only half of the sum is sent back because of the freq domain
873
+ # symmetry.
874
+ ccn = ccn / np . sum ( ccn ) * 2
875
+ # XXX Does normalization make this strictly positive?
883
876
884
877
f = utils .get_freqs (Fs , n )
885
878
return f , ccn [0 :(n // 2 + 1 )]
886
879
887
880
888
- #- -----------------------------------------------------------------------
889
- #Coherency calculated using cached spectra
890
- #- -----------------------------------------------------------------------
881
+ # -----------------------------------------------------------------------
882
+ # Coherency calculated using cached spectra
883
+ # -----------------------------------------------------------------------
891
884
"""The idea behind this set of functions is to keep a cache of the windowed fft
892
885
calculations of each time-series in a massive collection of time-series, so
893
886
that this calculation doesn't have to be repeated each time a cross-spectrum is
@@ -898,8 +891,8 @@ def correlation_spectrum(x1, x2, Fs=2 * np.pi, norm=False):
898
891
899
892
900
893
def cache_fft (time_series , ij , lb = 0 , ub = None ,
901
- method = None , prefer_speed_over_memory = False ,
902
- scale_by_freq = True ):
894
+ method = None , prefer_speed_over_memory = False ,
895
+ scale_by_freq = True ):
903
896
"""compute and cache the windowed FFTs of the time_series, in such a way
904
897
that computing the psd and csd of any combination of them can be done
905
898
quickly.
@@ -957,7 +950,7 @@ def cache_fft(time_series, ij, lb=0, ub=None,
957
950
raise ValueError (e_s )
958
951
time_series = utils .zero_pad (time_series , NFFT )
959
952
960
- #The shape of the zero-padded version:
953
+ # The shape of the zero-padded version:
961
954
n_channels , n_time_points = time_series .shape
962
955
963
956
# get all the unique channels in time_series that we are interested in by
@@ -973,30 +966,30 @@ def cache_fft(time_series, ij, lb=0, ub=None,
973
966
else :
974
967
n_freqs = NFFT // 2 + 1
975
968
976
- #Which frequencies
969
+ # Which frequencies
977
970
freqs = utils .get_freqs (Fs , NFFT )
978
971
979
- #If there are bounds, limit the calculation to within that band,
980
- #potentially include the DC component:
972
+ # If there are bounds, limit the calculation to within that band,
973
+ # potentially include the DC component:
981
974
lb_idx , ub_idx = utils .get_bounds (freqs , lb , ub )
982
975
983
976
n_freqs = ub_idx - lb_idx
984
- #Make the window:
977
+ # Make the window:
985
978
if mlab .cbook .iterable (window ):
986
979
assert (len (window ) == NFFT )
987
980
window_vals = window
988
981
else :
989
982
window_vals = window (np .ones (NFFT , time_series .dtype ))
990
983
991
- #Each fft needs to be normalized by the square of the norm of the window
992
- #and, for consistency with newer versions of mlab.csd (which, in turn, are
993
- #consistent with Matlab), normalize also by the sampling rate:
984
+ # Each fft needs to be normalized by the square of the norm of the window
985
+ # and, for consistency with newer versions of mlab.csd (which, in turn, are
986
+ # consistent with Matlab), normalize also by the sampling rate:
994
987
995
988
if scale_by_freq :
996
- #This is the normalization factor for one-sided estimation, taking into
997
- #account the sampling rate. This makes the PSD a density function, with
998
- #units of dB/Hz, so that integrating over frequencies gives you the RMS
999
- #(XXX this should be in the tests!).
989
+ # This is the normalization factor for one-sided estimation, taking
990
+ # into account the sampling rate. This makes the PSD a density
991
+ # function, with units of dB/Hz, so that integrating over
992
+ # frequencies gives you the RMS. (XXX this should be in the tests!).
1000
993
norm_val = (np .abs (window_vals ) ** 2 ).sum () * (Fs / 2 )
1001
994
1002
995
else :
@@ -1012,16 +1005,14 @@ def cache_fft(time_series, ij, lb=0, ub=None,
1012
1005
FFT_conj_slices = {}
1013
1006
1014
1007
for i_channel in all_channels :
1015
- #dbg:
1016
- #print i_channel
1017
1008
Slices = np .zeros ((n_slices , n_freqs ), dtype = np .complex )
1018
1009
for iSlice in range (n_slices ):
1019
1010
thisSlice = time_series [i_channel ,
1020
1011
i_times [iSlice ]:i_times [iSlice ] + NFFT ]
1021
1012
1022
- #Windowing:
1013
+ # Windowing:
1023
1014
thisSlice = window_vals * thisSlice # No detrending
1024
- #Derive the fft for that slice:
1015
+ # Derive the fft for that slice:
1025
1016
Slices [iSlice , :] = (fftpack .fft (thisSlice )[lb_idx :ub_idx ])
1026
1017
1027
1018
FFT_slices [i_channel ] = Slices
@@ -1068,15 +1059,13 @@ def cache_to_psd(cache, ij):
1068
1059
all_channels .add (j )
1069
1060
1070
1061
for i in all_channels :
1071
- #dbg:
1072
- #print i
1073
- #If we made the conjugate slices:
1062
+ # If we made the conjugate slices:
1074
1063
if FFT_conj_slices :
1075
1064
Pxx [i ] = FFT_slices [i ] * FFT_conj_slices [i ]
1076
1065
else :
1077
1066
Pxx [i ] = FFT_slices [i ] * np .conjugate (FFT_slices [i ])
1078
1067
1079
- #If there is more than one window
1068
+ # If there is more than one window
1080
1069
if FFT_slices [i ].shape [0 ] > 1 :
1081
1070
Pxx [i ] = np .mean (Pxx [i ], 0 )
1082
1071
@@ -1123,7 +1112,7 @@ def cache_to_phase(cache, ij):
1123
1112
1124
1113
for i in all_channels :
1125
1114
Phase [i ] = np .angle (FFT_slices [i ])
1126
- #If there is more than one window, average over all the windows:
1115
+ # If there is more than one window, average over all the windows:
1127
1116
if FFT_slices [i ].shape [0 ] > 1 :
1128
1117
Phase [i ] = np .mean (Phase [i ], 0 )
1129
1118
@@ -1171,10 +1160,10 @@ def cache_to_relative_phase(cache, ij):
1171
1160
1172
1161
channels_i = max (1 , max (ij_array [:, 0 ]) + 1 )
1173
1162
channels_j = max (1 , max (ij_array [:, 1 ]) + 1 )
1174
- #Pre-allocate for speed:
1163
+ # Pre-allocate for speed:
1175
1164
Phi_xy = np .zeros ((channels_i , channels_j , freqs ), dtype = np .complex )
1176
1165
1177
- #These checks take time, so do them up front, not in every iteration:
1166
+ # These checks take time, so do them up front, not in every iteration:
1178
1167
if list (FFT_slices .items ())[0 ][1 ].shape [0 ] > 1 :
1179
1168
if FFT_conj_slices :
1180
1169
for i , j in ij :
0 commit comments