def add_noise_to_sino(sinogram_in, I0):
    """Adds Poisson noise to a sinogram.

    :param sinogram_in: Sinogram to add noise to.
    :type sinogram_in: :class:`numpy.ndarray`
    :param I0: Background intensity. Lower values lead to higher noise.
    :type I0: :class:`float`
    :returns:  :class:`numpy.ndarray` -- the sinogram with added noise.

    """
    if isinstance(sinogram_in, np.ndarray):
        sinogramRaw = sinogram_in
    else:
        sinogramRaw = data2d.get(sinogram_in)
    max_sinogramRaw = sinogramRaw.max()
    sinogramRawScaled = sinogramRaw / max_sinogramRaw
    # to detector count
    sinogramCT = I0 * np.exp(-sinogramRawScaled)
    # add poison noise
    sinogramCT_C = np.zeros_like(sinogramCT)
    for i in xrange(sinogramCT_C.shape[0]):
        for j in xrange(sinogramCT_C.shape[1]):
            sinogramCT_C[i, j] = np.random.poisson(sinogramCT[i, j])
    # to density
    sinogramCT_D = sinogramCT_C / I0
    sinogram_out = -max_sinogramRaw * np.log(sinogramCT_D)

    if not isinstance(sinogram_in, np.ndarray):
        at.data2d.store(sinogram_in, sinogram_out)
    return sinogram_out
Exemple #2
0
def create_sino(data, proj_id, useCUDA=False, returnData=True, gpuIndex=None):
    """Create a forward projection of an image (2D).

:param data: Image data or ID.
:type data: :class:`numpy.ndarray` or :class:`int`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param useCUDA: If ``True``, use CUDA for the calculation.
:type useCUDA: :class:`bool`
:param returnData: If False, only return the ID of the forward projection.
:type returnData: :class:`bool`
:param gpuIndex: Optional GPU index.
:type gpuIndex: :class:`int`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the forward projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order.

"""

    proj_geom = projector.projection_geometry(proj_id)
    vol_geom = projector.volume_geometry(proj_id)
    if isinstance(data, np.ndarray):
        volume_id = data2d.create("-vol", vol_geom, data)
    else:
        volume_id = data
    sino_id = data2d.create("-sino", proj_geom, 0)
    algString = "FP"
    if useCUDA:
        algString = algString + "_CUDA"
    cfg = astra_dict(algString)
    if not useCUDA:
        cfg["ProjectorId"] = proj_id
    if not gpuIndex == None:
        cfg["option"] = {"GPUindex": gpuIndex}
    cfg["ProjectionDataId"] = sino_id
    cfg["VolumeDataId"] = volume_id
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id)
    algorithm.delete(alg_id)

    if isinstance(data, np.ndarray):
        data2d.delete(volume_id)
    if returnData:
        return sino_id, data2d.get(sino_id)
    else:
        return sino_id
Exemple #3
0
def create_sino(data, proj_id, useCUDA=False, returnData=True, gpuIndex=None):
    """Create a forward projection of an image (2D).

:param data: Image data or ID.
:type data: :class:`numpy.ndarray` or :class:`int`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param useCUDA: If ``True``, use CUDA for the calculation.
:type useCUDA: :class:`bool`
:param returnData: If False, only return the ID of the forward projection.
:type returnData: :class:`bool`
:param gpuIndex: Optional GPU index.
:type gpuIndex: :class:`int`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the forward projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order.

"""

    proj_geom = projector.projection_geometry(proj_id)
    vol_geom = projector.volume_geometry(proj_id)
    if isinstance(data, np.ndarray):
        volume_id = data2d.create('-vol', vol_geom, data)
    else:
        volume_id = data
    sino_id = data2d.create('-sino', proj_geom, 0)
    algString = 'FP'
    if useCUDA:
        algString = algString + '_CUDA'
    cfg = astra_dict(algString)
    if not useCUDA:
        cfg['ProjectorId'] = proj_id
    if not gpuIndex==None:
        cfg['option']={'GPUindex':gpuIndex}
    cfg['ProjectionDataId'] = sino_id
    cfg['VolumeDataId'] = volume_id
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id)
    algorithm.delete(alg_id)

    if isinstance(data, np.ndarray):
        data2d.delete(volume_id)
    if returnData:
        return sino_id, data2d.get(sino_id)
    else:
        return sino_id
