Files
fourierOptics/fourierOptics/profiles.py
T

120 lines
4.2 KiB
Python

# from .__init__ import __data_dir__
import numpy as np
import os
from astropy.io import fits
from scipy import interpolate
class Profiles:
def __init__(self):
pass
def top_hat(self, r, n, m, dpix, oversample=1, dx=0, dy=0):
j,i = np.mgrid[-n/2*dpix : n/2*dpix : 1j*n*oversample, -m/2*dpix : m/2*dpix : 1j*m*oversample]
dist_from_center = np.sqrt((i-dx)**2 + (j-dy)**2)
_Anew = (dist_from_center <= (r)).astype(int)
return _Anew
def obscured_top_hat(self, r1, r2, n, m, dpix, oversample=1):
'''
Creates a grid of n x m points, following a top hat function
where all points inside a radius r is 1 and 0 otherwise.
'''
assert r1 > r2, "r2 < r1, change input"
j,i = np.mgrid[-n/2*dpix : n/2*dpix : 1j*n*oversample, -m/2*dpix : m/2*dpix : 1j*m*oversample]
dist_from_center = np.sqrt(i**2 + j**2)
_Anew = (dist_from_center <= (r1)) & (dist_from_center >= (r2))
return _Anew.astype(int)
def spider_top_hat(self, r1, r2, n, m, dpix, oversample=1):
'''
Creates a grid of n x m points, following a top hat function
where all points inside a radius r is 1 and 0 otherwise.
'''
assert r1 > r2, "r2 < r1, change input"
j,i = np.mgrid[-n/2*dpix : n/2*dpix : 1j*n*oversample, -m/2*dpix : m/2*dpix : 1j*m*oversample]
n *= oversample
m *= oversample
dist_from_center = np.sqrt(i**2 + j**2)
_Anew = (dist_from_center <= (r1)) & (dist_from_center >= (r2))
_Aspider = (np.abs(i) < (0.05*r1)) | (np.abs(j) < (0.05*r1))
_Anew = _Anew & ~_Aspider
return _Anew
def gaussian(self, r, n, m, dpix, oversample=1, dx=0, dy=0):
'''
Creates a grid of n x m points, following a gaussian function
where the radius r is the FWHM of the gaussian shape.
'''
j,i = np.mgrid[-n/2*dpix : n/2*dpix : 1j*n*oversample, -m/2*dpix : m/2*dpix : 1j*m*oversample]
dist_from_center = np.sqrt((i-dx)**2 + (j-dy)**2)
return np.exp(-((j-dx)**2 + (i-dy)**2) / r**2)
def ELT_pupil(self, n, m, dpix):
# Find data directory
__pkg_dir__ = os.path.dirname(os.path.realpath(__file__))
__data_dir__ = os.path.join(__pkg_dir__, 'data')
_fits_image = __data_dir__ + '/ELT_M1_pupil_profile.fits'
_ELT_pupil = fits.open(_fits_image)[0].data
_ELT_inner_diam = 38542 # all glass diameter of M1 in mm
_dpix_fits = _ELT_inner_diam / 623 # pixels on the diameter filled with 'glass'
_resx, _resy = np.shape(_ELT_pupil)
_xf = np.linspace(-_resx/2*_dpix_fits, _resx/2*_dpix_fits, _resx)
_yf = np.linspace(-_resy/2*_dpix_fits, _resy/2*_dpix_fits, _resy)
_f_pupil = interpolate.interp2d(_xf, _yf, _ELT_pupil, kind='linear')
_x = np.linspace(-n/2*dpix, n/2*dpix, n)
_y = np.linspace(-m/2*dpix, m/2*dpix, m)
_ELT_pupil = _f_pupil(_x, _y)
return _ELT_pupil
def bahtinov_mask(self, r1, r2, n, m, dpix, N, oversample=1, half_width_spiders=None):
'''
Creates a Bahtinov mask profile.
This profile is a popular mask to focus a telescope in the
amateur community.
'''
assert r1 > r2, "r2 < r1, change input"
if half_width_spiders is None:
half_width_spiders = 0.03 * r1
# Obscured top hat
j,i = np.mgrid[-n/2*dpix : n/2*dpix : 1j*n*oversample, -m/2*dpix : m/2*dpix : 1j*m*oversample]
dist_from_center = np.sqrt(i**2 + j**2)
_Anew = (dist_from_center <= (r1)) & (dist_from_center >= (r2))
_Anew = _Anew.astype(int)
# Three quadrants of Bahtinov mask
_M1 = (i < -half_width_spiders)
_M2 = (i > half_width_spiders) & (j > half_width_spiders)
_M3 = (i > half_width_spiders) & (j < -half_width_spiders)
_MC = _M1 | _M2 | _M3
# Generating the lines
_d = 2 * r1 / int(N)
_M4 = step(j, i, period=_d, rotation=0)
_M5 = step(j, i, period=_d, rotation=30)
_M6 = step(j, i, period=_d, rotation=-30)
_MC = (_M1 & _M4) | (_M2 & _M5) | (_M3 & _M6)
# Combining with the obscured top hat
_Anew = _Anew * _MC
return _Anew.astype(int)
def step(x, y, period=1, rotation=0):
'''
Function that returns a 2D square wave with period and rotation.
'''
theta = np.deg2rad(rotation)
xn = x * np.cos(theta) - y * np.sin(theta)
yn = x * np.sin(theta) + y * np.cos(theta)
a = ((2/period * xn ).astype(int) % 2) & (xn>= 0)
b = ((2/period * xn - 1).astype(int) % 2) & (xn< 0)
return a + b