示例#1
0
def test_dft_call(impl):

    # 2d, complex, all ones and random back & forth
    shape = (4, 5)
    dft_dom = odl.discr_sequence_space(shape, dtype="complex64")
    dft = DiscreteFourierTransform(domain=dft_dom, impl=impl)
    idft = DiscreteFourierTransformInverse(range=dft_dom, impl=impl)

    assert dft.domain == idft.range
    assert dft.range == idft.domain

    one = dft.domain.one()
    one_dft1 = dft(one, flags=("FFTW_ESTIMATE",))
    one_dft2 = dft.inverse.inverse(one, flags=("FFTW_ESTIMATE",))
    one_dft3 = dft.adjoint.adjoint(one, flags=("FFTW_ESTIMATE",))
    true_dft = [[20, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]  # along all axes by default
    assert np.allclose(one_dft1, true_dft)
    assert np.allclose(one_dft2, true_dft)
    assert np.allclose(one_dft3, true_dft)

    one_idft1 = idft(one_dft1, flags=("FFTW_ESTIMATE",))
    one_idft2 = dft.inverse(one_dft1, flags=("FFTW_ESTIMATE",))
    one_idft3 = dft.adjoint(one_dft1, flags=("FFTW_ESTIMATE",))
    assert np.allclose(one_idft1, one)
    assert np.allclose(one_idft2, one)
    assert np.allclose(one_idft3, one)

    rand_arr = noise_element(dft_dom)
    rand_arr_dft = dft(rand_arr, flags=("FFTW_ESTIMATE",))
    rand_arr_idft = idft(rand_arr_dft, flags=("FFTW_ESTIMATE",))
    assert (rand_arr_idft - rand_arr).norm() < 1e-6

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = 0
    dft_dom = odl.discr_sequence_space(shape, dtype="float32")
    dft = DiscreteFourierTransform(domain=dft_dom, impl=impl, halfcomplex=True, axes=axes)
    idft = DiscreteFourierTransformInverse(range=dft_dom, impl=impl, halfcomplex=True, axes=axes)

    assert dft.domain == idft.range
    assert dft.range == idft.domain

    one = dft.domain.one()
    one_dft = dft(one, flags=("FFTW_ESTIMATE",))
    true_dft = [[4, 4, 4, 4, 4], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]  # transform axis shortened
    assert np.allclose(one_dft, true_dft)

    one_idft1 = idft(one_dft, flags=("FFTW_ESTIMATE",))
    one_idft2 = dft.inverse(one_dft, flags=("FFTW_ESTIMATE",))
    assert np.allclose(one_idft1, one)
    assert np.allclose(one_idft2, one)

    rand_arr = noise_element(dft_dom)
    rand_arr_dft = dft(rand_arr, flags=("FFTW_ESTIMATE",))
    rand_arr_idft = idft(rand_arr_dft, flags=("FFTW_ESTIMATE",))
    assert (rand_arr_idft - rand_arr).norm() < 1e-6
示例#2
0
def test_dft_sign(impl):
    # Test if the FT sign behaves as expected, i.e. that the FT with sign
    # '+' and '-' have same real parts and opposite imaginary parts.

    # 2d, complex, all ones and random back & forth
    shape = (4, 5)
    dft_dom = odl.discr_sequence_space(shape, dtype='complex64')
    dft_minus = DiscreteFourierTransform(domain=dft_dom, impl=impl, sign='-')
    dft_plus = DiscreteFourierTransform(domain=dft_dom, impl=impl, sign='+')

    arr = dft_dom.element([[0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0],
                           [0, 0, 0, 0, 0]])
    arr_dft_minus = dft_minus(arr, flags=('FFTW_ESTIMATE', ))
    arr_dft_plus = dft_plus(arr, flags=('FFTW_ESTIMATE', ))

    assert all_almost_equal(arr_dft_minus.real, arr_dft_plus.real)
    assert all_almost_equal(arr_dft_minus.imag, -arr_dft_plus.imag)
    assert all_almost_equal(dft_minus.inverse(arr_dft_minus), arr)
    assert all_almost_equal(dft_plus.inverse(arr_dft_plus), arr)
    assert all_almost_equal(dft_minus.inverse.inverse(arr), dft_minus(arr))
    assert all_almost_equal(dft_plus.inverse.inverse(arr), dft_plus(arr))

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = (0, )
    dft_dom = odl.discr_sequence_space(shape, dtype='float32')
    arr = dft_dom.element([[0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0],
                           [0, 0, 0, 0, 0]])

    dft = DiscreteFourierTransform(domain=dft_dom,
                                   impl=impl,
                                   halfcomplex=True,
                                   sign='-',
                                   axes=axes)

    arr_dft_minus = dft(arr, flags=('FFTW_ESTIMATE', ))
    arr_idft_minus = dft.inverse(arr_dft_minus, flags=('FFTW_ESTIMATE', ))

    assert all_almost_equal(arr_idft_minus, arr)

    with pytest.raises(ValueError):
        DiscreteFourierTransform(domain=dft_dom,
                                 impl=impl,
                                 halfcomplex=True,
                                 sign='+',
                                 axes=axes)
示例#3
0
def test_dft_range():
    # 1d
    shape = 10
    dom = odl.discr_sequence_space(shape, dtype='complex128')
    fft = DiscreteFourierTransform(dom)
    true_ran = odl.discr_sequence_space(shape, dtype='complex128')
    assert fft.range == true_ran

    # 3d
    shape = (3, 4, 5)
    ran = odl.discr_sequence_space(shape, dtype='complex64')
    fft = DiscreteFourierTransform(ran)
    true_ran = odl.discr_sequence_space(shape, dtype='complex64')
    assert fft.range == true_ran

    # 3d, with axes and halfcomplex
    shape = (3, 4, 5)
    axes = (-1, -2)
    ran_shape = (3, 3, 5)
    dom = odl.discr_sequence_space(shape, dtype='float32')
    fft = DiscreteFourierTransform(dom, axes=axes, halfcomplex=True)
    true_ran = odl.discr_sequence_space(ran_shape, dtype='complex64')
    assert fft.range == true_ran
示例#4
0
def test_dft_sign(impl):
    # Test if the FT sign behaves as expected, i.e. that the FT with sign
    # '+' and '-' have same real parts and opposite imaginary parts.

    # 2d, complex, all ones and random back & forth
    shape = (4, 5)
    dft_dom = odl.discr_sequence_space(shape, dtype="complex64")
    dft_minus = DiscreteFourierTransform(domain=dft_dom, impl=impl, sign="-")
    dft_plus = DiscreteFourierTransform(domain=dft_dom, impl=impl, sign="+")

    arr = dft_dom.element([[0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]])
    arr_dft_minus = dft_minus(arr, flags=("FFTW_ESTIMATE",))
    arr_dft_plus = dft_plus(arr, flags=("FFTW_ESTIMATE",))

    assert all_almost_equal(arr_dft_minus.real, arr_dft_plus.real)
    assert all_almost_equal(arr_dft_minus.imag, -arr_dft_plus.imag)
    assert all_almost_equal(dft_minus.inverse(arr_dft_minus), arr)
    assert all_almost_equal(dft_plus.inverse(arr_dft_plus), arr)
    assert all_almost_equal(dft_minus.inverse.inverse(arr), dft_minus(arr))
    assert all_almost_equal(dft_plus.inverse.inverse(arr), dft_plus(arr))

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = (0,)
    dft_dom = odl.discr_sequence_space(shape, dtype="float32")
    arr = dft_dom.element([[0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]])

    dft = DiscreteFourierTransform(domain=dft_dom, impl=impl, halfcomplex=True, sign="-", axes=axes)

    arr_dft_minus = dft(arr, flags=("FFTW_ESTIMATE",))
    arr_idft_minus = dft.inverse(arr_dft_minus, flags=("FFTW_ESTIMATE",))

    assert all_almost_equal(arr_idft_minus, arr)

    with pytest.raises(ValueError):
        DiscreteFourierTransform(domain=dft_dom, impl=impl, halfcomplex=True, sign="+", axes=axes)
示例#5
0
def test_dft_init_plan(impl):

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = 0
    dft_dom = odl.discr_sequence_space(shape, dtype="float32")

    dft = DiscreteFourierTransform(dft_dom, impl=impl, axes=axes, halfcomplex=True)

    if impl != "pyfftw":
        with pytest.raises(ValueError):
            dft.init_fftw_plan()
        with pytest.raises(ValueError):
            dft.clear_fftw_plan()
    else:
        dft.init_fftw_plan()

        # Make sure plan can be used
        dft._fftw_plan(dft.domain.element().asarray(), dft.range.element().asarray())
        dft.clear_fftw_plan()
        assert dft._fftw_plan is None
示例#6
0
def test_dft_init_raise():
    # Test different error scenarios
    shape = (4, 5)
    dom = odl.discr_sequence_space(shape)
    dom_f32 = odl.discr_sequence_space(shape, dtype='float32')

    # Bad types
    with pytest.raises(TypeError):
        DiscreteFourierTransform(dom.tspace)

    with pytest.raises(TypeError):
        DiscreteFourierTransform(dom, dom.tspace)

    # Illegal arguments
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, impl='fftw')

    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, axes=(1, 2))

    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, axes=(1, -3))

    # Badly shaped range
    bad_ran = odl.discr_sequence_space((3, 5), dtype='complex128')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran)

    bad_ran = odl.discr_sequence_space((10, 10), dtype='complex128')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran)

    bad_ran = odl.discr_sequence_space((4, 5), dtype='complex128')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran, halfcomplex=True)

    bad_ran = odl.discr_sequence_space((4, 3), dtype='complex128')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran, halfcomplex=True, axes=(0, ))

    # Bad data types
    bad_ran = odl.discr_sequence_space(shape, dtype='complex64')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran)

    bad_ran = odl.discr_sequence_space(shape, dtype='float64')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran)

    bad_ran = odl.discr_sequence_space((4, 3), dtype='float64')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, bad_ran, halfcomplex=True)

    bad_ran = odl.discr_sequence_space((4, 3), dtype='complex128')
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom_f32, bad_ran, halfcomplex=True)

    # Bad sign
    with pytest.raises(ValueError):
        DiscreteFourierTransform(dom, sign=-1)
示例#7
0
def test_dft_init(impl):
    # Just check if the code runs at all
    shape = (4, 5)
    dom = odl.discr_sequence_space(shape)
    dom_nonseq = odl.uniform_discr([0, 0], [1, 1], shape)
    dom_f32 = odl.discr_sequence_space(shape, dtype='float32')
    ran = odl.discr_sequence_space(shape, dtype='complex128')
    ran_c64 = odl.discr_sequence_space(shape, dtype='complex64')
    ran_hc = odl.discr_sequence_space((3, 5), dtype='complex128')

    # Implicit range
    DiscreteFourierTransform(dom, impl=impl)
    DiscreteFourierTransform(dom_nonseq, impl=impl)
    DiscreteFourierTransform(dom_f32, impl=impl)
    DiscreteFourierTransform(dom, axes=(0, ), impl=impl)
    DiscreteFourierTransform(dom, axes=(0, -1), impl=impl)
    DiscreteFourierTransform(dom, axes=(0, ), halfcomplex=True, impl=impl)
    DiscreteFourierTransform(dom, impl=impl, sign='+')

    # Explicit range
    DiscreteFourierTransform(dom, range=ran, impl=impl)
    DiscreteFourierTransform(dom_f32, range=ran_c64, impl=impl)
    DiscreteFourierTransform(dom, range=ran, axes=(0, ), impl=impl)
    DiscreteFourierTransform(dom, range=ran, axes=(0, ), impl=impl, sign='+')
    DiscreteFourierTransform(dom, range=ran, axes=(0, -1), impl=impl)
    DiscreteFourierTransform(dom,
                             range=ran_hc,
                             axes=(0, ),
                             impl=impl,
                             halfcomplex=True)
示例#8
0
def test_dft_init_plan(impl):

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = 0
    dft_dom = odl.discr_sequence_space(shape, dtype='float32')

    dft = DiscreteFourierTransform(dft_dom,
                                   impl=impl,
                                   axes=axes,
                                   halfcomplex=True)

    if impl != 'pyfftw':
        with pytest.raises(ValueError):
            dft.init_fftw_plan()
        with pytest.raises(ValueError):
            dft.clear_fftw_plan()
    else:
        dft.init_fftw_plan()

        # Make sure plan can be used
        dft._fftw_plan(dft.domain.element().asarray(),
                       dft.range.element().asarray())
        dft.clear_fftw_plan()
        assert dft._fftw_plan is None
示例#9
0
def test_dft_call(impl):

    # 2d, complex, all ones and random back & forth
    shape = (4, 5)
    dft_dom = odl.discr_sequence_space(shape, dtype='complex64')
    dft = DiscreteFourierTransform(domain=dft_dom, impl=impl)
    idft = DiscreteFourierTransformInverse(range=dft_dom, impl=impl)

    assert dft.domain == idft.range
    assert dft.range == idft.domain

    one = dft.domain.one()
    one_dft1 = dft(one, flags=('FFTW_ESTIMATE', ))
    one_dft2 = dft.inverse.inverse(one, flags=('FFTW_ESTIMATE', ))
    one_dft3 = dft.adjoint.adjoint(one, flags=('FFTW_ESTIMATE', ))
    true_dft = [
        [20, 0, 0, 0, 0],  # along all axes by default
        [0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0]
    ]
    assert np.allclose(one_dft1, true_dft)
    assert np.allclose(one_dft2, true_dft)
    assert np.allclose(one_dft3, true_dft)

    one_idft1 = idft(one_dft1, flags=('FFTW_ESTIMATE', ))
    one_idft2 = dft.inverse(one_dft1, flags=('FFTW_ESTIMATE', ))
    one_idft3 = dft.adjoint(one_dft1, flags=('FFTW_ESTIMATE', ))
    assert np.allclose(one_idft1, one)
    assert np.allclose(one_idft2, one)
    assert np.allclose(one_idft3, one)

    rand_arr = noise_element(dft_dom)
    rand_arr_dft = dft(rand_arr, flags=('FFTW_ESTIMATE', ))
    rand_arr_idft = idft(rand_arr_dft, flags=('FFTW_ESTIMATE', ))
    assert (rand_arr_idft - rand_arr).norm() < 1e-6

    # 2d, halfcomplex, first axis
    shape = (4, 5)
    axes = 0
    dft_dom = odl.discr_sequence_space(shape, dtype='float32')
    dft = DiscreteFourierTransform(domain=dft_dom,
                                   impl=impl,
                                   halfcomplex=True,
                                   axes=axes)
    idft = DiscreteFourierTransformInverse(range=dft_dom,
                                           impl=impl,
                                           halfcomplex=True,
                                           axes=axes)

    assert dft.domain == idft.range
    assert dft.range == idft.domain

    one = dft.domain.one()
    one_dft = dft(one, flags=('FFTW_ESTIMATE', ))
    true_dft = [
        [4, 4, 4, 4, 4],  # transform axis shortened
        [0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0]
    ]
    assert np.allclose(one_dft, true_dft)

    one_idft1 = idft(one_dft, flags=('FFTW_ESTIMATE', ))
    one_idft2 = dft.inverse(one_dft, flags=('FFTW_ESTIMATE', ))
    assert np.allclose(one_idft1, one)
    assert np.allclose(one_idft2, one)

    rand_arr = noise_element(dft_dom)
    rand_arr_dft = dft(rand_arr, flags=('FFTW_ESTIMATE', ))
    rand_arr_idft = idft(rand_arr_dft, flags=('FFTW_ESTIMATE', ))
    assert (rand_arr_idft - rand_arr).norm() < 1e-6