Example #1
0
def test_factory_dtypes(fn_impl):
    real_float_dtypes = [np.float32, np.float64]
    nonfloat_dtypes = [np.int8, np.int16, np.int32, np.int64,
                       np.uint8, np.uint16, np.uint32, np.uint64]
    complex_float_dtypes = [np.complex64, np.complex128]

    for dtype in real_float_dtypes:
        try:
            discr = odl.uniform_discr(0, 1, 10, impl=fn_impl, dtype=dtype)
            assert isinstance(discr.dspace, FnBase)
            assert discr.dspace.impl == fn_impl
            assert discr.is_rn
        except TypeError:
            continue

    for dtype in nonfloat_dtypes:
        try:
            discr = odl.uniform_discr(0, 1, 10, impl=fn_impl, dtype=dtype)
            assert isinstance(discr.dspace, FnBase)
            assert discr.dspace.impl == fn_impl
            assert discr.dspace.element().space.dtype == dtype
        except TypeError:
            continue

    for dtype in complex_float_dtypes:
        try:
            discr = odl.uniform_discr(0, 1, 10, impl=fn_impl, dtype=dtype)
            assert isinstance(discr.dspace, FnBase)
            assert discr.dspace.impl == fn_impl
            assert discr.is_cn
            assert discr.dspace.element().space.dtype == dtype
        except TypeError:
            continue
Example #2
0
def test_element_from_array_2d():
    # assert orderings work properly with 2d
    discr = odl.uniform_discr([0, 0], [1, 1], [2, 2], impl='numpy', order='C')
    vec = discr.element([[1, 2],
                         [3, 4]])

    assert isinstance(vec, odl.DiscreteLpVector)
    assert isinstance(vec.ntuple, odl.FnVector)

    # Check ordering
    assert all_equal(vec.ntuple, [1, 2, 3, 4])

    # Linear creation works as well
    linear_vec = discr.element([1, 2, 3, 4])
    assert all_equal(vec.ntuple, [1, 2, 3, 4])

    # Fortran order
    discr = odl.uniform_discr([0, 0], [1, 1], (2, 2), impl='numpy', order='F')
    vec = discr.element([[1, 2],
                         [3, 4]])

    # Check ordering
    assert all_equal(vec.ntuple, [1, 3, 2, 4])

    # Linear creation works aswell
    linear_vec = discr.element([1, 2, 3, 4])
    assert all_equal(linear_vec.ntuple, [1, 2, 3, 4])
Example #3
0
def test_resizing_op_call(fn_impl):

    dtypes = [dt for dt in odl.FN_IMPLS[fn_impl].available_dtypes()
              if is_scalar_dtype(dt)]

    for dtype in dtypes:
        # Minimal test since this operator only wraps resize_array
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=fn_impl)
        res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2),
                                      impl=fn_impl)
        res_op = odl.ResizingOperator(space, res_space)
        out = res_op(space.one())
        true_res = np.zeros((8, 2))
        true_res[:4, :] = 1
        assert np.array_equal(out, true_res)

        out = res_space.element()
        res_op(space.one(), out=out)
        assert np.array_equal(out, true_res)

        # Test also mapping to default impl for other 'fn_impl'
        if fn_impl != 'numpy':
            space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=fn_impl)
            res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2))
            res_op = odl.ResizingOperator(space, res_space)
            out = res_op(space.one())
            true_res = np.zeros((8, 2))
            true_res[:4, :] = 1
            assert np.array_equal(out, true_res)

            out = res_space.element()
            res_op(space.one(), out=out)
            assert np.array_equal(out, true_res)
Example #4
0
def test_element_from_array_2d():
    # assert orderings work properly with 2d
    square_space = odl.FunctionSpace(odl.Rectangle([0, 0], [1, 1]))
    discr = odl.uniform_discr(square_space, (2, 2), impl='numpy', order='C')
    vec = discr.element([[1, 2],
                         [3, 4]])

    assert isinstance(vec, discr.Vector)
    assert isinstance(vec.ntuple, odl.Rn.Vector)

    # Check ordering
    assert all_equal(vec.ntuple, [1, 2, 3, 4])

    # Linear creation works as well
    linear_vec = discr.element([1, 2, 3, 4])
    assert all_equal(vec.ntuple, [1, 2, 3, 4])

    # Fortran order
    discr = odl.uniform_discr(square_space, (2, 2), impl='numpy', order='F')
    vec = discr.element([[1, 2],
                         [3, 4]])

    # Check ordering
    assert all_equal(vec.ntuple, [1, 3, 2, 4])

    # Linear creation works aswell
    linear_vec = discr.element([1, 2, 3, 4])
    assert all_equal(linear_vec.ntuple, [1, 2, 3, 4])
Example #5
0
def test_fixed_disp_init():
    """Verify that the init method and checks work properly."""
    space = odl.uniform_discr(0, 1, 5)
    disp_field = space.tangent_bundle.element(
        disp_field_factory(space.ndim))

    # Valid input
    print(LinDeformFixedDisp(disp_field))
    print(LinDeformFixedDisp(disp_field, templ_space=space))

    # Non-valid input
    with pytest.raises(TypeError):  # displacement not ProductSpaceElement
        LinDeformFixedDisp(space.one())
    with pytest.raises(TypeError):  # templ_space not DiscreteLp
        LinDeformFixedDisp(disp_field, space.tangent_bundle)
    with pytest.raises(TypeError):  # templ_space not a power space
        bad_pspace = odl.ProductSpace(space, odl.rn(3))
        LinDeformFixedDisp(disp_field, bad_pspace)
    with pytest.raises(TypeError):  # templ_space not based on DiscreteLp
        bad_pspace = odl.ProductSpace(odl.rn(2), 1)
        LinDeformFixedDisp(disp_field, bad_pspace)
    with pytest.raises(TypeError):  # wrong dtype on templ_space
        wrong_dtype = odl.ProductSpace(space.astype(complex), 1)
        LinDeformFixedDisp(disp_field, wrong_dtype)
    with pytest.raises(ValueError):  # vector field spaces don't match
        bad_space = odl.uniform_discr(0, 1, 10)
        LinDeformFixedDisp(disp_field, bad_space)
Example #6
0
def test_fourier_trafo_charfun_1d():
    # Characteristic function of [0, 1], its Fourier transform is
    # given by exp(-1j * y / 2) * sinc(y/2)
    def char_interval(x):
        return (x >= 0) & (x <= 1)

    def char_interval_ft(x):
        return np.exp(-1j * x / 2) * sinc(x / 2) / np.sqrt(2 * np.pi)

    # Base version
    discr = odl.uniform_discr(-2, 2, 40, impl="numpy")
    dft_base = FourierTransform(discr)

    # Complex version, should be as good
    discr = odl.uniform_discr(-2, 2, 40, impl="numpy", dtype="complex64")
    dft_complex = FourierTransform(discr)

    # Without shift
    discr = odl.uniform_discr(-2, 2, 40, impl="numpy", dtype="complex64")
    dft_complex_shift = FourierTransform(discr, shift=False)

    for dft in [dft_base, dft_complex, dft_complex_shift]:
        func_true_ft = dft.range.element(char_interval_ft)
        func_dft = dft(char_interval)
        assert (func_dft - func_true_ft).norm() < 5e-6
Example #7
0
def test_gradient(method, impl, padding):
    """Discretized spatial gradient operator."""

    with pytest.raises(TypeError):
        Gradient(odl.Rn(1), method=method)

    if isinstance(padding, tuple):
        padding_method, padding_value = padding
    else:
        padding_method, padding_value = padding, None

    # DiscreteLp Vector
    discr_space = odl.uniform_discr([0, 0], [1, 1], DATA_2D.shape, impl=impl)
    dom_vec = discr_space.element(DATA_2D)

    # computation of gradient components with helper function
    dx0, dx1 = discr_space.cell_sides
    diff_0 = finite_diff(DATA_2D, axis=0, dx=dx0, method=method,
                         padding_method=padding_method,
                         padding_value=padding_value)
    diff_1 = finite_diff(DATA_2D, axis=1, dx=dx1, method=method,
                         padding_method=padding_method,
                         padding_value=padding_value)

    # gradient
    grad = Gradient(discr_space, method=method,
                    padding_method=padding_method,
                    padding_value=padding_value)
    grad_vec = grad(dom_vec)
    assert len(grad_vec) == DATA_2D.ndim
    assert all_almost_equal(grad_vec[0].asarray(), diff_0)
    assert all_almost_equal(grad_vec[1].asarray(), diff_1)

    # Test adjoint operator
    derivative = grad.derivative()
    ran_vec = derivative.range.element([DATA_2D, DATA_2D ** 2])
    deriv_grad_vec = derivative(dom_vec)
    adj_grad_vec = derivative.adjoint(ran_vec)
    lhs = ran_vec.inner(deriv_grad_vec)
    rhs = dom_vec.inner(adj_grad_vec)
    # Check not to use trivial data
    assert lhs != 0
    assert rhs != 0
    assert almost_equal(lhs, rhs)

    # higher dimensional arrays
    lin_size = 3
    for ndim in [1, 3, 6]:

        # DiscreteLp Vector
        space = odl.uniform_discr([0.] * ndim, [1.] * ndim, [lin_size] * ndim)
        dom_vec = odl.phantom.cuboid(space, [0.2] * ndim, [0.8] * ndim)

        # gradient
        grad = Gradient(space, method=method,
                        padding_method=padding_method,
                        padding_value=padding_value)
        grad(dom_vec)
