def skimage_radon_forward_projector(volume, geometry, proj_space, out=None): """Calculate forward projection using skimage. Parameters ---------- volume : `DiscreteLpElement` The volume to project. geometry : `Geometry` The projection geometry to use. proj_space : `DiscreteLp` Space in which the projections (sinograms) live. out : ``proj_space`` element, optional Element to which the result should be written. Returns ------- sinogram : ``proj_space`` element Result of the forward projection. If ``out`` was given, the returned object is a reference to it. """ # Lazy import due to significant import time from skimage.transform import radon # Check basic requirements. Fully checking should be in wrapper assert volume.shape[0] == volume.shape[1] theta = np.degrees(geometry.angles) skimage_range = skimage_proj_space(geometry, volume.space, proj_space) # Rotate volume from (x, y) to (rows, cols), then project sino_arr = radon( np.rot90(volume.asarray(), 1), theta=theta, circle=False ) sinogram = skimage_range.element(sino_arr.T) if out is None: out = proj_space.element() with writable_array(out) as out_arr: point_collocation( clamped_interpolation(skimage_range, sinogram), proj_space.grid.meshgrid, out=out_arr, ) scale = volume.space.cell_sides[0] out *= scale return out
def _call(self, x, out=None): """Apply resampling operator. The element ``x`` is resampled using the sampling and interpolation operators of the underlying spaces. """ interpolator = per_axis_interpolator(x, self.domain.grid.coord_vectors, self.interp) context = none_context if out is None else writable_array with context(out) as out_arr: return point_collocation(interpolator, self.range.meshgrid, out=out_arr)
def test_collocation_interpolation_identity(): """Check if collocation is left-inverse to interpolation.""" # Interpolation followed by collocation on the same grid should be # the identity coord_vecs = [[0.125, 0.375, 0.625, 0.875], [0.25, 0.75]] f = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype='float64') interpolators = [ nearest_interpolator(f, coord_vecs), linear_interpolator(f, coord_vecs), per_axis_interpolator(f, coord_vecs, interp=['linear', 'nearest']), ] for interpolator in interpolators: mg = sparse_meshgrid(*coord_vecs) ident_f = point_collocation(interpolator, mg) assert all_almost_equal(ident_f, f)
def skimage_radon_back_projector(sinogram, geometry, vol_space, out=None): """Calculate forward projection using skimage. Parameters ---------- sinogram : `DiscreteLpElement` Sinogram (projections) to backproject. geometry : `Geometry` The projection geometry to use. vol_space : `DiscreteLp` Space in which reconstructed volumes live. out : ``vol_space`` element, optional An element to which the result should be written. Returns ------- volume : ``vol_space`` element Result of the back-projection. If ``out`` was given, the returned object is a reference to it. """ # Lazy import due to significant import time from skimage.transform import iradon theta = np.degrees(geometry.angles) skimage_range = skimage_proj_space(geometry, vol_space, sinogram.space) skimage_sinogram = skimage_range.element() with writable_array(skimage_sinogram) as sino_arr: point_collocation( clamped_interpolation(sinogram.space, sinogram), skimage_range.grid.meshgrid, out=sino_arr, ) if out is None: out = vol_space.element() else: # Only do asserts here since these are backend functions assert out in vol_space # Rotate back from (rows, cols) to (x, y), then back-project (no filter) backproj = iradon( skimage_sinogram.asarray().T, theta, output_size=vol_space.shape[0], filter=None, circle=False, ) out[:] = np.rot90(backproj, -1) # Empirically determined value, gives correct scaling scaling_factor = 4 * geometry.motion_params.length / (2 * np.pi) # Correct in case of non-weighted spaces proj_volume = np.prod(sinogram.space.partition.extent) proj_size = sinogram.space.partition.size proj_weighting = proj_volume / proj_size scaling_factor *= sinogram.space.weighting.const / proj_weighting scaling_factor /= vol_space.weighting.const / vol_space.cell_volume # Correctly scale the output out *= scaling_factor return out