iactrace.core¶
Low-level ray tracing components. Most users should use the
Telescope class instead of these functions
directly.
Rendering Functions¶
High-level functions for rendering images through a telescope:
- iactrace.core.render(tel, sources, values, source_type, sensor_idx=0)[source]¶
Render sources through telescope onto sensor group.
Supports mixed reflective/refractive optical systems. Stage 0 can be mirrors, lenses, or slabs. Stages 1+ can be any interaction type.
- Args:
tel: Telescope object sources: Source positions (n_sources, 3) for ‘point’ or directions for ‘parallel’ values: Source intensities (n_sources,) source_type: ‘point’ or ‘parallel’ sensor_idx: Index of sensor group to use
- Returns:
Accumulated image with shape (n_sensors, *per_sensor_shape). For square sensors: (n_sensors, height, width) For hexagonal sensors: (n_sensors, n_pixels)
- iactrace.core.render_debug(tel, sources, values, source_type, sensor_idx=0)[source]¶
Render without accumulation - returns raw hits.
Supports mixed reflective/refractive optical systems.
- Args:
tel: Telescope object sources: Source positions (n_sources, 3) for ‘point’ or directions for ‘parallel’ values: Source intensities (n_sources,) source_type: ‘point’ or ‘parallel’ sensor_idx: Index of sensor group to use
- Returns:
- Tuple of (points, sensor_idx, values) arrays with all ray intersections:
points: (n_rays, 2) sensor coordinates for each ray
sensor_idx: (n_rays,) index of sensor each ray hit
values: (n_rays,) final intensity values (0 if ray missed)
- iactrace.core.render_response_matrix(tel, sources, values, source_type, sensor_idx=0)[source]¶
Render multiple sources and return the source-to-pixel response matrix.
This function traces N sources through the telescope and returns an N×M matrix where each row contains one source’s contribution to all M pixels across all sensors. Uses incremental accumulation for memory efficiency.
Supports mixed reflective/refractive optical systems.
- Args:
tel: Telescope object sources: Source positions (n_sources, 3) for ‘point’ or directions for ‘parallel’ values: Source intensities (n_sources,) source_type: ‘point’ or ‘parallel’ sensor_idx: Index of sensor group to use
- Returns:
Array of shape (n_sources, n_sensors * n_pixels) where n_pixels is the flattened per-sensor size.
- iactrace.core.trace_rays(tel, ray_origins, ray_directions, values, sensor_idx=0)[source]¶
Render classical rays through telescope onto sensor group.
Unlike render() which samples rays from primary mirror surfaces, this function traces rays from arbitrary external origins through the full optical system, including intersection with primary mirrors (stage 0).
Supports mixed reflective/refractive systems - rays are automatically reflected or refracted based on each optical element’s interaction type.
- Args:
tel: Telescope object ray_origins: Ray starting positions (n_rays, 3) ray_directions: Ray directions (n_rays, 3), should be normalized values: Ray intensities (n_rays,) sensor_idx: Index of sensor group to use
- Returns:
Accumulated image with shape (n_sensors, *per_sensor_shape).
- iactrace.core.trace_rays_debug(tel, ray_origins, ray_directions, values, sensor_idx=0)[source]¶
Render classical rays without accumulation - returns raw hits.
Debug version of trace_rays that returns individual ray hit positions and values instead of accumulated image.
Supports mixed reflective/refractive systems.
- Args:
tel: Telescope object ray_origins: Ray starting positions (n_rays, 3) ray_directions: Ray directions (n_rays, 3), should be normalized values: Ray intensities (n_rays,) sensor_idx: Index of sensor group to use
- Returns:
- Tuple of (points, sensor_idx, values):
points: (n_rays, 2) sensor coordinates for each ray
sensor_idx: (n_rays,) index of sensor each ray hit
values: (n_rays,) final intensity values (0 if ray missed)
Integrators¶
Classes for sampling rays on optical surfaces:
- class iactrace.core.Integrator[source]¶
Bases:
ABCAbstract base class for optical element sampling integrators.
- abstractmethod sample_group(group, key)[source]¶
Sample a single optical group and return updated object.
- Args:
group: OpticalGroupBase object (mirror or lens) key: JAX random key
- Returns:
OpticalGroup with sampled aperture positions and perturbation angles
- sample_optical_groups(optical_groups, key)[source]¶
Sample all optical groups (mirrors and lenses) and return updated list.
This is the unified entry point for sampling any optical element.
- Args:
optical_groups: List of OpticalGroupBase objects key: JAX random key
- Returns:
List of OpticalGroupBase objects with sampled aperture positions
- class iactrace.core.MCIntegrator[source]¶
Bases:
IntegratorMonte Carlo integrator for optical element groups (mirrors and lenses).
- n_samples¶
- sample_group(group, key)[source]¶
Sample a single optical group using Monte Carlo sampling.
Works with both mirror groups (AsphericDiskMirrorGroup, AsphericPolygonMirrorGroup) and lens groups (AsphericDiskLensGroup, PlanoSlabGroup).
The sampling process: 1. Generate uniform random 2D points on each aperture 2. Generate random perturbation angles for surface roughness 3. Geometry (3D points, normals, weights) is computed at render time
- Args:
group: OpticalGroupBase object (mirror or lens) key: JAX random key
- Returns:
OpticalGroup with sampled aperture positions and perturbation angles
Optical Physics¶
Functions for ray-surface interactions:
- iactrace.core.reflect(direction, normal)[source]¶
Reflect ray direction off surface with given normal.
Implements the law of reflection: the angle of incidence equals the angle of reflection, with the reflected ray in the plane of incidence.
- Args:
direction: Ray direction (3,), pointing towards surface normal: Surface normal (3,), pointing outward from surface
- Returns:
reflected: Reflected direction (3,) cos_angle: Cosine of incident angle (positive value)
- iactrace.core.refract(direction, normal, n1, n2)[source]¶
Refract ray direction through interface using Snell’s law.
Computes the refracted ray direction when light passes from a medium with refractive index n1 into a medium with refractive index n2.
The function handles rays coming from either side of the surface by checking the sign of the dot product and flipping the normal if needed.
- Args:
direction: Ray direction (3,), normalized, pointing towards surface normal: Surface normal (3,), normalized, pointing outward n1: Refractive index of incident medium (scalar) n2: Refractive index of transmitted medium (scalar)
- Returns:
refracted: Refracted direction (3,), or original direction if TIR cos_theta_t: Cosine of refracted angle tir: Boolean, True if total internal reflection occurred
- iactrace.core.refract_slab(direction, normal, position, n_out, n_in, thickness)[source]¶
Refract ray through a parallel-sided slab (window).
Handles both entry and exit refractions for a slab with parallel surfaces. The exit surface normal is assumed to be opposite to the entry normal. Applies Fresnel transmission coefficients at both surfaces.
For flat slabs, the exiting ray direction equals the entering direction (but with a lateral offset). For curved slabs with parallel surfaces, there may be slight direction change due to the curved geometry.
- Args:
direction: Ray direction (3,), normalized normal: Front surface normal (3,), pointing outward (into incident medium) position: Entry point position (3,) n_out: Refractive index of ambient medium (scalar) n_in: Refractive index of slab material (scalar) thickness: Slab thickness (scalar)
- Returns:
exit_direction: Direction after exiting slab (3,) exit_position: Position where ray exits slab (3,) transmittance: Combined Fresnel transmission coefficient for both surfaces valid: Boolean, True if ray successfully transmitted (no TIR)
- iactrace.core.fresnel_unpolarized(cos_theta_i, cos_theta_t, n1, n2)[source]¶
Compute Fresnel reflection and transmission coefficients for unpolarized light.
Uses the Fresnel equations to compute the fraction of light reflected (R) and transmitted (T) at an interface, averaged over s and p polarizations.
- Args:
cos_theta_i: Cosine of incident angle (scalar or array) cos_theta_t: Cosine of transmitted angle (scalar or array) n1: Refractive index of incident medium n2: Refractive index of transmitted medium
- Returns:
R: Reflectance (fraction of light reflected), 0 <= R <= 1 T: Transmittance (fraction of light transmitted), T = 1 - R
Surfaces¶
Aspheric surface calculations:
- class iactrace.core.AsphericSurface[source]¶
Bases:
ModuleAspheric surface defined by curvature, conic constant, and polynomial terms.
This class stores surface parameters and provides intersection functionality. For computing sag/normals in differentiable pipelines, use the standalone functions which enable full gradient flow.
- curvature = <dataclasses._MISSING_TYPE object>¶
- conic = <dataclasses._MISSING_TYPE object>¶
- aspheric = <dataclasses._MISSING_TYPE object>¶
- sag(x, y, offset)[source]¶
Compute surface sag z(x,y) in local mirror coordinates.
Convenience method that calls the standalone sag function.
- Args:
x: x-coordinate in local mirror frame (scalar) y: y-coordinate in local mirror frame (scalar) offset: (x0, y0) offset on parent surface (2,)
- Returns:
z: Surface sag at (x, y) relative to offset point
- intersect(ray_origin, ray_direction, offset, max_iter=10, tol=1e-08)[source]¶
Find ray-surface intersection using Newton-Raphson iteration.
Uses closed-form conic intersection as initial guess, then refines with Newton-Raphson to account for aspheric terms.
- Args:
ray_origin: Ray origin in local coordinates (3,) ray_direction: Ray direction (3,) offset: Surface offset (x0, y0) (2,) max_iter: Maximum Newton-Raphson iterations tol: Convergence tolerance
- Returns:
t: Intersection distance point: Intersection point (3,) normal: Surface normal at intersection (3,)
- __init__(curvature, conic, aspheric)¶
- iactrace.core.sag(x, y, offset, curvature, conic, aspheric)[source]¶
Compute surface sag z(x,y) in local mirror coordinates.
- Args:
x: x-coordinate in local mirror frame (scalar) y: y-coordinate in local mirror frame (scalar) offset: (x0, y0) offset on parent surface (2,) curvature: Surface curvature (1/radius) conic: Conic constant k aspheric: Array of aspheric coefficients (K,)
- Returns:
z: Surface sag at (x, y) relative to offset point
- iactrace.core.compute_sag_and_normal(x, y, offset, curvature, conic, aspheric)[source]¶
Compute surface point and normal at (x, y) with given parameters.
- Args:
x: x-coordinate in local mirror frame (scalar) y: y-coordinate in local mirror frame (scalar) offset: (x0, y0) offset on parent surface (2,) curvature: Surface curvature (1/radius) conic: Conic constant k aspheric: Array of aspheric coefficients (K,)
- Returns:
point: 3D surface point (3,) normal: Surface normal (3,), normalized
Intersection Functions¶
Geometric ray-primitive intersection tests:
- iactrace.core.intersect_plane(ray_origin, ray_direction, plane_center, plane_rotation)[source]¶
Intersect ray with a plane defined by center and rotation matrix.
- Args:
ray_origin: Ray origin (3,) ray_direction: Ray direction (3,) plane_center: Plane center (3,) plane_rotation: Rotation matrix (3, 3) - Z-axis is normal
- Returns:
Tuple of (2D coordinates on plane (2,), t parameter (scalar))
- iactrace.core.intersect_sphere(ray_origin, ray_direction, center, radius)[source]¶
Intersect ray with sphere.
- Args:
ray_origin: Ray origin (3,) ray_direction: Ray direction (3,), assumed normalized center: Sphere center (3,) radius: Sphere radius (scalar)
- Returns:
t parameter of nearest intersection, jnp.inf if no hit
- iactrace.core.intersect_cylinder(ray_origin, ray_direction, p1, p2, radius)[source]¶
Single cylinder intersection (for vmapping).
- iactrace.core.intersect_box(ray_origin, ray_direction, p1, p2)[source]¶
Single box intersection (for vmapping).
- iactrace.core.intersect_oriented_box(ray_origin, ray_direction, center, half_extents, rotation)[source]¶
Intersect ray with oriented bounding box.
- Args:
ray_origin: Ray origin (3,) ray_direction: Ray direction (3,) center: Box center (3,) half_extents: Half-sizes along local axes (3,) rotation: Rotation matrix (3, 3) transforming local to world coords
- Returns:
t parameter of nearest intersection, jnp.inf if no hit
- iactrace.core.intersect_triangle(ray_origin, ray_direction, v0, v1, v2)[source]¶
Intersect ray with triangle using Möller-Trumbore algorithm.
- Args:
ray_origin: Ray origin (3,) ray_direction: Ray direction (3,) v0, v1, v2: Triangle vertices (3,) each
- Returns:
t parameter of intersection, jnp.inf if no hit
- iactrace.core.intersect_conic(ray_origin, ray_direction, curvature, conic)[source]¶
Compute closed-form ray-conic intersection parameter.
- The conic surface is defined by the implicit equation:
c*(x² + y²) + (1+k)*c*z² - 2*z = 0
where c is curvature and k is the conic constant.
- Args:
ray_origin: Ray origin (3,) ray_direction: Ray direction (3,), assumed normalized curvature: Surface curvature (1/radius) conic: Conic constant (0=sphere, -1=paraboloid, <-1=hyperboloid, >-1=ellipsoid)
- Returns:
t: Ray parameter at intersection (smallest positive root), inf if no intersection
Obstruction Groups¶
Classes for modeling ray obstructions:
- class iactrace.core.ObstructionGroup[source]¶
Bases:
ModuleBase class for grouped obstructions.
- config_type = ''¶
- abstractmethod intersect(ray_origin, ray_direction)[source]¶
Returns min t across all primitives in group.
- abstractmethod classmethod from_config(configs)[source]¶
Create an ObstructionGroup from a list of config dicts.
- __init__()¶
- class iactrace.core.CylinderGroup[source]¶
Bases:
ObstructionGroupCylinderGroup(p1, p2, r)
- config_type = 'cylinder'¶
Group of cylinders for efficient batched intersection.
- p1 = <dataclasses._MISSING_TYPE object>¶
- p2 = <dataclasses._MISSING_TYPE object>¶
- r = <dataclasses._MISSING_TYPE object>¶
- class iactrace.core.BoxGroup[source]¶
Bases:
ObstructionGroupBoxGroup(p1, p2)
- config_type = 'box'¶
Group of axis-aligned boxes for efficient batched intersection.
- p1 = <dataclasses._MISSING_TYPE object>¶
- p2 = <dataclasses._MISSING_TYPE object>¶
- class iactrace.core.SphereGroup[source]¶
Bases:
ObstructionGroupSphereGroup(centers, radii)
- config_type = 'sphere'¶
Group of spheres for efficient batched intersection.
- centers = <dataclasses._MISSING_TYPE object>¶
- radii = <dataclasses._MISSING_TYPE object>¶
- class iactrace.core.OrientedBoxGroup[source]¶
Bases:
ObstructionGroupOrientedBoxGroup(centers, half_extents, rotations)
- config_type = 'oriented_box'¶
Group of oriented boxes for efficient batched intersection.
- centers = <dataclasses._MISSING_TYPE object>¶
- half_extents = <dataclasses._MISSING_TYPE object>¶
- rotations = <dataclasses._MISSING_TYPE object>¶
Transforms¶
Coordinate transformation utilities: