{ "cells": [ { "cell_type": "raw", "id": "0", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Design & Specifications\n", "=======================\n", "\n", "This report inspects the ESIS-II optical design and evaluates its performance.\n", "\n", "The ESIS-II optical design has been modified from the ESIS-I design to have higher resolution \n", "and different target wavelengths.\n", "The changes from ESIS-I are as follows:\n", "\n", "- The target wavelengths have changed to Ne VII 46.5 nm and Si XII 49.9 nm.\n", "- The primary mirror is moved back by 6 holes on the optical bench.\n", "- The gratings are moved forward by 2 holes on the optical bench.\n", "- The filter position and orientation has been adjusted to account for the shallower beam.\n", "\n", "To account for these changes, the angle, radius of curvature, and the\n", "ruling parameters of the grating need to be adjusted.\n", "This design used :func:`~scipy.optimize.differential_evolution` to\n", "compute these parameters." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import astropy.units as u\n", "import astropy.visualization\n", "import named_arrays as na\n", "import optika\n", "import esis" ] }, { "cell_type": "raw", "id": "2", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Start by loading a single channel of the optical design to investigate its performance." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "instrument = esis.flights.f2.optics.design_single(num_distribution=0)" ] }, { "cell_type": "raw", "id": "4", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Lower the number of field angles from the default to make the results easier to interpret." ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "instrument.field.num = 5" ] }, { "cell_type": "raw", "id": "6", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Plot the rays associated with this single channel." ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "with astropy.visualization.quantity_support():\n", " fig, ax = plt.subplots(\n", " figsize=(8, 4),\n", " constrained_layout=True,\n", " )\n", " instrument.system.plot(\n", " ax=ax,\n", " components=(\"z\", \"x\"),\n", " color=\"black\",\n", " kwargs_rays=dict(\n", " color=na.ScalarArray(\n", " ndarray=np.array([\"tab:blue\", \"tab:orange\"]),\n", " axes=\"wavelength\",\n", " ),\n", " label=instrument.wavelength.to_string_array(),\n", " zorder=-instrument.wavelength.value,\n", " ),\n", " )\n", " ax.set_xlabel(f\"$z$ ({ax.get_xlabel()})\")\n", " ax.set_ylabel(f\"$x$ ({ax.get_ylabel()})\")\n", "\n", " handles, labels = ax.get_legend_handles_labels()\n", " by_label = dict(zip(labels, handles))\n", " ax.legend(by_label.values(), by_label.keys())" ] }, { "cell_type": "raw", "id": "8", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Spot Diagram\n", "------------\n", "Plot the spot diagram associated with this channel to inspect the PSF of the system." ] }, { "cell_type": "code", "execution_count": null, "id": "9", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "instrument.system.spot_diagram();" ] }, { "cell_type": "raw", "id": "10", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Primary Footprint Diagram\n", "-------------------------\n", "Now, we would like to plot a diagram showing the footprint of the beam on the primary mirror.\n", "To do this, we will define a dense array of field points that goes almost to the edge of the FOV," ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "field = na.Cartesian2dVectorLinearSpace(\n", " start=-0.99,\n", " stop=+0.99,\n", " axis=na.Cartesian2dVectorArray(\"fx\", \"fy\"),\n", " num=11,\n", ")" ] }, { "cell_type": "raw", "id": "12", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "and a denser array of pupil points that also goes almost to the edge." ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "pupil=na.Cartesian2dVectorLinearSpace(\n", " start=-0.99,\n", " stop=+0.99,\n", " axis=na.Cartesian2dVectorArray(\"px\", \"py\"),\n", " num=41,\n", ")" ] }, { "cell_type": "raw", "id": "14", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Now, load the model of the full ESIS-II instrument, including all channels, with a much denser grid of rays." ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "instrument_full = esis.flights.f2.optics.design(\n", " grid=optika.vectors.ObjectVectorArray(\n", " wavelength=instrument.wavelength,\n", " field=field,\n", " pupil=pupil,\n", " ), \n", " num_distribution=0,\n", ")" ] }, { "cell_type": "raw", "id": "16", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "We will also rotate the instrument 22.5 degrees counter clockwise so that the borders of the primary are parallel to the vertical and horizontal." ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "instrument_full.roll = 22.5 * u.deg" ] }, { "cell_type": "raw", "id": "18", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Finally, we will rotate the primary mirror 180 degrees about the :math:`y` axis so that we view it from the front." ] }, { "cell_type": "code", "execution_count": null, "id": "19", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "transformation = na.transformations.Cartesian3dRotationY(180 * u.deg)" ] }, { "cell_type": "raw", "id": "20", "metadata": { "editable": true, "raw_mimetype": "text/x-rst", "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Now, we are ready to plot a footprint diagram of the beam on the primary mirror." ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "with astropy.visualization.quantity_support():\n", " fig, ax = plt.subplots(constrained_layout=True)\n", " instrument_full.schematic_primary(\n", " ax=ax,\n", " transformation=transformation,\n", " )\n", " ax.set_aspect(\"equal\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.3" } }, "nbformat": 4, "nbformat_minor": 5 }