Exemple #4
0
def create_backprojection(data, proj_id, useCUDA=False, returnData=True):
    """Create a backprojection of a sinogram (2D).

:param data: Sinogram data or ID.
:type data: :class:`numpy.ndarray` or :class:`int`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param useCUDA: If ``True``, use CUDA for the calculation.
:type useCUDA: :class:`bool`
:param returnData: If False, only return the ID of the backprojection.
:type returnData: :class:`bool`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order.

"""
    proj_geom = projector.projection_geometry(proj_id)
    vol_geom = projector.volume_geometry(proj_id)
    if isinstance(data, np.ndarray):
        sino_id = data2d.create("-sino", proj_geom, data)
    else:
        sino_id = data
    vol_id = data2d.create("-vol", vol_geom, 0)

    algString = "BP"
    if useCUDA:
        algString = algString + "_CUDA"

    cfg = astra_dict(algString)
    if not useCUDA:
        cfg["ProjectorId"] = proj_id
    cfg["ProjectionDataId"] = sino_id
    cfg["ReconstructionDataId"] = vol_id
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id)
    algorithm.delete(alg_id)

    if isinstance(data, np.ndarray):
        data2d.delete(sino_id)

    if returnData:
        return vol_id, data2d.get(vol_id)
    else:
        return vol_id
Exemple #5
0
def create_backprojection(data, proj_id, useCUDA=False, returnData=True):
    """Create a backprojection of a sinogram (2D).

:param data: Sinogram data or ID.
:type data: :class:`numpy.ndarray` or :class:`int`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param useCUDA: If ``True``, use CUDA for the calculation.
:type useCUDA: :class:`bool`
:param returnData: If False, only return the ID of the backprojection.
:type returnData: :class:`bool`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order.

"""
    proj_geom = projector.projection_geometry(proj_id)
    vol_geom = projector.volume_geometry(proj_id)
    if isinstance(data, np.ndarray):
        sino_id = data2d.create('-sino', proj_geom, data)
    else:
        sino_id = data
    vol_id = data2d.create('-vol', vol_geom, 0)

    algString = 'BP'
    if useCUDA:
        algString = algString + '_CUDA'

    cfg = astra_dict(algString)
    if not useCUDA:
        cfg['ProjectorId'] = proj_id
    cfg['ProjectionDataId'] = sino_id
    cfg['ReconstructionDataId'] = vol_id
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id)
    algorithm.delete(alg_id)

    if isinstance(data, np.ndarray):
        data2d.delete(sino_id)

    if returnData:
        return vol_id, data2d.get(vol_id)
    else:
        return vol_id
