Esempio n. 1
0
    def single_test_adjoint3D(self, geom_type, proj_type):
        for vg in VolumeGeometries(True, True):
            for pg in ProjectionGeometries(geom_type):
                for i in range(5):
                    X = np.random.random(astra.geom_size(vg))
                    Y = np.random.random(astra.geom_size(pg))
                    proj_id, fX = astra.create_sino3d_gpu(X, pg, vg)
                    bp_id, fTY = astra.create_backprojection3d_gpu(Y, pg, vg)

                    astra.data3d.delete([proj_id, bp_id])

                    da = np.dot(fX.ravel(), Y.ravel())
                    db = np.dot(X.ravel(), fTY.ravel())
                    m = np.abs(da - db)
                    TOL = 1e-1
                    if m / da >= TOL:
                        print(vg)
                        print(pg)
                        print(m / da, da / db, da, db)
                    self.assertTrue(m / da < TOL)
Esempio n. 2
0
def do_AGD(meta, vecs, sc, g, niter):
    start = time.time()
    ang, u, v = g.shape
    g_vec = np.transpose(g.copy(), (2, 0, 1))
    vox = 1024 // sc
    pix_size = meta['pix_size'] * sc
    src_rad = meta['s2o']
    det_rad = meta['o2d']
    magn = src_rad / (src_rad + det_rad)
    bounds = vox * pix_size * magn / 2
    vol_geom = astra.create_vol_geom(vox, vox, vox, -bounds, bounds, -bounds,
                                     bounds, -bounds, bounds)

    proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)

    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)
    # %%
    projector_id = astra.create_projector('cuda3d', proj_geom, vol_geom)

    #    rec_id = astra.data3d.create('-vol', vol_geom)

    proj_id = astra.data3d.create('-proj3d', proj_geom, g_vec)

    astra.plugin.register(NesterovGradient.AcceleratedGradientPlugin)
    cfg_agd = astra.astra_dict('AGD-PLUGIN')
    cfg_agd['ProjectionDataId'] = proj_id
    cfg_agd['ReconstructionDataId'] = rec_id
    cfg_agd['ProjectorId'] = projector_id
    cfg_agd['option'] = {}
    cfg_agd['option']['MinConstraint'] = 0
    alg_id = astra.algorithm.create(cfg_agd)

    # Run Nesterov Accelerated Gradient Descent algorithm with 'nb_iter' iterations

    astra.algorithm.run(alg_id, niter)
    rec = np.transpose(rec, (2, 1, 0))
    # %%
    pylab.figure()
    pylab.imshow(rec[vox // 2, :, :])
    pylab.figure()
    pylab.imshow(rec[:, vox // 2, :])
    pylab.figure()
    pylab.imshow(rec[:, :, vox // 2])

    # release memory allocated by ASTRA structures
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(proj_id)
    astra.data3d.delete(rec_id)
    print((time.time() - start), 'Finished AGD 50 reconstructionn')
    return rec
Esempio n. 3
0
def FDK_astra(g, filt, geom, reco_space, ang_freq=None):
    # %% Create geometry
    # Make a circular scanning geometry
    ang, u, v = g.shape
    minvox = reco_space.min_pt[0]
    maxvox = reco_space.max_pt[0]
    vol_geom = astra.create_vol_geom(v, v, v, minvox, maxvox, minvox, maxvox,
                                     minvox, maxvox)
    w_du, w_dv = (geom.detector.partition.max_pt \
                    -geom.detector.partition.min_pt) / np.array([u,v])
    if ang_freq is not None:
        angles = np.linspace(np.pi / 500, (2 + 1 / 500) * np.pi, 500,
                             False)[::ang_freq]
    else:
        angles = np.linspace(np.pi / ang, (2 + 1 / ang) * np.pi, ang, False)

    proj_geom = astra.create_proj_geom('cone', w_du, w_dv, v, u, angles,
                                       geom.src_radius, geom.det_radius)
    g = np.transpose(np.asarray(g.copy()), (2, 0, 1))
    # %%
    # Create a data object for the reconstruction
    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)
    #    rec_id = astra.data3d.create('-vol', vol_geom)

    proj_id = astra.data3d.create('-proj3d', proj_geom, g)

    #    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    fullFilterSize = int(2**(np.ceil(np.log2(2 * u))))
    halfFilterSize = fullFilterSize // 2 + 1
    # %% Make the matrix columns of the matrix B
    filter2d = np.zeros((ang, halfFilterSize))
    for i in range(ang):
        filter2d[i, :] = filt * 4 * w_du

    # %% Make a filter geometry
    filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                         angles)
    filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
    #

    cfg = astra.astra_dict('FDK_CUDA')
    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = proj_id
    cfg['option'] = {'FilterSinogramId': filter_id}
    # Create the algorithm object from the configuration structure
    alg_id = astra.algorithm.create(cfg)

    # %%
    astra.algorithm.run(alg_id)
    rec = np.transpose(rec, (2, 1, 0))

    # %%
    # 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(proj_id)
    astra.data2d.delete(filter_id)
    return rec
Esempio n. 4
0
def NNFDK_astra(g,
                NW,
                geom,
                reco_space,
                w_du,
                Exp_op,
                node_output,
                ang_freq=None):
    # %% Create geometry
    # Make a circular scanning geometry
    ang, u, v = g.shape
    minvox = reco_space.min_pt[0]
    maxvox = reco_space.max_pt[0]
    vox = np.shape(reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    if type(geom) == np.ndarray:
        vecs = geom
        proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)
    elif type(geom) == odl.tomo.geometry.conebeam.ConeFlatGeometry:
        angles = np.linspace((1 / ang) * np.pi, (2 + 1 / ang) * np.pi, ang,
                             False)
        w_du, w_dv = 2 * geom.detector.partition.max_pt / [u, v]
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           geom.src_radius, geom.det_radius)

    g = np.transpose(np.asarray(g), (2, 0, 1))
    # %%
    proj_id = astra.data3d.create('-proj3d', proj_geom, g)
    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)

    rec_tot = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)

    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    fullFilterSize = int(2**(np.ceil(np.log2(u)) + 1))
    halfFilterSize = fullFilterSize // 2 + 1
    filter2d = np.zeros((ang, halfFilterSize))
    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Make a filter geometry

    filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                         np.zeros(ang))

    cfg = astra.astra_dict('FDK_CUDA')
    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = proj_id

    # Create the algorithm object from the configuration structure
    # %%
    # Set a container list for the learned filters
    h_e = []
    if node_output:
        mid = v // 2
        node_output_axis = []

    for i in range(NW['nNodes']):
        h = NW['l1'][:-1, i] * 2 * NW['sc1'][0, :]
        h_e += [h]
        b = NW['l1'][-1, i] + np.sum(
            NW['l1'][:-1, i]) + 2 * np.dot(NW['l1'][:-1, i], NW['sc1'][1, :])
        filter2d = Exp_op_FFT(Exp_op, h, filter2d, Resize_Op, w_du)

        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        cfg['option'] = {'FilterSinogramId': filter_id}
        alg_id = astra.algorithm.create(cfg)
        astra.algorithm.run(alg_id)
        rec_tot = hidden_layer(rec, rec_tot, NW['l2'][i], b)
        if node_output:
            rec2 = hidden_layer(rec, 0, NW['l2'][i], b)
            node_output_axis += [
                rec2[:, :, mid], rec2[:, mid, :], rec2[mid, :, :]
            ]

    # Make a numpy array of the filter list
    h_e = np.asarray(h_e)
    # b_o = self.network['l2'][-1]
    rec_tot = outer_layer(rec_tot, NW['l2'][-1], NW['sc2'][0], NW['sc2'][1])
    rec_tot = np.transpose(rec_tot, (2, 1, 0))

    # %% Make the matrix columns of the matrix B

    # %%
    # 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(proj_id)
    if node_output:
        return rec_tot, h_e, node_output_axis
    else:
        return rec_tot, h_e
