def stir_projector_from_file(volume_file, projection_file): """Create a STIR projector from given template files. Parameters ---------- volume_file : string Full file path to the STIR input file containing information on the volume. This is usually a '.hv' file. For STIR reasons, a '.v' file is also needed. projection_file : string Full file path to the STIR input file with information on the projection data. This is usually a '.hs' file. For STIR reasons, a '.s' file is also needed. Returns ------- projector : `ForwardProjectorByBinWrapper` A STIR forward projector. """ volume = stir.FloatVoxelsOnCartesianGrid.read_from_file(volume_file) proj_data_in = stir.ProjData.read_from_file(projection_file) proj_data = stir.ProjDataInMemory(proj_data_in.get_exam_info(), proj_data_in.get_proj_data_info()) origin = volume.get_origin() grid_spacing = volume.get_grid_spacing() grid_shape = [ volume.get_z_size(), volume.get_y_size(), volume.get_x_size() ] min_pt = [origin[1], origin[2], origin[3]] max_pt = [ origin[1] + grid_spacing[1] * grid_shape[0], origin[2] + grid_spacing[2] * grid_shape[1], origin[3] + grid_spacing[3] * grid_shape[2] ] # reverse to handle STIR bug? See: # https://github.com/UCL/STIR/issues/7 recon_sp = uniform_discr(min_pt, max_pt, grid_shape, dtype='float32') # TODO: set correct projection space. Currently, a default grid with # stride (1, 1, 1) is used. proj_shape = proj_data.to_array().shape() data_sp = uniform_discr([0, 0, 0], proj_shape, proj_shape, dtype='float32') return ForwardProjectorByBinWrapper(recon_sp, data_sp, volume, proj_data)
def stir_projector_from_file(volume_file, projection_file): """Create a STIR projector from given template files. Parameters ---------- volume_file : string Full file path to the STIR input file containing information on the volume. This is usually a '.hv' file. For STIR reasons, a '.v' file is also needed. projection_file : string Full file path to the STIR input file with information on the projection data. This is usually a '.hs' file. For STIR reasons, a '.s' file is also needed. Returns ------- projector : `ForwardProjectorByBinWrapper` A STIR forward projector. """ volume = stir.FloatVoxelsOnCartesianGrid.read_from_file(volume_file) proj_data_in = stir.ProjData.read_from_file(projection_file) proj_data = stir.ProjDataInMemory(proj_data_in.get_exam_info(), proj_data_in.get_proj_data_info()) origin = volume.get_origin() grid_spacing = volume.get_grid_spacing() grid_shape = [volume.get_z_size(), volume.get_y_size(), volume.get_x_size()] min_pt = [origin[1], origin[2], origin[3]] max_pt = [origin[1] + grid_spacing[1] * grid_shape[0], origin[2] + grid_spacing[2] * grid_shape[1], origin[3] + grid_spacing[3] * grid_shape[2]] # reverse to handle STIR bug? See: # https://github.com/UCL/STIR/issues/7 recon_sp = uniform_discr(min_pt, max_pt, grid_shape, dtype='float32') # TODO: set correct projection space. Currently, a default grid with # stride (1, 1, 1) is used. proj_shape = proj_data.to_array().shape() data_sp = uniform_discr([0, 0, 0], proj_shape, proj_shape, dtype='float32') return ForwardProjectorByBinWrapper(recon_sp, data_sp, volume, proj_data)
def get_range_from_proj_data(proj_data, radius=1.): """ Get an ODL codomain (range) from the projection data. The second coordinate is an angle. The last one is a tangential coordinate, normalised between -1 and 1. `radius`: units for the tangential coordinates """ shape = get_shape_from_proj_data(proj_data) min_pt = [0, 0, -radius] max_pt = [shape[0], np.pi, radius] data_sp = uniform_discr(min_pt=min_pt, max_pt=max_pt, shape=shape, axis_labels=("(dz,z)", "φ", "s"), dtype='float32') return data_sp
def spherical_sum(image, binning_factor=1.0): """Sum image values over concentric annuli. Parameters ---------- image : `DiscreteLp` element Input data whose radial sum should be computed. binning_factor : positive float, optional Reduce the number of output bins by this factor. Increasing this number can help reducing fluctuations due to the variance of points that fall in a particular annulus. A binning factor of ``1`` corresponds to a bin size equal to image pixel size for images with square pixels, otherwise :: max(norm2(c)) / norm2(shape) where the maximum is taken over all corners of the image domain. Returns ------- spherical_sum : 1D `DiscreteLp` element The spherical sum of ``image``. Its space is one-dimensional with domain ``[0, rmax]``, where ``rmax`` is the radius of the smallest ball containing ``image.space.domain``. Its shape is ``(N,)`` with :: N = int(sqrt(sum(n ** 2 for n in image.shape)) / binning_factor) """ r = np.sqrt(sum(xi**2 for xi in image.space.meshgrid)) rmax = max(np.linalg.norm(c) for c in image.space.domain.corners()) n_bins = int(np.sqrt(sum(n**2 for n in image.shape)) / binning_factor) rad_sum, _ = np.histogram(r, weights=image, bins=n_bins, range=(0, rmax)) out_spc = uniform_discr(min_pt=0, max_pt=rmax, shape=n_bins, impl=image.space.impl, dtype=image.space.dtype, interp="linear", axis_labels=["$r$"]) return out_spc.element(rad_sum)
def space_from_stir_domain(stir_domain): """ This function tries to transform the VoxelsOnCartesianGrid to DicreteLP. Parameters ---------- stir_domain: A VoxelsOnCartesianGrid Object Returns ------- An ODL DiscreteLP object with characteristics of the VoxelsOnCartesianGrid """ stir_vox_max = stir_domain.get_max_indices() stir_vox_min = stir_domain.get_min_indices() vox_num = [ stir_vox_max[1] - stir_vox_min[1] + 1, stir_vox_max[2] - stir_vox_min[2] + 1, stir_vox_max[3] - stir_vox_min[3] + 1 ] stir_vol_max = stir_domain.get_physical_coordinates_for_indices( stir_domain.get_max_indices()) stir_vol_min = stir_domain.get_physical_coordinates_for_indices( stir_domain.get_min_indices()) stir_vox_size = stir_domain.get_voxel_size() vol_max = [ stir_vol_max[1] + stir_vox_size[1], stir_vol_max[2] + stir_vox_size[2], stir_vol_max[3] + stir_vox_size[3] ] vol_min = [stir_vol_min[1], stir_vol_min[2], stir_vol_min[3]] return uniform_discr(min_pt=vol_min, max_pt=vol_max, shape=vox_num, axis_labels=["z", "y", "x"], dtype='float32')
def _resize_discr(discr, newshp, offset, discr_kwargs): """Return a space based on ``discr`` and ``newshp``. Use the domain of ``discr`` and its partition to create a new uniformly discretized space with ``newshp`` as shape. In axes where ``offset`` is given, it determines the number of added/removed cells to the left. Where ``offset`` is ``None``, the points are distributed evenly to left and right. The ``discr_kwargs`` parameter is passed to `uniform_discr` for further specification of discretization parameters. """ nodes_on_bdry = discr_kwargs.get('nodes_on_bdry', False) if np.shape(nodes_on_bdry) == (): nodes_on_bdry = ([(bool(nodes_on_bdry), bool(nodes_on_bdry))] * discr.ndim) elif discr.ndim == 1 and len(nodes_on_bdry) == 2: nodes_on_bdry = [nodes_on_bdry] elif len(nodes_on_bdry) != discr.ndim: raise ValueError('`nodes_on_bdry` has length {}, expected {}' ''.format(len(nodes_on_bdry), discr.ndim)) dtype = discr_kwargs.pop('dtype', discr.dtype) impl = discr_kwargs.pop('impl', discr.impl) exponent = discr_kwargs.pop('exponent', discr.exponent) interp = discr_kwargs.pop('interp', discr.interp) order = discr_kwargs.pop('order', discr.order) weighting = discr_kwargs.pop('weighting', discr.weighting) grid_min, grid_max = discr.grid.min(), discr.grid.max() cell_size = discr.cell_sides new_minpt, new_maxpt = [], [] for axis, (n_orig, n_new, off, on_bdry) in enumerate( zip(discr.shape, newshp, offset, nodes_on_bdry)): n_diff = n_new - n_orig if off is None: num_r = n_diff // 2 num_l = n_diff - num_r else: num_r = n_diff - off num_l = off try: on_bdry_l, on_bdry_r = on_bdry except TypeError: on_bdry_l = on_bdry on_bdry_r = on_bdry if on_bdry_l: new_minpt.append(grid_min[axis] - num_l * cell_size[axis]) else: new_minpt.append(grid_min[axis] - (num_l + 0.5) * cell_size[axis]) if on_bdry_r: new_maxpt.append(grid_max[axis] + num_r * cell_size[axis]) else: new_maxpt.append(grid_max[axis] + (num_r + 0.5) * cell_size[axis]) return uniform_discr(new_minpt, new_maxpt, newshp, dtype=dtype, impl=impl, exponent=exponent, interp=interp, order=order, weighting=weighting, nodes_on_bdry=nodes_on_bdry)
import numpy as np from hyperopt import hp from odl.discr import uniform_discr from dival.datasets.dataset import Dataset from dival.evaluation import TaskTable from dival.measure import L2, PSNR from dival.reconstructors.regression_reconstructors import LinRegReconstructor from dival.hyper_param_search import optimize_hyper_params # %% data observation_space = uniform_discr(-0.5, 69.5, 70) reco_space = uniform_discr(-0.5, 79.5, 71) np.random.seed(0) class LinearDataset(Dataset): def __init__(self, observation_space, reco_space, train_len=10000, validation_len=1000, test_len=1000): self.train_len = train_len self.validation_len = validation_len self.test_len = test_len self.observation_space = observation_space self.reco_space = reco_space self.space = (self.observation_space, self.reco_space) self.shape = (self.observation_space.shape, self.reco_space.shape) self.forward_matrix = np.random.rand(self.shape[0][0],
def _resize_discr(discr, newshp, offset, discr_kwargs): """Return a space based on ``discr`` and ``newshp``. Use the domain of ``discr`` and its partition to create a new uniformly discretized space with ``newshp`` as shape. In axes where ``offset`` is given, it determines the number of added/removed cells to the left. Where ``offset`` is ``None``, the points are distributed evenly to left and right. The ``discr_kwargs`` parameter is passed to `uniform_discr` for further specification of discretization parameters. """ nodes_on_bdry = discr_kwargs.get('nodes_on_bdry', False) if np.shape(nodes_on_bdry) == (): nodes_on_bdry = ([(bool(nodes_on_bdry), bool(nodes_on_bdry))] * discr.ndim) elif discr.ndim == 1 and len(nodes_on_bdry) == 2: nodes_on_bdry = [nodes_on_bdry] elif len(nodes_on_bdry) != discr.ndim: raise ValueError('`nodes_on_bdry` has length {}, expected {}' ''.format(len(nodes_on_bdry), discr.ndim)) dtype = discr_kwargs.pop('dtype', discr.dtype) impl = discr_kwargs.pop('impl', discr.impl) exponent = discr_kwargs.pop('exponent', discr.exponent) interp = discr_kwargs.pop('interp', discr.interp) order = discr_kwargs.pop('order', discr.order) weighting = discr_kwargs.pop('weighting', discr.weighting) grid_min, grid_max = discr.grid.min(), discr.grid.max() cell_size = discr.cell_sides new_minpt, new_maxpt = [], [] for axis, (n_orig, n_new, off, on_bdry) in enumerate(zip( discr.shape, newshp, offset, nodes_on_bdry)): n_diff = n_new - n_orig if off is None: num_r = n_diff // 2 num_l = n_diff - num_r else: num_r = n_diff - off num_l = off try: on_bdry_l, on_bdry_r = on_bdry except TypeError: on_bdry_l = on_bdry on_bdry_r = on_bdry if on_bdry_l: new_minpt.append(grid_min[axis] - num_l * cell_size[axis]) else: new_minpt.append(grid_min[axis] - (num_l + 0.5) * cell_size[axis]) if on_bdry_r: new_maxpt.append(grid_max[axis] + num_r * cell_size[axis]) else: new_maxpt.append(grid_max[axis] + (num_r + 0.5) * cell_size[axis]) return uniform_discr(new_minpt, new_maxpt, newshp, dtype=dtype, impl=impl, exponent=exponent, interp=interp, order=order, weighting=weighting, nodes_on_bdry=nodes_on_bdry)