예제 #1
0
    def test_operator_fourier_transform(self):
        # Define "true" FFTs
        Ft = lambda x: np.fft.fftshift(np.fft.fft2(np.fft.fftshift(x, axes=(0, 1)), axes=(0, 1), norm='ortho'), axes=(0, 1))
        iFt = lambda x: np.fft.fftshift(np.fft.ifft2(np.fft.fftshift(x, axes=(0, 1)), axes=(0, 1), norm='ortho'), axes=(0, 1))

        eps_fft = yp.precision(self.x, for_sum=True)

        if global_backend == 'numpy':
            fft_backends = ['scipy', 'numpy']
        else:
            fft_backends = ['af']

        for fft_backend in fft_backends:

            # Create Operator
            F = ops.FourierTransform(image_size, dtype=global_dtype, axes=(0, 1), fft_backend=fft_backend, center=True, backend=global_backend)

            # Check forward model
            assert yp.sumb(yp.abs(Ft(self.x).reshape(image_size) - yp.changeBackend(F * self.x, 'numpy').reshape(image_size))) < eps_fft, '%f' % yp.sumb(yp.abs(Ft(x).reshape(image_size) - yp.changeBackend(F * vec(self.x), 'numpy').reshape(image_size)))
            assert yp.sumb(yp.abs(iFt(self.x).reshape(image_size) - yp.changeBackend((F.H * self.x), 'numpy').reshape(image_size))) < eps_fft

            # Check reciprocity
            assert yp.sumb(yp.abs(F * F.H * self.x - self.x)) < eps_fft, "%.4e" % yp.sumb(yp.abs(F * F.H * vec(self.x) - vec(self.x)))

            # Check Gradient
            F.gradient_check()
예제 #2
0
    def test_methanical_condition_number(self):
        ''' Mechanical test of condition number calculation '''

        # Unitary Matrix
        F = ops.FourierTransform(image_size, dtype=global_dtype, backend=global_backend)
        assert F.condition_number == 1
        assert not F.condition_number_is_upper_bound

        # Matrix with a condition number
        hh = yp.changeBackend((np.random.rand(image_size[0], image_size[1]) + 0.1).astype(np.complex64), global_backend)
        D = ops.Diagonalize(hh, dtype=global_dtype, backend=global_backend)
        assert not D.condition_number_is_upper_bound

        # Product of two unitary matricies
        assert (F * F).condition_number == 1
        assert not (F * F).condition_number_is_upper_bound

        # Product of one unitary and one non-singular matrix
        assert (F * D).condition_number == D.condition_number
        assert not (F * D).condition_number_is_upper_bound # because one matrix is unitary, this condition number is NOT an upper bound. This can be checked numerically.

        # Product of two non-singular matricies.
        hh_2 = yp.changeBackend((np.random.rand(image_size[0], image_size[1]) + 0.1).astype(np.complex64), global_backend)
        D2 = ops.Diagonalize(hh_2, dtype=global_dtype, backend=global_backend)
        assert (D * D2).condition_number >= D.condition_number
        assert (D * D2).condition_number_is_upper_bound
예제 #3
0
    def test_mechanical_smooth_flag(self):
        F = ops.FourierTransform(image_size, dtype=global_dtype, axes=(0, 1)) # Linear Operator
        L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend) # Non-linear operator

        assert F.linear
        assert not L2.linear
        assert not (L2 * F).linear
        assert (F + F).linear
        assert not (L2 * F + L2 * F).linear
예제 #4
0
    def test_mechanical_gradient_2(self):
        ''' Mechanical test for calculating the gradient of chained linear operators '''
        F = ops.FourierTransform(image_size, dtype=global_dtype, axes=(0, 1))
        D = ops.Diagonalize(self.h, dtype=global_dtype, backend=global_backend)
        A = F.H * D * F
        A.label = 'A'

        # Check gradient numerically
        A.gradient_check()
예제 #5
0
    def test_mechanical_sum_of_norms(self):
        L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend)
        F = ops.FourierTransform(image_size, dtype=global_dtype, axes=(0, 1))
        D = ops.Diagonalize(self.h, dtype=global_dtype, backend=global_backend)

        O_1 = L2 * ((F.H * D * F) - self.y)
        O_2 = 1e-3 * L2 * F
        O = O_1 + O_2

        # Check gradient operator (adjoint form)
        O.gradient_check()
예제 #6
0
    def test_mechanical_gradient_4(self):
        ''' Mechanical test for an outer non-linear operator with outer non-linear operator and a linear operator in-between'''
        shift_true = np.asarray((-5,3)).astype(yp.getNativeDatatype(global_dtype, 'numpy'))

        # Inner non-linear operator, linear operator in middle, and norm on outside
        F = ops.FourierTransform(image_size, dtype=global_dtype, backend=global_backend)
        D_object = ops.Diagonalize((F * yp.vec(self.x)).reshape(image_size), label='D_{object}', dtype=global_dtype, backend=global_backend)
        R = ops.PhaseRamp(image_size, dtype=global_dtype, backend=global_backend)
        A_shift = F.H * D_object * R
        y = A_shift(shift_true)
        L2 = ops.L2Norm(image_size[0] * image_size[1], dtype=global_dtype, backend=global_backend)
        objective = L2 * (A_shift - self.y)

        # Check gradient
        objective.gradient_check()
