asd
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/lib/python3.12/site-packages/scipy/fftpack/tests/test.npz
Normal file
BIN
venv/lib/python3.12/site-packages/scipy/fftpack/tests/test.npz
Normal file
Binary file not shown.
@ -0,0 +1,873 @@
|
||||
# Created by Pearu Peterson, September 2002
|
||||
|
||||
from numpy.testing import (assert_, assert_equal, assert_array_almost_equal,
|
||||
assert_array_almost_equal_nulp, assert_array_less)
|
||||
import pytest
|
||||
from pytest import raises as assert_raises
|
||||
from scipy.fftpack import ifft, fft, fftn, ifftn, rfft, irfft, fft2
|
||||
|
||||
from numpy import (arange, array, asarray, zeros, dot, exp, pi,
|
||||
swapaxes, double, cdouble)
|
||||
import numpy as np
|
||||
import numpy.fft
|
||||
from numpy.random import rand
|
||||
|
||||
# "large" composite numbers supported by FFTPACK
|
||||
LARGE_COMPOSITE_SIZES = [
|
||||
2**13,
|
||||
2**5 * 3**5,
|
||||
2**3 * 3**3 * 5**2,
|
||||
]
|
||||
SMALL_COMPOSITE_SIZES = [
|
||||
2,
|
||||
2*3*5,
|
||||
2*2*3*3,
|
||||
]
|
||||
# prime
|
||||
LARGE_PRIME_SIZES = [
|
||||
2011
|
||||
]
|
||||
SMALL_PRIME_SIZES = [
|
||||
29
|
||||
]
|
||||
|
||||
|
||||
def _assert_close_in_norm(x, y, rtol, size, rdt):
|
||||
# helper function for testing
|
||||
err_msg = f"size: {size} rdt: {rdt}"
|
||||
assert_array_less(np.linalg.norm(x - y), rtol*np.linalg.norm(x), err_msg)
|
||||
|
||||
|
||||
def random(size):
|
||||
return rand(*size)
|
||||
|
||||
|
||||
def direct_dft(x):
|
||||
x = asarray(x)
|
||||
n = len(x)
|
||||
y = zeros(n, dtype=cdouble)
|
||||
w = -arange(n)*(2j*pi/n)
|
||||
for i in range(n):
|
||||
y[i] = dot(exp(i*w), x)
|
||||
return y
|
||||
|
||||
|
||||
def direct_idft(x):
|
||||
x = asarray(x)
|
||||
n = len(x)
|
||||
y = zeros(n, dtype=cdouble)
|
||||
w = arange(n)*(2j*pi/n)
|
||||
for i in range(n):
|
||||
y[i] = dot(exp(i*w), x)/n
|
||||
return y
|
||||
|
||||
|
||||
def direct_dftn(x):
|
||||
x = asarray(x)
|
||||
for axis in range(len(x.shape)):
|
||||
x = fft(x, axis=axis)
|
||||
return x
|
||||
|
||||
|
||||
def direct_idftn(x):
|
||||
x = asarray(x)
|
||||
for axis in range(len(x.shape)):
|
||||
x = ifft(x, axis=axis)
|
||||
return x
|
||||
|
||||
|
||||
def direct_rdft(x):
|
||||
x = asarray(x)
|
||||
n = len(x)
|
||||
w = -arange(n)*(2j*pi/n)
|
||||
r = zeros(n, dtype=double)
|
||||
for i in range(n//2+1):
|
||||
y = dot(exp(i*w), x)
|
||||
if i:
|
||||
r[2*i-1] = y.real
|
||||
if 2*i < n:
|
||||
r[2*i] = y.imag
|
||||
else:
|
||||
r[0] = y.real
|
||||
return r
|
||||
|
||||
|
||||
def direct_irdft(x):
|
||||
x = asarray(x)
|
||||
n = len(x)
|
||||
x1 = zeros(n, dtype=cdouble)
|
||||
for i in range(n//2+1):
|
||||
if i:
|
||||
if 2*i < n:
|
||||
x1[i] = x[2*i-1] + 1j*x[2*i]
|
||||
x1[n-i] = x[2*i-1] - 1j*x[2*i]
|
||||
else:
|
||||
x1[i] = x[2*i-1]
|
||||
else:
|
||||
x1[0] = x[0]
|
||||
return direct_idft(x1).real
|
||||
|
||||
|
||||
class _TestFFTBase:
|
||||
def setup_method(self):
|
||||
self.cdt = None
|
||||
self.rdt = None
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
x = np.array([1,2,3,4+1j,1,2,3,4+2j], dtype=self.cdt)
|
||||
y = fft(x)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
y1 = direct_dft(x)
|
||||
assert_array_almost_equal(y,y1)
|
||||
x = np.array([1,2,3,4+0j,5], dtype=self.cdt)
|
||||
assert_array_almost_equal(fft(x),direct_dft(x))
|
||||
|
||||
def test_n_argument_real(self):
|
||||
x1 = np.array([1,2,3,4], dtype=self.rdt)
|
||||
x2 = np.array([1,2,3,4], dtype=self.rdt)
|
||||
y = fft([x1,x2],n=4)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
assert_equal(y.shape,(2,4))
|
||||
assert_array_almost_equal(y[0],direct_dft(x1))
|
||||
assert_array_almost_equal(y[1],direct_dft(x2))
|
||||
|
||||
def _test_n_argument_complex(self):
|
||||
x1 = np.array([1,2,3,4+1j], dtype=self.cdt)
|
||||
x2 = np.array([1,2,3,4+1j], dtype=self.cdt)
|
||||
y = fft([x1,x2],n=4)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
assert_equal(y.shape,(2,4))
|
||||
assert_array_almost_equal(y[0],direct_dft(x1))
|
||||
assert_array_almost_equal(y[1],direct_dft(x2))
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
assert_raises(ValueError, fft, [])
|
||||
assert_raises(ValueError, fft, [[1,1],[2,2]], -5)
|
||||
|
||||
|
||||
class TestDoubleFFT(_TestFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex128
|
||||
self.rdt = np.float64
|
||||
|
||||
|
||||
class TestSingleFFT(_TestFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex64
|
||||
self.rdt = np.float32
|
||||
|
||||
reason = ("single-precision FFT implementation is partially disabled, "
|
||||
"until accuracy issues with large prime powers are resolved")
|
||||
|
||||
@pytest.mark.xfail(run=False, reason=reason)
|
||||
def test_notice(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestFloat16FFT:
|
||||
|
||||
def test_1_argument_real(self):
|
||||
x1 = np.array([1, 2, 3, 4], dtype=np.float16)
|
||||
y = fft(x1, n=4)
|
||||
assert_equal(y.dtype, np.complex64)
|
||||
assert_equal(y.shape, (4, ))
|
||||
assert_array_almost_equal(y, direct_dft(x1.astype(np.float32)))
|
||||
|
||||
def test_n_argument_real(self):
|
||||
x1 = np.array([1, 2, 3, 4], dtype=np.float16)
|
||||
x2 = np.array([1, 2, 3, 4], dtype=np.float16)
|
||||
y = fft([x1, x2], n=4)
|
||||
assert_equal(y.dtype, np.complex64)
|
||||
assert_equal(y.shape, (2, 4))
|
||||
assert_array_almost_equal(y[0], direct_dft(x1.astype(np.float32)))
|
||||
assert_array_almost_equal(y[1], direct_dft(x2.astype(np.float32)))
|
||||
|
||||
|
||||
class _TestIFFTBase:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
x = np.array([1,2,3,4+1j,1,2,3,4+2j], self.cdt)
|
||||
y = ifft(x)
|
||||
y1 = direct_idft(x)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
assert_array_almost_equal(y,y1)
|
||||
|
||||
x = np.array([1,2,3,4+0j,5], self.cdt)
|
||||
assert_array_almost_equal(ifft(x),direct_idft(x))
|
||||
|
||||
def test_definition_real(self):
|
||||
x = np.array([1,2,3,4,1,2,3,4], self.rdt)
|
||||
y = ifft(x)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
y1 = direct_idft(x)
|
||||
assert_array_almost_equal(y,y1)
|
||||
|
||||
x = np.array([1,2,3,4,5], dtype=self.rdt)
|
||||
assert_equal(y.dtype, self.cdt)
|
||||
assert_array_almost_equal(ifft(x),direct_idft(x))
|
||||
|
||||
def test_random_complex(self):
|
||||
for size in [1,51,111,100,200,64,128,256,1024]:
|
||||
x = random([size]).astype(self.cdt)
|
||||
x = random([size]).astype(self.cdt) + 1j*x
|
||||
y1 = ifft(fft(x))
|
||||
y2 = fft(ifft(x))
|
||||
assert_equal(y1.dtype, self.cdt)
|
||||
assert_equal(y2.dtype, self.cdt)
|
||||
assert_array_almost_equal(y1, x)
|
||||
assert_array_almost_equal(y2, x)
|
||||
|
||||
def test_random_real(self):
|
||||
for size in [1,51,111,100,200,64,128,256,1024]:
|
||||
x = random([size]).astype(self.rdt)
|
||||
y1 = ifft(fft(x))
|
||||
y2 = fft(ifft(x))
|
||||
assert_equal(y1.dtype, self.cdt)
|
||||
assert_equal(y2.dtype, self.cdt)
|
||||
assert_array_almost_equal(y1, x)
|
||||
assert_array_almost_equal(y2, x)
|
||||
|
||||
def test_size_accuracy(self):
|
||||
# Sanity check for the accuracy for prime and non-prime sized inputs
|
||||
if self.rdt == np.float32:
|
||||
rtol = 1e-5
|
||||
elif self.rdt == np.float64:
|
||||
rtol = 1e-10
|
||||
|
||||
for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES:
|
||||
np.random.seed(1234)
|
||||
x = np.random.rand(size).astype(self.rdt)
|
||||
y = ifft(fft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
y = fft(ifft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
|
||||
x = (x + 1j*np.random.rand(size)).astype(self.cdt)
|
||||
y = ifft(fft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
y = fft(ifft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
assert_raises(ValueError, ifft, [])
|
||||
assert_raises(ValueError, ifft, [[1,1],[2,2]], -5)
|
||||
|
||||
|
||||
class TestDoubleIFFT(_TestIFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex128
|
||||
self.rdt = np.float64
|
||||
|
||||
|
||||
class TestSingleIFFT(_TestIFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex64
|
||||
self.rdt = np.float32
|
||||
|
||||
|
||||
class _TestRFFTBase:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
for t in [[1, 2, 3, 4, 1, 2, 3, 4], [1, 2, 3, 4, 1, 2, 3, 4, 5]]:
|
||||
x = np.array(t, dtype=self.rdt)
|
||||
y = rfft(x)
|
||||
y1 = direct_rdft(x)
|
||||
assert_array_almost_equal(y,y1)
|
||||
assert_equal(y.dtype, self.rdt)
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
assert_raises(ValueError, rfft, [])
|
||||
assert_raises(ValueError, rfft, [[1,1],[2,2]], -5)
|
||||
|
||||
# See gh-5790
|
||||
class MockSeries:
|
||||
def __init__(self, data):
|
||||
self.data = np.asarray(data)
|
||||
|
||||
def __getattr__(self, item):
|
||||
try:
|
||||
return getattr(self.data, item)
|
||||
except AttributeError as e:
|
||||
raise AttributeError("'MockSeries' object "
|
||||
f"has no attribute '{item}'") from e
|
||||
|
||||
def test_non_ndarray_with_dtype(self):
|
||||
x = np.array([1., 2., 3., 4., 5.])
|
||||
xs = _TestRFFTBase.MockSeries(x)
|
||||
|
||||
expected = [1, 2, 3, 4, 5]
|
||||
rfft(xs)
|
||||
|
||||
# Data should not have been overwritten
|
||||
assert_equal(x, expected)
|
||||
assert_equal(xs.data, expected)
|
||||
|
||||
def test_complex_input(self):
|
||||
assert_raises(TypeError, rfft, np.arange(4, dtype=np.complex64))
|
||||
|
||||
|
||||
class TestRFFTDouble(_TestRFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex128
|
||||
self.rdt = np.float64
|
||||
|
||||
|
||||
class TestRFFTSingle(_TestRFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex64
|
||||
self.rdt = np.float32
|
||||
|
||||
|
||||
class _TestIRFFTBase:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
x1 = [1,2,3,4,1,2,3,4]
|
||||
x1_1 = [1,2+3j,4+1j,2+3j,4,2-3j,4-1j,2-3j]
|
||||
x2 = [1,2,3,4,1,2,3,4,5]
|
||||
x2_1 = [1,2+3j,4+1j,2+3j,4+5j,4-5j,2-3j,4-1j,2-3j]
|
||||
|
||||
def _test(x, xr):
|
||||
y = irfft(np.array(x, dtype=self.rdt))
|
||||
y1 = direct_irdft(x)
|
||||
assert_equal(y.dtype, self.rdt)
|
||||
assert_array_almost_equal(y,y1, decimal=self.ndec)
|
||||
assert_array_almost_equal(y,ifft(xr), decimal=self.ndec)
|
||||
|
||||
_test(x1, x1_1)
|
||||
_test(x2, x2_1)
|
||||
|
||||
def test_random_real(self):
|
||||
for size in [1,51,111,100,200,64,128,256,1024]:
|
||||
x = random([size]).astype(self.rdt)
|
||||
y1 = irfft(rfft(x))
|
||||
y2 = rfft(irfft(x))
|
||||
assert_equal(y1.dtype, self.rdt)
|
||||
assert_equal(y2.dtype, self.rdt)
|
||||
assert_array_almost_equal(y1, x, decimal=self.ndec,
|
||||
err_msg="size=%d" % size)
|
||||
assert_array_almost_equal(y2, x, decimal=self.ndec,
|
||||
err_msg="size=%d" % size)
|
||||
|
||||
def test_size_accuracy(self):
|
||||
# Sanity check for the accuracy for prime and non-prime sized inputs
|
||||
if self.rdt == np.float32:
|
||||
rtol = 1e-5
|
||||
elif self.rdt == np.float64:
|
||||
rtol = 1e-10
|
||||
|
||||
for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES:
|
||||
np.random.seed(1234)
|
||||
x = np.random.rand(size).astype(self.rdt)
|
||||
y = irfft(rfft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
y = rfft(irfft(x))
|
||||
_assert_close_in_norm(x, y, rtol, size, self.rdt)
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
assert_raises(ValueError, irfft, [])
|
||||
assert_raises(ValueError, irfft, [[1,1],[2,2]], -5)
|
||||
|
||||
def test_complex_input(self):
|
||||
assert_raises(TypeError, irfft, np.arange(4, dtype=np.complex64))
|
||||
|
||||
|
||||
# self.ndec is bogus; we should have a assert_array_approx_equal for number of
|
||||
# significant digits
|
||||
|
||||
class TestIRFFTDouble(_TestIRFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex128
|
||||
self.rdt = np.float64
|
||||
self.ndec = 14
|
||||
|
||||
|
||||
class TestIRFFTSingle(_TestIRFFTBase):
|
||||
def setup_method(self):
|
||||
self.cdt = np.complex64
|
||||
self.rdt = np.float32
|
||||
self.ndec = 5
|
||||
|
||||
|
||||
class Testfft2:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_regression_244(self):
|
||||
"""FFT returns wrong result with axes parameter."""
|
||||
# fftn (and hence fft2) used to break when both axes and shape were
|
||||
# used
|
||||
x = numpy.ones((4, 4, 2))
|
||||
y = fft2(x, shape=(8, 8), axes=(-3, -2))
|
||||
y_r = numpy.fft.fftn(x, s=(8, 8), axes=(-3, -2))
|
||||
assert_array_almost_equal(y, y_r)
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
assert_raises(ValueError, fft2, [[]])
|
||||
assert_raises(ValueError, fft2, [[1, 1], [2, 2]], (4, -3))
|
||||
|
||||
|
||||
class TestFftnSingle:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
x = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]]
|
||||
y = fftn(np.array(x, np.float32))
|
||||
assert_(y.dtype == np.complex64,
|
||||
msg="double precision output with single precision")
|
||||
|
||||
y_r = np.array(fftn(x), np.complex64)
|
||||
assert_array_almost_equal_nulp(y, y_r)
|
||||
|
||||
@pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES)
|
||||
def test_size_accuracy_small(self, size):
|
||||
x = np.random.rand(size, size) + 1j*np.random.rand(size, size)
|
||||
y1 = fftn(x.real.astype(np.float32))
|
||||
y2 = fftn(x.real.astype(np.float64)).astype(np.complex64)
|
||||
|
||||
assert_equal(y1.dtype, np.complex64)
|
||||
assert_array_almost_equal_nulp(y1, y2, 2000)
|
||||
|
||||
@pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES)
|
||||
def test_size_accuracy_large(self, size):
|
||||
x = np.random.rand(size, 3) + 1j*np.random.rand(size, 3)
|
||||
y1 = fftn(x.real.astype(np.float32))
|
||||
y2 = fftn(x.real.astype(np.float64)).astype(np.complex64)
|
||||
|
||||
assert_equal(y1.dtype, np.complex64)
|
||||
assert_array_almost_equal_nulp(y1, y2, 2000)
|
||||
|
||||
def test_definition_float16(self):
|
||||
x = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]]
|
||||
y = fftn(np.array(x, np.float16))
|
||||
assert_equal(y.dtype, np.complex64)
|
||||
y_r = np.array(fftn(x), np.complex64)
|
||||
assert_array_almost_equal_nulp(y, y_r)
|
||||
|
||||
@pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES)
|
||||
def test_float16_input_small(self, size):
|
||||
x = np.random.rand(size, size) + 1j*np.random.rand(size, size)
|
||||
y1 = fftn(x.real.astype(np.float16))
|
||||
y2 = fftn(x.real.astype(np.float64)).astype(np.complex64)
|
||||
|
||||
assert_equal(y1.dtype, np.complex64)
|
||||
assert_array_almost_equal_nulp(y1, y2, 5e5)
|
||||
|
||||
@pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES)
|
||||
def test_float16_input_large(self, size):
|
||||
x = np.random.rand(size, 3) + 1j*np.random.rand(size, 3)
|
||||
y1 = fftn(x.real.astype(np.float16))
|
||||
y2 = fftn(x.real.astype(np.float64)).astype(np.complex64)
|
||||
|
||||
assert_equal(y1.dtype, np.complex64)
|
||||
assert_array_almost_equal_nulp(y1, y2, 2e6)
|
||||
|
||||
|
||||
class TestFftn:
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
def test_definition(self):
|
||||
x = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]]
|
||||
y = fftn(x)
|
||||
assert_array_almost_equal(y, direct_dftn(x))
|
||||
|
||||
x = random((20, 26))
|
||||
assert_array_almost_equal(fftn(x), direct_dftn(x))
|
||||
|
||||
x = random((5, 4, 3, 20))
|
||||
assert_array_almost_equal(fftn(x), direct_dftn(x))
|
||||
|
||||
def test_axes_argument(self):
|
||||
# plane == ji_plane, x== kji_space
|
||||
plane1 = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]]
|
||||
plane2 = [[10, 11, 12],
|
||||
[13, 14, 15],
|
||||
[16, 17, 18]]
|
||||
plane3 = [[19, 20, 21],
|
||||
[22, 23, 24],
|
||||
[25, 26, 27]]
|
||||
ki_plane1 = [[1, 2, 3],
|
||||
[10, 11, 12],
|
||||
[19, 20, 21]]
|
||||
ki_plane2 = [[4, 5, 6],
|
||||
[13, 14, 15],
|
||||
[22, 23, 24]]
|
||||
ki_plane3 = [[7, 8, 9],
|
||||
[16, 17, 18],
|
||||
[25, 26, 27]]
|
||||
jk_plane1 = [[1, 10, 19],
|
||||
[4, 13, 22],
|
||||
[7, 16, 25]]
|
||||
jk_plane2 = [[2, 11, 20],
|
||||
[5, 14, 23],
|
||||
[8, 17, 26]]
|
||||
jk_plane3 = [[3, 12, 21],
|
||||
[6, 15, 24],
|
||||
[9, 18, 27]]
|
||||
kj_plane1 = [[1, 4, 7],
|
||||
[10, 13, 16], [19, 22, 25]]
|
||||
kj_plane2 = [[2, 5, 8],
|
||||
[11, 14, 17], [20, 23, 26]]
|
||||
kj_plane3 = [[3, 6, 9],
|
||||
[12, 15, 18], [21, 24, 27]]
|
||||
ij_plane1 = [[1, 4, 7],
|
||||
[2, 5, 8],
|
||||
[3, 6, 9]]
|
||||
ij_plane2 = [[10, 13, 16],
|
||||
[11, 14, 17],
|
||||
[12, 15, 18]]
|
||||
ij_plane3 = [[19, 22, 25],
|
||||
[20, 23, 26],
|
||||
[21, 24, 27]]
|
||||
ik_plane1 = [[1, 10, 19],
|
||||
[2, 11, 20],
|
||||
[3, 12, 21]]
|
||||
ik_plane2 = [[4, 13, 22],
|
||||
[5, 14, 23],
|
||||
[6, 15, 24]]
|
||||
ik_plane3 = [[7, 16, 25],
|
||||
[8, 17, 26],
|
||||
[9, 18, 27]]
|
||||
ijk_space = [jk_plane1, jk_plane2, jk_plane3]
|
||||
ikj_space = [kj_plane1, kj_plane2, kj_plane3]
|
||||
jik_space = [ik_plane1, ik_plane2, ik_plane3]
|
||||
jki_space = [ki_plane1, ki_plane2, ki_plane3]
|
||||
kij_space = [ij_plane1, ij_plane2, ij_plane3]
|
||||
x = array([plane1, plane2, plane3])
|
||||
|
||||
assert_array_almost_equal(fftn(x),
|
||||
fftn(x, axes=(-3, -2, -1))) # kji_space
|
||||
assert_array_almost_equal(fftn(x), fftn(x, axes=(0, 1, 2)))
|
||||
assert_array_almost_equal(fftn(x, axes=(0, 2)), fftn(x, axes=(0, -1)))
|
||||
y = fftn(x, axes=(2, 1, 0)) # ijk_space
|
||||
assert_array_almost_equal(swapaxes(y, -1, -3), fftn(ijk_space))
|
||||
y = fftn(x, axes=(2, 0, 1)) # ikj_space
|
||||
assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -1, -2),
|
||||
fftn(ikj_space))
|
||||
y = fftn(x, axes=(1, 2, 0)) # jik_space
|
||||
assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -3, -2),
|
||||
fftn(jik_space))
|
||||
y = fftn(x, axes=(1, 0, 2)) # jki_space
|
||||
assert_array_almost_equal(swapaxes(y, -2, -3), fftn(jki_space))
|
||||
y = fftn(x, axes=(0, 2, 1)) # kij_space
|
||||
assert_array_almost_equal(swapaxes(y, -2, -1), fftn(kij_space))
|
||||
|
||||
y = fftn(x, axes=(-2, -1)) # ji_plane
|
||||
assert_array_almost_equal(fftn(plane1), y[0])
|
||||
assert_array_almost_equal(fftn(plane2), y[1])
|
||||
assert_array_almost_equal(fftn(plane3), y[2])
|
||||
|
||||
y = fftn(x, axes=(1, 2)) # ji_plane
|
||||
assert_array_almost_equal(fftn(plane1), y[0])
|
||||
assert_array_almost_equal(fftn(plane2), y[1])
|
||||
assert_array_almost_equal(fftn(plane3), y[2])
|
||||
|
||||
y = fftn(x, axes=(-3, -2)) # kj_plane
|
||||
assert_array_almost_equal(fftn(x[:, :, 0]), y[:, :, 0])
|
||||
assert_array_almost_equal(fftn(x[:, :, 1]), y[:, :, 1])
|
||||
assert_array_almost_equal(fftn(x[:, :, 2]), y[:, :, 2])
|
||||
|
||||
y = fftn(x, axes=(-3, -1)) # ki_plane
|
||||
assert_array_almost_equal(fftn(x[:, 0, :]), y[:, 0, :])
|
||||
assert_array_almost_equal(fftn(x[:, 1, :]), y[:, 1, :])
|
||||
assert_array_almost_equal(fftn(x[:, 2, :]), y[:, 2, :])
|
||||
|
||||
y = fftn(x, axes=(-1, -2)) # ij_plane
|
||||
assert_array_almost_equal(fftn(ij_plane1), swapaxes(y[0], -2, -1))
|
||||
assert_array_almost_equal(fftn(ij_plane2), swapaxes(y[1], -2, -1))
|
||||
assert_array_almost_equal(fftn(ij_plane3), swapaxes(y[2], -2, -1))
|
||||
|
||||
y = fftn(x, axes=(-1, -3)) # ik_plane
|
||||
assert_array_almost_equal(fftn(ik_plane1),
|
||||
swapaxes(y[:, 0, :], -1, -2))
|
||||
assert_array_almost_equal(fftn(ik_plane2),
|
||||
swapaxes(y[:, 1, :], -1, -2))
|
||||
assert_array_almost_equal(fftn(ik_plane3),
|
||||
swapaxes(y[:, 2, :], -1, -2))
|
||||
|
||||
y = fftn(x, axes=(-2, -3)) # jk_plane
|
||||
assert_array_almost_equal(fftn(jk_plane1),
|
||||
swapaxes(y[:, :, 0], -1, -2))
|
||||
assert_array_almost_equal(fftn(jk_plane2),
|
||||
swapaxes(y[:, :, 1], -1, -2))
|
||||
assert_array_almost_equal(fftn(jk_plane3),
|
||||
swapaxes(y[:, :, 2], -1, -2))
|
||||
|
||||
y = fftn(x, axes=(-1,)) # i_line
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
assert_array_almost_equal(fft(x[i, j, :]), y[i, j, :])
|
||||
y = fftn(x, axes=(-2,)) # j_line
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
assert_array_almost_equal(fft(x[i, :, j]), y[i, :, j])
|
||||
y = fftn(x, axes=(0,)) # k_line
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
assert_array_almost_equal(fft(x[:, i, j]), y[:, i, j])
|
||||
|
||||
y = fftn(x, axes=()) # point
|
||||
assert_array_almost_equal(y, x)
|
||||
|
||||
def test_shape_argument(self):
|
||||
small_x = [[1, 2, 3],
|
||||
[4, 5, 6]]
|
||||
large_x1 = [[1, 2, 3, 0],
|
||||
[4, 5, 6, 0],
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0]]
|
||||
|
||||
y = fftn(small_x, shape=(4, 4))
|
||||
assert_array_almost_equal(y, fftn(large_x1))
|
||||
|
||||
y = fftn(small_x, shape=(3, 4))
|
||||
assert_array_almost_equal(y, fftn(large_x1[:-1]))
|
||||
|
||||
def test_shape_axes_argument(self):
|
||||
small_x = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]]
|
||||
large_x1 = array([[1, 2, 3, 0],
|
||||
[4, 5, 6, 0],
|
||||
[7, 8, 9, 0],
|
||||
[0, 0, 0, 0]])
|
||||
y = fftn(small_x, shape=(4, 4), axes=(-2, -1))
|
||||
assert_array_almost_equal(y, fftn(large_x1))
|
||||
y = fftn(small_x, shape=(4, 4), axes=(-1, -2))
|
||||
|
||||
assert_array_almost_equal(y, swapaxes(
|
||||
fftn(swapaxes(large_x1, -1, -2)), -1, -2))
|
||||
|
||||
def test_shape_axes_argument2(self):
|
||||
# Change shape of the last axis
|
||||
x = numpy.random.random((10, 5, 3, 7))
|
||||
y = fftn(x, axes=(-1,), shape=(8,))
|
||||
assert_array_almost_equal(y, fft(x, axis=-1, n=8))
|
||||
|
||||
# Change shape of an arbitrary axis which is not the last one
|
||||
x = numpy.random.random((10, 5, 3, 7))
|
||||
y = fftn(x, axes=(-2,), shape=(8,))
|
||||
assert_array_almost_equal(y, fft(x, axis=-2, n=8))
|
||||
|
||||
# Change shape of axes: cf #244, where shape and axes were mixed up
|
||||
x = numpy.random.random((4, 4, 2))
|
||||
y = fftn(x, axes=(-3, -2), shape=(8, 8))
|
||||
assert_array_almost_equal(y,
|
||||
numpy.fft.fftn(x, axes=(-3, -2), s=(8, 8)))
|
||||
|
||||
def test_shape_argument_more(self):
|
||||
x = zeros((4, 4, 2))
|
||||
with assert_raises(ValueError,
|
||||
match="when given, axes and shape arguments"
|
||||
" have to be of the same length"):
|
||||
fftn(x, shape=(8, 8, 2, 1))
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
with assert_raises(ValueError,
|
||||
match="invalid number of data points"
|
||||
r" \(\[1, 0\]\) specified"):
|
||||
fftn([[]])
|
||||
|
||||
with assert_raises(ValueError,
|
||||
match="invalid number of data points"
|
||||
r" \(\[4, -3\]\) specified"):
|
||||
fftn([[1, 1], [2, 2]], (4, -3))
|
||||
|
||||
|
||||
class TestIfftn:
|
||||
dtype = None
|
||||
cdtype = None
|
||||
|
||||
def setup_method(self):
|
||||
np.random.seed(1234)
|
||||
|
||||
@pytest.mark.parametrize('dtype,cdtype,maxnlp',
|
||||
[(np.float64, np.complex128, 2000),
|
||||
(np.float32, np.complex64, 3500)])
|
||||
def test_definition(self, dtype, cdtype, maxnlp):
|
||||
x = np.array([[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]], dtype=dtype)
|
||||
y = ifftn(x)
|
||||
assert_equal(y.dtype, cdtype)
|
||||
assert_array_almost_equal_nulp(y, direct_idftn(x), maxnlp)
|
||||
|
||||
x = random((20, 26))
|
||||
assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp)
|
||||
|
||||
x = random((5, 4, 3, 20))
|
||||
assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp)
|
||||
|
||||
@pytest.mark.parametrize('maxnlp', [2000, 3500])
|
||||
@pytest.mark.parametrize('size', [1, 2, 51, 32, 64, 92])
|
||||
def test_random_complex(self, maxnlp, size):
|
||||
x = random([size, size]) + 1j*random([size, size])
|
||||
assert_array_almost_equal_nulp(ifftn(fftn(x)), x, maxnlp)
|
||||
assert_array_almost_equal_nulp(fftn(ifftn(x)), x, maxnlp)
|
||||
|
||||
def test_invalid_sizes(self):
|
||||
with assert_raises(ValueError,
|
||||
match="invalid number of data points"
|
||||
r" \(\[1, 0\]\) specified"):
|
||||
ifftn([[]])
|
||||
|
||||
with assert_raises(ValueError,
|
||||
match="invalid number of data points"
|
||||
r" \(\[4, -3\]\) specified"):
|
||||
ifftn([[1, 1], [2, 2]], (4, -3))
|
||||
|
||||
|
||||
class FakeArray:
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
self.__array_interface__ = data.__array_interface__
|
||||
|
||||
|
||||
class FakeArray2:
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
|
||||
def __array__(self, dtype=None, copy=None):
|
||||
return self._data
|
||||
|
||||
|
||||
class TestOverwrite:
|
||||
"""Check input overwrite behavior of the FFT functions."""
|
||||
|
||||
real_dtypes = (np.float32, np.float64)
|
||||
dtypes = real_dtypes + (np.complex64, np.complex128)
|
||||
fftsizes = [8, 16, 32]
|
||||
|
||||
def _check(self, x, routine, fftsize, axis, overwrite_x):
|
||||
x2 = x.copy()
|
||||
for fake in [lambda x: x, FakeArray, FakeArray2]:
|
||||
routine(fake(x2), fftsize, axis, overwrite_x=overwrite_x)
|
||||
|
||||
sig = "{}({}{!r}, {!r}, axis={!r}, overwrite_x={!r})".format(
|
||||
routine.__name__, x.dtype, x.shape, fftsize, axis, overwrite_x)
|
||||
if not overwrite_x:
|
||||
assert_equal(x2, x, err_msg="spurious overwrite in %s" % sig)
|
||||
|
||||
def _check_1d(self, routine, dtype, shape, axis, overwritable_dtypes,
|
||||
fftsize, overwrite_x):
|
||||
np.random.seed(1234)
|
||||
if np.issubdtype(dtype, np.complexfloating):
|
||||
data = np.random.randn(*shape) + 1j*np.random.randn(*shape)
|
||||
else:
|
||||
data = np.random.randn(*shape)
|
||||
data = data.astype(dtype)
|
||||
|
||||
self._check(data, routine, fftsize, axis,
|
||||
overwrite_x=overwrite_x)
|
||||
|
||||
@pytest.mark.parametrize('dtype', dtypes)
|
||||
@pytest.mark.parametrize('fftsize', fftsizes)
|
||||
@pytest.mark.parametrize('overwrite_x', [True, False])
|
||||
@pytest.mark.parametrize('shape,axes', [((16,), -1),
|
||||
((16, 2), 0),
|
||||
((2, 16), 1)])
|
||||
def test_fft_ifft(self, dtype, fftsize, overwrite_x, shape, axes):
|
||||
overwritable = (np.complex128, np.complex64)
|
||||
self._check_1d(fft, dtype, shape, axes, overwritable,
|
||||
fftsize, overwrite_x)
|
||||
self._check_1d(ifft, dtype, shape, axes, overwritable,
|
||||
fftsize, overwrite_x)
|
||||
|
||||
@pytest.mark.parametrize('dtype', real_dtypes)
|
||||
@pytest.mark.parametrize('fftsize', fftsizes)
|
||||
@pytest.mark.parametrize('overwrite_x', [True, False])
|
||||
@pytest.mark.parametrize('shape,axes', [((16,), -1),
|
||||
((16, 2), 0),
|
||||
((2, 16), 1)])
|
||||
def test_rfft_irfft(self, dtype, fftsize, overwrite_x, shape, axes):
|
||||
overwritable = self.real_dtypes
|
||||
self._check_1d(irfft, dtype, shape, axes, overwritable,
|
||||
fftsize, overwrite_x)
|
||||
self._check_1d(rfft, dtype, shape, axes, overwritable,
|
||||
fftsize, overwrite_x)
|
||||
|
||||
def _check_nd_one(self, routine, dtype, shape, axes, overwritable_dtypes,
|
||||
overwrite_x):
|
||||
np.random.seed(1234)
|
||||
if np.issubdtype(dtype, np.complexfloating):
|
||||
data = np.random.randn(*shape) + 1j*np.random.randn(*shape)
|
||||
else:
|
||||
data = np.random.randn(*shape)
|
||||
data = data.astype(dtype)
|
||||
|
||||
def fftshape_iter(shp):
|
||||
if len(shp) <= 0:
|
||||
yield ()
|
||||
else:
|
||||
for j in (shp[0]//2, shp[0], shp[0]*2):
|
||||
for rest in fftshape_iter(shp[1:]):
|
||||
yield (j,) + rest
|
||||
|
||||
if axes is None:
|
||||
part_shape = shape
|
||||
else:
|
||||
part_shape = tuple(np.take(shape, axes))
|
||||
|
||||
for fftshape in fftshape_iter(part_shape):
|
||||
self._check(data, routine, fftshape, axes,
|
||||
overwrite_x=overwrite_x)
|
||||
if data.ndim > 1:
|
||||
self._check(data.T, routine, fftshape, axes,
|
||||
overwrite_x=overwrite_x)
|
||||
|
||||
@pytest.mark.parametrize('dtype', dtypes)
|
||||
@pytest.mark.parametrize('overwrite_x', [True, False])
|
||||
@pytest.mark.parametrize('shape,axes', [((16,), None),
|
||||
((16,), (0,)),
|
||||
((16, 2), (0,)),
|
||||
((2, 16), (1,)),
|
||||
((8, 16), None),
|
||||
((8, 16), (0, 1)),
|
||||
((8, 16, 2), (0, 1)),
|
||||
((8, 16, 2), (1, 2)),
|
||||
((8, 16, 2), (0,)),
|
||||
((8, 16, 2), (1,)),
|
||||
((8, 16, 2), (2,)),
|
||||
((8, 16, 2), None),
|
||||
((8, 16, 2), (0, 1, 2))])
|
||||
def test_fftn_ifftn(self, dtype, overwrite_x, shape, axes):
|
||||
overwritable = (np.complex128, np.complex64)
|
||||
self._check_nd_one(fftn, dtype, shape, axes, overwritable,
|
||||
overwrite_x)
|
||||
self._check_nd_one(ifftn, dtype, shape, axes, overwritable,
|
||||
overwrite_x)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('func', [fftn, ifftn, fft2])
|
||||
def test_shape_axes_ndarray(func):
|
||||
# Test fftn and ifftn work with NumPy arrays for shape and axes arguments
|
||||
# Regression test for gh-13342
|
||||
a = np.random.rand(10, 10)
|
||||
|
||||
expect = func(a, shape=(5, 5))
|
||||
actual = func(a, shape=np.array([5, 5]))
|
||||
assert_equal(expect, actual)
|
||||
|
||||
expect = func(a, axes=(-1,))
|
||||
actual = func(a, axes=np.array([-1,]))
|
||||
assert_equal(expect, actual)
|
||||
|
||||
expect = func(a, shape=(4, 7), axes=(1, 0))
|
||||
actual = func(a, shape=np.array([4, 7]), axes=np.array([1, 0]))
|
||||
assert_equal(expect, actual)
|
||||
@ -0,0 +1,54 @@
|
||||
# Created by Pearu Peterson, September 2002
|
||||
|
||||
__usage__ = """
|
||||
Build fftpack:
|
||||
python setup_fftpack.py build
|
||||
Run tests if scipy is installed:
|
||||
python -c 'import scipy;scipy.fftpack.test(<level>)'
|
||||
Run tests if fftpack is not installed:
|
||||
python tests/test_helper.py [<level>]
|
||||
"""
|
||||
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
from scipy.fftpack import fftshift, ifftshift, fftfreq, rfftfreq
|
||||
|
||||
from numpy import pi, random
|
||||
|
||||
class TestFFTShift:
|
||||
|
||||
def test_definition(self):
|
||||
x = [0,1,2,3,4,-4,-3,-2,-1]
|
||||
y = [-4,-3,-2,-1,0,1,2,3,4]
|
||||
assert_array_almost_equal(fftshift(x),y)
|
||||
assert_array_almost_equal(ifftshift(y),x)
|
||||
x = [0,1,2,3,4,-5,-4,-3,-2,-1]
|
||||
y = [-5,-4,-3,-2,-1,0,1,2,3,4]
|
||||
assert_array_almost_equal(fftshift(x),y)
|
||||
assert_array_almost_equal(ifftshift(y),x)
|
||||
|
||||
def test_inverse(self):
|
||||
for n in [1,4,9,100,211]:
|
||||
x = random.random((n,))
|
||||
assert_array_almost_equal(ifftshift(fftshift(x)),x)
|
||||
|
||||
|
||||
class TestFFTFreq:
|
||||
|
||||
def test_definition(self):
|
||||
x = [0,1,2,3,4,-4,-3,-2,-1]
|
||||
assert_array_almost_equal(9*fftfreq(9),x)
|
||||
assert_array_almost_equal(9*pi*fftfreq(9,pi),x)
|
||||
x = [0,1,2,3,4,-5,-4,-3,-2,-1]
|
||||
assert_array_almost_equal(10*fftfreq(10),x)
|
||||
assert_array_almost_equal(10*pi*fftfreq(10,pi),x)
|
||||
|
||||
|
||||
class TestRFFTFreq:
|
||||
|
||||
def test_definition(self):
|
||||
x = [0,1,1,2,2,3,3,4,4]
|
||||
assert_array_almost_equal(9*rfftfreq(9),x)
|
||||
assert_array_almost_equal(9*pi*rfftfreq(9,pi),x)
|
||||
x = [0,1,1,2,2,3,3,4,4,5]
|
||||
assert_array_almost_equal(10*rfftfreq(10),x)
|
||||
assert_array_almost_equal(10*pi*rfftfreq(10,pi),x)
|
||||
@ -0,0 +1,33 @@
|
||||
"""Test possibility of patching fftpack with pyfftw.
|
||||
|
||||
No module source outside of scipy.fftpack should contain an import of
|
||||
the form `from scipy.fftpack import ...`, so that a simple replacement
|
||||
of scipy.fftpack by the corresponding fftw interface completely swaps
|
||||
the two FFT implementations.
|
||||
|
||||
Because this simply inspects source files, we only need to run the test
|
||||
on one version of Python.
|
||||
"""
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
import tokenize
|
||||
import pytest
|
||||
from numpy.testing import assert_
|
||||
import scipy
|
||||
|
||||
class TestFFTPackImport:
|
||||
@pytest.mark.slow
|
||||
def test_fftpack_import(self):
|
||||
base = Path(scipy.__file__).parent
|
||||
regexp = r"\s*from.+\.fftpack import .*\n"
|
||||
for path in base.rglob("*.py"):
|
||||
if base / "fftpack" in path.parents:
|
||||
continue
|
||||
# use tokenize to auto-detect encoding on systems where no
|
||||
# default encoding is defined (e.g., LANG='C')
|
||||
with tokenize.open(str(path)) as file:
|
||||
assert_(all(not re.fullmatch(regexp, line)
|
||||
for line in file),
|
||||
f"{path} contains an import from fftpack")
|
||||
@ -0,0 +1,380 @@
|
||||
# Created by Pearu Peterson, September 2002
|
||||
|
||||
__usage__ = """
|
||||
Build fftpack:
|
||||
python setup_fftpack.py build
|
||||
Run tests if scipy is installed:
|
||||
python -c 'import scipy;scipy.fftpack.test(<level>)'
|
||||
Run tests if fftpack is not installed:
|
||||
python tests/test_pseudo_diffs.py [<level>]
|
||||
"""
|
||||
|
||||
from numpy.testing import (assert_equal, assert_almost_equal,
|
||||
assert_array_almost_equal)
|
||||
from scipy.fftpack import (diff, fft, ifft, tilbert, itilbert, hilbert,
|
||||
ihilbert, shift, fftfreq, cs_diff, sc_diff,
|
||||
ss_diff, cc_diff)
|
||||
|
||||
import numpy as np
|
||||
from numpy import arange, sin, cos, pi, exp, tanh, sum, sign
|
||||
from numpy.random import random
|
||||
|
||||
|
||||
def direct_diff(x,k=1,period=None):
|
||||
fx = fft(x)
|
||||
n = len(fx)
|
||||
if period is None:
|
||||
period = 2*pi
|
||||
w = fftfreq(n)*2j*pi/period*n
|
||||
if k < 0:
|
||||
w = 1 / w**k
|
||||
w[0] = 0.0
|
||||
else:
|
||||
w = w**k
|
||||
if n > 2000:
|
||||
w[250:n-250] = 0.0
|
||||
return ifft(w*fx).real
|
||||
|
||||
|
||||
def direct_tilbert(x,h=1,period=None):
|
||||
fx = fft(x)
|
||||
n = len(fx)
|
||||
if period is None:
|
||||
period = 2*pi
|
||||
w = fftfreq(n)*h*2*pi/period*n
|
||||
w[0] = 1
|
||||
w = 1j/tanh(w)
|
||||
w[0] = 0j
|
||||
return ifft(w*fx)
|
||||
|
||||
|
||||
def direct_itilbert(x,h=1,period=None):
|
||||
fx = fft(x)
|
||||
n = len(fx)
|
||||
if period is None:
|
||||
period = 2*pi
|
||||
w = fftfreq(n)*h*2*pi/period*n
|
||||
w = -1j*tanh(w)
|
||||
return ifft(w*fx)
|
||||
|
||||
|
||||
def direct_hilbert(x):
|
||||
fx = fft(x)
|
||||
n = len(fx)
|
||||
w = fftfreq(n)*n
|
||||
w = 1j*sign(w)
|
||||
return ifft(w*fx)
|
||||
|
||||
|
||||
def direct_ihilbert(x):
|
||||
return -direct_hilbert(x)
|
||||
|
||||
|
||||
def direct_shift(x,a,period=None):
|
||||
n = len(x)
|
||||
if period is None:
|
||||
k = fftfreq(n)*1j*n
|
||||
else:
|
||||
k = fftfreq(n)*2j*pi/period*n
|
||||
return ifft(fft(x)*exp(k*a)).real
|
||||
|
||||
|
||||
class TestDiff:
|
||||
|
||||
def test_definition(self):
|
||||
for n in [16,17,64,127,32]:
|
||||
x = arange(n)*2*pi/n
|
||||
assert_array_almost_equal(diff(sin(x)),direct_diff(sin(x)))
|
||||
assert_array_almost_equal(diff(sin(x),2),direct_diff(sin(x),2))
|
||||
assert_array_almost_equal(diff(sin(x),3),direct_diff(sin(x),3))
|
||||
assert_array_almost_equal(diff(sin(x),4),direct_diff(sin(x),4))
|
||||
assert_array_almost_equal(diff(sin(x),5),direct_diff(sin(x),5))
|
||||
assert_array_almost_equal(diff(sin(2*x),3),direct_diff(sin(2*x),3))
|
||||
assert_array_almost_equal(diff(sin(2*x),4),direct_diff(sin(2*x),4))
|
||||
assert_array_almost_equal(diff(cos(x)),direct_diff(cos(x)))
|
||||
assert_array_almost_equal(diff(cos(x),2),direct_diff(cos(x),2))
|
||||
assert_array_almost_equal(diff(cos(x),3),direct_diff(cos(x),3))
|
||||
assert_array_almost_equal(diff(cos(x),4),direct_diff(cos(x),4))
|
||||
assert_array_almost_equal(diff(cos(2*x)),direct_diff(cos(2*x)))
|
||||
assert_array_almost_equal(diff(sin(x*n/8)),direct_diff(sin(x*n/8)))
|
||||
assert_array_almost_equal(diff(cos(x*n/8)),direct_diff(cos(x*n/8)))
|
||||
for k in range(5):
|
||||
assert_array_almost_equal(diff(sin(4*x),k),direct_diff(sin(4*x),k))
|
||||
assert_array_almost_equal(diff(cos(4*x),k),direct_diff(cos(4*x),k))
|
||||
|
||||
def test_period(self):
|
||||
for n in [17,64]:
|
||||
x = arange(n)/float(n)
|
||||
assert_array_almost_equal(diff(sin(2*pi*x),period=1),
|
||||
2*pi*cos(2*pi*x))
|
||||
assert_array_almost_equal(diff(sin(2*pi*x),3,period=1),
|
||||
-(2*pi)**3*cos(2*pi*x))
|
||||
|
||||
def test_sin(self):
|
||||
for n in [32,64,77]:
|
||||
x = arange(n)*2*pi/n
|
||||
assert_array_almost_equal(diff(sin(x)),cos(x))
|
||||
assert_array_almost_equal(diff(cos(x)),-sin(x))
|
||||
assert_array_almost_equal(diff(sin(x),2),-sin(x))
|
||||
assert_array_almost_equal(diff(sin(x),4),sin(x))
|
||||
assert_array_almost_equal(diff(sin(4*x)),4*cos(4*x))
|
||||
assert_array_almost_equal(diff(sin(sin(x))),cos(x)*cos(sin(x)))
|
||||
|
||||
def test_expr(self):
|
||||
for n in [64,77,100,128,256,512,1024,2048,4096,8192][:5]:
|
||||
x = arange(n)*2*pi/n
|
||||
f = sin(x)*cos(4*x)+exp(sin(3*x))
|
||||
df = cos(x)*cos(4*x)-4*sin(x)*sin(4*x)+3*cos(3*x)*exp(sin(3*x))
|
||||
ddf = -17*sin(x)*cos(4*x)-8*cos(x)*sin(4*x)\
|
||||
- 9*sin(3*x)*exp(sin(3*x))+9*cos(3*x)**2*exp(sin(3*x))
|
||||
d1 = diff(f)
|
||||
assert_array_almost_equal(d1,df)
|
||||
assert_array_almost_equal(diff(df),ddf)
|
||||
assert_array_almost_equal(diff(f,2),ddf)
|
||||
assert_array_almost_equal(diff(ddf,-1),df)
|
||||
|
||||
def test_expr_large(self):
|
||||
for n in [2048,4096]:
|
||||
x = arange(n)*2*pi/n
|
||||
f = sin(x)*cos(4*x)+exp(sin(3*x))
|
||||
df = cos(x)*cos(4*x)-4*sin(x)*sin(4*x)+3*cos(3*x)*exp(sin(3*x))
|
||||
ddf = -17*sin(x)*cos(4*x)-8*cos(x)*sin(4*x)\
|
||||
- 9*sin(3*x)*exp(sin(3*x))+9*cos(3*x)**2*exp(sin(3*x))
|
||||
assert_array_almost_equal(diff(f),df)
|
||||
assert_array_almost_equal(diff(df),ddf)
|
||||
assert_array_almost_equal(diff(ddf,-1),df)
|
||||
assert_array_almost_equal(diff(f,2),ddf)
|
||||
|
||||
def test_int(self):
|
||||
n = 64
|
||||
x = arange(n)*2*pi/n
|
||||
assert_array_almost_equal(diff(sin(x),-1),-cos(x))
|
||||
assert_array_almost_equal(diff(sin(x),-2),-sin(x))
|
||||
assert_array_almost_equal(diff(sin(x),-4),sin(x))
|
||||
assert_array_almost_equal(diff(2*cos(2*x),-1),sin(2*x))
|
||||
|
||||
def test_random_even(self):
|
||||
for k in [0,2,4,6]:
|
||||
for n in [60,32,64,56,55]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
# zeroing Nyquist mode:
|
||||
f = diff(diff(f,1),-1)
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(diff(diff(f,k),-k),f)
|
||||
assert_array_almost_equal(diff(diff(f,-k),k),f)
|
||||
|
||||
def test_random_odd(self):
|
||||
for k in [0,1,2,3,4,5,6]:
|
||||
for n in [33,65,55]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(diff(diff(f,k),-k),f)
|
||||
assert_array_almost_equal(diff(diff(f,-k),k),f)
|
||||
|
||||
def test_zero_nyquist(self):
|
||||
for k in [0,1,2,3,4,5,6]:
|
||||
for n in [32,33,64,56,55]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
# zeroing Nyquist mode:
|
||||
f = diff(diff(f,1),-1)
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(diff(diff(f,k),-k),f)
|
||||
assert_array_almost_equal(diff(diff(f,-k),k),f)
|
||||
|
||||
|
||||
class TestTilbert:
|
||||
|
||||
def test_definition(self):
|
||||
for h in [0.1,0.5,1,5.5,10]:
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
y = tilbert(sin(x),h)
|
||||
y1 = direct_tilbert(sin(x),h)
|
||||
assert_array_almost_equal(y,y1)
|
||||
assert_array_almost_equal(tilbert(sin(x),h),
|
||||
direct_tilbert(sin(x),h))
|
||||
assert_array_almost_equal(tilbert(sin(2*x),h),
|
||||
direct_tilbert(sin(2*x),h))
|
||||
|
||||
def test_random_even(self):
|
||||
for h in [0.1,0.5,1,5.5,10]:
|
||||
for n in [32,64,56]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(direct_tilbert(direct_itilbert(f,h),h),f)
|
||||
|
||||
def test_random_odd(self):
|
||||
for h in [0.1,0.5,1,5.5,10]:
|
||||
for n in [33,65,55]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(itilbert(tilbert(f,h),h),f)
|
||||
assert_array_almost_equal(tilbert(itilbert(f,h),h),f)
|
||||
|
||||
|
||||
class TestITilbert:
|
||||
|
||||
def test_definition(self):
|
||||
for h in [0.1,0.5,1,5.5,10]:
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
y = itilbert(sin(x),h)
|
||||
y1 = direct_itilbert(sin(x),h)
|
||||
assert_array_almost_equal(y,y1)
|
||||
assert_array_almost_equal(itilbert(sin(x),h),
|
||||
direct_itilbert(sin(x),h))
|
||||
assert_array_almost_equal(itilbert(sin(2*x),h),
|
||||
direct_itilbert(sin(2*x),h))
|
||||
|
||||
|
||||
class TestHilbert:
|
||||
|
||||
def test_definition(self):
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
y = hilbert(sin(x))
|
||||
y1 = direct_hilbert(sin(x))
|
||||
assert_array_almost_equal(y,y1)
|
||||
assert_array_almost_equal(hilbert(sin(2*x)),
|
||||
direct_hilbert(sin(2*x)))
|
||||
|
||||
def test_tilbert_relation(self):
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
f = sin(x)+cos(2*x)*sin(x)
|
||||
y = hilbert(f)
|
||||
y1 = direct_hilbert(f)
|
||||
assert_array_almost_equal(y,y1)
|
||||
y2 = tilbert(f,h=10)
|
||||
assert_array_almost_equal(y,y2)
|
||||
|
||||
def test_random_odd(self):
|
||||
for n in [33,65,55]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(ihilbert(hilbert(f)),f)
|
||||
assert_array_almost_equal(hilbert(ihilbert(f)),f)
|
||||
|
||||
def test_random_even(self):
|
||||
for n in [32,64,56]:
|
||||
f = random((n,))
|
||||
af = sum(f,axis=0)/n
|
||||
f = f-af
|
||||
# zeroing Nyquist mode:
|
||||
f = diff(diff(f,1),-1)
|
||||
assert_almost_equal(sum(f,axis=0),0.0)
|
||||
assert_array_almost_equal(direct_hilbert(direct_ihilbert(f)),f)
|
||||
assert_array_almost_equal(hilbert(ihilbert(f)),f)
|
||||
|
||||
|
||||
class TestIHilbert:
|
||||
|
||||
def test_definition(self):
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
y = ihilbert(sin(x))
|
||||
y1 = direct_ihilbert(sin(x))
|
||||
assert_array_almost_equal(y,y1)
|
||||
assert_array_almost_equal(ihilbert(sin(2*x)),
|
||||
direct_ihilbert(sin(2*x)))
|
||||
|
||||
def test_itilbert_relation(self):
|
||||
for n in [16,17,64,127]:
|
||||
x = arange(n)*2*pi/n
|
||||
f = sin(x)+cos(2*x)*sin(x)
|
||||
y = ihilbert(f)
|
||||
y1 = direct_ihilbert(f)
|
||||
assert_array_almost_equal(y,y1)
|
||||
y2 = itilbert(f,h=10)
|
||||
assert_array_almost_equal(y,y2)
|
||||
|
||||
|
||||
class TestShift:
|
||||
|
||||
def test_definition(self):
|
||||
for n in [18,17,64,127,32,2048,256]:
|
||||
x = arange(n)*2*pi/n
|
||||
for a in [0.1,3]:
|
||||
assert_array_almost_equal(shift(sin(x),a),direct_shift(sin(x),a))
|
||||
assert_array_almost_equal(shift(sin(x),a),sin(x+a))
|
||||
assert_array_almost_equal(shift(cos(x),a),cos(x+a))
|
||||
assert_array_almost_equal(shift(cos(2*x)+sin(x),a),
|
||||
cos(2*(x+a))+sin(x+a))
|
||||
assert_array_almost_equal(shift(exp(sin(x)),a),exp(sin(x+a)))
|
||||
assert_array_almost_equal(shift(sin(x),2*pi),sin(x))
|
||||
assert_array_almost_equal(shift(sin(x),pi),-sin(x))
|
||||
assert_array_almost_equal(shift(sin(x),pi/2),cos(x))
|
||||
|
||||
|
||||
class TestOverwrite:
|
||||
"""Check input overwrite behavior """
|
||||
|
||||
real_dtypes = (np.float32, np.float64)
|
||||
dtypes = real_dtypes + (np.complex64, np.complex128)
|
||||
|
||||
def _check(self, x, routine, *args, **kwargs):
|
||||
x2 = x.copy()
|
||||
routine(x2, *args, **kwargs)
|
||||
sig = routine.__name__
|
||||
if args:
|
||||
sig += repr(args)
|
||||
if kwargs:
|
||||
sig += repr(kwargs)
|
||||
assert_equal(x2, x, err_msg="spurious overwrite in %s" % sig)
|
||||
|
||||
def _check_1d(self, routine, dtype, shape, *args, **kwargs):
|
||||
np.random.seed(1234)
|
||||
if np.issubdtype(dtype, np.complexfloating):
|
||||
data = np.random.randn(*shape) + 1j*np.random.randn(*shape)
|
||||
else:
|
||||
data = np.random.randn(*shape)
|
||||
data = data.astype(dtype)
|
||||
self._check(data, routine, *args, **kwargs)
|
||||
|
||||
def test_diff(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(diff, dtype, (16,))
|
||||
|
||||
def test_tilbert(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(tilbert, dtype, (16,), 1.6)
|
||||
|
||||
def test_itilbert(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(itilbert, dtype, (16,), 1.6)
|
||||
|
||||
def test_hilbert(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(hilbert, dtype, (16,))
|
||||
|
||||
def test_cs_diff(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(cs_diff, dtype, (16,), 1.0, 4.0)
|
||||
|
||||
def test_sc_diff(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(sc_diff, dtype, (16,), 1.0, 4.0)
|
||||
|
||||
def test_ss_diff(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(ss_diff, dtype, (16,), 1.0, 4.0)
|
||||
|
||||
def test_cc_diff(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(cc_diff, dtype, (16,), 1.0, 4.0)
|
||||
|
||||
def test_shift(self):
|
||||
for dtype in self.dtypes:
|
||||
self._check_1d(shift, dtype, (16,), 1.0)
|
||||
@ -0,0 +1,815 @@
|
||||
from os.path import join, dirname
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_almost_equal, assert_equal
|
||||
import pytest
|
||||
from pytest import raises as assert_raises
|
||||
|
||||
from scipy.fftpack._realtransforms import (
|
||||
dct, idct, dst, idst, dctn, idctn, dstn, idstn)
|
||||
|
||||
# Matlab reference data
|
||||
MDATA = np.load(join(dirname(__file__), 'test.npz'))
|
||||
X = [MDATA['x%d' % i] for i in range(8)]
|
||||
Y = [MDATA['y%d' % i] for i in range(8)]
|
||||
|
||||
# FFTW reference data: the data are organized as follows:
|
||||
# * SIZES is an array containing all available sizes
|
||||
# * for every type (1, 2, 3, 4) and every size, the array dct_type_size
|
||||
# contains the output of the DCT applied to the input np.linspace(0, size-1,
|
||||
# size)
|
||||
FFTWDATA_DOUBLE = np.load(join(dirname(__file__), 'fftw_double_ref.npz'))
|
||||
FFTWDATA_SINGLE = np.load(join(dirname(__file__), 'fftw_single_ref.npz'))
|
||||
FFTWDATA_SIZES = FFTWDATA_DOUBLE['sizes']
|
||||
|
||||
|
||||
def fftw_dct_ref(type, size, dt):
|
||||
x = np.linspace(0, size-1, size).astype(dt)
|
||||
dt = np.result_type(np.float32, dt)
|
||||
if dt == np.float64:
|
||||
data = FFTWDATA_DOUBLE
|
||||
elif dt == np.float32:
|
||||
data = FFTWDATA_SINGLE
|
||||
else:
|
||||
raise ValueError()
|
||||
y = (data['dct_%d_%d' % (type, size)]).astype(dt)
|
||||
return x, y, dt
|
||||
|
||||
|
||||
def fftw_dst_ref(type, size, dt):
|
||||
x = np.linspace(0, size-1, size).astype(dt)
|
||||
dt = np.result_type(np.float32, dt)
|
||||
if dt == np.float64:
|
||||
data = FFTWDATA_DOUBLE
|
||||
elif dt == np.float32:
|
||||
data = FFTWDATA_SINGLE
|
||||
else:
|
||||
raise ValueError()
|
||||
y = (data['dst_%d_%d' % (type, size)]).astype(dt)
|
||||
return x, y, dt
|
||||
|
||||
|
||||
def dct_2d_ref(x, **kwargs):
|
||||
"""Calculate reference values for testing dct2."""
|
||||
x = np.array(x, copy=True)
|
||||
for row in range(x.shape[0]):
|
||||
x[row, :] = dct(x[row, :], **kwargs)
|
||||
for col in range(x.shape[1]):
|
||||
x[:, col] = dct(x[:, col], **kwargs)
|
||||
return x
|
||||
|
||||
|
||||
def idct_2d_ref(x, **kwargs):
|
||||
"""Calculate reference values for testing idct2."""
|
||||
x = np.array(x, copy=True)
|
||||
for row in range(x.shape[0]):
|
||||
x[row, :] = idct(x[row, :], **kwargs)
|
||||
for col in range(x.shape[1]):
|
||||
x[:, col] = idct(x[:, col], **kwargs)
|
||||
return x
|
||||
|
||||
|
||||
def dst_2d_ref(x, **kwargs):
|
||||
"""Calculate reference values for testing dst2."""
|
||||
x = np.array(x, copy=True)
|
||||
for row in range(x.shape[0]):
|
||||
x[row, :] = dst(x[row, :], **kwargs)
|
||||
for col in range(x.shape[1]):
|
||||
x[:, col] = dst(x[:, col], **kwargs)
|
||||
return x
|
||||
|
||||
|
||||
def idst_2d_ref(x, **kwargs):
|
||||
"""Calculate reference values for testing idst2."""
|
||||
x = np.array(x, copy=True)
|
||||
for row in range(x.shape[0]):
|
||||
x[row, :] = idst(x[row, :], **kwargs)
|
||||
for col in range(x.shape[1]):
|
||||
x[:, col] = idst(x[:, col], **kwargs)
|
||||
return x
|
||||
|
||||
|
||||
def naive_dct1(x, norm=None):
|
||||
"""Calculate textbook definition version of DCT-I."""
|
||||
x = np.array(x, copy=True)
|
||||
N = len(x)
|
||||
M = N-1
|
||||
y = np.zeros(N)
|
||||
m0, m = 1, 2
|
||||
if norm == 'ortho':
|
||||
m0 = np.sqrt(1.0/M)
|
||||
m = np.sqrt(2.0/M)
|
||||
for k in range(N):
|
||||
for n in range(1, N-1):
|
||||
y[k] += m*x[n]*np.cos(np.pi*n*k/M)
|
||||
y[k] += m0 * x[0]
|
||||
y[k] += m0 * x[N-1] * (1 if k % 2 == 0 else -1)
|
||||
if norm == 'ortho':
|
||||
y[0] *= 1/np.sqrt(2)
|
||||
y[N-1] *= 1/np.sqrt(2)
|
||||
return y
|
||||
|
||||
|
||||
def naive_dst1(x, norm=None):
|
||||
"""Calculate textbook definition version of DST-I."""
|
||||
x = np.array(x, copy=True)
|
||||
N = len(x)
|
||||
M = N+1
|
||||
y = np.zeros(N)
|
||||
for k in range(N):
|
||||
for n in range(N):
|
||||
y[k] += 2*x[n]*np.sin(np.pi*(n+1.0)*(k+1.0)/M)
|
||||
if norm == 'ortho':
|
||||
y *= np.sqrt(0.5/M)
|
||||
return y
|
||||
|
||||
|
||||
def naive_dct4(x, norm=None):
|
||||
"""Calculate textbook definition version of DCT-IV."""
|
||||
x = np.array(x, copy=True)
|
||||
N = len(x)
|
||||
y = np.zeros(N)
|
||||
for k in range(N):
|
||||
for n in range(N):
|
||||
y[k] += x[n]*np.cos(np.pi*(n+0.5)*(k+0.5)/(N))
|
||||
if norm == 'ortho':
|
||||
y *= np.sqrt(2.0/N)
|
||||
else:
|
||||
y *= 2
|
||||
return y
|
||||
|
||||
|
||||
def naive_dst4(x, norm=None):
|
||||
"""Calculate textbook definition version of DST-IV."""
|
||||
x = np.array(x, copy=True)
|
||||
N = len(x)
|
||||
y = np.zeros(N)
|
||||
for k in range(N):
|
||||
for n in range(N):
|
||||
y[k] += x[n]*np.sin(np.pi*(n+0.5)*(k+0.5)/(N))
|
||||
if norm == 'ortho':
|
||||
y *= np.sqrt(2.0/N)
|
||||
else:
|
||||
y *= 2
|
||||
return y
|
||||
|
||||
|
||||
class TestComplex:
|
||||
def test_dct_complex64(self):
|
||||
y = dct(1j*np.arange(5, dtype=np.complex64))
|
||||
x = 1j*dct(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
def test_dct_complex(self):
|
||||
y = dct(np.arange(5)*1j)
|
||||
x = 1j*dct(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
def test_idct_complex(self):
|
||||
y = idct(np.arange(5)*1j)
|
||||
x = 1j*idct(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
def test_dst_complex64(self):
|
||||
y = dst(np.arange(5, dtype=np.complex64)*1j)
|
||||
x = 1j*dst(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
def test_dst_complex(self):
|
||||
y = dst(np.arange(5)*1j)
|
||||
x = 1j*dst(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
def test_idst_complex(self):
|
||||
y = idst(np.arange(5)*1j)
|
||||
x = 1j*idst(np.arange(5))
|
||||
assert_array_almost_equal(x, y)
|
||||
|
||||
|
||||
class _TestDCTBase:
|
||||
def setup_method(self):
|
||||
self.rdt = None
|
||||
self.dec = 14
|
||||
self.type = None
|
||||
|
||||
def test_definition(self):
|
||||
for i in FFTWDATA_SIZES:
|
||||
x, yr, dt = fftw_dct_ref(self.type, i, self.rdt)
|
||||
y = dct(x, type=self.type)
|
||||
assert_equal(y.dtype, dt)
|
||||
# XXX: we divide by np.max(y) because the tests fail otherwise. We
|
||||
# should really use something like assert_array_approx_equal. The
|
||||
# difference is due to fftw using a better algorithm w.r.t error
|
||||
# propagation compared to the ones from fftpack.
|
||||
assert_array_almost_equal(y / np.max(y), yr / np.max(y), decimal=self.dec,
|
||||
err_msg="Size %d failed" % i)
|
||||
|
||||
def test_axis(self):
|
||||
nt = 2
|
||||
for i in [7, 8, 9, 16, 32, 64]:
|
||||
x = np.random.randn(nt, i)
|
||||
y = dct(x, type=self.type)
|
||||
for j in range(nt):
|
||||
assert_array_almost_equal(y[j], dct(x[j], type=self.type),
|
||||
decimal=self.dec)
|
||||
|
||||
x = x.T
|
||||
y = dct(x, axis=0, type=self.type)
|
||||
for j in range(nt):
|
||||
assert_array_almost_equal(y[:,j], dct(x[:,j], type=self.type),
|
||||
decimal=self.dec)
|
||||
|
||||
|
||||
class _TestDCTIBase(_TestDCTBase):
|
||||
def test_definition_ortho(self):
|
||||
# Test orthornomal mode.
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr in X:
|
||||
x = np.array(xr, dtype=self.rdt)
|
||||
y = dct(x, norm='ortho', type=1)
|
||||
y2 = naive_dct1(x, norm='ortho')
|
||||
assert_equal(y.dtype, dt)
|
||||
assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec)
|
||||
|
||||
class _TestDCTIIBase(_TestDCTBase):
|
||||
def test_definition_matlab(self):
|
||||
# Test correspondence with MATLAB (orthornomal mode).
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr, yr in zip(X, Y):
|
||||
x = np.array(xr, dtype=dt)
|
||||
y = dct(x, norm="ortho", type=2)
|
||||
assert_equal(y.dtype, dt)
|
||||
assert_array_almost_equal(y, yr, decimal=self.dec)
|
||||
|
||||
|
||||
class _TestDCTIIIBase(_TestDCTBase):
|
||||
def test_definition_ortho(self):
|
||||
# Test orthornomal mode.
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr in X:
|
||||
x = np.array(xr, dtype=self.rdt)
|
||||
y = dct(x, norm='ortho', type=2)
|
||||
xi = dct(y, norm="ortho", type=3)
|
||||
assert_equal(xi.dtype, dt)
|
||||
assert_array_almost_equal(xi, x, decimal=self.dec)
|
||||
|
||||
class _TestDCTIVBase(_TestDCTBase):
|
||||
def test_definition_ortho(self):
|
||||
# Test orthornomal mode.
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr in X:
|
||||
x = np.array(xr, dtype=self.rdt)
|
||||
y = dct(x, norm='ortho', type=4)
|
||||
y2 = naive_dct4(x, norm='ortho')
|
||||
assert_equal(y.dtype, dt)
|
||||
assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec)
|
||||
|
||||
|
||||
class TestDCTIDouble(_TestDCTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 10
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDCTIFloat(_TestDCTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDCTIInt(_TestDCTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDCTIIDouble(_TestDCTIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 10
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDCTIIFloat(_TestDCTIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDCTIIInt(_TestDCTIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDCTIIIDouble(_TestDCTIIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDCTIIIFloat(_TestDCTIIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDCTIIIInt(_TestDCTIIIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDCTIVDouble(_TestDCTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDCTIVFloat(_TestDCTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDCTIVInt(_TestDCTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
|
||||
class _TestIDCTBase:
|
||||
def setup_method(self):
|
||||
self.rdt = None
|
||||
self.dec = 14
|
||||
self.type = None
|
||||
|
||||
def test_definition(self):
|
||||
for i in FFTWDATA_SIZES:
|
||||
xr, yr, dt = fftw_dct_ref(self.type, i, self.rdt)
|
||||
x = idct(yr, type=self.type)
|
||||
if self.type == 1:
|
||||
x /= 2 * (i-1)
|
||||
else:
|
||||
x /= 2 * i
|
||||
assert_equal(x.dtype, dt)
|
||||
# XXX: we divide by np.max(y) because the tests fail otherwise. We
|
||||
# should really use something like assert_array_approx_equal. The
|
||||
# difference is due to fftw using a better algorithm w.r.t error
|
||||
# propagation compared to the ones from fftpack.
|
||||
assert_array_almost_equal(x / np.max(x), xr / np.max(x), decimal=self.dec,
|
||||
err_msg="Size %d failed" % i)
|
||||
|
||||
|
||||
class TestIDCTIDouble(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 10
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDCTIFloat(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDCTIInt(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDCTIIDouble(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 10
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDCTIIFloat(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDCTIIInt(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDCTIIIDouble(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestIDCTIIIFloat(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestIDCTIIIInt(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 3
|
||||
|
||||
class TestIDCTIVDouble(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestIDCTIVFloat(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 5
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestIDCTIVInt(_TestIDCTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 4
|
||||
|
||||
class _TestDSTBase:
|
||||
def setup_method(self):
|
||||
self.rdt = None # dtype
|
||||
self.dec = None # number of decimals to match
|
||||
self.type = None # dst type
|
||||
|
||||
def test_definition(self):
|
||||
for i in FFTWDATA_SIZES:
|
||||
xr, yr, dt = fftw_dst_ref(self.type, i, self.rdt)
|
||||
y = dst(xr, type=self.type)
|
||||
assert_equal(y.dtype, dt)
|
||||
# XXX: we divide by np.max(y) because the tests fail otherwise. We
|
||||
# should really use something like assert_array_approx_equal. The
|
||||
# difference is due to fftw using a better algorithm w.r.t error
|
||||
# propagation compared to the ones from fftpack.
|
||||
assert_array_almost_equal(y / np.max(y), yr / np.max(y), decimal=self.dec,
|
||||
err_msg="Size %d failed" % i)
|
||||
|
||||
|
||||
class _TestDSTIBase(_TestDSTBase):
|
||||
def test_definition_ortho(self):
|
||||
# Test orthornomal mode.
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr in X:
|
||||
x = np.array(xr, dtype=self.rdt)
|
||||
y = dst(x, norm='ortho', type=1)
|
||||
y2 = naive_dst1(x, norm='ortho')
|
||||
assert_equal(y.dtype, dt)
|
||||
assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec)
|
||||
|
||||
class _TestDSTIVBase(_TestDSTBase):
|
||||
def test_definition_ortho(self):
|
||||
# Test orthornomal mode.
|
||||
dt = np.result_type(np.float32, self.rdt)
|
||||
for xr in X:
|
||||
x = np.array(xr, dtype=self.rdt)
|
||||
y = dst(x, norm='ortho', type=4)
|
||||
y2 = naive_dst4(x, norm='ortho')
|
||||
assert_equal(y.dtype, dt)
|
||||
assert_array_almost_equal(y, y2, decimal=self.dec)
|
||||
|
||||
class TestDSTIDouble(_TestDSTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDSTIFloat(_TestDSTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDSTIInt(_TestDSTIBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestDSTIIDouble(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDSTIIFloat(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 6
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDSTIIInt(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 6
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestDSTIIIDouble(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDSTIIIFloat(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 7
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDSTIIIInt(_TestDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 7
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestDSTIVDouble(_TestDSTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestDSTIVFloat(_TestDSTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 4
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestDSTIVInt(_TestDSTIVBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 5
|
||||
self.type = 4
|
||||
|
||||
|
||||
class _TestIDSTBase:
|
||||
def setup_method(self):
|
||||
self.rdt = None
|
||||
self.dec = None
|
||||
self.type = None
|
||||
|
||||
def test_definition(self):
|
||||
for i in FFTWDATA_SIZES:
|
||||
xr, yr, dt = fftw_dst_ref(self.type, i, self.rdt)
|
||||
x = idst(yr, type=self.type)
|
||||
if self.type == 1:
|
||||
x /= 2 * (i+1)
|
||||
else:
|
||||
x /= 2 * i
|
||||
assert_equal(x.dtype, dt)
|
||||
# XXX: we divide by np.max(x) because the tests fail otherwise. We
|
||||
# should really use something like assert_array_approx_equal. The
|
||||
# difference is due to fftw using a better algorithm w.r.t error
|
||||
# propagation compared to the ones from fftpack.
|
||||
assert_array_almost_equal(x / np.max(x), xr / np.max(x), decimal=self.dec,
|
||||
err_msg="Size %d failed" % i)
|
||||
|
||||
|
||||
class TestIDSTIDouble(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDSTIFloat(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDSTIInt(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 4
|
||||
self.type = 1
|
||||
|
||||
|
||||
class TestIDSTIIDouble(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDSTIIFloat(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 6
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDSTIIInt(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 6
|
||||
self.type = 2
|
||||
|
||||
|
||||
class TestIDSTIIIDouble(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 14
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestIDSTIIIFloat(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 6
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestIDSTIIIInt(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 6
|
||||
self.type = 3
|
||||
|
||||
|
||||
class TestIDSTIVDouble(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float64
|
||||
self.dec = 12
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestIDSTIVFloat(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = np.float32
|
||||
self.dec = 6
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestIDSTIVnt(_TestIDSTBase):
|
||||
def setup_method(self):
|
||||
self.rdt = int
|
||||
self.dec = 6
|
||||
self.type = 4
|
||||
|
||||
|
||||
class TestOverwrite:
|
||||
"""Check input overwrite behavior."""
|
||||
|
||||
real_dtypes = [np.float32, np.float64]
|
||||
|
||||
def _check(self, x, routine, type, fftsize, axis, norm, overwrite_x, **kw):
|
||||
x2 = x.copy()
|
||||
routine(x2, type, fftsize, axis, norm, overwrite_x=overwrite_x)
|
||||
|
||||
sig = "{}({}{!r}, {!r}, axis={!r}, overwrite_x={!r})".format(
|
||||
routine.__name__, x.dtype, x.shape, fftsize, axis, overwrite_x)
|
||||
if not overwrite_x:
|
||||
assert_equal(x2, x, err_msg="spurious overwrite in %s" % sig)
|
||||
|
||||
def _check_1d(self, routine, dtype, shape, axis):
|
||||
np.random.seed(1234)
|
||||
if np.issubdtype(dtype, np.complexfloating):
|
||||
data = np.random.randn(*shape) + 1j*np.random.randn(*shape)
|
||||
else:
|
||||
data = np.random.randn(*shape)
|
||||
data = data.astype(dtype)
|
||||
|
||||
for type in [1, 2, 3, 4]:
|
||||
for overwrite_x in [True, False]:
|
||||
for norm in [None, 'ortho']:
|
||||
self._check(data, routine, type, None, axis, norm,
|
||||
overwrite_x)
|
||||
|
||||
def test_dct(self):
|
||||
for dtype in self.real_dtypes:
|
||||
self._check_1d(dct, dtype, (16,), -1)
|
||||
self._check_1d(dct, dtype, (16, 2), 0)
|
||||
self._check_1d(dct, dtype, (2, 16), 1)
|
||||
|
||||
def test_idct(self):
|
||||
for dtype in self.real_dtypes:
|
||||
self._check_1d(idct, dtype, (16,), -1)
|
||||
self._check_1d(idct, dtype, (16, 2), 0)
|
||||
self._check_1d(idct, dtype, (2, 16), 1)
|
||||
|
||||
def test_dst(self):
|
||||
for dtype in self.real_dtypes:
|
||||
self._check_1d(dst, dtype, (16,), -1)
|
||||
self._check_1d(dst, dtype, (16, 2), 0)
|
||||
self._check_1d(dst, dtype, (2, 16), 1)
|
||||
|
||||
def test_idst(self):
|
||||
for dtype in self.real_dtypes:
|
||||
self._check_1d(idst, dtype, (16,), -1)
|
||||
self._check_1d(idst, dtype, (16, 2), 0)
|
||||
self._check_1d(idst, dtype, (2, 16), 1)
|
||||
|
||||
|
||||
class Test_DCTN_IDCTN:
|
||||
dec = 14
|
||||
dct_type = [1, 2, 3, 4]
|
||||
norms = [None, 'ortho']
|
||||
rstate = np.random.RandomState(1234)
|
||||
shape = (32, 16)
|
||||
data = rstate.randn(*shape)
|
||||
|
||||
@pytest.mark.parametrize('fforward,finverse', [(dctn, idctn),
|
||||
(dstn, idstn)])
|
||||
@pytest.mark.parametrize('axes', [None,
|
||||
1, (1,), [1],
|
||||
0, (0,), [0],
|
||||
(0, 1), [0, 1],
|
||||
(-2, -1), [-2, -1]])
|
||||
@pytest.mark.parametrize('dct_type', dct_type)
|
||||
@pytest.mark.parametrize('norm', ['ortho'])
|
||||
def test_axes_round_trip(self, fforward, finverse, axes, dct_type, norm):
|
||||
tmp = fforward(self.data, type=dct_type, axes=axes, norm=norm)
|
||||
tmp = finverse(tmp, type=dct_type, axes=axes, norm=norm)
|
||||
assert_array_almost_equal(self.data, tmp, decimal=12)
|
||||
|
||||
@pytest.mark.parametrize('fforward,fforward_ref', [(dctn, dct_2d_ref),
|
||||
(dstn, dst_2d_ref)])
|
||||
@pytest.mark.parametrize('dct_type', dct_type)
|
||||
@pytest.mark.parametrize('norm', norms)
|
||||
def test_dctn_vs_2d_reference(self, fforward, fforward_ref,
|
||||
dct_type, norm):
|
||||
y1 = fforward(self.data, type=dct_type, axes=None, norm=norm)
|
||||
y2 = fforward_ref(self.data, type=dct_type, norm=norm)
|
||||
assert_array_almost_equal(y1, y2, decimal=11)
|
||||
|
||||
@pytest.mark.parametrize('finverse,finverse_ref', [(idctn, idct_2d_ref),
|
||||
(idstn, idst_2d_ref)])
|
||||
@pytest.mark.parametrize('dct_type', dct_type)
|
||||
@pytest.mark.parametrize('norm', [None, 'ortho'])
|
||||
def test_idctn_vs_2d_reference(self, finverse, finverse_ref,
|
||||
dct_type, norm):
|
||||
fdata = dctn(self.data, type=dct_type, norm=norm)
|
||||
y1 = finverse(fdata, type=dct_type, norm=norm)
|
||||
y2 = finverse_ref(fdata, type=dct_type, norm=norm)
|
||||
assert_array_almost_equal(y1, y2, decimal=11)
|
||||
|
||||
@pytest.mark.parametrize('fforward,finverse', [(dctn, idctn),
|
||||
(dstn, idstn)])
|
||||
def test_axes_and_shape(self, fforward, finverse):
|
||||
with assert_raises(ValueError,
|
||||
match="when given, axes and shape arguments"
|
||||
" have to be of the same length"):
|
||||
fforward(self.data, shape=self.data.shape[0], axes=(0, 1))
|
||||
|
||||
with assert_raises(ValueError,
|
||||
match="when given, axes and shape arguments"
|
||||
" have to be of the same length"):
|
||||
fforward(self.data, shape=self.data.shape[0], axes=None)
|
||||
|
||||
with assert_raises(ValueError,
|
||||
match="when given, axes and shape arguments"
|
||||
" have to be of the same length"):
|
||||
fforward(self.data, shape=self.data.shape, axes=0)
|
||||
|
||||
@pytest.mark.parametrize('fforward', [dctn, dstn])
|
||||
def test_shape(self, fforward):
|
||||
tmp = fforward(self.data, shape=(128, 128), axes=None)
|
||||
assert_equal(tmp.shape, (128, 128))
|
||||
|
||||
@pytest.mark.parametrize('fforward,finverse', [(dctn, idctn),
|
||||
(dstn, idstn)])
|
||||
@pytest.mark.parametrize('axes', [1, (1,), [1],
|
||||
0, (0,), [0]])
|
||||
def test_shape_is_none_with_axes(self, fforward, finverse, axes):
|
||||
tmp = fforward(self.data, shape=None, axes=axes, norm='ortho')
|
||||
tmp = finverse(tmp, shape=None, axes=axes, norm='ortho')
|
||||
assert_array_almost_equal(self.data, tmp, decimal=self.dec)
|
||||
Reference in New Issue
Block a user