Beispiel #1
0
    def __init__(self,
                 operator,
                 data,
                 u,
                 v,
                 tau,
                 inner_iters,
                 relative_tolerance=1e-20,
                 absolute_tolerance=1e-19,
                 verbose=0,
                 EHs=None):
        self._data = data
        self._op = operator
        self._iters = inner_iters
        self._tau = tau
        self._relative_tolerance = relative_tolerance
        self._absolute_tolerance = absolute_tolerance
        src_shape = (self._data.nX1, self._data.nX2, 1)
        self._dest_shape = (self._data.nT, self._data.nC)
        self.converged = False
        self.iteration = 0
        self._verbose = (verbose > 1)

        try:
            recondata_gpu = self._op.dgpu['recondata']
        except NameError:
            recondata_gpu = gpuarray.to_gpu(self._data.recondata)

        # y
        if EHs is None:
            self.EHs = gpuarray.zeros(src_shape, dtype=np.complex64)
            self._op.adjoint(recondata_gpu, self.EHs)
        else:
            self.EHs = EHs

        self._m = u

        self.rhs = gpuarray.zeros_like(self.EHs)
        inner_cg_rhs(self.rhs, u, v, self.EHs, self._tau)

        self._p_k = gpuarray.zeros_like(self.EHs)
        self._v_k = gpuarray.zeros_like(self.EHs)

        self._residual_k = gpuarray_copy(self.rhs)
        self._forward(self._m, self._v_k)  # initial guess

        self._residual_k = self._residual_k - self._v_k
        self._v_k = gpuarray_copy(self._residual_k)

        self._rho_0 = measure(self._v_k, self._residual_k)
        self._rho_k = self._rho_0

        if self._rho_0 <= self._absolute_tolerance:
            if self._verbose:
                print("Already converged!")
            self.converged = True
            self.iteration = 0

        self._p_k = gpuarray_copy(self._v_k)
Beispiel #2
0
    def test_adjoint(self, iters=5):
        """Test the adjoint operator.

        Args:
            iters (int): number of iterations
        """
        src_shape = (self.data.nX1, self.data.nX2, 1)
        dest_shape = (self.data.nT, self.data.nC)
        u = gpuarray.zeros(src_shape, self.precision_complex, order='F')
        ut = gpuarray.zeros(src_shape, self.precision_real, order='F')
        Ku = gpuarray.zeros(dest_shape, self.precision_complex, order='F')
        v = gpuarray.zeros(dest_shape, self.precision_complex, order='F')
        vt = gpuarray.zeros(dest_shape, self.precision_real, order='F')
        Kadv = gpuarray.zeros(src_shape, self.precision_complex, order='F')

        generator = curandom.XORWOWRandomNumberGenerator()
        errors = []

        try:
            i = 0
            for i in range(iters):
                # randomness
                generator.fill_uniform(ut)
                generator.fill_uniform(vt)
                v = gpuarray_copy(vt.astype(self.precision_complex))
                u = gpuarray_copy(ut.astype(self.precision_complex))

                # apply operators
                self.apply(u, Ku)
                self.adjoint(v, Kadv)

                scp1 = dotc_gpu(Ku, v)
                scp2 = dotc_gpu(u, Kadv)
                n_Ku = dotc_gpu(Ku)
                n_Kadv = dotc_gpu(Kadv)
                n_u = dotc_gpu(u)
                n_v = dotc_gpu(v)

                errors.append(np.abs(scp1-scp2))

            print("Test " + str(i) + ": <Ku,v>=" + str(scp1) + ", <u,Kadv>=" +
                  str(scp2) + ", Error=" + str(np.abs(scp1-scp2)) +
                  ", Relative Error=" +
                  str((scp1-scp2)/(n_Ku*n_v + n_Kadv*n_u)))
        except KeyboardInterrupt:
            if len(errors) == 0:
                errors = -1
        finally:
            print("Mean Error: " + repr(np.mean(errors)))
            print("Standarddeviation: " + repr(np.std(errors)))
        return i
Beispiel #3
0
    def norm_est(self, u, iters=10):
        """Estimates norm of the operator with a power iteration.

        Args:
            u (gpuarray): input array
            iters (int): number of iterations
        """
        if self._verbose:
            print("Estimating Norm...")

        u_temp = gpuarray_copy(u)
        result = gpuarray.zeros([self.data.nC, self.data.nT],
                                self.precision_complex, order='F')

        for _ in range(0, iters):
            dot_tmp = dotc_gpu(u_temp)
            u_temp /= np.sqrt(np.abs(dot_tmp))
            self.apply(u_temp, result)
            self.adjoint(result, u_temp)
            normsqr = dotc_gpu(u_temp)
        return np.sqrt(np.abs(normsqr)/self._norm_div)
