iactrace.analysis

Analysis tools for post-processing ray bundles.

Focal Surface

Intersect a RayBundle with a parametric focal surface to inspect spot diagrams, chief-ray angles, and other PSF metrics without going through the camera’s pixel binning.

class iactrace.analysis.FocalSurface[source]

Bases: Module

Abstract focal surface attached to the camera frame.

position = <dataclasses._MISSING_TYPE object>
rotation = <dataclasses._MISSING_TYPE object>
intersect(ray_bundle)[source]

Intersect every ray in ray_bundle with this focal surface.

Lazy bundles are materialised first; per-ray analysis cannot fold.

__init__(position, rotation)
class iactrace.analysis.FlatFocalPlane[source]

Bases: FocalSurface

A flat focal plane.

__init__(position=None, rotation=None)[source]
class iactrace.analysis.AsphericFocalSurface[source]

Bases: FocalSurface

A rotationally-symmetric aspheric focal surface.

Parameterisation matches AsphericSurfaceGroup; the surface sag is

z(r) = c r^2 / (1 + sqrt(1 - (1 + k) c^2 r^2))
  • sum_i a_i r^(2i+4)

__init__(position=None, rotation=None, *, curvature=0.0, conic=0.0, aspherics=None)[source]
curvature = <dataclasses._MISSING_TYPE object>
conic = <dataclasses._MISSING_TYPE object>
aspherics = <dataclasses._MISSING_TYPE object>
class iactrace.analysis.FocalSurfaceHits[source]

Bases: Module

Result of intersecting a RayBundle with a FocalSurface.

Variables:
  • xy_local (jax.Array) – Tangent-plane coordinates at the hit, in the surface-local frame (n_rays, 2).

  • z_local (jax.Array) – Sag of the surface at the hit (n_rays,). Always 0 for a flat focal plane.

  • t (jax.Array) – Ray parameter at the hit; equals the world-frame distance travelled from ray_bundle.origins to the surface (n_rays,).

  • hit_mask (jax.Array) – Liveness at the surface (n_rays,).

  • directions_local (ndarray (n_rays, 3)) – Ray directions in the surface-local frame.

  • opl (jax.Array) – Per-ray optical path length from the source wavefront to the focal surface, in metres (n_rays,). Equals ray_bundle.path_length + t * ray_bundle.n.

  • values (jax.Array) – Throughput-weighted intensity carried to the surface (n_rays,), in the input bundle’s units.

  • wavelength (ndarray (n_rays,)) – Per-ray wavelength carried from the input bundle.

xy_local = <dataclasses._MISSING_TYPE object>
z_local = <dataclasses._MISSING_TYPE object>
t = <dataclasses._MISSING_TYPE object>
hit_mask = <dataclasses._MISSING_TYPE object>
directions_local = <dataclasses._MISSING_TYPE object>
opl = <dataclasses._MISSING_TYPE object>
values = <dataclasses._MISSING_TYPE object>
wavelength = <dataclasses._MISSING_TYPE object>
property alive

Rays that reached the surface carrying light (hit_mask & values > 0).

__init__(xy_local, z_local, t, hit_mask, directions_local, opl, values, wavelength)

Effective Aperture

Tabulate what a telescope and camera together do to a plane wave: the per-pixel effective area, over field angle and over wavelength. The scan is the expensive step, so a table is normally written once and read back many times – see iactrace.io.save_aperture_table() for the format, which numpy alone can read.

iactrace.analysis.effective_aperture(telescope, camera, *, half_angle, step, wavelengths, sensor_idx=0, window=None, frame=None, chunk_size=512, tol=0.0001, progress=False)[source]

Tabulate a telescope + camera’s per-pixel effective aperture.

Parameters:
  • telescope – Its n_samples per primary element sets the Monte-Carlo noise.

  • camera – The camera.

  • half_angle – Half-width of the field to scan, radians. Must clear the camera: roughly atan(camera_radius / focal_length) plus margin.

  • step – Lattice node spacing, radians. Resolves the response shape.

  • wavelengths – Grid (K,) for B(lambda), in nm; at least two distinct values.

  • sensor_idx – Which sensor group to tabulate.

  • window – Side length of each response window in nodes, forced odd. Defaults to the largest measured extent plus a zero border.

  • frame – The FieldFrame offsets are measured in. Defaults to FieldFrame.from_telescope.

  • chunk_size – Directions per render call; bounds device memory only.

  • tol – Fraction of a pixel’s peak below which its response counts as zero, both when bounding it and when checking it fits its window.

  • progress – Print progress to stderr.

