iactrace.telescope¶
The Telescope class and helper modules for building optical systems.
Telescope Class¶
- class iactrace.telescope.Telescope[source]¶
Bases:
ModuleIACT telescope optical system as an Equinox Module.
The Telescope owns the full optical path including the camera frame (position and orientation of the detector plane). After ray tracing, rays are transformed into the camera frame so that the Camera class operates purely in its local coordinate system.
Optical elements (mirrors and lenses) are stored separately for clarity, but can be accessed together via the
optical_groupsproperty for unified ray tracing through mixed reflective/refractive systems.- __init__(mirror_groups, obstruction_groups=None, name='telescope', lens_groups=None, camera_position=None, camera_rotation=None)[source]¶
Initialize Telescope.
- Args:
mirror_groups: List of Mirror groups (reflective elements) obstruction_groups: List of Obstruction groups name: Telescope name lens_groups: List of Lens groups (refractive elements) camera_position: Camera origin in world coordinates (3,).
Defaults to [0, 0, 0].
- camera_rotation: Camera orientation as Euler angles in degrees (3,).
Defaults to [0, 0, 0].
- mirror_groups = <dataclasses._MISSING_TYPE object>¶
- lens_groups = <dataclasses._MISSING_TYPE object>¶
- obstruction_groups = <dataclasses._MISSING_TYPE object>¶
- name = <dataclasses._MISSING_TYPE object>¶
- camera_position = <dataclasses._MISSING_TYPE object>¶
- camera_rotation = <dataclasses._MISSING_TYPE object>¶
- property optical_groups¶
Return all optical groups (mirrors + lenses) combined.
- render(sources, values, source_type='point')[source]¶
Describe a render through the optics; do not execute yet.
Returns a
LazyRayBundlepackaging this telescope’s optics and camera frame with the given sources. Downstream camera methods (Camera.image(),Camera.response_matrix(),Camera.collect()) consume it directly: image and response_matrix fold per primary element so the full ray buffer is never materialised; collect materialises (per-ray output cannot be folded).- Args:
sources: Source positions
(N, 3)or directions(N, 3). values: Source strengths(N,). For'parallel'these areirradiances on the aperture; for
'point'they are radiant intensities, and the irradiance each primary sample sees isvalue / d^2for that sample’s distancedto the source.source_type:
'point'or'parallel'.
- trace(ray_origins, ray_directions, values, record_trajectory=False)[source]¶
Trace rays from arbitrary origins through the full optical system.
- Args:
ray_origins: Ray starting positions (N, 3) ray_directions: Ray directions (N, 3), should be normalized values: Ray intensities (N,) record_trajectory: When True, also record the per-stage ray path for
diagnostics / 3D visualization (see
iactrace.viz.show_telescope()). Off by default and free when off – nothing extra is computed. Mirrors thetrace_chain()option on the chain side.- Returns:
A
TraceResult, as every tracer returns. Itsraysare in the camera’s local coordinate system; pass them tocamera.collect()orcamera.image()for detection:rays = telescope.trace(origins, directions, values).rays rays, trajectory = telescope.trace(..., record_trajectory=True)
trajectoryisNoneunlessrecord_trajectorywas set, in which case theTrajectoryholds the source point, each optical stage’s landing point, and finally the converging leg’s landing on the camera reference plane –(n_stages + 2, N, 3), so the beam is seen coming to a focus.raysstops on the last optic (the sensor intersection happens downstream inCamera); the trajectory adds that last leg for display.The trajectory is in the world frame (the frame
iactrace.viz.show_telescope()draws the optics in), not the camera frameraysis reframed into.
- classmethod from_yaml(filename, n_samples=100, *, key)[source]¶
Load a telescope from a standalone telescope YAML file.
The telescope file describes only the optical system and the camera frame. Load the camera separately via
Camera.from_yaml().- Args:
filename: Path to telescope YAML file. n_samples: Number of Monte Carlo samples per mirror element. key: JAX random key for sampling and roughness.
- to_yaml(filename, precision=6, overwrite=True)[source]¶
Save the telescope configuration to a standalone YAML file.
- Args:
filename: Output file path. precision: Number of decimal places for float values. overwrite: If True, overwrite existing file.
- Returns:
Path to the saved file.
- stages_of_kind(kind)[source]¶
Sorted stages whose group has the given kind (‘mirror’, ‘lens’, ‘slab’).
- property n_stages¶
- property n_mirror_elements¶
- property n_lens_elements¶
Optical Element Composition¶
Mirrors and lenses are both represented as
OpticalElementGroup instances composed from a
surface, an aperture, an interaction, and an optional BSDF (see
iactrace.core). The helper submodules below provide builders that assemble
the right combination for common optical elements.
Mirror builders¶
- iactrace.telescope.mirrors.mirror_group(*, positions, rotations, curvatures, conics, aspherics, offsets, aperture, reflectivity=1.0, sample_key, coating=None, bsdf=None, optical_stage=0, n_samples=100)[source]¶
Canonical reflective
OpticalElementGroupbuilder.Takes pre-shaped per-element arrays plus a pre-built aperture and an optional
BSDFinstance, and assembles the surface + interaction + group wiring.- Args:
positions: Per-element vertex positions, shape
(N, 3). rotations: Per-element Euler angles in degrees, shape(N, 3). curvatures: Per-element curvatures1/R, shape(N,). conics: Per-element Schwarzschild conic constants, shape(N,). aspherics: Per-element even aspheric coefficients[A4, A6, ...],shape
(N, K); columnimultipliesr^(2i + 4).- offsets: Per-element surface decentering, shape
(N, 2). Use jnp.zeros((N, 2))for a centred disk.
aperture: Pre-built aperture. reflectivity: Per-element reflectivity in
[0, 1], shape(N,). sample_key: JAX PRNG key used for aperture sampling and BSDF. bsdf: OptionalBSDFinstance.Noneleaves the elementperfectly specular (the
OpticalElementGroupconstructor fills in a zero-scaleGaussianBSDF).- optical_stage: Stage index within the Telescope; each group in a
telescope must have a unique stage.
n_samples: Monte Carlo samples per element per render.
- offsets: Per-element surface decentering, shape
- Returns:
A ready-to-use
OpticalElementGroup.
- iactrace.telescope.mirrors.spherical(*, position, focal_length, radius, rotation=(0.0, 0.0, 0.0), inner_radius=0.0, reflectivity=1.0, coating=None, bsdf_scale=0.0, optical_stage=0, n_samples=100, key)[source]¶
Build a spherical mirror as a single-element group.
Uses
c = 1 / (2 * focal_length)withconic = 0. Setinner_radius > 0for an annular mirror.- Args:
position: Mirror vertex in world coordinates, shape (3,). focal_length: Paraxial focal length in metres (positive = concave). radius: Outer disk radius in metres. rotation: Euler angles in degrees. Defaults to no rotation. inner_radius: Inner hole radius in metres. Zero for a solid disk. reflectivity: Per-element reflectivity in
[0, 1]. bsdf_scale: Gaussian roughness sigma in arcseconds (0 disables). optical_stage: Stage index within the Telescope. n_samples: Monte Carlo samples per render call. key: JAX PRNG key.
- iactrace.telescope.mirrors.parabolic(*, position, focal_length, radius, rotation=(0.0, 0.0, 0.0), inner_radius=0.0, reflectivity=1.0, coating=None, bsdf_scale=0.0, optical_stage=0, n_samples=100, key)[source]¶
Build a parabolic mirror as a single-element group.
Uses
c = 1 / (2 * focal_length)andconic = -1, matching the referenceconfigs/BASIC/Cassegrain_telescope.yamlprimary (focal_length=0.4->curvature=1.25).Args: see
spherical().
- iactrace.telescope.mirrors.aspheric(*, position, curvature, radius, rotation=(0.0, 0.0, 0.0), conic=0.0, aspheric_coeffs=None, inner_radius=0.0, reflectivity=1.0, coating=None, bsdf_scale=0.0, optical_stage=0, n_samples=100, key)[source]¶
Build a general aspheric mirror as a single-element group.
Fully explicit version of
spherical()/parabolic(): you supply the curvature, conic constant, and optional even aspheric coefficients. Use this for hyperbolic / elliptic / higher-order aspheric mirrors.- Args:
position: Mirror vertex in world coordinates, shape (3,). curvature: Paraxial curvature
1/Rin m^-1. radius: Outer disk radius in metres. rotation: Euler angles in degrees. Defaults to no rotation. conic: Schwarzschild conic constant.0spherical,-1parabolic,
-1 < k < 0prolate ellipsoid,k < -1hyperboloid.- aspheric_coeffs: Even aspheric coefficients
[A4, A6, ...], i.e.
aspheric_coeffs[i]multipliesr^(2i + 4). The polynomial starts atr^4.- inner_radius, reflectivity, bsdf_scale, optical_stage, n_samples, key:
see
spherical().
- aspheric_coeffs: Even aspheric coefficients
- iactrace.telescope.mirrors.disk_array(*, positions, rotations, curvatures, radii, conics=None, aspheric_coeffs=None, inner_radii=None, reflectivities=None, coating=None, bsdf_scales=None, offsets=None, optical_stage=0, n_samples=100, key)[source]¶
Build a batched
N-element disk-aperture mirror group.Use this for segmented primary mirrors. Per-element arrays must all match length
N. Scalar defaults fill in where an argument is omitted. For anything beyond disk apertures / Gaussian BSDF, drop down tomirror_group().- Args:
positions: Per-element vertex positions, shape
(N, 3). rotations: Per-element Euler angles in degrees, shape(N, 3). curvatures: Per-element curvatures1/R, shape(N,). radii: Outer disk radii, shape(N,). conics: Per-element conic constants, shape(N,). Defaults tozeros (spherical).
- aspheric_coeffs: Per-element aspheric coefficients, shape
(N, K). Nonedisables aspherics.- inner_radii: Per-element central hole radii, shape
(N,). Defaults to zeros.
- reflectivities: Per-element reflectivities, shape
(N,). Defaults to ones.
- bsdf_scales: Per-element Gaussian BSDF roughness in arcseconds,
shape
(N,). Zero (the default) disables the BSDF.- offsets: Per-element surface decentering, shape
(N, 2). Defaults to zeros.
optical_stage: Stage index shared by all elements in this group. n_samples: Monte Carlo samples per element per render. key: JAX PRNG key for aperture sampling and BSDF.
- aspheric_coeffs: Per-element aspheric coefficients, shape
Lens builders¶
- iactrace.telescope.lenses.refractive_group(*, positions, rotations, curvatures, conics, aspherics, offsets, aperture, n_inside, transmittance=1.0, sample_key, coating=None, optical_stage=0, n_samples=100)[source]¶
Canonical builder for refractive
OpticalElementGroupinstances.Assembles an
AsphericSurfaceGroup+RefractInteraction+ group wiring from pre-shaped arrays. Use this for curved single-surface refracting lenses with any aperture type. Both the user-facing sugar helpers and the YAML adapter delegate to this function.- Args:
positions: Per-element vertex positions, shape
(N, 3). rotations: Per-element Euler angles in degrees, shape(N, 3). curvatures: Per-element curvatures1/R, shape(N,). conics: Per-element conic constants, shape(N,). aspherics: Per-element even aspheric coefficients[A4, A6, ...],shape
(N, K); columnimultipliesr^(2i + 4).offsets: Per-element surface decentering, shape
(N, 2). aperture: Pre-built aperture sized toN. n_inside: Per-element refractive index, shape(N,). The ambientindex on the incident side is not stored: the render loop reads it dynamically from each ray’s current medium (see
RefractInteraction).- transmittance: Per-element bulk transmittance in
[0, 1], shape (N,).
sample_key: JAX PRNG key for aperture sampling. optical_stage: Stage index within the Telescope. n_samples: Monte Carlo samples per element per render.
- transmittance: Per-element bulk transmittance in
- iactrace.telescope.lenses.slab_group(*, positions, rotations, aperture, n_inside, thickness, transmittance=1.0, sample_key, coating=None, optical_stage=0, n_samples=100)[source]¶
Canonical builder for parallel-sided slab (window) groups.
The surface is always zero curvature, conic, and aspheric, a slab is by definition flat, so no surface parameters are exposed. Both the user-facing
plano_slab()helper and the YAML adapter delegate to this function.- Args:
positions: Per-element front-surface positions, shape
(N, 3). rotations: Per-element Euler angles in degrees, shape(N, 3). aperture: Pre-built aperture sized toN. n_inside: Per-element slab refractive index, shape(N,). Theambient index is not stored: the render loop reads it dynamically from each ray’s current medium (see
SlabInteraction).thickness: Per-element slab thickness in metres, shape
(N,). transmittance: Per-element bulk transmittance in[0, 1], shape(N,).sample_key: JAX PRNG key for aperture sampling. optical_stage: Stage index within the Telescope. n_samples: Monte Carlo samples per element per render.
- iactrace.telescope.lenses.aspheric_lens(*, position, curvature, radius, rotation=(0.0, 0.0, 0.0), conic=0.0, aspheric_coeffs=None, n_inside=1.5, transmittance=1.0, coating=None, optical_stage=0, n_samples=100, key)[source]¶
Build a general aspheric-disk refracting lens as a single-element group.
Fully explicit version of
thin(): you supply the raw curvature, conic constant and optional aspheric coefficients. Use this for precisely-specified lens prescriptions.- Args:
position: Vertex position in world coordinates, shape (3,). curvature: Surface curvature
1/Rin m^-1. radius: Outer disk radius in metres. rotation: Euler angles in degrees. Defaults to no rotation. conic: Schwarzschild conic constant. aspheric_coeffs: Even aspheric coefficients[A4, A6, ...],i.e.
aspheric_coeffs[i]multipliesr^(2i + 4).- n_inside, transmittance, optical_stage, n_samples, key:
see
thin().
- iactrace.telescope.lenses.plano_slab(*, position, radius, thickness, rotation=(0.0, 0.0, 0.0), n_inside=1.5, transmittance=1.0, coating=None, optical_stage=0, n_samples=100, key)[source]¶
Build a flat parallel-sided window as a single-element group.
The surface is zero-curvature (flat) and rays pass through a
SlabInteractionthat handles entry refraction, propagation through the slab, and exit refraction. Useful for entrance windows and filters.- Args:
position: Vertex position of the front surface, shape (3,). radius: Outer disk radius in metres. thickness: Slab thickness in metres (along the optical axis). rotation: Euler angles in degrees. Defaults to no rotation. n_inside: Refractive index of the slab material. Defaults to 1.5. transmittance: Bulk transmittance in
[0, 1]. Defaults to 1.0. optical_stage: Stage index within the Telescope. n_samples: Monte Carlo samples per element per render. key: JAX PRNG key for aperture sampling.
Obstruction builders¶
- class iactrace.telescope.obstructions.ObstructionGroup[source]¶
Bases:
ModuleBase class for grouped obstructions.
Subclasses supply their intersection kernel and stacked parameters via
_primitive(); the two traversal strategies are shared from here.- intersect_batch(origins, directions)[source]¶
Nearest hit distance per ray, for
(n_rays, 3)rays.Same answer as
vmap(self.intersect), but chooses how to walk the primitives based on how many rays there are.
- __init__()¶
- class iactrace.telescope.obstructions.CylinderGroup[source]¶
Bases:
ObstructionGroupGroup of cylinders for efficient batched intersection.
- p1 = <dataclasses._MISSING_TYPE object>¶
- p2 = <dataclasses._MISSING_TYPE object>¶
- r = <dataclasses._MISSING_TYPE object>¶
- class iactrace.telescope.obstructions.OpenCylinderGroup[source]¶
Bases:
ObstructionGroupGroup of open cylinders (no end caps) for efficient batched intersection.
An open cylinder is a finite cylindrical surface without circular caps at the ends. Useful for modeling tubes, pipes, or hollow cylindrical structures where rays can pass through the ends.
- p1 = <dataclasses._MISSING_TYPE object>¶
- p2 = <dataclasses._MISSING_TYPE object>¶
- r = <dataclasses._MISSING_TYPE object>¶
- class iactrace.telescope.obstructions.BoxGroup[source]¶
Bases:
ObstructionGroupGroup of axis-aligned boxes for efficient batched intersection.
- p1 = <dataclasses._MISSING_TYPE object>¶
- p2 = <dataclasses._MISSING_TYPE object>¶
- class iactrace.telescope.obstructions.SphereGroup[source]¶
Bases:
ObstructionGroupGroup of spheres for efficient batched intersection.
- centers = <dataclasses._MISSING_TYPE object>¶
- radii = <dataclasses._MISSING_TYPE object>¶
- class iactrace.telescope.obstructions.OrientedBoxGroup[source]¶
Bases:
ObstructionGroupGroup of oriented boxes for efficient batched intersection.
- centers = <dataclasses._MISSING_TYPE object>¶
- half_extents = <dataclasses._MISSING_TYPE object>¶
- rotations = <dataclasses._MISSING_TYPE object>¶
- class iactrace.telescope.obstructions.TriangleGroup[source]¶
Bases:
ObstructionGroupGroup of triangles for efficient batched intersection.
- v0 = <dataclasses._MISSING_TYPE object>¶
- v1 = <dataclasses._MISSING_TYPE object>¶
- v2 = <dataclasses._MISSING_TYPE object>¶
- iactrace.telescope.obstructions.cylinder(*, p1, p2, r)[source]¶
Build a single closed cylinder as a
CylinderGroupof size one.- Args:
p1: One endpoint of the cylinder axis, shape (3,). p2: The other endpoint, shape (3,). r: Cylinder radius in metres.
- iactrace.telescope.obstructions.open_cylinder(*, p1, p2, r)[source]¶
Build a single open cylinder (no end caps) as a size-one group.
- Args:
p1: One endpoint of the cylinder axis, shape (3,). p2: The other endpoint, shape (3,). r: Cylinder radius in metres.
Operations¶
Functional operations for modifying telescope configurations (e.g., for calibration, error injection, optimization). All operations return new telescope instances.
- iactrace.telescope.operations.set_positions(telescope, stage, positions)[source]¶
Set element positions for the group at
stage.
- iactrace.telescope.operations.set_rotations(telescope, stage, rotations)[source]¶
Set element rotations (Euler XYZ degrees) for the group at
stage.
- iactrace.telescope.operations.apply_displacement(telescope, stage, sigma_z, key)[source]¶
Apply random Gaussian z-displacement to elements in the group at
stage.
- iactrace.telescope.operations.apply_misalignment(telescope, stage, sigma_h, sigma_v, key)[source]¶
Apply random Gaussian tip/tilt to element orientations.
sigma_h/sigma_vare in arcseconds.
- iactrace.telescope.operations.apply_roughness(telescope, stage, sigma)[source]¶
Apply Gaussian BSDF roughness (arcseconds RMS) to the group at
stage.
- iactrace.telescope.operations.set_curvatures(telescope, stage, curvatures)[source]¶
Set surface curvatures (1/R) for the group at
stage.
- iactrace.telescope.operations.set_conics(telescope, stage, conics)[source]¶
Set surface conic constants for the group at
stage.
- iactrace.telescope.operations.set_aspherics(telescope, stage, aspherics)[source]¶
Set surface aspheric coefficients for the group at
stage.
- iactrace.telescope.operations.scale_curvatures(telescope, stage, factor)[source]¶
Multiply curvatures by
factor(scalar or per-element).
- iactrace.telescope.operations.offset_curvatures(telescope, stage, offset)[source]¶
Add
offsetto curvatures (scalar or per-element).
- iactrace.telescope.operations.apply_conic_error(telescope, stage, sigma, key)[source]¶
Apply random Gaussian error to conic constants.
- iactrace.telescope.operations.apply_aspheric_error(telescope, stage, sigmas, key)[source]¶
Apply random Gaussian errors to aspheric coefficients.
- iactrace.telescope.operations.apply_zernike_error(telescope, stage, sigmas, key)[source]¶
Add random Gaussian Zernike figure error to the surface at
stage.Draws independent per-element coefficients for each Noll mode and composes them onto the stage’s surface: a bare aspheric mirror becomes an asphere + Zernike
SumSurfaceGroup, while a surface that already carries a Zernike term has the new draw added to it (matchingapply_conic_error()andapply_aspheric_error(), which accumulate noise rather than replace).The Noll terms are RMS-normalized, so
sigmasare RMS surface-error sigmas in metres.sigmas[m]scales Noll indexm + 1: index 0 is piston (removed by the surface re-zero), 1/2 tilt, 3 defocus, 4/5 astigmatism, 6/7 coma, 8/9 trefoil, 10 spherical. Only the first 11 Noll terms are available; a longersigmasraises.- Args:
stage: Optical stage to perturb. sigmas: Per-Noll-mode RMS sigmas in metres, shape
(J,)withJ <= 11.key: JAX PRNG key for the coefficient draw.
- iactrace.telescope.operations.apply_astigmatism(telescope, stage, sigma, key)[source]¶
Add random astigmatism (Noll Z5/Z6) of RMS
sigmametres per component.
- iactrace.telescope.operations.apply_coma(telescope, stage, sigma, key)[source]¶
Add random coma (Noll Z7/Z8) of RMS
sigmametres per component.
- iactrace.telescope.operations.apply_trefoil(telescope, stage, sigma, key)[source]¶
Add random trefoil (Noll Z9/Z10) of RMS
sigmametres per component.
- iactrace.telescope.operations.resample(telescope, stage, key)[source]¶
Refresh the Monte-Carlo sampling key on the group at
stage.
- iactrace.telescope.operations.set_reflectivity(telescope, stage, reflectivity)[source]¶
Set per-element mirror reflectivity. Mirror stages only.
- iactrace.telescope.operations.scale_reflectivity(telescope, stage, factor)[source]¶
Multiply mirror reflectivity by
factor. Mirror stages only.Scales the bulk multiplier
reflectivity_scalar; the coating on the interaction is left untouched.
- iactrace.telescope.operations.set_transmittance(telescope, stage, transmittance)[source]¶
Set per-element bulk transmittance. Lens or slab stages only.
Writes the bulk multiplier
transmittance_scalar; the coating on the interaction is left untouched.
- iactrace.telescope.operations.scale_transmittance(telescope, stage, factor)[source]¶
Multiply bulk transmittance by
factor. Lens or slab stages only.Scales the bulk multiplier
transmittance_scalar; the coating on the interaction is left untouched.
- iactrace.telescope.operations.set_refractive_index(telescope, stage, n_inside)[source]¶
Set per-element refractive index. Lens or slab stages only.
- iactrace.telescope.operations.set_thickness(telescope, stage, thickness)[source]¶
Set slab thickness in metres. Slab stages only.
- iactrace.telescope.operations.set_focal_lengths(telescope, stage, focal_lengths, n_outside=1.0)[source]¶
Set focal lengths via curvature.
Mirror stages:
c = 1 / (2 f). Lens stages (single refracting surface):c = 1 / ((n_inside - n_outside) f), wheren_outsideis a design-time ambient-index assumption (default1.0), not a value stored on the lens.
- iactrace.telescope.operations.apply_focal_error(telescope, stage, sigma, key, relative=False, n_outside=1.0)[source]¶
Perturb focal lengths by Gaussian noise; update curvatures accordingly.
Kind-aware: uses the mirror or single-refracting-lens formula. Slabs are rejected.
n_outsideis the design-time ambient index for the lens formula (default1.0); seeset_focal_lengths().
- iactrace.telescope.operations.add_obstruction(telescope, obstruction)[source]¶
Append an obstruction group.
- iactrace.telescope.operations.remove_obstruction(telescope, group_idx)[source]¶
Remove the obstruction group at
group_idx.