def __call_Atb(self, data):
     if has_gpu_sel:
         return Atb(data, self.tigre_geom, self.tigre_geom.angles,
                    self.method['adjoint'], self.tigre_geom.mode,
                    self.gpuids)
     else:
         return Atb(data, self.tigre_geom, self.tigre_geom.angles,
                    self.method['adjoint'], self.tigre_geom.mode)
Exemple #2
0
def FDK(projh, geo, angles, filter=None):
    ('\n'
     'FDK solves Cone Beam CT image reconstruction'
     '\n'
     'Parameters \n'
     '-------------------------------------------------------------------\n'
     '\n'
     'proj:         Data input in the form of 3d, np.array(dtype=float32)\n'
     '\n'
     'geo:          Geometry of detector and image (see examples/Demo code)\n'
     '\n'
     'alpha:        1d array of angles corresponding to image data, np.array(dtype=float32)\n'
     '\n'
     'filter:       default="ram_lak" \n'
     '              opts: \n'
     '                  "shep_logan"'
     '                  "cosine"   '
     '                  "hamming" '
     '                  "hann" '
     'Examples \n'
     '---------------------------------------------------------------------------\n'
     'See Demos/Example code for further instructions.\n'
     '---------------------------------------------------------------------------'
     '\n'
     """This file is part of the TIGRE Toolbox

        Copyright (c) 2015, University of Bath and
                            CERN-European Organization for Nuclear Research
                            All rights reserved.

        License:            Open Source under BSD.
                            See the full license at
                            https://github.com/CERN/TIGRE/license.txt

        Contact:            [email protected]
        Codes:              https://github.com/CERN/TIGRE/
      --------------------------------------------------------------------------
        Coded by:          MATLAB (original code): Ander Biguri
                           PYTHON : Reuben Lindroos,Sam Loescher, """)
    if filter is not None:
        geo.filter = filter
    # Weight
    proj = copy.deepcopy(projh)
    proj = proj.transpose()
    proj = proj.transpose(0, 2, 1)

    for ii in range(len(angles)):
        xv = np.arange((-geo.nDetector[0] / 2) + 0.5, 1 +
                       (geo.nDetector[0] / 2) - 0.5) * geo.dDetector[0]
        yv = np.arange((-geo.nDetector[1] / 2) + 0.5, 1 +
                       (geo.nDetector[1] / 2) - 0.5) * geo.dDetector[1]
        (xx, yy) = np.meshgrid(xv, yv)

        w = geo.DSD / np.sqrt((geo.DSD**2 + xx**2 + yy**2))
        proj[ii] = proj[ii] * w

    proj_filt = filtering(proj.transpose(0, 2, 1), geo, angles,
                          parker=False).transpose()
    res = Atb(proj_filt, geo, angles, 'FDK')
    return res
Exemple #3
0
def CGLS(projections,
         geometry,
         angles,
         iterations,
         verbose=False,
         log_parameters=False):
    if log_parameters:
        parameter_history = {}
        parameter_history['alpha'] = np.zeros([iterations], dtype=np.float32)
        parameter_history['beta'] = np.zeros([iterations], dtype=np.float32)
        parameter_history['gamma'] = np.zeros([iterations], dtype=np.float32)
        parameter_history['q_norm'] = np.zeros([iterations], dtype=np.float32)
        parameter_history['s_norm'] = np.zeros([iterations], dtype=np.float32)

    x = np.zeros(geometry.nVoxel.astype(int), dtype=np.float32)

    r = projections - Ax(x, geometry, angles, 'ray-voxel')
    p = Atb(r, geometry, angles, 'matched')
    p_norm = np.linalg.norm(p.ravel(), 2)
    gamma = p_norm * p_norm

    errorsL2 = np.zeros([iterations], dtype=np.float32)
    for i in range(iterations):
        q = Ax(p, geometry, angles, 'ray-voxel')
        q_norm = np.linalg.norm(q.ravel(), 2)
        alpha = gamma / (q_norm * q_norm)
        x += alpha * p

        aux = projections - Ax(x, geometry, angles, 'ray-voxel')
        errorsL2[i] = np.linalg.norm(aux.ravel(), 2)

        if i > 0 and errorsL2[i] > errorsL2[i - 1]:
            x -= alpha * p
            if verbose:
                print('CGLS stoped in iteration', i, 'due to divergence.')
            if log_parameters:
                return x, errorsL2, parameter_history
            return x, errorsL2

        r -= alpha * q

        s = Atb(r, geometry, angles, 'matched')
        s_norm = np.linalg.norm(s.ravel(), 2)

        gamma1 = s_norm * s_norm
        beta = gamma1 / gamma

        if log_parameters:
            parameter_history['alpha'][i] = alpha
            parameter_history['beta'][i] = beta
            parameter_history['gamma'][i] = gamma
            parameter_history['q_norm'][i] = q_norm
            parameter_history['s_norm'][i] = s_norm

        gamma = gamma1
        p = s + beta * p

    if log_parameters:
        return x, errorsL2, parameter_history
    return x, errorsL2
