def grad(self, atoms, axis=None): # reg = sum s*(r-r_0)^{-k} c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) dI = 0 * I dx = 0 * x if atoms.space.isotropic: dr = self.dim * self.k * (r - self.r0)**(self.k - 1) else: dr = r.copy() dr[:, :self.dim] = self.k * \ (r[:, :self.dim] - self.r0) ** (self.k - 1) dr[:, self.dim:] = 0 if axis == 0 or axis == 'I': d = dI elif axis == 1 or axis == 'x': d = dx elif axis == 2 or axis == 'r': d = dr else: d = concatenate((dI.reshape(-1), dx.reshape(-1), dr.reshape(-1))) return self.s * d
def doLoc_L2Step(res, atom): # argmin_{A,x} \int .5|res(y)-A*atom(y-x)|^2 # = argmin \int -A*res(y)atom(y-x) + A^2|atom|^2 # = argmax A(res\star atom) - A^2|atom|_2^2 # atom(y) = e^{-.5|Ry|^2} \implies |atom|_2^2 = sqrt(2pi)^dim/(sqrt(2)|R|) # (this assumes data is 0 in unseen fourier data...) # NOTE: Computing maximum convolution requires a back-projection of the # data! This is a bit of a pain. Maybe I can bluff it with two? FT = GaussFT(res.space) conv = FT.inverse(FT(res) * FT(atom)).asarray() # NEED TO DO BACK PROJECTION m = conv.max() ind = where(conv == m) dim = len(ind) i = random.choice(dim) x = [0] * dim for j in range(dim): x[j] = FT.inGrid[j][ind[j][i]] print(x) c = context() c.set(atom.x[:], x) r = c.asarray(atom.r) A = m / sqrt(2 * (2 * pi) ** dim) if r.shape[1] == 1: A /= r[0] ** dim else: A *= r[:dim].prod() c.set(atom.I[:], A) return atom
def grad(self, atoms, axis=None): # reg = s*|det(r)-r0^dim|^k # dr_i = sk*(det(r)-r0^dim)|det(r)-r0^dim|^{k-2}*prod(r_{-i}) c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) dI = 0 * I dx = 0 * x if atoms.space.isotropic: d = r**-self.dim - self.__p[0] dr = d * abs(d) ** (self.__p[1] - 2) * \ (-self.__p[2] * self.dim * r ** (-self.dim - 1)) else: R = r[:, :self.dim].prod(1, keepdims=True) d = R - self.__p[0] d = self.__p[2] * d * abs(d)**(self.__p[1] - 2) dr = zeros(r.shape) ind = (slice(None), slice(self.dim)) dr[ind] = d * R / r[ind] if axis == 0 or axis == 'I': d = dI elif axis == 1 or axis == 'x': d = dx elif axis == 2 or axis == 'r': d = dr else: d = concatenate((dI.reshape(-1), dx.reshape(-1), dr.reshape(-1))) return d
def grad(self, atoms, axis=None): # reg(atoms) = s(I/det(r)-m)^k = s(I*R-m)^k c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) if atoms.space.isotropic: R = r**self.dim else: R = 1 / prod(r[:, :self.dim], axis=1) dI = R dx = 0 * x if atoms.space.isotropic: dr = I * self.dim * r**(self.dim - 1) else: dr = zeros(r.shape) ind = (slice(None), slice(self.dim)) dr[ind] = -(I * R).reshape(-1, 1) / r[ind] if axis == 0 or axis == 'I': d = dI elif axis == 1 or axis == 'x': d = dx elif axis == 2 or axis == 'r': d = dr else: d = concatenate((dI.reshape(-1), dx.reshape(-1), dr.reshape(-1))) return (self.param[2] * self.param[1]) * d * (I * R - self.param[0])**( self.param[1] - 1)
def __DFT(self, arr, inverse=False): ''' X = (x-x0)/dx = 0, 1, ..., L-1 K = k/dk = -L/2, ..., 0, 1, ..., L/2 dft(arr)[K] = \sum_X arr[X] e^{-2\pi i KX/L} = \sum_X arr[X] e^{-2\pi i kx/(dkdxL)}e^{2\pi/(dkdxL) i k\cdot x0} FT(k) = \int arr(x)e^{-2\pi ik\cdot x}dx = \int arr(x) e^{-2\pi ik\cdot x}dx ~ |dx|\sum_x arr[X] e^{-2\pi i Kdk\cdot (Xdx+x0)} = |dx| dft(arr)[K] e^{-2\pi i k\cdot x0} if 1 = dxdk L Assume periodicity so fft(arr)[-k] = fft(arr)[N-k] via fftshift if dim == len(inGrid): Do a full FT on the array else: Use Fourier slice theorem ''' if hasattr(arr, 'asarray'): arr = arr.asarray() arr = context().asarray(arr) if inverse: dx = [1 / (g.item(1) - g.item(0)) for g in self.inGrid] x0 = [-g.item(0) for g in self.inGrid] else: dx = [g.item(1) - g.item(0) for g in self.inGrid] x0 = [g.item(0) for g in self.inGrid] if isinstance(self.ElementSpace, VolSpace): if inverse: FT = _applyweight(arr, self.outGrid, dx, x0) FT = ifftn(ifftshift(FT)) else: FT = fftshift(fftn(arr)) FT = _applyweight(FT, self.outGrid, dx, x0) else: ''' arr[t,x] = \int_{y-x || t} f(y)dy FT[t,X] = FT[f](X) x[t,i,...] = detector[0][i]*w[0][t]+... ''' ax = [i + 1 for i in range(self.dim - 1)] detector = self.outGrid[:self.dim - 1] w = self.outGrid[self.dim - 1:] if inverse: FT = _applyweight_hyperplane(arr, detector, w, dx, x0) FT = ifftn(ifftshift(FT, axes=ax), axes=ax) else: FT = fftshift(fftn(arr, axes=ax), axes=ax) FT = _applyweight_hyperplane(FT, detector, w, dx, x0) return FT
def grad(self, atoms, axis=0): c = context() if axis == 0 or axis == 'I': d = 0 * c.asarray(atoms.I) elif axis == 1 or axis == 'x': d = 0 * c.asarray(atoms.x) elif axis == 2 or axis == 'r': d = 0 * c.asarray(atoms.r) return d
def __call__(self, atoms): r = context().asarray(atoms.r) if r.shape[0] == r.size: return 0 else: d = abs(r[:, self.dim:]) d = d * d return self.s * d.sum() / 2
def __call__(self, atoms): # reg = s*|det(r)-r0^dim|^k c = context() r = c.asarray(atoms.r) if r[:, :self.dim].min() <= 0: return infty if atoms.space.isotropic: d = r**-self.dim - self.__p[0] else: d = r[:, :self.dim].prod(1) - self.__p[0] return self.__p[2] * (abs(d)**self.__p[1]).sum()
def __call__(self, atoms): # reg = sum s*(r-r_0)^{-k} c = context() r = c.asarray(atoms.r) if r[:, :self.dim].min() <= self.r0: return infty if atoms.space.isotropic: d = self.dim * (r - self.r0)**self.k else: d = ((r[:, :self.dim] - self.r0)**self.k).sum(axis=1) return self.s * d.sum()
def hess(self, atoms): # reg(atoms) = s(I/det(r)-m)^k = s(I*R-m)^k # d_y = d(IR)_y*(k(V-m)^{k-1}) # dd_{yz} = dd(IR)_{yz}*(k(V-m)^{k-1}) + # d(IR)_y*d(IR)_z*(k(k-1)(V-m)^{k-2}) c = context() I, r = c.asarray(atoms.I), c.asarray(atoms.r) D = self.dim if atoms.space.isotropic: R = r**D dd = zeros((D + 2, D + 2)) else: R = 1 / prod(r[:, :D], axis=1) dd = zeros((int(1 + D + (D * (D + 1)) / 2), int(1 + D + (D * (D + 1)) / 2))) s = (self.param[1] * (I * R - self.param[0])**(self.param[1] - 1), self.param[1] * (self.param[1] - 1) * (I * R - self.param[0])**(self.param[1] - 2)) # dd_{II} dd[0, 0] = R * R * s[1] # dd_{Ix} dd[0, 1:1 + D], dd[1:1 + D, 0] = 0, 0 # dd_{xx} dd[1:1 + D, 1:1 + D] = 0 # dd_{xr} dd[1:1 + D, 1 + D:], dd[1 + D:, 1:1 + D] = 0, 0 if atoms.space.isotropic: # dd_{Ir} dd[0, 1 + D] = (D * r**(D - 1)) * (s[0] + R * I * s[1]) dd[1 + D, 0] = (D * r**(D - 1)) * (s[0] + R * I * s[1]) # dd_{rr} dd[1 + D, 1 + D] = I * D * (D - 1) * r ** (D - 2) * \ s[0] + (I * D * r ** (D - 1)) ** 2 * s[1] else: # dd_{Ir} for i in range(D): dd[0, 1 + D + i] = -R / r[:, i] * (s[0] + I * R * s[1]) dd[1 + D + i, 0] = -R / r[:, i] * (s[0] + I * R * s[1]) # dd_{rr} for i in range(D): for j in range(i - 1): dd[1 + D + i, 1 + D + j] = I * R / \ (r[:, i] * r[:, j]) * (s[0] + I * R * s[1]) dd[1 + D + j, 1 + D + i] = dd[1 + D + i, 1 + D + j] dd[1 + D + i, 1 + D + i] = I * R / \ (r[:, i] * r[:, i]) * (2 * s[0] + I * R * s[1]) return self.param[2] * dd
def __init__(self, Atoms, Volume, Sino, device='GPU'): DictionaryOp.__init__(self, Atoms, Volume, Sino, linear=False) self.__device = device.lower() if self.__device == 'cpu': raise ValueError('CPU processing not yet supported') self.__fwrd, self.__derivs, self.__L2derivs, self.__proj = self._getOps(Atoms.dim) c = context() # self.__params = (c.copy(Sino.orientations), # tuple(c.copy(x) for x in Sino.ortho), # tuple(c.copy(x) for x in Sino.detector)) self.__vol = tuple(c.cast(x) for x in self.embedding.coord_vectors)
def grad(self, x, y, axis=0): if hasattr(x, 'asarray'): x = x.asarray() if hasattr(y, 'asarray'): y = y.asarray() # d = x - y c = context() if axis == 0: d = c.sub(x, y) else: d = c.sub(y, x) return d
def grad(self, x, y, axis=0): if hasattr(x, 'asarray'): x = x.asarray() if hasattr(y, 'asarray'): y = y.asarray() d = empty(x.shape, dtype=x.dtype) if axis == 1: return -self.grad(x, y, axis=0) c = context() self.__earth_mover_grad(c.asarray(x), c.asarray(y), d) return d
def __call__(self, atoms): # reg(atoms) = s*(I/det(r)-m)^{k} c = context() I, r = c.asarray(atoms.I), c.asarray(atoms.r) if I.min() < 0: return infty if atoms.space.isotropic: V = I * r**self.dim else: V = I / prod(r[:, :self.dim], axis=1) V = abs(V) d = (V - self.param[0])**(self.param[1]) return self.param[2] * d.sum()
def __call__(self, x, y): if hasattr(x, 'asarray'): x = x.asarray() if hasattr(y, 'asarray'): y = y.asarray() d = empty(x.shape[:self.dim - 1], dtype=x.dtype) c = context() x, y = c.asarray(x), c.asarray(y) from time import time tic = time() self.__earth_mover(x, y, d) print('Timing:', time() - tic) return d.sum()
def test_grad(space, Radon, eps, axis=None): if axis is None: Axis = range(3) else: Axis = [axis] from numpy import log10 from time import time tic = time() a = space.random(10, seed=1) R = Radon(a) c = context() def norm2(x): return c.sum(c.mul(x.data, x.data)) / 2 n = norm2(R) for axis in Axis: grad = Radon.grad(a, axis, R) # print(np.array_str(grad, precision=2)) if axis == 0: da = c.rand(a.I.shape) elif axis == 1: da = c.rand(a.x.shape) else: da = c.rand(a.r.shape) for e in eps: aP = a.copy() if axis == 0: c.set(aP.I, c.add(aP.I, c.mul(e, da))) elif axis == 1: c.set(aP.x, c.add(aP.x, c.mul(e, da))) elif axis == 2: c.set(aP.r, c.add(aP.r, c.mul(e, da))) Rp = Radon(aP) nP = norm2(Rp) print('axis = %d: % 3.2f, % 3.2f' % (axis, log10( abs(nP - n - e * c.sum(c.mul(grad, da)))), log10(e))) # print(nP, n, abs(grad).max(), abs(Rp.asarray()).max()) # print((nP - n) / e, c.asarray(c.sum(c.mul(grad, da)))) # print(abs(nP - n - e * c.sum(c.mul(e, da))), log10(e)) print() print('Finished after time: ', time() - tic)
def __call__(self, x, y): if hasattr(x, 'asarray'): x = x.asarray() if hasattr(y, 'asarray'): y = y.asarray() # d = (x - y)**2 c = context() d = c.sub(x, y) if str(x.dtype)[0] == 'f': c.mul(d, d, d) else: # TODO: fix l2 norm for complex data d = abs(d) d *= d return c.sum(d) / 2
def _step(recon, Radon, R, d, data, E, F, dim, iso, j, jj, n, fidelity, reg): c = context() R_old = Radon(recon[j]) I = c.asarray(recon.I[j:j + 1]).copy() x = c.asarray(recon.x[j]).copy() r = c.asarray(recon.r[j]).copy() # c.set(recon.I[j:j + 1], I + d[0]) c.set(recon.x[j], x + d[1:dim + 1]) # c.set(recon.r[j], r + d[dim + 1:]) c.set(recon.I[j:j + 1], max(0, I + d[0])) # c.set(recon.x[j], maximum(-.99, minimum(.99, x + d[1:1 + dim]))) if iso: rr = abs(r + d[dim + 1]) else: rr = r + d[dim + 1:] if dim == 2: if rr[0] < 0: rr[0], rr[2] = -rr[0], -rr[2] if rr[1] < 0: rr[1] = -rr[1] else: if rr[0] < 0: rr[0], rr[3], rr[5] = -rr[0], -rr[3], -rr[5] if rr[1] < 0: rr[1], rr[4] = -rr[1], -rr[4] if rr[2] < 0: rr[2] = -rr[2] c.set(recon.r[j], rr) R, R_old = R + Radon(recon[j]) - R_old, R # R = Radon(recon[:n]) F[jj] = fidelity(R, data) E[jj] = F[jj] + reg(recon[:n]) if E[jj] > E[jj - 1]: c.set(recon.I[j:j + 1], I) c.set(recon.x[j], x) c.set(recon.r[j], r) R = R_old # R = Radon(recon[:n]) return R
def grad(self, atoms, axis=0): # reg(atoms) = -a\log(I) + b/2|x|^2 + c|r| - d\log(|r|) c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) if axis == 0 or axis == 'I': d = -self.param[0] / I elif axis == 1 or axis == 'x': d = self.param[1] * x elif axis == 2 or axis == 'r': if atoms.space.isotropic: d = (self.dim * self.param[2]) * \ r ** (self.dim - 1) - (self.dim * self.param[3]) / r else: d = zeros(r.shape) ind = (slice(None), slice(self.dim)) d[ind] = prod(r[ind], axis=1).reshape(-1, 1) d[ind] = (self.param[2] * d[ind] - self.param[3]) / r[ind] return d
def hess(self, atoms): # reg(atoms) = s(I/det(r)-m)^k = s(I*R-m)^k # d_y = d(IR)_y*(k(V-m)^{k-1}) # dd_{yz} = dd(IR)_{yz}*(k(V-m)^{k-1}) + # d(IR)_y*d(IR)_z*(k(k-1)(V-m)^{k-2}) c = context() r = c.asarray(atoms.r) D = self.dim if atoms.space.isotropic: dd = zeros((D + 2, D + 2)) else: dd = zeros((int(1 + D + (D * (D + 1)) / 2), int(1 + D + (D * (D + 1)) / 2))) if not atoms.space.isotropic: # dd_{rr} for i in range(D, r.shape[1]): dd[1 + D + i, 1 + D + i] = self.s return dd
def __call__(self, atoms): # atoms.I, atoms.x, atoms.r # reg(atoms) = -a\log(I) + b/2|x|^2 + c|r| - d\log(|r|) c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) if I.min() <= 0: return infty d = -self.param[0] * log(I).sum() d += (self.param[1] / 2) * (x * x).sum() if r.min() <= 0: return infty if atoms.space.isotropic: r = r**self.dim else: r = prod(r[:, :self.dim], axis=1) d += self.param[2] * r.sum() - self.param[3] * log(r).sum() d -= r.size * self.param[4] return d
def hess(self, atom): # reg = s*|det(r)-r0^dim|^k # dr_i = sk*sign(R)|R|^{k-1}*prod(r_{-i}) # drr_{ij} = sk*sign(R)[ (k-1)sign(R)|R|^{k-2}prod(r_{-i})prod(r_{-j}) # + |R|^{k-1}prod(r_{-ij})delta_{ij}] # = sk|R|^{k-2}[ (k-1)prod(r_{-i})prod(r_{-j}) # + R*prod(r_{-ij})delta_{ij}] # |r^{-d}-r0|^k -> -dk|r^{-d}-r0|^{k-1}r^{-d-1} # -> dk|R|^{k-2}[d(k-1)r^{-2(d-1)} +(d+1)Rr^{-d-2}] c = context() r = c.asarray(atom.r) D = self.dim if atom.space.isotropic: dd = zeros((D + 2, D + 2)) else: dd = zeros((int(1 + D + (D * (D + 1)) / 2), int(1 + D + (D * (D + 1)) / 2))) # dd_{II} dd[0, 0] = 0 # dd_{xx} dd[1:1 + D, 1:1 + D] = 0 if atom.space.isotropic: # dd_{rr} R = r**-self.dim - self.__p[0] scale = self.__p[2] * self.dim * self.__p[1] * R**(self.__p[1] - 2) dd[1 + D, 1 + D] = scale * (self.dim * (self.__p[1] - 1) * r**(-2 * (self.dim - 1)) + (self.dim + 1) * R * r**(-self.dim - 2)) else: # dd_{rr} for i in range(D): dd[1 + D + i, 1 + D + i] = 1 / (r[:, i] * r[:, i]) return self.s * dd
def grad(self, atoms, axis=None): c = context() I, x, r = c.asarray(atoms.I), c.asarray(atoms.x), c.asarray(atoms.r) dI = 0 * I dx = 0 * x if atoms.space.isotropic: dr = 0 * r else: dr = zeros(r.shape) dr[:, self.dim:] = r[:, self.dim:] if axis == 0 or axis == 'I': d = dI elif axis == 1 or axis == 'x': d = dx elif axis == 2 or axis == 'r': d = dr else: d = concatenate((dI.reshape(-1), dx.reshape(-1), dr.reshape(-1))) return self.s * d
def hess(self, atoms): # reg = sum s*(r-r_0)^{-k} c = context() r = c.asarray(atoms.r) D = self.dim if atoms.space.isotropic: dd = zeros((r.shape[0], D + 2, D + 2)) else: dd = zeros((r.shape[0], int(1 + D + (D * (D + 1)) / 2), int(1 + D + (D * (D + 1)) / 2))) if atoms.space.isotropic: # dd_{rr} dd[:, 1 + D, 1 + D] = D * self.k * \ (self.k - 1) * (r - self.r0) ** (self.k - 2) else: # dd_{rr} for i in range(D): dd[:, 1 + D + i, 1 + D + i] = self.k * \ (self.k - 1) * (r[:, i] - self.r0) ** (self.k - 2) return self.s * dd
def doKL_ProjGDStep_iso(res, atom, t, R): ''' res = data - R(atom) min |data-f|^2 s.t. f = R(atom) f_{n+1} = argmin |data-f|^2 + t*KL(\bar f_n|f) atom_{n+1} = argmin KL(f_{n+1}|R(atom)) \bar f_{n+1} = R(atom_{n+1}) ''' c = context() dim = atom.x.shape[1] iso = (atom.r.shape[1] == 1) res += R(atom) f = maximum(0, c.copy(res.data)) if iso: Z = 0 else: Z = (0, 0) c.set(atom.r[0, dim:], 0) # params = res.data.shape, res.data.dtype # const = 2 * pi * params[0][0] * res.data.size / res.space.volume() # from matplotlib import pyplot as plt # plt.subplot('131') # plt.imshow(res.data.T) c.set(atom.I[:], 1) c.set(atom.x[:], 0) c.set(atom.r[0, :3], 10) c.set(atom.r[0, 3:], 0) for _ in range(100): old = [ c.copy(atom.r[Z]), c.copy(atom.x).reshape(-1), c.copy(atom.I[0]) ] if not iso: old[0] = 1 / old[0] If = MOM0(f) if If.sum() < 1e-8: if atom.r[Z] < 1e-4: return atom c.set(atom.r, c.mul(atom.r, .5)) continue Ify = MOM1(f, res.space.detector, res.space.ortho) op, vec = orthog_op(If, Ify, res.space.orientations) try: M = linalg.solve(op, vec) except Exception: M = 0 * vec Ifyy = MOM2(f, res.space.detector, res.space.ortho, M) c.set(atom.x[:], M) # S^(n+2)[Ifyy] + S^n[If] -n A*const = 0 # A = (If*S^n)/const S = sqrt(Ifyy / ((dim - 1) * If.sum())) if iso: c.set(atom.r[:], S) else: c.set(atom.r[0, :dim], 1 / S) RR = R(atom).data A = (If.sum() * atom.I[0]) / c.sum(RR) RR *= (A / atom.I[0]) c.set(atom.I[:], A) if (norm(old[0] - S) > 1e-4 * norm(old[0])) or ( norm(old[1] - M.reshape(-1)) > 1e-4 * norm(old[1])) or ( norm(old[2] - A) > 1e-4 * norm(old[2])): f = maximum(0, t * res.data + (1 - t) * RR) else: break # print(M, S, A, KL_2D(f, R(atom).data)) # plt.subplot('132') # plt.imshow(R(atom).data.T) # plt.subplot('133') # plt.imshow(f.T) # plt.show(block=True) # print(A, S, M) return atom
def _startup(recon, data, max_iter, Radon, view, guess, L, gt=None, RECORD=None, thresh=None, angles=None): ''' recon is element of atom space L is number of energy recordings per iter ''' from time import gmtime, strftime print('Start time is: ', strftime("%H:%M", gmtime())) if RECORD is not None: __makeVid(stage=0) from matplotlib import pyplot as plt c = context() if not hasattr(max_iter, '__iter__'): max_iter = [max_iter, 1] elif len(max_iter) == 1: max_iter = max_iter.copy() max_iter.append(1) nAtoms = len(recon) if view is None: view = Radon.discretise if guess is None: tmp = nAtoms else: tmp = int(round(nAtoms * (nAtoms + 1) / 2)) + 1 E = zeros(prod(max_iter) * tmp * L + 1) F = zeros(prod(max_iter) * tmp * L + 1) dim = recon.space.dim # iso = recon.space.isotropic if dim == 2: fig, ax = plt.subplots(2, 3, figsize=(20, 10)) if gt is None: def plotter(recon, R, E, F, jj): n = max_iter[1] return _plot2D(ax, view(recon), R, data, E[::n], F[::n], jj // (n * L)) else: def plotter(recon, R, E, F, jj): n = max_iter[1] return _plot2DwithGT(ax, view(recon), gt, R, data, E[::n], F[::n], jj // (n * L)) else: from mpl_toolkits.mplot3d.art3d import Poly3DCollection fig, ax = plt.subplots(2, 4, figsize=(20, 10)) ax[0, 0].remove() ax[0, 0] = fig.add_subplot(241, projection='3d') ax[0, 0].set_axis_off() ax[1, 0].remove() ax[1, 0] = fig.add_subplot(245, projection='3d') ax[1, 0].set_axis_off() if gt is None: if thresh is None: thresh = data.asarray().max() / 100 if angles is None: angles = ((20, 45), (20, 135)) def plotter(recon, R, E, F, jj): n = max_iter[1] return _plot3D(ax, view(recon), R, data, E[::n], F[::n], jj // (n * L), len(recon), thresh, angles) else: ax[0, 1].remove() ax[0, 1] = fig.add_subplot(242, projection='3d') ax[0, 1].set_axis_off() ax[1, 1].remove() ax[1, 1] = fig.add_subplot(246, projection='3d') ax[1, 1].set_axis_off() if thresh is None: thresh = gt.asarray().max() / 10 if angles is None: angles = ((0, 0), (0, 90)) def plotter(recon, R, E, F, jj): n = max_iter[1] return _plot3DwithGT(ax, view(recon), gt, R, data, E[::n], F[::n], jj // (n * L), len(recon), thresh, angles) if RECORD is not None: writer = __makeVid(fig, RECORD, stage=1) def do_plot(recon, r, e, f, n, i, jj, end=False): if end: print('Reconstruction Finished', jj, F[:jj].min()) __makeVid(writer, plt, stage=3) else: plotter(recon[:n], r, e, f, jj) __makeVid(writer, plt, stage=2) print('%.2f, %.2f, % 5.3f' % (n / nAtoms, i / max_iter[0], E[jj - 1])) else: def do_plot(recon, r, e, f, n, i, jj, end=False): if end: print('Reconstruction Finished', jj, F[:jj].min()) plt.show(block=True) else: print('%.2f, %.2f, % 5.3f' % (n / nAtoms, i / max_iter[0], E[jj - 1])) plt.draw() plt.pause(.01) plotter(recon[:n], r, e, f, jj) plt.show(block=False) return c, E, F, nAtoms, max_iter, do_plot
def doKL_LagrangeStep_iso(res, atom, t, R): ''' res = data - R(atom) min |data-f|^2 + t*KL(f|R(atom)) ''' c = context() dim = atom.x.shape[1] iso = (atom.r.shape[1] == 1) res += R(atom) f = maximum(0, c.copy(res.data)) if iso: Z = 0 else: Z = (0, 0) c.set(atom.r[dim:], 0) for _ in range(100): old = [ c.copy(atom.r[Z]), c.copy(atom.x).reshape(-1), c.copy(atom.I[0]) ] if not iso: old[0] = 1 / old[0] If = MOM0(f) if If.sum() < 1e-8: if atom.r[Z] < 1e-4: return atom if iso: c.set(atom.r, c.mul(atom.r, .5)) else: c.set(atom.r, c.mul(atom.r, 2)) continue Ify = MOM1(f, res.space.detector, res.space.ortho) op, vec = orthog_op(If, Ify, res.space.orientations) try: M = linalg.solve(op, vec) except Exception: M = 0 * vec Ifyy = MOM2(f, res.space.detector, res.space.ortho, M) c.set(atom.x[:], M) S = sqrt(Ifyy / ((dim - 1) * If.sum())) if iso: c.set(atom.r[:], S) else: c.set(atom.r[0, :dim], 1 / S) RR = R(atom).data A = (If.sum() * atom.I[0]) / c.sum(RR) RR *= (A / atom.I[0]) c.set(atom.I[:], A) if (norm(old[0] - S) > 1e-4 * norm(old[0])) or ( norm(old[1] - M.reshape(-1)) > 1e-4 * norm(old[1])) or ( norm(old[2] - A) > 1e-4 * norm(old[2])): Newton_sino_2D(res.data, RR, t, f) else: break return atom
def MOM0(res): ''' return \int res ''' return array([context().sum(res[i]) for i in range(res.shape[0])], dtype=res.dtype)
def discretise(self, atoms, out=None): if out is None: out = self.embedding.element(context().empty(self.embedding.shape)) self.__proj(atoms, self.__vol, out.data) return out
def __call__(self, atoms, out=None): if out is None: out = self.range.element(context().empty(self.range.shape)) self.__fwrd(atoms, self, out.data) return out