Пример #1
0
def astrarecon(tilt_data,tilt_angles,iterations=1,geometry='parallel3d',SO_dist=1.0,OD_dist=1.0):
    proj_shape = np.shape(tilt_data)
    recon_shape = (proj_shape[2],proj_shape[2],proj_shape[1])
    
    vol_geom = astra.create_vol_geom(recon_shape)

    angles = np.pi*tilt_angles/180
    
    if geometry == 'parallel3d':
        proj_geom = astra.create_proj_geom(geometry, 1.0, 1.0, proj_shape[1], proj_shape[2], angles)
        cfg = astra.astra_dict('SIRT3D_CUDA')
    elif geometry == 'cone':
        proj_geom = astra.create_proj_geom(geometry, 1.0, 1.0, proj_shape[1], proj_shape[2], angles, SO_dist, OD_dist)
        cfg = astra.astra_dict('FDK_CUDA')
        
    proj_id = astra.data3d.create('-proj3d', proj_geom, np.swapaxes(tilt_data,0,1))
    
    rec_id = astra.data3d.create('-vol', vol_geom)
    
    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = proj_id
    
    alg_id = astra.algorithm.create(cfg)
    
    astra.algorithm.run(alg_id, iterations)
    
    rec = astra.data3d.get(rec_id)
    
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    
    return(rec)
Пример #2
0
 def geom_setup_2D(self, sino, angles, shape, cors):
     p_low, p_high = self.array_pad(cors, self.nCols)
     sino = np.pad(sino, ((0, 0), (p_low, p_high)), mode='reflect')
     vol_geom = astra.create_vol_geom(shape[0], shape[1])
     proj_geom = astra.create_proj_geom('parallel', 1.0, sino.shape[1],
                                        np.deg2rad(angles))
     return sino, vol_geom, proj_geom
Пример #3
0
def recon_mr_fbp(im, angles, cor_shift):
    """Reconstruct a sinogram with the Minimum Residual FBP algorithm (Pelt, 2013).

	Parameters
	----------
	im : array_like
		Sinogram image data as numpy array.

	angles : double
		Value in radians representing the number of angles of the input sinogram.
	
	"""
    # Create ASTRA geometries:
    vol_geom = astra.create_vol_geom(im.shape[1], im.shape[1])
    proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1],
                                       linspace(0, angles, im.shape[0], False))

    # Projection geometry with shifted center of rotation (doesn't work apparently):
    #proj_geom = astra.geom_postalignment(proj_geom, cor_shift);

    # Create the ASTRA projector:
    p = mrfbp.ASTRAProjector.ASTRAProjector2D(proj_geom, vol_geom)

    # Create the MR-FBP Reconstructor:
    rec = mrfbp.Reconstructor(p)

    # Reconstruct the image using MR-FBP:
    im_rec = rec.reconstruct(im)

    return im_rec.astype(float32)
Пример #4
0
def bp0(sino, det_col=111, num_angles=222, voxel_size_mm=1):
    """Wrapper for astra forward projector

    :param sino:
    :param projector_id:
    :return: backprojected sinogram
    """

    vol_geom = astra.create_vol_geom(sino.shape)
    proj_id = astra.create_projector(
        'cuda',
        astra.create_proj_geom('parallel', 1.0, det_col,
                               np.linspace(0, np.pi, num_angles, False)),
        vol_geom)


    rec_id, backprojection = astra.create_backprojection(sino * voxel_size_mm,
                                                   proj_id)

    # rec_id, backprojection = astra.create_backprojection(sino, projector_id)

    # backprojection /= sino.shape[0]
    # backprojection *= np.pi
    astra.data2d.delete(rec_id)
    astra.projector.delete(proj_id)

    return backprojection
Пример #5
0
def pid(number_of_angles):
    """Return projector ID.
    :param number_of_angles:
    :return:
    """
    return astra.create_projector('cuda', astra.create_proj_geom('parallel',
    1.0, vshape[0], np.linspace(0, np.pi, number_of_angles, False)), vol_geom)
Пример #6
0
 def run(self, iterations):
     self.fn = getFilterFile(self.fd, self.pg, iterations, self.rg, self.osz)
     if os.path.exists(self.fn):
         flt = np.load(self.fn)
         self.v[:] = self.customFBP(flt)
         return
     nd = self.nd
     if self.osz:
         nds = self.osz
     else:
         nds = nd
     na = len(self.ang)
     pgc = astra.create_proj_geom('parallel',1.0,nd,self.ang)
     vgc = astra.create_vol_geom((nds,nds))
     pidc = astra.create_projector('strip',pgc,vgc)
     x = np.zeros((nds,nds))
     xs = np.zeros((nds,nds))
     sf = np.zeros((na,nd))
     vid = astra.data2d.create('-vol',vgc)
     sid = astra.data2d.create('-sino',pgc)
     cfg = astra.astra_dict('FP')
     cfg['ProjectorId']=pidc
     cfg['ProjectionDataId']=sid
     cfg['VolumeDataId']=vid
     fpid = astra.algorithm.create(cfg)
     cfg = astra.astra_dict('BP')
     cfg['ProjectorId']=pidc
     cfg['ProjectionDataId']=sid
     cfg['ReconstructionDataId']=vid
     bpid = astra.algorithm.create(cfg)
     vc = astra.data2d.get_shared(vid)
     sc = astra.data2d.get_shared(sid)
     x[nds//2,nds//2]=1
     alp = 1./(na*nds)
     if self.rg:
         if self.rg*alp >=0.1:
             alp = 0.1/self.rg
     astra.log.info('Computing filter...')
     for i in range(iterations):
         if i%10==0: astra.log.info('{:.2f} % done'.format(100*float(i)/iterations))
         xs+=x
         vc[:] = x
         astra.algorithm.run(fpid)
         astra.algorithm.run(bpid)
         if self.rg:
             dx = x[:-1,:] - x[1:,:]
             dy = x[:,:-1] - x[:,1:]
             x[:-1,:] -= self.rg*dx*alp
             x[1:,:] += self.rg*dx*alp
             x[:,:-1] -= self.rg*dy*alp
             x[:,1:] += self.rg*dy*alp
         x -= vc*alp
     vc[:] = xs
     astra.algorithm.run(fpid)
     flt = sc.copy()*alp
     astra.algorithm.delete([fpid,bpid])
     astra.algorithm.delete([vid,sid])
     np.save(self.fn,flt)
     self.v[:] = self.customFBP(flt)
     astra.projector.delete(pidc)
Пример #7
0
def FBP_reconstruction(projections, scanner_params, proj_vecs, voxel_size=.1, rec_shape=501, vol_center=0, **kwargs):

    astra.astra.set_gpu_index(globals().get('GPU_ID', kwargs.get('gpu_id', -1)))

    # from [proj_slc,rows,cols] to [rows,proj_slc,cols]
    projections = np.transpose(projections, (1,0,2))
    proj_geom = astra.create_proj_geom('cone_vec', *scanner_params.detector_effective_size, proj_vecs)    
    projections_id = astra.data3d.create('-sino', proj_geom, projections)

    # [z,x,y] to [y,x,z] axis transposition
    vol_center = tuple([vol_center[i] for i in [2,1,0]]) if isinstance(vol_center, tuple) else (vol_center,) *3
    reconstructed_shape = tuple([rec_shape[i] for i in [2,1,0]]) if isinstance(rec_shape, tuple) else (rec_shape,) *3
    
    vol_geom = astra.creators.create_vol_geom(*reconstructed_shape,
        *[center+sign*size/2*voxel_size for center, size in zip(vol_center, reconstructed_shape) for sign in [-1, 1]]
    )
    reconstruction_id = astra.data3d.create('-vol', vol_geom, data=0)

    alg_cfg = astra.astra_dict('BP3D_CUDA')
    alg_cfg['ProjectionDataId'] = projections_id
    alg_cfg['ReconstructionDataId'] = reconstruction_id
    algorithm_id = astra.algorithm.create(alg_cfg)

    astra.algorithm.run(algorithm_id)
    reconstruction = astra.data3d.get(reconstruction_id)

    # Free ressources
    astra.algorithm.delete(algorithm_id)
    astra.data3d.delete([projections_id, reconstruction_id])

    return reconstruction
Пример #8
0
def run_soft_ineq(data, name, alpha, bound):
    d_pr, M, m = check_bounds(data['data'], bound, 0)
    pixel_size = 1.0
    proj_geom = astra.create_proj_geom(
        'parallel',
        pixel_size,
        d_pr.shape[1],
        data['angles']
    )

    rec_pix = d_pr.shape[1]

    vol_geom = astra.create_vol_geom(rec_pix, rec_pix)
    projector = astra.create_projector('linear', proj_geom, vol_geom)

    res = ineq_linear_least_squares(1.0, 
        proj_geom, vol_geom,
        np.exp(-d_pr), projector, np.exp(-bound),
        alpha)

    plt.figure()
    plt.imshow(res, cmap=plt.cm.viridis)
    plt.colorbar(orientation='horizontal')
    name_suffix = '%s_a%.1f' % (name, alpha)
    plt.title("%s, alpha %.1f" % (name, alpha))
    plt.savefig('soft_ineq_' + name_suffix + '.png')
    # plt.show(block=False)
    np.savetxt(name_suffix, res)
Пример #9
0
def astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter, proj_type, gpu_index, opts):
    # Lazy import ASTRA
    import astra as astra_mod
    nslices, nang, ndet = tomo.shape
    cfg = astra_mod.astra_dict(opts['method'])
    if 'extra_options' in opts:
        # NOTE: we are modifying 'extra_options' and so need to make a copy
        cfg['option'] = copy.deepcopy(opts['extra_options'])
    else:
        cfg['option'] = {}
    if gpu_index is not None:
        cfg['option']['GPUindex'] = gpu_index
    oc = None
    const_theta = np.ones(nang)
    proj_geom = astra_mod.create_proj_geom(
        'parallel', 1.0, ndet, theta.astype(np.float64))
    for i in range(nslices):
        if center[i] != oc:
            oc = center[i]
            proj_geom['option'] = {
                'ExtraDetectorOffset':
                (center[i] - ndet / 2.) * const_theta}
        pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom)
        cfg['ProjectorId'] = pid
        sid = astra_mod.data2d.link('-sino', proj_geom, tomo[i])
        cfg['ProjectionDataId'] = sid
        vid = astra_mod.data2d.link('-vol', vol_geom, recon[i])
        cfg['ReconstructionDataId'] = vid
        alg_id = astra_mod.algorithm.create(cfg)
        astra_mod.algorithm.run(alg_id, niter)
        astra_mod.algorithm.delete(alg_id)
        astra_mod.data2d.delete(vid)
        astra_mod.data2d.delete(sid)
        astra_mod.projector.delete(pid)
