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 Scene is “everything on the sky that the telescope sees” – one System (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 composable eqx.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:

Loaders:

  • from_exovista (top-level) – one-call ingestion of ExoVista FITS

See also: