mirror of
https://github.com/yosata/fourierOptics.git
synced 2026-10-30 05:01:04 +00:00
215 lines
7.7 KiB
Python
215 lines
7.7 KiB
Python
import numpy as np
|
|
import sys
|
|
# sys.path.insert(0, '/Users/joost/Dropbox/Werk/PhD/Analyses/Python/Analytical/Fourier Optics')
|
|
# sys.path.insert(0, '/home/joost/Dropbox/Werk/PhD/Analyses/Python/Analytical/Fourier Optics')
|
|
sys.path.insert(0, '/Users/joost/Dropbox/Werk/PhD/Documents/Published/FourierOptics GitHub release/')
|
|
from fourierOptics import *
|
|
from pdb import set_trace
|
|
|
|
'''
|
|
Author: Joost van den Born, PhD student at University of Groningen
|
|
Contact: born@astro.rug.nl
|
|
Description: Script to generate the geometric distortions due to WFEs
|
|
off the ADC prisms. The distortions are produced by measuring
|
|
the offset of the PSF centroid with and without WFE as a
|
|
function of field position.
|
|
Script made for the SPIE manuscript.
|
|
'''
|
|
|
|
def plot_distortions():
|
|
# Coordinates without WFEs
|
|
xe = load_variable('../data/GD_IFP_obscured_PSF_xcentroid_expected_fs.pkl')
|
|
ye = load_variable('../data/GD_IFP_obscured_PSF_ycentroid_expected_fs.pkl')
|
|
|
|
# Coordinates with WFEs
|
|
xf = load_variable('../data/GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_fs.pkl')
|
|
yf = load_variable('../data/GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_fs.pkl')
|
|
|
|
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, l=1.49e-3)
|
|
|
|
n = xe.shape[0]
|
|
X = xe.flatten()
|
|
Y = ye.flatten()
|
|
dX = xf - xe
|
|
dY = yf - ye
|
|
dx = dX.flatten()
|
|
dy = dY.flatten()
|
|
|
|
# Magnitude of the distortions
|
|
R = np.sqrt(dx**2 + dy**2) * mcd.platescale * 1e6
|
|
|
|
# Dummy figure, used for the colorbar colors in the quiver plot
|
|
im = plt.imshow(np.reshape(R, (n,n)))
|
|
plt.close()
|
|
|
|
fig = plt.figure()
|
|
ax = fig.add_subplot()
|
|
for i in range(len(xe)):
|
|
ax.plot(xe[:,i], ye[:,i], 'k-', alpha=0.2, linewidth=.5)
|
|
ax.plot(xe[i,:], ye[i,:], 'k-', alpha=0.2, linewidth=.5)
|
|
ax.quiver(X,Y,dx,dy, angles='xy', edgecolor='k', facecolor='None', linewidth=.5, units='dots')
|
|
ax.quiver(X,Y,dx,dy,R, alpha=.5, units='dots')
|
|
ax.set_aspect('equal', adjustable='box')
|
|
ax.set_xlabel('x (mm)')
|
|
ax.set_ylabel('y (mm)')
|
|
fig.colorbar(im, ax=ax, label='PSF centroid shift ($\\mu$as)')
|
|
plt.savefig('../figures/UPDATED_GD_focal_plane_fs.pdf', bbox_inches='tight', transparent=True)
|
|
plt.savefig('../figures/UPDATED_GD_focal_plane_fs.png', bbox_inches='tight', transparent=True)
|
|
plt.tight_layout()
|
|
plt.show()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# plt.rc('text', usetex=True)
|
|
plt.rc('font', family='serif')
|
|
plt.rc('axes', labelsize='large')
|
|
|
|
|
|
# Setup of simulation
|
|
l = 1.49e-3
|
|
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50)
|
|
# mcd.plot_ray_trace()
|
|
|
|
# Get x3 and y3 (the coordinates to apply the ADC WFE to):
|
|
# The focal plane area is about 200x200 mm, so we apply the wavefront error to an area
|
|
# of 200x200 mm.
|
|
xfp, yfp = np.meshgrid(np.linspace(-150, 150, mcd.n), np.linspace(-150, 150, mcd.m))
|
|
# _, xfp, yfp = mcd.propagate(l=l,surface=1, zoom=False, show=False,
|
|
# print_progress=False)
|
|
|
|
# Generate a wavefront error for the intermediate focal plane.
|
|
print('\nSetting the wavefront errors...')
|
|
wfe_fp = WavefrontError(mcd.n,mcd.m)
|
|
wfe_rms = 15000e-6
|
|
#PSD Wavefront error
|
|
|
|
# Loading the phase generated using a Fourier Series
|
|
fs_array = load_variable('wfe_fp_phase_array_{}_{}.pkl'.format(mcd.n, mcd.m))
|
|
|
|
# Retrieving the coefficients for the Fourier series
|
|
np.random.seed(2183)
|
|
coeff = np.random.uniform(-1,1,(101,101))
|
|
wfe_fp.coefficients = coeff
|
|
fs_array = fourier_series(xfp, yfp, coeff, Px=30, Py=30, xs=10, ys=10)
|
|
|
|
# Setting the initial full window phase array to generate the full window surface height map.
|
|
wfe_fp.phase = fs_array
|
|
surface_map_fp = wfe_fp.generate_height_map(wfe_rms, 2, 1)
|
|
# plot_real_valued_results(surface_map_fp*1e6, xfp, yfp, logscale=False, fig_size=(8,6.4), grid=False, show=True,
|
|
# colormap='jet', labeltext='Surface height (nm)')
|
|
|
|
# save_variable('../data/MCD_IFP_wfe_object_PSD_50nm.pkl', wfe_fp)
|
|
# wfe_fp = load_variable('../data/MCD_IFP_wfe_object_PSD_50nm.pkl')
|
|
# surface_map_fp = wfe_fp.data
|
|
# plt.show()
|
|
|
|
|
|
Elist, Eplist = [], []
|
|
xlist, ylist = [], []
|
|
xplist, yplist = [], []
|
|
x_expected_list, y_expected_list = [], []
|
|
x_centroid_list, y_centroid_list = [], []
|
|
|
|
# Set field points
|
|
hxList, hyList = np.mgrid[-1:1:11j,-1:1:11j]-(1/300)
|
|
# hxList, hyList = np.mgrid[-.1/11:.1/11:11j,-.1/11:.1/11:11j]-(1/300) # Zoomed in to central area
|
|
hxList = hxList.flatten()
|
|
hyList = hyList.flatten()
|
|
# hxList, hyList = [0.0], [0.0]
|
|
|
|
# List of performed simulations
|
|
# Defined by PSD
|
|
## GD_IFP : -1:1
|
|
## GD_IFP_zoom : -1/11 :1/11
|
|
## GD_IFP_zoom2 : -.5/11:.5/11
|
|
## GD_IFP_zoom3 : -.1/11:.1/11
|
|
|
|
# Defined by zernikes
|
|
## GD_IFP_obscured_PSF_xcentroid_expected_zern : 50 nm rms 19 zernike modes : -1 : 1
|
|
## To do; check PSF shape at center field with zern wfe
|
|
## To do; check interpolated WFE at any zoomed in field point.
|
|
|
|
# Propagate through the field positions without any WFEs
|
|
for i in range(len(hxList)):
|
|
hx = hxList[i]
|
|
hy = hyList[i]
|
|
print('Data point: i={:.0f} of i_max={:.0f}'.format(i, len(hxList)))
|
|
print('hx: {} - hy: {}'.format(hx,hy) )
|
|
|
|
# Initializing MICADO paraxial model
|
|
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, entrance_pupil='obscured')
|
|
|
|
# Propagate through the MICADO system
|
|
E, x, y = mcd.propagate(l=l,surface=-1, zoom=False, show=False,
|
|
print_progress=False, hx=hx, hy=hy)
|
|
|
|
# Find approximation for the centroid and amplitude as a first
|
|
# guess for the Obscured Airy pattern fit.
|
|
amplitude_guess = np.max(np.abs(E))**2
|
|
xbc, ybc, _, _ = mcd.centroid_shift(method='Barycenter')
|
|
print('Barycenter guess: ', xbc, ybc)
|
|
|
|
# Do the Obscured Airy Pattern Fit for the unperturbed PSF
|
|
xe, ye, _, _ = mcd.centroid_shift(method='Obscured Airy', initialGuess=(amplitude_guess, xbc, ybc, 0.0, 0.03))
|
|
print('Airy result: ', xe, ye)
|
|
x_expected_list.append(xe)
|
|
y_expected_list.append(ye)
|
|
|
|
|
|
|
|
# Load in the WFEs and set them to the corresponding ADC surfaces
|
|
print('\nSetting the wavefront errors...')
|
|
# null_wfe = np.zeros((3001,3001))
|
|
mcd.ELT_FP.add_wavefront_error(surface_map_fp, xfp, yfp, wfe=wfe_fp)
|
|
|
|
|
|
# Propagate through the MICADO system
|
|
print('Propagating with Wavefront Errors applied...')
|
|
Ep, xp, yp = mcd.propagate(l=l,surface=-1, zoom=False, show=True,
|
|
print_progress=False, hx=hx, hy=hy)
|
|
|
|
|
|
# Do the Obscured Airy Pattern Fit for the perturbed PSF
|
|
xf, yf, _, _ = mcd.centroid_shift(method='Obscured Airy', initialGuess=(amplitude_guess, xe, ye, 0.0, 0.03))
|
|
|
|
# Resulting centroid shift due to the WFE
|
|
x_centroid_list.append(xf)
|
|
y_centroid_list.append(yf)
|
|
R = np.sqrt( (xf-xe)**2 + (yf-ye)**2 ) * mcd.platescale * 1e6
|
|
print('xf: {}, yf: {}, shift (uas): {}'.format(xf,yf, R))
|
|
|
|
data_tuple = (i, hx, hy, xe, ye, xf, yf)
|
|
data_name = 'gd_point_{:03d}_hx{}_hy{}.pkl'.format(i, hx, hy)
|
|
save_variable('../data/GD_IFP_intermediate_results/{}'.format(data_name), data_tuple)
|
|
|
|
# Clear the memory by emptying the large arrays
|
|
mcd = None
|
|
wfe = None
|
|
E, x, y = None, None, None
|
|
Ep, xp, yp = None, None, None
|
|
|
|
|
|
# Reshaping the arrays
|
|
shape = (int(np.sqrt(len(x_expected_list))), int(np.sqrt(len(x_expected_list))))
|
|
x_expected = np.asarray(x_expected_list).reshape(shape)
|
|
y_expected = np.asarray(y_expected_list).reshape(shape)#.T
|
|
|
|
# Saving the arrays
|
|
save_variable('../data/GD_IFP_obscured_PSF_xcentroid_expected_fs.pkl', x_expected)
|
|
save_variable('../data/GD_IFP_obscured_PSF_ycentroid_expected_fs.pkl', y_expected)
|
|
|
|
|
|
# Reshaping the arrays
|
|
shape = (int(np.sqrt(len(x_centroid_list))), int(np.sqrt(len(x_centroid_list))))
|
|
x_centroid = np.asarray(x_centroid_list).reshape(shape)
|
|
y_centroid = np.asarray(y_centroid_list).reshape(shape)
|
|
|
|
# Saving the arrays
|
|
save_variable('../data/GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_fs.pkl', x_centroid)
|
|
save_variable('../data/GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_fs.pkl', y_centroid)
|
|
|
|
plot_distortions()
|
|
|
|
|
|
|