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
예제 #2
0
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)
예제 #5
0
    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
예제 #11
0
    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()
예제 #16
0
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
예제 #18
0
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
예제 #26
0
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)
예제 #29
0
 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
예제 #30
0
 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