def generate_il(im_array, f_ih, theta, phi, cfg): """ Returns the low resolution sampled image with added reconstructed phase in the according spectral position. More detailed explanation: Takes the high resolution spectrum, calculates a low resolution sample in the spectral area occupied by the sampled image (im_array) by cuting it with the pupil at the (theta, phi), takes just the phase information in this area and replaces its modulus with the acquired im_array. Why this is outside the main function? Because it is also used in the quality metric (to be reimpemented here). """ ps = fpmm.ps_required(cfg.phi[1], cfg.wavelength, cfg.na) image_size = np.shape(im_array) pupil = fpmm.generate_pupil(theta=theta, phi=phi, image_size=image_size, wavelength=cfg.wavelength, pixel_size=ps, na=cfg.na) pupil_shift = fftshift(pupil) # Step 2: lr of the estimated image using the known pupil f_il = ifft2(f_ih*pupil_shift) # space pupil * fourier image Phl = np.angle(f_il) # Step 3: spectral pupil area replacement Il = np.sqrt(im_array) * np.exp(1j*Phl) # Spacial update Iupdate = Il # Iupdate /= np.max(Iupdate) # Iupdate *= 150 return Iupdate
def dpc_init(samples=None, backgrounds=None, it=None, init_point=None, cfg=None, debug=False): """ Absolutely experimental reconstruction function. Virtually analog to fpm_reconstruct() to be used as a test sandbox. """ # pc = PlatformCoordinates(theta=0, phi=0, height=cfg.sample_height, cfg=cfg) xoff, yoff = init_point # Selection of the image patch ps_required = fpmm.ps_required(cfg.phi[1], cfg.wavelength, cfg.na) # mask = get_mask(samples, backgrounds, xoff, yoff, cfg) # Getting the maximum angle by the given configuration # Step 1: initial estimation Et = initialize(samples, backgrounds, xoff, yoff, cfg, 'zero') f_ih = fft2(Et) # unshifted transform, shift is later applied to the pupil if debug: fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(25, 15)) fig.show() # fig, axes = implot.init_plot(4) # Steps 2-5 for iteration in range(cfg.n_iter): iterator = ct.set_iterator(cfg) print('Iteration n. %d' % iteration) # Patching for testing for index, theta, shift in iterator: theta, phi = ct.corrected_coordinates(theta=theta, shift=shift, cfg=cfg) print(theta, phi) # Final step: squared inverse fft for visualization im_array = fpmm.crop_image(samples[(theta, shift)], cfg.patch_size, xoff, yoff) background = fpmm.crop_image(backgrounds[(theta, shift)], cfg.patch_size, xoff, yoff) im_array = image_correction(im_array, background, mode='background') im_array, resc_size = image_rescaling(im_array, cfg) Il = generate_il(im_array, f_ih, theta, phi, cfg) # print("Testing quality metric", quality_metric(image_dict, Il, cfg), phi) pupil = fpmm.generate_pupil(theta=theta, phi=phi, image_size=resc_size, wavelength=cfg.wavelength, pixel_size=ps_required, na=cfg.objective_na) pupil_shift = fftshift(pupil) f_il = fft2(Il) f_ih = f_il*pupil_shift + f_ih*(1 - pupil_shift) if debug and index % 1 == 0: fft_rec = np.log10(np.abs(f_ih)+1) fft_rec *= (255.0/fft_rec.max()) fft_rec = fftshift(fft_rec) # fft_rec = Image.fromarray(np.uint8(fft_rec*255), 'L') im_rec = ifft2(f_ih) # im_rec *= (255.0/im_rec.max()) im_rec_abs = np.abs(im_rec*np.conj(im_rec)) def plot_image(ax, image): ax.cla() ax.imshow(image, cmap=plt.get_cmap('hot')) ax = iter([ax1, ax2, ax3, ax4]) for image in [np.abs(fft_rec), im_rec, im_array, np.angle(im_rec)]: plot_image(ax.next(), image) fig.canvas.draw() # print("Testing quality metric", quality_metric(image_dict, Il, cfg, max_phi)) return np.abs(np.power(ifft2(f_ih), 2)), np.angle(ifft2(f_ih+1))
def pupil_wrap(zfocus, radius): CTF = fpmm.generate_pupil(0, 0, [lrsize, lrsize], pupil_radius) # focus test # dky = 2*np.pi/(float(cfg.ps_req)*hrshape[0]) kmax = np.pi/float(cfg.pixel_size) step = kmax/((lrsize-1)/2) kxm, kym = np.meshgrid(np.arange(-kmax,kmax+1,step), np.arange(-kmax,kmax+1, step)); k0 = 2*np.pi/float(cfg.wavelength) kzm = np.sqrt(k0**2-kxm**2-kym**2); pupil = np.exp(1j*zfocus*np.real(kzm))*np.exp(-np.abs(zfocus)*np.abs(np.imag(kzm))); return CTF*pupil;
def fpm_reconstruct(samples=None, hrshape=None, it=None, pupil_radius=None, kdsc=None, cfg=None, debug=False): """ FPM reconstructon using the alternating projections algorithm. Here the complete samples and (optional) background images are loaded and Then cropped according to the patch size set in the configuration tuple (cfg). Args: ----- samples: the acquired samples as a dictionary with angles as keys. backgrounds: the acquired background as a dictionary with angles as keys. They must be acquired right after or before taking the samples. it: iterator with additional sampling information for each sample. init_point: [xoff, yoff] center of the patch to be reconstructed. cfg: configuration (named tuple) debug: set it to 'True' if you want to see the reconstruction proccess (it slows down the reconstruction). Returns: -------- (ndarray) The reconstructed modulus and phase of the sampled image. """ # Getting the maximum angle by the given configuration # Step 1: initial estimation # objectRecover = initialize(hrshape, cfg, 'zero') objectRecover = np.ones(hrshape) lrsize = samples[(15, 15)].shape[0] xc, yc = fpmm.image_center(hrshape) print(lrsize, pupil_radius) CTF = fpmm.generate_pupil(0, 0, [lrsize, lrsize], pupil_radius) # focus test # dky = 2*np.pi/(float(cfg.ps_req)*hrshape[0]) kmax = np.pi/float(cfg.pixel_size) step = kmax/((lrsize-1)/2) kxm, kym = np.meshgrid(np.arange(-kmax,kmax+1,step), np.arange(-kmax,kmax+1, step)); z = -.35E-6 k0 = 2*np.pi/float(cfg.wavelength) kzm = np.sqrt(k0**2-kxm**2-kym**2); pupil = np.exp(1j*z*np.real(kzm))*np.exp(-np.abs(z)*np.abs(np.imag(kzm))); pupil = CTF*pupil; objectRecoverFT = fftshift(fft2(objectRecover)) # shifted transform if debug: fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(25, 15)) fig.show() # Steps 2-5 factor = (lrsize/hrshape[0])**2 for iteration in range(cfg.n_iter): iterator = ct.set_iterator(cfg) print('Iteration n. %d' % iteration) # Patching for testing for it in iterator: acqpars = it['acqpars'] # indexes, theta, phi = it['indexes'], it['theta'], it['phi'] indexes, kx_rel, ky_rel = ct.n_to_krels(it, cfg) print(indexes, kx_rel, ky_rel) if indexes[0] > 19 or indexes[0] < 11 or indexes[1] > 19 or indexes[1] < 11: continue lr_sample = samples[it['indexes']]/(acqpars[1]) # From generate_il # Calculating coordinates [kx, ky] = kdsc*kx_rel, kdsc*ky_rel # if kx > 80 or ky > 80: # continue # [kx, ky] = ct.angles_to_k(theta, phi, kdsc) # coords = np.array([np.sin(phi_rad)*np.cos(theta_rad), # np.sin(phi_rad)*np.sin(theta_rad)]) # [kx, ky] = coords*kdsc # f_ih_shift = fftshift(fft2(lr_sample)) kyl = int(np.round(yc+ky-(lrsize+1)/2)) kyh = kyl + lrsize kxl = int(np.round(xc+kx-(lrsize+1)/2)) kxh = kxl + lrsize # Il = generate_il(im_array, f_ih, theta, phi, cfg) lowResFT = factor * objectRecoverFT[kyl:kyh, kxl:kxh]*pupil # Step 2: lr of the estimated image using the known pupil im_lowRes = ifft2(ifftshift(lowResFT)) # space pupil * fourier image im_lowRes = 1/factor * lr_sample * np.exp(1j*np.angle(im_lowRes)) lowResFT = fftshift(fft2(im_lowRes))*pupil objectRecoverFT[kyl:kyh, kxl:kxh] = (1-pupil)*objectRecoverFT[kyl:kyh, kxl:kxh] + lowResFT # Step 3: spectral pupil area replacement #################################################################### # If debug mode is on if debug and indexes[0] % 5 == 0: im_out = ifft2(ifftshift(objectRecoverFT)) fft_rec = np.log10(np.abs(objectRecoverFT)) # fft_rec *= (255.0/fft_rec.max()) # Il = Image.fromarray(np.uint8(Il), 'L') # im_rec *= (255.0/im_rec.max()) def plot_image(ax, image, title): ax.cla() ax.imshow(image, cmap=plt.get_cmap('gray')) ax.set_title(title) axiter = iter([(ax1, 'Reconstructed FFT'), (ax2, 'Reconstructed magnitude'), (ax3, 'Acquired image'), (ax4, 'Reconstructed phase')]) for image in [np.abs(fft_rec), np.abs(im_out), lr_sample, np.angle(im_out)]: ax, title = next(axiter) plot_image(ax, image, title) fig.canvas.draw() # print("Testing quality metric", fpmm.quality_metric(samples, Il, cfg)) return np.abs(im_out), np.angle(im_out)
plt.show() if task is 'test_and_measure': image_dict = np.load(out_file) for index, theta, phi, power in iterator: if phi == 20 or phi == 40: im_array = image_dict[()][(theta, phi)] intensity = np.mean(im_array) print('int: %f, theta: %d, phi: %d' % (intensity, theta, phi)) ax = plt.gca() or plt ax.imshow(im_array, cmap=plt.get_cmap('gray')) ax.get_figure().canvas.draw() plt.show(block=False) if task is 'visualize': from pyfpm.plotsgui import plot_crossections img = client.load_image(cfg.input_mag) image = misc.imread(StringIO(img), 'gray') plot_crossections(image) if task is 'test': fig, ax = plt.subplots(1, 1, figsize=(25, 15)) fig.show() image = client.acquire(0, 0, 100) ax.cla() pupil = generate_pupil(0, 0, 100, 50, [640, 480]) im_ax = ax.imshow(image, cmap=plt.get_cmap('gray')) fig.canvas.draw() ax.format_coord = Formatter(im_ax) plt.show()
plt.grid(False) fig.show() theta, phi = [0, 5] sim_im_array = simclient.acquire(theta, phi, power=100) ps_req = fpm.pixel_size_required(cfg.phi[1], cfg.wavelength, cfg.objective_na) original_shape = np.shape(sim_im_array) scale_factor = cfg.pixel_size / ps_req processing_shape = np.array(original_shape) * scale_factor pupil_radius = fpm.calculate_pupil_radius(cfg.objective_na, processing_shape[0], cfg.pixel_size, cfg.wavelength) pupil = fpm.generate_pupil(theta=0, phi=0, image_size=processing_shape.astype(int), wavelength=cfg.wavelength, pixel_size=ps_req, na=cfg.objective_na) sim_im_array = fpm.resize_complex_image(sim_im_array, processing_shape) pupil_shift = fftshift(pupil) f_image = fft2(sim_im_array) f_cut = f_image * pupil_shift im_rec = np.power(np.abs(ifft2(f_cut)), 1) sim_im_array = fpm.resize_complex_image(sim_im_array, [150, 150]) im_rec = fpm.resize_complex_image(im_rec, [150, 150]) pupil = fpm.resize_complex_image(pupil, [150, 150]) f_image = fpm.resize_complex_image(f_image, [150, 150]) corr = signal.correlate2d(np.abs(fftshift(f_image)),