def FDK_astra(g, filt, geom, reco_space, w_du, ang_freq=None, ang_offset=0):
    # %% Create geometry
    # Make a circular scanning geometry
    ang, u, v = g.shape
    minvox = reco_space.min_pt[0]
    maxvox = reco_space.max_pt[0]
    vox = np.shape(reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)
    # Build the projection geometry, through vecs or odl geometry
    if type(geom) == np.ndarray:
        vecs = geom
        proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)
    elif type(geom) == odl.tomo.geometry.conebeam.ConeFlatGeometry:
        angles = np.linspace((1 / ang) * np.pi + ang_offset,
                             (2 + 1 / ang) * np.pi + ang_offset, ang, False)
        w_du, w_dv = 2 * geom.detector.partition.max_pt / [u, v]
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           geom.src_radius, geom.det_radius)
    elif geom == 'xHQ':
        ang = 1000
        src_rad = 100
        det_rad = 0
        angles = np.linspace((1 / ang) * np.pi, (2 + 1 / ang) * np.pi, ang,
                             False)
        #        angles = np.linspace(0, (2) * np.pi, ang,
        #                      False)
        obj_size = 2 * reco_space.max_pt[0]
        w_du = 2 * obj_size / u
        w_dv = obj_size / v
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           src_rad * obj_size,
                                           det_rad * obj_size)
    g = np.transpose(np.asarray(g.copy()), (2, 0, 1))

    cfg = astra.astra_dict('FDK_CUDA')
    # %%
    # Create a data object for the reconstruction
    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)
    #    rec_id = astra.data3d.create('-vol', vol_geom)

    proj_id = astra.data3d.create('-proj3d', proj_geom, g)

    #    rec_id = astra.data3d.link('-vol', vol_geom, rec)
    #    if geom == 'xHQ':
    #        cfg['option'] = { 'FilterType': 'hann' }
    #    else:
    fullFilterSize = int(2**(np.ceil(np.log2(2 * u))))
    halfFilterSize = fullFilterSize // 2 + 1
    # %% Make the matrix columns of the matrix B
    filter2d = np.zeros((ang, halfFilterSize))
    for i in range(ang):
        filter2d[i, :] = filt * 4 * w_du

    # %% Make a filter geometry
    filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                         np.zeros((ang)))
    filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
    cfg['option'] = {'FilterSinogramId': filter_id}

    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = proj_id

    # Create the algorithm object from the configuration structure
    alg_id = astra.algorithm.create(cfg)

    # %%
    astra.algorithm.run(alg_id)
    rec = np.transpose(rec, (2, 1, 0))

    # %%
    # 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(proj_id)
    if geom == 'xHQ':
        pass
    else:
        astra.data2d.delete(filter_id)
    return rec
