def astra_fp_3d(volume, proj_geom):
    """
    :param proj_geom:
    :param volume:
    :return:3D sinogram
    """
    detector_size = volume.shape[1]
    slices_number = volume.shape[0]
    rec_size = detector_size

    vol_geom = build_volume_geometry_3d(rec_size, slices_number)

    sinogram_id = astra.data3d.create('-sino', proj_geom)
    # Create a data object for the reconstruction
    rec_id = astra.data3d.create('-vol', vol_geom, data=volume)

    # Set up the parameters for a reconstruction algorithm using the GPU
    cfg = astra.astra_dict('FP3D_CUDA')
    cfg['VolumeDataId'] = rec_id
    cfg['ProjectionDataId'] = sinogram_id
    cfg['option'] = {}

    alg_id = astra.algorithm.create(cfg)
    astra.algorithm.run(alg_id, 1)
    res_sino = astra.data3d.get(sinogram_id)

    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(sinogram_id)
    astra.clear()
    return res_sino
Beispiel #2
0
def getSystemMatrix(geom):
    vectors = np.zeros((len(geom), 12), dtype=np.float32)

    for i, _ in enumerate(vectors):
        vectors[i, [0, 1, 2]] = geom[i]['Anode']
        vectors[i, [3, 4, 5]] = geom[i]['Detector']
        vectors[i, [6, 7, 8]] = geom[i]['U Axis']
        vectors[i, [9, 10, 11]] = geom[i]['V Axis']

    # Range of X, Y, Z in mm over the entire volume
    volX = np.array([-10, 10])
    volY = np.array([-9, 20])
    volZ = np.array([-15, 15])

    # Chosen grid size
    voxelSize = [0.1, 0.1, 0.1]

    # Set reconstruction grid size
    # Length of the OVERALL volume grid
    volSize = np.array([
        volX.ptp() / voxelSize[0],
        volY.ptp() / voxelSize[1],
        volZ.ptp() / voxelSize[2]
    ],
                       dtype=int)
    gridSize = volSize
    gridX = np.linspace(volX[0], volX[1], gridSize[0])
    gridY = np.linspace(volY[0], volY[1], gridSize[1])
    gridZ = np.linspace(volZ[0], volZ[1], gridSize[2])

    # Setup ASTRA geometry
    proj_geom = astra.create_proj_geom('cone_vec', 512, 512, vectors)
    vol_geom = astra.create_vol_geom(volSize[1], volSize[0], volSize[2],
                                     volX[0], volX[1], volY[0], volY[1],
                                     volZ[0], volZ[1])

    # 3D projectors: cuda3d
    # blob not implemented, linear3d and linearcone not available(?)
    proj_id = astra.create_projector('cuda3d', proj_geom, vol_geom)

    # Get the OpTomo representation of the system matrix for brevity
    W = astra.optomo.OpTomo(proj_id)

    # Clearing astra variables (only need W)
    astra.clear()

    # Print volume size
    print(f'Volume grid size (px): {gridSize}')

    return W
def astra_recon_3d(sinogram, proj_geom, method=['CGLS3D_CUDA', 10], data=None):
    """
    :param proj_geom:
    :param sinogram:
    :param method:
    :param n_iters:
    :param data:
    :return:
    """

    methods = parse_recon_methods(method)

    detector_size = sinogram.shape[-1]
    slices_number = sinogram.shape[0]

    rec_size = detector_size
    vol_geom = astra.create_vol_geom(rec_size, rec_size, slices_number)

    sinogram_id = astra.data3d.create('-sino', proj_geom, data=sinogram)

    # Create a data object for the reconstruction
    rec_id = astra.data3d.create('-vol', vol_geom, data)

    alg_id = None

    for m in methods:
        cfg = astra.astra_dict(m[0])
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
        cfg['option'] = m[2]
        alg_id = astra.algorithm.create(cfg)
        astra.algorithm.run(alg_id, m[1])
        astra.algorithm.delete(alg_id)

    tomo_rec = astra.data3d.get(rec_id)
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.

    astra.data3d.delete(rec_id)
    astra.data3d.delete(sinogram_id)
    astra.clear()
    return tomo_rec
