Point-Spread Function#

This report computes the point-spread function of the ESIS optical system.

[1]:
import matplotlib.pyplot as plt
import astropy.visualization
import astropy.units as u
import named_arrays as na
import esis

Start by loading the proposed optical design

[2]:
instrument = esis.flights.f1.optics.design_single(num_distribution=0)
instrument.field.num = 5
# spectrograph.pupil.num = 21

Plot a schematic of the spectrograph design

[3]:
with astropy.visualization.quantity_support():
    fig, ax = plt.subplots(
        figsize=(8, 4),
        constrained_layout=True,
    )
    instrument.system.plot(
        ax=ax,
        # plot_rays=False,
        components=("z", "x"),
        color="black",
        # plot_rays_vignetted=True,
        kwargs_rays=dict(
            color="tab:blue",
            zorder=0,
        ),
    )
    ax.set_xlabel(f"$z$ ({ax.get_xlabel()})")
    ax.set_ylabel(f"$x$ ({ax.get_ylabel()})")
    # ax.set_aspect("equal")
WARNING: function 'sqrt' is not known to astropy's Quantity. Will run it anyway, hoping it will treat ndarray subclasses correctly. Please raise an issue at https://github.com/astropy/astropy/issues. [astropy.units.quantity]
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/site-packages/astropy/units/quantity.py:653: RuntimeWarning: divide by zero encountered in divide
  result = super().__array_ufunc__(function, method, *arrays, **kwargs)
../_images/reports_point-spread-function_5_1.png

Plot a spot diagram for the nominal wavelength

[4]:
field = instrument.field

rays = instrument.system.rayfunction_default.outputs
position = rays.position.to(u.um)
position_relative = position - position.mean(instrument.pupil.axes)

with astropy.visualization.quantity_support():
    fig, ax = na.plt.subplots(
        axis_rows=field.axis.y,
        axis_cols=field.axis.x,
        nrows=field.num,
        ncols=field.num,
        sharex=True,
        sharey=True,
        figsize=(7, 6),
        constrained_layout=True,
    )
    na.plt.scatter(
        position_relative.x,
        position_relative.y,
        ax=ax,
        s=5,
        where=rays.unvignetted,
    )

    ax_lower = ax[{field.axis.y: +0}]
    ax_upper = ax[{field.axis.y: ~0}]
    ax_left = ax[{field.axis.x: +0}]
    ax_right = ax[{field.axis.x: ~0}]

    na.plt.set_xlabel(f"$x$ ({position.x.unit:latex_inline})", ax=ax_lower)
    na.plt.set_ylabel(f"$y$ ({position.y.unit:latex_inline})", ax=ax_left)

    angle = instrument.system.rayfunction_default.inputs.field.to(u.arcsec)
    angle_x = angle.x.mean(set(angle.axes) - {field.axis.x,})
    angle_y = angle.y.mean(set(angle.axes) - {field.axis.y,})
    na.plt.text(
        x=0.5,
        y=1,
        s=angle_x.nominal.to_string_array(),
        ax=ax_upper,
        transform=na.plt.transAxes(ax_upper),
        ha="center",
        va="bottom",
    )
    na.plt.text(
        x=1.05,
        y=0.5,
        s=angle_y.nominal.to_string_array(),
        ax=ax_right,
        transform=na.plt.transAxes(ax_right),
        ha="left",
        va="center",
    )
../_images/reports_point-spread-function_7_0.png