coronagraphoto.simulation#

Functions for running full simulations and processing sources.

Public API conventions:

  • <source>_rate(source, optical_path, *, ...) returns the noiseless per-pixel photo-electron rate on the detector for one source.

  • <source>_readout(source, optical_path, prng_key, *, ...) returns a noisy detector readout (photon Poisson + QE binomial) for one source.

  • system_rate(scene, optical_path, *, ...) sums every per-source rate map for a scene (the differentiable forward model).

  • system_readout(scene, optical_path, prng_key, *, ...) sums every per-source Poisson-realised readout for a scene.

All observation parameters (start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, telescope_pa_deg, ecliptic_lat_deg, solar_lon_deg) are kwarg-only. The convention keeps signatures discoverable when more parameters land later (IFS, multi-roll observations).

Functions#

pre_coro_bin_processing(flux, bin_center_nm, ...)

Process a bin through the pre-coro elements of the optical path.

_detector_sampling_lod(bin_center_nm, optical_path)

The detector grid expressed in coronagraph (lambda/D) units.

star_rate(star, optical_path, *, start_time_jd, ...)

Generate the star count rate on the detector.

star_readout(star, optical_path, prng_key, *, ...)

Process a star through the provided optical path.

planet_rate(planet, optical_path, *, start_time_jd, ...)

Generate the per-batch planet count rate on the detector.

planet_readout(planet, optical_path, prng_key, *, ...)

Process a per-batch Planet through the optical path.

disk_rate(disk, optical_path, *, start_time_jd, ...)

Generate the disk count rate on the detector.

disk_readout(disk, optical_path, prng_key, *, ...)

Process a disk through the provided optical path.

zodi_rate(zodi, optical_path, *, start_time_jd, ...)

Generate the zodi count rate on the detector.

zodi_readout(zodi, optical_path, prng_key, *, ...)

Process a zodi source through the provided optical path.

speckle_rate(speckle, optical_path, *, start_time_jd, ...)

Generate the speckle count rate on the detector.

speckle_readout(speckle, optical_path, prng_key, *, ...)

Process a speckle field through the provided optical path.

system_rate(scene, optical_path, *, start_time_jd, ...)

Sum of deterministic per-source count rates for a Scene.

system_readout(scene, optical_path, prng_key, *, ...)

Simulate a full Scene through the optical path.

Module Contents#

coronagraphoto.simulation.pre_coro_bin_processing(flux, bin_center_nm, bin_width_nm, optical_path)[source]#

Process a bin through the pre-coro elements of the optical path.

coronagraphoto.simulation._detector_sampling_lod(bin_center_nm, optical_path)[source]#

The detector grid expressed in coronagraph (lambda/D) units.

The coronagraph contract is sampling-explicit and dimensionless: every rate function requests maps directly at the detector grid, converted to lambda/D at this wavelength. Chromatic magnification is exactly this conversion changing with the bin center.

coronagraphoto.simulation.star_rate(star, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm)[source]#

Generate the star count rate on the detector.

coronagraphoto.simulation.star_readout(star, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm)[source]#

Process a star through the provided optical path.

coronagraphoto.simulation.planet_rate(planet, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm, telescope_pa_deg, star, trig_solver)[source]#

Generate the per-batch planet count rate on the detector.

Operates on a single skyscapes.scene.Planet (which internally batches K planets sharing the same atmosphere class). The Python loop over a heterogeneous System.planets tuple lives in system_readout(); this function stays inside the per-Planet-type JIT cache boundary.

coronagraphoto.simulation.planet_readout(planet, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, telescope_pa_deg, star, trig_solver)[source]#

Process a per-batch Planet through the optical path.

coronagraphoto.simulation.disk_rate(disk, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm, telescope_pa_deg, star, incl_deg, pa_deg)[source]#

Generate the disk count rate on the detector.

Disks return CONTRAST (dimensionless flux ratio relative to the host star); we multiply by star.spec_flux_density here to convert to photon flux density per pixel before resampling and PSF convolution.

