In [ ]:
import batoid
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact
import ipywidgets as widgets
%matplotlib inline

In [ ]:
# Let's model my 12-inch f/5 Newtonian reflector.
# 12-inch is approx 0.3 m
# f/5 then means the focal length is 1.5 m
# Which then means the parabolic equation is:
# z = (x^2+y^2) / (4*1.5)

D = 0.3
fn = 5
f = D * fn  # focal-length
R = 2 * f
plate_scale = 1./f # radians / m

def makeTelescope(defocus=0.0): # defocus in mm
    telescope = batoid.CompoundOptic(
        items = [
            batoid.Mirror(
                batoid.Paraboloid(R),
                name="Mirror"
            ),
            batoid.Detector(
                batoid.Plane(),
                name="detector",
                coordSys=batoid.CoordSys().shiftGlobal([0,0,f+0.001*defocus])
            )
        ]
    )
    return telescope

In [ ]:
@interact(theta_x=widgets.FloatSlider(min=-1,max=1,step=0.01,value=0.1),
          theta_y=widgets.FloatSlider(min=-1,max=1,step=0.01,value=-0.3),
          focus=widgets.FloatSlider(min=-0.5, max=0.5, step=0.01,value=0.1))
def spot(theta_x, theta_y, focus):
    """Display a spot diagram for a Newtonian telescope.

    @param theta_x  Field angle in degrees
    @param theta_y  Field angle in degrees
    @param focus    Defocus distance in mm
    """
    telescope = makeTelescope(focus)
    rays = batoid.RayVector.asPolar(
        backDist=1.0, nrad=40, naz=160, wavelength=500e-9,
        theta_x=np.deg2rad(theta_x), theta_y=np.deg2rad(theta_y),
        outer=D/2
    )
    telescope.trace(rays)
    rays.trimVignetted()
    x, y = np.array(rays.x), np.array(rays.y)
    x -= np.mean(x)
    y -= np.mean(y)
    x *= plate_scale*206265
    y *= plate_scale*206265

    plt.figure(figsize=(4.5,4))
    plt.scatter(x, y, s=1, alpha=0.5)
    plt.xlim(-10, 10)
    plt.ylim(-10, 10)
    plt.title(r"$\theta_x = {:4.2f}\,,\theta_y = {:4.2f}\,, f={:4.2f}$".format(theta_x, theta_y, focus))
    plt.xlabel("arcseconds")
    plt.ylabel("arcseconds")

In [ ]: