Skip to main content

Interactive radio astronomy visualization widget for Jupyter

Project description

astrowidget

Interactive radio astronomy visualization for Jupyter. Renders radio images on a rotatable celestial sphere with SIN projection, reading directly from zarr stores -- no FITS intermediary.

PyPI version License Python DOI

Why astrowidget?

Existing tools like ipyaladin have significant limitations for radio astronomy workflows:

Problem with ipyaladin astrowidget solution
Broken sphere overlay for radio images Correct SIN projection on a rotatable sphere
Requires FITS round-trip (zarr -> HDU -> FITS -> display) Direct binary transfer (zarr -> numpy -> GPU)
GPL-3 license (Aladin Lite) BSD-3, fully owned
No native zarr support open_dataset() reads zarr natively
FITS serialization adds latency Raw float32 transfer, <50 ms per frame
No frequency/time slider controls Built-in time/freq slice navigation

Features

  • Interactive sphere -- Pan, zoom, and rotate the celestial sphere at 60 fps
  • Zarr-native -- Load local, remote (S3/HTTPS), or in-memory zarr stores
  • WCS coordinate grid -- RA/Dec grid overlay with auto-scaling intervals
  • HiPS backgrounds -- Aladin Lite embed for DSS, WISE, Planck survey tiles
  • Click-to-inspect -- Click anywhere on the sphere to extract spectrum and light curve
  • SkyViewer dashboard -- Panel-based dashboard with controls and linked HoloViews plots
  • Box zoom -- Drag a rectangle to zoom into a region of interest
  • Tested -- 63 Python + 15 JS tests with astropy-validated projection vectors

Quick Start

from astrowidget import SkyWidget, open_dataset

# Load zarr data
ds = open_dataset("path/to/observation.zarr")

# Display on the celestial sphere
widget = SkyWidget()
widget.set_dataset(ds)
widget.background_survey = "DSS"  # optional HiPS background
widget

Synthetic data

from astrowidget import SkyWidget
import numpy as np
from astropy.wcs import WCS

data = np.random.randn(256, 256).astype(np.float32)

wcs = WCS(naxis=2)
wcs.wcs.ctype = ["RA---SIN", "DEC--SIN"]
wcs.wcs.crval = [180.0, 45.0]
wcs.wcs.cdelt = [-0.1, 0.1]
wcs.wcs.crpix = [128.5, 128.5]

widget = SkyWidget()
widget.set_image(data, wcs)
widget

Dashboard with linked views

from astrowidget import SkyViewer

viewer = SkyViewer.from_zarr("path/to/observation.zarr")
viewer.panel()

This opens a Panel dashboard with the sky widget, time/frequency sliders, colormap controls, and linked spectrum + light curve plots that update on click.

Installation

From PyPI

pip install astrowidget

Optional extras:

pip install 'astrowidget[dashboard]'  # Panel, HoloViews, Bokeh for SkyViewer
pip install 'astrowidget[remote]'     # S3/fsspec for remote zarr stores
pip install 'astrowidget[ingest]'     # xradio for radio data ingestion

From source (development)

git clone https://github.com/uw-ssec/astrowidget.git
cd astrowidget
pixi install
pixi run test  # verify everything works

As a dependency in another pixi project

Add to your pyproject.toml:

[tool.pixi.feature.visualization.pypi-dependencies]
astrowidget = { path = "../astrowidget", editable = true }

Development

astrowidget uses pixi for reproducible development environments. All tasks are defined in pyproject.toml:

Task Description
pixi run test Run all Python and JS tests
pixi run test-py Run Python tests only
pixi run test-js Run JS tests only
pixi run lint Lint with ruff
pixi run build Build JS bundle with Vite
pixi run dev Watch mode for JS development
pixi run docs-serve Serve docs locally at localhost:8000
pixi run docs-build Build static documentation site
pixi run vectors Regenerate astropy projection test fixtures

Build pipeline

  1. JS: npm run build bundles js/inline_widget.js into src/astrowidget/static/widget.js via Vite
  2. Python: python -m build creates sdist + wheel with the bundled JS
  3. CI/CD: GitHub Actions builds and publishes to PyPI on release via trusted publisher

Architecture

zarr store ──> xarray.Dataset ──> PreloadedCube (LRU cache)
                                       │
                                  float32 slice
                                       │
                              SkyWidget (anywidget)
                                       │
                               ┌───────┴───────┐
                               │  Python ←→ JS  │
                               │   (traitlets)  │
                               └───────┬───────┘
                                       │
                              WebGL2 fragment shader
                              ┌────────────────────┐
                              │ screen pixel        │
                              │   → gnomonic inv.   │
                              │   → RA/Dec          │
                              │   → SIN proj.       │
                              │   → (l, m)          │
                              │   → texture sample  │
                              │   → stretch         │
                              │   → colormap LUT    │
                              │   → RGBA            │
                              └────────────────────┘