Пример #10
0
def recon_sirt_fbp(im, angles, iter, temppath ):
	"""Reconstruct a sinogram with the SIRT-FBP algorithm (Pelt, 2015).

	Parameters
	----------
	im : array_like
		Sinogram image data as numpy array.

    iter : int
		Number of iterations to be used for the computation of SIRT filter.

	angles : double
		Value in radians representing the number of angles of the input sinogram.
	
	"""
	# Create ASTRA geometries:
	vol_geom = astra.create_vol_geom(im.shape[1] , im.shape[1])
	proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1], linspace(0,angles,im.shape[0],False))
	proj = astra.create_projector('cuda', proj_geom, vol_geom)
	p = astra.OpTomo(proj)

	# Register plugin with ASTRA
	astra.plugin.register(sirtfbp.plugin)

	# Create the ASTRA projector
	im_rec = p.reconstruct('SIRT-FBP',im, iter, extraOptions={'filter_dir':temppath})
	
	return im_rec.astype(float32)
Пример #11
0
def run_fbp(data, bound):
    d_pr, M, m = check_bounds(data['data'], bound, 0)
    pixel_size = 1.0
    proj_geom = astra.create_proj_geom(
        'parallel',
        pixel_size,
        d_pr.shape[1],
        data['angles']
    )

    rec_pix = d_pr.shape[1]

    vol_geom = astra.create_vol_geom(rec_pix, rec_pix)
    projector = astra.create_projector('linear', proj_geom, vol_geom)

    res = fbp(1.0, proj_geom, vol_geom, np.exp(-d_pr), projector, np.exp(-bound))

    plt.figure()
    plt.imshow(res, cmap=plt.cm.viridis)
    plt.colorbar(orientation='vertical')
    name_suffix = 'FBP'
    plt.title("FBP")
    plt.savefig(name_suffix + '.png')
    np.savetxt(name_suffix, res)
    return res    
    def __init__(self, angles, img_size, det_count, sdist, ddist, det_spacing):
        self.angles = angles
        self.vol_geom = astra.create_vol_geom(img_size, img_size)
        self.proj_geom = astra.create_proj_geom('fanflat', det_spacing, det_count, self.angles, sdist, ddist)
        self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom)

        self.data2d = []
    def __init__(self, angles, img_size, det_count):
        self.angles = angles
        self.vol_geom = astra.create_vol_geom(img_size, img_size)
        self.proj_geom = astra.create_proj_geom('parallel', 1.0, det_count, self.angles)
        self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom)

        self.data2d = []
Пример #14
0
def recon_mr_fbp(im, angles):
	"""Reconstruct a sinogram with the Minimum Residual FBP algorithm (Pelt, 2013).

	Parameters
	----------
	im : array_like
		Sinogram image data as numpy array.

	angles : double
		Value in radians representing the number of angles of the input sinogram.
	
	"""
	# Create ASTRA geometries:
	vol_geom = astra.create_vol_geom(im.shape[1] , im.shape[1])
	proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1], linspace(0,angles,im.shape[0],False))

	# Create the ASTRA projector:
	p = mrfbp.ASTRAProjector.ASTRAProjector2D(proj_geom,vol_geom)
	
	# Create the MR-FBP Reconstructor:
	rec = mrfbp.Reconstructor(p)

	# Reconstruct the image using MR-FBP:
	im_rec = rec.reconstruct(im)
	
	return im_rec.astype(float32)
Пример #15
0
def gen_random_geometry_parallel():
  if not NONUNITDET:
    w = 1.0
  else:
    w = 0.8 + 0.4 * np.random.random()
  pg = astra.create_proj_geom('parallel', w, np.random.randint(*range2d), np.linspace(0, 2*np.pi, np.random.randint(*range2d), endpoint=False))
  return pg
Пример #16
0
def fbp(sinogram, geo):
    vol_geom = astra.create_vol_geom(geo["nVoxelY"], geo["nVoxelX"],
                                     -1 * geo["sVoxelY"] / 2,
                                     geo["sVoxelY"] / 2,
                                     -1 * geo["sVoxelX"] / 2,
                                     geo["sVoxelX"] / 2)
    proj_geom = astra.create_proj_geom(
        geo["mode"], geo["dDetecU"], geo["nDetecU"],
        np.linspace(geo["start_angle"], geo["end_angle"], geo["sino_views"],
                    False), geo["DSO"], geo["DOD"])
    if geo["mode"] is "parallel":
        proj_id = astra.create_projector("linear", proj_geom, vol_geom)
    elif geo["mode"] is "fanflat":
        proj_id = astra.create_projector("line_fanflat", proj_geom_full,
                                         vol_geom)

    rec_id = astra.data2d.create('-vol', vol_geom)
    sinogram_id = astra.data2d.create('-sino', proj_geom, sinogram)

    cfg = astra.astra_dict('FBP')
    cfg['ProjectorId'] = proj_id
    cfg["FilterType"] = "Ram-Lak"
    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = sinogram_id

    alg_id = astra.algorithm.create(cfg)
    astra.algorithm.run(alg_id)

    image_recon = astra.data2d.get(rec_id)
    astra.algorithm.delete(alg_id)
    astra.data2d.delete(rec_id)
    astra.data2d.delete(sinogram_id)

    return image_recon
Пример #17
0
    def __init__(self,
                 geometry_obj=Geometry(1),
                 vol_vector=None,
                 proj_vector=None, gpu_index=0):
        self.geom = geometry_obj
        if vol_vector is None:
            self.vol = Rn(self.geom.vol_size)
        else:
            self.vol = vol_vector
        if proj_vector is None:
            self.proj = Rn(self.geom.proj_size)
        else:
            self.proj = proj_vector
        self.gpu_index = gpu_index
        self.bp_id = None
        self.fp_id = None

        # Create volume geometry
        self.vol_geom = astra.create_vol_geom(self.geom.vol_shape)

        # Create projection geometry
        self.proj_geom = astra.create_proj_geom(
            self.geom.geom_type,
            self.geom.detector_spacing_x, self.geom.detector_spacing_y,
            self.geom.det_row_count, self.geom.det_col_count,
            self.geom.angles,
            self.geom.source_origin, self.geom.origin_detector)

        # Allocate ASTRA memory for volume data
        self.volume_id = astra.data3d.create('-vol', self.vol_geom)

        # Allocate ASTRA memory for projection data
        self.proj_id = astra.data3d.create('-sino', self.proj_geom)
Пример #18
0
def gen_random_geometry_fanflat():
  if not NONUNITDET:
    w = 1.0
  else:
    w = 0.6 + 0.8 * np.random.random()
  pg = astra.create_proj_geom('fanflat', w, np.random.randint(*range2d), np.linspace(0, 2*np.pi, np.random.randint(*range2d), endpoint=False), 256 * (0.5 + np.random.random()), 256 * np.random.random())
  return pg
Пример #19
0
    def _initialize_astra(self,
                          sz=None,
                          pixel_size=None,
                          det2obj=None,
                          src2obj=None,
                          theta=None):

        if sz is None: sz = self._parent.data.shape()
        if pixel_size is None:
            pixel_size = self._parent.meta.geometry['det_pixel']
        if det2obj is None: det2obj = self._parent.meta.geometry['det2obj']
        if src2obj is None: src2obj = self._parent.meta.geometry['src2obj']
        if theta is None: theta = self._parent.meta.theta

        # Initialize ASTRA (3D):
        det_count_x = sz[2]
        det_count_z = sz[0]

        # Make volume count x > detector count to include corneres of the object:
        vol_count_x = sz[2]
        vol_count_z = sz[0]

        tot_dist = det2obj + src2obj

        magnification = tot_dist / src2obj

        self.vol_geom = astra.create_vol_geom(vol_count_x, vol_count_x,
                                              vol_count_z)
        self.proj_geom = astra.create_proj_geom(
            'cone', magnification, magnification, det_count_z, det_count_x,
            theta, (src2obj * magnification) / pixel_size,
            (det2obj * magnification) / pixel_size)
Пример #20
0
    def single_sino(sino: np.ndarray,
                    cor: ScalarCoR,
                    proj_angles: ProjectionAngles,
                    recon_params: ReconstructionParameters,
                    progress: Optional[Progress] = None) -> np.ndarray:
        assert sino.ndim == 2, "Sinogram must be a 2D image"

        sino = BaseRecon.prepare_sinogram(sino, recon_params)
        image_width = sino.shape[1]

        if astra_mutex.locked():
            LOG.warning("Astra recon already in progress. Waiting")
        with astra_mutex:
            vectors = vec_geom_init2d(proj_angles, 1.0,
                                      cor.to_vec(image_width).value)
            vol_geom = astra.create_vol_geom((image_width, image_width))
            proj_geom = astra.create_proj_geom('parallel_vec', image_width,
                                               vectors)
            cfg = astra.astra_dict(recon_params.algorithm)
            cfg['FilterType'] = recon_params.filter_name

            with _managed_recon(sino, cfg, proj_geom,
                                vol_geom) as (alg_id, rec_id):
                astra.algorithm.run(alg_id, iterations=recon_params.num_iter)
                return astra.data2d.get(rec_id)
Пример #21
0
def astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter, proj_type,
                   gpu_index, opts):
    # Lazy import ASTRA
    import astra as astra_mod
    nslices, nang, ndet = tomo.shape
    cfg = astra_mod.astra_dict(opts['method'])
    if 'extra_options' in opts:
        #NOTE: we are modifying 'extra_options' and so need to make a copy
        cfg['option'] = copy.deepcopy(opts['extra_options'])
    else:
        cfg['option'] = {}
    if gpu_index is not None:
        cfg['option']['GPUindex'] = gpu_index
    oc = None
    const_theta = np.ones(nang)
    proj_geom = astra_mod.create_proj_geom('parallel', 1.0, ndet,
                                           theta.astype(np.float64))
    for i in range(nslices):
        if center[i] != oc:
            oc = center[i]
            proj_geom['option'] = {
                'ExtraDetectorOffset': (center[i] - ndet / 2.) * const_theta
            }
        pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom)
        cfg['ProjectorId'] = pid
        sid = astra_mod.data2d.link('-sino', proj_geom, tomo[i])
        cfg['ProjectionDataId'] = sid
        vid = astra_mod.data2d.link('-vol', vol_geom, recon[i])
        cfg['ReconstructionDataId'] = vid
        alg_id = astra_mod.algorithm.create(cfg)
        astra_mod.algorithm.run(alg_id, niter)
        astra_mod.algorithm.delete(alg_id)
        astra_mod.data2d.delete(vid)
        astra_mod.data2d.delete(sid)
        astra_mod.projector.delete(pid)
Пример #22
0
def recon_sirt_fbp(im, angles, iter, temppath):
    """Reconstruct a sinogram with the SIRT-FBP algorithm (Pelt, 2015).

	Parameters
	----------
	im : array_like
		Sinogram image data as numpy array.

    iter : int
		Number of iterations to be used for the computation of SIRT filter.

	angles : double
		Value in radians representing the number of angles of the input sinogram.
	
	"""
    # Create ASTRA geometries:
    vol_geom = astra.create_vol_geom(im.shape[1], im.shape[1])
    proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1],
                                       linspace(0, angles, im.shape[0], False))
    proj = astra.create_projector('cuda', proj_geom, vol_geom)
    p = astra.OpTomo(proj)

    # Register plugin with ASTRA
    astra.plugin.register(sirtfbp.plugin)

    # Create the ASTRA projector
    im_rec = p.reconstruct('SIRT-FBP',
                           im,
                           iter,
                           extraOptions={'filter_dir': temppath})

    return im_rec.astype(float32)
Пример #23
0
def astra_rec_cpu(tomo, center, recon, theta, vol_geom, niter, proj_type, opts):
    # Lazy import ASTRA
    import astra as astra_mod
    nslices, nang, ndet = tomo.shape
    cfg = astra_mod.astra_dict(opts['method'])
    if 'extra_options' in opts:
        cfg['option'] = opts['extra_options']
    proj_geom = astra_mod.create_proj_geom('parallel', 1.0, ndet, theta.astype(np.float64))
    pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom)
    sino = np.zeros((nang, ndet), dtype=np.float32)
    sid = astra_mod.data2d.link('-sino', proj_geom, sino)
    cfg['ProjectorId'] = pid
    cfg['ProjectionDataId'] = sid
    for i in range(nslices):
        shft = int(np.round(ndet / 2. - center[i]))
        if not shft == 0:
            sino[:] = np.roll(tomo[i], shft)
            l = shft
            r = ndet + shft
            if l < 0:
                l = 0
            if r > ndet:
                r = ndet
            sino[:, :l] = 0
            sino[:,  r:] = 0
        else:
            sino[:] = tomo[i]
        vid = astra_mod.data2d.link('-vol', vol_geom, recon[i])
        cfg['ReconstructionDataId'] = vid
        alg_id = astra_mod.algorithm.create(cfg)
        astra_mod.algorithm.run(alg_id, niter)
        astra_mod.algorithm.delete(alg_id)
        astra_mod.data2d.delete(vid)
    astra_mod.data2d.delete(sid)
    astra_mod.projector.delete(pid)
Пример #24
0
 def init(self, volume_data=1, projection_data=1):
     # Create volume geometry
     self.volume_geom = astra.create_vol_geom(self.num_voxel)
 
     # Create projection geometry
     self.projection_geom = astra.create_proj_geom(self.geometry_type,
                                        self.detector_spacing_x, self.detector_spacing_y,
                                        self.det_row_count, self.det_col_count,
                                        self.angles,
                                        self.source_origin, self.origin_detector)
 
     # Allocate and store volume data in ASTRA memory
     self.volume_id = astra.data3d.create('-vol', self.volume_geom, volume_data)
 
     # Allocate and store projection data in ASTRA memeory
     self.projection_id = astra.data3d.create('-sino', self.projection_geom, projection_data)
     
     # Create algorithm object: forward projector
     cfg = astra.astra_dict('FP3D_CUDA')
     cfg['option'] = {'GPUindex': self.gpu_index}
     cfg['ProjectionDataId'] = self.projection_id
     cfg['VolumeDataId'] = self.volume_id
     self.forward_alg_id = astra.algorithm.create(cfg)
     
     # Create algorithm object: backward projector
     cfg = astra.astra_dict('BP3D_CUDA')
     cfg['option'] = {'GPUindex': self.gpu_index}
     cfg['ProjectionDataId'] = self.projection_id
     cfg['ReconstructionDataId'] = self.volume_id
     self.backward_alg_id = astra.algorithm.create(cfg)
