Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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')
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
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],
Ejemplo n.º 8
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)