def calc_gradients(image, dx, dg, lambda0, peak, zT, downsample=3): """This function performs Fourier fringe analysis of the Talbot image, and downsamples the gradient by selecting an ROI around the Fourier peak Arguments: image -- Talbot image (NxM) dx -- pixel size in Talbot image (m) dg -- grating period (m) lambda0 -- wavelength (m) mag -- Talbot magnification (approximate) peak -- peak location in Fourier space for subtraction of linear phase zT -- Talbot distance, distance between grating and detector (m) downsample -- amount to downsample (power of 2) (default by factor of 8) Returns: h_grad -- downsampled gradient v_grad -- downsampled gradient zero_order -- downsampled zero order x1, y1 -- downsampled coordinates mid_peak -- average Fourier location of horizontal and vertical peaks p0 -- base second order coefficient """ # calculate second order coefficient corresponding to peak shift that will be applied # R2 is the distance from focus to detector corresponding to this peak R2 = zT / (1 - dg * peak) p0 = np.pi / lambda0 / R2 print(zT) mag = R2/(R2-zT) print('magnification: %.1f' % mag) # get image dimensions N, M = np.shape(image) # fourier transform start = time.time() fourier_plane = Beam.NFFT(image) end = time.time() print(end-start) #plt.figure() #plt.imshow(np.abs(fourier_plane)) # spatial frequencies fxmax = 1.0/(dx*2) dfx = 2.*fxmax/M fx = np.linspace(-M/2.,M/2.-1,M)*dfx dfy = 2.*fxmax/N fy = np.linspace(-N/2.,N/2.-1,N)*dfy fx, fy = np.meshgrid(fx,fy) # spatial frequency of grating (m^-1) fG = 1.0/dg # mask off first order peaks in fourier space v_mask = fx**2 + (fy-fG/mag)**2 < (fG/mag/4)**2 h_mask = (fx-fG/mag)**2 + fy**2 < (fG/mag/4)**2 # mask off zero order peak in Fourier space zero_mask = fx**2 + fy**2 < (fG/mag/4)**2 # multiply fourier plane by mask v_mask = fourier_plane*v_mask h_mask = fourier_plane*h_mask #plt.figure() #plt.imshow(np.abs(v_mask)) #plt.figure() #plt.imshow(np.abs(h_mask)) #plt.show() # multiply fourier plane by zero order mask zero_fourier = fourier_plane*zero_mask # find peak location for both horizontal and vertical # project along each dimension # thresholding of masked Fourier peaks to calculate peak location h_2 = beam_threshold(h_mask,.2) v_2 = beam_threshold(v_mask,.2) # set up coordinates (Talbot image plane) xp = np.linspace(-M/2,M/2-1,M) yp = np.linspace(-N/2,N/2-1,N) xp,yp = np.meshgrid(xp,yp) x1 = xp*dx y1 = yp*dx # find peaks in Fourier space h_peak = np.sum(h_2*fx)/np.sum(np.abs(h_2)) v_peak = np.sum(v_2*fy)/np.sum(np.abs(v_2)) h_mask = (fx-h_peak)**2 + fy**2<(fG/mag/4)**2 v_mask = fx**2 + (fy-v_peak)**2<(fG/mag/4)**2 h_mask = fourier_plane*h_mask v_mask = fourier_plane*v_mask # thresholding of masked Fourier peaks to calculate peak location h_2 = beam_threshold(h_mask,.2) v_2 = beam_threshold(v_mask,.2) # find peaks in Fourier space h_peak = np.sum(h_2*fx)/np.sum(np.abs(h_2)) v_peak = np.sum(v_2*fy)/np.sum(np.abs(v_2)) # find peak widths in Fourier space h_width = np.sqrt(np.sum(h_2*(fx-h_peak)**2)/np.sum(np.abs(h_2))) v_width = np.sqrt(np.sum(v_2*(fy-v_peak)**2)/np.sum(np.abs(v_2))) # calculate average position of horizontal/vertical peaks mid_peak = (v_peak+h_peak)/2. peak = mid_peak #R2x = zT / (1 - dg * h_peak) #p0x = np.pi / lambda0 / R2x #R2y = zT / (1 - dg * v_peak) #p0y = np.pi / lambda0 / R2y p0x = -np.pi/lambda0/zT * dg * h_peak p0y = -np.pi/lambda0/zT * dg * v_peak R2 = zT / (1 - dg * mid_peak) p0 = np.pi / lambda0 / R2 # define linear phase related to approximate peak location #h_grating = np.exp(-1j*2.*np.pi*h_peak*x1) #v_grating = np.exp(-1j*2.*np.pi*v_peak*y1) h_grating = np.exp(-1j*2.*np.pi*h_peak*x1) v_grating = np.exp(-1j*2.*np.pi*v_peak*y1) # Fourier transform back to real space, and multiply by linear phase h_grad = np.conj(Beam.INFFT(h_mask)*h_grating) v_grad = np.conj(Beam.INFFT(v_mask)*v_grating) # back to Fourier space, now peaks have been shifted to zero h_fourier = Beam.NFFT(h_grad) v_fourier = Beam.NFFT(v_grad) # crop out center of Fourier pattern to downsample down = (2**downsample)*2 v_fourier = v_fourier[N/2-N/down:N/2+N/down,M/2-M/down:M/2+M/down] h_fourier = h_fourier[N/2-N/down:N/2+N/down,M/2-M/down:M/2+M/down] zero_fourier = zero_fourier[N/2-N/down:N/2+N/down,M/2-M/down:M/2+M/down] # downsampled array size N2,M2 = np.shape(v_fourier) # downsampled image coordinates xp = np.linspace(-M2/2,M2/2-1,M2) yp = np.linspace(-N2/2,N2/2-1,N2) xp,yp = np.meshgrid(xp,yp) x1 = xp*dx*M/M2 y1 = yp*dx*N/N2 # back to real space, now downsampled h_grad = Beam.INFFT(h_fourier) v_grad = Beam.INFFT(v_fourier) # calculate zero order (downsampled) zero_order = np.abs(Beam.INFFT(zero_fourier)) params = {} params['zero_order'] = zero_order params['x1'] = x1 params['y1'] = y1 params['h_peak'] = h_peak params['v_peak'] = v_peak params['h_width'] = h_width params['v_width'] = v_width params['p0x'] = p0x params['p0y'] = p0y params['p0'] = p0 params['fourier'] = fourier_plane # output return h_grad, v_grad, params
def get_amplitude(image, dx, dg, mag): """This function performs Fourier fringe analysis of the Talbot image, and downsamples the gradient by selecting an ROI around the Fourier peak Arguments: image -- Talbot image (NxM) dx -- pixel size in Talbot image (m) dg -- grating period (m) lambda0 -- wavelength (m) mag -- Talbot magnification (approximate) peak -- peak location in Fourier space for subtraction of linear phase zT -- Talbot distance, distance between grating and detector (m) downsample -- amount to downsample (power of 2) (default by factor of 8) Returns: h_grad -- downsampled gradient v_grad -- downsampled gradient zero_order -- downsampled zero order x1, y1 -- downsampled coordinates mid_peak -- average Fourier location of horizontal and vertical peaks p0 -- base second order coefficient """ # get image dimensions N, M = np.shape(image) # fourier transform fourier_plane = Beam.NFFT(image) # spatial frequencies fxmax = 1.0 / (dx * 2) dfx = 2. * fxmax / M fx = np.linspace(-M / 2., M / 2. - 1, M) * dfx dfy = 2. * fxmax / N fy = np.linspace(-N / 2., N / 2. - 1, N) * dfy fx, fy = np.meshgrid(fx, fy) # spatial frequency of grating (m^-1) fG = 1.0 / dg # mask off first order peaks in fourier space v_mask = fx ** 2 + (fy - fG / mag) ** 2 < (fG / mag / 2) ** 2 h_mask = (fx - fG / mag) ** 2 + fy ** 2 < (fG / mag / 2) ** 2 # mask off zero order peak in Fourier space zero_mask = fx ** 2 + fy ** 2 < (fG / mag / 2) ** 2 # multiply fourier plane by mask v_mask = fourier_plane * v_mask h_mask = fourier_plane * h_mask # multiply fourier plane by zero order mask zero_fourier = fourier_plane * zero_mask # find peak location for both horizontal and vertical # project along each dimension # thresholding of masked Fourier peaks to calculate peak location h_2 = beam_threshold(h_mask, .2) v_2 = beam_threshold(v_mask, .2) # set up coordinates (Talbot image plane) xp = np.linspace(-M / 2, M / 2 - 1, M) yp = np.linspace(-N / 2, N / 2 - 1, N) xp, yp = np.meshgrid(xp, yp) x1 = xp * dx y1 = yp * dx # find peaks in Fourier space h_peak = np.sum(h_2 * fx) / np.sum(np.abs(h_2)) v_peak = np.sum(v_2 * fy) / np.sum(np.abs(v_2)) # calculate average position of horizontal/vertical peaks mid_peak = (v_peak + h_peak) / 2. # Fourier transform back to real space, and multiply by linear phase h_grad = np.conj(Beam.INFFT(h_mask)) v_grad = np.conj(Beam.INFFT(v_mask)) params = {} params['x1'] = x1 params['y1'] = y1 params['mid_peak'] = mid_peak zero_order = (np.abs(h_grad) + np.abs(v_grad)) / 2 # output return zero_order, params