Пример #25
0
    def __init__(self,
                 geometry_obj=Geometry(1),
                 vol_vector=None,
                 proj_vector=None,
                 gpu_index=0):
        self.geom = geometry_obj
        if vol_vector is None:
            self.vol = Rn(self.geom.vol_size)
        else:
            self.vol = vol_vector
        if proj_vector is None:
            self.proj = Rn(self.geom.proj_size)
        else:
            self.proj = proj_vector
        self.gpu_index = gpu_index
        self.bp_id = None
        self.fp_id = None

        # Create volume geometry
        self.vol_geom = astra.create_vol_geom(self.geom.vol_shape)

        # Create projection geometry
        self.proj_geom = astra.create_proj_geom(
            self.geom.geom_type, self.geom.detector_spacing_x,
            self.geom.detector_spacing_y, self.geom.det_row_count,
            self.geom.det_col_count, self.geom.angles, self.geom.source_origin,
            self.geom.origin_detector)

        # Allocate ASTRA memory for volume data
        self.volume_id = astra.data3d.create('-vol', self.vol_geom)

        # Allocate ASTRA memory for projection data
        self.proj_id = astra.data3d.create('-sino', self.proj_geom)
Пример #26
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--width', type=int, required=True)
    parser.add_argument('--num-projections', type=int, required=True)
    parser.add_argument('--num-slices', type=int, required=True)

    args = parser.parse_args()
    angles = np.linspace(0,
                         np.pi,
                         args.num_projections,
                         False,
                         dtype=np.float64)

    vol_geom = astra.create_vol_geom(args.width, args.width, args.num_slices)
    proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, args.num_slices,
                                       args.width, angles)

    vid = astra.data3d.create('-vol', vol_geom)
    pid = astra.data3d.create('-proj3d', proj_geom, 0.0)

    config = astra.astra_dict('BP3D_CUDA')
    config['ProjectionDataId'] = pid
    config['ReconstructionDataId'] = vid

    aid = astra.algorithm.create(config)
    astra.algorithm.run(aid)
Пример #27
0
def create_example_parallel3d(example_type=''):
    """
    :brief:                 create an example of a parallel3d geometry
    :param example_type:    for the examples, there are different options
                            -   '' or 'normal':
                                example of a standard parallel geometry with 100 angles
                            -   'vec':
                                same geometry as for normal, but converted to a vector geometry
                                this gives a different plot visualizing the individual angles on
                                top of the geometry
    :return:                the example geometry
    """
    det_spacing = [0.035, 0.035]
    detector_px = [1000, 1000]
    angles = np.linspace(0, 2 * np.pi, 100)

    if example_type == '' or example_type == 'normal':
        proj_geom = astra.create_proj_geom('parallel3d', det_spacing[0],
                                           det_spacing[1], detector_px[0],
                                           detector_px[1], angles)
    elif example_type == 'vec':
        proj_geom = astra.geom_2vec(create_example_parallel3d())
    else:
        raise ValueError(
            "ASTRA: example type {0} not recognized for parallel3d geometry".
            format(example_type))

    return proj_geom
Пример #28
0
    def __init__(self, DetColumnCount, DetRowCount, AnglesVec, CenterRotOffset,
                 ObjSize, OS):
        self.ObjSize = ObjSize
        self.DetectorsDimV = DetRowCount
        if type(ObjSize) == tuple:
            Y, X, Z = [int(i) for i in ObjSize]
        else:
            Y = X = ObjSize
            Z = DetRowCount
        self.vol_geom = astra.create_vol_geom(Y, X, Z)

        ################ arrange ordered-subsets ################
        import numpy as np
        AnglesTot = np.size(AnglesVec)  # total number of angles
        self.NumbProjBins = (int)(np.ceil(
            float(AnglesTot) /
            float(OS)))  # get the number of projections per bin (subset)
        self.newInd_Vec = np.zeros(
            [OS, self.NumbProjBins],
            dtype='int')  # 2D array of OS-sorted indeces
        for sub_ind in range(OS):
            ind_sel = 0
            for proj_ind in range(self.NumbProjBins):
                indexS = ind_sel + sub_ind
                if (indexS < AnglesTot):
                    self.newInd_Vec[sub_ind, proj_ind] = indexS
                    ind_sel += OS

        # create full ASTRA geometry (to calculate Lipshitz constant)
        vectors = vec_geom_init3D(AnglesVec, 1.0, 1.0, CenterRotOffset)
        self.proj_geom = astra.create_proj_geom('parallel3d_vec', DetRowCount,
                                                DetColumnCount, vectors)
        # create OS-specific ASTRA geometry
        self.proj_geom_OS = {}
        for sub_ind in range(OS):
            self.indVec = self.newInd_Vec[sub_ind, :]
            if (self.indVec[self.NumbProjBins - 1] == 0):
                self.indVec = self.indVec[:-1]  #shrink vector size
            anglesOS = AnglesVec[self.indVec]  # OS-specific angles

            if np.ndim(CenterRotOffset) == 0:  # CenterRotOffset is a _scalar_
                vectors = vec_geom_init3D(anglesOS, 1.0, 1.0, CenterRotOffset)
            else:  # CenterRotOffset is a _vector_
                vectors = vec_geom_init3D(anglesOS, 1.0, 1.0,
                                          CenterRotOffset[self.indVec])
            self.proj_geom_OS[sub_ind] = astra.create_proj_geom(
                'parallel3d_vec', DetRowCount, DetColumnCount, vectors)
Пример #29
0
def FDK_reconstruction(projections,
                       scanner_params,
                       proj_vecs,
                       voxel_size=.1,
                       rec_shape=501,
                       **kwargs):
    """Uses FDK method to reconstruct CT volume from CB projections
        
        Args:
        -----
            projections (np.ndarray): [proj_slc, rows, cols] CBCT projections
            scanner_params (class): class containing scanner data
            proj_vecs (np.ndarray): vects describing the scanning used for reconstruction
            voxel_size (float): size of the voxels in the reconstructed volume
            rec_shape (int/tuple): shape of the reconstructed volume tuple with 3 dims [z,x,y] or int if isotropic

            --optional--
            gpu_id (int): GPU for astra to use if not set globaly, defaults to -1
            
        Returns:
        --------
            reconstruction (np.ndarray): [z,x,y] recontructed CT volume
    """

    astra.astra.set_gpu_index(globals().get('GPU_ID', kwargs.get('gpu_id',
                                                                 -1)))

    # from [proj_slc,rows,cols] to [rows,proj_slc,cols]
    projections = np.transpose(projections, (1, 0, 2))
    proj_geom = astra.create_proj_geom('cone_vec',
                                       *scanner_params.detector_binned_size,
                                       proj_vecs)
    projections_id = astra.data3d.create('-sino', proj_geom, projections)

    # [z,x,y] to [y,x,z] axis transposition
    reconstructed_shape = tuple([rec_shape[i]
                                 for i in [2, 1, 0]]) if isinstance(
                                     rec_shape, tuple) else (rec_shape, ) * 3
    vol_geom = astra.creators.create_vol_geom(
        *reconstructed_shape, *[
            sign * size / 2 * voxel_size for size in reconstructed_shape
            for sign in [-1, 1]
        ])
    reconstruction_id = astra.data3d.create('-vol', vol_geom, data=0)

    alg_cfg = astra.astra_dict('FDK_CUDA')
    alg_cfg['ProjectionDataId'] = projections_id
    alg_cfg['ReconstructionDataId'] = reconstruction_id
    alg_cfg['option'] = {'ShortScan': False}
    algorithm_id = astra.algorithm.create(alg_cfg)

    astra.algorithm.run(algorithm_id)
    reconstruction = astra.data3d.get(reconstruction_id)

    # Free ressources
    astra.algorithm.delete(algorithm_id)
    astra.data3d.delete([projections_id, reconstruction_id])

    return reconstruction
Пример #30
0
 def __init__(self, n_pixels, n_angles, rayperdetec=None):
     '''
     Initialize the ASTRA toolbox with a simple parallel configuration.
     The image is assumed to be square, and the detector count is equal to the number of rows/columns.
     '''
     self.vol_geom = astra.create_vol_geom(n_pixels, n_pixels)
     self.proj_geom = astra.create_proj_geom('parallel', 1.0, n_pixels, np.linspace(0,np.pi,n_angles,False))
     self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom)
Пример #31
0
def astrafp(im, ang, prj="cuda"):
    proj_geom = astra.create_proj_geom("parallel", 1.0, im.shape[0], np.array([ang, 0]))
    vol_geom = astra.create_vol_geom(im.shape)
    pid = astra.create_projector(prj, proj_geom, vol_geom)
    w = astra.OpTomo(pid)
    fpim = w * im
    astra.projector.delete(pid)
    return fpim[0 : im.shape[0]]