Beispiel #4
0
        astra.algorithm.run(self.forward_alg_id)
        self.projection_data = astra.data3d.get(self.projection_id)

    def backward(self):
        astra.algorithm.run(self.backward_alg_id)
        self.volume_data = astra.data3d.get(self.volume_id)

    def clear(self):
        astra.data3d.delete(self.volume_id)
        astra.data3d.delete(self.projection_id)
        astra.algorithm.delete(self.forward_alg_id)
        astra.algorithm.delete(self.backward_alg_id)


# SIRT
astra.clear()
p = Projector()
p.init()
p.forward()
p.backward()


class Mmm:
    def __init__(self, num_voxel=(100, 100, 100)):
        self.num_voxel = num_voxel
        self.vol_geom = astra.create_vol_geom(self.num_voxel)
        self.volume_id = astra.data3d.create('-vol', self.vol_geom, 0)

    counter = 0
    num_voxel = (10, 10, 10)
Beispiel #5
0
    def forward(self):
        astra.algorithm.run(self.forward_alg_id)
        self.projection_data = astra.data3d.get(self.projection_id)
        
    def backward(self):
        astra.algorithm.run(self.backward_alg_id)
        self.volume_data = astra.data3d.get(self.volume_id)
        
    def clear(self):
        astra.data3d.delete(self.volume_id)
        astra.data3d.delete(self.projection_id)
        astra.algorithm.delete(self.forward_alg_id)
        astra.algorithm.delete(self.backward_alg_id)

# SIRT  
astra.clear()
p = Projector()
p.init()
p.forward()
p.backward()


class Mmm:
    
    def __init__(self, num_voxel = (100, 100, 100)):
        self.num_voxel = num_voxel
        self.vol_geom = astra.create_vol_geom(self.num_voxel)
        self.volume_id = astra.data3d.create('-vol', self.vol_geom, 0)
    
    counter = 0
    num_voxel = (10, 10, 10)
Beispiel #6
0
def astra_sirt_error(sinogram,
                     angles,
                     iterations=50,
                     constrain=True,
                     thresh=0,
                     cuda=False):
    """
    Perform SIRT reconstruction using the Astra toolbox algorithms.

    Args
    ----------
    stack : NumPy array
       Tilt series data either of the form [angles, x] or [angles, y, x] where
       y is the tilt axis and x is the projection axis.
    angles : list or NumPy array
        Projection angles in degrees.
    thickness : int or float
        Number of pixels in the projection (through-thickness) direction
        for the reconstructed volume.  If None, thickness is set to be the
        same as that in the x-direction of the sinogram.
    iterations : integer
        Number of iterations for the SIRT reconstruction.
    constrain : boolean
        If True, output reconstruction is constrained above value given by
        'thresh'. Default is True.
    thresh : integer or float
        Value above which to constrain the reconstructed data if 'constrain'
        is True.
    cuda : boolean
        If True, use the CUDA-accelerated Astra algorithms. Otherwise,
        use the CPU-based algorithms
    Returns
    ----------
    rec : Numpy array
        3D array of the form [y, z, x] containing the reconstructed object.

    """
    sino = sinogram.data[:, 0, :]
    thetas = angles * np.pi / 180

    n_angles, x_pix = sino.shape

    thickness = x_pix

    rec = np.zeros([thickness, x_pix], sino.dtype)
    vol_geom = astra.create_vol_geom(thickness, x_pix)
    proj_geom = astra.create_proj_geom('parallel', 1, x_pix, thetas)
    data_id = astra.data2d.create('-sino', proj_geom, sino)
    rec_id = astra.data2d.create('-vol', vol_geom)

    if cuda:
        cfg = astra.astra_dict('SIRT_CUDA')
    else:
        proj_id = astra.create_projector('strip', proj_geom, vol_geom)
        cfg = astra.astra_dict('SIRT')
        cfg['ProjectorId'] = proj_id

    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = data_id
    if constrain:
        cfg['option'] = {}
        cfg['option']['MinConstraint'] = thresh

    alg_id = astra.algorithm.create(cfg)
    residual_error = np.zeros(iterations)
    rec_stack = np.zeros([iterations, thickness, x_pix])

    for i in range(iterations):
        astra.algorithm.run(alg_id, 1)
        rec = astra.data2d.get(rec_id)
        rec_stack[i] = rec

        forward_project = astra_project(rec, angles=angles, cuda=cuda)[:, 0, :]
        residual_error[i] = np.sqrt(np.square(forward_project - sino).sum())

    astra.clear()
    return rec_stack, residual_error
