def test_comp_proj(): r3 = odl.rn(3) r3xr3 = odl.ProductSpace(r3, 2) x = r3xr3.element([[1, 2, 3], [4, 5, 6]]) proj_0 = odl.ComponentProjection(r3xr3, 0) assert x[0] == proj_0(x) assert x[0] == proj_0(x, out=proj_0.range.element()) proj_1 = odl.ComponentProjection(r3xr3, 1) assert x[1] == proj_1(x) assert x[1] == proj_1(x, out=proj_1.range.element())
def test_comp_proj_adjoint(): r3 = odl.rn(3) r3xr3 = odl.ProductSpace(r3, 2) x = r3.element([1, 2, 3]) result_0 = r3xr3.element([[1, 2, 3], [0, 0, 0]]) proj_0 = odl.ComponentProjection(r3xr3, 0) assert result_0 == proj_0.adjoint(x) assert result_0 == proj_0.adjoint(x, out=proj_0.domain.element()) result_1 = r3xr3.element([[0, 0, 0], [1, 2, 3]]) proj_1 = odl.ComponentProjection(r3xr3, 1) assert result_1 == proj_1.adjoint(x) assert result_1 == proj_1.adjoint(x, out=proj_1.domain.element())
def test_comp_proj_indices(): r3 = odl.rn(3) r33 = odl.ProductSpace(r3, 3) x = r33.element([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) proj = odl.ComponentProjection(r33, [0, 2]) assert x[[0, 2]] == proj(x) assert x[[0, 2]] == proj(x, out=proj.range.element())
def test_comp_proj_slice(): r3 = odl.Rn(3) r33 = odl.ProductSpace(r3, 3) x = r33.element([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) proj = odl.ComponentProjection(r33, slice(0, 2)) assert x[0:2] == proj(x) assert x[0:2] == proj(x, out=proj.range.element())
def test_comp_proj_adjoint_slice(): r3 = odl.rn(3) r33 = odl.ProductSpace(r3, 3) x = r33[0:2].element([[1, 2, 3], [4, 5, 6]]) result = r33.element([[1, 2, 3], [4, 5, 6], [0, 0, 0]]) proj = odl.ComponentProjection(r33, slice(0, 2)) assert result == proj.adjoint(x) assert result == proj.adjoint(x, out=proj.domain.element())
def tnv(operator, data, alpha, sinfo, eta, nonneg=True, datafit=None): space = operator.domain grad = odl.Gradient(space) P = odl.ComponentProjection(grad.range**2, 0) D = P.adjoint * grad Q = odl.ComponentProjection(grad.range**2, 1) A = odl.BroadcastOperator(operator, D) F1 = get_data_fit(datafit, data) N = odl.solvers.NuclearNorm(D.range, outer_exp=1, singular_vector_exp=1) F2 = alpha * N.translated(-Q.adjoint(eta * grad(sinfo))) F = odl.solvers.SeparableSum(F1, F2) if nonneg: G = odl.solvers.IndicatorNonnegativity(space) else: G = odl.solvers.ZeroFunctional(space) return G, F, A
# Initialize gradient operator gradient = odl.Gradient(reco_space, method='forward') gradient_back = odl.Gradient(reco_space, method='backward') eps = odl.DiagonalOperator(gradient_back, reco_space.ndim) # Create the domain of the problem, given by the reconstruction space and the # range of the gradient on the reconstruction space. domain = odl.ProductSpace(reco_space, gradient.range) # Column vector of three operators defined as: # 1. Computes ``A(x)`` # 2. Computes ``grad(x) - y`` # 3. Computes ``eps(y)`` op = odl.BroadcastOperator( ray_trafo * odl.ComponentProjection(domain, 0), odl.ReductionOperator(gradient, odl.ScalingOperator(gradient.range, -1)), eps * odl.ComponentProjection(domain, 1)) # Do not use the g functional, set it to zero. g = odl.solvers.ZeroFunctional(op.domain) # Create functionals for the dual variable # l2-squared data matching l2_norm = odl.solvers.L2NormSquared(ray_trafo.range).translated(data) # The l1-norms scaled by regularization paramters l1_norm_1 = 0.001 * odl.solvers.L1Norm(gradient.range) l1_norm_2 = 1e-4 * odl.solvers.L1Norm(eps.range)
noisy_data, niter=10, callback=callback) multigrid.graphics.show_both(*reco) elif reco_method == 'TV': insert_grad = odl.Gradient(insert_discr, pad_mode='order1') coarse_grad = odl.Gradient(coarse_discr, pad_mode='order1') # Differentiable part, build as ||. - g||^2 o P data_func = odl.solvers.L2NormSquared( sum_ray_trafo.range).translated(noisy_data) * sum_ray_trafo reg_param_1 = 8e-3 reg_func_1 = reg_param_1 * (odl.solvers.L2NormSquared(coarse_discr) * odl.ComponentProjection(pspace, 0)) smooth_func = data_func + reg_func_1 # Non-differentiable part composed with linear operators reg_param = 8e-3 nonsmooth_func = reg_param * odl.solvers.L1Norm(insert_grad.range) if iter == 0: reg_param_2 = 8e-2 elif iter == 1: reg_param_2 = 8e-3 elif iter == 2: reg_param_2 = 8e-4 elif iter == 3: reg_param_2 = 8e-5 elif iter == 4:
# D = data matching functional: Y1 x Y2 -> R, ||. - g1||_Y1^2 + ||. - g2||_Y2^2 # S1 = squared L2-norm: X1^2 -> R, for Tikhonov functional # S2 = (alpha * L12-Norm): X2^2 -> R, for isotropic TV # Operators # A = forward operator "matrix": X1 x X2 -> Y1 x Y2 # G1 = spatial gradient: X1 -> X1^2 # G2 = spatial gradient: X2 -> X2^2 # B1 = G1 extended to X1 x X2, B1(f1, f2) = G1(f1) # B2 = G2 extended to X1 x X2, B2(f1, f2) = G2(f2) A = odl.ProductSpaceOperator([[R11, 0], [A21, R22]]) G1 = odl.Gradient(X1, pad_mode='symmetric') G2 = odl.Gradient(X2, pad_mode='order1') # Extend gradients to product space B1 = G1 * odl.ComponentProjection(A.domain, 0) B2 = G2 * odl.ComponentProjection(A.domain, 1) # TODO: weighting for differences in sizes (avoid large region domination) D = odl.solvers.L2NormSquared(A.range).translated([g1, g2]) # For isotropic TV # alpha1 = 1e-2 # S1 = alpha1 * odl.solvers.GroupL1Norm(G1.range) # For Tikhonov alpha1 = 1e-2 S1 = alpha1 * odl.solvers.L2NormSquared(G1.range) # TV on second component alpha2 = 1e-4 S2 = alpha2 * odl.solvers.GroupL1Norm(G2.range)
#sym_gradient = odl.operator.ProductSpaceOperator( # [[Dx, 0], [0, Dy], [0.5*Dy, 0.5*Dx]], range=W) E = odl.operator.ProductSpaceOperator( [[Dx, 0], [0, Dy], [0.5*Dy, 0.5*Dx], [0.5*Dy, 0.5*Dx]]) W = E.range # Create the domain of the problem, given by the reconstruction space and the # range of the gradient on the reconstruction space. domain = odl.ProductSpace(U, V) # Column vector of three operators defined as: # 1. Computes ``Ax`` # 2. Computes ``Gx - y`` # 3. Computes ``Ey`` op = odl.BroadcastOperator( A * odl.ComponentProjection(domain, 0), odl.ReductionOperator(G, odl.ScalingOperator(V, -1)), E * odl.ComponentProjection(domain, 1)) # Do not use the g functional, set it to zero. g = odl.solvers.ZeroFunctional(domain) # l2-squared data matching l2_norm = odl.solvers.L2NormSquared(A.range).translated(data) # parameters alpha = 1e-1 beta = 1 # The l1-norms scaled by regularization paramters l1_norm_1 = alpha * odl.solvers.L1Norm(V)
# Initialize gradient and 2nd order derivative operator gradient = odl.Gradient(reco_space) eps = odl.DiagonalOperator(gradient, reco_space.ndim) domain = odl.ProductSpace(gradient.domain, eps.domain) # Assemble operators and functionals for the solver # The linear operators are # 1. identity on the first component for the data matching # 2. gradient of component 1 - component 2 for the auxiliary functional # 3. eps on the second component # 4. projection onto the first component lin_ops = [ odl.ComponentProjection(domain, 0), odl.ReductionOperator(gradient, odl.ScalingOperator(gradient.range, -1)), eps * odl.ComponentProjection(domain, 1), odl.ComponentProjection(domain, 0) ] # The functionals are # 1. L2 data matching # 2. regularization parameter 1 times L1 norm on the range of the gradient # 3. regularization parameter 2 times L1 norm on the range of eps # 4. box indicator on the reconstruction space data_matching = odl.solvers.L2NormSquared(reco_space).translated(data) reg_param1 = 4e0 regularizer1 = reg_param1 * odl.solvers.L1Norm(gradient.range) reg_param2 = 1e0
R2 = odl.tomo.RayTransform(X2, geometry) M = odl_multigrid.MaskingOperator(X1, roi_min_pt, roi_max_pt) A1 = R1 * M A2 = R2 A = odl.ReductionOperator(A1, A2) G1 = odl.Gradient(X1, pad_mode='symmetric') G2 = odl.Gradient(X2, pad_mode='order1') alpha1 = 1e0 alpha2 = 5e-2 S1 = alpha1 * odl.solvers.L2NormSquared(G1.range) S2 = alpha2 * odl.solvers.GroupL1Norm(G2.range) B1 = G1 * odl.ComponentProjection(X1 * X2, 0) B2 = G2 * odl.ComponentProjection(X1 * X2, 1) D = odl.solvers.L2NormSquared(A.range).translated(y) # We check how much we gained regarding runtimes: get_ipython().run_line_magic('timeit', 'A(A.domain.zero())') get_ipython().run_line_magic('timeit', 'A.adjoint(A.range.zero())') # The forward operator is not so much faster, since we still have the same # number of rays to compute, i.e., forward projection scales with the number # of angles and detector pixels. That is something to improve later. # However, the adjoint is much faster since it scales with the number voxels. # Now we do the usual steps and reconstruct:
else: odl.solvers.conjugate_gradient_normal(ray_trafo_combined, reco, data, niter=niter_cg, callback=callback) multigrid.graphics.show_both(*reco) elif reco_method == 'TV': grad_detail = odl.Gradient(space_detail, pad_mode='order1') l2_norm_sq = odl.solvers.L2NormSquared(ray_trafo_combined.range) data_func = l2_norm_sq.translated(data) reg_func_lowres = odl.solvers.ZeroFunctional(space_lowres) comp_proj_lowres = odl.ComponentProjection(pspace, 0) reg_param_detail = 3e-3 reg_func_detail = (reg_param_detail * odl.solvers.L1Norm(grad_detail.range)) comp_proj_detail = odl.ComponentProjection(pspace, 1) min_val, max_val = np.min(reco_fbp), np.max(reco_fbp) box_constr = odl.solvers.IndicatorBox(pspace, min_val, max_val) f = odl.solvers.ZeroFunctional(pspace) L = [ray_trafo_combined, comp_proj_lowres, grad_detail * comp_proj_detail] g = [data_func, reg_func_lowres, reg_func_detail] ray_trafo_norm = 1.2 * odl.power_method_opnorm(ray_trafo_combined, maxiter=4)
planes=planes) c = float(norm_K) / float(norm_D) D *= c norm_D *= c L1 = odl.solvers.SeparableSum( *[(alpha / c) * odl.solvers.GroupL1Norm(gradient.range), (alpha * beta / c) * odl.solvers.GroupL1Norm(E.range)]) g = odl.solvers.SeparableSum( odl.solvers.IndicatorBox(U, lower=0), odl.solvers.ZeroFunctional(gradient.range)) X = D.domain P = [odl.ComponentProjection(X, i) for i in range(2)] A_ = odl.BroadcastOperator(K * P[0], D) f_ = odl.solvers.SeparableSum(KL, L1) obj_fun = f_ * A_ + g # objective functional fldr = '{}/pics'.format(folder_param) if not os.path.exists('{}/gray_image_pet.png'.format(fldr)): tmp = U.element() tmp_op = mMR.operator_mmr() tmp_op.toodl(image, tmp) misc.save_image(tmp.asarray(), 'image_pet', fldr, planes=planes) tmp_op.toodl(image_mr, tmp) misc.save_image(tmp.asarray(), 'image_mr', fldr, planes=planes) tmp_op.toodl(image_ct, tmp) misc.save_image(tmp.asarray(), 'image_ct', fldr, planes=planes)