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.3.tar.gz (276.7 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.3-py3-none-any.whl (169.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: astrowidget-0.1.3.tar.gz
  • Upload date:
  • Size: 276.7 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.3.tar.gz
Algorithm Hash digest
SHA256 ebd06824c9af9cb535a476433ee45fc3de96c0cf0c23649b2d80f44506d81c7a
MD5 178ead3c3e850803547cef311d17eafb
BLAKE2b-256 c9b169c924207667137323f1a3400a3116ddac0a4ad5097b0d5dfa8f2852c53f

See more details on using hashes here.

Provenance

The following attestation bundles were made for astrowidget-0.1.3.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.3-py3-none-any.whl.

File metadata

  • Download URL: astrowidget-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 169.4 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 858fb87bb86df2475386c4133b025ec903fc27234ce3e30672c14e95517fa89a
MD5 6233090f3d184c179a690eef5161dba3
BLAKE2b-256 ff218845fd0f1bd6d920b17f2135177b89b3f938c1db461cc6830460c065849a

See more details on using hashes here.

Provenance

The following attestation bundles were made for astrowidget-0.1.3-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