Example #8
0
def test_reductions():
    spaces = [odl.uniform_discr([0, 0], [1, 1], [2, 2])]

    if odl.CUDA_AVAILABLE:
        spaces += [odl.uniform_discr([0, 0], [1, 1], [2, 2], impl='cuda')]

    for fn in spaces:
        for name, _ in odl.util.ufuncs.REDUCTIONS:
            yield _impl_test_reduction, fn, name
Example #9
0
def test_factory_cuda(exponent):
    discr = odl.uniform_discr(0, 1, 10, impl='cuda', exponent=exponent)
    assert isinstance(discr.dspace, odl.CudaFn)
    assert discr.is_rn
    assert discr.dspace.exponent == exponent
    assert discr.dtype == odl.CudaFn.default_dtype(odl.RealNumbers())

    # Cuda currently does not support complex numbers, check error
    with pytest.raises(NotImplementedError):
        odl.uniform_discr(0, 1, 10, impl='cuda', dtype='complex')
Example #10
0
def test_factory_cuda(exponent):
    space = odl.FunctionSpace(odl.Interval(0, 1))
    discr = odl.uniform_discr(space, 10, impl='cuda', exponent=exponent)
    assert isinstance(discr.dspace, odl.CudaRn)
    assert discr.dspace.exponent == exponent

    # Cuda currently does not support complex numbers, check error
    space = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers())
    with pytest.raises(NotImplementedError):
        odl.uniform_discr(space, 10, impl='cuda')
Example #11
0
def fn(fn_impl, request):
    spc = request.param

    if spc == 'rn':
        return odl.rn(10 ** 5, impl=fn_impl)
    elif spc == '1d':
        return odl.uniform_discr(0, 1, 10 ** 5, impl=fn_impl)
    elif spc == '3d':
        return odl.uniform_discr([0, 0, 0], [1, 1, 1],
                                 [100, 100, 100], impl=fn_impl)
Example #12
0
def test_getslice():
    discr = odl.uniform_discr(0, 1, 3)
    vec = discr.element([1, 2, 3])

    assert isinstance(vec[:], odl.FnVector)
    assert all_equal(vec[:], [1, 2, 3])

    discr = odl.uniform_discr(0, 1, 3, field=odl.ComplexNumbers())
    vec = discr.element([1 + 2j, 2 - 2j, 3])

    assert isinstance(vec[:], odl.FnVector)
    assert all_equal(vec[:], [1 + 2j, 2 - 2j, 3])
Example #13
0
def test_getslice():
    discr = odl.uniform_discr(0, 1, 3)
    elem = discr.element([1, 2, 3])

    assert isinstance(elem[:], odl.NumpyFnVector)
    assert all_equal(elem[:], [1, 2, 3])

    discr = odl.uniform_discr(0, 1, 3, dtype='complex')
    elem = discr.element([1 + 2j, 2 - 2j, 3])

    assert isinstance(elem[:], odl.NumpyFnVector)
    assert all_equal(elem[:], [1 + 2j, 2 - 2j, 3])
Example #14
0
def test_divergence_cpu():
    """Discretized spatial divergence operator."""

    # Invalid space
    with pytest.raises(TypeError):
        Divergence(range=odl.Rn(1))

    # DiscreteLp
    # space = odl.uniform_discr([0, 0], [6, 2.5], DATA.shape)
    space = odl.uniform_discr([0, 0], [3, 5], DATA_2D.shape)

    # Operator instance
    div = Divergence(range=space, method='forward')

    # Apply operator
    # dom_vec = div.domain.element([DATA / 2, DATA ** 3])
    dom_vec = div.domain.element([DATA_2D, DATA_2D])
    div_dom_vec = div(dom_vec)

    # computation of divergence with helper function
    dx0, dx1 = space.cell_sides
    diff_0 = finite_diff(dom_vec[0].asarray(), axis=0, dx=dx0,
                         padding_method='constant')
    diff_1 = finite_diff(dom_vec[1].asarray(), axis=1, dx=dx1,
                         padding_method='constant')

    assert all_equal(diff_0 + diff_1, div_dom_vec.asarray())

    # Adjoint operator
    adj_div = div.adjoint
    ran_vec = div.range.element(DATA_2D ** 2)
    adj_div_ran_vec = adj_div(ran_vec)

    # Adjoint condition
    lhs = ran_vec.inner(div_dom_vec)
    rhs = dom_vec.inner(adj_div_ran_vec)
    # Check not to use trivial data
    assert lhs != 0
    assert rhs != 0
    assert almost_equal(lhs, rhs)

    # Higher dimensional arrays
    for ndim in range(1, 6):
        # DiscreteLp Vector
        lin_size = 3
        space = odl.uniform_discr([0.] * ndim, [lin_size] * ndim,
                                  [lin_size] * ndim)

        # Divergence
        div = Divergence(range=space)
        dom_vec = div.domain.element([ndvolume(lin_size, ndim)] * ndim)
        div(dom_vec)
Example #15
0
def test_equals_space(exponent, fn_impl):
    x1 = odl.uniform_discr(0, 1, 3, exponent=exponent, impl=fn_impl)
    x2 = odl.uniform_discr(0, 1, 3, exponent=exponent, impl=fn_impl)
    y = odl.uniform_discr(0, 1, 4, exponent=exponent, impl=fn_impl)

    assert x1 is x1
    assert x1 is not x2
    assert x1 is not y
    assert x1 == x1
    assert x1 == x2
    assert x1 != y
    assert hash(x1) == hash(x2)
    assert hash(x1) != hash(y)
Example #16
0
def test_factory(exponent):
    space = odl.FunctionSpace(odl.Interval(0, 1))
    discr = odl.uniform_discr(space, 10, impl='numpy', exponent=exponent)

    assert isinstance(discr.dspace, odl.Rn)
    assert discr.dspace.exponent == exponent

    # Complex
    space = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers())
    discr = odl.uniform_discr(space, 10, impl='numpy', exponent=exponent)

    assert isinstance(discr.dspace, odl.Cn)
    assert discr.dspace.exponent == exponent
Example #17
0
def fn(request):
    spc, impl = request.param.split()

    if spc == 'rn':
        if impl == 'numpy':
            return odl.Rn(10 ** 5)
        elif impl == 'cuda':
            return odl.CudaRn(10 ** 5)
    elif spc == '1d':
        return odl.uniform_discr(0, 1, 10 ** 5, impl=impl)
    elif spc == '3d':
        return odl.uniform_discr([0, 0, 0], [1, 1, 1],
                                 [100, 100, 100], impl=impl)
Example #18
0
def fn(request):
    spc, impl, dtype = request.param.split()

    if spc == 'fn':
        if impl == 'numpy':
            return odl.Fn(10 ** 5, dtype=dtype)
        elif impl == 'cuda':
            return odl.CudaFn(10 ** 5, dtype=dtype)
    elif spc == '1d':
        return odl.uniform_discr(0, 1, 10 ** 5, impl=impl, dtype=dtype)
    elif spc == '3d':
        return odl.uniform_discr([0, 0, 0], [1, 1, 1],
                                 [100, 100, 100], impl=impl, dtype=dtype)
Example #19
0
def test_pointwise_norm_init_properties():
    # 1d
    fspace = odl.uniform_discr([0, 0], [1, 1], (2, 2))
    vfspace = ProductSpace(fspace, 1, exponent=1)

    # Make sure the code runs and test the properties
    pwnorm = PointwiseNorm(vfspace)
    assert pwnorm.base_space == fspace
    assert all_equal(pwnorm.weights, [1])
    assert not pwnorm.is_weighted
    assert pwnorm.exponent == 1.0
    repr(pwnorm)

    pwnorm = PointwiseNorm(vfspace, exponent=2)
    assert pwnorm.exponent == 2

    pwnorm = PointwiseNorm(vfspace, weighting=2)
    assert all_equal(pwnorm.weights, [2])
    assert pwnorm.is_weighted

    # 3d
    fspace = odl.uniform_discr([0, 0], [1, 1], (2, 2))
    vfspace = ProductSpace(fspace, 3, exponent=1)

    # Make sure the code runs and test the properties
    pwnorm = PointwiseNorm(vfspace)
    assert pwnorm.base_space == fspace
    assert all_equal(pwnorm.weights, [1, 1, 1])
    assert not pwnorm.is_weighted
    assert pwnorm.exponent == 1.0
    repr(pwnorm)

    pwnorm = PointwiseNorm(vfspace, exponent=2)
    assert pwnorm.exponent == 2

    pwnorm = PointwiseNorm(vfspace, weighting=[1, 2, 3])
    assert all_equal(pwnorm.weights, [1, 2, 3])
    assert pwnorm.is_weighted

    # Bad input
    with pytest.raises(TypeError):
        PointwiseNorm(odl.rn(3))  # No power space

    with pytest.raises(ValueError):
        PointwiseNorm(vfspace, exponent=0.5)  # < 1 not allowed

    with pytest.raises(ValueError):
        PointwiseNorm(vfspace, weighting=-1)  # < 0 not allowed

    with pytest.raises(ValueError):
        PointwiseNorm(vfspace, weighting=[1, 0, 1])  # 0 invalid
