Exemple #1
0
def test_theano_operator():
    """Test the ODL->Theano operator wrapper."""
    # Define ODL operator
    matrix = np.random.rand(3, 2)
    odl_op = odl.MatrixOperator(matrix)

    # Define evaluation points
    x = [1., 2.]
    dy = [1., 2., 3.]

    # Create Theano placeholders
    x_theano = T.dvector()
    dy_theano = T.dvector()

    # Create Theano layer from odl operator
    odl_op_layer = odl.contrib.theano.TheanoOperator(odl_op)

    # Build computation graphs
    y_theano = odl_op_layer(x_theano)
    y_theano_func = theano.function([x_theano], y_theano)
    dy_theano_func = theano.function([x_theano, dy_theano],
                                     T.Rop(y_theano, x_theano, dy_theano))

    # Evaluate using Theano
    result = y_theano_func(x)
    expected = odl_op(x)

    assert all_almost_equal(result, expected)

    # Evaluate the adjoint of the derivative, called gradient in Theano
    result = dy_theano_func(x, dy)
    expected = odl_op.derivative(x).adjoint(dy)

    assert all_almost_equal(result, expected)
Exemple #2
0
def test_as_tensorflow_layer():
    # Define ODL operator
    matrix = np.random.rand(3, 2)
    odl_op = odl.MatrixOperator(matrix)

    # Define evaluation points
    x = np.random.rand(2)
    z = np.random.rand(3)

    # Add empty axes for batch and channel
    x_tf = tf.constant(x)[None, ..., None]
    z_tf = tf.constant(z)[None, ..., None]

    # Create tensorflow layer from odl operator
    odl_op_layer = odl.contrib.tensorflow.as_tensorflow_layer(
        odl_op, 'MatrixOperator')
    y_tf = odl_op_layer(x_tf)

    # Evaluate using tensorflow
    result = y_tf.eval().ravel()
    expected = odl_op(x)

    assert all_almost_equal(result, expected)

    # Evaluate the adjoint of the derivative, called gradient in tensorflow
    result = tf.gradients(y_tf, [x_tf], z_tf)[0].eval().ravel()
    expected = odl_op.derivative(x).adjoint(z)

    assert all_almost_equal(result, expected)
Exemple #3
0
def test_reciprocal_grid_nd_axes():

    grid = odl.uniform_grid([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)
    axes_list = [[1, -1], [0], 0, [0, 2, 1], [2, 0]]

    for axes in axes_list:
        active = np.zeros(grid.ndim, dtype=bool)
        active[axes] = True
        inactive = np.logical_not(active)

        true_recip_stride = np.empty(grid.ndim)
        true_recip_stride[active] = 2 * np.pi / (s[active] * n[active])
        true_recip_stride[inactive] = s[inactive]

        # Without shift altogether
        rgrid = reciprocal_grid(grid, shift=False, axes=axes,
                                halfcomplex=False)

        assert all_equal(rgrid.shape, n)
        assert all_almost_equal(rgrid.stride, true_recip_stride)
        assert all_almost_equal(rgrid.min_pt[active], -rgrid.max_pt[active])
        assert all_equal(rgrid.min_pt[inactive], grid.min_pt[inactive])
        assert all_equal(rgrid.max_pt[inactive], grid.max_pt[inactive])

        # Inverting should give back the original
        irgrid = realspace_grid(rgrid, grid.min_pt, axes=axes,
                                halfcomplex=False)
        assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #4
0
def test_reciprocal_grid_nd_axes():

    grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)
    axes_list = [[1, -1], [0], 0, [0, 2, 1], [2, 0]]

    for axes in axes_list:
        active = np.zeros(grid.ndim, dtype=bool)
        active[axes] = True
        inactive = np.logical_not(active)

        true_recip_stride = np.empty(grid.ndim)
        true_recip_stride[active] = 2 * np.pi / (s[active] * n[active])
        true_recip_stride[inactive] = s[inactive]

        # Without shift altogether
        rgrid = reciprocal_grid(grid, shift=False, axes=axes,
                                halfcomplex=False)

        assert all_equal(rgrid.shape, n)
        assert all_almost_equal(rgrid.stride, true_recip_stride)
        assert all_almost_equal(rgrid.min_pt[active], -rgrid.max_pt[active])
        assert all_equal(rgrid.min_pt[inactive], grid.min_pt[inactive])
        assert all_equal(rgrid.max_pt[inactive], grid.max_pt[inactive])

        # Inverting should give back the original
        irgrid = realspace_grid(rgrid, grid.min_pt, axes=axes,
                                halfcomplex=False)
        assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #5
0
def test_pyfftw_call_plan_preserve_input(planning):

    for shape in [(10,), (3, 4)]:
        arr = _random_array(shape, dtype='complex128')
        arr_cpy = arr.copy()

        idft_scaling = np.prod(shape)
        true_idft = np.fft.ifftn(arr) * idft_scaling
        idft_arr = np.empty(shape, dtype='complex128')
        pyfftw_call(arr, idft_arr, direction='backward', halfcomplex=False,
                    planning=planning)

        assert all_almost_equal(arr, arr_cpy)  # Input perserved
        assert all_almost_equal(idft_arr, true_idft)
Exemple #6
0
def test_pyfftw_call_backward_with_axes(floating_dtype):
    if floating_dtype == np.dtype('float16'):  # not supported, skipping
        return

    halfcomplex, in_dtype = _params_from_dtype(floating_dtype)
    shape = (3, 4, 5)

    test_axes = [(0, 1), [1], (-1,), (1, 0), (-1, -2, -3)]
    for axes in test_axes:
        # Only the shape indexed by axes count for the scaling
        active_shape = np.take(shape, axes)
        idft_scaling = np.prod(active_shape)

        if halfcomplex:
            arr = _random_array(_halfcomplex_shape(shape, axes), in_dtype)
            true_idft = (np.fft.irfftn(arr, s=active_shape, axes=axes) *
                         idft_scaling)
        else:
            arr = _random_array(shape, in_dtype)
            true_idft = (np.fft.ifftn(arr, s=active_shape, axes=axes) *
                         idft_scaling)

        idft_arr = np.empty(shape, dtype=floating_dtype)
        pyfftw_call(arr, idft_arr, direction='backward', axes=axes,
                    halfcomplex=halfcomplex)

        assert all_almost_equal(idft_arr, true_idft)
Exemple #7
0
def test_pyfftw_call_threads():
    shape = (3, 4, 5)
    arr = _random_array(shape, dtype='complex64')
    true_dft = np.fft.fftn(arr)
    dft_arr = np.empty(shape, dtype='complex64')
    pyfftw_call(arr, dft_arr, direction='forward', preserve_input=False,
                threads=4)
    assert all_almost_equal(dft_arr, true_dft)

    shape = (1000,)  # Trigger cpu_count() as number of threads
    arr = _random_array(shape, dtype='complex64')
    true_dft = np.fft.fftn(arr)
    dft_arr = np.empty(shape, dtype='complex64')
    pyfftw_call(arr, dft_arr, direction='forward', preserve_input=False)

    assert all_almost_equal(dft_arr, true_dft)
Exemple #8
0
def test_reciprocal_grid_nd():

    grid = odl.uniform_grid([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)

    true_recip_stride = 2 * np.pi / (s * n)

    # Without shift altogether
    rgrid = reciprocal_grid(grid, shift=False, halfcomplex=False)

    assert all_equal(rgrid.shape, n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)
    assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #9
0
def test_reciprocal_grid_nd():

    grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)

    true_recip_stride = 2 * np.pi / (s * n)

    # Without shift altogether
    rgrid = reciprocal_grid(grid, shift=False, halfcomplex=False)

    assert all_equal(rgrid.shape, n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)
    assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #10
0
def test_pyfftw_call_forward_real_not_halfcomplex():
    # Test against Numpy's FFT
    for shape in [(10,), (3, 4, 5)]:
        arr = _random_array(shape, dtype='float64')

        true_dft = np.fft.fftn(arr)
        dft_arr = np.empty(shape, dtype='complex128')
        pyfftw_call(arr, dft_arr, direction='forward', halfcomplex=False)

        assert all_almost_equal(dft_arr, true_dft)
Exemple #11
0
def test_pyfftw_call_forward_with_plan():

    for shape in [(10,), (3, 4, 5)]:
        arr = _random_array(shape, dtype='complex128')
        arr_cpy = arr.copy()
        true_dft = np.fft.fftn(arr)

        # First run, create plan
        dft_arr = np.empty(shape, dtype='complex128')
        plan = pyfftw_call(arr, dft_arr, direction='forward',
                           halfcomplex=False, planning_effort='measure')

        # Second run, reuse with fresh output array
        dft_arr = np.empty(shape, dtype='complex128')
        pyfftw_call(arr, dft_arr, direction='forward', fftw_plan=plan,
                    halfcomplex=False)

        assert all_almost_equal(arr, arr_cpy)  # Input perserved
        assert all_almost_equal(dft_arr, true_dft)