Exemple #4
0
def OS_SART(proj,
            geo,
            alpha,
            niter,
            blocksize=20,
            lmbda=1,
            lmbda_red=0.99,
            OrderStrategy=None,
            Quameasopts=None,
            init=None,
            verbose=True,
            noneg=True,
            computel2=False):
    ('\n'
     """SART_CBCT solves Cone Beam CT image reconstruction using Oriented Subsets
              Simultaneous Algebraic Reconxtruction Techique algorithm

   OS_SART(PROJ,GEO,ALPHA,NITER,BLOCKSIZE=20) solves the reconstruction problem
   using the projection data PROJ taken over ALPHA angles, corresponding
   to the geometry descrived in GEO, using NITER iterations."""
     '\n'
     'Parameters \n'
     '-------------------------------------------------------------------\n'
     '\n'
     'proj:         Data input in the form of 3d, np.array(dtype=float32)\n'
     '\n'
     'geo:          Geometry of detector and image (see examples/Demo code)\n'
     '\n'
     'alpha:        1d array of angles corresponding to image data, np.array(dtype=float32)\n'
     '\n'
     'niter:        number of iterations of algorithm\n'
     '\n'
     'blocksize'
     'lmbda:        Sets the value of the hyperparameter.\n '
     '              Default is 1 \n'
     '\n'
     'lmbda_red:    Reduction of lambda.Every iteration \n'
     '              lambda=lambdared*lambda. Default is 0.99\n'
     '\n'
     'Init:         Describes diferent initialization techniques.\n'
     '                "none"     : Initializes the image to zeros (default) \n'
     '                "FDK"      : intializes image to FDK reconstrucition \n'
     '                "multigrid": Initializes image by solving the problem in\n'
     '                             small scale and increasing it when relative\n'
     '                             convergence is reached.\n'
     '                "image"    : Initialization using a user specified\n'
     '                             image. Not recomended unless you really\n'
     '                             know what you are doing.\n'
     '\n'
     'InitImg:      Image for the "image" initialization. (avoid)\n'
     '\n'
     'Verbose:      Feedback print statements for algorithm progress \n'
     '              default=True \n'
     '\n'
     'QualMeas:     Asks the algorithm for a set of quality measurement\n'
     '              parameters. Input should contain a list or tuple of strings of\n'
     '              quality measurement names. Example: ["CC","RMSE","MSSIM"]\n'
     '              These will be computed in each iteration.\n'
     '\n'
     'OrderStrategy:  Chooses the subset ordering strategy. Options are:\n'
     '                   "ordered"        : uses them in the input order, but divided\n'
     '                   "random"         : orders them randomply\n'
     '                   "angularDistance": chooses the next subset with the\n'
     '                                      biggest angular distance with the ones used\n'
     'Examples \n'
     '---------------------------------------------------------------------------\n'
     'See Demos/Example code for further instructions.\n'
     '---------------------------------------------------------------------------'
     '\n'
     """This file is part of the TIGRE Toolbox

        Copyright (c) 2015, University of Bath and
                            CERN-European Organization for Nuclear Research
                            All rights reserved.

        License:            Open Source under BSD.
                            See the full license at
                            https://github.com/CERN/TIGRE/license.txt

        Contact:            [email protected]
        Codes:              https://github.com/CERN/TIGRE/
      --------------------------------------------------------------------------
        Coded by:          MATLAB (original code): Ander Biguri
                           PYTHON : Reuben Lindroos,Sam Loescher, """)
    if verbose:
        print('OS_SART algorithm in progress.')

    angleblocks, angle_index = order_subsets(alpha, blocksize, OrderStrategy)
    #     Projection weight:
    #       - fixing the geometry
    #       - making sure there are no infs in W
    geox = copy.deepcopy(geo)
    geox.sVoxel[0:] = geo.DSD - geo.DSO
    geox.sVoxel[2] = max(geox.sDetector[1], geox.sVoxel[2])
    geox.nVoxel = np.array([2, 2, 2])
    geox.dVoxel = geox.sVoxel / geox.nVoxel
    W = Ax(np.ones(geox.nVoxel, dtype=np.float32), geox, alpha, "ray-voxel")
    W[W < min(geo.dVoxel / 4)] = np.inf
    W = 1 / W

    geox = None
    #     Back_Proj weight
    #     NOTE: hstack(array,last value) as np.arange does not include upper limit of interval.
    if geo.mode != 'parallel':

        start = geo.sVoxel[1] / 2 - geo.dVoxel[1] / 2 + geo.offOrigin[1]
        stop = -geo.sVoxel[1] / 2 + geo.dVoxel[1] / 2 + geo.offOrigin[1]
        step = -geo.dVoxel[1]
        xv = np.arange(start, stop + step, step)

        start = geo.sVoxel[2] / 2 - geo.dVoxel[2] / 2 + geo.offOrigin[2]
        stop = -geo.sVoxel[2] / 2 + geo.dVoxel[2] / 2 + geo.offOrigin[2]
        step = -geo.dVoxel[2]
        yv = -1 * np.arange(start, stop + step, step)

        (yy, xx) = np.meshgrid(yv, xv)
        xx = np.expand_dims(xx, axis=2)
        yy = np.expand_dims(yy, axis=2)

        A = (alpha + np.pi / 2)
        V = (geo.DSO / (geo.DSO + (yy * np.sin(-A)) - (xx * np.cos(-A))))**2
        V = np.array(V, dtype=np.float32)

    elif geo.mode == 'parallel':
        V = np.ones([len(alpha), geo.nVoxel[1], geo.nVoxel[0]],
                    dtype=np.float32)

    # Set up init parameters
    lq = []
    l2l = []
    if init == 'multigrid':
        if verbose:
            print('init multigrid in progress...')
            print('default blocksize=1 for init_multigrid(OS_SART)')
        res = init_multigrid(proj, geo, alpha, alg='SART')
        if verbose:
            print('init multigrid complete.')
    if init == 'FDK':
        res = FDK(proj, geo, alpha).transpose()

    if type(init) == np.ndarray:
        if (geo.nVoxel == init.shape).all():

            res = init

        else:
            raise ValueError('wrong dimension of array for initialisation')
    elif init is None:
        res = np.zeros(geo.nVoxel, dtype=np.float32)

    # Iterate

    tic = None
    toc = time.clock()
    for i in range(niter):
        if Quameasopts is not None:
            res_prev = res
        if verbose:
            if i == 1:
                if tic is None:
                    pass
                else:
                    print('Esitmated time until completetion (s): ' +
                          str(niter * (tic - toc)))

        for j in range(len(angleblocks)):
            if blocksize == 1:
                angle = np.array([angleblocks[j]], dtype=np.float32)
                sumax = 0
                dim_exp = True
            else:
                angle = angleblocks[j]
                sumax = 3
                dim_exp = False

            # PRESENT FOR LOOP
            res += lmbda * 1 / np.array(
                np.sum(np.expand_dims(V[:, :, angle_index[j]], axis=0),
                       axis=sumax),
                dtype=np.float32) * Atb(
                    adddim(W[:, :, angle_index[j]], dim_exp) *
                    (adddim(proj[:, :, angle_index[j]], dim_exp) -
                     Ax(res, geo, angle, 'ray-voxel')), geo, angle, 'FDK')
            if noneg:
                res = res.clip(min=0)

            # VERBOSE:
            # proj_err = proj[angle_index[j]] - Ax(res, geo, angle_blocks[j],'ray-voxel')
            # weighted_err = W[angle_index[j]]*proj_err
            # backprj = Atb(weighted_err,geo,angle_blocks[j],'FDK')
            # weighted_backprj = 1/V[angle_index[j]]*backprj
            # res+=1*weighted_backprj
            # res[res < 0] = 0

        if Quameasopts is not None:
            lq.append(MQ(res, res_prev, Quameasopts))
            res_prev = res
        if computel2:
            # compute l2 borm for b-Ax
            errornow = im3DNORM(proj - Ax(res, geo, alpha, 'ray-voxel'), 2)
            l2l.append(errornow)

        tic = time.clock()
    lmbda *= lmbda_red
    # parkerweight(projsirt,TIGRE_parameters,angles,q=1)
    if computel2:
        return res.transpose(), l2l
    if Quameasopts is not None:
        return res.transpose(), lq
    else:
        return res