def fpm_reconstruct_wrap(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. """ from skimage.measure import compare_ssim as ssim # Getting the maximum angle by the given configuration # Step 1: initial estimation # objectRecover = initialize(hrshape, cfg, 'zero') im_out = None objectRecover = np.ones(hrshape) lrsize = samples[(15, 15)].shape[0] xc, yc = fpmm.image_center(hrshape) 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; 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 im_cmp = Image.fromarray(samples[(15, 15)]) im_cmp = im_cmp.resize(hrshape) im_cmp = np.array(im_cmp) im_cmp = im_cmp.astype('float64') for iteration in range(20): objectRecoverFT = fftshift(fft2(objectRecover)) # shifted transform zfocus = (-.4E-6) xoff = -0.45+0.1*iteration yoff = -.1. pupil = pupil_wrap(zfocus, pupil_radius) print(xoff, yoff, zfocus*1E6) if im_out is not None: im_out /= np.amax(im_out) im_cmp /= np.amax(im_cmp) print('ssim %.2f' % ssim(im_cmp, im_out)) for iteration in range(5): iterator = ct.set_iterator(cfg) print('Iteration n. %d' % iteration) # Patching for testing for it in iterator: acqpars = it['acqpars'] indexes, kx_rel, ky_rel = ct.n_to_krels(it, cfg, xoff, yoff) 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 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 #################################################################### im_out = np.abs(ifft2(ifftshift(objectRecoverFT))) if debug: 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), im_out, im_cmp, np.angle(ifft2(ifftshift(objectRecoverFT)))]: 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)
import matplotlib.pyplot as plt import numpy as np import datetime import pyfpm.local as local import pyfpm.coordtrans as ct import pyfpm.fpmmath as fpmm import pyfpm.data as dt # Simulation parameters cfg = dt.load_config() out_file = dt.generate_out_file(fname='simtest.npy') iterator = ct.set_iterator(cfg) simclient = local.SimClient(cfg=cfg) imshape = simclient.im_array.shape xc, yc = fpmm.image_center(imshape) pupil_radius = simclient.pupil_radius kdsc = simclient.kdsc pup_list = list() fig, ax1 = plt.subplots(1, 1, figsize=(5, 5)) fig.show() image_dict = dict() for it in iterator: print(it['indexes']) [kx, ky] = ct.angles_to_k(it['theta'], it['phi'], kdsc) # print('theta: %.1f phi: %.1f' % (it['theta'], it['phi'])) pup_array = fpmm.pupil_image(yc + ky, yc + kx, pupil_radius, imshape) pup_list.append(pup_array) ax1.cla()
def fpm_reconstruct_classic(samples=None, it=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 # Getting the maximum angle by the given configuration # Step 1: initial estimation lrsize = fpmm.get_image_size(cfg) pupil_radius = fpmm.get_pupil_radius(cfg) ps = fpmm.get_pixel_size(cfg) wlen = fpmm.get_wavelength(cfg) hrshape = fpmm.get_reconstructed_shape(cfg) # k relative to absolute k factor npx = fpmm.get_image_size(cfg) ps_req = fpmm.get_pixel_size_required(cfg) wlen = fpmm.get_wavelength(cfg) led_gap = float(cfg.led_gap) height = float(cfg.sample_height) objectRecover_mag = (samples[(0, -1)]) / np.amax(samples[(0, -1)]) objectRecover_phase = (samples[(0, -1)] - samples[(-1, 0)]) / (samples[ (0, -1)] + samples[(-1, 0)]) objectRecover_phase = np.pi * ( objectRecover_phase) / np.amax(objectRecover_phase) objectRecover = objectRecover_mag * np.exp(1j * objectRecover_phase) objectRecover = np.ones(hrshape) # plt.imshow(objectRecover_phase) # plt.show() center = fpmm.image_center(hrshape) CTF = fpmm.generate_CTF(image_size=[lrsize, lrsize], pupil_radius=pupil_radius) * .1 # pupil = fpmm.aberrated_pupil(image_size=[lrsize, lrsize], pupil_radius=pupil_radius, # aberrations=[0,], pixel_size=ps, wavelength=wlen) objectRecoverFT = fftshift(fft2(objectRecover)) # shifted transform # Steps 2-5 factor = (lrsize / hrshape[0])**2 # For the convergence index # Steps 2-5 for iteration in range(10): iterator = ct.set_iterator(cfg) # print('Iteration n. %d' % iteration) for it in iterator: # indexes, kx_rel, ky_rel = ct.n_to_krels(it=it, cfg=cfg, xoff=0, yoff=0) indexes = it['indexes'] lr_sample = np.copy(samples[it['indexes']]) led_number = np.array([it['ny'], it['nx']]) # Convert indexes to pupil center coordinates kx, ky mc = np.array(cfg.mat_center) # Matrix center k_rel = np.sin(np.arctan((led_number - mc) * led_gap / height)) k_abs = k_rel * ps_req * npx / wlen pup_center = k_abs + center # Pupil borders lp = np.round(pup_center - (lrsize + 1) / 2).astype( int) # Extreme left low point hp = lp + lrsize # Extreme right high point pupil_square = [slice(lp[0], hp[0]), slice(lp[1], hp[1])] lowResFT = factor * objectRecoverFT[pupil_square] * CTF im_lowRes = ifft2(ifftshift(lowResFT)) im_lowRes = (1 / factor) * lr_sample * np.exp( 1j * np.angle(im_lowRes)) lowResFT = fftshift(fft2(im_lowRes)) * CTF objectRecoverFT[pupil_square] = ( 1 - CTF) * objectRecoverFT[pupil_square] + lowResFT im_out = ifft2(fftshift(objectRecoverFT)) return im_out
def fpm_reconstruct_wrappable(samples=None, it=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 lrsize = fpmm.get_image_size(cfg) pupil_radius = fpmm.get_pupil_radius(cfg) ps = fpmm.get_pixel_size(cfg) wlen = fpmm.get_wavelength(cfg) hrshape = fpmm.get_reconstructed_shape(cfg) kdsc = fpmm.get_k_discrete(cfg) objectRecover = np.ones(hrshape) xc, yc = fpmm.image_center(hrshape) CTF = fpmm.generate_CTF(0, 0, [lrsize, lrsize], pupil_radius) objectRecoverFT = fftshift(fft2(objectRecover)) # shifted transform # Steps 2-5 factor = (lrsize / hrshape[0])**2 # For the convergence index N = len(samples) for iteration in range(1): iterator = ct.set_iterator(cfg) # Patching for testing for it in iterator: # Coordinates manipulation acqpars = it['acqpars'] indexes, kx_rel, ky_rel = ct.n_to_krels(it=it, cfg=cfg, xoff=0, yoff=0) lr_sample = np.copy(samples[it['indexes']]) [kx, ky] = kdsc * kx_rel, kdsc * ky_rel # Iteration step kyl = int(np.round(yc + ky - (lrsize + 1) / 2)) kyh = kyl + lrsize kxl = int(np.round(xc + kx - (lrsize + 1) / 2)) kxh = kxl + lrsize lowResFT = factor * objectRecoverFT[kyl:kyh, kxl:kxh] * CTF # 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)) ## pupil correction update lowResFT2 = fftshift(fft2(im_lowRes)) * CTF * 1. / pupil ORFT = objectRecoverFT[kyl:kyh, kxl:kxh].ravel() objectRecoverFT[kyl:kyh, kxl:kxh] += (lowResFT2 - lowResFT) * np.conjugate( pupil) / np.max(np.abs(pupil.ravel())**2) pupil += (lowResFT2 - lowResFT) * np.conjugate( objectRecoverFT[kyl:kyh, kxl:kxh]) / np.max(np.abs(ORFT)**2) #################################################################### im_out = ifft2(ifftshift(objectRecoverFT)) return im_out
def fpm_reconstruct_epry(samples=None, it=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 lrsize = fpmm.get_image_size(cfg) pupil_radius = fpmm.get_pupil_radius(cfg) ps = fpmm.get_pixel_size(cfg) wlen = fpmm.get_wavelength(cfg) hrshape = fpmm.get_reconstructed_shape(cfg) kdsc = fpmm.get_k_discrete(cfg) objectRecover = np.ones(hrshape) xc, yc = fpmm.image_center(hrshape) CTF = fpmm.generate_CTF(0, 0, [lrsize, lrsize], 1. * pupil_radius) # print(lrsize,hrshape) # plt.imshow(CTF) # plt.show() # pupil = np.ones_like(CTF, dtype='complex') pupil = 1 # pupil = fpmm.aberrated_pupil(image_size=[lrsize, lrsize], pupil_radius=pupil_radius, aberrations=[-.1E-6,], pixel_size=ps, wavelength=wlen)*CTF # pupil = (rand(lrsize, lrsize)*(1+0*1j)+1)*0.5 # gfk = exp(1j*rand(hrshape[0], hrshape[1])*pi)*fpmm.generate_CTF(0, 0, [hrshape[0], hrshape[1]], pupil_radius*.1) # gfk = np.zeros(hrshape, dtype='complex') gfk = fftshift(fft2(objectRecover)) # gfk += rand(hrshape[0], hrshape[1])+1 # gfk[yc-lrsize//2:yc+lrsize//2, xc-lrsize//2:xc+lrsize//2] = 1+rand(lrsize, lrsize) # gfk[yc, xc] = 1 # Steps 2-5 factor = (float(lrsize) / hrshape[0])**2 # For convergence index e_gk = 0 gk_prev = np.zeros_like(gfk) gk = np.ones_like(gfk) * (1 + 1j) gpk_prev = np.zeros_like(gfk) gpk = np.ones_like(gfk) ek = 1 gm = 0 a = 1 b = 1 sum_lr = 0 for it in ct.set_iterator(cfg): indexes, kx_rel, ky_rel = ct.n_to_krels(it=it, cfg=cfg) sum_lr += np.sum(samples[it['indexes']]) for iteration in range(15): iterator = ct.set_iterator(cfg) print('Iteration n. %d' % iteration) # Patching for testing e_gk = np.sum((abs(gk) - abs(gk_prev))**2) / (np.sum(abs(gk)**2)) e_gpk = np.sum( (angle(gk) - angle(gk_prev))**2) / (np.sum(angle(gk)**2)) gk_prev = gk print('Iteration %d | gk error %.2e | gpk error %.4f | ek %.2e |' % (iteration, e_gk, e_gpk, ek)) # if (ek < 0.00001): # break ek = 0 gm = gm * e_gk for it in iterator: acqpars = it['acqpars'] indexes, kx_rel, ky_rel = ct.n_to_krels(it=it, cfg=cfg, xoff=0., yoff=0.) lr_sample = np.copy( np.sqrt(samples[it['indexes']][:lrsize, :lrsize])) # From generate_il # Calculating coordinates [kx, ky] = kdsc * kx_rel, kdsc * ky_rel # k_rel is sin(phi) # print(kdsc) kyl = int(np.round(yc + ky - (lrsize + 1) / 2)) kyh = kyl + lrsize kxl = int(np.round(xc + kx - (lrsize + 1) / 2)) kxh = kxl + lrsize delta_gfk1 = gfk[kyl:kyh, kxl:kxh] * pupil * CTF # print(kyl, kyh, kxl, kxh, yc+kx, yc+ky) # Step 2: lr of the estimated image using the known pupil delta_gk = ifft2(ifftshift(delta_gfk1)) gk_prime = 1 / factor * lr_sample * delta_gk / abs(delta_gk) delta_gfk2 = fftshift(fft2(gk_prime)) # update of the pupil and the fourier transform of the sample. delta_phi = delta_gfk2 - delta_gfk1 sampled_gfk = gfk[kyl:kyh, kxl:kxh] sampled_gfk += a * delta_phi * conj(CTF * pupil) / amax( abs(CTF * pupil))**2 if iteration > -1: pupil += b * delta_phi * conj(sampled_gfk) / amax( abs(sampled_gfk))**2 gfk[kyl:kyh, kxl:kxh] = sampled_gfk # test_img = delta_phi # plt.plot(abs(delta_phi[25,:])) # plt.show() ek += np.sum(abs(delta_gfk2 - delta_gfk1)**2) / sum_lr**2 gk = ifft2(fftshift(gfk)) # plt.imshow(np.log(abs(gfk))) # plt.show() return gk, pupil
def fpm_reconstruct(samples=None, it=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') lrsize = fpmm.get_image_size(cfg) pupil_radius = fpmm.get_pupil_radius(cfg) ps = fpmm.get_pixel_size(cfg) wlen = fpmm.get_wavelength(cfg) hrshape = fpmm.get_reconstructed_shape(cfg) kdsc = fpmm.get_k_discrete(cfg) # Initialization xc, yc = fpmm.image_center(hrshape) CTF = fpmm.generate_CTF(0, 0, [lrsize, lrsize], pupil_radius) # gk_prime = np.ones(hrshape)*exp(1j*rand(hrshape)*pi) # gfk = np.ones(hrshape)*exp(1j*rand(hrshape[0], hrshape[1])*pi) objectRecover = np.ones(hrshape) gfk = fftshift(fft2(objectRecover)) # shifted transform factor = (lrsize / hrshape[0])**2 # For the convergence index N = len(samples) beta = 0. gm = 0 # lrarray = np.zeros((lrsize, lrsize, N)) e_gk = 0 gk_prev = np.zeros_like(gfk) gk = np.ones_like(gfk) gpk_prev = np.zeros_like(gfk) gpk = np.ones_like(gfk) for iteration in range(5): iterator = ct.set_iterator(cfg) # Patching for testing e_gk = np.sum((abs(gk) - abs(gk_prev))**2) / (np.sum(abs(gk)**2)) e_gpk = np.sum( (angle(gk) - angle(gk_prev))**2) / (np.sum(angle(gk)**2)) gk_prev = gk print('Iteration %d | gk error %.4f' % (iteration, e_gk)) print(e_gpk) if (e_gk < 5E-5): break for it in iterator: gm = gm * e_gk CTF = fpmm.generate_CTF(0, 0, [lrsize, lrsize], pupil_radius) acqpars = it['acqpars'] # indexes, theta, phi = it['indexes'], it['theta'], it['phi'] indexes, kx_rel, ky_rel = ct.n_to_krels(it, cfg=cfg) lr_sample = np.copy(samples[it['indexes']][:lrsize, :lrsize]) # Calculating coordinates [ky, kx] = kdsc * ky_rel, kdsc * kx_rel kyl = int(np.round(yc + ky - (lrsize + 1) / 2)) kyh = kyl + lrsize kxl = int(np.round(xc + kx - (lrsize + 1) / 2)) kxh = kxl + lrsize # Fourier-space update delta_gfk = factor * gfk[kyl:kyh, kxl:kxh] * CTF # Step 2: lr of the estimated image using the known pupil delta_gk = ifft2(ifftshift(delta_gfk)) + gm * rand(lrsize, lrsize) # phase = arctan(real(delta_gk)/(imag(delta_gk)+0.)) phase = angle(delta_gk) gk_prime = lr_sample * exp(1j * phase) / factor delta_gfk = fftshift(fft2(gk_prime)) * CTF gfk[kyl:kyh, kxl:kxh] = (1 - CTF) * gfk[kyl:kyh, kxl:kxh] + delta_gfk gk = ifft2(fftshift(gfk)) return gk, gk