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)
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
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)
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
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
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)
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)