From: <ry...@us...> - 2008-11-11 18:42:16
|
Revision: 6392 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6392&view=rev Author: ryanmay Date: 2008-11-11 18:42:11 +0000 (Tue, 11 Nov 2008) Log Message: ----------- Update the mlab.csd() to match the new options added to mlab.psd(). Factor out the keyword argument docs so that they can be shared between the two functions. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/mlab.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-11 18:39:46 UTC (rev 6391) +++ trunk/matplotlib/CHANGELOG 2008-11-11 18:42:11 UTC (rev 6392) @@ -1,3 +1,7 @@ +2008-11-11 Update the mlab.csd() to match the new options added to + mlab.psd(). Factor out the keyword argument docs so that + they can be shared between the two functions. - RM + 2008-11-11 Update the axes.psd() method to reflect the new options available in mlab.psd. Add an example to show how the options change things. - RM Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-11 18:39:46 UTC (rev 6391) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-11 18:42:11 UTC (rev 6392) @@ -252,51 +252,7 @@ *x* Array or sequence containing the data - - *NFFT* - The number of data points used in each block for the FFT. - Must be even; a power 2 is most efficient. The default value is 256. - - *Fs* - The sampling frequency (samples per time unit). It is used - to calculate the Fourier frequencies, freqs, in cycles per time - unit. The default value is 2. - - *detrend* - Any callable function (unlike in matlab where it is a vector). - For examples, see :func:`detrend`, :func:`detrend_none`, and - :func:`detrend_mean`. The default is :func:`detrend_none`. - - *window* - A function or a vector of length *NFFT*. To create window - vectors see :func:`window_hanning`, :func:`window_none`, - :func:`numpy.blackman`, :func:`numpy.hamming`, - :func:`numpy.bartlett`, :func:`scipy.signal`, - :func:`scipy.signal.get_window`, etc. The default is - :func:`window_hanning`. If a function is passed as the - argument, it must take a data segment as an argument and - return the windowed version of the segment. - - *noverlap* - The number of points of overlap between blocks. The default value - is 0 (no overlap). - - *pad_to* - The number of points to which the data segment is padd when - performing the FFT. This can be different from *NFFT*, which - specifies the number of data points used. While not increasing - the actual resolution of the psd (the minimum distance between - resolvable peaks), this can give more points in the plot, - allowing for more detail. This corresponds to the *n* parameter - in the call to fft(). The default is None, which sets *pad_to* - equal to *NFFT* - - *sides* [ 'default' | 'onesided' | 'twosided' ] - Specifies which sides of the PSD to return. Default gives the - default behavior, which returns one-sided for real data and both - for complex data. 'one' forces the return of a one-sided PSD, while - 'both' forces two-sided. - + %(PSD)s Returns the tuple (*Pxx*, *freqs*). Refs: @@ -314,14 +270,14 @@ if pad_to is None: pad_to = NFFT - # for real x, ignore the negative frequencies + # For real x, ignore the negative frequencies unless told otherwise if (sides == 'default' and np.iscomplexobj(x)) or sides == 'twosided': numFreqs = pad_to elif sides in ('default', 'onesided'): numFreqs = pad_to//2 + 1 else: raise ValueError("sides must be one of: 'default', 'onesided', or " - "twosided") + "'twosided'") if cbook.iterable(window): assert(len(window) == NFFT) @@ -351,23 +307,9 @@ return Pxx, freqs -def csd(x, y, NFFT=256, Fs=2, detrend=detrend_none, - window=window_hanning, noverlap=0): - """ - The cross power spectral density by Welch's average periodogram - method. The vectors *x* and *y* are divided into *NFFT* length - blocks. Each block is detrended by the function *detrend* and - windowed by the function *window*. *noverlap* gives the length - of the overlap between blocks. The product of the direct FFTs - of *x* and *y* are averaged over each segment to compute *Pxy*, - with a scaling to correct for power loss due to windowing. - - If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero - padded to *NFFT*. - - *x*, *y* - Array or sequence containing the data - +#Split out these keyword docs so that they can be used elsewhere +kwdocd = dict() +kwdocd['PSD'] =""" *NFFT* The number of data points used in each block for the FFT. Must be even; a power 2 is most efficient. The default value is 256. @@ -388,12 +330,49 @@ :func:`numpy.blackman`, :func:`numpy.hamming`, :func:`numpy.bartlett`, :func:`scipy.signal`, :func:`scipy.signal.get_window`, etc. The default is - :func:`window_hanning`. + :func:`window_hanning`. If a function is passed as the + argument, it must take a data segment as an argument and + return the windowed version of the segment. *noverlap* The number of points of overlap between blocks. The default value is 0 (no overlap). + *pad_to* + The number of points to which the data segment is padd when + performing the FFT. This can be different from *NFFT*, which + specifies the number of data points used. While not increasing + the actual resolution of the psd (the minimum distance between + resolvable peaks), this can give more points in the plot, + allowing for more detail. This corresponds to the *n* parameter + in the call to fft(). The default is None, which sets *pad_to* + equal to *NFFT* + + *sides* [ 'default' | 'onesided' | 'twosided' ] + Specifies which sides of the PSD to return. Default gives the + default behavior, which returns one-sided for real data and both + for complex data. 'one' forces the return of a one-sided PSD, while + 'both' forces two-sided. +""" +psd.__doc__ = psd.__doc__ % kwdocd + +def csd(x, y, NFFT=256, Fs=2, detrend=detrend_none, + window=window_hanning, noverlap=0, pad_to=None, sides='default'): + """ + The cross power spectral density by Welch's average periodogram + method. The vectors *x* and *y* are divided into *NFFT* length + blocks. Each block is detrended by the function *detrend* and + windowed by the function *window*. *noverlap* gives the length + of the overlap between blocks. The product of the direct FFTs + of *x* and *y* are averaged over each segment to compute *Pxy*, + with a scaling to correct for power loss due to windowing. + + If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero + padded to *NFFT*. + + *x*, *y* + Array or sequence containing the data + %(PSD)s Returns the tuple (*Pxy*, *freqs*). Refs: @@ -401,9 +380,6 @@ Procedures, John Wiley & Sons (1986) """ - if NFFT % 2: - raise ValueError, 'NFFT must be even' - x = np.asarray(x) # make sure we're dealing with a numpy array y = np.asarray(y) # make sure we're dealing with a numpy array @@ -417,40 +393,50 @@ y = np.resize(y, (NFFT,)) y[n:] = 0 - # for real x, ignore the negative frequencies - if np.iscomplexobj(x): numFreqs = NFFT - else: numFreqs = NFFT//2+1 + if pad_to is None: + pad_to = NFFT + # For real x, ignore the negative frequencies unless told otherwise + if (sides == 'default' and np.iscomplexobj(x)) or sides == 'twosided': + numFreqs = pad_to + elif sides in ('default', 'onesided'): + numFreqs = pad_to//2 + 1 + else: + raise ValueError("sides must be one of: 'default', 'onesided', or " + "'twosided'") + if cbook.iterable(window): assert(len(window) == NFFT) windowVals = window else: windowVals = window(np.ones((NFFT,), x.dtype)) - step = NFFT-noverlap - ind = range(0,len(x)-NFFT+1,step) + + step = NFFT - noverlap + ind = range(0, len(x) - NFFT + 1, step) n = len(ind) Pxy = np.zeros((numFreqs,n), np.complex_) # do the ffts of the slices for i in range(n): thisX = x[ind[i]:ind[i]+NFFT] - thisX = windowVals*detrend(thisX) + thisX = windowVals * detrend(thisX) thisY = y[ind[i]:ind[i]+NFFT] - thisY = windowVals*detrend(thisY) - fx = np.fft.fft(thisX) - fy = np.fft.fft(thisY) - Pxy[:,i] = np.conjugate(fx[:numFreqs])*fy[:numFreqs] + thisY = windowVals * detrend(thisY) + fx = np.fft.fft(thisX, n=pad_to) + fy = np.fft.fft(thisY, n=pad_to) + Pxy[:,i] = np.conjugate(fx[:numFreqs]) * fy[:numFreqs] - - # Scale the spectrum by the norm of the window to compensate for # windowing loss; see Bendat & Piersol Sec 11.5.2 if n>1: Pxy = Pxy.mean(axis=1) + Pxy /= (np.abs(windowVals)**2).sum() - freqs = Fs/NFFT*np.arange(numFreqs) + freqs = float(Fs) / pad_to * np.arange(numFreqs) return Pxy, freqs +csd.__doc__ = csd.__doc__ % kwdocd + def specgram(x, NFFT=256, Fs=2, detrend=detrend_none, window=window_hanning, noverlap=128): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |