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
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])
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)
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])
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)
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
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)
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
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')
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')
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)
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])
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])
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)
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)
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
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)
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)
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
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])
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])
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
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])
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
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)
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
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
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))
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')
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
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')
"""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')
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')
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)
"""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]
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]
# 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)
"""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 --- #
"""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)
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') ##%%
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
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
"""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()
# # 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):
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()
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')
def test_getitem(): discr = odl.uniform_discr(0, 1, 3) elem = discr.element([1, 2, 3]) assert all_equal(elem, [1, 2, 3])
-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)
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)
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
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])
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)
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)
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()
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())