Beispiel #7
0
def astra_fbp(stack, angles, thickness=None, cuda=False):
    """
    Perform SIRT reconstruction using the Astra toolbox algorithms.

    Args
    ----------
    stack : NumPy array
       Tilt series data either of the form [angles, x] or [angles, y, x] where
       y is the tilt axis and x is the projection axis.
    angles : list or NumPy array
        Projection angles in degrees.
    thickness : int or float
        Number of pixels in the projection (through-thickness) direction
        for the reconstructed volume.  If None, thickness is set to be the
        same as that in the x-direction of the sinogram.
    cuda : boolean
        If True, use the CUDA-accelerated Astra algorithms. Otherwise,
        use the CPU-based algorithms
    Returns
    ----------
    rec : Numpy array
        3D array of the form [y, z, x] containing the reconstructed object.

    """
    thetas = angles * np.pi / 180

    if len(stack.shape) == 2:
        data = np.expand_dims(stack, 1)
    else:
        data = stack
    data = np.rollaxis(data, 1)
    y_pix, n_angles, x_pix = data.shape

    if thickness is None:
        thickness = data.shape[2]

    if cuda:
        rec = np.zeros([y_pix, thickness, x_pix], data.dtype)

        vol_geom = astra.create_vol_geom(thickness, x_pix)
        proj_geom = astra.create_proj_geom('parallel', 1, x_pix, thetas)
        data_id = astra.data2d.create('-sino', proj_geom)
        rec_id = astra.data2d.create('-vol', vol_geom)

        cfg = astra.astra_dict('FBP_CUDA')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = data_id
        cfg['option'] = {}
        cfg['option']['FilterType'] = 'ram-lak'

        alg_id = astra.algorithm.create(cfg)

        for i in range(0, y_pix):
            astra.data2d.store(data_id, data[i, :, :])
            astra.algorithm.run(alg_id)
            rec[i, :, :] = astra.data2d.get(rec_id)

        astra.algorithm.delete(alg_id)
        astra.data3d.delete(rec_id)
        astra.data3d.delete(data_id)

    else:
        rec = np.zeros([y_pix, thickness, x_pix], data.dtype)
        vol_geom = astra.create_vol_geom(thickness, x_pix)
        proj_geom = astra.create_proj_geom('parallel', 1.0, x_pix, thetas)
        proj_id = astra.create_projector('strip', proj_geom, vol_geom)
        rec_id = astra.data2d.create('-vol', vol_geom)
        sinogram_id = astra.data2d.create('-sino', proj_geom, data[0, :, :])
        cfg = astra.astra_dict('FBP')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
        cfg['ProjectorId'] = proj_id
        cfg['option'] = {}
        cfg['option']['FilterType'] = 'ram-lak'

        alg_id = astra.algorithm.create(cfg)
        for i in range(0, y_pix):
            astra.data2d.store(sinogram_id, data[i, :, :])
            astra.algorithm.run(alg_id)
            rec[i, :, :] = astra.data2d.get(rec_id)

        astra.algorithm.delete(alg_id)
        astra.data2d.delete(rec_id)
        astra.data2d.delete(sinogram_id)
        astra.clear()
    return rec
