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_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_nearest_interpolation_2d_string(): rect = odl.Rectangle([0, 0], [1, 1]) grid = odl.uniform_sampling(rect, [4, 2], as_midp=True) # Coordinate vectors are: # [0.125, 0.375, 0.625, 0.875], [0.25, 0.75] space = odl.FunctionSet(rect, odl.Strings(1)) dspace = odl.Ntuples(grid.ntotal, dtype='U1') interp_op = NearestInterpolation(space, grid, dspace) values = np.array([c for c in 'mystring']) function = interp_op(values) # Evaluate at single point val = function([0.3, 0.6]) # closest to index (1, 1) -> 3 assert val == 't' # Input array, with and without output array pts = np.array([[0.3, 0.6], [1.0, 1.0]]) true_arr = ['t', 'g'] assert all_equal(function(pts.T), true_arr) out = np.empty(2, dtype='U1') function(pts.T, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array mg = sparse_meshgrid([0.3, 1.0], [0.4, 1.0]) # Indices: (1, 3) x (0, 1) true_mg = [['s', 't'], ['n', 'g']] assert all_equal(function(mg), true_mg) out = np.empty((2, 2), dtype='U1') function(mg, out=out) assert all_equal(out, true_mg)
def test_init(exponent): # Validate that the different init patterns work and do not crash. space = odl.FunctionSpace(odl.Interval(0, 1)) grid = odl.uniform_sampling(space.domain, 10) rn = odl.Rn(10, exponent=exponent) odl.DiscreteLp(space, grid, rn, exponent=exponent) # 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, grid, cn, exponent=exponent) # Real space should not work with complex with pytest.raises(ValueError): odl.DiscreteLp(space, grid, cn) # Complex space should not work with reals with pytest.raises(ValueError): odl.DiscreteLp(complex_space, grid, rn) # Wrong size of underlying space rn_wrong_size = odl.Rn(20) with pytest.raises(ValueError): odl.DiscreteLp(space, grid, rn_wrong_size)
def test_collocation_interpolation_identity(): # Check if interpolation followed by collocation on the same grid # is the identity rect = odl.Rectangle([0, 0], [1, 1]) grid = odl.uniform_sampling(rect, [4, 2], as_midp=True) space = odl.FunctionSpace(rect) dspace = odl.Rn(grid.ntotal) # Testing 'C' and 'F' ordering and all interpolation schemes coll_op_c = GridCollocation(space, grid, dspace, order='C') coll_op_f = GridCollocation(space, grid, dspace, order='F') interp_ops_c = [ NearestInterpolation(space, grid, dspace, order='C', variant='left'), NearestInterpolation(space, grid, dspace, order='C', variant='right'), LinearInterpolation(space, grid, dspace, order='C'), PerAxisInterpolation(space, grid, dspace, order='C', schemes=['linear', 'nearest'])] interp_ops_f = [ NearestInterpolation(space, grid, dspace, order='F', variant='left'), NearestInterpolation(space, grid, dspace, order='F', variant='right'), LinearInterpolation(space, grid, dspace, order='F'), PerAxisInterpolation(space, grid, dspace, order='F', schemes=['linear', 'nearest'])] values = np.arange(1, 9, dtype='float64') for interp_op_c in interp_ops_c: ident_values = coll_op_c(interp_op_c(values)) assert all_almost_equal(ident_values, values) for interp_op_f in interp_ops_f: ident_values = coll_op_f(interp_op_f(values)) assert all_almost_equal(ident_values, values)
def test_nearest_interpolation_1d_complex(): intv = odl.Interval(0, 1) grid = odl.uniform_sampling(intv, 5, as_midp=True) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv, field=odl.ComplexNumbers()) dspace = odl.Cn(grid.ntotal) interp_op = NearestInterpolation(space, grid, 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) grid = odl.uniform_sampling(intv, 5, as_midp=True) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv) dspace = odl.Rn(grid.ntotal) # 'left' variant interp_op = NearestInterpolation(space, grid, 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, grid, 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_nearest_interpolation_2d_float(): rect = odl.Rectangle([0, 0], [1, 1]) grid = odl.uniform_sampling(rect, [4, 2], as_midp=True) # Coordinate vectors are: # [0.125, 0.375, 0.625, 0.875], [0.25, 0.75] space = odl.FunctionSpace(rect) dspace = odl.Rn(grid.ntotal) interp_op = NearestInterpolation(space, grid, dspace) function = interp_op([0, 1, 2, 3, 4, 5, 6, 7]) # Evaluate at single point val = function([0.3, 0.6]) # closest to index (1, 1) -> 3 assert val == 3.0 # Input array, with and without output array pts = np.array([[0.3, 0.6], [1.0, 1.0]]) true_arr = [3, 7] assert all_equal(function(pts.T), true_arr) out = np.empty(2, dtype='float64') function(pts.T, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array mg = sparse_meshgrid([0.3, 1.0], [0.4, 1.0]) # Indices: (1, 3) x (0, 1) true_mg = [[2, 3], [6, 7]] assert all_equal(function(mg), true_mg) out = np.empty((2, 2), dtype='float64') function(mg, out=out) assert all_equal(out, true_mg)
def test_reciprocal_grid_nd_halfcomplex(): grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5)) s = grid.stride n = np.array(grid.shape) stride_last = 2 * np.pi / (s[-1] * n[-1]) n[-1] = n[-1] // 2 + 1 # Without shift rgrid = reciprocal_grid(grid, shift=False, halfcomplex=True) assert all_equal(rgrid.shape, n) assert rgrid.max_pt[-1] == 0 # last dim is odd # With shift rgrid = reciprocal_grid(grid, shift=True, halfcomplex=True) assert all_equal(rgrid.shape, n) assert rgrid.max_pt[-1] == -stride_last / 2 # Inverting should give back the original irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=True, halfcx_parity='odd') assert irgrid.approx_equals(grid, atol=1e-6) with pytest.raises(ValueError): realspace_grid(rgrid, grid.min_pt, halfcomplex=True, halfcx_parity='+')
def test_reciprocal_grid_nd_axes(): grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5)) s = grid.stride n = np.array(grid.shape) axes_list = [[1, -1], [0], 0, [0, 2, 1], [2, 0]] for axes in axes_list: active = np.zeros(grid.ndim, dtype=bool) active[axes] = True inactive = np.logical_not(active) true_recip_stride = np.empty(grid.ndim) true_recip_stride[active] = 2 * np.pi / (s[active] * n[active]) true_recip_stride[inactive] = s[inactive] # Without shift altogether rgrid = reciprocal_grid(grid, shift=False, axes=axes, halfcomplex=False) assert all_equal(rgrid.shape, n) assert all_almost_equal(rgrid.stride, true_recip_stride) assert all_almost_equal(rgrid.min_pt[active], -rgrid.max_pt[active]) assert all_equal(rgrid.min_pt[inactive], grid.min_pt[inactive]) assert all_equal(rgrid.max_pt[inactive], grid.max_pt[inactive]) # Inverting should give back the original irgrid = realspace_grid(rgrid, grid.min_pt, axes=axes, halfcomplex=False) assert irgrid.approx_equals(grid, atol=1e-6)
def test_per_axis_interpolation(): rect = odl.Rectangle([0, 0], [1, 1]) grid = odl.uniform_sampling(rect, [4, 2], as_midp=True) # Coordinate vectors are: # [0.125, 0.375, 0.625, 0.875], [0.25, 0.75] space = odl.FunctionSpace(rect) dspace = odl.Rn(grid.ntotal) schemes = ['linear', 'nearest'] variants = [None, 'right'] interp_op = PerAxisInterpolation(space, grid, dspace, schemes=schemes, nn_variants=variants) values = np.arange(1, 9, dtype='float64') function = interp_op(values) rvals = values.reshape([4, 2]) # Evaluate at single point val = function([0.3, 0.5]) l1 = (0.3 - 0.125) / (0.375 - 0.125) # 0.5 equally far from both neighbors -> 'right' chooses 0.75 true_val = (1 - l1) * rvals[0, 1] + l1 * rvals[1, 1] assert almost_equal(val, true_val) # Input array, with and without output array pts = np.array([[0.3, 0.6], [0.1, 0.25], [1.0, 1.0]]) l1 = (0.3 - 0.125) / (0.375 - 0.125) true_val_1 = (1 - l1) * rvals[0, 1] + l1 * rvals[1, 1] l1 = (0.125 - 0.1) / (0.375 - 0.125) true_val_2 = (1 - l1) * rvals[0, 0] # only lower left contributes l1 = (1.0 - 0.875) / (0.875 - 0.625) true_val_3 = (1 - l1) * rvals[3, 1] # lower left only true_arr = [true_val_1, true_val_2, true_val_3] assert all_equal(function(pts.T), true_arr) out = np.empty(3, dtype='float64') function(pts.T, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array mg = sparse_meshgrid([0.3, 1.0], [0.4, 0.85]) # Indices: (1, 3) x (0, 1) lx1 = (0.3 - 0.125) / (0.375 - 0.125) lx2 = (1.0 - 0.875) / (0.875 - 0.625) true_val_11 = (1 - lx1) * rvals[0, 0] + lx1 * rvals[1, 0] true_val_12 = ((1 - lx1) * rvals[0, 1] + lx1 * rvals[1, 1]) true_val_21 = (1 - lx2) * rvals[3, 0] true_val_22 = (1 - lx2) * rvals[3, 1] true_mg = [[true_val_11, true_val_12], [true_val_21, true_val_22]] assert all_equal(function(mg), true_mg) out = np.empty((2, 2), dtype='float64') function(mg, out=out) assert all_equal(out, true_mg)
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()
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_reciprocal_grid_1d(halfcomplex, shift, parity): shape = 10 if parity == 'even' else 11 grid = odl.uniform_sampling(0, 1, shape=shape) s = grid.stride n = np.array(grid.shape) rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=halfcomplex) # Independent of halfcomplex, shift and parity true_recip_stride = 2 * np.pi / (s * n) assert all_almost_equal(rgrid.stride, true_recip_stride) if halfcomplex: assert all_equal(rgrid.shape, n // 2 + 1) if parity == 'odd' and shift: # Max point should be half a negative recip stride assert all_almost_equal(rgrid.max_pt, -true_recip_stride / 2) elif parity == 'even' and not shift: # Max point should be half a positive recip stride assert all_almost_equal(rgrid.max_pt, true_recip_stride / 2) elif (parity == 'odd' and not shift) or (parity == 'even' and shift): # Max should be zero assert all_almost_equal(rgrid.max_pt, 0) else: raise RuntimeError('parameter combination not covered') else: # halfcomplex = False assert all_equal(rgrid.shape, n) if (parity == 'even' and shift) or (parity == 'odd' and not shift): # Zero should be at index n // 2 assert all_almost_equal(rgrid[n // 2], 0) elif (parity == 'odd' and shift) or (parity == 'even' and not shift): # No point should be closer to 0 than half a recip stride atol = 0.999 * true_recip_stride / 2 assert not rgrid.approx_contains(0, atol=atol) else: raise RuntimeError('parameter combination not covered') if not shift: # Grid Should be symmetric assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt) if parity == 'odd': # Midpoint should be 0 assert all_almost_equal(rgrid.mid_pt, 0) # Inverting should give back the original irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=halfcomplex, halfcx_parity=parity) assert irgrid.approx_equals(grid, atol=1e-6)
def test_reciprocal_grid_nd(): grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5)) s = grid.stride n = np.array(grid.shape) true_recip_stride = 2 * np.pi / (s * n) # Without shift altogether rgrid = reciprocal_grid(grid, shift=False, halfcomplex=False) assert all_equal(rgrid.shape, n) assert all_almost_equal(rgrid.stride, true_recip_stride) assert all_almost_equal(rgrid.min_pt, -rgrid.max_pt) # Inverting should give back the original irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False) assert irgrid.approx_equals(grid, atol=1e-6)
def test_linear_interpolation_1d(): intv = odl.Interval(0, 1) grid = odl.uniform_sampling(intv, 5, as_midp=True) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv) dspace = odl.Rn(grid.ntotal) interp_op = LinearInterpolation(space, grid, 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_reciprocal_grid_nd_shift_list(): grid = odl.uniform_sampling([0] * 3, [1] * 3, shape=(3, 4, 5)) s = grid.stride n = np.array(grid.shape) shift = [False, True, False] true_recip_stride = 2 * np.pi / (s * n) # Shift only the even dimension, then zero must be contained rgrid = reciprocal_grid(grid, shift=shift, halfcomplex=False) noshift = np.where(np.logical_not(shift)) assert all_equal(rgrid.shape, n) assert all_almost_equal(rgrid.stride, true_recip_stride) assert all_almost_equal(rgrid.min_pt[noshift], -rgrid.max_pt[noshift]) assert all_almost_equal(rgrid[n // 2], [0] * 3) # Inverting should give back the original irgrid = realspace_grid(rgrid, grid.min_pt, halfcomplex=False) assert irgrid.approx_equals(grid, atol=1e-6)
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) # Adjoint currently bugged, needs to be fixed
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, dtype='float32',
# vpts = 5 xx = 5.5 vpts = 11 # xx = 5.25 # vpts = 21 # xx = 8 # vpts = 16 # xx = 6 # vpts = 6 discr_vol_space_2d = odl.uniform_discr([-xx] * 2, [xx] * 2, [vpts] * 2, dtype='float32') discr_vol_space_3d = odl.uniform_discr([-xx] * 3, [xx] * 3, [vpts] * 3, dtype='float32') # Angle grid agrid = odl.uniform_sampling(-.25 * np.pi, 0.75 * np.pi, 2) astride = float(agrid.stride) num_angle = agrid.size # Detector grid # dx = 11 # dpts = 11 dx = 10.5 dpts = 21 # dx = 5.5 # dpts = 11 # dx = 5.25 # dpts = 21 dgrid_2d = odl.uniform_sampling(-dx, dx, dpts) dy = 1.0 * dx dgrid_3d = odl.uniform_sampling([-dx, -dy], [dx, dy], [dpts] * 2)
def test_init_cuda(exponent): # Normal discretization of unit interval space = odl.FunctionSpace(odl.Interval(0, 1)) grid = odl.uniform_sampling(space.domain, 10) rn = odl.CudaRn(10, exponent=exponent) odl.DiscreteLp(space, grid, rn, exponent=exponent)
def numba_example(): # Some functions are not easily vectorized, here we can use Numba to # improve performance. # See http://numba.pydata.org/ try: import numba except ImportError: print('Numba not installed, skipping.') return def myfunc(x): """Return x - y if x > y, otherwise return x + y.""" if x[0] > x[1]: return x[0] - x[1] else: return x[0] + x[1] # Numba expects functions f(x1, x2, x3, ...), while we have the # convention f(x) with x = (x1, x2, x3, ...). Therefore we need # to wrap the Numba-vectorized function. vectorized = numba.vectorize(lambda x, y: x - y if x > y else x + y) def myfunc_vec(x): """Return x - y if x > y, otherwise return x + y.""" return vectorized(x[0], x[1]) def myfunc_native_vec(x): """Return x - y if x > y, otherwise return x + y.""" # This implementation uses Numpy's fast built-in vectorization # directly. The function np.where checks the condition in the # first argument and takes the values from the second argument # for all entries where the condition is `True`, otherwise # the values from the third argument are taken. The arrays are # automatically broadcast, i.e. the broadcast shape of the # condition expression determines the output shape. return np.where(x[0] > x[1], x[0] - x[1], x[0] + x[1]) # Create (continuous) functions in the space of function defined # on the rectangle [0, 1] x [0, 1]. fspace = odl.FunctionSpace(odl.Rectangle([0, 0], [1, 1])) f_default = fspace.element(myfunc, vectorized=False) f_numba = fspace.element(myfunc_vec) f_native = fspace.element(myfunc_native_vec, vectorized=True) # Create a unform grid in [0, 1] x [0, 1] (fspace.domain) with 2000 # samples per dimension. grid = odl.uniform_sampling(fspace.domain, [2000, 2000]) # The points() method really creates all grid points (2000^2) and # stores them one-by-one (row-wise) in a large array with shape # (2000*2000, 2). Since the function expects points[i] to be the # array of i-th components of all points, we need to transpose. points = grid.points().T # The meshgrid property only returns a sparse representation of the # grid, a tuple whose i-th entry is the vector of all possible i-th # components in the grid (2000). Extra dimensions are added to the # vector in order to support automatic broadcasting. This is both # faster and more memory-friendly than creating the full point array. # See the numpy.meshgrid function for more information. mesh = grid.meshgrid # Returns a sparse meshgrid (2000 * 2) print('Non-Vectorized runtime (points): {:5f}' ''.format(timeit.timeit(lambda: f_default(points), number=1))) print('Non-Vectorized runtime (meshgrid): {:5f}' ''.format(timeit.timeit(lambda: f_default(mesh), number=1))) print('Numba vectorized runtime (points): {:5f}' ''.format(timeit.timeit(lambda: f_numba(points), number=1))) print('Numba vectorized runtime (meshgrid): {:5f}' ''.format(timeit.timeit(lambda: f_numba(mesh), number=1))) print('Native vectorized runtime (points): {:5f}' ''.format(timeit.timeit(lambda: f_native(points), number=1))) print('Native vectorized runtime (meshgrid): {:5f}' ''.format(timeit.timeit(lambda: f_native(mesh), number=1)))
indices=[slice(None), y, slice(None)]) data.show('imshow', saveto=pth.join(path, '{}_x{:03d}.png'.format( name.replace(' ', '_'), x)), title='{} [{},:,:]'.format(name, x), indices=[x, slice(None), slice(None)]) plt.close('all') # `DiscreteLp` volume space vol_shape = (80, 70, 60) discr_vol_space = odl.uniform_discr([-40, -35, -30], [40, 35, 30], vol_shape, dtype='float32') # Angles angle_intvl = odl.Interval(0, 2 * np.pi) angle_grid = odl.uniform_sampling(angle_intvl, 90, as_midp=False) # Detector dparams = odl.Rectangle([-50, -45], [50, 45]) det_grid = odl.uniform_sampling(dparams, (100, 90)) # Cone beam parameter src_rad = 1000 det_rad = 10 pitch_factor = 0 # Create an element in the volume space # discr_data = odl.util.phantom.cuboid(discr_vol_space, # (0.1, 0.15, 0.2,), (0.4, 0.35, 0.3)) discr_data = odl.util.phantom.indicate_proj_axis(discr_vol_space) sli = 0.5
def test_linear_interpolation_2d(): rect = odl.Rectangle([0, 0], [1, 1]) grid = odl.uniform_sampling(rect, [4, 2], as_midp=True) # Coordinate vectors are: # [0.125, 0.375, 0.625, 0.875], [0.25, 0.75] space = odl.FunctionSpace(rect) dspace = odl.Rn(grid.ntotal) interp_op = LinearInterpolation(space, grid, dspace) values = np.arange(1, 9, dtype='float64') function = interp_op(values) rvals = values.reshape([4, 2]) # Evaluate at single point val = function([0.3, 0.6]) l1 = (0.3 - 0.125) / (0.375 - 0.125) l2 = (0.6 - 0.25) / (0.75 - 0.25) true_val = ((1 - l1) * (1 - l2) * rvals[0, 0] + (1 - l1) * l2 * rvals[0, 1] + l1 * (1 - l2) * rvals[1, 0] + l1 * l2 * rvals[1, 1]) assert almost_equal(val, true_val) # Input array, with and without output array pts = np.array([[0.3, 0.6], [0.1, 0.25], [1.0, 1.0]]) l1 = (0.3 - 0.125) / (0.375 - 0.125) l2 = (0.6 - 0.25) / (0.75 - 0.25) true_val_1 = ((1 - l1) * (1 - l2) * rvals[0, 0] + (1 - l1) * l2 * rvals[0, 1] + l1 * (1 - l2) * rvals[1, 0] + l1 * l2 * rvals[1, 1]) l1 = (0.125 - 0.1) / (0.375 - 0.125) # l2 = 0 true_val_2 = (1 - l1) * rvals[0, 0] # only lower left contributes l1 = (1.0 - 0.875) / (0.875 - 0.625) l2 = (1.0 - 0.75) / (0.75 - 0.25) true_val_3 = (1 - l1) * (1 - l2) * rvals[3, 1] # lower left only true_arr = [true_val_1, true_val_2, true_val_3] assert all_equal(function(pts.T), true_arr) out = np.empty(3, dtype='float64') function(pts.T, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array mg = sparse_meshgrid([0.3, 1.0], [0.4, 0.75]) # Indices: (1, 3) x (0, 1) lx1 = (0.3 - 0.125) / (0.375 - 0.125) lx2 = (1.0 - 0.875) / (0.875 - 0.625) ly1 = (0.4 - 0.25) / (0.75 - 0.25) # ly2 = 0 true_val_11 = ((1 - lx1) * (1 - ly1) * rvals[0, 0] + (1 - lx1) * ly1 * rvals[0, 1] + lx1 * (1 - ly1) * rvals[1, 0] + lx1 * ly1 * rvals[1, 1]) true_val_12 = ((1 - lx1) * rvals[0, 1] + lx1 * rvals[1, 1]) # ly2 = 0 true_val_21 = ((1 - lx2) * (1 - ly1) * rvals[3, 0] + (1 - lx2) * ly1 * rvals[3, 1]) # high node 1.0, no upper true_val_22 = (1 - lx2) * rvals[3, 1] # ly2 = 0, no upper for 1.0 true_mg = [[true_val_11, true_val_12], [true_val_21, true_val_22]] assert all_equal(function(mg), true_mg) out = np.empty((2, 2), dtype='float64') function(mg, out=out) assert all_equal(out, true_mg)
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)
# 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, dtype='float32',