Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b7ad379

Browse files
committed
applied Ariel's mlab.cohere_pairs fixes
svn path=/branches/v0_99_maint/; revision=7522
1 parent 4d6d9ff commit b7ad379

1 file changed

Lines changed: 67 additions & 63 deletions

File tree

lib/matplotlib/mlab.py

Lines changed: 67 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
649653
def entropy(y, bins):
650654
r"""
651655
Return the entropy of the data in *y*.

0 commit comments

Comments
 (0)