Exemple #12
0
def test_reciprocal_grid_nd_shift_list():

    grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)
    shift = [False, True, False]

    true_recip_stride = 2 * np.pi / (s * n)

    # Shift only the even dimension, then zero must be contained
    rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=False)
    noshift = np.where(np.logical_not(shift))

    assert all_equal(rgrid.shape, n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)
    assert all_almost_equal(rgrid.min_pt[noshift], -rgrid.max_pt[noshift])
    assert all_almost_equal(rgrid[n // 2], [0] * 3)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #13
0
def test_reciprocal_grid_nd_shift_list():

    grid = odl.uniform_grid([0] * 3, [1] * 3, shape=(3, 4, 5))
    s = grid.stride
    n = np.array(grid.shape)
    shift = [False, True, False]

    true_recip_stride = 2 * np.pi / (s * n)

    # Shift only the even dimension, then zero must be contained
    rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=False)
    noshift = np.where(np.logical_not(shift))

    assert all_equal(rgrid.shape, n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)
    assert all_almost_equal(rgrid.min_pt[noshift], -rgrid.max_pt[noshift])
    assert all_almost_equal(rgrid[n // 2], [0] * 3)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #14
0
def test_pyfftw_call_backward_real_not_halfcomplex():
    # Test against Numpy's IFFT, no normalization
    for shape in [(10,), (3, 4, 5)]:
        # Scaling happens wrt output (large) shape
        idft_scaling = np.prod(shape)

        arr = _random_array(shape, dtype='float64')
        true_idft = np.fft.ifftn(arr) * idft_scaling
        idft_arr = np.empty(shape, dtype='complex128')
        pyfftw_call(arr, idft_arr, direction='backward', halfcomplex=False)

        assert all_almost_equal(idft_arr, true_idft)
Exemple #15
0
def test_dft_preprocess_data_halfcomplex(sign):

    shape = (2, 3, 4)

    # With shift
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * ((i + j + k) % 2))

    arr = np.ones(shape, dtype='float64')
    preproc = dft_preprocess_data(arr, shift=True, sign=sign)  # out-of-place
    out = np.empty_like(arr)
    dft_preprocess_data(arr, shift=True, out=out, sign=sign)  # in-place
    dft_preprocess_data(arr, shift=True, out=arr, sign=sign)  # in-place
    assert all_almost_equal(preproc.ravel(), correct_arr)
    assert all_almost_equal(arr.ravel(), correct_arr)
    assert all_almost_equal(out.ravel(), correct_arr)

    # Without shift
    imag = 1j if sign == '-' else -1j
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        argsum = sum((idx * (1 - 1 / shp))
                     for idx, shp in zip((i, j, k), shape))

        correct_arr.append(np.exp(imag * np.pi * argsum))

    arr = np.ones(shape, dtype='float64')
    preproc = dft_preprocess_data(arr, shift=False, sign=sign)
    assert all_almost_equal(preproc.ravel(), correct_arr)

    # Non-float input works, too
    arr = np.ones(shape, dtype='int')
    preproc = dft_preprocess_data(arr, shift=False, sign=sign)
    assert all_almost_equal(preproc.ravel(), correct_arr)

    # In-place modification not possible for float array and no shift
    arr = np.ones(shape, dtype='float64')
    with pytest.raises(ValueError):
        dft_preprocess_data(arr, shift=False, out=arr, sign=sign)
Exemple #16
0
def test_dft_preprocess_data_halfcomplex(sign):

    shape = (2, 3, 4)

    # With shift
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * ((i + j + k) % 2))

    arr = np.ones(shape, dtype='float64')
    preproc = dft_preprocess_data(arr, shift=True, sign=sign)  # out-of-place
    out = np.empty_like(arr)
    dft_preprocess_data(arr, shift=True, out=out, sign=sign)  # in-place
    dft_preprocess_data(arr, shift=True, out=arr, sign=sign)  # in-place
    assert all_almost_equal(preproc.ravel(), correct_arr)
    assert all_almost_equal(arr.ravel(), correct_arr)
    assert all_almost_equal(out.ravel(), correct_arr)

    # Without shift
    imag = 1j if sign == '-' else -1j
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        argsum = sum((idx * (1 - 1 / shp))
                     for idx, shp in zip((i, j, k), shape))

        correct_arr.append(np.exp(imag * np.pi * argsum))

    arr = np.ones(shape, dtype='float64')
    preproc = dft_preprocess_data(arr, shift=False, sign=sign)
    assert all_almost_equal(preproc.ravel(), correct_arr)

    # Non-float input works, too
    arr = np.ones(shape, dtype='int')
    preproc = dft_preprocess_data(arr, shift=False, sign=sign)
    assert all_almost_equal(preproc.ravel(), correct_arr)

    # In-place modification not possible for float array and no shift
    arr = np.ones(shape, dtype='float64')
    with pytest.raises(ValueError):
        dft_preprocess_data(arr, shift=False, out=arr, sign=sign)
Exemple #17
0
def test_reciprocal_grid_1d(halfcomplex, shift, parity):

    shape = 10 if parity == 'even' else 11
    grid = odl.uniform_grid(0, 1, shape=shape)
    s = grid.stride
    n = np.array(grid.shape)

    rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=halfcomplex)

    # Independent of halfcomplex, shift and parity
    true_recip_stride = 2 * np.pi / (s * n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)

    if halfcomplex:
        assert all_equal(rgrid.shape, n // 2 + 1)

        if parity == 'odd' and shift:
            # Max point should be half a negative recip stride
            assert all_almost_equal(rgrid.max_pt, -true_recip_stride / 2)
        elif parity == 'even' and not shift:
            # Max point should be half a positive recip stride
            assert all_almost_equal(rgrid.max_pt, true_recip_stride / 2)
        elif (parity == 'odd' and not shift) or (parity == 'even' and shift):
            # Max should be zero
            assert all_almost_equal(rgrid.max_pt, 0)
        else:
            raise RuntimeError('parameter combination not covered')
    else:  # halfcomplex = False
        assert all_equal(rgrid.shape, n)

        if (parity == 'even' and shift) or (parity == 'odd' and not shift):
            # Zero should be at index n // 2
            assert all_almost_equal(rgrid[n // 2], 0)
        elif (parity == 'odd' and shift) or (parity == 'even' and not shift):
            # No point should be closer to 0 than half a recip stride
            atol = 0.999 * true_recip_stride / 2
            assert not rgrid.approx_contains(0, atol=atol)
        else:
            raise RuntimeError('parameter combination not covered')

        if not shift:
            # Grid Should be symmetric
            assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt)
            if parity == 'odd':
                # Midpoint should be 0
                assert all_almost_equal(rgrid.mid_pt, 0)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid,
                            grid.min_pt,
                            halfcomplex=halfcomplex,
                            halfcx_parity=parity)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #18
0
def test_dft_preprocess_data_with_axes(sign):

    shape = (2, 3, 4)

    axes = 1  # Only middle index counts
    correct_arr = []
    for _, j, __ in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * (j % 2))

    arr = np.ones(shape, dtype='complex64')
    dft_preprocess_data(arr, shift=True, axes=axes, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)

    axes = [0, -1]  # First and last
    correct_arr = []
    for i, _, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * ((i + k) % 2))

    arr = np.ones(shape, dtype='complex64')
    dft_preprocess_data(arr, shift=True, axes=axes, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)