Key components

Component File Role
SkyWidget src/astrowidget/widget.py Anywidget class -- bridges Python data to JS renderer
open_dataset src/astrowidget/io.py Unified zarr loader (local, S3, in-memory)
PreloadedCube src/astrowidget/cube.py LRU-cached slice loader with strided downsampling
get_wcs src/astrowidget/wcs.py WCS extraction from zarr metadata (3 fallback locations)
SkyViewer src/astrowidget/viewer.py Panel dashboard with linked spectrum/light curve views
WebGL renderer js/inline_widget.js Raw WebGL2 fragment shader with SIN projection

API Overview

SkyWidget

The core widget for displaying radio images on the celestial sphere.

widget = SkyWidget()

# Load data
widget.set_image(data_2d, wcs)           # numpy array + astropy WCS
widget.set_dataset(ds)                    # xarray Dataset from zarr

# Navigation
widget.goto(SkyCoord(180, 45, unit="deg"), fov=10)

# Display options
widget.colormap = "viridis"               # inferno, viridis, plasma, magma, grayscale
widget.stretch = "sqrt"                   # linear, log, sqrt, asinh
widget.show_grid = True                   # RA/Dec coordinate grid
widget.auto_scale(5, 99.5)               # percentile-based vmin/vmax

# HiPS background
widget.background_survey = "DSS"          # DSS, WISE, Planck, 2MASS, ...
widget.background_opacity = 0.5

# Events
widget.clicked_coord                      # (RA, Dec) of last click

open_dataset

from astrowidget import open_dataset

ds = open_dataset("/local/path.zarr")
ds = open_dataset("s3://bucket/obs.zarr", storage_options={"anon": True})

SkyViewer

from astrowidget import SkyViewer

viewer = SkyViewer.from_zarr("path/to/data.zarr")
viewer.panel()  # returns a Panel layout

Tech Stack

Layer Technology
Widget framework anywidget
Rendering Raw WebGL2 (fragment shader)
Projection SIN (slant orthographic)
Data format zarr v2 via xarray + dask
Coordinates astropy WCS
Dashboard Panel + HoloViews + Bokeh
Build Hatchling (Python) + Vite (JS)
Environment pixi (conda-forge)
Testing pytest + vitest
CI/CD GitHub Actions -> PyPI trusted publisher

Documentation

Full documentation is available at uw-ssec.github.io/astrowidget:

Section Description
Getting Started Installation, first widget, pixi tasks
Architecture Overview System design, data flow, components
Data Pipeline Zarr loading, WCS extraction, caching
WebGL Renderer Fragment shader, SIN projection, colormaps
Design Decisions Why raw WebGL2, inline ESM, uint8 textures
OVRO-LWA Integration Using with ovro-lwa-portal
HiPS Backgrounds Aladin Lite survey configuration
API Reference SkyWidget, open_dataset, SkyViewer

License

BSD 3-Clause -- Copyright (c) 2026, UW Scientific Software Engineering Center

Citation

If you use astrowidget in your research, please cite:

@software{astrowidget,
  title     = {astrowidget: Interactive Radio Astronomy Visualization for Jupyter},
  author    = {{UW Scientific Software Engineering Center}},
  year      = {2026},
  url       = {https://github.com/uw-ssec/astrowidget},
  license   = {BSD-3-Clause}
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

astrowidget-0.1.2.tar.gz (323.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

astrowidget-0.1.2-py3-none-any.whl (215.6 kB view details)

Uploaded Python 3

File details

Details for the file astrowidget-0.1.2.tar.gz.

File metadata

  • Download URL: astrowidget-0.1.2.tar.gz
  • Upload date:
  • Size: 323.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for astrowidget-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3cd39cea5020ba0c2b7389af39afe4a4b83373c3e097a260f0f23423a007026e
MD5 51ade631534b0f31619700912bd6732a
BLAKE2b-256 d62de3c72106648e0c2425263e95d00a47e4dc6bb251b6ecba8fe37116d91038

See more details on using hashes here.

Provenance

The following attestation bundles were made for astrowidget-0.1.2.tar.gz:

Publisher: publish.yml on uw-ssec/astrowidget

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file astrowidget-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: astrowidget-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 215.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for astrowidget-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c417b91d4f53c6f63fbc464c8d3c9eeb110b3ae0ad23d2202446124a4e82290a
MD5 ba0fb27e1a2a4243cd9f6882ddee0444
BLAKE2b-256 f823b90d8e2f3b075d53e2e0295775add34f052acedeeef478e679d2dccc8de3

See more details on using hashes here.

Provenance

The following attestation bundles were made for astrowidget-0.1.2-py3-none-any.whl:

Publisher: publish.yml on uw-ssec/astrowidget

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page