ESBO-ETC/esbo_etc/classes/psf/Zemax.py

57 lines
2.6 KiB
Python

from .AGriddedPSF import AGriddedPSF
from ...lib.logger import logger
import numpy as np
import astropy.units as u
import re
class Zemax(AGriddedPSF):
"""
A class for modelling the PSF from a Zemax output file
"""
@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):
"""
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.
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.
"""
# Read PSF from file
with open(file, encoding="utf16") as fp:
psf = np.genfromtxt((x.replace(",", ".") for x in fp), delimiter='\t', skip_header=21)
# 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])]
if shape != list(psf.shape):
logger.warning("Not all PSF entries read.")
# Parse and calculate the grid width
grid_delta = [float(x.replace(",", ".")) for x in
re.findall("[0-9]+,*[0-9]*", list(filter(re.compile("Data area is ").match, head))[0])]
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]
grid_delta = np.array(grid_delta) / np.array(shape) << u.Unit(unit)
# Parse the center point of the PSF in the grid
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
super().__init__(psf, f_number, wl, d_aperture, osf, pixel_size, grid_delta, center_point)