Esempio n. 6
0
import astra
import numpy as np
import pygpu
import pylab

# Initialize pygpu
ctx = pygpu.init('cuda')
pygpu.set_default_context(ctx)

vol_geom = astra.create_vol_geom(128, 128, 128)
angles = np.linspace(0, 2 * np.pi, 180, False)
proj_geom = astra.create_proj_geom('cone', 1.0, 1.0, 128, 192, angles, 1000, 0)

# Create a simple hollow cube phantom, as a pygpu gpuarray
vol_gpuarr = pygpu.gpuarray.zeros(astra.geom_size(vol_geom), dtype='float32')
vol_gpuarr[17:113, 17:113, 17:113] = 1
vol_gpuarr[33:97, 33:97, 33:97] = 0

# Create a pygpu gpuarray for the output projection data
proj_gpuarr = pygpu.gpuarray.zeros(astra.geom_size(proj_geom), dtype='float32')

# Create the astra GPULink objects and create astra data3d objects from them
z, y, x = proj_gpuarr.shape
proj_data_link = astra.data3d.GPULink(proj_gpuarr.gpudata, x, y, z,
                                      proj_gpuarr.strides[-2])
z, y, x = vol_gpuarr.shape
vol_link = astra.data3d.GPULink(vol_gpuarr.gpudata, x, y, z,
                                vol_gpuarr.strides[-2])

