2020-10-26 18:01:39 +01:00
|
|
|
from .AGriddedPSF import AGriddedPSF
|
2020-05-29 09:36:02 +02:00
|
|
|
from ...lib.logger import logger
|
2020-04-29 17:08:03 +02:00
|
|
|
import numpy as np
|
2020-05-06 10:21:23 +02:00
|
|
|
import astropy.units as u
|
2020-04-29 17:08:03 +02:00
|
|
|
import re
|
|
|
|
|
|
|
|
|
2020-10-26 18:01:39 +01:00
|
|
|
class Zemax(AGriddedPSF):
|
2020-04-29 17:08:03 +02:00
|
|
|
"""
|
|
|
|
A class for modelling the PSF from a Zemax output file
|
|
|
|
"""
|
|
|
|
|
2020-05-06 10:21:23 +02:00
|
|
|
@u.quantity_input(wl="length", d_aperture="length", pixel_size="length")
|
|
|
|
def __init__(self, file: str, f_number: float, wl: u.Quantity, d_aperture: u.Quantity, osf: float,
|
|
|
|
pixel_size: u.Quantity):
|
2020-04-29 17:08:03 +02:00
|
|
|
"""
|
|
|
|
Initialize a new PSF from a Zemax file.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
file : str
|
|
|
|
Path to the Zemax-file. The origin of the coordinate system is in the lower left corner of the matrix
|
|
|
|
f_number : float
|
|
|
|
The working focal number of the optical system
|
|
|
|
wl : Quantity
|
|
|
|
The central wavelength which is used for calculating the PSF
|
|
|
|
d_aperture : Quantity
|
|
|
|
The diameter of the telescope's aperture.
|
2020-05-06 10:21:23 +02:00
|
|
|
osf : float
|
|
|
|
The oversampling factor to be used for oversampling the PSF with regards to the pixel size.
|
|
|
|
pixel_size : Quantity
|
|
|
|
The size of a pixel as length-quantity.
|
2020-04-29 17:08:03 +02:00
|
|
|
"""
|
|
|
|
# Read PSF from file
|
|
|
|
with open(file, encoding="utf16") as fp:
|
2020-10-26 18:01:39 +01:00
|
|
|
psf = np.genfromtxt((x.replace(",", ".") for x in fp), delimiter='\t', skip_header=21)
|
2020-04-29 17:08:03 +02:00
|
|
|
# Read header parameters from the file
|
|
|
|
with open(file, encoding="utf16") as fp:
|
|
|
|
head = [next(fp) for _ in range(21)]
|
|
|
|
# Parse shape of the grid and check the read PSF-array
|
|
|
|
shape = [int(x) for x in re.findall("[0-9]+", list(filter(re.compile("Image grid size: ").match, head))[0])]
|
2020-10-26 18:01:39 +01:00
|
|
|
if shape != list(psf.shape):
|
2020-05-29 09:36:02 +02:00
|
|
|
logger.warning("Not all PSF entries read.")
|
2020-04-29 17:08:03 +02:00
|
|
|
# Parse and calculate the grid width
|
|
|
|
grid_delta = [float(x.replace(",", ".")) for x in
|
2020-05-06 10:21:23 +02:00
|
|
|
re.findall("[0-9]+,*[0-9]*", list(filter(re.compile("Data area is ").match, head))[0])]
|
2020-04-29 17:08:03 +02:00
|
|
|
unit = re.findall(".+(?=\\.$)", re.sub("Data area is [0-9]+,*[0-9]* by [0-9]+,*[0-9]* ", "",
|
|
|
|
list(filter(re.compile("Data area is ").match, head))[0]))[0]
|
2020-10-26 18:01:39 +01:00
|
|
|
grid_delta = np.array(grid_delta) / np.array(shape) << u.Unit(unit)
|
2020-04-29 17:08:03 +02:00
|
|
|
# Parse the center point of the PSF in the grid
|
2020-10-26 18:01:39 +01:00
|
|
|
center_point = [int(x) for x in
|
|
|
|
re.findall("[0-9]+", list(filter(re.compile("Center point is: ").match, head))[0])]
|
|
|
|
center_point[0] = psf.shape[0] - center_point[0]
|
|
|
|
center_point[1] -= 1
|
2020-04-29 17:08:03 +02:00
|
|
|
|
2020-10-26 18:01:39 +01:00
|
|
|
super().__init__(psf, f_number, wl, d_aperture, osf, pixel_size, grid_delta, center_point)
|