Exemple #19
0
def test_dft_preprocess_data_with_axes(sign):

    shape = (2, 3, 4)

    axes = 1  # Only middle index counts
    correct_arr = []
    for _, j, __ in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * (j % 2))

    arr = np.ones(shape, dtype='complex64')
    dft_preprocess_data(arr, shift=True, axes=axes, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)

    axes = [0, -1]  # First and last
    correct_arr = []
    for i, _, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append(1 - 2 * ((i + k) % 2))

    arr = np.ones(shape, dtype='complex64')
    dft_preprocess_data(arr, shift=True, axes=axes, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)
Exemple #20
0
def test_dft_preprocess_data(sign):

    shape = (2, 3, 4)

    # With shift
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append((1 + 1j) * (1 - 2 * ((i + j + k) % 2)))

    arr = np.ones(shape, dtype='complex64') * (1 + 1j)
    preproc = dft_preprocess_data(arr, shift=True, sign=sign)  # out-of-place
    dft_preprocess_data(arr, shift=True, out=arr, sign=sign)  # in-place

    assert all_almost_equal(preproc.ravel(), correct_arr)
    assert all_almost_equal(arr.ravel(), correct_arr)

    # Without shift
    imag = 1j if sign == '-' else -1j
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        argsum = sum((idx * (1 - 1 / shp))
                     for idx, shp in zip((i, j, k), shape))

        correct_arr.append((1 + 1j) * np.exp(imag * np.pi * argsum))

    arr = np.ones(shape, dtype='complex64') * (1 + 1j)
    dft_preprocess_data(arr, shift=False, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)

    # Bad input
    with pytest.raises(ValueError):
        dft_preprocess_data(arr, out=arr, sign=1)

    arr = np.zeros(shape, dtype='S2')
    with pytest.raises(ValueError):
        dft_preprocess_data(arr)
Exemple #21
0
def test_dft_preprocess_data(sign):

    shape = (2, 3, 4)

    # With shift
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        correct_arr.append((1 + 1j) * (1 - 2 * ((i + j + k) % 2)))

    arr = np.ones(shape, dtype='complex64') * (1 + 1j)
    preproc = dft_preprocess_data(arr, shift=True, sign=sign)  # out-of-place
    dft_preprocess_data(arr, shift=True, out=arr, sign=sign)  # in-place

    assert all_almost_equal(preproc.ravel(), correct_arr)
    assert all_almost_equal(arr.ravel(), correct_arr)

    # Without shift
    imag = 1j if sign == '-' else -1j
    correct_arr = []
    for i, j, k in product(range(shape[0]), range(shape[1]), range(shape[2])):
        argsum = sum((idx * (1 - 1 / shp))
                     for idx, shp in zip((i, j, k), shape))

        correct_arr.append((1 + 1j) * np.exp(imag * np.pi * argsum))

    arr = np.ones(shape, dtype='complex64') * (1 + 1j)
    dft_preprocess_data(arr, shift=False, out=arr, sign=sign)

    assert all_almost_equal(arr.ravel(), correct_arr)

    # Bad input
    with pytest.raises(ValueError):
        dft_preprocess_data(arr, out=arr, sign=1)

    arr = np.zeros(shape, dtype='S2')
    with pytest.raises(ValueError):
        dft_preprocess_data(arr)
Exemple #22
0
def test_fourier_trafo_inverse(impl, sign):
    # Test if the inverse really is the inverse

    def char_interval(x):
        return (x >= 0) & (x <= 1)

    # Complex-to-complex
    discr = odl.uniform_discr(-2, 2, 40, impl='numpy', dtype='complex64')
    discr_char = discr.element(char_interval)

    ft = FourierTransform(discr, sign=sign, impl=impl)
    assert all_almost_equal(ft.inverse(ft(char_interval)), discr_char)
    assert all_almost_equal(ft.adjoint(ft(char_interval)), discr_char)

    # Half-complex
    discr = odl.uniform_discr(-2, 2, 40, impl='numpy', dtype='float32')
    ft = FourierTransform(discr, impl=impl, halfcomplex=True)
    assert all_almost_equal(ft.inverse(ft(char_interval)), discr_char)

    def char_rect(x):
        return (x[0] >= 0) & (x[0] <= 1) & (x[1] >= 0) & (x[1] <= 1)

    # 2D with axes, C2C
    discr = odl.uniform_discr([-2, -2], [2, 2], (20, 10),
                              impl='numpy',
                              dtype='complex64')
    discr_rect = discr.element(char_rect)

    for axes in [(0, ), 1]:
        ft = FourierTransform(discr, sign=sign, impl=impl, axes=axes)
        assert all_almost_equal(ft.inverse(ft(char_rect)), discr_rect)
        assert all_almost_equal(ft.adjoint(ft(char_rect)), discr_rect)

    # 2D with axes, halfcomplex
    discr = odl.uniform_discr([-2, -2], [2, 2], (20, 10),
                              impl='numpy',
                              dtype='float32')
    discr_rect = discr.element(char_rect)

    for halfcomplex in [False, True]:
        if halfcomplex and sign == '+':
            continue  # cannot mix halfcomplex with sign

        for axes in [(0, ), (1, )]:
            ft = FourierTransform(discr,
                                  sign=sign,
                                  impl=impl,
                                  axes=axes,
                                  halfcomplex=halfcomplex)
            assert all_almost_equal(ft.inverse(ft(char_rect)), discr_rect)
            assert all_almost_equal(ft.adjoint(ft(char_rect)), discr_rect)