Пример #32
0
 def __init__(self, angles, img_size):
     self.angles = angles
     self.vol_geom = astra.create_vol_geom(img_size, img_size)
     self.proj_geom = astra.create_proj_geom('fanflat', 1.0, img_size,
                                             self.angles, img_size,
                                             img_size)
     self.proj_id = astra.create_projector('cuda', self.proj_geom,
                                           self.vol_geom)
Пример #33
0
    def __init__(self, geometry_type='cone',
                 num_voxel=(100, 100, 100),
                 det_row_count=100, det_col_count=100,
                 angles=np.linspace(0, 2 * np.pi, 180, endpoint=False),
                 det_col_spacing=1.0, det_row_spacing=1.0,
                 source_origin=100.0, origin_detector=10.0,
                 volume_data=1, projection_data=1,
                 gpu_index=0):
        self.geometry_type = geometry_type
        self.num_voxel = num_voxel
        self.detector_spacing_x = det_col_spacing
        self.detector_spacing_y = det_row_spacing
        self.det_row_count = det_row_count
        self.det_col_count = det_col_count
        self.angles = angles
        self.source_origin = source_origin
        self.origin_detector = origin_detector
        self.volume_data = volume_data
        self.projection_data = projection_data
        self.gpu_index = gpu_index

        # Create volume geometry
        self.volume_geom = astra.create_vol_geom(self.num_voxel)

        # Create projection geometry
        self.projection_geom = astra.create_proj_geom(
            self.geometry_type,
            self.detector_spacing_x, self.detector_spacing_y,
            self.det_row_count, self.det_col_count,
            self.angles,
            self.source_origin, self.origin_detector)

        # Allocate and store volume data in ASTRA memory
        self.volume_id = astra.data3d.create(
            '-vol',
            self.volume_geom,
            self.volume_data)

        # Allocate and store projection data in ASTRA memory
        self.projection_id = astra.data3d.create(
            '-sino',
            self.projection_geom,
            self.projection_data)

        # Create algorithm object: forward projector
        cfg = astra.astra_dict('FP3D_CUDA')
        cfg['option'] = {'GPUindex': self.gpu_index}
        cfg['ProjectionDataId'] = self.projection_id
        cfg['VolumeDataId'] = self.volume_id
        self.forward_alg_id = astra.algorithm.create(cfg)

        # Create algorithm object: backward projector
        cfg = astra.astra_dict('BP3D_CUDA')
        # classmethod?
        cfg['option'] = {'GPUindex': self.gpu_index}
        cfg['ProjectionDataId'] = self.projection_id
        cfg['ReconstructionDataId'] = self.volume_id
        self.backward_alg_id = astra.algorithm.create(cfg)
Пример #34
0
def DT(W,p, vol_size, proj_size, angles, Ngv, lamb=10, PU = 'cuda', K = 4, Niter = 50, epsilon=1e-4):
    
    [Nx,Nz] = vol_size
    [Ndetx, Ndety] = proj_size
    Nan = len(angles)
    if Ndety==1:
        sinogram = p.reshape([Nan, Ndetx])
    else:
        sinogram = p.reshape([Nan, Ndetx, Ndety])
    
    # create projection geometry and operator
    print('TVR-DART ...')
    print('Create projection geometry and operator...')
    proj_geom = astra.create_proj_geom('parallel', 1.0, Ndetx, angles)
    vol_geom = astra.create_vol_geom(Nz,Nx)
    proj_id = astra.create_projector(PU,proj_geom,vol_geom)
    W = astra.OpTomo(proj_id)
    
    # initial reconstruction
    print('Initial reconstruction...')
    recsirt = SIRT.recon(sinogram, 200, proj_geom, vol_geom, PU)
    sf = np.max(recsirt)
    p = p/sf
    if Ndety==1:
        sinogram = p.reshape([Nan, Ndetx])
    else:
        sinogram = p.reshape([Nan, Ndetx, Ndety])
    recsirt = recsirt/sf
    
    # set initial TVR-DART parameters
    K = K*np.ones(Ngv-1)
    gv = np.linspace(0, 1, Ngv,True)
    param0 = gv2param(gv,K)
    
    # Esimating parameter using a small section of the dataset
    print('Estimation of optimal parameters...')
    if Ndety==1:
        Segrec,param_esti = joint(W,p, recsirt, param0 ,lamb)
    else:
        Elist = np.sum(recsirt,axis=(0,2))
        index = np.argmax(Elist)
    
        index1 = np.max(np.hstack((0,index-1)))
        index2 = np.min(np.hstack((index+1,Ndety-1)))
    
        x0_esti = recsirt[:,index1:index2+1,:]
        sinogram_esti = sinogram[:,:,index1:index2+1]
        p_esti = sinogram_esti.reshape(Nan*Ndetx*(index2-index1+1))
    
        Segrec,param_esti = joint(W,p_esti, x0_esti, param0 ,lamb)
    
    # Reconstruction with estimated parameter
    print('Reconstruction with estimated parameters...')
    Segrec,rec = recon(W,p, recsirt, param_esti, lamb, Niter, epsilon)
    [gv,K] = param2gv(param_esti)
    param_esti = gv2param(gv*sf,K)
    Segrec = Segrec*sf;
    return Segrec, param_esti;
Пример #35
0
def astra_project(obj, angles, cuda=False):
    """
    Calculate projection of a 3D object using Astra-toolbox.

    Args
    ----------
    obj : NumPy array
        Either a 2D or 3D array containing the object to project.
        If 2D, the structure is of the form [z, x] where z is the
        projection axis.  If 3D, the strucutre is [y, z, x] where y is
        the tilt axis.
    angles : list or NumPy array
        The projection angles in degrees
    cuda : boolean
        If True, perform reconstruction using the GPU-accelerated algorithm.

    Returns
    ----------
    sino : Numpy array
        3D array of the form [y, angle, x] containing the projection of
        the input object

    """
    if len(obj.shape) == 2:
        obj = np.expand_dims(obj, 0)
    thetas = np.pi * angles / 180.
    y_pix, thickness, x_pix = obj.shape
    if cuda:
        vol_geom = astra.create_vol_geom(thickness, x_pix, y_pix)
        proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, y_pix,
                                           x_pix, thetas)
        sino_id, sino = astra.create_sino3d_gpu(obj, proj_geom, vol_geom)
        astra.data3d.delete(sino_id)
    else:
        sino = np.zeros([y_pix, len(angles), x_pix], np.float32)
        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)
        for i in range(0, y_pix):
            sino_id, sino[i, :, :] = astra.create_sino(obj[i, :, :], proj_id,
                                                       vol_geom)
        astra.data2d.delete(sino_id)

    sino = np.rollaxis(sino, 1)
    return sino
Пример #36
0
    def __init__(self, vol_shape, angles, beam_shape="parallel"):
        if len(vol_shape) > 2:
            raise ValueError("Only 2D volumes")

        self.proj_id = []
        self.dispose_projector()

        self.vol_geom = astra.create_vol_geom(vol_shape)
        self.proj_geom = astra.create_proj_geom(beam_shape, 1, np.max(vol_shape), angles)
Пример #37
0
    def forward_single(self, x):
        vol_geom = astra.create_vol_geom(x.shape[0], x.shape[1])
        proj_geom = astra.create_proj_geom('parallel', 1.0, x.shape[0],
                                           self.angles)
        proj_id = astra.create_projector('cuda', proj_geom, vol_geom)

        self.projectors.append(proj_id)

        return astra.create_sino(x, proj_id)
Пример #38
0
    def __init__(self,
                 geometry_type='cone',
                 num_voxel=(100, 100, 100),
                 det_row_count=100,
                 det_col_count=100,
                 angles=np.linspace(0, 2 * np.pi, 180, endpoint=False),
                 det_col_spacing=1.0,
                 det_row_spacing=1.0,
                 source_origin=100.0,
                 origin_detector=10.0,
                 volume_data=1,
                 projection_data=1,
                 gpu_index=0):
        self.geometry_type = geometry_type
        self.num_voxel = num_voxel
        self.detector_spacing_x = det_col_spacing
        self.detector_spacing_y = det_row_spacing
        self.det_row_count = det_row_count
        self.det_col_count = det_col_count
        self.angles = angles
        self.source_origin = source_origin
        self.origin_detector = origin_detector
        self.volume_data = volume_data
        self.projection_data = projection_data
        self.gpu_index = gpu_index

        # Create volume geometry
        self.volume_geom = astra.create_vol_geom(self.num_voxel)

        # Create projection geometry
        self.projection_geom = astra.create_proj_geom(
            self.geometry_type, self.detector_spacing_x,
            self.detector_spacing_y, self.det_row_count, self.det_col_count,
            self.angles, self.source_origin, self.origin_detector)

        # Allocate and store volume data in ASTRA memory
        self.volume_id = astra.data3d.create('-vol', self.volume_geom,
                                             self.volume_data)

        # Allocate and store projection data in ASTRA memory
        self.projection_id = astra.data3d.create('-sino', self.projection_geom,
                                                 self.projection_data)

        # Create algorithm object: forward projector
        cfg = astra.astra_dict('FP3D_CUDA')
        cfg['option'] = {'GPUindex': self.gpu_index}
        cfg['ProjectionDataId'] = self.projection_id
        cfg['VolumeDataId'] = self.volume_id
        self.forward_alg_id = astra.algorithm.create(cfg)

        # Create algorithm object: backward projector
        cfg = astra.astra_dict('BP3D_CUDA')
        # classmethod?
        cfg['option'] = {'GPUindex': self.gpu_index}
        cfg['ProjectionDataId'] = self.projection_id
        cfg['ReconstructionDataId'] = self.volume_id
        self.backward_alg_id = astra.algorithm.create(cfg)
