def test_resample(self): """ Compare resampling in Fourier space vs. real space i.e. compare resample() with resample_fourier_sp() :return: """ expand_x = 3 expand_y = 2 img = np.random.rand(30, 30) img_ft = fft.fft2(img) img_resampled_rs = tools.duplicate_pix(img, nx=expand_x, ny=expand_y) img_resampled_rs_ft = fft.fft2(img_resampled_rs) img_resampled_fs = tools.duplicate_pix_ft(img_ft, mx=expand_x, my=expand_y, centered=False) img_resampled_fs_rs = fft.ifft2(img_resampled_fs) err_fs = np.abs(img_resampled_fs - img_resampled_rs_ft).max() err_rs = np.abs(img_resampled_rs - img_resampled_fs_rs).max() self.assertTrue(err_fs < 1e-12) self.assertTrue(err_rs < 1e-12)
def high_pass_filter(image, std, cutoff): # 2d gaussian kernel kernel = gaussian_kernel(std) kernel_2d = kernel * kernel.T # pp.imsave('q4_07_highpass_{}.jpg'.format(std), 1 - kernel_2d, cmap='gray') # gaussian kernel shifted fft kernel_shifted_fft = 1 - (fft.fftshift( np.abs(fft.fft2(kernel_2d, image.shape)))) # pp.imsave('07_highpass_{}_frequency_domain.jpg'.format(std), kernel_shifted_fft, cmap='gray') # apply cutoff h = kernel_shifted_fft.shape[0] w = kernel_shifted_fft.shape[1] center_h = h // 2 if is_even(h) else (h + 1) // 2 center_w = w // 2 if is_even(w) else (w + 1) // 2 for row in range(h): for col in range(w): if (row - center_h)**2 + (col - center_w)**2 < cutoff**2: kernel_shifted_fft[row, col] = 0 # pp.imsave('09_highpass_cutoff.jpg', kernel_shifted_fft, cmap='gray') # image shifted fft image_shifted_fft = (fft.fftshift((fft.fft2((image))))) # filtered image shifted fft filtered_image_frequency_domain = image_shifted_fft * kernel_shifted_fft return filtered_image_frequency_domain
def test_fft2(self): x = random((30, 20)) + 1j * random((30, 20)) expect = fft.fft(fft.fft(x, axis=1), axis=0) assert_array_almost_equal(expect, fft.fft2(x)) assert_array_almost_equal(expect, fft.fft2(x, norm="backward")) assert_array_almost_equal(expect / np.sqrt(30 * 20), fft.fft2(x, norm="ortho")) assert_array_almost_equal(expect / (30 * 20), fft.fft2(x, norm="forward"))
def power_spec(temp, source): """ Compute power spectrum via fft. Much fast than a convolution """ data_fft = fft2(temp) data_fft2 = np.conj(fft2(source)) x = np.multiply(data_fft, data_fft2) x /= np.abs(x) return ifft2(x).real
def kinematicsim(crystal, kx, ky, energy=90): """ Propagate a plane wave through a crystal and compute the resulting diffraction pattern, in the kinematic approximation (thin specimen). .. versionadded:: 2.0.5 Parameters ---------- crystal : crystals.Crystal Crystal from which to scatter. kx, ky : `~numpy.ndarray`, shape (N,M) Momenta mesh where to calculate the diffraction pattern [:math:`Å^{-1}`] energy : float, optional Electron energy [keV] Returns ------- diff_pattern : `~numpy.ndarray` Scattered intensity. """ shape = tuple(map(fft.next_fast_len, kx.shape)) period_x, period_y, period_z = crystal.periodicity # We create the grid ourselves so that we minimize Fourier artifacts as much as possible. # It is much easier to interpolate to the requested grid than to prevent artifact formation. extent = 8 * period_x * period_y extent_x = np.linspace(0, extent, num=shape[0]) extent_y = np.linspace(0, extent, num=shape[1]) xx, yy = np.meshgrid( extent_x, extent_y, indexing="xy", ) kx_, ky_ = fft2freq(xx, yy, indexing="xy") k = np.hypot(kx_, ky_) potential = pelectrostatic(crystal, xx, yy) transmission_function = np.exp(1j * interaction_parameter(energy) * potential) exit_wave = fft.ifft2( fft.fft2(np.ones_like(xx, dtype=complex) * transmission_function) ) intensity = fft.fftshift(np.abs(fft.fft2(exit_wave)) ** 2) kx_ = fft.fftshift(kx_) ky_ = fft.fftshift(ky_) # Note that the definition of 'frequency' in fftfreq & friends necessitates dividing by 2pi twopi = 2 * np.pi return RegularGridInterpolator( points=(kx_[0, :], ky_[:, 0]), values=intensity, bounds_error=False, fill_value=0, ).__call__(xi=(kx / twopi, ky / twopi))
def forward_U(w, beta): # u-component for grounded ice w_ft = fft2(w) beta_ft = fft2(beta) h_ft = forward_w(w) + forward_beta(beta) S_ft = -Ub_ * (nu * beta_ft + tau * sg_fwd(w)) - 1j * (2 * np.pi * kx) * ( lamda * Uh_ * h_ft + Uw_ * w_ft) return S_ft
def forward_V(w, beta): # v-component for grounded ice w_ft = fft2(w) beta_ft = fft2(beta) h_ft = forward_w(w) + forward_beta(beta) S_ft = -Vb_ * (nu * beta_ft + tau * sg_fwd(w)) - 1j * (2 * np.pi * ky) * ( lamda * Vh_ * h_ft + Vw_ * w_ft) return S_ft
def filter_bank(M, N, J, L=8): """ Builds in Fourier the Morlet filters used for the scattering transform. Each single filter is provided as a dictionary with the following keys: * 'j' : scale * 'theta' : angle used Parameters ---------- M, N : int spatial support of the input J : int logscale of the scattering L : int, optional number of angles used for the wavelet transform Returns ------- filters : list A two list of dictionary containing respectively the low-pass and wavelet filters. Notes ----- The design of the filters is optimized for the value L = 8. """ filters = {} filters['psi'] = [] for j in range(J): for theta in range(L): psi = {} psi['j'] = j psi['theta'] = theta psi_signal = morlet_2d(M, N, 0.8 * 2**j, (int(L - L / 2 - 1) - theta) * np.pi / L, 3.0 / 4.0 * np.pi / 2**j, 4.0 / L) psi_signal_fourier = fft2(psi_signal) # drop the imaginary part, it is zero anyway psi_signal_fourier = np.real(psi_signal_fourier) for res in range(min(j + 1, max(J - 1, 1))): psi_signal_fourier_res = periodize_filter_fft( psi_signal_fourier, res) psi[res] = psi_signal_fourier_res filters['psi'].append(psi) filters['phi'] = {} phi_signal = gabor_2d(M, N, 0.8 * 2**(J - 1), 0, 0) phi_signal_fourier = fft2(phi_signal) # drop the imaginary part, it is zero anyway phi_signal_fourier = np.real(phi_signal_fourier) filters['phi']['j'] = J for res in range(J): phi_signal_fourier_res = periodize_filter_fft(phi_signal_fourier, res) filters['phi'][res] = phi_signal_fourier_res return filters
def ourconv(image, filt): # pad padded_size = np.array(image.shape) + np.array(filt.shape) pad_img = pad_RHS(image, padded_size, padval=0.5) pad_filt = pad_RHS(filt, padded_size, padval=0) # Paul's slightly corrected version temp = np.real(fft.ifft2(fft.fft2(pad_img) * fft.fft2(pad_filt))) # extract the appropriate portion of the filtered image filtered = unpad_RHS(temp, image.shape) return filtered
def _fresnel_old_dfft(cmode_to_propagate, wavelength, nx, ny, xstart, ystart, xend, yend, rx, ry, distance): # Warning! The fft2 of impulse function and ic should be done together with # numpy fft fft2. Or some speckle will apear. """ Double FFT Fresnel propagation of coherent mode. Args: cmode_to_propagate - the coherent mode to propagate. cmode_mask - the mask of coherent mode. wavelength - the wavelength of light field. nx - the dim of aixs x. ny - the dim of axis y. xstart - location of start along axis x. ystart - location of start along axis y. xend - location of end along axis x. yend - lcoation of end along axis y. rx - the range of x. ry - the range of y. distance - the distance of the propagation. Return: propagated coherent mode. """ # cmode_to_propagate = cmode_to_propagate # wave number k wave_num = 2 * np.pi / wavelength # the axis in frequency space x0 = np.linspace(xstart, xend, nx) y0 = np.linspace(ystart, yend, ny) mesh_x, mesh_y = np.meshgrid(x0, y0) # propagation function impulse = (np.exp(1j * wave_num * distance) * np.exp(-1j * wave_num * (mesh_x**2 + mesh_y**2) / (2 * distance)) / (1j * wavelength * distance)) # the multiply of coherent mode and propagation function propagated_cmode = fft.ifftshift( fft.ifft2(fft.fft2(cmode_to_propagate) * fft.fft2(impulse))) return propagated_cmode
def test_translate_ft(self): """ Test translate_ft() function :return: """ img = np.random.rand(100, 100) img_ft = fft.fftshift(fft.fft2(fft.ifftshift(img))) dx = 0.065 fx = tools.get_fft_frqs(img.shape[1], dx) fy = tools.get_fft_frqs(img.shape[0], dx) df = fx[1] - fx[0] # x-shifting for n in range(1, 20): img_ft_shifted = tools.translate_ft(img_ft, [n * df, 0], dx) max_err = np.abs(img_ft_shifted[:, :-n] - img_ft[:, n:]).max() self.assertTrue(max_err < 1e-7) # y-shifting for n in range(1, 20): img_ft_shifted = tools.translate_ft(img_ft, [0, n * df], dx) max_err = np.abs(img_ft_shifted[:-n, :] - img_ft[n:, :]).max() self.assertTrue(max_err < 1e-7) # x+y shifting for n in range(1, 20): img_ft_shifted = tools.translate_ft(img_ft, [n * df, n * df], dx) max_err = np.abs(img_ft_shifted[:-n, :-n] - img_ft[n:, n:]).max() self.assertTrue(max_err < 1e-7)
def test_estimate_phase(self): """ Test estimate_phase() function, which guesses phase from value of image FT :return: """ # set parameters dx = 0.065 nx = 2048 f = 1 / 0.25 angle = 30 * np.pi / 180 frqs = [f * np.cos(angle), f * np.sin(angle)] phi = 0.2377747474 # create sample image with origin in center x_center = tools.get_fft_pos(nx, dx) y_center = x_center xx_center, yy_center = np.meshgrid(x_center, y_center) m_center = 1 + 0.2 * np.cos( 2 * np.pi * (frqs[0] * xx_center + frqs[1] * yy_center) + phi) m_center_ft = fft.fftshift(fft.fft2(fft.ifftshift(m_center))) phase_guess_center = sim.get_phase_ft(m_center_ft, frqs, dx) self.assertAlmostEqual(phi, float(phase_guess_center), places=5)
def step(self): """Advance the algorithm one iteration.""" G = fft.fft2(self.g) mseF = np.sum((abs(G) - self.absF)**2) / G.size phs_G = np.angle(G) Gprime = self.absF * np.exp(1j * phs_G) gprime = fft.ifft2(Gprime) msef = np.sum((abs(gprime) - self.absg)**2) / G.size gprimeprime = gprime # update g'' where the constraints are violated mask = abs(gprime) < 0 mask |= self.supportmask gprimeprime[~mask] = self.g[~mask] gprimeprime[mask] = self.g[mask] - self.beta * gprime[mask] # finally, apply the object domain constraint # phs_gprime = np.angle(gprimeprime) # gprimeprime = self.absg * np.exp(1j*phs_gprime) self.costF.append(mseF) self.costf.append(msef) self.iter += 1 self.g = gprimeprime return gprimeprime
def step(self): """Advance the algorithm one iteration.""" G = fft.fft2(self.g) mse = _mean_square_error(abs(G), self.absF, self.mse_denom) phs_G = np.angle(G) Gprime = self.absF * np.exp(1j * phs_G) gprime = fft.ifft2(Gprime) # steepest descent is the same as GS until the time to form # g'' ... # g'' - g = -1/4 partial_g B = 1/2 (g' - g) # move g out of the LHS # -> g'' = 1/2 (g' - g) + g # if doublestep g'' = (g' - g) + g => g'' = g' if self.doublestep: gprimeprime = gprime else: gprimeprime = 0.5 * (gprime - self.g) + self.g # finally, apply the object domain constraint phs_gprime = np.angle(gprime) gprimeprime = self.absg * np.exp(1j * phs_gprime) self.costF.append(mse) self.iter += 1 self.g = gprimeprime return gprimeprime
def filter(): file = Image.open('fourierPeriodic.JPEG') image = np.asarray(file) per = Image.open('periodic.JPEG') imagep = np.asarray(per) selectedFilter = request.json['filter'] nx = int(request.json['nx']) ny = int(request.json['ny']) newImage = [] inv = [] f = fft.fftshift(fft.fft2(imagep)) imager, imagei = getMagAndPhase(f) if selectedFilter == 'band': newImage = saveArrayImage('band', np.asarray(bandReject(image, nx, ny))) inv = inverse(np.asarray(bandReject(imager, nx, ny)), imagei) elif selectedFilter == 'notch': newImage = saveArrayImage('notch', np.asarray(notchFilter(image, nx, ny))) inv = inverse(np.asarray(notchFilter(imager, nx, ny)), imagei) else: newImage = saveArrayImage('fourierPeriodic', image) inv = inverse(imager, imagei) invF = fft.ifft2(inv) newImageInv = saveArrayImage('inverse', np.abs(invF)) return jsonify({'img': newImage, 'inv': newImageInv})
def fft_forward_xy(phixy): """ Forward Fourier transform phi[y,x]->phi[ky,kx] Parameters ---------- phixy[2*nyw,2*nxw] : Numpy array, dtype=np.float64 phi[y,x] in real space Returns ------- phikxky[global_ny+1,2*nx+1] : Numpy array, dtype=np.complex128 phi[ky,kx] in wavenumber space """ import numpy as np from scipy import fft from diag_geom import nx, global_ny # 2次元フーリエ変換 phi[y,x] -> phi[ky,kx] phikxky_base = fft.fft2(phixy) / (phixy.shape[0] * phixy.shape[1] ) # フーリエ変換(次元はphixyと同一) phikxky = np.zeros( [global_ny + 1, 2 * nx + 1], dtype=np.complex128) # [global_nyy+1, 2*nx+1]サイズの要素を切り出す準備 phikxky[0:global_ny + 1, nx:2 * nx + 1] = phikxky_base[0:global_ny + 1, 0:nx + 1] # 第1象限の次元サイズ変換 phikxky[0:global_ny + 1, 0:nx] = phikxky_base[0:global_ny + 1, -nx:] # 第2象限の次元サイズ変換 return phikxky
def PhaseKai2opt(k2fa, fS1aTnoisy, OTFo): w = np.shape(fS1aTnoisy)[0] wo = np.int(w / 2) # Clean up for noise reduction. fS1aTnoisy = fS1aTnoisy * (1 - 1 * OTFo**10) fS1aT = fS1aTnoisy * np.conj(OTFo) Kotf = OTFedgeF(OTFo) # If the FFT is too large relative to the size of the array then this will rehouse it to a doubled array. if (2 * Kotf > wo): t = 2 * w fS1aT_temp = np.zeros((t, t),dtype=complex) fS1aT_temp[wo : w + wo, wo : w + wo] = fS1aT fS1aT = fS1aT_temp else: t = w to = np.int(t / 2) u = np.linspace(0, t - 1, t) v = np.linspace(0, t - 1, t) [U, V] = np.meshgrid(u, v) # Generates the line map in real space and multiplies it by the edited real image. # This thus amplifies the waveforms present. A better match = better resonance. S1aT = np.exp(-1j * 2 * np.pi * (k2fa[1] / t * (U - to)) + (k2fa[0] / t * (V - to))) * fft.ifft2(fS1aT) fS1aT0 = fft.fft2(S1aT) # Correlation values. mA = np.sum(fS1aT * np.conj(fS1aT0)) # This is the correlation value mA = mA / (np.sum(fS1aT0 * np.conj(fS1aT0))) # Normalise. CCop = -abs(mA) # Correlation value normalised and negativised so we can easily minimise. return(CCop)
def mfft2(a, overwrite_x = False): """Computes matrix fft2 on a matrix of shape (..., n,n,4,4). This is identical to np.fft2(a, axes = (-4,-3)) Parameters ---------- a : array_like Input array (must be complex). overwrite_x : bool Specifies whether original array can be destroyed (for inplace transform) Returns ------- out : complex ndarray Result of the transformation along the (-4,-3) axes. """ a = np.asarray(a, dtype = CDTYPE) libname = DTMMConfig["fftlib"] if libname == "mkl_fft": return mkl_fft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) elif libname == "scipy": return spfft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) elif libname == "numpy": return npfft.fft2(a, axes = (-4,-3)) elif libname == "pyfftw": return pyfftw.interfaces.scipy_fft.fft2(a, axes = (-4,-3), overwrite_x = overwrite_x) else: #default implementation is numpy return npfft.fft2(a, axes = (-4,-3))
def PhaseKai2opt(k2fa, fS1aTnoisy, OTFo): w = np.shape(fS1aTnoisy)[0] # The size of the image along one side wo = w / 2 # Not required fS1aTnoisy = fS1aTnoisy * ( 1 - 1 * OTFo ** 10) # FFT of the original image is muliplied by 1-the OTF^10 (why is this? variable seems to suggest denoising?) fS1aT = fS1aTnoisy * np.conj( OTFo) # The new image is multiplied byt the conj of the OTF to give the final image (what is the purpose of this?) # Is the above to not change the phase by multiplying the conjugate and the original by variable amounts? Kotf = OTFedgeF(OTFo) # Find the high-frequency envelope of the OTF; THIS IS NOT USED, WHY IS IT HERE? # The below section to S1aT is basically making a pattern as is defined in the functions outside. With a few added extras. t = w # Why redefine? to = t / 2 # ^^ # Build a 2D linear meshgrid u = np.linspace(0, t - 1, t) v = np.linspace(0, t - 1, t) [U, V] = np.meshgrid(u, v) # What is j? Can't find an equation like this in the paper and not sure what the variables are, so can't work out what this is doing # e ^ (-j* 2pi (k2fa[y]/width * (position_Y- halfwidth) + ktfa[x]/width * (position_X - halfwidth)) * inverse FFT of (FFT of the file multiplied by the conjugated base OTF) S1aT = np.exp(-1j * 2 * np.pi * (k2fa[1] / t * (U - to) + k2fa[0] / t * (V - to))) * fft.ifft2(fS1aT) fS1aT0 = fft.fft2(S1aT) mA = np.sum(fS1aT * np.conj(fS1aT0)) mA = mA / np.sum(fS1aT0 * np.conj(fS1aT0)) return (-1 * np.abs(mA)) # Specifically what does this mean in context and what are we aiming for it to be?
def Uzk(u0=None, z=50, lam=lam): A = fft2(U0) dx = np.diff(g)[0] kg = 2 * np.pi * fftfreq(n=len(g), d=dx) kx, ky = np.meshgrid(kg, kg) k = 1e6 * 2 * np.pi / lam return np.abs(ifft2(A * np.exp(-1j * z * np.sqrt(k**2 - kx**2 - ky**2))))
def fft_forward_xyz(phixyz): """ Forward Fourier transform phi[z,y,x]->phi[z,ky,kx] Parameters ---------- phixyz[:,2*nyw,2*nxw] : Numpy array, dtype=np.float64 phi[z,y,x] in real space Returns ------- phikxky[:,global_ny+1,2*nx+1] : Numpy array, dtype=np.complex128 phi[z,ky,kx] in wavenumber space and z """ import numpy as np from scipy import fft from diag_geom import nx, global_ny len_z = phixyz.shape[0] # 2次元フーリエ変換 phi[z,y,x] -> phi[z,ky,kx] phikxkyz_base = fft.fft2(phixyz, axes=(-2, -1)) / ( phixyz.shape[1] * phixyz.shape[2]) # フーリエ変換(次元はphixyと同一) phikxkyz = np.zeros( [len_z, global_ny + 1, 2 * nx + 1], dtype=np.complex128) # [:, global_nyy+1, 2*nx+1]サイズの要素を切り出す準備 phikxkyz[:, 0:global_ny + 1, nx:2 * nx + 1] = phikxkyz_base[:, 0:global_ny + 1, 0:nx + 1] # 第1象限の次元サイズ変換 phikxkyz[:, 0:global_ny + 1, 0:nx] = phikxkyz_base[:, 0:global_ny + 1, -nx:] # 第2象限の次元サイズ変換 return phikxkyz
def test_masked_registration_random_masks_non_equal_sizes(): """masked_register_translation should be able to register translations between images that are not the same size even with random masks.""" # See random number generator for reproducible results np.random.seed(23) reference_image = camera() shift = (-7, 12) shifted = np.real(fft.ifft2(fourier_shift( fft.fft2(reference_image), shift))) # Crop the shifted image shifted = shifted[64:-64, 64:-64] # Random masks with 75% of pixels being valid ref_mask = np.random.choice( [True, False], reference_image.shape, p=[3 / 4, 1 / 4]) shifted_mask = np.random.choice( [True, False], shifted.shape, p=[3 / 4, 1 / 4]) measured_shift = masked_register_translation( reference_image, shifted, reference_mask=np.ones_like(ref_mask), moving_mask=np.ones_like(shifted_mask)) assert_equal(measured_shift, -np.array(shift))
def fourier(): file = Image.open('original.JPEG') image = np.asarray(file) fourier = fft.fftshift(fft.fft2(image)) fourierReal, imag, real = convertToRealWithScale(fourier) newImage = saveArrayImage('fourier', fourierReal) return jsonify({'img': newImage})
def defocus(pupil, defocus_distance, r, wavelenght): ''' Takes the image and created the FT at some distance Parameters ---------- pupil : numpy ndarray The image of the aperture to transform defocus_distance : float The distance of the defocus in mm in range(-2.5,2.5) r : numpy ndarray The radial variable on the pupil wavelenght : float The center wavelength in mm Output ------ image : numpy ndarray The FT of the pupil at defocus_distance from the focus plane, AKA the PSF ''' log.info(hist()) phaseAngle = 1j*defocus_distance*10*np.sqrt((2*np.pi/wavelenght)**2-r**2+0j) #unnecessary 0j but keeping it for complex reasons kernel = np.exp(phaseAngle) defocusPupil = pupil * kernel defocusPSFA = fft.fftshift(fft.fft2(defocusPupil)) image = np.abs(defocusPSFA) return image
def mask(): click = request.json['click'] if click == 0: file = Image.open('fourierPeriodic.JPEG') fileOrg = Image.open('periodic.JPEG') elif click == 1: file = Image.open('mask.JPEG') fileOrg = Image.open('maskOrg.JPEG') width, height = file.size x = request.json['x'] y = request.json['y'] h = request.json['height'] w = request.json['width'] fx = math.floor(x / (w / width)) fy = math.floor(y / (h / height)) image = np.asarray(file) imageOrg = np.asarray(fileOrg) f = fft.fftshift(fft.fft2(imageOrg)) imager, imagei = getMagAndPhase(f) editedImage = image.copy() editedImage[fy, fx] = 0 editedImageOrg = imager.copy() editedImageOrg[fy, fx] = 0 editedImageFinal = saveArrayImage('mask', editedImage) inv = inverse(np.asarray(editedImageOrg), imagei) invF = fft.ifft2(inv) newImageInv = saveArrayImage('maskOrg', np.abs(invF)) return jsonify({'img': editedImageFinal, 'inv': newImageInv})
def Defocusor(imgSize, wavelenght, structure): #creates the defocused psf pupil = structure[0] #it use the data of the pupil KX = structure[1] KY = structure[2] dk = structure[3] defocusDistance = np.arange(-2.75, 0.1, 0.25) # Creates an arry of test distances defocusPSF = np.zeros( (imgSize, imgSize, defocusDistance.size)) #creates an array of defocused psf # Classic Integration through Fourier Transformation for ctr, z in enumerate( defocusDistance): #a control number and the actual distance phaseAngle = 1j * z * np.sqrt( (2 * np.pi / wavelength)**2 - KX**2 - KY**2 + 0j ) #unnecessary 0j but keeps it to make sure sqrt knows is a complex kernel = np.exp(phaseAngle) defocusPupil = pupil * kernel #bind the amplitude with the phase defocusPSFA = fft.fftshift( fft.fft2(defocusPupil)) * dk**2 #creates the psf defocusPSF[:, :, ctr] = np.abs( defocusPSFA) #adds the psf at the array of psfs vmax = np.max( defocusPSF[:, :, 10] ) #find the maximum in PSF (in focus) to scale the others (can be eliminated) return defocusDistance, defocusPSF, vmax
def step(self): """Advance the algorithm one iteration.""" G = fft.fft2(self.g) mse = _mean_square_error(abs(G), self.absF, self.mse_denom) Bk = mse phs_G = np.angle(G) Gprime = self.absF * np.exp(1j * phs_G) gprime = fft.ifft2(Gprime) # this is the update described in Fienup1982 Eq. 36 # if self.iter == 0: # D = gprime - self.g # else: # D = (gprime - self.g) + (Bk/self.Bkm1) * self.Dkm1 # gprimeprime = self.g + self.hk * D gprimeprime = gprime + self.hk * (gprime - self.gprimekm1) # finally, apply the object domain constraint phs_gprime = np.angle(gprimeprime) gprimeprime = self.absg * np.exp(1j * phs_gprime) self.costF.append(mse) self.iter += 1 self.Bkm1 = Bk # bkm1 = "B_{k-1}"; B for iter k-1 # self.Dkm1 = D self.gprimekm1 = gprime self.g = gprimeprime return gprimeprime
def PupilStructure(wavelength, NA, pixelSize, imgSize): # Working with FFT a new set of variables is created kMax = 2 * np.pi / pixelSize # Value of k at the maximum extent of the pupil function kNA = 2 * np.pi * NA / wavelength dk = 2 * np.pi / (imgSize * pixelSize) kx = np.arange((-kMax + dk) / 2, (kMax + dk) / 2, dk) ky = np.arange((-kMax + dk) / 2, (kMax + dk) / 2, dk) KX, KY = np.meshgrid(kx, ky) # Coordinate system for the pupil function maskRadius = kNA / dk # Radius of amplitude mask for defining the pupil maskCenter = np.floor(imgSize / 2) W, H = np.meshgrid(np.arange(0, imgSize), np.arange(0, imgSize)) mask = np.sqrt( (W - maskCenter)**2 + (H - maskCenter)**2) < maskRadius #create the figure of a circular dot plt.imshow(mask, extent=(kx.min(), kx.max(), ky.min(), ky.max())) plt.xlabel('kx') plt.ylabel('ky') plt.colorbar() plt.show() amp = np.ones((imgSize, imgSize)) * mask #creates the amplitude phase = 2j * np.pi * np.ones((imgSize, imgSize)) #creates the phase angle pupil = amp * np.exp( phase) #Bind the amplitude with the phase in order to obtain the pupil structure = [pupil, KX, KY, dk] #the structural parameter of the pupil psfA_Unaberrated = fft.fftshift( fft.fft2(pupil)) * dk**2 #the psf of the pipul psf = np.abs(psfA_Unaberrated) #the absolute value of the psf return psf, structure
def test_fit_modulation_frq(self): """ Test fit_modulation_frq() function :return: """ # set parameters options = {'pixel_size': 0.065, 'wavelength': 0.5, 'na': 1.3} fmax = 1 / (0.5 * options["wavelength"] / options["na"]) nx = 512 f = 1 / 0.25 angle = 30 * np.pi / 180 frqs = [f * np.cos(angle), f * np.sin(angle)] phi = 0.2377747474 # create sample image x = options['pixel_size'] * np.arange(nx) y = x xx, yy = np.meshgrid(x, y) m = 1 + 0.5 * np.cos(2 * np.pi * (frqs[0] * xx + frqs[1] * yy) + phi) mft = fft.fftshift(fft.fft2(fft.ifftshift(m))) frq_extracted, mask, = sim.fit_modulation_frq(mft, mft, options["pixel_size"], fmax, exclude_res=0.6) self.assertAlmostEqual(np.abs(frq_extracted[0]), np.abs(frqs[0]), places=5) self.assertAlmostEqual(np.abs(frq_extracted[1]), np.abs(frqs[1]), places=5)
def transform(self): """The main method of the class, performs the FFT of the current image""" self._data = fft.fft2( self._data ) # may also use real fft here, but it will only give a half of the image self._plotting = np.abs(self._data) return self