@@ -501,70 +501,76 @@ def cohere_pairs( X, ij, NFFT=256, Fs=2, detrend=detrend_none,
501501 returnPxx = False ):
502502
503503 u"""
504- Cxy, Phase, freqs = cohere_pairs(X, ij, ...)
504+ Cxy, Phase, freqs = cohere_pairs( X, ij, ...)
505505
506- Compute the coherence for all pairs in *ij*. *X* is a
507- (*numSamples*, *numCols*) numpy array. *ij* is a list of tuples
508- (*i*, *j*). Each tuple is a pair of indexes into the columns of *X*
509- for which you want to compute coherence. For example, if *X* has 64
510- columns, and you want to compute all nonredundant pairs, define *ij*
511- as::
506+ Compute the coherence and phase for all pairs ij, in X.
507+
508+ Parameters
509+ ----------
510+ X: array
511+ a numSamples*numCols array
512+
513+ ij: list of tuples
514+ Each tuple is a pair of indexes into the columns of X for which you want to
515+ compute coherence. For example, if X has 64 columns, and you want to
516+ compute all nonredundant pairs, define ij as
512517
513518 ij = []
514519 for i in range(64):
515520 for j in range(i+1,64):
516- ij.append( (i, j) )
517-
518- The other function arguments, except for *preferSpeedOverMemory*
519- (see below), are explained in the help string of :func:`psd`.
521+ ij.append( (i,j) )
522+
523+ preferSpeedOverMemory: optional, bool
524+
525+ Defaults to true. If false, limits the caching by only making one, rather
526+ than two, complex cache arrays. This is useful if memory becomes critical.
527+ Even when preferSpeedOverMemory is false, cohere_pairs will still give
528+ significant performace gains over calling cohere for each pair, and will
529+ use subtantially less memory than if preferSpeedOverMemory is true. In my
530+ tests with a 43000,64 array over all nonredundant pairs,
531+ preferSpeedOverMemory=1 delivered a 33% performace boost on a 1.7GHZ Athlon
532+ with 512MB RAM compared with preferSpeedOverMemory=0. But both solutions
533+ were more than 10x faster than naievly crunching all possible pairs through
534+ cohere.
535+
536+ Returns
537+ -------
520538
521- Return value is a tuple (*Cxy*, *Phase*, *freqs*).
539+ (Cxy, Phase, freqs), where:
540+
541+ Cxy: dictionary of (i,j) tuples -> coherence vector for that
542+ pair. Ie, Cxy[(i,j) = cohere(X[:,i], X[:,j]). Number of
543+ dictionary keys is len(ij)
522544
523- - *Cxy*: a dictionary of (*i*, *j*) tuples -> coherence vector for that
524- pair. I.e., ``Cxy[(i,j)] = cohere(X[:,i], X[:,j])``. Number of
525- dictionary keys is ``len(ij)``.
545+ Phase: dictionary of phases of the cross spectral density at
546+ each frequency for each pair. keys are (i,j).
526547
527- - *Phase*: a dictionary of phases of the cross spectral density at
528- each frequency for each pair. The keys are ``( i,j)`` .
548+ freqs: vector of frequencies, equal in length to either the
549+ coherence or phase vectors for any i,j key .
529550
530- - *freqs*: a vector of frequencies, equal in length to either
531- the coherence or phase vectors for any (*i*, *j*) key.. Eg,
532- to make a coherence Bode plot::
551+ Eg, to make a coherence Bode plot:
533552
534553 subplot(211)
535554 plot( freqs, Cxy[(12,19)])
536555 subplot(212)
537556 plot( freqs, Phase[(12,19)])
538557
539- For a large number of pairs, :func:`cohere_pairs` can be much more
540- efficient than just calling :func:`cohere` for each pair, because
541- it caches most of the intensive computations. If *N* is the
542- number of pairs, this function is O(N) for most of the heavy
543- lifting, whereas calling cohere for each pair is
544- O(N\N{SUPERSCRIPT TWO} ). However, because of the caching, it is
545- also more memory intensive, making 2 additional complex arrays
546- with approximately the same number of elements as *X*.
547-
548- The parameter *preferSpeedOverMemory*, if *False*, limits the
549- caching by only making one, rather than two, complex cache arrays.
550- This is useful if memory becomes critical. Even when
551- *preferSpeedOverMemory* is *False*, :func:`cohere_pairs` will
552- still give significant performace gains over calling
553- :func:`cohere` for each pair, and will use subtantially less
554- memory than if *preferSpeedOverMemory* is *True*. In my tests
555- with a (43000, 64) array over all non-redundant pairs,
556- *preferSpeedOverMemory* = *True* delivered a 33% performace boost
557- on a 1.7GHZ Athlon with 512MB RAM compared with
558- *preferSpeedOverMemory* = *False*. But both solutions were more
559- than 10x faster than naievly crunching all possible pairs through
560- cohere.
561-
562- .. seealso::
563-
564- :file:`test/cohere_pairs_test.py` in the src tree
565- For an example script that shows that this
566- :func:`cohere_pairs` and :func:`cohere` give the same
567- results for a given pair.
558+ For a large number of pairs, cohere_pairs can be much more
559+ efficient than just calling cohere for each pair, because it
560+ caches most of the intensive computations. If N is the number of
561+ pairs, this function is O(N) for most of the heavy lifting,
562+ whereas calling cohere for each pair is O(N^2). However, because
563+ of the caching, it is also more memory intensive, making 2
564+ additional complex arrays with approximately the same number of
565+ elements as X.
566+
567+ See test/cohere_pairs_test.py in the src tree for an example
568+ script that shows that this cohere_pairs and cohere give the same
569+ results for a given pair.
570+
571+ See also
572+ --------
573+ :func: psd
568574 """
569575 numRows , numCols = X .shape
570576
@@ -578,12 +584,10 @@ def cohere_pairs( X, ij, NFFT=256, Fs=2, detrend=detrend_none,
578584 numRows , numCols = X .shape
579585 # get all the columns of X that we are interested in by checking
580586 # the ij tuples
581- seen = {}
587+ allColumns = set ()
582588 for i ,j in ij :
583- seen [i ]= 1 ; seen [j ] = 1
584- allColumns = seen .keys ()
589+ allColumns .add (i ); allColumns .add (j )
585590 Ncols = len (allColumns )
586- del seen
587591
588592 # for real X, ignore the negative frequencies
589593 if np .iscomplexobj (X ): numFreqs = NFFT
@@ -596,26 +600,26 @@ def cohere_pairs( X, ij, NFFT=256, Fs=2, detrend=detrend_none,
596600 assert (len (window ) == NFFT )
597601 windowVals = window
598602 else :
599- windowVals = window (np .ones (( NFFT ,), typecode ( X ) ))
603+ windowVals = window (np .ones (NFFT , X . dtype ))
600604 ind = range (0 , numRows - NFFT + 1 , NFFT - noverlap )
601605 numSlices = len (ind )
602606 FFTSlices = {}
603607 FFTConjSlices = {}
604608 Pxx = {}
605609 slices = range (numSlices )
606- normVal = norm (windowVals )** 2
610+ normVal = np . linalg . norm (windowVals )** 2
607611 for iCol in allColumns :
608612 progressCallback (i / Ncols , 'Cacheing FFTs' )
609613 Slices = np .zeros ( (numSlices ,numFreqs ), dtype = np .complex_ )
610614 for iSlice in slices :
611615 thisSlice = X [ind [iSlice ]:ind [iSlice ]+ NFFT , iCol ]
612616 thisSlice = windowVals * detrend (thisSlice )
613- Slices [iSlice ,:] = fft (thisSlice )[:numFreqs ]
617+ Slices [iSlice ,:] = np . fft . fft (thisSlice )[:numFreqs ]
614618
615619 FFTSlices [iCol ] = Slices
616620 if preferSpeedOverMemory :
617- FFTConjSlices [iCol ] = conjugate (Slices )
618- Pxx [iCol ] = np .divide (np .mean (absolute (Slices )** 2 ), normVal )
621+ FFTConjSlices [iCol ] = np . conjugate (Slices )
622+ Pxx [iCol ] = np .divide (np .mean (abs (Slices )** 2 ), normVal )
619623 del Slices , ind , windowVals
620624
621625 # compute the coherences and phases for all pairs using the
@@ -634,18 +638,18 @@ def cohere_pairs( X, ij, NFFT=256, Fs=2, detrend=detrend_none,
634638 else :
635639 Pxy = FFTSlices [i ] * np .conjugate (FFTSlices [j ])
636640 if numSlices > 1 : Pxy = np .mean (Pxy )
637- Pxy = np .divide (Pxy , normVal )
638- Cxy [(i ,j )] = np .divide (np .absolute (Pxy )** 2 , Pxx [i ]* Pxx [j ])
639- Phase [(i ,j )] = np .arctan2 (Pxy .imag , Pxy .real )
641+ #Pxy = np.divide(Pxy, normVal)
642+ Pxy /= normVal
643+ #Cxy[(i,j)] = np.divide(np.absolute(Pxy)**2, Pxx[i]*Pxx[j])
644+ Cxy [i ,j ] = abs (Pxy )** 2 / (Pxx [i ]* Pxx [j ])
645+ Phase [i ,j ] = np .arctan2 (Pxy .imag , Pxy .real )
640646
641647 freqs = Fs / NFFT * np .arange (numFreqs )
642648 if returnPxx :
643649 return Cxy , Phase , freqs , Pxx
644650 else :
645651 return Cxy , Phase , freqs
646652
647-
648-
649653def entropy (y , bins ):
650654 r"""
651655 Return the entropy of the data in *y*.
0 commit comments