Пример #39
0
    def reconstruct(self, sinogram, centre_of_rotation, angles, shape, center):

        ctr = centre_of_rotation
        width = sinogram.shape[1]
        pad = 50

        sino = np.nan_to_num(sinogram)

        # pad the array so that the centre of rotation is in the middle
        alen = ctr
        blen = width - ctr
        mid = width / 2.0

        if (ctr > mid):
            plow = pad
            phigh = (alen - blen) + pad
        else:
            plow = (blen - alen) + pad
            phigh = pad

        logdata = np.log(sino+1)
        sinogram = np.pad(logdata, ((0, 0), (int(plow), int(phigh))),
                          mode='reflect')

        width = sinogram.shape[1]

        vol_geom = astra.create_vol_geom(shape[0], shape[1])
        proj_geom = astra.create_proj_geom('parallel', 1.0, width,
                                           np.deg2rad(angles))

        sinogram_id = astra.data2d.create("-sino", proj_geom, sinogram)

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

        proj_id = astra.create_projector('strip', proj_geom, vol_geom)

        cfg = astra.astra_dict(self.parameters['reconstruction_type'])
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
        cfg['ProjectorId'] = proj_id

        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)
        # Run 20 iterations of the algorithm
        itterations = int(self.parameters['number_of_iterations'])
        # This will have a runtime in the order of 10 seconds.
        astra.algorithm.run(alg_id, itterations)
        # Get the result
        rec = astra.data2d.get(rec_id)

        # Clean up.
        astra.algorithm.delete(alg_id)
        astra.data2d.delete(rec_id)
        astra.data2d.delete(sinogram_id)

        return rec
Пример #40
0
 def __init__(self, DetRows, DetColumns, AnglesVec, ObjSize):
     self.ObjSize = ObjSize
     self.proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0,
                                             DetRows, DetColumns, AnglesVec)
     if type(ObjSize) == tuple:
         N1, N2, N3 = [int(i) for i in ObjSize]
     else:
         N1 = N2 = N3 = ObjSize
     self.vol_geom = astra.create_vol_geom(N3, N2, N1)