Example #20
0
def test_getslice():
    discr = odl.uniform_discr(odl.FunctionSpace(odl.Interval(0, 1)), 3)
    vec = discr.element([1, 2, 3])

    assert isinstance(vec[:], odl.Rn.Vector)
    assert all_equal(vec[:], [1, 2, 3])

    discr = odl.uniform_discr(
        odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()),
        3)
    vec = discr.element([1 + 2j, 2 - 2j, 3])

    assert isinstance(vec[:], odl.Cn.Vector)
    assert all_equal(vec[:], [1 + 2j, 2 - 2j, 3])
Example #21
0
def test_cell_sides():
    # Non-degenerated case, should be same as cell size
    discr = odl.uniform_discr([0, 0], [1, 1], [2, 2])
    elem = discr.element()

    assert all_equal(discr.cell_sides, [0.5] * 2)
    assert all_equal(elem.cell_sides, [0.5] * 2)

    # Degenerated case, uses interval size in 1-point dimensions
    discr = odl.uniform_discr([0, 0], [1, 1], [2, 1])
    elem = discr.element()

    assert all_equal(discr.cell_sides, [0.5, 1])
    assert all_equal(elem.cell_sides, [0.5, 1])
Example #22
0
def test_cell_volume():
    # Non-degenerated case
    discr = odl.uniform_discr([0, 0], [1, 1], [2, 2])
    elem = discr.element()

    assert discr.cell_volume == 0.25
    assert elem.cell_volume == 0.25

    # Degenerated case, uses interval size in 1-point dimensions
    discr = odl.uniform_discr([0, 0], [1, 1], [2, 1])
    elem = discr.element()

    assert discr.cell_volume == 0.5
    assert elem.cell_volume == 0.5
Example #23
0
def test_real_imag():

    # Get real and imag
    cdiscr = odl.uniform_discr([0, 0], [1, 1], [2, 2], dtype=complex)
    rdiscr = odl.uniform_discr([0, 0], [1, 1], [2, 2], dtype=float)

    x = cdiscr.element([[1 - 1j, 2 - 2j], [3 - 3j, 4 - 4j]])
    assert x.real in rdiscr
    assert all_equal(x.real, [1, 2, 3, 4])
    assert x.imag in rdiscr
    assert all_equal(x.imag, [-1, -2, -3, -4])

    # Set with different data types and shapes
    newreal = rdiscr.element([[2, 3], [4, 5]])
    x.real = newreal
    assert all_equal(x.real, [2, 3, 4, 5])
    newreal = [[3, 4], [5, 6]]
    x.real = newreal
    assert all_equal(x.real, [3, 4, 5, 6])
    newreal = [4, 5, 6, 7]
    x.real = newreal
    assert all_equal(x.real, [4, 5, 6, 7])
    newreal = 0
    x.real = newreal
    assert all_equal(x.real, [0, 0, 0, 0])

    newimag = rdiscr.element([-2, -3, -4, -5])
    x.imag = newimag
    assert all_equal(x.imag, [-2, -3, -4, -5])
    newimag = [[-3, -4], [-5, -6]]
    x.imag = newimag
    assert all_equal(x.imag, [-3, -4, -5, -6])
    newimag = [-4, -5, -6, -7]
    x.imag = newimag
    assert all_equal(x.imag, [-4, -5, -6, -7])
    newimag = -1
    x.imag = newimag
    assert all_equal(x.imag, [-1, -1, -1, -1])

    # 'F' ordering
    cdiscr = odl.uniform_discr([0, 0], [1, 1], [2, 2], dtype=complex,
                               order='F')

    x = cdiscr.element()
    newreal = [[3, 4], [5, 6]]
    x.real = newreal
    assert all_equal(x.real, [3, 5, 4, 6])  # flattened in 'F' order
    newreal = [4, 5, 6, 7]
    x.real = newreal
    assert all_equal(x.real, [4, 5, 6, 7])
Example #24
0
def test_factory(exponent):
    discr = odl.uniform_discr(0, 1, 10, impl='numpy', exponent=exponent)

    assert isinstance(discr.dspace, odl.Fn)
    assert discr.is_rn
    assert discr.dspace.exponent == exponent

    # Complex
    discr = odl.uniform_discr(0, 1, 10, field=odl.ComplexNumbers(),
                              impl='numpy', exponent=exponent)

    assert isinstance(discr.dspace, odl.Fn)
    assert discr.is_cn
    assert discr.dspace.exponent == exponent
Example #25
0
def test_factory_dtypes_cuda():
    real_float_dtypes = [np.float32, np.float64]
    nonfloat_dtypes = [np.int8, np.int16, np.int32, np.int64,
                       np.uint8, np.uint16, np.uint32, np.uint64]
    complex_float_dtypes = [np.complex64, np.complex128]

    for dtype in real_float_dtypes:
        if dtype not in odl.CUDA_DTYPES:
            with pytest.raises(TypeError):
                odl.uniform_discr(0, 1, 10, impl='cuda', dtype=dtype)
        else:
            discr = odl.uniform_discr(0, 1, 10, impl='cuda', dtype=dtype)
            assert isinstance(discr.dspace, odl.CudaFn)
            assert discr.is_rn
            assert discr.dspace.element().space.dtype == dtype

    for dtype in nonfloat_dtypes:
        if dtype not in odl.CUDA_DTYPES:
            with pytest.raises(TypeError):
                odl.uniform_discr(0, 1, 10, impl='cuda', dtype=dtype)
        else:
            discr = odl.uniform_discr(0, 1, 10, impl='cuda', dtype=dtype)
            assert isinstance(discr.dspace, odl.CudaFn)
            assert not discr.is_rn
            assert discr.dspace.element().space.dtype == dtype

    for dtype in complex_float_dtypes:
        with pytest.raises(NotImplementedError):
            odl.uniform_discr(0, 1, 10, impl='cuda', dtype=dtype)
Example #26
0
def test_equals_vec(exponent, fn_impl):
    discr = odl.uniform_discr(0, 1, 3, exponent=exponent, impl=fn_impl)
    discr2 = odl.uniform_discr(0, 1, 4, exponent=exponent, impl=fn_impl)
    x1 = discr.element([1, 2, 3])
    x2 = discr.element([1, 2, 3])
    y = discr.element([2, 2, 3])
    z = discr2.element([1, 2, 3, 4])

    assert x1 is x1
    assert x1 is not x2
    assert x1 is not y
    assert x1 == x1
    assert x1 == x2
    assert x1 != y
    assert x1 != z
Example #27
0
def test_resizing_op_deriv(padding):

    pad_mode, pad_const = padding
    space = odl.uniform_discr([0, -1], [1, 1], (4, 5))
    res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2))
    res_op = odl.ResizingOperator(space, res_space, pad_mode=pad_mode,
                                  pad_const=pad_const)
    res_op_deriv = res_op.derivative(space.one())

    if pad_mode == 'constant' and pad_const != 0:
        # Only non-trivial case is constant padding with const != 0
        assert res_op_deriv.pad_mode == 'constant'
        assert res_op_deriv.pad_const == 0.0
    else:
        assert res_op_deriv is res_op
Example #28
0
def test_pointwise_inner_real():
    # 1d
    fspace = odl.uniform_discr([0, 0], [1, 1], (2, 2))
    vfspace = ProductSpace(fspace, 1)
    array = np.array([[[-1, -3],
                       [2, 0]]])
    pwinner = PointwiseInner(vfspace, vecfield=array)

    testarr = np.array([[[1, 2],
                         [3, 4]]])

    true_inner = np.sum(testarr * array, axis=0)

    func = vfspace.element(testarr)
    func_pwinner = pwinner(func)
    assert all_almost_equal(func_pwinner, true_inner.reshape(-1))

    out = fspace.element()
    pwinner(func, out=out)
    assert all_almost_equal(out, true_inner.reshape(-1))

    # 3d
    fspace = odl.uniform_discr([0, 0], [1, 1], (2, 2))
    vfspace = ProductSpace(fspace, 3)
    array = np.array([[[-1, -3],
                       [2, 0]],
                      [[0, 0],
                       [0, 1]],
                      [[-1, 1],
                       [1, 1]]])
    pwinner = PointwiseInner(vfspace, vecfield=array)

    testarr = np.array([[[1, 2],
                         [3, 4]],
                        [[0, -1],
                         [0, 1]],
                        [[1, 1],
                         [1, 1]]])

    true_inner = np.sum(testarr * array, axis=0)

    func = vfspace.element(testarr)
    func_pwinner = pwinner(func)
    assert all_almost_equal(func_pwinner, true_inner.reshape(-1))

    out = fspace.element()
    pwinner(func, out=out)
    assert all_almost_equal(out, true_inner.reshape(-1))
Example #29
0
def optimization_problem(request):
    problem_name = request.param

    if problem_name == 'MatVec':
        # Define problem
        op_arr = np.eye(5) * 5 + np.ones([5, 5])
        op = odl.MatVecOperator(op_arr)

        # Simple right hand side
        rhs = op.range.one()

        # Initial guess
        x = op.domain.element([0.6, 0.8, 1.0, 1.2, 1.4])

        return op, x, rhs
    elif problem_name == 'Identity':
        # Define problem
        space = odl.uniform_discr(0, 1, 5)
        op = odl.IdentityOperator(space)

        # Simple right hand side
        rhs = op.range.element([0, 0, 1, 0, 0])

        # Initial guess
        x = op.domain.element([0.6, 0.8, 1.0, 1.2, 1.4])

        return op, x, rhs
    else:
        raise ValueError('problem not valid')
Example #30
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)
and show their convergence rates.

For further details and a description of the solution method used, see
https://odlgroup.github.io/odl/guide/pdhg_guide.html in the ODL documentation.
"""

import numpy as np
import scipy
import odl
import matplotlib.pyplot as plt

# Define ground truth, space and noisy data
image = np.rot90(scipy.misc.ascent()[::2, ::2].astype('float'), 3)
shape = image.shape
image /= image.max()
space = odl.uniform_discr([0, 0], shape, shape)
orig = space.element(image.copy())
d = odl.phantom.white_noise(space, orig, 0.1)

# Define objective functional
op = odl.Gradient(space)  # operator
norm_op = np.sqrt(8) + 1e-4  # norm with forward differences is well-known
lam = 0.1  # Regularization parameter
f = 1 / (2 * lam) * odl.solvers.L2NormSquared(space).translated(d)  # data fit
g = odl.solvers.Huber(op.range, gamma=.01)  # regularization
obj_fun = f + g * op # combined functional
mu_g = 1 / lam  # strong convexity of "g"
mu_f = 1 / f.grad_lipschitz  # strong convexity of "f*"

# Define algorithm parameters
Example #32
0
device = 'cuda' if astra.astra.use_cuda() else 'cpu'
impl = 'astra_cuda' if astra.astra.use_cuda() else 'astra_cpu'
learning_rate = 1e-2
log_interval = 20
iter4Net = 4
size = 512
val_size = 1
nIter = 10000
nAngles = 60

noiseLev = 0.01

n_data = 4

space = odl.uniform_discr([-128, -128], [128, 128], [size, size],
                          dtype='float32')
geometry = odl.tomo.cone_beam_geometry(space,
                                       src_radius=500,
                                       det_radius=500,
                                       num_angles=nAngles)
ray_trafo = odl.tomo.RayTransform(space, geometry, impl=impl)
fbp_op = odl.tomo.fbp_op(ray_trafo, filter_type='Hann', frequency_scaling=0.6)


def generate_data(validation=False):
    """Generate a set of random data."""
    n_generate = val_size if validation else n_data

    x_arr = np.empty(
        (n_generate, 1, ray_trafo.range.shape[0], ray_trafo.range.shape[1]),
        dtype='float32')
Example #33
0
"""Reference TV reconstruction for head data."""

import numpy as np
import odl

mu_water = 0.02
photons_per_pixel = 10000.0
epsilon = 1.0 / photons_per_pixel
use_artificial_data = True

# Create ODL data structures
size = 512
space = odl.uniform_discr([-128, -128], [128, 128], [size, size],
                          dtype='float32',
                          weighting='const')

# Make a fan beam geometry with flat detector
# Angles: uniformly spaced, n = 1000, min = 0, max = 2 * pi
angle_partition = odl.uniform_partition(0, 2 * np.pi, 1000)
# Detector: uniformly sampled, n = 1000, min = -360, max = 360
detector_partition = odl.uniform_partition(-360, 360, 1000)
geometry = odl.tomo.FanFlatGeometry(angle_partition,
                                    detector_partition,
                                    src_radius=500,
                                    det_radius=500)

# Create ray transform operator
operator = odl.tomo.RayTransform(space, geometry)

# Create pseudoinverse
pseudoinverse = odl.tomo.fbp_op(operator, filter_type='Hann')
Example #34
0
                              domain=kernel.space,
                              range=kernel.space,
                              linear=True)

    def _call(self, x):
        """Implement calling the operator by calling scipy."""
        return scipy.signal.fftconvolve(self.kernel, x, mode='same')

    @property  # making adjoint a property lets users access it as A.adjoint
    def adjoint(self):
        return self  # the adjoint is the same as this operator


# Define the space the problem should be solved on.
# Here the square [-1, 1] x [-1, 1] discretized on a 100x100 grid.
space = odl.uniform_discr([-1, -1], [1, 1], [100, 100])

# Convolution kernel, a small centered rectangle.
kernel = odl.phantom.cuboid(space, [-0.05, -0.05], [0.05, 0.05])

# Create convolution operator
A = Convolution(kernel)

# Create phantom (the "unknown" solution)
phantom = odl.phantom.shepp_logan(space, modified=True)

# Apply convolution to phantom to create data
g = A(phantom)

# Display the results using the show method
kernel.show('kernel')
Example #35
0
for some small ``eps`` in order to account for noise. This can be done using
the `IndicatorLpUnitBall` functional instead of `IndicatorZero`.
"""

import numpy as np
import odl

# Parameters
lam = 0.01
data_matching = 'exact'

# --- Create spaces, forward operator and simulated data ---

# Discrete reconstruction space: discretized functions on the rectangle
# [-20, 20]^2 with 512 samples per dimension.
space = odl.uniform_discr(min_pt=[-20, -20], max_pt=[20, 20], shape=[512, 512])

# Make a parallel beam geometry with flat detector
# Angles: uniformly spaced, n = 22, min = 0, max = pi
angle_partition = odl.uniform_partition(0, np.pi, 22)
# Detector: uniformly sampled, n = 512, min = -30, max = 30
detector_partition = odl.uniform_partition(-30, 30, 512)
geometry = odl.tomo.Parallel2dGeometry(angle_partition, detector_partition)

# Ray transform (= forward projection).
ray_trafo = odl.tomo.RayTransform(space, geometry)

# Create sinogram
phantom = odl.phantom.shepp_logan(space, modified=True)
data = ray_trafo(phantom)
Example #36
0
"""Solver for the STEM problem with L2 distance.

    min_{x1, ..., xn} ||d - sum_i W xi||_2^2 + sum_i ||d - W xi||_2^2

This is solved using the CGLS/CGN method in ODL.

W is taken as the ray transform.
"""

import numpy as np
import odl

# Discrete reconstruction space
space = odl.uniform_discr(min_pt=[-20, -20, -20],
                          max_pt=[20, 20, 20],
                          shape=[128] * 3,
                          dtype='float32')

# Make a parallel beam geometry with flat detector
angle_partition = odl.uniform_partition(-np.deg2rad(75), np.deg2rad(75), 31)
detector_partition = odl.uniform_partition([-20, -20], [20, 20], [128] * 2)
geometry = odl.tomo.Parallel3dAxisGeometry(angle_partition,
                                           detector_partition,
                                           axis=[1, 0, 0])

# Ray transform (= forward projection). We use ASTRA CUDA backend.
ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')

# Create phantom
ellipses = odl.phantom.shepp_logan_ellipses(3, modified=True)[::4]
Example #37
0
where ``grad`` is the spatial gradient and ``g`` the given noisy data.
"""

import numpy as np
import scipy.misc
import odl

# Load image
image = np.rot90(scipy.misc.ascent()[::2, ::2], 3)

# Reading the size
n, m = image.shape

# Create a space
space = odl.uniform_discr([0, 0], [n, m], [n, m])

# Create data, noise and noisy data
data = space.element(image)
noise = odl.phantom.white_noise(space) * 10.0
noisy_data = data + noise
data.show('Original data')
noisy_data.show('Noisy data')

# Gradient for TV regularization
gradient = odl.Gradient(space)

# Assemble the linear operators. Here the TV-term is represented as a
# composition of the 1-norm and the gradient. See the documentation of the
# solver `forward_backward_pd` for the general form of the problem.
lin_ops = [gradient]
Example #38
0
# You should have received a copy of the GNU General Public License
# along with ODL.  If not, see <http://www.gnu.org/licenses/>.
"""Example using the ray transform with 3d parallel beam geometry."""

# Imports for common Python 2/3 codebase
from __future__ import print_function, division, absolute_import
from future import standard_library
standard_library.install_aliases()

import numpy as np
import odl

# Discrete reconstruction space: discretized functions on the cube
# [-20, 20]^3 with 300 samples per dimension.
reco_space = odl.uniform_discr(min_corner=[-20, -20, -20],
                               max_corner=[20, 20, 20],
                               nsamples=[300, 300, 300],
                               dtype='float32')

# Make a parallel beam geometry with flat detector
# Angles: uniformly spaced, n = 360, min = 0, max = 2 * pi
angle_partition = odl.uniform_partition(0, 2 * np.pi, 360)
# Detector: uniformly sampled, n = (558, 558), min = (-30, -30), max = (30, 30)
detector_partition = odl.uniform_partition([-30, -30], [30, 30], [558, 558])
# Discrete reconstruction space

# Astra cannot handle axis aligned origin_to_det unless it is aligned
# with the third coordinate axis. See issue #18 at ASTRA's github.
# This is fixed in new versions of astra, with older versions, this could
# give a zero result.
geometry = odl.tomo.Parallel3dAxisGeometry(angle_partition, detector_partition)
Example #39
0
        """Run all tests on this operator."""
        print('\n== RUNNING ALL TESTS ==')
        print('Operator = {}'.format(self.operator))

        self.norm()

        if self.operator.is_linear:
            self.linear()
            self.adjoint()
        else:
            self.derivative()

    def __str__(self):
        return '{}({})'.format(self.__class__.__name__, self.operator)

    def __repr__(self):
        return '{}({!r})'.format(self.__class__.__name__, self.operator)

if __name__ == '__main__':
    # pylint: disable=wrong-import-position

    import odl
    X = odl.uniform_discr([0, 0], [1, 1], [3, 3])
    # Linear operator
    I = odl.IdentityOperator(X)
    OperatorTest(I).run_tests()

    # Nonlinear operator op(x) = x**4
    op = odl.PowerOperator(X, 4)
    OperatorTest(op).run_tests()
Example using a filtered back-projection (FBP) in cone-beam 3d using `fbp_op`.

Note that the FBP is only approximate in this geometry, but still gives a
decent reconstruction that can be used as an initial guess in more complicated
methods.
"""

import numpy as np
import odl

# --- Set up geometry of the problem --- #

# Reconstruction space: discretized functions on the cube
# [-20, 20]^3 with 300 samples per dimension.
reco_space = odl.uniform_discr(min_pt=[-20, -20, -20],
                               max_pt=[20, 20, 20],
                               shape=[300, 300, 300],
                               dtype='float32')

# Make a circular cone beam geometry with flat detector
# Angles: uniformly spaced, n = 360, min = 0, max = 2 * pi
angle_partition = odl.uniform_partition(0, 2 * np.pi, 360)
# Detector: uniformly sampled, n = (512, 512), min = (-40, -40), max = (40, 40)
detector_partition = odl.uniform_partition([-40, -40], [40, 40], [512, 512])
# Geometry with large cone and fan angle and tilted axis.
geometry = odl.tomo.ConeFlatGeometry(angle_partition,
                                     detector_partition,
                                     src_radius=40,
                                     det_radius=40,
                                     axis=[1, 1, 1])

# --- Create Filtered Back-projection (FBP) operator --- #
Example #41
0
"""Partially learned gradient descent without regularizer as input."""

import tensorflow as tf
import numpy as np
import odl
import odl.contrib.tensorflow
from util import random_phantom, conv2d

sess = tf.InteractiveSession()

# Create ODL data structures
size = 128
space = odl.uniform_discr([-64, -64], [64, 64], [size, size],
                          dtype='float32')

geometry = odl.tomo.parallel_beam_geometry(space, num_angles=30)
operator = odl.tomo.RayTransform(space, geometry)
pseudoinverse = odl.tomo.fbp_op(operator)

# Ensure operator has fixed operator norm for scale invariance
opnorm = odl.power_method_opnorm(operator)
operator = (1 / opnorm) * operator
pseudoinverse = pseudoinverse * opnorm

# Create tensorflow layer from odl operator
odl_op_layer = odl.contrib.tensorflow.as_tensorflow_layer(operator,
                                                          'RayTransform')
odl_op_layer_adjoint = odl.contrib.tensorflow.as_tensorflow_layer(operator.adjoint,
                                                                  'RayTransformAdjoint')

# User selected paramters
"""Visualization of the test functions in the diagnostics module."""

import odl

space_1d = odl.uniform_discr(0, 1, 100)

for name, elem in space_1d.examples:
    elem.show(name)

space_2d = odl.uniform_discr([0, 0], [1, 1], [100, 100])

for name, elem in space_2d.examples:
    elem.show(name)
Example #43
0
    for j in range(dy+1):
        points.append([xmin +fac*sigma_kernel* i*1.0, ymin + fac*sigma_kernel*j*1.0])
#        x0.append(xmin +fac*sigma_kernel* i*1.0)
#        x0.append(ymin + fac*sigma_kernel*j*1.0)

#Number of translations
nbtrans=round(0.5*len(points))

# to be of the good shape for iterative scheme
points = np.array(points).T

def kernel(x, y):
    return np.exp(- sum([ (xi - yi) ** 2 for xi, yi in zip(x,y)]) / (sigma_kernel ** 2))

space=odl.uniform_discr(
min_pt=[-16, -16], max_pt=[16, 16], shape=[128,128],
dtype='float32', interp='linear')

vectorfield_list_center=[]
path='/home/bgris/data/SheppLoganRotationSmallDef/'
name='vectfield_smalldef_sigma_0_3'
for i in range(size):
    name_i=path + name + '_{}'.format(i)
    vect_field_load_i_test=space.tangent_bundle.element(np.loadtxt(name_i)).copy()
    vectorfield_list_center.append(vect_field_load_i_test.copy())

if False:
    vectorfield_list_center[0].show()
    plt.plot(points[0], points[1],'x')

##%%
Example #44
0
Numerical test of a few implemented FOMs (mean square error, mean
absolute error, mean value difference, standard deviation difference,
range difference, blurring, false structures and structural similarity)
as a function of increasing noise level.

"""

import odl
from odl.contrib import fom
import numpy as np
import matplotlib.pyplot as plt

# Discrete space: discretized functions on the rectangle
# [-20, 20]^2 with 100 samples per dimension.
reco_space = odl.uniform_discr(min_pt=[-20, -20],
                               max_pt=[20, 20],
                               shape=[100, 100])

# Create a discrete Shepp-Logan phantom (modified version)
phantom = odl.phantom.shepp_logan(reco_space, modified=True)

mse = []
mae = []
mvd = []
std_diff = []
range_diff = []
blur = []
false_struct = []
ssim = []

# Create mask for ROI to evaluate blurring and false structures. Arbitrarily
Example #45
0
def test_ufunc_corner_cases(odl_tspace_impl):
    """Check if some corner cases are handled correctly."""
    impl = odl_tspace_impl
    space = odl.uniform_discr([0, 0], [1, 1], (2, 3), impl=impl)
    x = space.element([[-1, 0, 1],
                       [1, 2, 3]])
    space_no_w = odl.uniform_discr([0, 0], [1, 1], (2, 3), impl=impl,
                                   weighting=1.0)

    # --- Ufuncs with nin = 1, nout = 1 --- #

    with pytest.raises(ValueError):
        # Too many arguments
        x.__array_ufunc__(np.sin, '__call__', x, np.ones((2, 3)))

    # Check that `out=(None,)` is the same as not providing `out`
    res = x.__array_ufunc__(np.sin, '__call__', x, out=(None,))
    assert all_almost_equal(res, np.sin(x.asarray()))
    # Check that the result space is the same
    assert res.space == space

    # Check usage of `order` argument
    for order in ('C', 'F'):
        res = x.__array_ufunc__(np.sin, '__call__', x, order=order)
        assert all_almost_equal(res, np.sin(x.asarray()))
        assert res.tensor.data.flags[order + '_CONTIGUOUS']

    # Check usage of `dtype` argument
    res = x.__array_ufunc__(np.sin, '__call__', x, dtype=complex)
    assert all_almost_equal(res, np.sin(x.asarray(), dtype=complex))
    assert res.dtype == complex

    # Check propagation of weightings
    y = space_no_w.one()
    res = y.__array_ufunc__(np.sin, '__call__', y)
    assert res.space.weighting == space_no_w.weighting
    y = space_no_w.one()
    res = y.__array_ufunc__(np.sin, '__call__', y)
    assert res.space.weighting == space_no_w.weighting

    # --- Ufuncs with nin = 2, nout = 1 --- #

    with pytest.raises(ValueError):
        # Too few arguments
        x.__array_ufunc__(np.add, '__call__', x)

    with pytest.raises(ValueError):
        # Too many outputs
        out1, out2 = np.empty_like(x), np.empty_like(x)
        x.__array_ufunc__(np.add, '__call__', x, x, out=(out1, out2))

    # Check that npy_array += odl_vector works
    arr = np.ones((2, 3))
    arr += x
    assert all_almost_equal(arr, x.asarray() + 1)
    # For Numpy >= 1.13, this will be equivalent
    arr = np.ones((2, 3))
    res = x.__array_ufunc__(np.add, '__call__', arr, x, out=(arr,))
    assert all_almost_equal(arr, x.asarray() + 1)
    assert res is arr

    # --- `accumulate` --- #

    res = x.__array_ufunc__(np.add, 'accumulate', x)
    assert all_almost_equal(res, np.add.accumulate(x.asarray()))
    assert res.space == space
    arr = np.empty_like(x)
    res = x.__array_ufunc__(np.add, 'accumulate', x, out=(arr,))
    assert all_almost_equal(arr, np.add.accumulate(x.asarray()))
    assert res is arr

    # `accumulate` with other dtype
    res = x.__array_ufunc__(np.add, 'accumulate', x, dtype='float32')
    assert res.dtype == 'float32'

    # Error scenarios
    with pytest.raises(ValueError):
        # Too many `out` arguments
        out1, out2 = np.empty_like(x), np.empty_like(x)
        x.__array_ufunc__(np.add, 'accumulate', x, out=(out1, out2))

    # --- `reduce` --- #

    res = x.__array_ufunc__(np.add, 'reduce', x)
    assert all_almost_equal(res, np.add.reduce(x.asarray()))

    with pytest.raises(ValueError):
        x.__array_ufunc__(np.add, 'reduce', x, keepdims=True)

    # With `out` argument and `axis`
    out_ax0 = np.empty(3)
    res = x.__array_ufunc__(np.add, 'reduce', x, axis=0, out=(out_ax0,))
    assert all_almost_equal(out_ax0, np.add.reduce(x.asarray(), axis=0))
    assert res is out_ax0
    out_ax1 = odl.rn(2).element()
    res = x.__array_ufunc__(np.add, 'reduce', x, axis=1, out=(out_ax1,))
    assert all_almost_equal(out_ax1, np.add.reduce(x.asarray(), axis=1))
    assert res is out_ax1

    # Addition is reorderable, so we can give multiple axes
    res = x.__array_ufunc__(np.add, 'reduce', x, axis=(0, 1))
    assert res == pytest.approx(np.add.reduce(x.asarray(), axis=(0, 1)))

    # Constant weighting should be preserved (recomputed from cell
    # volume)
    y = space.one()
    res = y.__array_ufunc__(np.add, 'reduce', y, axis=0)
    assert res.space.weighting.const == pytest.approx(space.cell_sides[1])

    # Check that `exponent` is propagated
    space_1 = odl.uniform_discr([0, 0], [1, 1], (2, 3), impl=impl,
                                exponent=1)
    z = space_1.one()
    res = z.__array_ufunc__(np.add, 'reduce', z, axis=0)
    assert res.space.exponent == 1

    # --- `outer` --- #

    # Check that weightings are propagated correctly
    x = y = space.one()
    res = x.__array_ufunc__(np.add, 'outer', x, y)
    assert isinstance(res.space.weighting, ConstWeighting)
    assert res.space.weighting.const == pytest.approx(x.space.weighting.const *
                                                      y.space.weighting.const)

    x = space.one()
    y = space_no_w.one()
    res = x.__array_ufunc__(np.add, 'outer', x, y)
    assert isinstance(res.space.weighting, ConstWeighting)
    assert res.space.weighting.const == pytest.approx(x.space.weighting.const)

    x = y = space_no_w.one()
    res = x.__array_ufunc__(np.add, 'outer', x, y)
    assert not res.space.is_weighted
Example #46
0
"""Run the standardized diagonstics suite on some of the spaces."""

import odl

print('\n\n TESTING FOR Lp SPACE \n\n')

discr = odl.uniform_discr(0, 1, 10)
odl.diagnostics.SpaceTest(discr).run_tests()

print('\n\n TESTING FOR rn SPACE \n\n')

spc = odl.rn(10)
odl.diagnostics.SpaceTest(spc).run_tests()

print('\n\n TESTING FOR cn SPACE \n\n')

spc = odl.cn(10)
odl.diagnostics.SpaceTest(spc).run_tests()

if 'cuda' in odl.fn_impl_names():
    print('\n\n TESTING FOR CUDA rn SPACE \n\n')

    spc = odl.rn(10, impl='cuda')
    odl.diagnostics.SpaceTest(spc, tol=0.0001).run_tests()
Example #47
0
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.
"""Test for parameter optimization."""

import pytest
import numpy as np
import odl
import odl.contrib.fom
import odl.contrib.param_opt
from odl.util.testutils import simple_fixture

space = simple_fixture('space', [
    odl.rn(3),
    odl.uniform_discr([0, 0], [1, 1], [9, 11]),
    odl.uniform_discr(0, 1, 10)
])

fom = simple_fixture(
    'fom',
    [odl.contrib.fom.mean_squared_error, odl.contrib.fom.mean_absolute_error])


def test_optimal_parameters_one_parameter(space, fom):
    """Tests if optimal_parameters works for some simple examples."""
    noise = [odl.phantom.white_noise(space) for _ in range(2)]
    phantoms = noise.copy()
    data = noise.copy()

    def reconstruction(data, lam):
Example #48
0
def test_real_imag(odl_tspace_impl, odl_elem_order):
    """Check if real and imaginary parts can be read and written to."""
    impl = odl_tspace_impl
    order = odl_elem_order
    tspace_cls = odl.space.entry_points.tensor_space_impl(impl)
    for dtype in filter(odl.util.is_complex_floating_dtype,
                        tspace_cls.available_dtypes()):
        cdiscr = odl.uniform_discr([0, 0], [1, 1], [2, 2], dtype=dtype,
                                   impl=impl)
        rdiscr = cdiscr.real_space

        # Get real and imag
        x = cdiscr.element([[1 - 1j, 2 - 2j],
                            [3 - 3j, 4 - 4j]], order=order)
        assert x.real in rdiscr
        assert all_equal(x.real, [[1, 2],
                                  [3, 4]])
        assert x.imag in rdiscr
        assert all_equal(x.imag, [[-1, -2],
                                  [-3, -4]])

        # Set with different data types and shapes
        for assigntype in (lambda x: x, tuple, rdiscr.element):

            # Using setters
            x = cdiscr.zero()
            x.real = assigntype([[2, 3],
                                 [4, 5]])
            assert all_equal(x.real, [[2, 3],
                                      [4, 5]])

            x = cdiscr.zero()
            x.imag = assigntype([[4, 5],
                                 [6, 7]])
            assert all_equal(x.imag, [[4, 5],
                                      [6, 7]])

            # With [:] assignment
            x = cdiscr.zero()
            x.real[:] = assigntype([[2, 3],
                                    [4, 5]])
            assert all_equal(x.real, [[2, 3],
                                      [4, 5]])

            x = cdiscr.zero()
            x.imag[:] = assigntype([[2, 3],
                                    [4, 5]])
            assert all_equal(x.imag, [[2, 3],
                                      [4, 5]])

        # Setting with scalars
        x = cdiscr.zero()
        x.real = 1
        assert all_equal(x.real, [[1, 1],
                                  [1, 1]])

        x = cdiscr.zero()
        x.imag = -1
        assert all_equal(x.imag, [[-1, -1],
                                  [-1, -1]])

    # Incompatible shapes
    with pytest.raises(ValueError):
        x.real = [4, 5, 6, 7]
    with pytest.raises(ValueError):
        x.imag = [4, 5, 6, 7]
Where ``A`` is a convolution operator, ``grad`` the spatial gradient and ``g``
is given noisy data.

For further details and a description of the solution method used, see
:ref:`chambolle_pock` in the ODL documentation.
"""

import numpy as np
import odl

# Discretization parameters
n = 128

# Discretized spaces
space = odl.uniform_discr([0, 0], [n, n], [n, n])

# Initialize convolution operator by Fourier formula
#     conv(f, g) = F^{-1}[F[f] * F[g]]
# Where F[.] is the Fourier transform and the fourier transform of a guassian
# with standard deviation filter_width is another gaussian with width
# 1 / filter_width
filter_width = 3.0  # standard deviation of the Gaussian filter
ft = odl.trafos.FourierTransform(space)
c = filter_width ** 2 / 4.0 ** 2
gaussian = ft.range.element(lambda x: np.exp(-(x[0] ** 2 + x[1] ** 2) * c))
convolution = ft.inverse * gaussian * ft

# Optional: Run diagnostics to assure the adjoint is properly implemented
# odl.diagnostics.OperatorTest(conv_op).run_tests()
Example #50
0
def test_operators(odl_tspace_impl):
    impl = odl_tspace_impl
    # Test of all operator overloads against the corresponding NumPy
    # implementation
    discr = odl.uniform_discr(0, 1, 10, impl=impl)

    # Unary operators
    _test_unary_operator(discr, lambda x: +x)
    _test_unary_operator(discr, lambda x: -x)

    # Scalar addition
    for scalar in [-31.2, -1, 0, 1, 2.13]:
        def iadd(x):
            x += scalar
        _test_unary_operator(discr, iadd)
        _test_unary_operator(discr, lambda x: x + scalar)

    # Scalar subtraction
    for scalar in [-31.2, -1, 0, 1, 2.13]:
        def isub(x):
            x -= scalar
        _test_unary_operator(discr, isub)
        _test_unary_operator(discr, lambda x: x - scalar)

    # Scalar multiplication
    for scalar in [-31.2, -1, 0, 1, 2.13]:
        def imul(x):
            x *= scalar
        _test_unary_operator(discr, imul)
        _test_unary_operator(discr, lambda x: x * scalar)

    # Scalar division
    for scalar in [-31.2, -1, 1, 2.13]:
        def idiv(x):
            x /= scalar
        _test_unary_operator(discr, idiv)
        _test_unary_operator(discr, lambda x: x / scalar)

    # Incremental operations
    def iadd(x, y):
        x += y

    def isub(x, y):
        x -= y

    def imul(x, y):
        x *= y

    def idiv(x, y):
        x /= y

    _test_binary_operator(discr, iadd)
    _test_binary_operator(discr, isub)
    _test_binary_operator(discr, imul)
    _test_binary_operator(discr, idiv)

    # Incremental operators with aliased inputs
    def iadd_aliased(x):
        x += x

    def isub_aliased(x):
        x -= x

    def imul_aliased(x):
        x *= x

    def idiv_aliased(x):
        x /= x

    _test_unary_operator(discr, iadd_aliased)
    _test_unary_operator(discr, isub_aliased)
    _test_unary_operator(discr, imul_aliased)
    _test_unary_operator(discr, idiv_aliased)

    # Binary operators
    _test_binary_operator(discr, lambda x, y: x + y)
    _test_binary_operator(discr, lambda x, y: x - y)
    _test_binary_operator(discr, lambda x, y: x * y)
    _test_binary_operator(discr, lambda x, y: x / y)

    # Binary with aliased inputs
    _test_unary_operator(discr, lambda x: x + x)
    _test_unary_operator(discr, lambda x: x - x)
    _test_unary_operator(discr, lambda x: x * x)
    _test_unary_operator(discr, lambda x: x / x)
from __future__ import print_function, division, absolute_import
from future import standard_library
standard_library.install_aliases()

# External
import numpy as np

# Internal
import odl
from odl.solvers import chambolle_pock_solver, f_cc_prox_l2_tv, g_prox_none
import matplotlib.pyplot as plt

n = 200

# Discrete reconstruction space
discr_reco_space = odl.uniform_discr([-20, -20, -20], [20, 20, 20],
                                     [n]*3, dtype='float32')

# Geometry
src_rad = 1000
det_rad = 100
angle_intvl = odl.Interval(0, 2 * np.pi)
dparams = odl.Rectangle([-50, -50], [50, 50])
agrid = odl.uniform_sampling(angle_intvl, n * 2)
dgrid = odl.uniform_sampling(dparams, [n, n])
geom = odl.tomo.CircularConeFlatGeometry(angle_intvl, dparams,
                                         src_rad, det_rad,
                                         agrid, dgrid)

# X-ray transform
A = odl.tomo.DiscreteXrayTransform(discr_reco_space, geom,
                                   backend='astra_cuda')
Example #52
0
def test_getitem():
    discr = odl.uniform_discr(0, 1, 3)
    elem = discr.element([1, 2, 3])

    assert all_equal(elem, [1, 2, 3])
Example #53
0
    -Laplacian(x) = b

where b is a gaussian peak at the origin.
"""

# Imports for common Python 2/3 codebase
from __future__ import print_function, division, absolute_import
from future import standard_library
standard_library.install_aliases()

import numpy as np
import scipy.sparse.linalg as sl
import odl

# Create discrete space, a square from [-1, 1] x [-1, 1] with (11 x 11) points
space = odl.uniform_discr([-1, -1], [1, 1], [11, 11])

# Create odl operator for negative laplacian
laplacian = -odl.Laplacian(space)

# Create right hand side, a gaussian around the point (0, 0)
rhs = space.element(lambda x: np.exp(-(x[0]**2 + x[1]**2) / 0.1**2))

# Convert laplacian to scipy operator
scipy_laplacian = odl.operator.oputils.as_scipy_operator(laplacian)

# Convert to array and flatten
rhs_arr = rhs.asarray().ravel(space.order)

# Solve using scipy
result, info = sl.cg(scipy_laplacian, rhs_arr)
Example #54
0
def test_setitem_nd():

    # 1D
    discr = odl.uniform_discr(0, 1, 3)
    elem = discr.element([1, 2, 3])

    elem[:] = [4, 5, 6]
    assert all_equal(elem, [4, 5, 6])

    elem[:] = np.array([3, 2, 1])
    assert all_equal(elem, [3, 2, 1])

    elem[:] = 0
    assert all_equal(elem, [0, 0, 0])

    elem[:] = [1]
    assert all_equal(elem, [1, 1, 1])

    with pytest.raises(ValueError):
        elem[:] = [0, 0]  # bad shape

    with pytest.raises(ValueError):
        elem[:] = [0, 0, 1, 2]  # bad shape

    # 2D
    discr = odl.uniform_discr([0, 0], [1, 1], [3, 2])

    elem = discr.element([[1, 2],
                          [3, 4],
                          [5, 6]])

    elem[:] = [[-1, -2],
               [-3, -4],
               [-5, -6]]
    assert all_equal(elem, [[-1, -2],
                            [-3, -4],
                            [-5, -6]])

    arr = np.arange(6, 12).reshape([3, 2])
    elem[:] = arr
    assert all_equal(elem, arr)

    elem[:] = 0
    assert all_equal(elem, np.zeros(elem.shape))

    elem[:] = [1]
    assert all_equal(elem, np.ones(elem.shape))

    elem[:] = [0, 0]  # broadcasting assignment
    assert all_equal(elem, np.zeros(elem.shape))

    with pytest.raises(ValueError):
        elem[:] = [0, 0, 0]  # bad shape

    with pytest.raises(ValueError):
        elem[:] = np.arange(6)  # bad shape (6,)

    with pytest.raises(ValueError):
        elem[:] = np.ones((2, 3))[..., np.newaxis]  # bad shape (2, 3, 1)

    with pytest.raises(ValueError):
        arr = np.arange(6, 12).reshape([3, 2])
        elem[:] = arr.T  # bad shape (2, 3)

    # nD
    shape = (3,) * 3 + (4,) * 3
    discr = odl.uniform_discr([0] * 6, [1] * 6, shape)
    size = np.prod(shape)
    elem = discr.element(np.zeros(shape))

    arr = np.arange(size).reshape(shape)

    elem[:] = arr
    assert all_equal(elem, arr)

    elem[:] = 0
    assert all_equal(elem, np.zeros(elem.shape))

    elem[:] = [1]
    assert all_equal(elem, np.ones(elem.shape))

    with pytest.raises(ValueError):
        # Reversed shape -> bad
        elem[:] = np.arange(size).reshape((4,) * 3 + (3,) * 3)
Example #55
0
import numpy as np
import pickle
import odl

# Define reco space
vol_size = np.array([230.0, 230.0])
vol_min = np.array([-115.0, -115.0])
shape = (512, 512)
reco_space = odl.uniform_discr(vol_min, vol_min + vol_size, shape)

# Set paths and file names
data_path = '/home/hkohr/SciData/Head_CT_Sim/'
geom_fname = 'HelicalSkullCT_70100644Phantom_no_bed_Dose150mGy_2D.geometry.p'
data_fname = 'HelicalSkullCT_70100644Phantom_no_bed_Dose150mGy_2D_120kV.npy'

# Get geometry and data
with open(data_path + geom_fname, 'rb') as f:
    geom = pickle.load(f, encoding='latin1')

data_arr = np.load(data_path + data_fname).astype('float32')
log_data_arr = -np.log(data_arr / np.max(data_arr))

# Define ray transform
ray_trafo = odl.tomo.RayTransform(reco_space, geom)

# Initialize data as ODL space element and display it, clipping to a
# somewhat reasonable range
data = ray_trafo.range.element(log_data_arr)
data.show('Sinogram', clim=[0, 4.5])

#  Compute FBP reco for a good initial guess
Example #56
0
def test_setslice():
    discr = odl.uniform_discr(0, 1, 3)
    elem = discr.element([1, 2, 3])

    elem[:] = [4, 5, 6]
    assert all_equal(elem, [4, 5, 6])
Example #57
0
def test_xray_trafo_parallel2d():
    """3D parallel-beam discrete X-ray transform with ASTRA CUDA."""

    # Discrete reconstruction space
    xx = 5
    nn = 5
    # xx = 5.5
    # nn = 11
    discr_vol_space = odl.uniform_discr([-xx] * 2, [xx] * 2, [nn] * 2,
                                        dtype='float32')

    # Angle
    angle_intvl = odl.Interval(0, 2 * np.pi) - np.pi / 4
    agrid = odl.uniform_sampling(angle_intvl, 4)

    # Detector
    yy = 11
    mm = 11
    # yy = 10.5
    # mm = 21
    dparams = odl.Interval(-yy, yy)
    dgrid = odl.uniform_sampling(dparams, mm)

    # Geometry
    geom = odl.tomo.Parallel2dGeometry(angle_intvl, dparams, agrid, dgrid)

    # Projection space
    proj_space = odl.FunctionSpace(geom.params)

    # `DiscreteLp` projection space
    proj_shape = geom.grid.shape
    discr_proj_space = odl.uniform_discr_fromspace(proj_space, proj_shape,
                                                   dtype='float32')

    # X-ray transform
    A = odl.tomo.XrayTransform(discr_vol_space, geom,
                               backend='astra_cuda')

    # Domain element
    f = A.domain.one()

    # Forward projection
    Af = A(f)
    A0f = odl.tomo.astra_cuda_forward_projector(f, geom,
                                                discr_proj_space)

    # Range element
    g = A.range.one()

    # Back projection
    Adg = A.adjoint(g)
    Adg0 = odl.tomo.astra_cuda_back_projector(g, geom,
                                              discr_vol_space)

    print('\nvol stride', discr_vol_space.grid.stride)
    print('proj stride', geom.grid.stride)
    print('angle intv:', angle_intvl.size)
    # f = discr_vol_space3.one()
    # print(f.asarray()[:, :, np.round(f.shape[2]/2)])
    print('forward')
    print(Af.asarray()[0])
    print(A0f.asarray()[0])
    print('backward')
    print(Adg.asarray() / float(agrid.stride) / agrid.ntotal)
    print(Adg0.asarray() / agrid.ntotal)
Example #58
0
def test_ufuncs(odl_tspace_impl, odl_ufunc):
    """Test ufuncs in ``x.ufuncs`` against direct Numpy ufuncs."""
    impl = odl_tspace_impl
    space = odl.uniform_discr([0, 0], [1, 1], (2, 3), impl=impl)
    name = odl_ufunc

    # Get the ufunc from numpy as reference
    npy_ufunc = getattr(np, name)
    nin = npy_ufunc.nin
    nout = npy_ufunc.nout
    if (np.issubsctype(space.dtype, np.floating) and
            name in ['bitwise_and',
                     'bitwise_or',
                     'bitwise_xor',
                     'invert',
                     'left_shift',
                     'right_shift']):
        # Skip integer only methods if floating point type
        return

    # Create some data
    arrays, elements = noise_elements(space, nin + nout)
    in_arrays = arrays[:nin]
    out_arrays = arrays[nin:]
    data_elem = elements[0]
    out_elems = elements[nin:]

    if nout == 1:
        out_arr_kwargs = {'out': out_arrays[0]}
        out_elem_kwargs = {'out': out_elems[0]}
    elif nout > 1:
        out_arr_kwargs = {'out': out_arrays[:nout]}
        out_elem_kwargs = {'out': out_elems[:nout]}

    # Get function to call, using both interfaces:
    # - vec.ufunc(other_args)
    # - np.ufunc(vec, other_args)
    elem_fun_old = getattr(data_elem.ufuncs, name)
    in_elems_old = elements[1:nin]
    elem_fun_new = npy_ufunc
    in_elems_new = elements[:nin]

    # Out-of-place
    with np.errstate(all='ignore'):  # avoid pytest warnings
        npy_result = npy_ufunc(*in_arrays)
        odl_result_old = elem_fun_old(*in_elems_old)
        assert all_almost_equal(npy_result, odl_result_old)
        odl_result_new = elem_fun_new(*in_elems_new)
        assert all_almost_equal(npy_result, odl_result_new)

    # Test type of output
    if nout == 1:
        assert isinstance(odl_result_old, space.element_type)
        assert isinstance(odl_result_new, space.element_type)
    elif nout > 1:
        for i in range(nout):
            assert isinstance(odl_result_old[i], space.element_type)
            assert isinstance(odl_result_new[i], space.element_type)

    # In-place with ODL objects as `out`
    with np.errstate(all='ignore'):  # avoid pytest warnings
        npy_result = npy_ufunc(*in_arrays, **out_arr_kwargs)
        odl_result_old = elem_fun_old(*in_elems_old, **out_elem_kwargs)
        assert all_almost_equal(npy_result, odl_result_old)
        odl_result_new = elem_fun_new(*in_elems_new, **out_elem_kwargs)
        assert all_almost_equal(npy_result, odl_result_new)

    # Check that returned stuff refers to given out
    if nout == 1:
        assert odl_result_old is out_elems[0]
        assert odl_result_new is out_elems[0]
    elif nout > 1:
        for i in range(nout):
            assert odl_result_old[i] is out_elems[i]
            assert odl_result_new[i] is out_elems[i]

    # In-place with Numpy array as `out` for new interface
    out_arrays_new = tuple(np.empty_like(arr) for arr in out_arrays)
    if nout == 1:
        out_arr_kwargs_new = {'out': out_arrays_new[0]}
    elif nout > 1:
        out_arr_kwargs_new = {'out': out_arrays_new[:nout]}

    with np.errstate(all='ignore'):  # avoid pytest warnings
        odl_result_arr_new = elem_fun_new(*in_elems_new,
                                          **out_arr_kwargs_new)
    assert all_almost_equal(npy_result, odl_result_arr_new)

    if nout == 1:
        assert odl_result_arr_new is out_arrays_new[0]
    elif nout > 1:
        for i in range(nout):
            assert odl_result_arr_new[i] is out_arrays_new[i]

    # In-place with data container (tensor) as `out` for new interface
    out_tensors_new = tuple(space.tspace.element(np.empty_like(arr))
                            for arr in out_arrays)
    if nout == 1:
        out_tens_kwargs_new = {'out': out_tensors_new[0]}
    elif nout > 1:
        out_tens_kwargs_new = {'out': out_tensors_new[:nout]}

    with np.errstate(all='ignore'):  # avoid pytest warnings
        odl_result_tens_new = elem_fun_new(*in_elems_new,
                                           **out_tens_kwargs_new)
    assert all_almost_equal(npy_result, odl_result_tens_new)

    if nout == 1:
        assert odl_result_tens_new is out_tensors_new[0]
    elif nout > 1:
        for i in range(nout):
            assert odl_result_tens_new[i] is out_tensors_new[i]

    # Check `ufunc.at`
    indices = ([0, 0, 1],
               [0, 1, 2])

    mod_array = in_arrays[0].copy()
    mod_elem = in_elems_new[0].copy()
    if nout > 1:
        return  # currently not supported by Numpy
    if nin == 1:
        with np.errstate(all='ignore'):  # avoid pytest warnings
            npy_result = npy_ufunc.at(mod_array, indices)
            odl_result = npy_ufunc.at(mod_elem, indices)
    elif nin == 2:
        other_array = in_arrays[1][indices]
        other_elem = in_elems_new[1][indices]
        with np.errstate(all='ignore'):  # avoid pytest warnings
            npy_result = npy_ufunc.at(mod_array, indices, other_array)
            odl_result = npy_ufunc.at(mod_elem, indices, other_elem)

    assert all_almost_equal(odl_result, npy_result)

    # Check `ufunc.reduce`
    if nin == 2 and nout == 1:
        in_array = in_arrays[0]
        in_elem = in_elems_new[0]

        # We only test along one axis since some binary ufuncs are not
        # re-orderable, in which case Numpy raises a ValueError
        with np.errstate(all='ignore'):  # avoid pytest warnings
            npy_result = npy_ufunc.reduce(in_array)
            odl_result = npy_ufunc.reduce(in_elem)
            assert all_almost_equal(odl_result, npy_result)
            # In-place using `out` (with ODL vector and array)
            out_elem = odl_result.space.element()
            out_array = np.empty(odl_result.shape,
                                 dtype=odl_result.dtype)
            npy_ufunc.reduce(in_elem, out=out_elem)
            npy_ufunc.reduce(in_elem, out=out_array)
            assert all_almost_equal(out_elem, odl_result)
            assert all_almost_equal(out_array, odl_result)
            # Using a specific dtype
            try:
                npy_result = npy_ufunc.reduce(in_array, dtype=complex)
            except TypeError:
                # Numpy finds no matching loop, bail out
                return
            else:
                odl_result = npy_ufunc.reduce(in_elem, dtype=complex)
                assert odl_result.dtype == npy_result.dtype
                assert all_almost_equal(odl_result, npy_result)
Example #59
0
    In 3d the phantom is simply the 2d phantom extended in the z direction as
    cylinders.
    """
    if space.ndim == 2:
        return ellipsoid_phantom(space, _derenzo_sources_2d())
    if space.ndim == 3:
        return ellipsoid_phantom(
            space, cylinders_from_ellipses(_derenzo_sources_2d()))
    else:
        raise ValueError('dimension not 2, no phantom available')