Exemple #23
0
def test_reciprocal_grid_1d(halfcomplex, shift, parity):

    shape = 10 if parity == 'even' else 11
    grid = odl.uniform_sampling(0, 1, shape=shape)
    s = grid.stride
    n = np.array(grid.shape)

    rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=halfcomplex)

    # Independent of halfcomplex, shift and parity
    true_recip_stride = 2 * np.pi / (s * n)
    assert all_almost_equal(rgrid.stride, true_recip_stride)

    if halfcomplex:
        assert all_equal(rgrid.shape, n // 2 + 1)

        if parity == 'odd' and shift:
            # Max point should be half a negative recip stride
            assert all_almost_equal(rgrid.max_pt, -true_recip_stride / 2)
        elif parity == 'even' and not shift:
            # Max point should be half a positive recip stride
            assert all_almost_equal(rgrid.max_pt, true_recip_stride / 2)
        elif (parity == 'odd' and not shift) or (parity == 'even' and shift):
            # Max should be zero
            assert all_almost_equal(rgrid.max_pt, 0)
        else:
            raise RuntimeError('parameter combination not covered')
    else:  # halfcomplex = False
        assert all_equal(rgrid.shape, n)

        if (parity == 'even' and shift) or (parity == 'odd' and not shift):
            # Zero should be at index n // 2
            assert all_almost_equal(rgrid[n // 2], 0)
        elif (parity == 'odd' and shift) or (parity == 'even' and not shift):
            # No point should be closer to 0 than half a recip stride
            atol = 0.999 * true_recip_stride / 2
            assert not rgrid.approx_contains(0, atol=atol)
        else:
            raise RuntimeError('parameter combination not covered')

        if not shift:
            # Grid Should be symmetric
            assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt)
            if parity == 'odd':
                # Midpoint should be 0
                assert all_almost_equal(rgrid.mid_pt, 0)

    # Inverting should give back the original
    irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=halfcomplex,
                            halfcx_parity=parity)
    assert irgrid.approx_equals(grid, atol=1e-6)
Exemple #24
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)
Exemple #25
0
def test_fourier_trafo_inverse(impl, sign):
    # Test if the inverse really is the inverse

    def char_interval(x):
        return (x >= 0) & (x <= 1)

    # Complex-to-complex
    discr = odl.uniform_discr(-2, 2, 40, impl="numpy", dtype="complex64")
    discr_char = discr.element(char_interval)

    ft = FourierTransform(discr, sign=sign, impl=impl)
    assert all_almost_equal(ft.inverse(ft(char_interval)), discr_char)
    assert all_almost_equal(ft.adjoint(ft(char_interval)), discr_char)

    # Half-complex
    discr = odl.uniform_discr(-2, 2, 40, impl="numpy", dtype="float32")
    ft = FourierTransform(discr, impl=impl, halfcomplex=True)
    assert all_almost_equal(ft.inverse(ft(char_interval)), discr_char)

    def char_rect(x):
        return (x[0] >= 0) & (x[0] <= 1) & (x[1] >= 0) & (x[1] <= 1)

    # 2D with axes, C2C
    discr = odl.uniform_discr([-2, -2], [2, 2], (20, 10), impl="numpy", dtype="complex64")
    discr_rect = discr.element(char_rect)

    for axes in [(0,), 1]:
        ft = FourierTransform(discr, sign=sign, impl=impl, axes=axes)
        assert all_almost_equal(ft.inverse(ft(char_rect)), discr_rect)
        assert all_almost_equal(ft.adjoint(ft(char_rect)), discr_rect)

    # 2D with axes, halfcomplex
    discr = odl.uniform_discr([-2, -2], [2, 2], (20, 10), impl="numpy", dtype="float32")
    discr_rect = discr.element(char_rect)

    for halfcomplex in [False, True]:
        if halfcomplex and sign == "+":
            continue  # cannot mix halfcomplex with sign

        for axes in [(0,), (1,)]:
            ft = FourierTransform(discr, sign=sign, impl=impl, axes=axes, halfcomplex=halfcomplex)
            assert all_almost_equal(ft.inverse(ft(char_rect)), discr_rect)
            assert all_almost_equal(ft.adjoint(ft(char_rect)), discr_rect)