Пример #41
0
def check_recon(folder, alg, iterations, bin_num):

    raw_data = np.load(os.path.join(directory, folder, 'Data',
                                    'data_corr.npy'))[:, :, :, 6]
    raw_data = np.transpose(raw_data,
                            axes=(1, 0,
                                  2))  # Transpose to (rows, angles, columns)

    # Change if isocentre is not directly in the center of the detector
    # raw_data = np.roll(raw_data, -2, axis=2)

    # Create a 3D projection geometry with our cone-beam data
    # Parameters: 'acquisition type', number of detector rows, number of detector columns, data ndarray
    proj_geom = astra.create_proj_geom('cone', pixel_pitch, pixel_pitch,
                                       det_row_count, det_col_count, angles,
                                       source_origin, origin_det)
    proj_id = astra.data3d.create('-proj3d', proj_geom, raw_data)

    # Create a 3D volume geometry.
    # Parameter order: rows, columns, slices (y, x, z)
    vol_geom = astra.create_vol_geom(det_col_count, det_col_count,
                                     det_row_count)

    # Create a data object for the reconstruction
    if alg == 'FDK_CUDA':
        recon_id = astra.data3d.create('-vol', vol_geom)
    else:
        ct_data = np.load(os.path.join(directory, folder, 'CT', 'FDK_CT.npy'))
        recon_id = astra.data3d.create('-vol', vol_geom, data=ct_data)

    # Set up the parameters for a reconstruction algorithm using the GPU
    cfg = astra.astra_dict(alg)
    cfg['ReconstructionDataId'] = recon_id
    cfg['ProjectionDataId'] = proj_id

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

    # Run the specified number of iterations of the algorithm
    rec_data = np.zeros((iterations // 5, 576, 576))
    for i in range(0, iterations, 5):
        astra.algorithm.run(alg_id, 5)

        # Get the result
        rec = astra.data3d.get(recon_id)[11]
        print(alg[0:4] + f': {i + 5} Iterations')
        rec_data[i // 5] = rec

    np.save(
        os.path.join(directory, folder, 'CT',
                     alg[0:4] + '_iteration_check.npy'), rec_data)

    # 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(recon_id)
    astra.data3d.delete(proj_id)
Пример #42
0
def test_fanbeam_error(device, batch_size, image_size, angles, spacing,
                       distances, det_count, clip_to_circle):
    # generate random images
    # generate random images
    det_count = int(det_count * image_size)
    mask_radius = det_count / 2.0 if clip_to_circle else -1
    x = generate_random_images(1, image_size, mask_radius)[0]

    s_dist, d_dist = distances
    s_dist *= image_size
    d_dist *= image_size

    # astra
    vol_geom = astra.create_vol_geom(x.shape[0], x.shape[1])
    proj_geom = astra.create_proj_geom('fanflat', spacing, det_count, angles,
                                       s_dist, d_dist)
    proj_id = astra.create_projector('cuda', proj_geom, vol_geom)

    id, astra_y = astra.create_sino(x, proj_id)
    _, astra_bp = astra.create_backprojection(astra_y, proj_id)
    if clip_to_circle:
        astra_bp *= circle_mask(image_size, mask_radius)

    # TODO clean astra structures

    # our implementation
    radon = RadonFanbeam(image_size,
                         angles,
                         s_dist,
                         d_dist,
                         det_count=det_count,
                         det_spacing=spacing,
                         clip_to_circle=clip_to_circle)
    x = torch.FloatTensor(x).to(device).view(1, x.shape[0], x.shape[1])
    # repeat data to fill batch size
    x = torch.cat([x] * batch_size, dim=0)

    our_fp = radon.forward(x)
    our_bp = radon.backprojection(our_fp)

    forward_error = relative_error(astra_y, our_fp[0].cpu().numpy())
    back_error = relative_error(astra_bp, our_bp[0].cpu().numpy())

    # if back_error > 5e-3:
    #     plt.imshow(astra_bp)
    #     plt.figure()
    #     plt.imshow(our_bp[0].cpu().numpy())
    #     plt.show()
    print(np.max(our_fp.cpu().numpy()), np.max(our_bp.cpu().numpy()))

    print(
        f"batch: {batch_size}, size: {image_size}, angles: {len(angles)}, spacing: {spacing}, distances: {distances} circle: {clip_to_circle}, forward: {forward_error}, back: {back_error}"
    )
    # TODO better checks
    assert_less(forward_error, 1e-2)
    assert_less(back_error, 5e-3)
Пример #43
0
def pid(number_of_angles):
    """Return projector ID.
    :param number_of_angles:
    :return:
    """
    return astra.create_projector(
        'cuda',
        astra.create_proj_geom('parallel', 1.0, vshape[0],
                               np.linspace(0, np.pi, number_of_angles, False)),
        vol_geom)
Пример #44
0
def _basic_par3d_fp():
  import astra
  import numpy as np
  vg = astra.create_vol_geom(2, 32, 32)
  pg = astra.create_proj_geom('parallel3d', 1, 1, 32, 32, [0])
  vol = np.random.rand(32, 2, 32)
  (sino_id, sino) = astra.create_sino3d_gpu(vol, pg, vg)
  astra.data3d.delete(sino_id)
  err = np.max(np.abs(sino[:,0,:] - np.sum(vol,axis=1)))
  return err < 1e-6
Пример #45
0
    def __init__(self,
                 geometry_obj=Geometry(),
                 volume_space=Rn(Geometry().vol_size),
                 projections_space=Rn(Geometry().proj_size),
                 gpu_index=0):
        self.geom = geometry_obj
        self.vol_space = volume_space
        self.proj_space = projections_space
        self.gpu_index = gpu_index
        self.bp_id = None
        self.fp_id = None

        # Create volume geometry
        self.vol_geom = astra.create_vol_geom(self.geom.vol_shape)

        # Create projection geometry
        if self.geom.geom_type == 'cone':
            self.proj_geom = astra.create_proj_geom(
                self.geom.geom_type,
                self.geom.detector_spacing_x, self.geom.detector_spacing_y,
                self.geom.det_row_count, self.geom.det_col_count,
                self.geom.angles,
                self.geom.source_origin, self.geom.origin_detector)
        elif self.geom.geom_type == 'parallel':
            self.proj_geom = astra.create_proj_geom(
                'parallel', self.geom.detector_spacing_x,
                self.geom.det_col_count, self.geom.angles)

        # Allocate ASTRA memory for volume data and projection data
        if self.geom.vol_ndim == 2:
            self.volume_id = astra.data2d.create('-vol', self.vol_geom)
            self.proj_id = astra.data2d.create('-sino', self.proj_geom)
        elif self.geom.vol_ndim == 3:
            self.volume_id = astra.data3d.create('-vol', self.vol_geom)
            self.proj_id = astra.data3d.create('-sino', self.proj_geom)
        else:
            raise Exception("Invalid number of dimensions 'ndim'.")

        # self.scal_fac = self.geom.full_angle_rad / self.geom.angles.size
        # self.scal_fac = 1.0 / self.geom.angles.size
        self.scal_fac = self.geom.voxel_size[0] / self.geom.angles.size
Пример #46
0
def _basic_par2d_fp(type):
  import astra
  import numpy as np
  vg = astra.create_vol_geom(2, 32)
  pg = astra.create_proj_geom('parallel', 1, 32, [0])
  proj_id = astra.create_projector(type, pg, vg)
  vol = np.random.rand(2, 32)
  (sino_id, sino) = astra.create_sino(vol, proj_id)
  astra.data2d.delete(sino_id)
  astra.projector.delete(proj_id)
  err = np.max(np.abs(sino[0,:] - np.sum(vol,axis=0)))
  return err < 1e-6
Пример #47
0
    def geom_setup_3D(self, sino, angles, shape, cors):
        nSinos = sino.shape[self.slice_dim]
        length = len(angles)
        angles = np.deg2rad(angles)

        vectors = np.zeros((length, 12))
        for i in range(len(angles)):
            # ray direction
            vectors[i, 0] = np.sin(angles[i])
            vectors[i, 1] = -np.cos(angles[i])
            vectors[i, 2] = 0

            # center of detector
            vectors[i, 3:6] = 0

            # vector from detector pixel (0,0) to (0,1)
            vectors[i, 6] = np.cos(angles[i])
            vectors[i, 7] = np.sin(angles[i])
            vectors[i, 8] = 0

            # vector from detector pixel (0,0) to (1,0)
            vectors[i, 9] = 0
            vectors[i, 10] = 0
            vectors[i, 11] = 1

#        i = range(length)
#        # ray direction
#        vectors[i, 0] = np.sin(theta[i])
#        vectors[i, 1] = -np.cos(theta[i])
#        vectors[i, 2] = 0
#        # detector centre (use this for translation)
#        # assuming all sinograms are translated by the same amount for now
#        #det_vec = [cors[0], 0, 0]
#        det_vec = [0, 0, 0]
#        vectors[i, 3:6] = det_vec
#        # (use the following vectors for rotation)
#        # vector from detector pixel (0,0) to (0,1)
#        vectors[i, 6] = np.cos(theta[i])
#        vectors[i, 7] = np.sin(theta[i])
#        vectors[i, 8] = 0
#        # vector from detector pixel (0,0) to (1,0)
#        vectors[i, 9:12] = [0, 0, 1]

        # Parameters: #rows, #columns, vectors
        vol_geom = astra.create_vol_geom(nSinos, shape[0], shape[2])
        proj_geom = astra.create_proj_geom('parallel3d_vec', sino.shape[1],
                                           sino.shape[2], vectors)
        return vol_geom, proj_geom
Пример #48
0
    def astra_2D_recon(self, data):
        sino = data[0]
        cor, angles, vol_shape, init = self.get_frame_params()
        angles = np.deg2rad(angles)
        if self.res:
            res = np.zeros(self.len_res)
        # create volume geom
        vol_geom = astra.create_vol_geom(vol_shape)
        # create projection geom
        det_width = sino.shape[self.dim_detX]
        proj_geom = astra.create_proj_geom('parallel', 1.0, det_width, angles)
        sino = np.transpose(sino, (self.dim_rot, self.dim_detX))

        # create sinogram id
        sino_id = astra.data2d.create("-sino", proj_geom, sino)
        # create reconstruction id
        if init is not None:
            rec_id = astra.data2d.create('-vol', vol_geom, init)
        else:
            rec_id = astra.data2d.create('-vol', vol_geom)

#        if self.mask_id:
#            self.mask_id = astra.data2d.create('-vol', vol_geom, self.mask)
        # setup configuration options
        cfg = self.set_config(rec_id, sino_id, proj_geom, vol_geom)
        # create algorithm id
        alg_id = astra.algorithm.create(cfg)
        # run algorithm
        if self.res:
            for j in range(self.iters):
                # Run a single iteration
                astra.algorithm.run(alg_id, 1)
                res[j] = astra.algorithm.get_res_norm(alg_id)
        else:
            astra.algorithm.run(alg_id, self.iters)
        # get reconstruction matrix

        if self.manual_mask is not False:
            recon = self.manual_mask*astra.data2d.get(rec_id)
        else:
            recon = astra.data2d.get(rec_id)

        # delete geometry
        self.delete(alg_id, sino_id, rec_id, False)
        return [recon, res] if self.res else recon
Пример #49
0
    def reconstruct3D(self, sinogram, angles, shape, depth, alg_name, iterations):
        
        det_rows = sinogram.shape[0]
        det_cols = sinogram.shape[2]

#        sinogram = np.transpose(sinogram, (2,1,0))
                      
        vol_geom = astra.create_vol_geom(shape[0], depth, shape[1])
        
        proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, det_cols, \
                                            det_rows, np.deg2rad(angles))
                                            
        sinogram_id = astra.data3d.create("-sino", proj_geom, sinogram)

        # Create a data object for the reconstruction
        rec_id = astra.data3d.create('-vol', vol_geom)
                
        cfg = astra.astra_dict(alg_name)
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
         
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)
        
        # This will have a runtime in the order of 10 seconds.
        astra.algorithm.run(alg_id, iterations)
        
        
        #if "CUDA" in params[0] and "FBP" not in params[0]:
        #self.res += astra.algorithm.get_res_norm(alg_id)**2
        #print math.sqrt(self.res)
        
        # Get the result
        rec = astra.data3d.get(rec_id)

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

        rec = rec[:160,:160,1]                

        return rec
Пример #50
0
def gen_random_geometry_fanflat_vec():
  Vectors = np.zeros([16,6])
  # We assume constant detector width in these tests
  if not NONUNITDET:
    w = 1.0
  else:
    w = 0.6 + 0.8 * np.random.random()
  for i in range(Vectors.shape[0]):
    angle1 = 2*np.pi*np.random.random()
    if OBLIQUE:
      angle2 = angle1 + 0.5 * np.random.random()
    else:
      angle2 = angle1
    dist1 = 256 * (0.5 + np.random.random())
    detc = 10 * np.random.random(size=2)
    detu = [ math.cos(angle1) * w, math.sin(angle1) * w ]
    src = [ math.sin(angle2) * dist1, -math.cos(angle2) * dist1 ]
    Vectors[i, :] = [ src[0], src[1], detc[0], detc[1], detu[0], detu[1] ]
  pg = astra.create_proj_geom('fanflat_vec', np.random.randint(*range2d), Vectors)
  return pg
Пример #51
0
def gen_random_geometry_parallel_vec():
  Vectors = np.zeros([16,6])
  # We assume constant detector width in these tests
  if not NONUNITDET:
    w = 1.0
  else:
    w = 0.6 + 0.8 * np.random.random()
  for i in range(Vectors.shape[0]):
    l = 0.6 + 0.8 * np.random.random()
    angle1 = 2*np.pi*np.random.random()
    if OBLIQUE:
      angle2 = angle1 + 0.5 * np.random.random()
    else:
      angle2 = angle1
    detc = 10 * np.random.random(size=2)
    detu = [ math.cos(angle1) * w, math.sin(angle1) * w ]
    ray = [ math.sin(angle2) * l, -math.cos(angle2) * l ]
    Vectors[i, :] = [ ray[0], ray[1], detc[0], detc[1], detu[0], detu[1] ]
  pg = astra.create_proj_geom('parallel_vec', np.random.randint(*range2d), Vectors)
  return pg
Пример #52
0
    def geom_setup_2D(self, dim_det_cols):
        in_pData = self.get_plugin_in_datasets()[0]
        cor = self.cor + self.pad_amount

        sino_shape = in_pData.get_shape()
        nCols = sino_shape[dim_det_cols]
        self.p_low, self.p_high = \
            self.array_pad(cor[0], nCols + 2*self.pad_amount)
        sino_width = \
            sino_shape[1] + self.p_low + self.p_high + 2*self.pad_amount

        vol_geom = astra.create_vol_geom(self.vol_shape[0], self.vol_shape[1])
        self.proj_geom = astra.create_proj_geom('parallel', 1.0, sino_width,
                                                np.deg2rad(self.angles))

        self.rec_id = self.astra_function.create('-vol', vol_geom)
        self.cfg = self.cfg_setup()
        if self.alg_type is '2D' and "CUDA" not in self.name:
            proj_id = astra.create_projector('strip', self.proj_geom, vol_geom)
            self.cfg['ProjectorId'] = proj_id
Пример #53
0
def fp0(image, det_col=111, num_angles=222, voxel_size_mm=1):
    """Wrapper for astra forward projector

    :param image:
    :return: sinogram
    """

    vol_geom = astra.create_vol_geom(image.shape)
    proj_id = astra.create_projector(
        'cuda',
        astra.create_proj_geom('parallel', 1.0, det_col,
                               np.linspace(0, np.pi, num_angles, False)),
        vol_geom)

    sino_id, sino = astra.create_sino(image, proj_id)
    sino *= voxel_size_mm

    astra.data2d.delete(sino_id)
    astra.projector.delete(proj_id)

    return sino
Пример #54
0
    def reconstruct2D(self, sinogram, angles, shape, alg_name, iterations):
        
        vol_geom = astra.create_vol_geom(shape[0], shape[1])
        
        proj_geom = astra.create_proj_geom('parallel', 1.0, sinogram.shape[1],
                                           np.deg2rad(angles))

        sinogram_id = astra.data2d.create("-sino", proj_geom, sinogram)

        # Create a data object for the reconstruction
        rec_id = astra.data2d.create('-vol', vol_geom)
        
        cfg = astra.astra_dict(alg_name)
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = sinogram_id
        
        if not "CUDA" in alg_name:
            proj_id = astra.create_projector('strip', proj_geom, vol_geom)
            cfg['ProjectorId'] = proj_id
         
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)
        
        # This will have a runtime in the order of 10 seconds.
        astra.algorithm.run(alg_id, iterations)
        
        if "CUDA" in alg_name and "FBP" not in alg_name:
                self.res += astra.algorithm.get_res_norm(alg_id)**2
                print math.sqrt(self.res)
        
        # Get the result
        rec = astra.data2d.get(rec_id)

        astra.algorithm.delete(alg_id)
        astra.data2d.delete(rec_id)
        astra.data2d.delete(sinogram_id)
        
        return rec