incl_deg / pa_deg are the disk’s intrinsic orientation in the sky frame; telescope_pa_deg is the telescope’s roll. The disk is rendered at its intrinsic geometry and the coronagraph’s extended_scene rotates it by -telescope_pa_deg into the detector frame while rendering.

Raises:
ValueError: from the coronagraph if it cannot render an extended

scene (e.g. a table-backed coronagraph built without a PSF datacube).

coronagraphoto.simulation.disk_readout(disk, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, telescope_pa_deg, star, incl_deg, pa_deg)[source]#

Process a disk through the provided optical path.

incl_deg / pa_deg are the disk’s intrinsic sky-frame orientation; system_readout pulls them from scene.system.midplane_inc_deg / midplane_pa_deg so every disk component in the System renders at the same midplane.

coronagraphoto.simulation.zodi_rate(zodi, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm, ecliptic_lat_deg, solar_lon_deg)[source]#

Generate the zodi count rate on the detector.

Treats zodi as a spatially uniform surface-brightness source. The coronagraph’s sky transmission map sets the per-pixel attenuation; no PSF convolution is needed (a flat field convolved with any normalised PSF returns itself).

Parameters:

zodi (skyscapes.background.Zodi)

coronagraphoto.simulation.zodi_readout(zodi, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, ecliptic_lat_deg, solar_lon_deg)[source]#

Process a zodi source through the provided optical path.

Parameters:

zodi (skyscapes.background.Zodi)

coronagraphoto.simulation.speckle_rate(speckle, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm, star)[source]#

Generate the speckle count rate on the detector.

The speckle field returns a CONTRAST delta (fraction of host-star flux per pixel) – the stochastic wavefront-error residual that sits on top of the deterministic stellar_intens floor already applied in star_rate(). We multiply by the host-star flux to convert to a photon rate, then resample to the detector. Structurally this mirrors star_rate(), not disk_rate(): the field is already a post-coronagraph focal-plane map, so there is no PSF convolution.

Evolution is driven by time, not a PRNG key: the elapsed seconds are (start_time_jd - speckle.epoch_jd), so the rate is deterministic and differentiable and temporal correlation survives across a roll sequence. The realization’s randomness is fixed at construction.

The speckle map is taken on the plane declared by its own speckle.pixel_scale_lod and resampled to the detector grid directly, so it need not share a plate scale with the coronagraph.

coronagraphoto.simulation.speckle_readout(speckle, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, star)[source]#

Process a speckle field through the provided optical path.

The PRNG key is used only for the photon Poisson draw; the speckle realization itself is deterministic in time (see speckle_rate()).

coronagraphoto.simulation.system_rate(scene, optical_path, *, start_time_jd, wavelength_nm, bin_width_nm, telescope_pa_deg, ecliptic_lat_deg, solar_lon_deg)[source]#

Sum of deterministic per-source count rates for a Scene.

The differentiable companion to system_readout(). Returns the total rate map (electrons/s/pixel, no Poisson noise, no QE multiply) summing star, every planet, the optional disk, the optional zodi, and the optional speckle field on optical_path. Use this for likelihood evaluation, retrievals, or any inference loop that needs gradients through the full forward model.

coronagraphoto.simulation.system_readout(scene, optical_path, prng_key, *, start_time_jd, exposure_time_s, wavelength_nm, bin_width_nm, telescope_pa_deg, ecliptic_lat_deg, solar_lon_deg)[source]#

Simulate a full Scene through the optical path.

Sums per-source detector readouts. Each source consumes its own independent PRNG subkey (see jax.random best practices). The optional speckle field on optical_path is the last source and consumes the final subkey, so scenes run without one are unaffected.

The Python loop over scene.system.planets is intentionally unjitted – it orchestrates JIT-cached per-Planet-type kernels. The expensive math is inside each planet_readout call, not the loop.