Chris@87: """ Chris@87: Discrete Fourier Transforms - helper.py Chris@87: Chris@87: """ Chris@87: from __future__ import division, absolute_import, print_function Chris@87: Chris@87: from numpy.compat import integer_types Chris@87: from numpy.core import ( Chris@87: asarray, concatenate, arange, take, integer, empty Chris@87: ) Chris@87: Chris@87: # Created by Pearu Peterson, September 2002 Chris@87: Chris@87: __all__ = ['fftshift', 'ifftshift', 'fftfreq', 'rfftfreq'] Chris@87: Chris@87: integer_types = integer_types + (integer,) Chris@87: Chris@87: Chris@87: def fftshift(x, axes=None): Chris@87: """ Chris@87: Shift the zero-frequency component to the center of the spectrum. Chris@87: Chris@87: This function swaps half-spaces for all axes listed (defaults to all). Chris@87: Note that ``y[0]`` is the Nyquist component only if ``len(x)`` is even. Chris@87: Chris@87: Parameters Chris@87: ---------- Chris@87: x : array_like Chris@87: Input array. Chris@87: axes : int or shape tuple, optional Chris@87: Axes over which to shift. Default is None, which shifts all axes. Chris@87: Chris@87: Returns Chris@87: ------- Chris@87: y : ndarray Chris@87: The shifted array. Chris@87: Chris@87: See Also Chris@87: -------- Chris@87: ifftshift : The inverse of `fftshift`. Chris@87: Chris@87: Examples Chris@87: -------- Chris@87: >>> freqs = np.fft.fftfreq(10, 0.1) Chris@87: >>> freqs Chris@87: array([ 0., 1., 2., 3., 4., -5., -4., -3., -2., -1.]) Chris@87: >>> np.fft.fftshift(freqs) Chris@87: array([-5., -4., -3., -2., -1., 0., 1., 2., 3., 4.]) Chris@87: Chris@87: Shift the zero-frequency component only along the second axis: Chris@87: Chris@87: >>> freqs = np.fft.fftfreq(9, d=1./9).reshape(3, 3) Chris@87: >>> freqs Chris@87: array([[ 0., 1., 2.], Chris@87: [ 3., 4., -4.], Chris@87: [-3., -2., -1.]]) Chris@87: >>> np.fft.fftshift(freqs, axes=(1,)) Chris@87: array([[ 2., 0., 1.], Chris@87: [-4., 3., 4.], Chris@87: [-1., -3., -2.]]) Chris@87: Chris@87: """ Chris@87: tmp = asarray(x) Chris@87: ndim = len(tmp.shape) Chris@87: if axes is None: Chris@87: axes = list(range(ndim)) Chris@87: elif isinstance(axes, integer_types): Chris@87: axes = (axes,) Chris@87: y = tmp Chris@87: for k in axes: Chris@87: n = tmp.shape[k] Chris@87: p2 = (n+1)//2 Chris@87: mylist = concatenate((arange(p2, n), arange(p2))) Chris@87: y = take(y, mylist, k) Chris@87: return y Chris@87: Chris@87: Chris@87: def ifftshift(x, axes=None): Chris@87: """ Chris@87: The inverse of `fftshift`. Although identical for even-length `x`, the Chris@87: functions differ by one sample for odd-length `x`. Chris@87: Chris@87: Parameters Chris@87: ---------- Chris@87: x : array_like Chris@87: Input array. Chris@87: axes : int or shape tuple, optional Chris@87: Axes over which to calculate. Defaults to None, which shifts all axes. Chris@87: Chris@87: Returns Chris@87: ------- Chris@87: y : ndarray Chris@87: The shifted array. Chris@87: Chris@87: See Also Chris@87: -------- Chris@87: fftshift : Shift zero-frequency component to the center of the spectrum. Chris@87: Chris@87: Examples Chris@87: -------- Chris@87: >>> freqs = np.fft.fftfreq(9, d=1./9).reshape(3, 3) Chris@87: >>> freqs Chris@87: array([[ 0., 1., 2.], Chris@87: [ 3., 4., -4.], Chris@87: [-3., -2., -1.]]) Chris@87: >>> np.fft.ifftshift(np.fft.fftshift(freqs)) Chris@87: array([[ 0., 1., 2.], Chris@87: [ 3., 4., -4.], Chris@87: [-3., -2., -1.]]) Chris@87: Chris@87: """ Chris@87: tmp = asarray(x) Chris@87: ndim = len(tmp.shape) Chris@87: if axes is None: Chris@87: axes = list(range(ndim)) Chris@87: elif isinstance(axes, integer_types): Chris@87: axes = (axes,) Chris@87: y = tmp Chris@87: for k in axes: Chris@87: n = tmp.shape[k] Chris@87: p2 = n-(n+1)//2 Chris@87: mylist = concatenate((arange(p2, n), arange(p2))) Chris@87: y = take(y, mylist, k) Chris@87: return y Chris@87: Chris@87: Chris@87: def fftfreq(n, d=1.0): Chris@87: """ Chris@87: Return the Discrete Fourier Transform sample frequencies. Chris@87: Chris@87: The returned float array `f` contains the frequency bin centers in cycles Chris@87: per unit of the sample spacing (with zero at the start). For instance, if Chris@87: the sample spacing is in seconds, then the frequency unit is cycles/second. Chris@87: Chris@87: Given a window length `n` and a sample spacing `d`:: Chris@87: Chris@87: f = [0, 1, ..., n/2-1, -n/2, ..., -1] / (d*n) if n is even Chris@87: f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n) if n is odd Chris@87: Chris@87: Parameters Chris@87: ---------- Chris@87: n : int Chris@87: Window length. Chris@87: d : scalar, optional Chris@87: Sample spacing (inverse of the sampling rate). Defaults to 1. Chris@87: Chris@87: Returns Chris@87: ------- Chris@87: f : ndarray Chris@87: Array of length `n` containing the sample frequencies. Chris@87: Chris@87: Examples Chris@87: -------- Chris@87: >>> signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5], dtype=float) Chris@87: >>> fourier = np.fft.fft(signal) Chris@87: >>> n = signal.size Chris@87: >>> timestep = 0.1 Chris@87: >>> freq = np.fft.fftfreq(n, d=timestep) Chris@87: >>> freq Chris@87: array([ 0. , 1.25, 2.5 , 3.75, -5. , -3.75, -2.5 , -1.25]) Chris@87: Chris@87: """ Chris@87: if not isinstance(n, integer_types): Chris@87: raise ValueError("n should be an integer") Chris@87: val = 1.0 / (n * d) Chris@87: results = empty(n, int) Chris@87: N = (n-1)//2 + 1 Chris@87: p1 = arange(0, N, dtype=int) Chris@87: results[:N] = p1 Chris@87: p2 = arange(-(n//2), 0, dtype=int) Chris@87: results[N:] = p2 Chris@87: return results * val Chris@87: #return hstack((arange(0,(n-1)/2 + 1), arange(-(n/2),0))) / (n*d) Chris@87: Chris@87: Chris@87: def rfftfreq(n, d=1.0): Chris@87: """ Chris@87: Return the Discrete Fourier Transform sample frequencies Chris@87: (for usage with rfft, irfft). Chris@87: Chris@87: The returned float array `f` contains the frequency bin centers in cycles Chris@87: per unit of the sample spacing (with zero at the start). For instance, if Chris@87: the sample spacing is in seconds, then the frequency unit is cycles/second. Chris@87: Chris@87: Given a window length `n` and a sample spacing `d`:: Chris@87: Chris@87: f = [0, 1, ..., n/2-1, n/2] / (d*n) if n is even Chris@87: f = [0, 1, ..., (n-1)/2-1, (n-1)/2] / (d*n) if n is odd Chris@87: Chris@87: Unlike `fftfreq` (but like `scipy.fftpack.rfftfreq`) Chris@87: the Nyquist frequency component is considered to be positive. Chris@87: Chris@87: Parameters Chris@87: ---------- Chris@87: n : int Chris@87: Window length. Chris@87: d : scalar, optional Chris@87: Sample spacing (inverse of the sampling rate). Defaults to 1. Chris@87: Chris@87: Returns Chris@87: ------- Chris@87: f : ndarray Chris@87: Array of length ``n//2 + 1`` containing the sample frequencies. Chris@87: Chris@87: Examples Chris@87: -------- Chris@87: >>> signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5, -3, 4], dtype=float) Chris@87: >>> fourier = np.fft.rfft(signal) Chris@87: >>> n = signal.size Chris@87: >>> sample_rate = 100 Chris@87: >>> freq = np.fft.fftfreq(n, d=1./sample_rate) Chris@87: >>> freq Chris@87: array([ 0., 10., 20., 30., 40., -50., -40., -30., -20., -10.]) Chris@87: >>> freq = np.fft.rfftfreq(n, d=1./sample_rate) Chris@87: >>> freq Chris@87: array([ 0., 10., 20., 30., 40., 50.]) Chris@87: Chris@87: """ Chris@87: if not isinstance(n, integer_types): Chris@87: raise ValueError("n should be an integer") Chris@87: val = 1.0/(n*d) Chris@87: N = n//2 + 1 Chris@87: results = arange(0, N, dtype=int) Chris@87: return results * val