Return type:

An EffectiveApertureTable.

Raises:

ValueError – if the optics collects no light, if any pixel is dark, if a response reaches the edge of the field (half_angle too small), or if one does not fit its window (window too small).

class iactrace.analysis.EffectiveApertureTable[source]

Bases: object

A telescope’s per-pixel effective aperture, tabulated over field angle.

Node (i, j) sits at field offset origin + (i, j) * step, and pixel p covers nodes offset[p] to offset[p] + values.shape[-2:]. Field offsets are the spherical offset coordinates of FieldFrame, and lon = lat = 0 is a node by construction.

Variables:
  • origin (ndarray (2,)) – Field offset of node (0, 0), [lon, lat] in radians.

  • step (ndarray (2,)) – Node spacing along [lon, lat], in radians.

  • offset (ndarray (n_pixels, 2)) – Node index of each pixel’s window corner.

  • values (numpy.ndarray) – Effective area in m^2 (n_pixels, W, W); axis -2 runs along lon, axis -1 along lat. Zero on the boundary by construction.

  • on_axis_area (float) – On-axis effective area over all pixels, band-averaged over spectral_area. Normalises values dimensionless.

  • wavelengths (ndarray (K,)) – Wavelength grid of spectral_area, in nm.

  • spectral_area (ndarray (K,)) – On-axis total effective area per wavelength.

  • meta (dict) – Provenance, including the table’s own on-axis sum for comparison against on_axis_area (they differ only by Monte-Carlo noise).

origin = <dataclasses._MISSING_TYPE object>
step = <dataclasses._MISSING_TYPE object>
offset = <dataclasses._MISSING_TYPE object>
values = <dataclasses._MISSING_TYPE object>
on_axis_area = <dataclasses._MISSING_TYPE object>
wavelengths = <dataclasses._MISSING_TYPE object>
spectral_area = <dataclasses._MISSING_TYPE object>
meta = <dataclasses._MISSING_TYPE object>
property n_pixels

Number of pixels tabulated.

property window

Side length of each pixel’s response window, in lattice nodes.

property centres

Field offset each pixel looks at (n_pixels, 2), radians.

property window_centres

Field offset of each pixel’s window centre. Shape (n_pixels, 2), radians.

save(filename, *, overwrite=True, compress=True)[source]

Write to a .npz file; see iactrace.io.save_aperture_table.

classmethod load(filename)[source]

Read a table back; see iactrace.io.load_aperture_table.

__init__(origin, step, offset, values, on_axis_area, wavelengths, spectral_area, meta)
class iactrace.analysis.FieldFrame[source]

Bases: Module

The telescope’s field-angle frame – optical axis plus two sky axes.

A field direction (lon, lat) is the propagation direction of a plane wave arriving from that offset in the usual spherical offset coordinates about the optical axis.

Variables:
  • axis (jax.Array) – Unit propagation direction of an on-axis ray – the direction light travels, pointing into the telescope (3,).

  • e_lon (ndarray (3,)) – Unit sky axis of increasing lon.

  • e_lat (ndarray (3,)) – Unit sky axis of increasing lat.

axis = <dataclasses._MISSING_TYPE object>
e_lon = <dataclasses._MISSING_TYPE object>
e_lat = <dataclasses._MISSING_TYPE object>
classmethod from_telescope(telescope, rotation_deg=0.0)[source]

Derive the field frame from a telescope’s optics and mount convention.

Parameters:
  • telescope – The Telescope.

  • rotation_deg – Roll about the optical axis.

directions(lon, lat)[source]

Unit propagation directions (…, 3) for field offsets in radians.

__init__(axis, e_lon, e_lat)
iactrace.analysis.effective_area(telescope, camera, wavelengths, *, direction=None, sensor_idx=0, progress=False)[source]

Total effective collecting area per wavelength in square metres.

iactrace.analysis.pixel_response(telescope, camera, directions, spectrum=None, *, sensor_idx=0)[source]

Per-pixel effective area for field directions (n_directions, 3), in m^2.