if __name__ == '__main__':
    # Show the phantoms
    import odl
    n = 300

    # 2D
    discr = odl.uniform_discr([-1, -1], [1, 1], [n, n])
    derenzo_sources(discr).show('derenzo_sources 2d')

    # 3D
    discr = odl.uniform_discr([-1, -1, -1], [1, 1, 1], [300, 300, 300])
    derenzo_sources(discr).show('derenzo_sources 3d')

    # Run also the doctests
    # pylint: disable=wrong-import-position
    from odl.util.testutils import run_doctests
    run_doctests()
Example #60
0
def test_pdhg_simple_space():
    """Test for the Primal-Dual Hybrid Gradient algorithm."""

    # Create a discretized image space
    space = odl.uniform_discr(0, 1, DATA.size)

    # Operator
    op = odl.IdentityOperator(space)

    # Starting point (image)
    discr_vec = op.domain.element(DATA)

    # Relaxation variable required to resume iteration
    discr_vec_relax = discr_vec.copy()

    # Dual variable required to resume iteration
    discr_dual = op.range.zero()

    # Functional, use the same functional for F^* and G
    g = odl.solvers.ZeroFunctional(space)
    f = g.convex_conj

    # Run the algorithm
    pdhg(discr_vec,
         f,
         g,
         op,
         tau=TAU,
         sigma=SIGMA,
         theta=THETA,
         niter=1,
         callback=None,
         x_relax=discr_vec_relax,
         y=discr_dual)

    # Explicit computation
    vec_expl = (1 - TAU * SIGMA) * DATA

    assert all_almost_equal(discr_vec, vec_expl, PLACES)

    # Explicit computation of the value of the relaxation variable
    vec_relax_expl = (1 + THETA) * vec_expl - THETA * DATA

    assert all_almost_equal(discr_vec_relax, vec_relax_expl, PLACES)

    # Resume iteration with previous x but without previous relaxation
    pdhg(discr_vec, f, g, op, tau=TAU, sigma=SIGMA, theta=THETA, niter=1)

    vec_expl *= (1 - SIGMA * TAU)
    assert all_almost_equal(discr_vec, vec_expl, PLACES)

    # Resume iteration with x1 as above and with relaxation parameter
    discr_vec[:] = vec_expl
    pdhg(discr_vec,
         f,
         g,
         op,
         tau=TAU,
         sigma=SIGMA,
         theta=THETA,
         niter=1,
         x_relax=discr_vec_relax,
         y=discr_dual)

    vec_expl = vec_expl - TAU * SIGMA * (DATA + vec_relax_expl)
    assert all_almost_equal(discr_vec, vec_expl, PLACES)

    # Test acceleration parameter: use output argument for the relaxation
    # variable since otherwise two iterations are required for the
    # relaxation to take effect on the input variable
    # Acceleration parameter gamma=0 corresponds to relaxation parameter
    # theta=1 without acceleration

    # Relaxation parameter 1 and no acceleration
    discr_vec = op.domain.element(DATA)
    discr_vec_relax_no_gamma = op.domain.element(DATA)
    pdhg(discr_vec,
         f,
         g,
         op,
         tau=TAU,
         sigma=SIGMA,
         theta=1,
         gamma_primal=None,
         niter=1,
         x_relax=discr_vec_relax_no_gamma)

    # Acceleration parameter 0, overwrites relaxation parameter
    discr_vec = op.domain.element(DATA)
    discr_vec_relax_g0 = op.domain.element(DATA)
    pdhg(discr_vec,
         f,
         g,
         op,
         tau=TAU,
         sigma=SIGMA,
         theta=0,
         gamma_primal=0,
         niter=1,
         x_relax=discr_vec_relax_g0)

    assert discr_vec != discr_vec_relax_no_gamma
    assert all_almost_equal(discr_vec_relax_no_gamma, discr_vec_relax_g0)

    # Test callback execution
    pdhg(discr_vec,
         f,
         g,
         op,
         tau=TAU,
         sigma=SIGMA,
         theta=THETA,
         niter=1,
         callback=odl.solvers.CallbackPrintIteration())