예제 #7
0
    def setup_method(self, test_method):
        # Load object and crop to size
        x_0 = yp.rand(image_size)

        # Convert object to desired backend
        self.x = yp.changeBackend(x_0, global_backend)

        # Generate convolution kernel h
        h_size = np.array([4, 4])
        self.h = yp.zeros(image_size, global_dtype, global_backend)
        self.h[image_size[0] // 2 - h_size[0] // 2:image_size[0] // 2 + h_size[0] // 2,
          image_size[1] // 2 - h_size[1] // 2:image_size[1] // 2 + h_size[1] // 2] = yp.randn((h_size[0], h_size[1]), global_dtype, global_backend)

        # A = ops.Convolution(image_size, h, dtype=global_dtype, fft_backend='numpy', backend=global_backend)
        self.A = ops.FourierTransform(image_size, dtype=global_dtype, backend=global_backend, center=True)
        self.y = self.A(yp.vectorize(self.x))
예제 #8
0
    def test_operator_exponential(self):
        L2 = ops.L2Norm(image_size)
        F = ops.FourierTransform(image_size)
        EXP = ops.Exponential(image_size)

        # Forward model
        assert yp.sumb(yp.abs(yp.changeBackend(EXP * self.x, 'numpy') - np.exp(yp.changeBackend(self.x, 'numpy')))) < eps

        # Check gradient
        EXP.gradient_check()

        # Generate composite operator
        D = ops.Diagonalize(self.h)
        L2 = ops.L2Norm(image_size)

        EXP_COMP = L2 * F * EXP
        EXP_COMP.gradient_check()

        EXP_COMP_2 = L2 * F * EXP * D
        EXP_COMP_2.gradient_check()
예제 #9
0
    def test_operator_stacking_linear(self):
        # Create list of operators
        op_list_linear = [
            ops.FourierTransform(image_size, dtype=global_dtype, backend=global_backend),
            ops.Identity(image_size, dtype=global_dtype, backend=global_backend),
            ops.Exponential(image_size, dtype=global_dtype, backend=global_backend)
        ]

        # Horizontally stacked operators
        H_l = ops.Hstack(op_list_linear)

        # Vertically stack x for forward operator
        x_np = yp.changeBackend(self.x, 'numpy')
        x3 = yp.changeBackend(np.vstack((x_np, x_np, x_np)), global_backend)

        # Check forward operation
        y2 = yp.zeros(op_list_linear[0].N, op_list_linear[0].dtype, op_list_linear[0].backend)

        for op in op_list_linear:
            y2 = y2 + op * self.x

        assert yp.sumb(yp.abs(yp.changeBackend(H_l(x3) - y2, 'numpy'))) < eps, "%.4e" % yp.sumb(yp.abs(H_l(x3) - y2))

        # Check gradient
        H_l.gradient_check()

        # Create vertically stacked operator
        V_l = ops.Vstack(op_list_linear)

        # Check forward operator
        y3 = np.empty((0,image_size[1]), dtype=yp.getNativeDatatype(global_dtype, 'numpy'))
        for index, op in enumerate(op_list_linear):
            y3 = np.append(y3, (op * self.x), axis=0)

        y3 = yp.changeBackend(y3, global_backend)
        assert yp.sumb(yp.abs(V_l * self.x - y3)) < eps, "%.4e" % yp.sumb(yp.abs(V_l * vec(x) - y3))

        # Check gradient
        V_l.gradient_check()
예제 #10
0
    def test_operator_phase_ramp(self):
        eps_phase_ramp = 1e-4
        shift = yp.changeBackend(np.asarray((-5,3)).astype(yp.getNativeDatatype(global_dtype, 'numpy')), global_backend)

        # Generate phase ramp
        R = ops.PhaseRamp(image_size)
        r = R * shift

        F = ops.FourierTransform(image_size, dtype=global_dtype, normalize=False, backend=global_backend)
        D_R = ops.Diagonalize(r, dtype=global_dtype)
        S_R = F.H * D_R * F

        # Pixel-wise shift operator
        S = ops.Shift(image_size, shift)

        # Check that phase ramp is shifting by correct amount
        assert yp.sumb(yp.abs(yp.changeBackend(S_R * self.x, 'numpy') - yp.changeBackend(S * self.x, 'numpy'))) < 1e-3

        # Check gradient of phase ramp convolution
        S_R.gradient_check()

        # Check gradient of phase ramp
        R.gradient_check(eps=1e-1)