Exemple #6
0
def create_reconstruction(
    rec_type,
    proj_id,
    sinogram,
    iterations=1,
    use_mask="no",
    mask=np.array([]),
    use_minc="no",
    minc=0,
    use_maxc="no",
    maxc=255,
    returnData=True,
    filterType=None,
    filterData=None,
):
    """Create a reconstruction of a sinogram (2D).

:param rec_type: Name of the reconstruction algorithm.
:type rec_type: :class:`string`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param sinogram: Sinogram data or ID.
:type sinogram: :class:`numpy.ndarray` or :class:`int`
:param iterations: Number of iterations to run.
:type iterations: :class:`int`
:param use_mask: Whether to use a mask.
:type use_mask: ``'yes'`` or ``'no'``
:param mask: Mask data or ID
:type mask: :class:`numpy.ndarray` or :class:`int`
:param use_minc: Whether to force a minimum value on the reconstruction pixels.
:type use_minc: ``'yes'`` or ``'no'``
:param minc: Minimum value to use.
:type minc: :class:`float`
:param use_maxc: Whether to force a maximum value on the reconstruction pixels.
:type use_maxc: ``'yes'`` or ``'no'``
:param maxc: Maximum value to use.
:type maxc: :class:`float`
:param returnData: If False, only return the ID of the reconstruction.
:type returnData: :class:`bool`
:param filterType: Which type of filter to use for filter-based methods.
:type filterType: :class:`string`
:param filterData: Optional filter data for filter-based methods.
:type filterData: :class:`numpy.ndarray`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the reconstruction. Otherwise, returns a tuple containing the ID of the reconstruction and reconstruction itself, in that order.

"""
    proj_geom = projector.projection_geometry(proj_id)
    if isinstance(sinogram, np.ndarray):
        sino_id = data2d.create("-sino", proj_geom, sinogram)
    else:
        sino_id = sinogram
    vol_geom = projector.volume_geometry(proj_id)
    recon_id = data2d.create("-vol", vol_geom, 0)
    cfg = astra_dict(rec_type)
    if not "CUDA" in rec_type:
        cfg["ProjectorId"] = proj_id
    cfg["ProjectionDataId"] = sino_id
    cfg["ReconstructionDataId"] = recon_id
    cfg["options"] = {}
    if use_mask == "yes":
        if isinstance(mask, np.ndarray):
            mask_id = data2d.create("-vol", vol_geom, mask)
        else:
            mask_id = mask
        cfg["options"]["ReconstructionMaskId"] = mask_id
    if not filterType == None:
        cfg["FilterType"] = filterType
    if not filterData == None:
        if isinstance(filterData, np.ndarray):
            nexpow = int(pow(2, math.ceil(math.log(2 * proj_geom["DetectorCount"], 2))))
            filtSize = nexpow / 2 + 1
            filt_proj_geom = create_proj_geom("parallel", 1.0, filtSize, proj_geom["ProjectionAngles"])
            filt_id = data2d.create("-sino", filt_proj_geom, filterData)
        else:
            filt_id = filterData
        cfg["FilterSinogramId"] = filt_id
    cfg["options"]["UseMinConstraint"] = use_minc
    cfg["options"]["MinConstraintValue"] = minc
    cfg["options"]["UseMaxConstraint"] = use_maxc
    cfg["options"]["MaxConstraintValue"] = maxc
    cfg["options"]["ProjectionOrder"] = "random"
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id, iterations)

    algorithm.delete(alg_id)

    if isinstance(sinogram, np.ndarray):
        data2d.delete(sino_id)
    if use_mask == "yes" and isinstance(mask, np.ndarray):
        data2d.delete(mask_id)
    if not filterData == None:
        if isinstance(filterData, np.ndarray):
            data2d.delete(filt_id)
    if returnData:
        return recon_id, data2d.get(recon_id)
    else:
        return recon_id
Exemple #7
0
def create_reconstruction(rec_type, proj_id, sinogram, iterations=1, use_mask='no', mask=np.array([]), use_minc='no', minc=0, use_maxc='no', maxc=255, returnData=True, filterType=None, filterData=None):
    """Create a reconstruction of a sinogram (2D).

:param rec_type: Name of the reconstruction algorithm.
:type rec_type: :class:`string`
:param proj_id: ID of the projector to use.
:type proj_id: :class:`int`
:param sinogram: Sinogram data or ID.
:type sinogram: :class:`numpy.ndarray` or :class:`int`
:param iterations: Number of iterations to run.
:type iterations: :class:`int`
:param use_mask: Whether to use a mask.
:type use_mask: ``'yes'`` or ``'no'``
:param mask: Mask data or ID
:type mask: :class:`numpy.ndarray` or :class:`int`
:param use_minc: Whether to force a minimum value on the reconstruction pixels.
:type use_minc: ``'yes'`` or ``'no'``
:param minc: Minimum value to use.
:type minc: :class:`float`
:param use_maxc: Whether to force a maximum value on the reconstruction pixels.
:type use_maxc: ``'yes'`` or ``'no'``
:param maxc: Maximum value to use.
:type maxc: :class:`float`
:param returnData: If False, only return the ID of the reconstruction.
:type returnData: :class:`bool`
:param filterType: Which type of filter to use for filter-based methods.
:type filterType: :class:`string`
:param filterData: Optional filter data for filter-based methods.
:type filterData: :class:`numpy.ndarray`
:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the reconstruction. Otherwise, returns a tuple containing the ID of the reconstruction and reconstruction itself, in that order.

"""
    proj_geom = projector.projection_geometry(proj_id)
    if isinstance(sinogram, np.ndarray):
        sino_id = data2d.create('-sino', proj_geom, sinogram)
    else:
        sino_id = sinogram
    vol_geom = projector.volume_geometry(proj_id)
    recon_id = data2d.create('-vol', vol_geom, 0)
    cfg = astra_dict(rec_type)
    if not 'CUDA' in rec_type:
        cfg['ProjectorId'] = proj_id
    cfg['ProjectionDataId'] = sino_id
    cfg['ReconstructionDataId'] = recon_id
    cfg['options'] = {}
    if use_mask == 'yes':
        if isinstance(mask, np.ndarray):
            mask_id = data2d.create('-vol', vol_geom, mask)
        else:
            mask_id = mask
        cfg['options']['ReconstructionMaskId'] = mask_id
    if not filterType == None:
        cfg['FilterType'] = filterType
    if not filterData == None:
        if isinstance(filterData, np.ndarray):
            nexpow = int(
                pow(2, math.ceil(math.log(2 * proj_geom['DetectorCount'], 2))))
            filtSize = nexpow / 2 + 1
            filt_proj_geom = create_proj_geom(
                'parallel', 1.0, filtSize, proj_geom['ProjectionAngles'])
            filt_id = data2d.create('-sino', filt_proj_geom, filterData)
        else:
            filt_id = filterData
        cfg['FilterSinogramId'] = filt_id
    cfg['options']['UseMinConstraint'] = use_minc
    cfg['options']['MinConstraintValue'] = minc
    cfg['options']['UseMaxConstraint'] = use_maxc
    cfg['options']['MaxConstraintValue'] = maxc
    cfg['options']['ProjectionOrder'] = 'random'
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id, iterations)

    algorithm.delete(alg_id)

    if isinstance(sinogram, np.ndarray):
        data2d.delete(sino_id)
    if use_mask == 'yes' and isinstance(mask, np.ndarray):
        data2d.delete(mask_id)
    if not filterData == None:
        if isinstance(filterData, np.ndarray):
            data2d.delete(filt_id)
    if returnData:
        return recon_id, data2d.get(recon_id)
    else:
        return recon_id
