fitsview
A JupyterLab extension for viewing FITS (Flexible Image Transport System) files without downloading entire files to the browser. This is essential for working with large astronomical datasets.
Features
- Lazy loading: Opens FITS files without downloading the full content to the browser
- Handles FITS quirks: Uses the battle-tested
astropy.io.fitson the backend - Metadata display: View HDU headers, shapes, and data types
- Data slicing: Request specific regions of data on demand
- Multiple HDU support: Browse all extensions in a FITS file
Requirements
- JupyterLab >= 4.0.0
- Python >= 3.10
- astropy >= 5.0
- numpy
Install
To install the extension, execute:
pip install fitsview
The server extension will be automatically enabled. Verify the installation:
# Check the lab extension
jupyter labextension list
# Check the server extension
jupyter server extension list
Both should show fitsview as enabled.
Usage
- Open JupyterLab
- Navigate to a
.fitsfile in the file browser - Double-click to open with the FITS Viewer
- View HDU metadata and test data slicing
Uninstall
To remove the extension, execute:
pip uninstall fitsview
API Endpoints
The extension provides two REST API endpoints (namespaced under /fitsview/):
GET /fitsview/metadata
Returns metadata for a FITS file.
Parameters:
path(required): Path to the FITS file relative to the Jupyter server root
Response: JSON object with:
path: File pathhdus: Array of HDU info (index, name, type, header, shape, dtype)
GET /fitsview/slice
Returns a data slice as raw bytes in little-endian byte order, preserving the original data type. Supports N-dimensional data (2D images, 3D cubes, 4D hypercubes, etc.).
Parameters:
path(required): Path to the FITS filehdu(optional, default=0): HDU indexslices(required): Comma-separated slice ranges for each axis in NumPy order.- Format:
start:stop,start:stop,...with one range per axis - Uses Python/NumPy conventions: 0-indexed, half-open intervals
[start, stop) - Axis order matches NumPy (for 2D:
row,colory,x; for 3D:z,y,x) - Examples:
- 2D image:
slices=0:100,50:150→ rows 0-99, columns 50-149 - 3D cube:
slices=0:10,0:100,50:150→ planes 0-9, rows 0-99, columns 50-149
- 2D image:
- Format:
Response: Binary data (application/octet-stream) with headers:
X-FITS-Shape: JSON array of dimensionsX-FITS-Type: Rust-style type name (e.g.f64oru16)
Errors: Returns 400 for out-of-bounds requests or dimension mismatches
Contributing
Development Setup
Prerequisites
- Python >= 3.10
- Node.js >= 18
- JupyterLab >= 4.0.0
- Rust toolchain (for building viewarr)
Building the viewarr Viewer Component
This extension uses viewarr, a WebAssembly image viewer built with Rust and egui. It is included as a git submodule and must be built before the extension.
One-time setup:
# Install wasm-pack if not already installed
cargo install wasm-pack
# Build the WebAssembly package (from the fitsview directory)
cd viewarr
npm run build
cd ..
Rebuilding after viewarr changes:
# From the fitsview directory, use the convenience script:
jlpm rebuild:viewarr
This runs cargo clean -p viewarr && npm run build in viewarr, copies the built package to node_modules/viewarr, and rebuilds the extension.
Initial Setup
# Clone the repository with submodules
git clone --recurse-submodules <repository-url>
cd fitsview
# Or if already cloned without submodules:
git submodule update --init --recursive
# Create a virtual environment
python -m venv .venv
# Install the package in development mode with all dependencies
.venv/bin/pip install -e '.[test]'
# activate virtual environment
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Check to make sure jlpm is coming from inside the virtualenv (should end with '.venv/bin/jlpm')
which jlpm
# Install JavaScript dependencies
jlpm install
# Build the extension
jlpm build
# Link the extension to JupyterLab (creates symlink)
jupyter labextension develop . --overwrite
# Verify the labextension is 'enabled OK' and points to the .venv folder
jupyter labextension list
# Verify the server extension is enabled and coming from the .venv folder too
jupyter server extension list
Development with Auto-Rebuild
For the best development experience, run these commands in separate terminals:
Terminal 1 - Watch TypeScript changes:
source .venv/bin/activate
jlpm watch
Terminal 2 - Run JupyterLab:
source .venv/bin/activate
jupyter lab --no-browser
With this setup:
- TypeScript changes are automatically rebuilt when you save files
- Refresh your browser to see frontend changes
- Python (server extension) changes require restarting
jupyter lab
Quick Iteration Workflow
- Make changes to TypeScript files in
src/ - Wait for
jlpm watchto rebuild (watch terminal output) - Refresh your browser (Cmd+Shift+R / Ctrl+Shift+R to hard refresh)
For Python changes in fitsview/:
- Make changes to Python files
- Restart the
jupyter labprocess - Refresh your browser
Debugging
Frontend debugging:
- Open browser DevTools (F12)
- Check Console for errors and extension logs
- Use Network tab to inspect API calls to
/fitsview/
Backend debugging:
- Server logs appear in the terminal running
jupyter lab - Add
server_app.log.info("message")for custom logging - Use
--debugflag:jupyter lab --debug
Development Uninstall
# Uninstall the package
pip uninstall fitsview
# Remove the symlink (find location with `jupyter labextension list`)
# Then remove the fitsview symlink from the labextensions directory
Testing the extension
Frontend tests (TypeScript/JavaScript)
This extension uses Jest for JavaScript testing:
jlpm test
Backend tests (Python)
This extension uses pytest with pytest-jupyter for testing the server extension:
# Install test dependencies
pip install -e ".[test]"
# Run tests
python -m pytest fitsview/tests -v
# Run with coverage
python -m pytest fitsview/tests -v --cov=fitsview --cov-report=term-missing
# Run with coverage HTML report
python -m pytest fitsview/tests -v --cov=fitsview --cov-report=html
The Python tests cover:
- Metadata retrieval from FITS files
- Data slice extraction with dtype preservation
- Error handling for invalid paths, HDU indices, and out-of-bounds requests
Integration tests (End-to-End)
This extension uses Playwright with Galata for integration tests.
More information in ui-tests/README.md.
Architecture
fitsview/
├── fitsview/ # Python server extension
│ ├── __init__.py # Extension entry points
│ ├── handlers.py # REST API handlers
│ └── tests/ # Python unit tests
├── src/ # TypeScript frontend
│ ├── index.ts # Plugin registration
│ ├── widget.ts # FITS viewer widget
│ └── handler.ts # API client utilities
├── ui-tests/ # Playwright integration tests
└── jupyter-config/ # Auto-enable configuration
viewarr/ (external) # WebAssembly image viewer
├── src/ # Rust source
│ ├── app.rs # egui App with pan/zoom/render
│ ├── transform.rs # Coordinate transforms
│ └── lib.rs # WASM bindings
└── pkg/ # Built wasm-pack output
The extension uses a Content Provider pattern to prevent JupyterLab from downloading full file contents. Instead, the frontend widget makes targeted API calls to fetch only the metadata and data slices needed.
The viewarr component is a Rust/WebAssembly viewer that provides:
- Hardware-accelerated rendering via WebGL (through egui)
- Pan and zoom with mouse/trackpad
- Support for multiple data types (uint8, uint16, int16, float32, float64)
AI Coding Assistant Support
This project includes an AGENTS.md file with coding standards and best practices for JupyterLab extension development. See AGENTS.md for details.
Metadata
Release files for fitsview 0.3.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fitsview-0.3.5.tar.gz | 3.5 MB | With provenance | Details for fitsview-0.3.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fitsview-0.3.5-py3-none-any.whl | Python 3 | none | any | Details for fitsview-0.3.5-py3-none-any.whl |
Total release size: 5.1 MB
Release files / fitsview-0.3.5.tar.gz
| Download URL | fitsview-0.3.5.tar.gz |
|---|---|
| Size | 3.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f0fddb116a05e748cb77f18078e2cc7f04f52dd199704e716f9c9b9a821f688
|
|
BLAKE2b-256 checksum How to use checksums |
f65c8c66731e76265df08e5ba8a0566e79d05593e7e4ba6882417f6aaa9e0ab8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.
Transparency logRelease files / fitsview-0.3.5-py3-none-any.whl
| Download URL | fitsview-0.3.5-py3-none-any.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
773b696e184877bea73d465e517d0a31519c41011c244c96c84d94889090e874
|
|
BLAKE2b-256 checksum How to use checksums |
d978666a318d262473a7106d2bc05df859f032cb9ca9c165b00bc423dd039ffa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.
Transparency logSecurity for fitsview 0.3.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for fitsview-0.3.5.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.