Source code for optixstuff.primary
"""Primary mirror abstractions."""
import equinox as eqx
import jax.numpy as jnp
from equinox import AbstractVar
[docs]
class AbstractPrimary(eqx.Module):
"""Abstract interface for a primary aperture.
Any concrete implementation must provide the diameter and collecting
area of the primary mirror as scalar values in SI units. These are
consumed by exposure time calculators and simulation tools alike.
"""
diameter_m: AbstractVar[float]
"""Primary mirror diameter in metres."""
area_m2: AbstractVar[float]
"""Effective collecting area in square metres."""
[docs]
class SimplePrimary(AbstractPrimary):
"""A simple circular primary mirror with a central obscuration.
Args:
diameter_m: Primary mirror diameter in metres.
obscuration: Linear obscuration fraction (0 = no obscuration).
shape_factor: Fraction of unobscured area that is collecting
(accounts for struts, segment gaps, etc.). Default 1.0.
"""
_diameter_m: float
obscuration: float
shape_factor: float
def __init__(
self,
diameter_m: float,
obscuration: float = 0.0,
shape_factor: float = 1.0,
) -> None:
"""Create a simple circular primary mirror."""
self._diameter_m = diameter_m
self.obscuration = obscuration
self.shape_factor = shape_factor
@property
def diameter_m(self) -> float:
"""Primary mirror diameter in metres."""
return self._diameter_m
@property
def area_m2(self) -> float:
"""Effective collecting area in square metres."""
r = self._diameter_m / 2.0
gross_area = jnp.pi * r**2
return gross_area * (1.0 - self.obscuration**2) * self.shape_factor
[docs]
def __repr__(self) -> str:
"""One-line summary of diameter, obscuration, and effective area."""
return (
f"SimplePrimary(D={self._diameter_m:.3g} m, "
f"obs={self.obscuration:.3g}, "
f"shape_factor={self.shape_factor:.3g}, "
f"area={float(self.area_m2):.3g} m^2)"
)