test_helper.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. """Test functions for fftpack.helper module
  2. Copied from fftpack.helper by Pearu Peterson, October 2005
  3. """
  4. from __future__ import division, absolute_import, print_function
  5. import numpy as np
  6. from numpy.testing import assert_array_almost_equal, assert_equal
  7. from numpy import fft, pi
  8. from numpy.fft.helper import _FFTCache
  9. class TestFFTShift(object):
  10. def test_definition(self):
  11. x = [0, 1, 2, 3, 4, -4, -3, -2, -1]
  12. y = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
  13. assert_array_almost_equal(fft.fftshift(x), y)
  14. assert_array_almost_equal(fft.ifftshift(y), x)
  15. x = [0, 1, 2, 3, 4, -5, -4, -3, -2, -1]
  16. y = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
  17. assert_array_almost_equal(fft.fftshift(x), y)
  18. assert_array_almost_equal(fft.ifftshift(y), x)
  19. def test_inverse(self):
  20. for n in [1, 4, 9, 100, 211]:
  21. x = np.random.random((n,))
  22. assert_array_almost_equal(fft.ifftshift(fft.fftshift(x)), x)
  23. def test_axes_keyword(self):
  24. freqs = [[0, 1, 2], [3, 4, -4], [-3, -2, -1]]
  25. shifted = [[-1, -3, -2], [2, 0, 1], [-4, 3, 4]]
  26. assert_array_almost_equal(fft.fftshift(freqs, axes=(0, 1)), shifted)
  27. assert_array_almost_equal(fft.fftshift(freqs, axes=0),
  28. fft.fftshift(freqs, axes=(0,)))
  29. assert_array_almost_equal(fft.ifftshift(shifted, axes=(0, 1)), freqs)
  30. assert_array_almost_equal(fft.ifftshift(shifted, axes=0),
  31. fft.ifftshift(shifted, axes=(0,)))
  32. assert_array_almost_equal(fft.fftshift(freqs), shifted)
  33. assert_array_almost_equal(fft.ifftshift(shifted), freqs)
  34. def test_uneven_dims(self):
  35. """ Test 2D input, which has uneven dimension sizes """
  36. freqs = [
  37. [0, 1],
  38. [2, 3],
  39. [4, 5]
  40. ]
  41. # shift in dimension 0
  42. shift_dim0 = [
  43. [4, 5],
  44. [0, 1],
  45. [2, 3]
  46. ]
  47. assert_array_almost_equal(fft.fftshift(freqs, axes=0), shift_dim0)
  48. assert_array_almost_equal(fft.ifftshift(shift_dim0, axes=0), freqs)
  49. assert_array_almost_equal(fft.fftshift(freqs, axes=(0,)), shift_dim0)
  50. assert_array_almost_equal(fft.ifftshift(shift_dim0, axes=[0]), freqs)
  51. # shift in dimension 1
  52. shift_dim1 = [
  53. [1, 0],
  54. [3, 2],
  55. [5, 4]
  56. ]
  57. assert_array_almost_equal(fft.fftshift(freqs, axes=1), shift_dim1)
  58. assert_array_almost_equal(fft.ifftshift(shift_dim1, axes=1), freqs)
  59. # shift in both dimensions
  60. shift_dim_both = [
  61. [5, 4],
  62. [1, 0],
  63. [3, 2]
  64. ]
  65. assert_array_almost_equal(fft.fftshift(freqs, axes=(0, 1)), shift_dim_both)
  66. assert_array_almost_equal(fft.ifftshift(shift_dim_both, axes=(0, 1)), freqs)
  67. assert_array_almost_equal(fft.fftshift(freqs, axes=[0, 1]), shift_dim_both)
  68. assert_array_almost_equal(fft.ifftshift(shift_dim_both, axes=[0, 1]), freqs)
  69. # axes=None (default) shift in all dimensions
  70. assert_array_almost_equal(fft.fftshift(freqs, axes=None), shift_dim_both)
  71. assert_array_almost_equal(fft.ifftshift(shift_dim_both, axes=None), freqs)
  72. assert_array_almost_equal(fft.fftshift(freqs), shift_dim_both)
  73. assert_array_almost_equal(fft.ifftshift(shift_dim_both), freqs)
  74. def test_equal_to_original(self):
  75. """ Test that the new (>=v1.15) implementation (see #10073) is equal to the original (<=v1.14) """
  76. from numpy.compat import integer_types
  77. from numpy.core import asarray, concatenate, arange, take
  78. def original_fftshift(x, axes=None):
  79. """ How fftshift was implemented in v1.14"""
  80. tmp = asarray(x)
  81. ndim = tmp.ndim
  82. if axes is None:
  83. axes = list(range(ndim))
  84. elif isinstance(axes, integer_types):
  85. axes = (axes,)
  86. y = tmp
  87. for k in axes:
  88. n = tmp.shape[k]
  89. p2 = (n + 1) // 2
  90. mylist = concatenate((arange(p2, n), arange(p2)))
  91. y = take(y, mylist, k)
  92. return y
  93. def original_ifftshift(x, axes=None):
  94. """ How ifftshift was implemented in v1.14 """
  95. tmp = asarray(x)
  96. ndim = tmp.ndim
  97. if axes is None:
  98. axes = list(range(ndim))
  99. elif isinstance(axes, integer_types):
  100. axes = (axes,)
  101. y = tmp
  102. for k in axes:
  103. n = tmp.shape[k]
  104. p2 = n - (n + 1) // 2
  105. mylist = concatenate((arange(p2, n), arange(p2)))
  106. y = take(y, mylist, k)
  107. return y
  108. # create possible 2d array combinations and try all possible keywords
  109. # compare output to original functions
  110. for i in range(16):
  111. for j in range(16):
  112. for axes_keyword in [0, 1, None, (0,), (0, 1)]:
  113. inp = np.random.rand(i, j)
  114. assert_array_almost_equal(fft.fftshift(inp, axes_keyword),
  115. original_fftshift(inp, axes_keyword))
  116. assert_array_almost_equal(fft.ifftshift(inp, axes_keyword),
  117. original_ifftshift(inp, axes_keyword))
  118. class TestFFTFreq(object):
  119. def test_definition(self):
  120. x = [0, 1, 2, 3, 4, -4, -3, -2, -1]
  121. assert_array_almost_equal(9*fft.fftfreq(9), x)
  122. assert_array_almost_equal(9*pi*fft.fftfreq(9, pi), x)
  123. x = [0, 1, 2, 3, 4, -5, -4, -3, -2, -1]
  124. assert_array_almost_equal(10*fft.fftfreq(10), x)
  125. assert_array_almost_equal(10*pi*fft.fftfreq(10, pi), x)
  126. class TestRFFTFreq(object):
  127. def test_definition(self):
  128. x = [0, 1, 2, 3, 4]
  129. assert_array_almost_equal(9*fft.rfftfreq(9), x)
  130. assert_array_almost_equal(9*pi*fft.rfftfreq(9, pi), x)
  131. x = [0, 1, 2, 3, 4, 5]
  132. assert_array_almost_equal(10*fft.rfftfreq(10), x)
  133. assert_array_almost_equal(10*pi*fft.rfftfreq(10, pi), x)
  134. class TestIRFFTN(object):
  135. def test_not_last_axis_success(self):
  136. ar, ai = np.random.random((2, 16, 8, 32))
  137. a = ar + 1j*ai
  138. axes = (-2,)
  139. # Should not raise error
  140. fft.irfftn(a, axes=axes)
  141. class TestFFTCache(object):
  142. def test_basic_behaviour(self):
  143. c = _FFTCache(max_size_in_mb=1, max_item_count=4)
  144. # Put
  145. c.put_twiddle_factors(1, np.ones(2, dtype=np.float32))
  146. c.put_twiddle_factors(2, np.zeros(2, dtype=np.float32))
  147. # Get
  148. assert_array_almost_equal(c.pop_twiddle_factors(1),
  149. np.ones(2, dtype=np.float32))
  150. assert_array_almost_equal(c.pop_twiddle_factors(2),
  151. np.zeros(2, dtype=np.float32))
  152. # Nothing should be left.
  153. assert_equal(len(c._dict), 0)
  154. # Now put everything in twice so it can be retrieved once and each will
  155. # still have one item left.
  156. for _ in range(2):
  157. c.put_twiddle_factors(1, np.ones(2, dtype=np.float32))
  158. c.put_twiddle_factors(2, np.zeros(2, dtype=np.float32))
  159. assert_array_almost_equal(c.pop_twiddle_factors(1),
  160. np.ones(2, dtype=np.float32))
  161. assert_array_almost_equal(c.pop_twiddle_factors(2),
  162. np.zeros(2, dtype=np.float32))
  163. assert_equal(len(c._dict), 2)
  164. def test_automatic_pruning(self):
  165. # That's around 2600 single precision samples.
  166. c = _FFTCache(max_size_in_mb=0.01, max_item_count=4)
  167. c.put_twiddle_factors(1, np.ones(200, dtype=np.float32))
  168. c.put_twiddle_factors(2, np.ones(200, dtype=np.float32))
  169. assert_equal(list(c._dict.keys()), [1, 2])
  170. # This is larger than the limit but should still be kept.
  171. c.put_twiddle_factors(3, np.ones(3000, dtype=np.float32))
  172. assert_equal(list(c._dict.keys()), [1, 2, 3])
  173. # Add one more.
  174. c.put_twiddle_factors(4, np.ones(3000, dtype=np.float32))
  175. # The other three should no longer exist.
  176. assert_equal(list(c._dict.keys()), [4])
  177. # Now test the max item count pruning.
  178. c = _FFTCache(max_size_in_mb=0.01, max_item_count=2)
  179. c.put_twiddle_factors(2, np.empty(2))
  180. c.put_twiddle_factors(1, np.empty(2))
  181. # Can still be accessed.
  182. assert_equal(list(c._dict.keys()), [2, 1])
  183. c.put_twiddle_factors(3, np.empty(2))
  184. # 1 and 3 can still be accessed - c[2] has been touched least recently
  185. # and is thus evicted.
  186. assert_equal(list(c._dict.keys()), [1, 3])
  187. # One last test. We will add a single large item that is slightly
  188. # bigger then the cache size. Some small items can still be added.
  189. c = _FFTCache(max_size_in_mb=0.01, max_item_count=5)
  190. c.put_twiddle_factors(1, np.ones(3000, dtype=np.float32))
  191. c.put_twiddle_factors(2, np.ones(2, dtype=np.float32))
  192. c.put_twiddle_factors(3, np.ones(2, dtype=np.float32))
  193. c.put_twiddle_factors(4, np.ones(2, dtype=np.float32))
  194. assert_equal(list(c._dict.keys()), [1, 2, 3, 4])
  195. # One more big item. This time it is 6 smaller ones but they are
  196. # counted as one big item.
  197. for _ in range(6):
  198. c.put_twiddle_factors(5, np.ones(500, dtype=np.float32))
  199. # '1' no longer in the cache. Rest still in the cache.
  200. assert_equal(list(c._dict.keys()), [2, 3, 4, 5])
  201. # Another big item - should now be the only item in the cache.
  202. c.put_twiddle_factors(6, np.ones(4000, dtype=np.float32))
  203. assert_equal(list(c._dict.keys()), [6])