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()
def test_operator_matrix_multiply(self): matrix_size = (10,10) m = yp.rand(matrix_size, global_dtype, global_backend) xm = yp.rand(matrix_size[1], global_dtype, global_backend) M = ops.MatrixMultiply(m) # Check Forward operator assert yp.sumb(yp.abs(yp.vec(yp.changeBackend(M * xm, 'numpy')) - yp.vec(yp.changeBackend(m, 'numpy').dot(yp.changeBackend(xm, 'numpy'))))) < eps, "%f" % yp.sumb(yp.abs(yp.changeBackend(M * xm, 'numpy') - yp.changeBackend(m, 'numpy').dot(yp.changeBackend(xm, 'numpy'))[:, np.newaxis])) # Check Adjoint assert yp.sumb(yp.abs(yp.vec(yp.changeBackend(M.H * xm, 'numpy')) - yp.vec(np.conj(yp.changeBackend(m, 'numpy').T).dot(yp.changeBackend(xm, 'numpy'))))) < eps, "%f" % yp.sumb(yp.abs(yp.changeBackend(M.H * xm, 'numpy') - np.conj(yp.changeBackend(m, 'numpy').T).dot(yp.changeBackend(xm, 'numpy'))[:, np.newaxis])) # Check gradient M.gradient_check()
def test_intensity(self): I = ops.Intensity(image_size) # Check forward operator assert yp.sumb(yp.abs((yp.abs(yp.changeBackend(self.x, 'numpy')) ** 2) - yp.changeBackend(I * self.x, 'numpy'))) < eps # Check gradient I.gradient_check()
def test_operator_flip(self): ''' Flip Operator ''' flip_axis = 0 L = ops.Flip(image_size, axis=flip_axis) # Check forward operator assert yp.sumb(yp.abs(L * self.x - yp.flip(self.x, flip_axis))) < eps, "%f" % yp.sumb(yp.abs(L * self.x - vec(yp.flip(self.x, flip_axis)))) # Check gradient L.gradient_check()
def test_operator_crop_non_centered(self): ''' Non-centered Crop Operator ''' # Generate Crop Operator crop_size = (image_size[0] // 2, image_size[1] // 2) crop_start = (6, 6) CR = ops.Crop(image_size, crop_size, pad_value=0, dtype=global_dtype, backend=global_backend, crop_start=crop_start) # Check forward operator y_1 = yp.changeBackend(CR * self.x, 'numpy') y_2 = yp.changeBackend(yp.crop(self.x, crop_size, crop_start), 'numpy') assert yp.sumb(yp.abs(y_1 - y_2)) < eps # Check Adjoint Operator pad_size = [int((image_size[i] - crop_size[i]) / 2) for i in range(len(image_size))] y_3 = yp.pad(yp.crop(self.x, crop_size, crop_start), image_size, crop_start, pad_value=0) y_4 = yp.reshape(CR.H * CR * self.x, image_size) assert yp.sumb(yp.abs(y_3 - y_4)) < eps # Check gradient CR.gradient_check()
def test_operator_crop(self): ''' Crop Operator ''' # Generate Crop Operator crop_size = (image_size[0] // 2, image_size[1] // 2) CR = ops.Crop(image_size, crop_size, pad_value=0, dtype=global_dtype, backend=global_backend) # Check forward operator crop_start = tuple(np.asarray(image_size) // 2 - np.asarray(crop_size) // 2) y_1 = yp.changeBackend(CR * self.x, 'numpy') y_2 = yp.changeBackend(yp.crop(self.x, crop_size, crop_start), 'numpy') assert yp.sumb(yp.abs(y_1 - y_2)) < eps # Check Adjoint Operator pad_size = [int((image_size[i] - crop_size[i]) / 2) for i in range(len(image_size))] y_3 = yp.pad(yp.crop(self.x, crop_size, crop_start), image_size, crop_start, pad_value=0) y_4 = CR.H * CR * self.x assert yp.sumb(yp.abs(y_3 - y_4)) < eps # Check gradient CR.gradient_check()
def test_operator_wavelet(self): ''' Wavelet Transform Operator ''' import pywt wavelet_list = ['db1', 'haar', 'rbio1.1', 'bior1.1', 'bior4.4', 'sym12'] for wavelet_test in wavelet_list: # Wavelet Transform W = ops.WaveletTransform(image_size, wavelet_type=wavelet_test, use_cycle_spinning=False) # Check forward operation coeffs = pywt.wavedecn(self.x, wavelet=wavelet_test) x_wavelet, coeff_slices = pywt.coeffs_to_array(coeffs) assert yp.sumb(yp.abs(yp.changeBackend(W * self.x, 'numpy') - x_wavelet)) < eps, "Difference %.6e" # Check inverse operation coeffs_from_arr = pywt.array_to_coeffs(x_wavelet, coeff_slices) cam_recon = pywt.waverecn(coeffs_from_arr, wavelet=wavelet_test) assert yp.sumb(yp.abs(W.H * W * self.x - self.x)) < 1e-2 # Ensure that the wavelet transform isn't just identity (weird bug) if W.shape[1] is yp.size(self.x): assert yp.sumb(yp.abs(W * yp.vec(self.x) - yp.vec(self.x))) > 1e-2, "%s" % wavelet_test
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()
def test_operator_shift(self): ''' Shift Operator ''' # Normal shift shift = (0, 10) # should be y, x T = ops.Shift(image_size, shift) def shift_func(x, shift): x = yp.changeBackend(self.x, 'numpy') for ax, sh in enumerate(shift): x = np.roll(self.x, int(sh), axis=ax) return(x) # Check Forward Operator y_1 = yp.changeBackend(T * self.x, 'numpy') y_2 = shift_func(yp.changeBackend(self.x, 'numpy'), shift) assert yp.sumb(yp.abs(y_1 - y_2)) < eps # Check Adjoint Operator assert yp.sumb(yp.abs(T.H * T * self.x - self.x)) < eps # Check gradient T.gradient_check()
def test_operator_sum(self): ''' Element-wise Sum Operator ''' axis_to_sum = (0,1) Σ = ops.Sum(image_size, axes=axis_to_sum) # Check forward operator y_1 = yp.changeBackend(Σ * self.x, 'numpy') y_2 = yp.sumb(yp.changeBackend(self.x, 'numpy'), axes=axis_to_sum) assert yp.abs(yp.sumb(y_1 - y_2)) < eps # Check adjoint operator y_3 = yp.changeBackend(Σ.H * Σ * self.x, 'numpy') reps = [1, ] * len(image_size) axes = list(range(len(image_size))) if axis_to_sum is 'all' else axis_to_sum scale = 1 for axis in axes: reps[axis] = image_size[axis] scale *= 1 / image_size[axis] y_4 = yp.tile(y_2, reps) * scale assert yp.sumb(yp.abs(y_3 - y_4)) < eps # Check gradient Σ.gradient_check(eps=1)
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()
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)