Пример #55
0
def recon_fista_tv(im, angles, lam, fista_iter, iter):
	"""Reconstruct the input sinogram by using the FISTA-TV algorithm

    Parameters
    ----------
    im : array_like
		Image data (sinogram) as numpy array. 

	angles : double
		Value in radians representing the number of angles of the input sinogram.

	lam : double
		Regularization parameter of the FISTA algorithm.

	fista_iter : int
		Number of iterations of the FISTA algorihtm.

	iter : int
		Number of iterations of the TV minimization.	
	
    """	

	# Create ASTRA geometries:
	vol_geom = astra.create_vol_geom(im.shape[1] , im.shape[1])
	proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1], linspace(0, angles, im.shape[0], False))

	# Create the ASTRA projector:
	p = tvtomo.ProjectorASTRA2D(proj_geom,vol_geom)	
	
	# Define parameters and FISTA object that performs reconstruction:
	#lam = 1**-14
	f = tvtomo.FISTA(p, lam, fista_iter)

	# Actual reconstruction (takes time):
	im_rec = f.reconstruct(im.astype(float32), iter)
	
	return im_rec.astype(float32)
Пример #56
0
def astra(*args):
    """
    Reconstruct object using the ASTRA toolbox

    Extra options
    ----------
    method : str
        ASTRA reconstruction method to use.
    num_iter : int, optional
        Number of algorithm iterations performed.
    proj_type : str, optional
        ASTRA projector type to use: 'line', 'linear', or 'strip' (CPU only).
    extra_options : dict, optional
        Extra options for the ASTRA config (i.e. those in cfg['option'])

    Warning
    -------
    When using CUDA, only 1 CPU core can be used.

    Example
    -------
    >>> import tomopy
    >>> obj = tomopy.shepp3d() # Generate an object.
    >>> ang = tomopy.angles(180) # Generate uniformly spaced tilt angles.
    >>> sim = tomopy.project(obj, ang) # Calculate projections.
    >>>
    >>> # Reconstruct object:
    >>> rec = tomopy.recon(sim, ang, algorithm=tomopy.astra,
    >>>       options={'method':'SART', 'num_iter':10*180, 'proj_type':'linear',
    >>>       'extra_options':{'MinConstraint':0}})
    >>>
    >>> # Show 64th slice of the reconstructed object.
    >>> import pylab
    >>> pylab.imshow(rec[64], cmap='gray')
    >>> pylab.show()
    """
    # Lazy import ASTRA
    import astra as astra_mod

    # Get shared arrays
    tomo = mproc.SHARED_TOMO
    recon = mproc.SHARED_ARRAY

    # Unpack arguments
    nang = args[0]
    nslices = args[1]
    ndet = args[2]
    centers = args[3]
    angles = args[4]
    num_gridx = args[5]['num_gridx']
    num_gridy = args[5]['num_gridy']
    opts = args[5]['options']
    istart = args[6]
    iend = args[7]

    # Check options
    for o in needed_options['astra']:
        if not o in opts:
            logger.error("Option %s needed for ASTRA reconstruction." % (o,))
            raise ValueError()
    for o in default_options['astra']:
        if not o in opts:
            opts[o] = default_options['astra'][o]

    # Create ASTRA geometries
    vol_geom = astra_mod.create_vol_geom((num_gridx,num_gridy))
    proj_geom = astra_mod.create_proj_geom('parallel',1.0,ndet,angles.astype(np.float64))

    # Create ASTRA data id
    sino = np.zeros((nang, ndet), dtype=np.float32)

    # Create ASTRA config
    cfg = astra_mod.astra_dict(opts['method'])

    if opts['proj_type']!='cuda':
        pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom)
        sid = astra_mod.data2d.link('-sino', proj_geom, sino)
        cfg['ProjectorId'] = pi
        cfg['ProjectionDataId'] = sid
        use_cuda=False
    else:
        use_cuda=True

    if 'extra_options' in opts:
        cfg['option'] = opts['extra_options']
    else:
        cfg['option'] = {}

    # Perform reconstruction
    for i in xrange(istart, iend):
        sino[:] = tomo[:,i,:]

        cfg['option']['z_id']=i

        # Fix center of rotation
        if use_cuda:
            proj_geom['option'] = {'ExtraDetectorOffset': (centers[i]-ndet/2.)*np.ones(nang)}
            sid = astra_mod.data2d.link('-sino', proj_geom, sino)
            cfg['ProjectionDataId'] = sid
            pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom)
            cfg['ProjectorId'] = pi
        else:
            # Temporary workaround, will be fixed in later ASTRA version
            shft = int(np.round(ndet/2.-centers[i]))
            sino[:] = np.roll(sino,shft)
            l = shft
            r = sino.shape[1]+shft
            if l<0: l=0
            if r>sino.shape[1]: r=sino.shape[1]
            sino[:,0:l]=0
            sino[:,r:sino.shape[1]]=0

        vid = astra_mod.data2d.link('-vol', vol_geom, recon[i])
        cfg['ReconstructionDataId'] = vid
        alg_id = astra_mod.algorithm.create(cfg)
        astra_mod.algorithm.run(alg_id, opts['num_iter'])
        astra_mod.algorithm.delete(alg_id)
        astra_mod.data2d.delete(vid)
        if use_cuda:
            astra_mod.projector.delete(pi)
            astra_mod.data2d.delete(sid)

    # Clean up
    if not use_cuda:
        astra_mod.projector.delete(pi)
        astra_mod.data2d.delete(sid)