proj_id = astra.data3d.link('-sino', proj_geom, proj_data_link)
Esempio n. 7
0
def Create_dataset_ASTRA_sim(pix, phantom, angles, src_rad, noise, Exp_bin,
                             bin_param, **kwargs):
    if phantom == 'Defrise':
        phantom = 'Defrise random'
    if phantom == 'Fourshape_test':
        phantom = 'Fourshape'

    if 'MaxVoxDataset' in kwargs:
        MaxVoxDataset = kwargs['MaxVoxDataset']

    else:
        MaxVoxDataset = np.max([int(pix**3 * 0.005), 1 * 10**6])

    # The size of the measured objects in voxels
    voxels = [pix, pix, pix]
    dpix = [voxels[0] * 2, voxels[1]]
    u, v = dpix
    # ! ! ! This will lead to some problems later on ! ! !
    det_rad = 0
    data_obj = ddf.phantom(voxels,
                           phantom,
                           angles,
                           noise,
                           src_rad,
                           det_rad,
                           compute_xHQ=True)
    WV_obj = ddf.support_functions.working_var_map()
    WV_path = WV_obj.WV_path
    data_obj.make_mask(WV_path)
    Smat = Make_Smat(voxels, MaxVoxDataset, WV_path)
    # %% saving tiffs for CNNs
    w_du = data_obj.w_detu
    filt = make_hann_filt(voxels, w_du)
    xFDK = ddf.FDK_ODL_astra_backend.FDK_astra(data_obj.g, filt,
                                               data_obj.geometry,
                                               data_obj.reco_space, None)

    # %% Create geometry
    # Make a circular scanning geometry
    minvox = data_obj.reco_space.min_pt[0]
    maxvox = data_obj.reco_space.max_pt[0]
    vox = np.shape(data_obj.reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    ang = np.linspace((1 / angles) * np.pi, (2 + 1 / angles) * np.pi, angles,
                      False)
    w_du, w_dv = 2 * data_obj.geometry.detector.partition.max_pt / [u, v]
    proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, ang,
                                       data_obj.geometry.src_radius,
                                       data_obj.geometry.det_radius)
    filter_part = odl.uniform_partition(-data_obj.detecsize[0],
                                        data_obj.detecsize[0], u)

    filter_space = odl.uniform_discr_frompartition(filter_part,
                                                   dtype='float64')
    spf_space, Exp_op = ddf.support_functions.ExpOp_builder(bin_param,
                                                            filter_space,
                                                            interp=Exp_bin)
    nParam = np.size(spf_space)

    fullFilterSize = int(2**(np.ceil(np.log2(dpix[0])) + 1))
    halfFilterSize = fullFilterSize // 2 + 1

    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Create forward and backward projector
    #    project_id = astra.create_projector('cuda3d', proj_geom, vol_geom)
    #    W = astra.OpTomo(project_id)

    # %% Create data
    proj_data = np.transpose(np.asarray(data_obj.g), (2, 0, 1)).copy()
    #    W.FP(np.transpose(np.asarray(data_obj.f), (2, 1, 0)))

    # ! ! ! wat is deze? ! ! !
    # if noise is not None:
    #     g = add_poisson_noise(proj_data, noise[1])
    # else:
    g = proj_data

    proj_id = astra.data3d.link('-sino', proj_geom, g)

    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    B = np.zeros((MaxVoxDataset, nParam + 1))

    # %% Make the matrix columns of the matrix B
    for nP in range(nParam):
        unit_vec = spf_space.zero()
        unit_vec[nP] = 1
        filt = Exp_op(unit_vec)

        rs_filt = Resize_Op(filt)

        f_filt = np.real(np.fft.rfft(np.fft.ifftshift(rs_filt)))
        filter2d = np.zeros((angles, halfFilterSize))
        for i in range(angles):
            filter2d[i, :] = f_filt * 4 * w_du

        # %% Make a filter geometry
        filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                             np.zeros((angles)))

        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        #

        cfg = astra.astra_dict('FDK_CUDA')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = proj_id
        cfg['option'] = {'FilterSinogramId': filter_id}
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)

        # %%
        astra.algorithm.run(alg_id)
        rec = np.transpose(rec, (2, 1, 0))
        B[:, nP] = rec[Smat]
    # %%
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    B[:, -1] = data_obj.xHQ[Smat]
    #    B[:, -1] = data_obj.f[Smat]
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    return B, data_obj.xHQ, xFDK
Esempio n. 8
0
def Create_dataset_ASTRA_real(dataset,
                              pix_size,
                              src_rad,
                              det_rad,
                              ang_freq,
                              Exp_bin,
                              bin_param,
                              vox=None,
                              vecs=None):

    # ! ! ! We overide 'vox' and 'vecs' later on
    # The size of the measured objects in voxels
    data_obj = ddf.real_data(dataset,
                             pix_size,
                             src_rad,
                             det_rad,
                             ang_freq,
                             vox=vox,
                             vecs=vecs)
    g = np.ascontiguousarray(np.transpose(np.asarray(data_obj.g.copy()),
                                          (2, 0, 1)),
                             dtype=np.float32)
    v, ang, u = g.shape
    if vox is None:
        voxels = data_obj.voxels

    else:
        voxels = [vox, vox, vox]

    MaxVoxDataset = np.max([int(voxels[0]**3 * 0.005), 5 * 10**6])

    Smat = Make_Smat(voxels, MaxVoxDataset, '', real_data=dataset['mask'])

    # %% Create geometry
    geom = data_obj.geometry
    w_du = data_obj.pix_size
    dpix = [u, v]

    minvox = data_obj.reco_space.min_pt[0]
    maxvox = data_obj.reco_space.max_pt[0]
    vox = np.shape(data_obj.reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    # Build a vecs vector from the geometry, or load it
    if type(geom) == np.ndarray:
        vecs = geom
        proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)
    elif type(geom) == odl.tomo.geometry.conebeam.ConeFlatGeometry:
        angles = np.linspace((1 / ang) * np.pi, (2 + 1 / ang) * np.pi, ang,
                             False)
        w_du, w_dv = 2 * data_obj.geometry.detector.partition.max_pt / [u, v]
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           data_obj.geometry.src_radius,
                                           data_obj.geometry.det_radius)

    filter_part = odl.uniform_partition(-data_obj.detecsize[0],
                                        data_obj.detecsize[0], dpix[0])

    filter_space = odl.uniform_discr_frompartition(filter_part,
                                                   dtype='float64')
    spf_space, Exp_op = ddf.ExpOp_builder(bin_param,
                                          filter_space,
                                          interp=Exp_bin)

    nParam = np.size(spf_space)

    fullFilterSize = int(2**(np.ceil(np.log2(dpix[0])) + 1))
    halfFilterSize = fullFilterSize // 2 + 1

    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Create projection and reconstion objects
    proj_id = astra.data3d.link('-proj3d', proj_geom, g)

    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    B = np.zeros((MaxVoxDataset, nParam + 1))

    # %% Make the matrix columns of the matrix B
    for nP in range(nParam):
        unit_vec = spf_space.zero()
        unit_vec[nP] = 1
        filt = Exp_op(unit_vec)

        rs_filt = Resize_Op(filt)

        f_filt = np.real(np.fft.rfft(np.fft.ifftshift(rs_filt)))
        filter2d = np.zeros((ang, halfFilterSize))
        for i in range(ang):
            filter2d[i, :] = f_filt * 4 * w_du

        # %% Make a filter geometry
        filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                             np.zeros(ang))
        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        #

        cfg = astra.astra_dict('FDK_CUDA')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = proj_id
        cfg['option'] = {'FilterSinogramId': filter_id}
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)

        # %%
        astra.algorithm.run(alg_id)
        rec = np.transpose(rec, (2, 1, 0))
        B[:, nP] = rec[Smat]
    # %%
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    B[:, -1] = data_obj.f[Smat]
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    return B
Esempio n. 9
0
import astra
import numpy as np
import pygpu
import pylab

