def test_init(exponent): # Validate that the different init patterns work and do not crash. space = odl.FunctionSpace(odl.Interval(0, 1)) part = odl.uniform_partition_fromintv(space.domain, 10) rn = odl.Rn(10, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent, interp='linear') # Normal discretization of unit interval with complex complex_space = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) cn = odl.Cn(10, exponent=exponent) odl.DiscreteLp(complex_space, part, cn, exponent=exponent) space = odl.FunctionSpace(odl.Rectangle([0, 0], [1, 1])) part = odl.uniform_partition_fromintv(space.domain, (10, 10)) rn = odl.Rn(100, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent, interp=['nearest', 'linear']) # Real space should not work with complex with pytest.raises(ValueError): odl.DiscreteLp(space, part, cn) # Complex space should not work with reals with pytest.raises(ValueError): odl.DiscreteLp(complex_space, part, rn) # Wrong size of underlying space rn_wrong_size = odl.Rn(20) with pytest.raises(ValueError): odl.DiscreteLp(space, part, rn_wrong_size)
def test_dspace_type_cuda(): # Plain function set -> Ntuples-like fset = odl.FunctionSet(odl.Interval(0, 1), odl.Strings(2)) assert dspace_type(fset, 'cuda') == odl.CudaNtuples assert dspace_type(fset, 'cuda', np.int) == odl.CudaNtuples # Real space rspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.RealNumbers()) assert dspace_type(rspc, 'cuda') == odl.CudaFn assert dspace_type(rspc, 'cuda', np.float64) == odl.CudaFn assert dspace_type(rspc, 'cuda', np.int) == odl.CudaFn with pytest.raises(TypeError): dspace_type(rspc, 'cuda', np.complex) with pytest.raises(TypeError): dspace_type(rspc, 'cuda', np.dtype('<U2')) # Complex space (not implemented) cspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) with pytest.raises(NotImplementedError): dspace_type(cspc, 'cuda') with pytest.raises(NotImplementedError): dspace_type(cspc, 'cuda', np.complex64) with pytest.raises(TypeError): dspace_type(cspc, 'cuda', np.float) with pytest.raises(TypeError): assert dspace_type(cspc, 'cuda', np.int)
def test_dspace_type_numpy(): # Plain function set -> Ntuples-like fset = odl.FunctionSet(odl.Interval(0, 1), odl.Strings(2)) assert dspace_type(fset, 'numpy') == odl.Ntuples, None assert dspace_type(fset, 'numpy', np.int) == odl.Ntuples # Real space rspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.RealNumbers()) assert dspace_type(rspc, 'numpy') == odl.Fn assert dspace_type(rspc, 'numpy', np.float32) == odl.Fn assert dspace_type(rspc, 'numpy', np.int) == odl.Fn with pytest.raises(TypeError): dspace_type(rspc, 'numpy', np.complex) with pytest.raises(TypeError): dspace_type(rspc, 'numpy', np.dtype('<U2')) # Complex space cspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) assert dspace_type(cspc, 'numpy') == odl.Fn assert dspace_type(cspc, 'numpy', np.complex64) == odl.Fn with pytest.raises(TypeError): dspace_type(cspc, 'numpy', np.float) with pytest.raises(TypeError): assert dspace_type(cspc, 'numpy', np.int) with pytest.raises(TypeError): dspace_type(cspc, 'numpy', np.dtype('<U2'))
def test_fspace_equality(): intv = odl.Interval(0, 1) intv2 = odl.Interval(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) fspace_intv2 = FunctionSpace(intv2) assert fspace == fspace_r assert fspace != fspace_c assert fspace != fspace_intv2
def test_fspace_vector_init(): # 1d, real intv = odl.Interval(0, 1) fspace = FunctionSpace(intv) fspace.element(func_1d_oop) fspace.element(func_1d_oop, vectorized=False) fspace.element(func_1d_oop, vectorized=True) fspace.element(func_1d_ip, vectorized=True) fspace.element(func_1d_dual, vectorized=True) # 2d, real rect = odl.Rectangle([0, 0], [1, 2]) fspace = FunctionSpace(rect) fspace.element(func_2d_novec, vectorized=False) fspace.element(func_2d_vec_oop) fspace.element(func_2d_vec_oop, vectorized=True) fspace.element(func_2d_vec_ip, vectorized=True) fspace.element(func_2d_vec_dual, vectorized=True) # 2d, complex fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) fspace.element(cfunc_2d_novec, vectorized=False) fspace.element(cfunc_2d_vec_oop) fspace.element(cfunc_2d_vec_oop, vectorized=True) fspace.element(cfunc_2d_vec_ip, vectorized=True) fspace.element(cfunc_2d_vec_dual, vectorized=True)
def make_projector(n): # 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) dgrid = odl.uniform_sampling(dparams, [n] * 2) geom = odl.tomo.CircularConeFlatGeometry(angle_intvl, dparams, src_rad, det_rad, agrid, dgrid) # X-ray transform projector = odl.tomo.XrayTransform(discr_reco_space, geom, backend='astra_cuda') phantom = projector.domain.one() projector._adjoint *= projector(phantom).inner( projector(phantom)) / phantom.inner( projector.adjoint(projector(phantom))) return 0.08 * projector
def test_nearest_interpolation_1d_complex(): intv = odl.Interval(0, 1) part = odl.uniform_partition_fromintv(intv, 5, nodes_on_bdry=False) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv, field=odl.ComplexNumbers()) dspace = odl.Cn(part.size) interp_op = NearestInterpolation(space, part, dspace) function = interp_op([0 + 1j, 1 + 2j, 2 + 3j, 3 + 4j, 4 + 5j]) # Evaluate at single point val = function(0.35) # closest to index 1 -> 1 + 2j assert val == 1.0 + 2.0j # Input array, with and without output array pts = np.array([0.4, 0.0, 0.65, 0.95]) true_arr = [1 + 2j, 0 + 1j, 3 + 4j, 4 + 5j] assert all_equal(function(pts), true_arr) # Should also work with a (1, N) array pts = pts[None, :] assert all_equal(function(pts), true_arr) out = np.empty(4, dtype='complex128') function(pts, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array # Same as array for 1d mg = sparse_meshgrid([0.4, 0.0, 0.65, 0.95]) true_mg = [1 + 2j, 0 + 1j, 3 + 4j, 4 + 5j] assert all_equal(function(mg), true_mg) function(mg, out=out) assert all_equal(out, true_mg)
def test_nearest_interpolation_1d_variants(): intv = odl.Interval(0, 1) part = odl.uniform_partition_fromintv(intv, 5, nodes_on_bdry=False) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv) dspace = odl.Rn(part.size) # 'left' variant interp_op = NearestInterpolation(space, part, dspace, variant='left') function = interp_op([0, 1, 2, 3, 4]) # Testing two midpoints and the extreme values pts = np.array([0.4, 0.8, 0.0, 1.0]) true_arr = [1, 3, 0, 4] assert all_equal(function(pts), true_arr) # 'right' variant interp_op = NearestInterpolation(space, part, dspace, variant='right') function = interp_op([0, 1, 2, 3, 4]) # Testing two midpoints and the extreme values pts = np.array([0.4, 0.8, 0.0, 1.0]) true_arr = [2, 4, 0, 4] assert all_equal(function(pts), true_arr)
def test_bwt1d(wbasis): # Verify that the operator works as axpected # 1D test n = 16 x = np.zeros(n) x[5:10] = 1 nscales = 2 # Define a discretized domain domain = odl.FunctionSpace(odl.Interval([-1], [1])) nPoints = np.array([n]) disc_domain = odl.uniform_discr_fromspace(domain, nPoints) disc_phantom = disc_domain.element(x) # Create the discrete wavelet transform operator. # Only the domain of the operator needs to be defined Wop = BiorthWaveletTransform(disc_domain, nscales, wbasis) # Compute the discrete wavelet transform of discrete imput image coeffs = Wop(disc_phantom) # Compute the inverse wavelet transform reconstruction = Wop.inverse(coeffs) # Verify that reconstructions lie in correct discretized domain assert reconstruction in disc_domain assert all_almost_equal(reconstruction.asarray(), x)
def test_fspace_astype(): rspace = FunctionSpace(odl.Interval(0, 1)) cspace = FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) rspace_s = FunctionSpace(odl.Interval(0, 1), out_dtype='float32') cspace_s = FunctionSpace(odl.Interval(0, 1), out_dtype='complex64') assert rspace.astype('complex64') == cspace_s assert rspace.astype('complex128') == cspace assert rspace.astype('complex128') is rspace._complex_space assert rspace.astype('float32') == rspace_s assert rspace.astype('float64') is rspace._real_space assert cspace.astype('float32') == rspace_s assert cspace.astype('float64') == rspace assert cspace.astype('float64') is cspace._real_space assert cspace.astype('complex64') == cspace_s assert cspace.astype('complex128') is cspace._complex_space
def test_fspace_simple_attributes(): intv = odl.Interval(0, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) assert fspace.domain == intv assert fspace.range == odl.RealNumbers() assert fspace_r.range == odl.RealNumbers() assert fspace_c.range == odl.ComplexNumbers()
def test_fspace_vector_ufunc(): intv = odl.Interval(0, 1) points = _points(intv, num=5) mg = _meshgrid(intv, shape=(5, )) fspace = FunctionSpace(intv) f_vec = fspace.element(np.sin) assert f_vec(0.5) == np.sin(0.5) assert all_equal(f_vec(points), np.sin(points.squeeze())) assert all_equal(f_vec(mg), np.sin(mg[0]))
def test_partition_init(): vec1 = np.array([2, 4, 5, 7]) vec2 = np.array([-4, -3, 0, 1, 4]) begin = [2, -5] end = [10, 4] # Simply test if code runs odl.RectPartition(odl.Rectangle(begin, end), odl.TensorGrid(vec1, vec2)) odl.RectPartition(odl.Interval(begin[0], end[0]), odl.TensorGrid(vec1)) # Degenerate dimensions should work, too vec2 = np.array([1.0]) odl.RectPartition(odl.Rectangle(begin, end), odl.TensorGrid(vec1, vec2))
def test_astra_projection_geometry(): """Create ASTRA projection geometry from geometry objects.""" with pytest.raises(TypeError): odl.tomo.astra_projection_geometry(None) apart = odl.uniform_partition(0, 2 * np.pi, 5) dpart = odl.uniform_partition(-40, 40, 10) # motion sampling grid, detector sampling grid but not RegularGrid dpart_0 = odl.RectPartition(odl.Interval(0, 0), odl.TensorGrid([0])) geom_p2d = odl.tomo.Parallel2dGeometry(apart, dpart=dpart_0) with pytest.raises(ValueError): odl.tomo.astra_projection_geometry(geom_p2d) # detector sampling grid, motion sampling grid geom_p2d = odl.tomo.Parallel2dGeometry(apart, dpart) odl.tomo.astra_projection_geometry(geom_p2d) # Parallel 2D geometry geom_p2d = odl.tomo.Parallel2dGeometry(apart, dpart) astra_geom = odl.tomo.astra_projection_geometry(geom_p2d) assert astra_geom['type'] == 'parallel' # Fan flat src_rad = 10 det_rad = 5 geom_ff = odl.tomo.FanFlatGeometry(apart, dpart, src_rad, det_rad) astra_geom = odl.tomo.astra_projection_geometry(geom_ff) assert astra_geom['type'] == 'fanflat_vec' dpart = odl.uniform_partition([-40, -3], [40, 3], (10, 5)) # Parallel 3D geometry geom_p3d = odl.tomo.Parallel3dAxisGeometry(apart, dpart) odl.tomo.astra_projection_geometry(geom_p3d) astra_geom = odl.tomo.astra_projection_geometry(geom_p3d) assert astra_geom['type'] == 'parallel3d_vec' # Circular conebeam flat geom_ccf = odl.tomo.CircularConeFlatGeometry(apart, dpart, src_rad, det_rad) astra_geom = odl.tomo.astra_projection_geometry(geom_ccf) assert astra_geom['type'] == 'cone_vec' # Helical conebeam flat pitch = 1 geom_hcf = odl.tomo.HelicalConeFlatGeometry(apart, dpart, src_rad, det_rad, pitch) astra_geom = odl.tomo.astra_projection_geometry(geom_hcf) assert astra_geom['type'] == 'cone_vec'
def test_proj(): # `DiscreteLp` volume space vol_shape = (100,) * 3 discr_vol_space = odl.uniform_discr([-50] * 3, [50] * 3, vol_shape, dtype='float32') # Angles: 0 and pi/2 angle_intvl = odl.Interval(0, np.pi / 2) angle_grid = odl.uniform_sampling(angle_intvl, 2, as_midp=False) # agrid = angle_grid.points() / np.pi # Detector dparams = odl.Rectangle([-50] * 2, [50] * 2) det_grid = odl.uniform_sampling(dparams, (100, 100)) def projector(index): axis = np.roll(np.array([1, 0, 0]), index) axis2 = np.roll(axis, 1) geom = odl.tomo.Parallel3dGeometry(angle_intvl, dparams, angle_grid, det_grid, axis=axis, origin_to_det=axis2) # Projection space proj_space = odl.FunctionSpace(geom.params) discr_data = odl.util.phantom.indicate_proj_axis(discr_vol_space, 0.5) # `DiscreteLp` projection space proj_shape = geom.grid.shape discr_proj_space = odl.uniform_discr_fromspace(proj_space, proj_shape, dtype='float32') # Forward proj_data = odl.tomo.astra_cuda_forward_projector( discr_data, geom, discr_proj_space) return proj_data proj_data = projector(0) proj_data.show(indices=(0, np.s_[:], np.s_[:])) proj_data.show(indices=(1, np.s_[:], np.s_[:])) proj_data = projector(1) proj_data.show(indices=(0, np.s_[:], np.s_[:])) proj_data.show(indices=(1, np.s_[:], np.s_[:])) proj_data = projector(2) proj_data.show(indices=(0, np.s_[:], np.s_[:])) proj_data.show(indices=(1, np.s_[:], np.s_[:])) plt.show(block=True)
def test_fspace_vector_copy(): fspace = FunctionSpace(odl.Interval(0, 1)) f_novec = fspace.element(func_1d_oop, vectorized=False) f_vec_ip = fspace.element(func_1d_ip, vectorized=True) f_vec_dual = fspace.element(func_1d_dual, vectorized=True) f_out = f_novec.copy() assert f_out == f_novec f_out = f_vec_ip.copy() assert f_out == f_vec_ip f_out = f_vec_dual.copy() assert f_out == f_vec_dual
def test_fwd_diff(): # Continuous definition of problem space = odl.FunctionSpace(odl.Interval(0, 1)) # Discretization n = 6 d = odl.uniform_discr(space, n, impl='cuda') fun = d.element([1, 2, 5, 3, 2, 1]) # Create operator diff = ForwardDiff(d) assert all_almost_equal(diff(fun), [0, 3, -2, -1, -1, 0]) assert all_almost_equal(diff.adjoint(fun), [0, -1, -3, 2, 1, 0]) assert all_almost_equal(diff.adjoint(diff(fun)), [0, -3, 5, -1, 0, 0])
def test_norm_interval(exponent): # Test the function f(x) = x^2 on the interval (0, 1). Its # L^p-norm is (1 + 2*p)^(-1/p) for finite p and 1 for p=inf p = exponent fspace = odl.FunctionSpace(odl.Interval(0, 1)) lpdiscr = odl.uniform_discr_fromspace(fspace, 10, exponent=p) testfunc = fspace.element(lambda x: x ** 2) discr_testfunc = lpdiscr.element(testfunc) if p == float('inf'): assert discr_testfunc.norm() <= 1 # Max at boundary not hit else: true_norm = (1 + 2 * p) ** (-1 / p) assert almost_equal(discr_testfunc.norm(), true_norm, places=2)
def test_linear_interpolation_1d(): intv = odl.Interval(0, 1) part = odl.uniform_partition_fromintv(intv, 5, nodes_on_bdry=False) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv) dspace = odl.Rn(part.size) interp_op = LinearInterpolation(space, part, dspace) function = interp_op([1, 2, 3, 4, 5]) # Evaluate at single point val = function(0.35) true_val = 0.75 * 2 + 0.25 * 3 assert almost_equal(val, true_val) # Input array, with and without output array pts = np.array([0.4, 0.0, 0.65, 0.95]) true_arr = [2.5, 0.5, 3.75, 3.75] assert all_almost_equal(function(pts), true_arr)
def test_fspace_init(): intv = odl.Interval(0, 1) FunctionSpace(intv) FunctionSpace(intv, field=odl.RealNumbers()) FunctionSpace(intv, field=odl.ComplexNumbers()) rect = odl.Rectangle([0, 0], [1, 2]) FunctionSpace(rect) FunctionSpace(rect, field=odl.RealNumbers()) FunctionSpace(rect, field=odl.ComplexNumbers()) cube = odl.Cuboid([0, 0, 0], [1, 2, 3]) FunctionSpace(cube) FunctionSpace(cube, field=odl.RealNumbers()) FunctionSpace(cube, field=odl.ComplexNumbers()) ndbox = odl.IntervalProd([0] * 10, np.arange(1, 11)) FunctionSpace(ndbox) FunctionSpace(ndbox, field=odl.RealNumbers()) FunctionSpace(ndbox, field=odl.ComplexNumbers())
def test_yzproj(): # `DiscreteLp` volume space vol_shape = (100,) * 3 discr_vol_space = odl.uniform_discr([-50] * 3, [50] * 3, vol_shape, dtype='float32') # Angles: 0 and pi/2 angle_intvl = odl.Interval(0, np.pi / 2) angle_grid = odl.uniform_sampling(angle_intvl, 2, as_midp=False) # agrid = angle_grid.points() / np.pi # Detector dparams = odl.Rectangle([-50] * 2, [50] * 2) det_grid = odl.uniform_sampling(dparams, (100, 100)) axis = (0, 1, 0) origin_to_det = (0, 0, 1) geom = odl.tomo.Parallel3dGeometry(angle_intvl, dparams, angle_grid, det_grid, axis=axis, origin_to_det=origin_to_det) # Projection space proj_space = odl.FunctionSpace(geom.params) discr_data = odl.util.phantom.indicate_proj_axis(discr_vol_space, 0.5) # `DiscreteLp` projection space proj_shape = geom.grid.shape discr_proj_space = odl.uniform_discr_fromspace(proj_space, proj_shape, dtype='float32') # Forward proj_data = odl.tomo.astra_cuda_forward_projector(discr_data, geom, discr_proj_space) plt.switch_backend('qt4agg') proj_data.show(indices=np.s_[0, :, :]) plt.show()
scale1.lincomb(1, scale1, I * mu1(E), tmp) return odl.ReductionOperator(odl.MultiplyOperator(scale0), odl.MultiplyOperator(scale1)) 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) dgrid = odl.uniform_sampling(dparams, [n]*2) geom = odl.tomo.CircularConeFlatGeometry(angle_intvl, dparams, src_rad, det_rad, agrid, dgrid) # X-ray transform proj = odl.tomo.DiscreteXrayTransform(discr_reco_space, geom, backend='astra_cuda') # Create phantom phantom0 = odl.util.shepp_logan(discr_reco_space, True) phantom1 = odl.util.derenzo_sources(discr_reco_space)
super().__init__(self.space, self.space, linear=True) def _call(self, rhs, out): ndimage.convolve(rhs.ntuple.data, self.kernel.ntuple.data, output=out.ntuple.data, mode='wrap') @property def adjoint(self): return Convolution(self.adjkernel, self.kernel) def opnorm(self): return self.norm # Continuous definition of the problem cont_space = odl.FunctionSpace(odl.Interval(0, 10)) # Complicated functions to check performance cont_kernel = cont_space.element(lambda x: np.exp(x / 2) * np.cos(x * 1.172)) cont_phantom = cont_space.element(lambda x: x ** 2 * np.sin(x) ** 2 * (x > 5)) # Discretization discr_space = odl.uniform_discr_fromspace(cont_space, 500, impl='numpy') kernel = discr_space.element(cont_kernel) phantom = discr_space.element(cont_phantom) # Create operator conv = Convolution(kernel) # Dampening parameter for landweber iterations = 100
def test_dwt(): # Verify that the operator works as axpected # 1D test n = 16 x = np.zeros(n) x[5:10] = 1 wbasis = pywt.Wavelet('db1') nscales = 2 mode = 'sym' size_list = coeff_size_list((n,), nscales, wbasis, mode) # Define a discretized domain domain = odl.FunctionSpace(odl.Interval([-1], [1])) nPoints = np.array([n]) disc_domain = odl.uniform_discr_fromspace(domain, nPoints) disc_phantom = disc_domain.element(x) # Create the discrete wavelet transform operator. # Only the domain of the operator needs to be defined Wop = WaveletTransform(disc_domain, nscales, wbasis, mode) # Compute the discrete wavelet transform of discrete imput image coeffs = Wop(disc_phantom) # Determine the correct range for Wop and verify that coeffs # is an element of it ran_size = np.prod(size_list[0]) ran_size += sum(np.prod(shape) for shape in size_list[1:-1]) disc_range = disc_domain.dspace_type(ran_size, dtype=disc_domain.dtype) assert coeffs in disc_range # Compute the inverse wavelet transform reconstruction1 = Wop.inverse(coeffs) # With othogonal wavelets the inverse is the adjoint reconstruction2 = Wop.adjoint(coeffs) # Verify that the output of Wop.inverse and Wop.adjoint are the same assert all_almost_equal(reconstruction1.asarray(), reconstruction2.asarray()) # Verify that reconstructions lie in correct discretized domain assert reconstruction1 in disc_domain assert reconstruction2 in disc_domain assert all_almost_equal(reconstruction1.asarray(), x) assert all_almost_equal(reconstruction2.asarray(), x) # --------------------------------------------------------------- # 2D test n = 16 x = np.zeros((n, n)) x[5:10, 5:10] = 1 wbasis = pywt.Wavelet('db1') nscales = 2 mode = 'sym' size_list = coeff_size_list((n, n), nscales, wbasis, mode) # Define a discretized domain domain = odl.FunctionSpace(odl.Rectangle([-1, -1], [1, 1])) nPoints = np.array([n, n]) disc_domain = odl.uniform_discr_fromspace(domain, nPoints) disc_phantom = disc_domain.element(x) # Create the discrete wavelet transform operator. # Only the domain of the operator needs to be defined Wop = WaveletTransform(disc_domain, nscales, wbasis, mode) # Compute the discrete wavelet transform of discrete imput image coeffs = Wop(disc_phantom) # Determine the correct range for Wop and verify that coeffs # is an element of it ran_size = np.prod(size_list[0]) ran_size += sum(3 * np.prod(shape) for shape in size_list[1:-1]) disc_range = disc_domain.dspace_type(ran_size, dtype=disc_domain.dtype) assert coeffs in disc_range # Compute the inverse wavelet transform reconstruction1 = Wop.inverse(coeffs) # With othogonal wavelets the inverse is the adjoint reconstruction2 = Wop.adjoint(coeffs) # Verify that the output of Wop.inverse and Wop.adjoint are the same assert all_almost_equal(reconstruction1.asarray(), reconstruction2.asarray()) # Verify that reconstructions lie in correct discretized domain assert reconstruction1 in disc_domain assert reconstruction2 in disc_domain assert all_almost_equal(reconstruction1.asarray(), x) assert all_almost_equal(reconstruction2.asarray(), x) # ------------------------------------------------------------- # 3D test n = 16 x = np.zeros((n, n, n)) x[5:10, 5:10, 5:10] = 1 wbasis = pywt.Wavelet('db2') nscales = 1 mode = 'per' size_list = coeff_size_list((n, n, n), nscales, wbasis, mode) # Define a discretized domain domain = odl.FunctionSpace(odl.Cuboid([-1, -1, -1], [1, 1, 1])) nPoints = np.array([n, n, n]) disc_domain = odl.uniform_discr_fromspace(domain, nPoints) disc_phantom = disc_domain.element(x) # Create the discrete wavelet transform operator related to 3D transform. Wop = WaveletTransform(disc_domain, nscales, wbasis, mode) # Compute the discrete wavelet transform of discrete imput image coeffs = Wop(disc_phantom) # Determine the correct range for Wop and verify that coeffs # is an element of it ran_size = np.prod(size_list[0]) ran_size += sum(7 * np.prod(shape) for shape in size_list[1:-1]) disc_range = disc_domain.dspace_type(ran_size, dtype=disc_domain.dtype) assert coeffs in disc_range # Compute the inverse wavelet transform reconstruction1 = Wop.inverse(coeffs) # With othogonal wavelets the inverse is the adjoint reconstruction2 = Wop.adjoint(coeffs) # Verify that the output of Wop.inverse and Wop.adjoint are the same assert all_almost_equal(reconstruction1, reconstruction2) # Verify that reconstructions lie in correct discretized domain assert reconstruction1 in disc_domain assert reconstruction2 in disc_domain assert all_almost_equal(reconstruction1.asarray(), x) assert all_almost_equal(reconstruction2, disc_phantom)
def test_init_cuda(exponent): # Normal discretization of unit interval space = odl.FunctionSpace(odl.Interval(0, 1), out_dtype='float32') part = odl.uniform_partition_fromintv(space.domain, 10) rn = odl.CudaRn(10, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent)
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 projector(request): n_angles = 200 geom, impl, angle = request.param.split() if angle == 'uniform': apart = odl.uniform_partition(0, 2 * np.pi, n_angles) elif angle == 'random': # Linearly spaced with random noise min_pt = 2 * (2.0 * np.pi) / n_angles max_pt = (2.0 * np.pi) - 2 * (2.0 * np.pi) / n_angles points = np.linspace(min_pt, max_pt, n_angles) points += np.random.rand(n_angles) * (max_pt - min_pt) / (5 * n_angles) agrid = odl.TensorGrid(points) apart = odl.RectPartition(odl.Interval(0, 2 * np.pi), agrid) elif angle == 'nonuniform': # Angles spaced quadratically min_pt = 2 * (2.0 * np.pi) / n_angles max_pt = (2.0 * np.pi) - 2 * (2.0 * np.pi) / n_angles points = np.linspace(min_pt**0.5, max_pt**0.5, n_angles)**2 agrid = odl.TensorGrid(points) apart = odl.RectPartition(odl.Interval(0, 2 * np.pi), agrid) else: raise ValueError('angle not valid') if geom == 'par2d': # Discrete reconstruction space discr_reco_space = odl.uniform_discr([-20, -20], [20, 20], [100, 100], dtype='float32') # Geometry dpart = odl.uniform_partition(-30, 30, 200) geom = tomo.Parallel2dGeometry(apart, dpart) # Ray transform return tomo.RayTransform(discr_reco_space, geom, impl=impl) elif geom == 'par3d': # Discrete reconstruction space discr_reco_space = odl.uniform_discr([-20, -20, -20], [20, 20, 20], [100, 100, 100], dtype='float32') # Geometry dpart = odl.uniform_partition([-30, -30], [30, 30], [200, 200]) geom = tomo.Parallel3dAxisGeometry(apart, dpart, axis=[1, 0, 0]) # Ray transform return tomo.RayTransform(discr_reco_space, geom, impl=impl) elif geom == 'cone2d': # Discrete reconstruction space discr_reco_space = odl.uniform_discr([-20, -20], [20, 20], [100, 100], dtype='float32') # Geometry dpart = odl.uniform_partition(-30, 30, 200) geom = tomo.FanFlatGeometry(apart, dpart, src_radius=200, det_radius=100) # Ray transform return tomo.RayTransform(discr_reco_space, geom, impl=impl) elif geom == 'cone3d': # Discrete reconstruction space discr_reco_space = odl.uniform_discr([-20, -20, -20], [20, 20, 20], [100, 100, 100], dtype='float32') # Geometry dpart = odl.uniform_partition([-30, -30], [30, 30], [200, 200]) geom = tomo.CircularConeFlatGeometry(apart, dpart, src_radius=200, det_radius=100, axis=[1, 0, 0]) # Ray transform return tomo.RayTransform(discr_reco_space, geom, impl=impl) elif geom == 'helical': # Discrete reconstruction space discr_reco_space = odl.uniform_discr([-20, -20, 0], [20, 20, 40], [100, 100, 100], dtype='float32') # Geometry # TODO: angles n_angle = 700 apart = odl.uniform_partition(0, 8 * 2 * np.pi, n_angle) dpart = odl.uniform_partition([-30, -3], [30, 3], [200, 20]) geom = tomo.HelicalConeFlatGeometry(apart, dpart, pitch=5.0, src_radius=200, det_radius=100) # Ray transform return tomo.RayTransform(discr_reco_space, geom, impl=impl) else: raise ValueError('param not valid')
plt.close() # Create `DiscreteLp` space for volume data vol_shape = (100, 110) discr_vol_space = odl.uniform_discr([-1, -1.1], [1, 1.1], vol_shape, dtype='float32') # Create an element in the volume space discr_vol_data = odl.util.phantom.cuboid(discr_vol_space, 0.2, 0.3) save_slice(discr_vol_data, 'phantom 2d cpu') # Angles angle_intvl = odl.Interval(0, 2 * np.pi) angle_grid = odl.uniform_sampling(angle_intvl, 180) # Detector dparams = odl.Interval(-2, 2) det_grid = odl.uniform_sampling(dparams, 100) # Create geometry instances for the projection space parameter geom = odl.tomo.Parallel2dGeometry(angle_intvl, dparams, angle_grid, det_grid) # Projection space proj_space = odl.FunctionSpace(geom.params) # `DiscreteLp` projection space discr_proj_space = odl.uniform_discr_fromspace(proj_space, geom.grid.shape,