def derivative(self, x): Ax = self(x) tmp = self.range.element() scale0 = self.range.zero() scale1 = self.range.zero() for I, E in zip(self.spectrum, self.energies): tmp.lincomb(1, Ax, -mu0(E), x[0]) tmp.lincomb(1, tmp, -mu1(E), x[1]) tmp.ufunc.exp(out=tmp) scale0.lincomb(1, scale0, I * mu0(E), tmp) scale1.lincomb(1, scale1, I * mu1(E), tmp) return odl.ReductionOperator(odl.MultiplyOperator(scale0), odl.MultiplyOperator(scale1))
def functional(request): """functional with optimum 0 at 0.""" name = request.param if name == 'l2_squared': space = odl.rn(3) return odl.solvers.L2NormSquared(space) elif name == 'l2_squared_scaled': space = odl.uniform_discr(0, 1, 3) scaling = odl.MultiplyOperator(space.element([1, 2, 3]), domain=space) return odl.solvers.L2NormSquared(space) * scaling elif name == 'quadratic_form': space = odl.rn(3) # Symmetric and diagonally dominant matrix matrix = odl.MatrixOperator([[7.0, 1, 2], [1, 5, -3], [2, -3, 8]]) vector = space.element([1, 2, 3]) # Calibrate so that functional is zero in optimal point constant = 1 / 4 * vector.inner(matrix.inverse(vector)) return odl.solvers.QuadraticForm(operator=matrix, vector=vector, constant=constant) elif name == 'rosenbrock': # Moderately ill-behaved rosenbrock functional. rosenbrock = odl.solvers.RosenbrockFunctional(odl.rn(2), scale=2) # Center at zero return rosenbrock.translated([-1, -1]) else: assert False
def proximal(self, sigma): if self.domain.is_rn: mult = self.support else: mult = self.domain.element() mult.real = self.support mult.imag = self.support return odl.MultiplyOperator(domain=self.domain, range=self.domain, multiplicand=mult)
def gradient(space, sinfo=None, mode=None, gamma=1, eta=1e-2, show_sinfo=False, prefix=None): grad = odl.Gradient(space, method='forward', pad_mode='symmetric') if sinfo is not None: if mode == 'direction': norm = odl.PointwiseNorm(grad.range) grad_sinfo = grad(sinfo) ngrad_sinfo = norm(grad_sinfo) for i in range(len(grad_sinfo)): grad_sinfo[i] /= ngrad_sinfo.ufuncs.max() ngrad_sinfo = norm(grad_sinfo) ngrad_sinfo_eta = np.sqrt(ngrad_sinfo**2 + eta**2) xi = grad.range.element([g / ngrad_sinfo_eta for g in grad_sinfo]) # UGLY Id = odl.operator.IdentityOperator(grad.range) xiT = odl.PointwiseInner(grad.range, xi) xixiT = odl.BroadcastOperator(*[x * xiT for x in xi]) grad = (Id - gamma * xixiT) * grad if show_sinfo: misc.save_image(ngrad_sinfo, prefix + '_sinfo_norm') misc.save_vfield(xi.asarray(), filename=prefix + '_sinfo_xi') misc.save_vfield_cmap(filename=prefix + '_sinfo_xi_cmap') elif mode == 'location': norm = odl.PointwiseNorm(grad.range) ngrad_sinfo = norm(grad(sinfo)) ngrad_sinfo /= ngrad_sinfo.ufuncs.max() w = eta / np.sqrt(ngrad_sinfo**2 + eta**2) grad = odl.DiagonalOperator(odl.MultiplyOperator(w), 2) * grad if show_sinfo: misc.save_image(ngrad_sinfo, prefix + '_sinfo_norm') misc.save_image(w, prefix + '_w') else: grad = None return grad
def functional(request): """functional with optimum 0 at 0.""" name = request.param # TODO: quadratic (#606) functionals if name == 'l2_squared': space = odl.rn(3) return odl.solvers.L2NormSquared(space) elif name == 'l2_squared_scaled': space = odl.uniform_discr(0, 1, 3) scaling = odl.MultiplyOperator(space.element([1, 2, 3]), domain=space) return odl.solvers.L2NormSquared(space) * scaling elif name == 'rosenbrock': # Moderately ill-behaved rosenbrock functional. rosenbrock = odl.solvers.RosenbrockFunctional(odl.rn(2), scale=2) # Center at zero return rosenbrock.translated([-1, -1]) else: assert False
grad = odl.Gradient(space) grad_vec = odl.DiagonalOperator(grad, 2) cross_terms = True c = 0.5 if not cross_terms: crlb[1, 0, ...] = 0 crlb[0, 1, ...] = 0 mat_sqrt_inv = inverse_sqrt_matrix(crlb) re = ray_trafo.range.element W = odl.ProductSpaceOperator([[odl.MultiplyOperator(re(mat_sqrt_inv[0, 0])), odl.MultiplyOperator(re(mat_sqrt_inv[0, 1]))], [odl.MultiplyOperator(re(mat_sqrt_inv[1, 0])), odl.MultiplyOperator(re(mat_sqrt_inv[1, 1]))]]) op = W * A rhs = W(data) data_discrepancy = odl.solvers.L2NormSquared(A.range).translated(rhs) l1_norm = odl.solvers.L1Norm(space) huber = 2.5 * odl.solvers.MoreauEnvelope(l1_norm, sigma=0.01) my_op = MyOperatorTrace(domain=grad_vec.range, range=space, linear=False) spc_cov_matrix = [[1, -c], [-c, 1]]
def reconstruct_filter(op: odl.Operator, p, u, niter=10, mask=None, fn_filter=None, clip=(None, None)): """ Iterative reconstruction based on R.F. Mudde, Time-resolved X-ray tomography of a fluidized bed input op - projection matrix or linear projection operator p - sinogram u - initial iterate options.niter - max iterations mask - image mask as array with same size as u beta - regularization parameter for median filter in [0,1] bounds - box constraints on values of u: [min,max] output u - final iterate """ ones = op.range.element(np.ones(op.range.shape)) C = odl.MultiplyOperator(np.divide(1, op.adjoint(ones))) ones = op.domain.element(np.ones(op.domain.shape)) R = odl.MultiplyOperator(np.divide(1, op(ones))) if mask is not None: M = odl.MultiplyOperator(op.domain.element(mask), domain=op.domain, range=op.domain) else: M = odl.IdentityOperator(op.domain) for _ in range(niter): # SART update # v = u + C(M.adjoint(op.adjoint(R(p - op(M(u)))))) # u += C*M.T*op.T*R*(p - op*M*u) u2 = M(u) v = op(u2) np.subtract(p, v, out=v.data) R(v, out=v) w = op.adjoint(v) M.adjoint(w, out=w) # adjoint of a diagonal... C(w, out=w) np.add(u, w, out=u.data) # import matplotlib.pyplot as plt # plt.ion() # plt.figure(29234) # plt.imshow(v.data) # plt.pause(.2) # box constraints if clip != (None, None): np.clip(u.data, *clip, out=u.data) # correction step (median filter) if fn_filter is not None: u.data[:] = fn_filter(u.data)
grad = odl.Gradient(space) grad_vec = odl.DiagonalOperator(grad, 2) cross_terms = True c = 0.0 if not cross_terms: crlb[1, 0, ...] = 0 crlb[0, 1, ...] = 0 mat_sqrt_inv = inverse_sqrt_matrix(crlb) re = ray_trafo.range.element W = odl.ProductSpaceOperator([[ odl.MultiplyOperator(re(mat_sqrt_inv[0, 0])), odl.MultiplyOperator(re(mat_sqrt_inv[0, 1])) ], [ odl.MultiplyOperator(re(mat_sqrt_inv[1, 0])), odl.MultiplyOperator(re(mat_sqrt_inv[1, 1])) ]]) mat_sqrt_inv_hat = mat_sqrt_inv.mean(axis=(2, 3)) mat_sqrt_inv_hat_inv = np.linalg.inv(mat_sqrt_inv_hat) I = odl.IdentityOperator(space) precon = odl.ProductSpaceOperator(np.multiply(mat_sqrt_inv_hat_inv, I)) precon_inv = odl.ProductSpaceOperator(np.multiply(mat_sqrt_inv_hat, I)) op = W * A
for j in range(I): convj = conv((x - c[j])**2) summand += np.power(convi / convj, 1.0 / (m - 1.0)) mu[i] = 1.0 / summand conv_adj_mu_pow_m[i] = conv.adjoint(np.power(mu[i], m)) # Update c for i in range(I): dividend = ones.inner(conv_adj_mu_pow_m[i] * x) divisor = ones.inner(conv_adj_mu_pow_m[i]) c[i] = dividend / divisor # Update x # construct operator diag = odl.MultiplyOperator(sum(conv_adj_mu_pow_m[i] for i in range(I))) op = scaling - lam2 * lap + diag # define right hand side rhs = scaling(y) - lam2 * lap(y) + sum(c[i] * conv_adj_mu_pow_m[i] for i in range(I)) # solve using CG odl.solvers.conjugate_gradient(op, x, rhs, niter=256) # Display partial results callback(y - x) print(c) # display final results
x_thresholded = threshold_op(x) x_thresholded.show('Initial thresholded guess') callback1 = odl.solvers.CallbackShow() callback2 = odl.solvers.CallbackShow() for i in range(50): print('Itertion {}'.format(i)) x_edge = edge_op(x_thresholded) callback1(x_edge) # Random part of DART x_edge = np.maximum( x_edge, np.float32(np.random.uniform(size=reco_space.shape) > 0.95)) free_op = odl.MultiplyOperator(x_edge) fix_op = odl.MultiplyOperator(1 - x_edge) free_data = data - (ray_trafo * fix_op)(x_thresholded) op = ray_trafo * free_op x_tmp = free_op(x) odl.solvers.conjugate_gradient_normal(op, x_tmp, free_data, niter=30) x_tmp += fix_op(x_thresholded) x = convolution(x_tmp) x_thresholded = threshold_op(x) callback2(x_thresholded)