Exemple #8
0
def create_sino(data, proj_id=None, proj_geom=None, vol_geom=None,
                useCUDA=False, returnData=True, gpuIndex=None):
    """Create a forward projection of an image (2D).

    :param data: Image data or ID.
    :type data: :class:`numpy.ndarray` or :class:`int`
    :param proj_id: ID of the projector to use.
    :type proj_id: :class:`int`
    :param proj_geom: Projection geometry.
    :type proj_geom: :class:`dict`
    :param vol_geom: Volume geometry.
    :type vol_geom: :class:`dict`
    :param useCUDA: If ``True``, use CUDA for the calculation.
    :type useCUDA: :class:`bool`
    :param returnData: If False, only return the ID of the forward projection.
    :type returnData: :class:`bool`
    :param gpuIndex: Optional GPU index.
    :type gpuIndex: :class:`int`
    :returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`)

    If ``returnData=False``, returns the ID of the forward
    projection. Otherwise, returns a tuple containing the ID of the
    forward projection and the forward projection itself, in that
    order.

    The geometry of setup is defined by ``proj_id`` or with
    ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then
    ``proj_geom`` and ``vol_geom`` must be None and vice versa.
"""
    if proj_id is not None:
        proj_geom = projector.projection_geometry(proj_id)
        vol_geom = projector.volume_geometry(proj_id)
    elif proj_geom is not None and vol_geom is not None:
        if not useCUDA:
            # We need more parameters to create projector.
            raise ValueError(
                """A ``proj_id`` is needed when CUDA is not used.""")
    else:
        raise Exception("""The geometry setup is not defined.
        The geometry of setup is defined by ``proj_id`` or with
        ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then
        ``proj_geom`` and ``vol_geom`` must be None and vice versa.""")

    if isinstance(data, np.ndarray):
        volume_id = data2d.create('-vol', vol_geom, data)
    else:
        volume_id = data
    sino_id = data2d.create('-sino', proj_geom, 0)
    algString = 'FP'
    if useCUDA:
        algString = algString + '_CUDA'
    cfg = astra_dict(algString)
    if not useCUDA:
        cfg['ProjectorId'] = proj_id
    if gpuIndex is not None:
        cfg['option'] = {'GPUindex': gpuIndex}
    cfg['ProjectionDataId'] = sino_id
    cfg['VolumeDataId'] = volume_id
    alg_id = algorithm.create(cfg)
    algorithm.run(alg_id)
    algorithm.delete(alg_id)

    if isinstance(data, np.ndarray):
        data2d.delete(volume_id)
    if returnData:
        return sino_id, data2d.get(sino_id)
    else:
        return sino_id