Beispiel #4
0
    def run(self):
        """Runs the conjugate gradient method.
        """
        i = 0
        try:
            for i in range(0, self._iters):
                if self._verbose:
                    print("  Inner CG Iteration " + repr(i))

                self._forward(self._p_k, self._v_k)
                sigma_k = measure(self._p_k, self._v_k)
                alpha_k = self._rho_k / sigma_k
                update_m(self._m, alpha_k, self._p_k)
                sub_scaled_vector(self._residual_k, self._residual_k, alpha_k,
                                  self._v_k)
                self._v_k = gpuarray_copy(self._residual_k)
                rho_k_plus_1 = measure(self._v_k, self._residual_k)
                rho_k_t = np.abs(rho_k_plus_1)

                if (rho_k_t / self._rho_0 <= self._relative_tolerance) \
                   or (rho_k_t <= self._absolute_tolerance):
                    if self._verbose:
                        print("Converged at Iteration " + str(i) + ".")
                    self.converged = True
                    self.iteration = i + 1
                    return

                add_scaled_vector(self._p_k, self._v_k,
                                  rho_k_plus_1 / self._rho_k, self._p_k)
                self._rho_k = rho_k_plus_1

                if self._verbose >= 3:
                    print("   Residual=" + repr(rho_k_t))
        except KeyboardInterrupt:
            raise
        finally:
            self.iteration = i + 1
