skyscapes#
JAX-native astrophysical scene modeling for HWO direct imaging.
skyscapes provides the scene representation that downstream
HWO simulation tools consume – a forward model that runs at variable
fidelity, from analytic sandbox models for fast iteration up to
research-grade physics for retrievals. High-fidelity scene generators
like ExoVista feed into skyscapes
through loaders (from_exovista()); skyscapes does not
try to replace them.
A
Sceneis “everything on the sky that the telescope sees” – oneSystem(a star with planets and optionally a disk) plus optional background sources (zodiacal light, background galaxies, etc.).Source models (
Star,Planet,Disk, physical models, backgrounds) are composableeqx.Modules – swap any one without touching the rest, or swap the whole class for a higher-fidelity variant.Loaders bridge external simulation outputs (ExoVista FITS) into the workspace via
from_exovista().
The same Scene flows through both the
coronagraphoto image simulator and the
jaxedith ETC, so the
astrophysical content is consistent across all downstream science
products.
Ecosystem position#
flowchart LR
src["External sources<br/>ExoVista · spectra · catalogues"]
sky(["<b>skyscapes</b><br/>Scene · System · Star · Planet · Disk · Zodi · PhysicalModel"])
opt["<b>optixstuff</b><br/>OpticalPath"]
cor["<b>coronagraphoto</b><br/>2D image simulation"]
jet["<b>jaxedith</b><br/>Scalar count rates"]
src --> sky
sky --> cor
sky --> jet
opt --> cor
opt --> jet
Quick start#
The easiest path is loading an ExoVista FITS file into a Scene:
from skyscapes import from_exovista
scene = from_exovista("path/to/exovista_system.fits")
Building one from scratch is a little more involved – a Scene
composes a System (star + planets + optional disk) with an optional
Zodi, and Planet itself owns its intrinsic params (radius, mass)
and composes an orbit (from orbix) with a physical model:
import jax.numpy as jnp
from orbix.system.orbit import KeplerianOrbit
from skyscapes import Scene, System
from skyscapes.scene import FlatStar, Planet
from skyscapes.physical_model import LambertianPhysicalModel
from skyscapes.background import AYOZodi
star = FlatStar(
Ms_kg=1.989e30,
dist_pc=10.0,
flux_phot_per_nm_m2=1e9,
)
orbit = KeplerianOrbit(
a_AU=jnp.array([1.0]),
e=jnp.array([0.0]),
W_rad=jnp.array([0.0]),
i_rad=jnp.array([jnp.pi / 3]),
w_rad=jnp.array([0.0]),
M0_rad=jnp.array([0.0]),
t0_d=jnp.array([0.0]),
)
physical_model = LambertianPhysicalModel(Ag=jnp.array([0.3]))
planet = Planet(
Rp_Rearth=jnp.array([1.0]),
Mp_Mearth=jnp.array([1.0]),
orbit=orbit,
physical_model=physical_model,
)
zodi = AYOZodi(
wavelengths_nm=jnp.linspace(400, 1000, 60),
surface_brightness_mag=22.0,
)
scene = Scene(
system=System(star=star, planets=(planet,)),
zodi=zodi,
)
Installation#
pip install skyscapes
What you find here#
Scene primitives:
skyscapes.scene–Star,Planet,System,Sceneskyscapes.disk–AbstractDisk,ExovistaDisk,GraterDisk,CompositeDisk, …skyscapes.physical_model–LambertianPhysicalModel,ExoJaxPhysicalModel,GridPhysicalModel, …skyscapes.background–Zodi(union),AYOZodi,LeinertZodi,PrecomputedZodi
Loaders:
from_exovista(top-level) – one-call ingestion of ExoVista FITS
See also:
Source models – what each source type represents and when to use which
Physical models – the physical-model hierarchy (reflective, emissive, joint) and how contrast is computed
Local zodi + telescope geometry – the geometry required for position-dependent zodi models