Exemple #26
0
def test_pyfftw_call_forward(floating_dtype):
    # Test against Numpy's FFT
    if floating_dtype == np.dtype('float16'):  # not supported, skipping
        return

    halfcomplex, out_dtype = _params_from_dtype(floating_dtype)

    for shape in [(10,), (3, 4, 5)]:
        arr = _random_array(shape, floating_dtype)

        if halfcomplex:
            true_dft = np.fft.rfftn(arr)
            dft_arr = np.empty(_halfcomplex_shape(shape), dtype=out_dtype)
        else:
            true_dft = np.fft.fftn(arr)
            dft_arr = np.empty(shape, dtype=out_dtype)

        pyfftw_call(arr, dft_arr, direction='forward',
                    halfcomplex=halfcomplex, preserve_input=False)

        assert all_almost_equal(dft_arr, true_dft)
Exemple #27
0
def test_pyfftw_call_forward_with_axes(floating_dtype):
    if floating_dtype == np.dtype('float16'):  # not supported, skipping
        return

    halfcomplex, out_dtype = _params_from_dtype(floating_dtype)
    shape = (3, 4, 5)

    test_axes = [(0, 1), [1], (-1,), (1, 0), (-1, -2, -3)]
    for axes in test_axes:
        arr = _random_array(shape, floating_dtype)
        if halfcomplex:
            true_dft = np.fft.rfftn(arr, axes=axes)
            dft_arr = np.empty(_halfcomplex_shape(shape, axes),
                               dtype=out_dtype)
        else:
            true_dft = np.fft.fftn(arr, axes=axes)
            dft_arr = np.empty(shape, dtype=out_dtype)

        pyfftw_call(arr, dft_arr, direction='forward', axes=axes,
                    halfcomplex=halfcomplex)

        assert all_almost_equal(dft_arr, true_dft)
Exemple #28
0
def test_pyfftw_call_backward(floating_dtype):
    # Test against Numpy's IFFT, no normalization
    if floating_dtype == np.dtype('float16'):  # not supported, skipping
        return

    halfcomplex, in_dtype = _params_from_dtype(floating_dtype)

    for shape in [(10,), (3, 4, 5)]:
        # Scaling happens wrt output (large) shape
        idft_scaling = np.prod(shape)

        if halfcomplex:
            arr = _random_array(_halfcomplex_shape(shape), in_dtype)
            true_idft = np.fft.irfftn(arr, shape) * idft_scaling
        else:
            arr = _random_array(shape, in_dtype)
            true_idft = np.fft.ifftn(arr) * idft_scaling

        idft_arr = np.empty(shape, dtype=floating_dtype)
        pyfftw_call(arr, idft_arr, direction='backward',
                    halfcomplex=halfcomplex)

        assert all_almost_equal(idft_arr, true_idft)
Exemple #29
0
def test_theano_gradient():
    """Test the gradient of ODL functionals wrapped as Theano Ops."""
    # Define ODL operator
    matrix = np.random.rand(3, 2)
    odl_op = odl.MatrixOperator(matrix)

    # Define evaluation point
    x = [1., 2.]

    # Define ODL cost and the composed functional
    odl_cost = odl.solvers.L2NormSquared(odl_op.range)
    odl_functional = odl_cost * odl_op

    # Create Theano placeholder
    x_theano = T.dvector()

    # Create Theano layers from odl operators
    odl_op_layer = odl.contrib.theano.TheanoOperator(odl_op)
    odl_cost_layer = odl.contrib.theano.TheanoOperator(odl_cost)

    # Build computation graph
    y_theano = odl_op_layer(x_theano)
    cost_theano = odl_cost_layer(y_theano)
    cost_theano_func = theano.function([x_theano], cost_theano)
    cost_grad_theano = T.grad(cost_theano, x_theano)
    cost_grad_theano_func = theano.function([x_theano], cost_grad_theano)

    # Evaluate using Theano
    result = cost_theano_func(x)
    expected = odl_functional(x)
    assert result == pytest.approx(expected)

    # Evaluate the gradient of the cost, should be 2 * matrix^T.dot(x)
    result = cost_grad_theano_func(x)
    expected = odl_functional.gradient(x)
    assert all_almost_equal(result, expected)
Exemple #30
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)