# Initialize pygpu
ctx = pygpu.init('cuda')
pygpu.set_default_context(ctx)

vol_geom = astra.create_vol_geom(128, 128, 128)
angles = np.linspace(0, 2 * np.pi, 180, False)
proj_geom = astra.create_proj_geom('cone', 1.0, 1.0, 128, 192, angles, 1000, 0)

# Create a simple hollow cube phantom, as a pygpu gpuarray
vol_gpuarr = pygpu.gpuarray.zeros(astra.geom_size(vol_geom), dtype='float32')
vol_gpuarr[17:113, 17:113, 17:113] = 1
vol_gpuarr[33:97, 33:97, 33:97] = 0

# Create a pygpu gpuarray for the output projection data
proj_gpuarr = pygpu.gpuarray.zeros(astra.geom_size(proj_geom), dtype='float32')

# Create the astra GPULink objects and create astra data3d objects from them
z, y, x = proj_gpuarr.shape
proj_data_link = astra.data3d.GPULink(proj_gpuarr.gpudata, x, y, z,
                                      proj_gpuarr.strides[-2])
z, y, x = vol_gpuarr.shape
vol_link = astra.data3d.GPULink(vol_gpuarr.gpudata, x, y, z,
                                vol_gpuarr.strides[-2])

proj_id = astra.data3d.link('-sino', proj_geom, proj_data_link)