Beispiel #5
0
def tgv(op, out_dir, alpha=4e-5, tau_p=0.625, tau_d=0.125, reduction=2**-8,
        fac=2, iters=3000, relative_tolerance=1e-20, absolute_tolerance=1e-19,
        cg=False, inner_iters=20, norm_est=None, norm_est_iters=10,
        time_iters=False, no_progress=False, save_images=False, save_mat=False,
        image_format='png', verbose=False):
    """TGV regularized reconstruction using the Encoding Matrix E.

    Args:
        op (:class:`artbox.operators.Operator`):
            :class:`artbox.operators.Operator` object.
        out_dir (str): Output directory.
        alpha (float): Regularization parameter.
        tau_p (float): tau_p.
        tau_d (float): tau_d.
        reduction (float): Regularization parameter reduction per iteration.
        fac (float): fac.
        iters (int): Number of iterations.
        relative_tolerance (float): Relative tolerance for early stopping rule.
        absolute_tolerance (float): Absolute tolerance for early stopping rule.
        cg (bool): Indicate whether inner CG method should be used (TGV-CG).
        inner_iters (int): Number of iterations for inner CG.
        norm_est (float): Estimated norm of operator. If `None`, it will be
            calculated.
        norm_est_iters (int): Number of iterations for norm estimation.
        time_iters (bool): If `True`, all iterations are timed.
        no_progress (bool): If `True`, no progress bar is shown.
        save_images (bool): If `True`, all intermediate images are saved to
            disk.
        save_mat (bool): If `True`, all intermediate images are saved as MATLAB
            data files.
        image_format (str): Format images are saved in.
        verbose (int): Verbosity level.
        double (bool): Indicate whether computations should be performed with
            double precision. TODO!!
    """
    data = op.data

    alpha = alpha/reduction
    alpha00 = alpha*fac
    alpha10 = alpha
    alpha01 = alpha00*reduction
    alpha11 = alpha10*reduction

    maxiter = iters

    # set up primal variables
    ut = gpuarray.zeros((data.nX1, data.nX2, 1), np.complex64, order='F')
    # 'reference zero'
    tt = gpuarray.zeros((data.nX1, data.nX2, 1), np.float32, order='F')

    op.adjoint(op.dgpu['recondata'], ut)

    # norm estimation
    if norm_est is None:
        # perform norm estimation
        norm_est = op.norm_est(ut, norm_est_iters)
        if verbose:
            print("Norm estimation: " + str(norm_est))
    else:
        # use user-provided norm
        if verbose:
            print("Norm estimation (provided by user): " + str(norm_est))

    ut /= norm_est
    u = gpuarray.maximum(tt, ut.real).astype(np.complex64)
    u_ = gpuarray_copy(u)
    w = gpuarray.zeros((u.shape[0], u.shape[1], 2*u.shape[2]), np.complex64,
                       order='F')
    w_ = gpuarray.zeros((u.shape[0], u.shape[1], 2*u.shape[2]), np.complex64,
                        order='F')

    # set up dual variables
    p = gpuarray.zeros((u.shape[0], u.shape[1], 2*u.shape[2]), np.complex64,
                       order='F')
    q = gpuarray.zeros((u.shape[0], u.shape[1], 3*u.shape[2]), np.complex64,
                       order='F')
    v = gpuarray.zeros_like(op.dgpu['recondata'])

    # set up variables associated with linear transform
    Ku = gpuarray.zeros(op.dgpu['recondata'].shape, np.complex64, order='F')
    Kadjv = gpuarray.zeros((data.nX1, data.nX2, 1), np.complex64,
                           order='F')

    # if args.L2 is None:
    #   # L2 is *not* provided by the user
    #   M = 1
    #   L2 = 0.5*(M*M + 17 + np.sqrt(pow(M, 4.0) - 2*M*M + 33))
    # else:
    #   # L2 is provided by the user
    #   L2 = args.L2

    # this one works for TGV
    # tau_p = 1.0/np.sqrt(L2)
    # tau_d = 1.0/tau_p/L2

    uold = gpuarray.empty_like(u)
    wold = gpuarray.empty_like(w)

    if cg:
        from artbox.cg import InnerCG
        tmp_EHs = None
        tau_p = 1.0/norm_est
        tau_d = 1.0/tau_p/(0.5*(17+np.sqrt(33)))

    if time_iters:
        from time import time

    if not no_progress and verbose:
        # set up progress bar
        from progressbar import ProgressBar
        progress = ProgressBar()
        iter_range = progress(range(maxiter))
    else:
        iter_range = range(maxiter)

    total_iterations = 0

    try:
        for k in iter_range:
            if verbose and no_progress:
                print("Iteration " + repr(k))

            if no_progress and time_iters:
                start = time()

            total_iterations += 1

            alpha0 = np.exp(float(k)/maxiter*np.log(alpha01) +
                            float(maxiter-k)/maxiter*np.log(alpha00))
            alpha1 = np.exp(float(k)/maxiter*np.log(alpha11) +
                            float(maxiter-k)/maxiter*np.log(alpha10))

            # primal update
            cuda.memcpy_dtod(uold.gpudata, u.gpudata, u.nbytes)
            cuda.memcpy_dtod(wold.gpudata, w.gpudata, w.nbytes)

            op.apply(u_, Ku)
            Ku /= norm_est

            tgvk.tgv_update_v(v, Ku, op.dgpu['recondata'], tau_d,
                              lin_constr=(alpha1 < 0))

            # dual update
            tgvk.tgv_update_p(u_, w_, p, tau_d, abs(alpha1))
            tgvk.tgv_update_q(w_, q, tau_d, abs(alpha0))

            op.adjoint(v, Kadjv)
            Kadjv /= norm_est

            # Inner conjugate gradient method
            if cg:
                try:
                    icg = InnerCG(op, data, u, p, tau_p, inner_iters,
                                  relative_tolerance, absolute_tolerance,
                                  verbose, EHs=tmp_EHs)
                    icg.run()
                except:
                    raise
                finally:
                    total_iterations += icg.iteration
                tmp_EHs = icg.EHs
            else:
                tgvk.tgv_update_u(u, p, Kadjv, tau_p)

            tgvk.tgv_update_w(w, p, q, tau_p)

            # extragradient update
            tgvk.tgv_update_u_2(u_, u, uold)
            tgvk.tgv_update_w_2(w_, w, wold)

            # Print time per iteration
            if no_progress and time_iters:
                print("Elapsed time for iteration " + str(k) + ": " +
                      str(time() - start) + " seconds")

            # Save images
            if save_images:
                save_image(np.abs(u.get().reshape(data.nX1, data.nX2)),
                           out_dir, k, image_format)

            # Save matlab files
            if save_mat:
                save_matlab(u.get().reshape(data.nX1, data.nX2),
                            out_dir, k)
    except KeyboardInterrupt:
        print("Reconstruction aborted (CTRL-C) at iteration " +
              str(total_iterations))
    finally:
        # always save final image and Matlab data
        save_image(np.abs(u.get().reshape(data.nX1, data.nX2)),
                   out_dir, "result", image_format)
        save_matlab(u.get().reshape(data.nX1, data.nX2),
                    out_dir, "result")
    return total_iterations
