def test_uniform_partition_fromgrid(): vec1 = np.array([2, 4, 5, 7]) vec2 = np.array([-4, -3, 0, 1, 4]) begin = [0, -4] end = [7, 8] beg_calc = [2 - (4 - 2) / 2, -4 - (-3 + 4) / 2] end_calc = [7 + (7 - 5) / 2, 4 + (4 - 1) / 2] # Default case grid = odl.TensorGrid(vec1, vec2) part = odl.uniform_partition_fromgrid(grid) assert part.set == odl.IntervalProd(beg_calc, end_calc) # Explicit begin / end, full vectors part = odl.uniform_partition_fromgrid(grid, begin=begin) assert part.set == odl.IntervalProd(begin, end_calc) part = odl.uniform_partition_fromgrid(grid, end=end) assert part.set == odl.IntervalProd(beg_calc, end) # begin / end as dictionaries beg_dict = {0: 0.5} end_dict = {-1: 8} part = odl.uniform_partition_fromgrid(grid, begin=beg_dict, end=end_dict) true_beg = [0.5, beg_calc[1]] true_end = [end_calc[0], 8] assert part.set == odl.IntervalProd(true_beg, true_end) # Degenerate dimension, needs both explicit begin and end grid = odl.TensorGrid(vec1, [1.0]) with pytest.raises(ValueError): odl.uniform_partition_fromgrid(grid) with pytest.raises(ValueError): odl.uniform_partition_fromgrid(grid, begin=begin) with pytest.raises(ValueError): odl.uniform_partition_fromgrid(grid, end=end)
def test_partition_insert(): vec11 = [2, 4, 5, 7] vec12 = [-4, -3, 0, 1, 4] begin1 = [1, -4] end1 = [7, 5] grid1 = odl.TensorGrid(vec11, vec12) intv1 = odl.IntervalProd(begin1, end1) part1 = odl.RectPartition(intv1, grid1) vec21 = [-2, 0, 3] vec22 = [0] begin2 = [-2, -2] end2 = [4, 0] grid2 = odl.TensorGrid(vec21, vec22) intv2 = odl.IntervalProd(begin2, end2) part2 = odl.RectPartition(intv2, grid2) part = part1.insert(0, part2) assert all_equal(part.begin, [-2, -2, 1, -4]) assert all_equal(part.end, [4, 0, 7, 5]) assert all_equal(part.grid.min_pt, [-2, 0, 2, -4]) assert all_equal(part.grid.max_pt, [3, 0, 7, 4]) part = part1.insert(1, part2) assert all_equal(part.begin, [1, -2, -2, -4]) assert all_equal(part.end, [7, 4, 0, 5]) assert all_equal(part.grid.min_pt, [2, -2, 0, -4]) assert all_equal(part.grid.max_pt, [7, 3, 0, 4])
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_partition_init_raise(): # Check different error scenarios vec1 = np.array([2, 4, 5, 7]) vec2 = np.array([-4, -3, 0, 1, 4]) grid = odl.TensorGrid(vec1, vec2) begin = [2, -5] end = [10, 4] beg_toolarge = (2, -3.5) end_toosmall = (7, 1) beg_badshape = (-1, 2, 0) end_badshape = (2, ) with pytest.raises(ValueError): odl.RectPartition(odl.IntervalProd(beg_toolarge, end), grid) with pytest.raises(ValueError): odl.RectPartition(odl.IntervalProd(begin, end_toosmall), grid) with pytest.raises(ValueError): odl.RectPartition(odl.IntervalProd(beg_badshape, end_badshape), grid) with pytest.raises(TypeError): odl.RectPartition(None, grid) with pytest.raises(TypeError): odl.RectPartition(odl.IntervalProd(beg_toolarge, end), None)
def test_partition_getitem(): vec1 = [2, 4, 5, 7] vec2 = [-4, -3, 0, 1, 4] vec3 = [-2, 0, 3] vec4 = [0] vecs = [vec1, vec2, vec3, vec4] begin = [1, -4, -2, -2] end = [7, 5, 4, 0] grid = odl.TensorGrid(*vecs) intv = odl.IntervalProd(begin, end) part = odl.RectPartition(intv, grid) # Test a couple of slices slc = (1, -2, 2, 0) slc_vecs = [v[i] for i, v in zip(slc, vecs)] slc_part = part[slc] assert slc_part.grid == odl.TensorGrid(*slc_vecs) slc_beg = [3, 0.5, 1.5, -2] slc_end = [4.5, 2.5, 4, 0] assert slc_part.set == odl.IntervalProd(slc_beg, slc_end) slc = (slice(None), slice(None, None, 2), slice(None, 2), 0) slc_vecs = [v[i] for i, v in zip(slc, vecs)] slc_part = part[slc] assert slc_part.grid == odl.TensorGrid(*slc_vecs) slc_beg = [1, -4, -2, -2] slc_end = [7, 5, 1.5, 0] assert slc_part.set == odl.IntervalProd(slc_beg, slc_end) # Fewer indices assert part[1] == part[1, :, :, :] == part[1, ...] assert part[1, 2:] == part[1, 2:, :, :] == part[1, 2:, ...] assert part[1, 2:, ::2] == part[1, 2:, ::2, :] == part[1, 2:, ::2, ...] # Index list using indices 0 and 2 lst_beg = [1, -4, -2, -2] lst_end = [6, 5, 4, 0] lst_intv = odl.IntervalProd(lst_beg, lst_end) lst_vec1 = [2, 5] lst_grid = odl.TensorGrid(lst_vec1, vec2, vec3, vec4) lst_part = odl.RectPartition(lst_intv, lst_grid) assert part[[0, 2]] == lst_part
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_partition_set(): vec1 = np.array([2, 4, 5, 7]) vec2 = np.array([-4, -3, 0, 1, 4]) grid = odl.TensorGrid(vec1, vec2) begin = [1, -4] end = [10, 5] intv = odl.IntervalProd(begin, end) part = odl.RectPartition(intv, grid) assert part.set == odl.IntervalProd(begin, end) assert all_equal(part.begin, begin) assert all_equal(part.min(), begin) assert all_equal(part.end, end) assert all_equal(part.max(), end)
def test_partition_cell_boundary_vecs(): vec1 = np.array([2, 4, 5, 7]) vec2 = np.array([-4, -3, 0, 1, 4]) grid = odl.TensorGrid(vec1, vec2) midpts1 = [3, 4.5, 6] midpts2 = [-3.5, -1.5, 0.5, 2.5] begin = [2, -6] end = [10, 4] intv = odl.IntervalProd(begin, end) true_bvec1 = [2] + midpts1 + [10] true_bvec2 = [-6] + midpts2 + [4] part = odl.RectPartition(intv, grid) assert all_equal(part.cell_boundary_vecs, (true_bvec1, true_bvec2))
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')