Large update for finishing thesis

This commit is contained in:
yosata committed 2022-08-02 14:26:17 +02:00
1 parent 8e0575e0e9
commit 9ce4b7045f
25 files changed
+2316 -521

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,86 @@
import numpy as np
import matplotlib.pyplot as plt
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
@Date: 14 July, 2022
@Description: I use this script to create a large array (1001x1001 and 3001x3001)
that can be used for the phase screen in the WFE production.
Because it takes very long to generate these at this high resolution,
we will need to save them to a pickle file.
What is saved:
The array of coefficients
The array of the full phase field
To Do:
- Normalize/Scale the amplitude in an appropriate manner.
'''
if __name__ == '__main__':
# plt.rc('text', usetex=True)
# plt.rc('font', family='serif')
import time
# Setup of simulation
l = 1.49e-3
# mcd = ParaxialMICADO(n=1001, m=1001, dpix=160)
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50)
# mcd.plot_ray_trace()
wfe = WavefrontError(mcd.n, mcd.m)
# -------------------------------------------------------
####### GENERATING THE PHASE WITH A FOURIER SERIES ######
# -------------------------------------------------------
# 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))
# np.random.seed(2183)
# coeff = np.random.uniform(-1,1,(int(mcd.n/3),int(mcd.m/3)))
np.random.seed(2183)
coeff = np.random.uniform(-1,1,(101,101))
if False:
print('Going in...')
s1 = time.time()
fs_array = fourier_series(xfp, yfp, coeff, Px=300, Py=300, xs=150, ys=150)
s2 = time.time()
print('Finished!')
print('That took me {:.4f} s!'.format(s2-s1) )
save_variable('wfe_fp_phase_array_coefficients_{}_{}.pkl'.format(mcd.n, mcd.m), coeff)
save_variable('wfe_fp_phase_array_{}_{}.pkl'.format(mcd.n, mcd.m), fs_array)
# -------------------------------------------------------
# -------------------------------------------------------
# -------------------------------------------------------
if True:
# coeff = load_variable('wfe_fp_phase_array_coefficients_{}_{}.pkl'.format(mcd.n, mcd.m))
fs_array = load_variable('wfe_fp_phase_array_{}_{}.pkl'.format(mcd.n, mcd.m))
wfe.phase = fs_array
surf = wfe.generate_height_map(50e-6, 2, 1)
rms = np.sqrt(np.mean(surf**2))
print('RMS: {}'.format(rms))
plt.figure()
plt.imshow(fs_array, cmap='jet', extent=[xfp.min(), xfp.max(), yfp.min(), yfp.max()], origin='lower')
plt.colorbar()
plt.show()
plt.figure()
plt.imshow(surf, cmap='jet', extent=[xfp.min(), xfp.max(), yfp.min(), yfp.max()], origin='lower')
plt.colorbar()
plt.show()
@@ -16,14 +16,14 @@ from pdb import set_trace
Script made for the SPIE manuscript.
'''
def plot_distortions():
def plot_distortions(xe, ye, xf, yf):
# Coordinates without WFEs
xe = load_variable('../data/GD_IFP_obscured_PSF_xcentroid_expected_zern.pkl')
ye = load_variable('../data/GD_IFP_obscured_PSF_ycentroid_expected_zern.pkl')
# xe = load_variable('../data/GD_IFP_zoom93_obscured_PSF_xcentroid_expected_zern_psd.pkl')
# ye = load_variable('../data/GD_IFP_zoom93_obscured_PSF_ycentroid_expected_zern_psd.pkl')
# Coordinates with WFEs
xf = load_variable('../data/GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_zern.pkl')
yf = load_variable('../data/GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_zern.pkl')
# # Coordinates with WFEs
# xf = load_variable('../data/GD_IFP_zoom93_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
# yf = load_variable('../data/GD_IFP_zoom93_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, l=1.49e-3)
@@ -53,8 +53,8 @@ def plot_distortions():
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_zern.pdf', bbox_inches='tight', transparent=True)
plt.savefig('../figures/UPDATED_GD_focal_plane_zern.png', bbox_inches='tight', transparent=True)
# plt.savefig('../figures/UPDATED_GD_zoom93_focal_plane_zern.pdf', bbox_inches='tight', transparent=True)
# plt.savefig('../figures/UPDATED_GD_zoom93_focal_plane_zern.png', bbox_inches='tight', transparent=True)
plt.tight_layout()
plt.show()
@@ -62,11 +62,10 @@ def plot_distortions():
if __name__ == '__main__':
# plt.rc('text', usetex=True)
# plt.rc('font', family='serif')
# Setup of simulation
l = 1.49e-3
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50)
# mcd.plot_ray_trace()
print(mcd.platescale)
wfe = WavefrontError(mcd.n, mcd.m)
# Get x3 and y3 (the coordinates to apply the ADC WFE to):
@@ -80,34 +79,91 @@ if __name__ == '__main__':
print('\nSetting the wavefront errors...')
wfe_fp = WavefrontError(mcd.n,mcd.m)
wfe_rms = 50e-6
#PSD Wavefront error
# 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
# Zernike wavefront error
# We re0se the ADC_surface classes because it can be applicable to any surface, if used properly
ifp_wfe = ADC_surfaces(xfp, yfp, clearAperture=300)
ifp_wfe.generate_ADC_wfe(zernRMS=wfe_rms, psdRMS=0.)
mask = np.sqrt(ifp_wfe.xz**2 + ifp_wfe.yz**2) > 1
# Plot the wfe
# surf_ifp = ifp_wfe.latest_surface.copy()
# surf_ifp[mask]=np.nan
# surface_map_fp = surf_ifp
# wfe_fp.data = surf_ifp
wfe_fp = load_variable('../data/MCD_IFP_wfe_object_zern_50nm.pkl')
surface_map_fp = wfe_fp.data
# save_variable('../data/MCD_IFP_wfe_object_zern_50nm.pkl', wfe_fp)
psdWFE = True
zernikeWFE = False
if psdWFE:
#PSD Wavefront error
# 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')
wfe_fp = load_variable('../data/GD Focal Plane WFEs/MCD_IFP_wfe_object_PSD_50nm.pkl')
surface_map_fp = wfe_fp.data
# from copy import deepcopy
# xy_img = deepcopy((xfp, yfp))
# x, y = np.meshgrid(np.linspace(-10, 10, mcd.n), np.linspace(-10, 10, mcd.m))
# xy = deepcopy((x,y))
# zoom_map = wfe_fp.generate_height_map_window(
# xy, xy_img, ip_type='phase')
# plt.figure()
# plt.grid()
# plt.plot(1e3*x[1500,:], 1e6*zoom_map[1500,:], '-')
# # plt.imshow(1e6*zoom_map, cmap='jet', extent=[x.min(), x.max(), y.min(), y.max()],
# # origin='lower', vmin=-150, vmax=150)
# plt.xlabel('x (μm)')
# plt.ylabel('surface heigth (nm)')
# plt.show()
if zernikeWFE:
# Zernike wavefront error
# We reuse the ADC_surface classes because it can be applicable to any surface, if used properly
ifp_wfe = ADC_surfaces(xfp, yfp, clearAperture=300)
ifp_wfe.generate_ADC_wfe(zernRMS=wfe_rms, psdRMS=0.)
mask = np.sqrt(ifp_wfe.xz**2 + ifp_wfe.yz**2) > 1
# Plot the wfe
# surf_ifp = ifp_wfe.latest_surface.copy()
# surf_ifp[mask]=np.nan
# surface_map_fp = surf_ifp
# wfe_fp.data = surf_ifp
# wfe_fp = load_variable('../data/GD Focal Plane WFEs/MCD_IFP_wfe_object_zern_50nm.pkl')
surface_map_fp = wfe_fp.data
# save_variable('../data/MCD_IFP_wfe_object_zern_50nm.pkl', wfe_fp)
# figp1, axp1 = plot_real_valued_results(surface_map_fp*1e6, xfp, yfp,
# colormap='jet', labeltext='Surface height (nm)', fig_size=None, show=True)
plt.show()
# colormap='jet', labeltext='Surface height (nm)', fig_size=None, show=True)
# plt.show()
# plt.close()
# 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
## GD_IFP_zoom7 : -.02/11:.02/11, surface interpolation
## GD_IFP_zoom8 : -.05/11:.05/11, surface interpolation
## GD_IFP_zoom9 : -.01/11:.01/11, surface interpolation
## GD_IFP_zoom91 : -.01/11:.01/11 but hx and hy shifted to an area near the corner of the image, where distortion is supposed to be large
## GD_IFP_zoom92 : -.01/11:.01/11, phase interpolation
## GD_IFP_zoom93 : -.004/11:.004/11, phase interpolation
# (implemented)IDEA: Automate it, let it run all simulations for the lower left corner. Take multiples of 11 for the field points
# i.e. 1/11, 1/11**2, 1/11**3, 1/11**4
# GD_IFP_zoom94 : - 1/11:1/11, phase interpolation, with shift to left bottom corner
# GD_IFP_zoom95 : - 1/11**2:1/11**2, phase interpolation, with shift to left bottom corner
# GD_IFP_zoom96 : - 1/11**3:1/11**3, phase interpolation, with shift to left bottom corner
# GD_IFP_zoom97 : - 1/11:1/11, phase interpolation, center of the field
# GD_IFP_zoom98 : - 1/11**2:1/11**2, phase interpolation, center of the field
# GD_IFP_zoom99 : - 1/11**3:1/11**3, phase interpolation, center of the field
# GD_IFP_zoom100 : - 1/11**4:1/11**4, phase interpolation, center of the field
# GD_IFP_zoom101 : - 1/11**4:1/11**4, phase interpolation, center of the field, with shift to left bottom corner
# 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.
## GD_IFP_zoom4 : -.02/11:.02/11 (actually zernike WFE!), surface interpolation --> CONTINUOUS :D
## GD_IFP_zoom5 : -.05/11:.05/11 (actually zernike WFE!), surface interpolation --> CONTINUOUS :D
## GD_IFP_zoom6 : -.05/11:.05/11, surface interpolation, but hx and hy shifted to an area near the corner of the image (actually zern!)
Elist, Eplist = [], []
xlist, ylist = [], []
xplist, yplist = [], []
@@ -117,96 +173,99 @@ if __name__ == '__main__':
# 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, hyList = np.mgrid[-.004/11:.004/11:11j,-.004/11:.004/11:11j]-(1/300) # Zoomed in to central area
hxList = hxList.flatten()
hyList = hyList.flatten()
# 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
# Zooming in around -84mm by -84mm on the image plane
ihx = hxList[108]
ihy = hyList[108]
# 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.
for p in [4]:
x_expected_list, y_expected_list = [], []
x_centroid_list, y_centroid_list = [], []
# Propagate through the field positions without any WFEs
for i in range(len(hxList)):
hx = hxList[i]
hy = hyList[i]
print('hx: {} - hy: {}'.format(hx,hy) )
hxList, hyList = np.mgrid[ihx-1/11**p:ihx+1/11**p:11j,
ihy-1/11**p:ihy+1/11**p:11j]-(1/300)
hxList = hxList.flatten()
hyList = hyList.flatten()
# Initializing MICADO paraxial model
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, entrance_pupil='obscured')
# Propagate through the field positions without any WFEs
for i in range(len(hxList)):
print('Field point #: {}/{}'.format(i+1, len(hxList)))
hx = hxList[i]
hy = hyList[i]
print('hx: {} - hy: {}'.format(hx,hy) )
# 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)
# Initializing MICADO paraxial model
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, entrance_pupil='obscured')
# 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)
# 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)
# 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)
# 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=False,
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))
# Clear the memory by emptying the large arrays
mcd = None
wfe = None
E, x, y = None, None, None
Ep, xp, yp = None, None, None
# 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)
# 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
# Propagate through the MICADO system
print('Propagating with Wavefront Errors applied...')
Ep, xp, yp = mcd.propagate(l=l,surface=-1, zoom=False, show=False,
print_progress=False, hx=hx, hy=hy)
# Saving the arrays
save_variable('../data/GD_IFP_obscured_PSF_xcentroid_expected_zern.pkl', x_expected)
save_variable('../data/GD_IFP_obscured_PSF_ycentroid_expected_zern.pkl', y_expected)
# 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))
# 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_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_zern.pkl', x_centroid)
save_variable('../data/GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_zern.pkl', y_centroid)
# 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
plot_distortions()
# Saving the arrays
zoom_value = 97 + p
save_variable('../data/GD_IFP_zoom{:.0f}_obscured_PSF_xcentroid_expected_zern_psd.pkl'.format(zoom_value), x_expected)
save_variable('../data/GD_IFP_zoom{:.0f}_obscured_PSF_ycentroid_expected_zern_psd.pkl'.format(zoom_value), 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_zoom{:.0f}_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl'.format(zoom_value), x_centroid)
save_variable('../data/GD_IFP_zoom{:.0f}_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl'.format(zoom_value), y_centroid)
plot_distortions(x_expected, y_expected, x_centroid, y_centroid)
@@ -0,0 +1,214 @@
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()
@@ -91,9 +91,10 @@ def convert_detector_size(x, y, old=True):
def plot_distortions(xe, ye, xp, yp, lims=False, add_detectors=True,
save=False, figtitle='geom_distortions',
show=True, cmap='magma'):
vmin, vmax = 0.1, 100
vmin, vmax = 0.01, 100
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50, l=1.49e-3)
n = xe.shape[0]
no_of_grids = int(n/121)
X = xe.flatten()
Y = ye.flatten()
dX = xp - xe
@@ -103,7 +104,7 @@ def plot_distortions(xe, ye, xp, yp, lims=False, add_detectors=True,
# Magnitude of the distortions
R = np.sqrt(dx**2 + dy**2) * mcd.platescale * 1e6
print('RMS of the PSF shifts: {:.4f} μas.'.format(np.sqrt(np.mean((R)**2))))
print('RMS of the PSF shifts: {:.4f} μas.'.format(np.sqrt(np.mean((R[:121])**2))))
# Dummy figure, used for the colorbar colors in the quiver plot
# im = plt.imshow(np.reshape(R, (n,n)))
@@ -113,104 +114,160 @@ def plot_distortions(xe, ye, xp, yp, lims=False, add_detectors=True,
plt.close()
# Initiate the figure
# fig = plt.figure(figsize=(9.6,4.8))
# ax = fig.add_subplot(121, aspect='equal')
# ax2 = fig.add_subplot(122, aspect='equal')
fig, axes = plt.subplots(ncols=2,
nrows=1,
gridspec_kw={'width_ratios': [1,1]},
figsize=(9.6,4.8))
ax, ax2 = axes
ax.set_aspect('equal')
ax2.set_aspect('equal')
fig = plt.figure(figsize=(12,4.8))
gs = GridSpec(ncols=3, nrows=2, width_ratios=[2,1,1], height_ratios=[1,1])#left=0.05, right=0.48, wspace=0.05)
ax = fig.add_subplot(gs[:, :1])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[0, 2])
ax4 = fig.add_subplot(gs[1, 1])
ax5 = fig.add_subplot(gs[1, 2])
axilist = [ax, ax2, ax3, ax4, ax5]
for axi in axilist:
axi.set_aspect('equal')
# Add the detector layout if so desired.
if add_detectors:
add_detector_layout((fig,ax), lw=.8, alpha=1, show_label=False)
add_detector_layout((fig,ax), lw=1, alpha=1, show_label=False)
# Plot the vector plot
xe = np.asarray(xe[:121]).reshape((11,11))
ye = np.asarray(ye[:121]).reshape((11,11))
# 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,R, alpha=1, units='dots', zorder=300)
for k in range(4):
print()
# Now we iterate over the different iterations of the GD simulations
print('Total number of grids: {}'.format(no_of_grids))
for k in range(no_of_grids):
# Selecting the different iterations (11x11 grid, but flattened)
ind_end = (k+1) * 121
ind_start = k * 121
dpix = np.diff(Y)[ind_start:ind_end][1]
print(k, ind_start, ind_end, dpix)
# Coordinates of the grid in this iteration
xplot = np.asarray(X[ind_start:ind_end]).reshape((11,11))
yplot = np.asarray(Y[ind_start:ind_end]).reshape((11,11))
yplot, xplot = np.mgrid[yplot.min()+dpix/2:yplot.max()-dpix/2:12j,
xplot.min()+dpix/2:xplot.max()-dpix/2:12j]
# Magnitude of the distortion at coordinates xplot, yplot
# Used to color the background
Rtemp = np.asarray(R[ind_start:ind_end]).reshape((11,11))
ax.pcolor(-1*yplot.T, -1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
# ax2.pcolor(-1*xplot.T, -1*yplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=1, vmax=100))
shiftx = X[ind_start:ind_end][61]#np.abs(dpix)/2
shiftx = X[ind_start:ind_end][61]
shifty = Y[ind_start:ind_end][60]
print(Y[ind_start:ind_end])
print('shiftx:', shiftx)
print('shifty:', shifty)
# ax2.pcolor(k*shifty-1*yplot.T, k*shiftx-1*xplot.T, Rtemp.T*10, cmap=cmap, norm=LogNorm(vmin=1, vmax=100))
if k == 1: ax2.pcolor(shifty-1*yplot.T, shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
elif k == 2: ax2.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
elif k == 3: ax2.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
if k == 0:
if k in [0,1,2,3,7]: # Plot the center part pcolor
ax.pcolor(1*shifty-1*yplot.T, 1*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
# if k > 3: # Plot the zoom and megazoom
ax2.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
ax3.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
if k in [0,4,5,6,8]: # Plot the left bottom part pcolor
if k!=0:
ax.pcolor(yplot.T, xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
ax4.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
ax5.pcolor(2*shifty-1*yplot.T, 2*shiftx-1*xplot.T, Rtemp.T, cmap=cmap, norm=LogNorm(vmin=vmin, vmax=vmax))
# Quiver plots
# Full field plot
if k == 0:
ax.quiver(X[ind_start:ind_end],Y[ind_start:ind_end],
dx[ind_start:ind_end],dy[ind_start:ind_end],
angles='xy', edgecolor='k', facecolor='k',
linewidth=.8, zorder=300, alpha=1, scale=1.4e-5,
linewidth=.8, zorder=300, alpha=1, scale=1.2e-5,
units='dots')
elif k in [2,3]:
# Center plot zoom
if k in [0,1,2]:
ax2.quiver(X[ind_start:ind_end],Y[ind_start:ind_end],
dx[ind_start:ind_end],dy[ind_start:ind_end],
angles='xy', edgecolor='k', facecolor='k',
linewidth=.8, zorder=300, alpha=1, scale=0.2e-5,
linewidth=.8, zorder=300, alpha=1, scale=7e-7,
units='dots')
# ax.pcolor(xplot * (1 - dpix/105), yplot * (1 - dpix/105), Rtemp, cmap='jet', norm=LogNorm(vmin=1, vmax=100))
ax.set_xlabel('x (mm)', fontsize=16)
ax.set_ylabel('y (mm)', fontsize=16)
ax.tick_params(axis='both', direction='in', labelsize=14, zorder=-1,
top=True, right=True)
ax2.set_xlabel('x (mm)', fontsize=16)
ax2.set_ylabel('y (mm)', fontsize=16)
ax2.tick_params(axis='both', direction='in', labelsize=14, zorder=-1,
top=True, right=True)
# Center plot megazoom
elif k in [2,3,7]:
ax3.quiver(X[ind_start:ind_end],Y[ind_start:ind_end],
dx[ind_start:ind_end],dy[ind_start:ind_end],
angles='xy', edgecolor='k', facecolor='k',
linewidth=.8, zorder=300, alpha=1, scale=1e-6,
units='dots')
# Left bottom zoom
if k in [4,5]:
ax4.quiver(X[ind_start:ind_end],Y[ind_start:ind_end],
dx[ind_start:ind_end],dy[ind_start:ind_end],
angles='xy', edgecolor='k', facecolor='k',
linewidth=.8, zorder=300, alpha=1, scale=1.2e-5,
units='dots')
if k in [5,6,8]:
ax5.quiver(X[ind_start:ind_end],Y[ind_start:ind_end],
dx[ind_start:ind_end],dy[ind_start:ind_end],
angles='xy', edgecolor='k', facecolor='k',
linewidth=.8, zorder=300, alpha=1, scale=7e-6,
units='dots')
# Adjusting how the axes look in all subfigures
for axi in [ax, ax2, ax4]:
axi.set_ylabel('y (mm)', fontsize=16)
for axi in [ax, ax4, ax5]:
axi.set_xlabel('x (mm)', fontsize=16)
for axi in axilist:
axi.tick_params(axis='both', direction='in', labelsize=14, zorder=-1,
top=True, right=True)
cb = fig.colorbar(im, ax=axes, fraction=0.025, pad=0.04)
cb.set_label(label='PSF centroid shift (μas)', size=14)
cb.ax.tick_params(labelsize=14)
lbls = 10**np.asarray(cb.ax.get_yticks())
print(lbls)
newlbls = ['{:.0f}'.format(x) for x in 10**np.asarray(cb.ax.get_yticks())]
newlbls[1] = '{:.1f}'.format(lbls[1])
newlbls[0] = '{:.1f}'.format(lbls[0])
cb.ax.set_yticklabels(newlbls)
print(cb.ax.get_yticks())
# Setting some limits to the subplots
if not lims:
ax.set_xlim([-125, 115])
ax.set_ylim([-115, 115])
elif lims:
ax.set_xlim(lims[0])
ax.set_ylim(lims[1])
ax2.set_xlim([-2.01,2.75])
ax2.set_ylim([-2.01,2.75])
ax.indicate_inset_zoom(ax2, edgecolor="black")
ax2.set_xlim([-1+0.3513,1+0.3513])
ax2.set_ylim([-1+0.3513,1+0.3513])
ax3.set_xlim([-0.01+0.3513, 0.01+0.3513])
ax3.set_ylim([-0.01+0.3513, 0.01+0.3513])
# ax4.set_xlim([-2.01-84,2.75-84])
# ax4.set_ylim([-2.01-84,2.75-84])
ax4.set_xlim([-83.6-1,-83.6+1])
ax4.set_ylim([-83.6-1,-83.6+1])
ax5.set_xlim([-0.01-83.6070, 0.01-83.6070])
ax5.set_ylim([-0.01-83.6070, 0.01-83.6070])
# For the center inset
ax.indicate_inset_zoom(ax2, edgecolor='black')
ax2.indicate_inset_zoom(ax3, edgecolor='black')
# For the off-center inset
ax.indicate_inset_zoom(ax4, edgecolor='black')
ax4.indicate_inset_zoom(ax5, edgecolor='black')
# after plotting the data, format the labels
ax5.set_xticklabels(['{:.2f}'.format(x) for x in ax5.get_xticks()])
ax5.set_yticklabels(['{:.2f}'.format(x) for x in ax5.get_yticks()])
fig.subplots_adjust(top=1.0,
bottom=0.0,
left=0.1,
right=0.8,
hspace=0.135,
wspace=0.3)
bottom=0.08,
left=0.075,
right=0.88,
hspace=0.145,
wspace=0.45)
# Setting and modifying the colorbar
fig.subplots_adjust(right=0.88)
cbar_ax = fig.add_axes([0.9, 0.12, 0.02, 0.85])
cb = fig.colorbar(im, cax=cbar_ax)
cb.set_label(label='PSF centroid shift (μas)', size=14)
cb.ax.tick_params(labelsize=14)
lbls = 10**np.asarray(cb.ax.get_yticks())
newlbls = ['{:.0f}'.format(x) for x in 10**np.asarray(cb.ax.get_yticks())]
newlbls[3] = '{:.1f}'.format(lbls[3])
newlbls[2] = '{:.1f}'.format(lbls[2])
newlbls[1] = '{:.2f}'.format(lbls[1])
newlbls[0] = '{:.2f}'.format(lbls[0])
cb.ax.set_yticklabels(newlbls)
# plt.tight_layout()
if save:
plt.savefig('{}.pdf'.format(figtitle),
@@ -228,51 +285,127 @@ def plot_distortions(xe, ye, xp, yp, lims=False, add_detectors=True,
if __name__ == '__main__':
ps = ParaxialMICADO(n=3001, m=3001, dpix=50, l=1.49e-3).platescale
print(ps)
plt.rc('font', family='serif')
plt.rc('axes', labelsize='large')
# convert_detector_size()
# Plotting the original distortions
# Plotting the original distortions, -1/11 :1/11
data_dir = '../data/GD Focal Plane WFEs/'
xe_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 1:
xe_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# # Zoom 1: -1/11 :1/11
# xe_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_expected_zern_psd.pkl')
# ye_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_expected_zern_psd.pkl')
# xp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
# yp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 2
xe_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# # Zoom 2: -.5/11:.5/11
# xe_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_xcentroid_expected_zern_psd.pkl')
# ye_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_ycentroid_expected_zern_psd.pkl')
# xp_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
# yp_og2 = load_variable(data_dir + 'GD_IFP_zoom2_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 3
xe_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# # Zoom 3: -.1/11:.1/11
# xe_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_xcentroid_expected_zern_psd.pkl')
# ye_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_ycentroid_expected_zern_psd.pkl')
# xp_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
# yp_og3 = load_variable(data_dir + 'GD_IFP_zoom3_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
xe = np.append(xe_og, [xe_og1, xe_og2, xe_og3])
ye = np.append(ye_og, [ye_og1, ye_og2, ye_og3])
xp = np.append(xp_og, [xp_og1, xp_og2, xp_og3])
yp = np.append(yp_og, [yp_og1, yp_og2, yp_og3])
# Zoom 97: -1/11: 1/11
xe_og1 = load_variable(data_dir + 'GD_IFP_zoom97_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og1 = load_variable(data_dir + 'GD_IFP_zoom97_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og1 = load_variable(data_dir + 'GD_IFP_zoom97_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og1 = load_variable(data_dir + 'GD_IFP_zoom97_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# xe = np.append(xe_og2, xe_og3)
# ye = np.append(ye_og2, ye_og3)
# xp = np.append(xp_og2, xp_og3)
# yp = np.append(yp_og2, yp_og3)
# Zoom 98: -1/121 : 1/121
xe_og2 = load_variable(data_dir + 'GD_IFP_zoom98_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og2 = load_variable(data_dir + 'GD_IFP_zoom98_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og2 = load_variable(data_dir + 'GD_IFP_zoom98_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og2 = load_variable(data_dir + 'GD_IFP_zoom98_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 99: -1/11**3 : -1/11**3
xe_og3 = load_variable(data_dir + 'GD_IFP_zoom99_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og3 = load_variable(data_dir + 'GD_IFP_zoom99_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og3 = load_variable(data_dir + 'GD_IFP_zoom99_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og3 = load_variable(data_dir + 'GD_IFP_zoom99_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
figtitle = '../figures adapted for thesis/Focal Plane/GD_IFP_zern'
plot_distortions(xe, ye, xp, yp, show=True, save=True, figtitle=figtitle,
# Zoom7: -.01/11:.01/11
xe_og4 = load_variable(data_dir + 'GD_IFP_zoom92_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og4 = load_variable(data_dir + 'GD_IFP_zoom92_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og4 = load_variable(data_dir + 'GD_IFP_zoom92_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og4 = load_variable(data_dir + 'GD_IFP_zoom92_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom8: -.05/11:.05/11 - not plotted
# Zoom93: -.004/11:.004/11
xe_og5 = load_variable(data_dir + 'GD_IFP_zoom93_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og5 = load_variable(data_dir + 'GD_IFP_zoom93_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og5 = load_variable(data_dir + 'GD_IFP_zoom93_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og5 = load_variable(data_dir + 'GD_IFP_zoom93_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# # Zoom91: -.01/11:.01/11 but hx and hy shifted to an area near the corner of the image,
# # where distortion is supposed to be large
# xe_og6 = load_variable(data_dir + 'GD_IFP_zoom91_obscured_PSF_xcentroid_expected_zern_psd.pkl')
# ye_og6 = load_variable(data_dir + 'GD_IFP_zoom91_obscured_PSF_ycentroid_expected_zern_psd.pkl')
# xp_og6 = load_variable(data_dir + 'GD_IFP_zoom91_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
# yp_og6 = load_variable(data_dir + 'GD_IFP_zoom91_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom94: -1/11:1/11 but hx and hy shifted to an area near the corner of the image,
# where distortion is supposed to be large
xe_og6 = load_variable(data_dir + 'GD_IFP_zoom94_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og6 = load_variable(data_dir + 'GD_IFP_zoom94_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og6 = load_variable(data_dir + 'GD_IFP_zoom94_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og6 = load_variable(data_dir + 'GD_IFP_zoom94_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom95: -1/121:1/121 but hx and hy shifted to an area near the corner of the image,
# where distortion is supposed to be large
xe_og7 = load_variable(data_dir + 'GD_IFP_zoom95_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og7 = load_variable(data_dir + 'GD_IFP_zoom95_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og7 = load_variable(data_dir + 'GD_IFP_zoom95_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og7 = load_variable(data_dir + 'GD_IFP_zoom95_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom96: -1/11**3:1/11**3 but hx and hy shifted to an area near the corner of the image,
# where distortion is supposed to be large
xe_og8 = load_variable(data_dir + 'GD_IFP_zoom96_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og8 = load_variable(data_dir + 'GD_IFP_zoom96_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og8 = load_variable(data_dir + 'GD_IFP_zoom96_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og8 = load_variable(data_dir + 'GD_IFP_zoom96_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 100: - 1/11**4:1/11**4, phase interpolation, center of the field
xe_og9 = load_variable(data_dir + 'GD_IFP_zoom100_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og9 = load_variable(data_dir + 'GD_IFP_zoom100_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og9 = load_variable(data_dir + 'GD_IFP_zoom100_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og9 = load_variable(data_dir + 'GD_IFP_zoom100_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Zoom 101: - 1/11**4:1/11**4, phase interpolation, center of the field, with shift to left bottom corner
xe_og10 = load_variable(data_dir + 'GD_IFP_zoom101_obscured_PSF_xcentroid_expected_zern_psd.pkl')
ye_og10 = load_variable(data_dir + 'GD_IFP_zoom101_obscured_PSF_ycentroid_expected_zern_psd.pkl')
xp_og10 = load_variable(data_dir + 'GD_IFP_zoom101_obscured_PSF_xcentroid_found_with_wfe_airy_zern_psd.pkl')
yp_og10 = load_variable(data_dir + 'GD_IFP_zoom101_obscured_PSF_ycentroid_found_with_wfe_airy_zern_psd.pkl')
# Combining the data points
# xe = np.append(xe_og, [xe_og1, xe_og2, xe_og3, xe_og4, xe_og5, xe_og6, xe_og7, xe_og8])
# ye = np.append(ye_og, [ye_og1, ye_og2, ye_og3, ye_og4, ye_og5, ye_og6, ye_og7, ye_og8])
# xp = np.append(xp_og, [xp_og1, xp_og2, xp_og3, xp_og4, xp_og5, xp_og6, xp_og7, xp_og8])
# yp = np.append(yp_og, [yp_og1, yp_og2, yp_og3, yp_og4, yp_og5, yp_og6, yp_og7, yp_og8])
xe = np.append(xe_og, [xe_og1, xe_og2, xe_og3, xe_og6, xe_og7, xe_og8, xe_og9, xe_og10])
ye = np.append(ye_og, [ye_og1, ye_og2, ye_og3, ye_og6, ye_og7, ye_og8, ye_og9, ye_og10])
xp = np.append(xp_og, [xp_og1, xp_og2, xp_og3, xp_og6, xp_og7, xp_og8, xp_og9, xp_og10])
yp = np.append(yp_og, [yp_og1, yp_og2, yp_og3, yp_og6, yp_og7, yp_og8, yp_og9, yp_og10])
figtitle = '../figures adapted for thesis/Focal Plane/GD_IFP_psd'
plot_distortions(xe, ye, xp, yp, show=False, save=True, figtitle=figtitle,
lims=[[-120,120],[-120,120]])
plt.close()
@@ -199,7 +199,7 @@ def plot_distortions2(xe, ye, xp, yp, lims=False, add_detectors=True,
# ax.plot(xe[i,:], ye[i,:], 'k-', alpha=0.2, linewidth=.5)
# ax.quiver(X,Y,dx,dy,R, alpha=1, units='dots', zorder=300)
for k in range(1):
for k in range(3):
print()
ind_end = (k+1) * 121
ind_start = k * 121
@@ -300,30 +300,30 @@ if __name__ == '__main__':
# convert_detector_size()
# Plotting the original distortions
data_dir = '../data/GD Focal Plane WFEs/'
xe_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_expected_zern.pkl')
ye_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_expected_zern.pkl')
xp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_zern.pkl')
yp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_zern.pkl')
xe_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_expected_psd.pkl')
ye_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_expected_psd.pkl')
xp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_xcentroid_found_with_wfe_airy_psd.pkl')
yp_og = load_variable(data_dir + 'GD_IFP_obscured_PSF_ycentroid_found_with_wfe_airy_psd.pkl')
# # Zoom 1:
# xe_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_expected_zern.pkl')
# ye_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_expected_zern.pkl')
# xp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_found_with_wfe_airy_zern.pkl')
# yp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_found_with_wfe_airy_zern.pkl')
xe_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_expected_psd.pkl')
ye_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_expected_psd.pkl')
xp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_xcentroid_found_with_wfe_airy_psd.pkl')
yp_og1 = load_variable(data_dir + 'GD_IFP_zoom_obscured_PSF_ycentroid_found_with_wfe_airy_psd.pkl')
xe = xe_og#np.append(xe_og, xe_og1)
ye = ye_og#np.append(ye_og, ye_og1)
xp = xp_og#np.append(xp_og, xp_og1)
yp = yp_og#np.append(yp_og, yp_og1)
xe = np.append(xe_og, xe_og1)
ye = np.append(ye_og, ye_og1)
xp = np.append(xp_og, xp_og1)
yp = np.append(yp_og, yp_og1)
# xe = np.append(xe_og2, xe_og3)
# ye = np.append(ye_og2, ye_og3)
# xp = np.append(xp_og2, xp_og3)
# yp = np.append(yp_og2, yp_og3)
xe = np.append(xe_og2, xe_og3)
ye = np.append(ye_og2, ye_og3)
xp = np.append(xp_og2, xp_og3)
yp = np.append(yp_og2, yp_og3)
figtitle = '../figures adapted for thesis/Focal Plane/GD_IFP_zern'
plot_distortions(xe, ye, xp, yp, show=True, save=False, figtitle=figtitle,
figtitle = '../figures adapted for thesis/Focal Plane/GD_IFP_zern2'
plot_distortions2(xe, ye, xp, yp, show=True, save=False, figtitle=figtitle,
lims=[[-120,120],[-120,120]])
@@ -0,0 +1,86 @@
import numpy as np
import matplotlib.pyplot as plt
from numpy.polynomial import polynomial
import sys
sys.path.insert(0, '/Users/joost/Dropbox/Werk/PhD/Documents/Published/FourierOptics GitHub release/')
from fourierOptics import *
from pdb import set_trace
def polyfit2d(x, y, z, deg):
x = np.asarray(x)
y = np.asarray(y)
z = np.asarray(z)
deg = np.asarray(deg)
vander = polynomial.polyvander2d(x, y, deg)
vander = vander.reshape((-1,vander.shape[-1])) # Wat gebeurt hier? reshape(-1) lijkt niets te doen?
z = z.reshape((vander.shape[0],))
c = np.linalg.lstsq(vander, z, rcond=None)[0]
return c.reshape(deg+1)
if __name__ == '__main__':
plt.rc('text', usetex=True)
plt.rc('font', family='serif')
# Initializing MICADO paraxial model
mcd = ParaxialMICADO(n=3001, m=3001, dpix=50)
wfe = WavefrontError(mcd.n, mcd.m)
# Setup
l = 1.49e-3
# Set field points
hxList = [0]
hyList = [0]
wfe_p1 = load_variable('../data/compressed items/ADC_tWFE_p1_zern_20nm_psd_15nm.pkl')
wfe_p2 = load_variable('../data/compressed items/ADC_tWFE_p2_zern_20nm_psd_15nm.pkl')
wfe_p3 = load_variable('../data/compressed items/ADC_tWFE_p3_zern_20nm_psd_15nm.pkl')
wfe_p4 = load_variable('../data/compressed items/ADC_tWFE_p4_zern_20nm_psd_15nm.pkl')
# wfe_p1 = load_variable('../data/compressed items/ADC_tWFE_p1_psd_25nm.pkl')
# wfe_p2 = load_variable('../data/compressed items/ADC_tWFE_p2_psd_25nm.pkl')
# wfe_p3 = load_variable('../data/compressed items/ADC_tWFE_p3_psd_25nm.pkl')
# wfe_p4 = load_variable('../data/compressed items/ADC_tWFE_p4_psd_25nm.pkl')
prop_surf = 4
E, x, y = mcd.propagate(l=l,surface=prop_surf, zoom=False, show=False,
print_progress=True, hx=0, hy=0)
# Save the resulting 'perfect' PSF for later
tx_combined = 0
ty_combined = 0
print(mcd.ELT_ADC.p1.CA)
for wfe_surf in [wfe_p1, wfe_p2, wfe_p3, wfe_p4]:
# Don't show anything outside the clear aperture.
mask = np.sqrt(x**2 + y**2) > 40#mcd.ELT_ADC.p1.CA/2
# Plot P1
phasescreenMasked = wfe_surf.copy()
wfe_p1[mask] = np.nan
phasescreenMasked[mask] = 0
# Bepaling van de gemiddelde tilt voor deze coordinaten, i.e. een lineaire fit.
pf1 = polyfit2d(x.real[~mask], y.real[~mask], phasescreenMasked[~mask], [1,1])
# Coefficienten van de fit vertaalt naar graden tilt
o1x = np.arctan(pf1[1,0])
o1y = np.arctan(pf1[0,1])
print(o1x, o1y)
o1x_deg = np.degrees(o1x)
o1y_deg = np.degrees(o1y)
tx_combined += o1x
ty_combined += o1y
print('tx: {} rad ({} deg = {:.2f} arcsec)'.format(o1x, o1x_deg, o1x_deg*3600))
print('ty: {} rad ({} deg = {:.2f} arcsec)'.format(o1y, o1y_deg, o1y_deg*3600))
print('Combined results:\n-----------------')
print('tx: {} rad --> distortion of {} μas'.format(tx_combined, 1601.688*tx_combined*0.267*1e6))
print('ty: {} rad --> distortion of {} μas'.format(ty_combined, 1601.688*ty_combined*0.267*1e6))
tr_combined = np.sqrt(tx_combined**2 + ty_combined**2)
print('tr: {} rad --> distortion of {} μas'.format(tr_combined, 1601.688*tr_combined*0.267*1e6))
Binary file not shown.
Binary file not shown.