Beispiel #6
0
    def run(self):
        """Runs the conjugate gradient method.
        """
        if not self._no_progress and self._verbose:
            from progressbar import ProgressBar
            progress = ProgressBar()
            iter_range = progress(range(self._iters))
        else:
            iter_range = range(self._iters)

        if self._no_progress and self._time_iters:
            from time import time

        i = 0
        try:
            for i in iter_range:
                if self._verbose and self._no_progress:
                    print("Iteration " + repr(i))

                if self._no_progress and self._time_iters:
                    start = time()

                self.iteration += 1

                self._forward(self._p_k, self._v_k)
                sigma_k = measure(self._p_k, self._v_k)
                alpha_k = self._rho_k / sigma_k
                if self._double:
                    update_m_double(self._m, alpha_k, self._p_k)
                    sub_scaled_vector_double(self._residual_k,
                                             self._residual_k, alpha_k,
                                             self._v_k)
                else:
                    update_m(self._m, alpha_k, self._p_k)
                    sub_scaled_vector(self._residual_k, self._residual_k,
                                      alpha_k, self._v_k)
                self._v_k = gpuarray_copy(self._residual_k)
                rho_k_plus_1 = measure(self._v_k, self._residual_k)
                rho_k_t = np.abs(rho_k_plus_1)

                if (rho_k_t / self._rho_0 <= self._relative_tolerance) \
                   or (rho_k_t <= self._absolute_tolerance):
                    print("Converged.")
                    self.converged = True
                    break

                if self._double:
                    add_scaled_vector_double(self._p_k, self._v_k,
                                             rho_k_plus_1 / self._rho_k,
                                             self._p_k)
                else:
                    add_scaled_vector(self._p_k, self._v_k,
                                      rho_k_plus_1 / self._rho_k, self._p_k)

                self._rho_k = rho_k_plus_1

                if self._noisy:
                    print(" Residual=" + str(rho_k_t))

                if self._no_progress and self._time_iters:
                    print("Elapsed time for iteration " + str(i) + ": " +
                          str(time() - start) + " seconds")

                if self._save_images:
                    save_image(
                        np.abs(self._m.get().reshape(self._data.nX1,
                                                     self._data.nX2)),
                        self._out_dir, i, self._image_format)
                if self._save_matlab:
                    save_matlab(
                        self._m.get().reshape(self._data.nX1, self._data.nX2),
                        self._out_dir, i)
        except KeyboardInterrupt:
            print("Reconstruction aborted (CTRL-C) at iteration " + str(i))
        finally:
            if self._save_images:
                save_image(
                    np.abs(self._m.get().reshape(self._data.nX1,
                                                 self._data.nX2)),
                    self._out_dir, "result", self._image_format)
            if self._save_matlab:
                save_matlab(
                    self._m.get().reshape(self._data.nX1, self._data.nX2),
                    self._out_dir, "result")
            self.iteration = i + 1
        return (self._m.get().reshape(self._data.nX1,
                                      self._data.nX2), self.iteration)
Beispiel #7
0
    def __init__(self,
                 operator,
                 data,
                 out_dir="results/cg",
                 double=False,
                 relative_tolerance=1e-20,
                 absolute_tolerance=1e-19,
                 iters=100,
                 no_progress=False,
                 time_iters=False,
                 save_images=False,
                 save_mat=True,
                 image_format='png',
                 verbose=0):
        self._data = data
        self._op = operator
        if data.weights is not None:
            self._weights = gpuarray.to_gpu(
                data.weights.astype(self._op.precision_complex))
        else:
            self._weights = None

        self._iters = iters
        self._relative_tolerance = relative_tolerance
        self._absolute_tolerance = absolute_tolerance
        src_shape = (self._data.nX1, self._data.nX2, 1)
        self._dest_shape = (self._data.nT, self._data.nC)
        self.converged = False
        self.iteration = 0
        self._double = double
        self._no_progress = no_progress
        self._time_iters = time_iters
        self._image_format = image_format
        self._save_images = save_images
        self._save_matlab = save_mat
        self._verbose = verbose
        self._noisy = verbose > 3
        self._out_dir = out_dir
        try:
            recondata_gpu = self._op.dgpu['recondata']
        except NameError:
            recondata_gpu = gpuarray.to_gpu(self._data.recondata)

        # y
        EHs = gpuarray.zeros(src_shape, dtype=self._op.precision_complex)
        self._op.adjoint(recondata_gpu, EHs)

        self._v_k = gpuarray.zeros_like(EHs)

        self._residual_k = gpuarray_copy(EHs)
        self._m = gpuarray.zeros(src_shape, dtype=self._op.precision_complex)
        self._forward(self._m, self._v_k)

        self._residual_k -= self._v_k
        self._v_k = gpuarray_copy(self._residual_k)

        self._rho_0 = measure(self._v_k, self._residual_k)
        self._rho_k = self._rho_0

        if self._rho_0 <= self._absolute_tolerance:
            if self._verbose:
                print("Already converged at initialization step!")
            self.converged = True
            self.iteration = 0

        self._p_k = gpuarray_copy(self._v_k)