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
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
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
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
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
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
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
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