Beispiel #8
0
def astra_sirt(stack,
               angles,
               thickness=None,
               iterations=50,
               constrain=True,
               thresh=0,
               cuda=False):
    """
    Perform SIRT reconstruction using the Astra toolbox algorithms.

    Args
    ----------
    stack : NumPy array
       Tilt series data either of the form [angles, x] or [angles, y, x] where
       y is the tilt axis and x is the projection axis.
    angles : list or NumPy array
        Projection angles in degrees.
    thickness : int or float
        Number of pixels in the projection (through-thickness) direction
        for the reconstructed volume.  If None, thickness is set to be the
        same as that in the x-direction of the sinogram.
    iterations : integer
        Number of iterations for the SIRT reconstruction.
    constrain : boolean
        If True, output reconstruction is constrained above value given by
        'thresh'. Default is True.
    thresh : integer or float
        Value above which to constrain the reconstructed data if 'constrain'
        is True.
    cuda : boolean
        If True, use the CUDA-accelerated Astra algorithms. Otherwise,
        use the CPU-based algorithms
    Returns
    ----------
    rec : Numpy array
        3D array of the form [y, z, x] containing the reconstructed object.

    """
    thetas = angles * np.pi / 180

    if len(stack.shape) == 2:
        data = np.expand_dims(stack, 1)
    else:
        data = stack
    data = np.rollaxis(data, 1)
    y_pix, n_angles, x_pix = data.shape

    if thickness is None:
        thickness = data.shape[2]

    if cuda:
        chunksize = 128
        rec = np.zeros([y_pix, thickness, x_pix], data.dtype)
        nchunks = int(np.ceil(y_pix / chunksize))

        if nchunks == 1:
            chunksize = y_pix
            chunk_list = [[0, y_pix]]
        else:
            chunk_list = [None] * nchunks
            for i in range(0, int(y_pix / chunksize)):
                chunk_list[i] = [i * chunksize, (i + 1) * chunksize]
            if (np.mod(y_pix, chunksize) != 0) and (nchunks > 1):
                chunk_list[-1] = [
                    chunk_list[-2][1],
                    chunk_list[-2][1] + np.mod(y_pix, chunksize)
                ]

        for i in range(0, len(chunk_list)):
            chunk = data[chunk_list[i][0]:chunk_list[i][1], :, :]
            vol_geom = astra.create_vol_geom(thickness, x_pix, chunk.shape[0])
            proj_geom = astra.create_proj_geom('parallel3d', 1, 1,
                                               chunk.shape[0], x_pix, thetas)
            data_id = astra.data3d.create('-proj3d', proj_geom, chunk)
            rec_id = astra.data3d.create('-vol', vol_geom)

            cfg = astra.astra_dict('SIRT3D_CUDA')
            cfg['ReconstructionDataId'] = rec_id
            cfg['ProjectionDataId'] = data_id
            if constrain:
                cfg['option'] = {}
                cfg['option']['MinConstraint'] = thresh

            alg_id = astra.algorithm.create(cfg)

            astra.algorithm.run(alg_id, iterations)

            rec[chunk_list[i][0]:chunk_list[i][1], :, :] =\
                astra.data3d.get(rec_id)
            astra.algorithm.delete(alg_id)
            astra.data3d.delete(rec_id)
            astra.data3d.delete(data_id)

    else:
        rec = np.zeros([y_pix, thickness, x_pix], data.dtype)
        vol_geom = astra.create_vol_geom(thickness, x_pix)
        proj_geom = astra.create_proj_geom('parallel', 1.0, x_pix, thetas)
        proj_id = astra.create_projector('strip', proj_geom, vol_geom)
        rec_id = astra.data2d.create('-vol', vol_geom)
        sinogram_id = astra.data2d.create('-sino', proj_geom, data[0, :, :])
        cfg = astra.astra_dict('SIRT')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
        cfg['ProjectorId'] = proj_id
        if constrain:
            cfg['option'] = {}
            cfg['option']['MinConstraint'] = thresh

        alg_id = astra.algorithm.create(cfg)
        for i in range(0, y_pix):
            astra.data2d.store(sinogram_id, data[i, :, :])
            astra.algorithm.run(alg_id, iterations)
            rec[i, :, :] = astra.data2d.get(rec_id)

        astra.algorithm.delete(alg_id)
        astra.data2d.delete(rec_id)
        astra.data2d.delete(sinogram_id)
        astra.clear()
    return rec