Regularized image reconstruction for radio interferometry — simulate an array, state χ² + regularizers, reconstruct on CPU or GPU. Not a black-box CLEAN.
Pyralysis is a Python library (Dask, optional CuPy) for simulation, gridding, and image reconstruction. You compose the objective; there is no hidden imager. It complements CASA / WSClean (CLEAN-style imaging) and tools like ehtim (VLBI RML): here the focus is composable χ² + regularizers at array / cluster scale.
Who it’s for. Researchers who want an explicit objective and GPU or Dask scaling —
not a drop-in tclean.
I/O & arrays. Measurement Set · FITS · Zarr · bundled VLA/ALMA configs · natural / uniform / robust weights · closure phase & amplitude · CPU or CuPy.
Guides: Read the Docs · website: clirai.gitlab.io. If you use Pyralysis in a paper, please cite it.
You can
Simulate an observation
VLA, ALMA, or a custom antenna config; parametric or FITS sky models; thermal noise and gain injectors.
ALMA C-9, Band 6 (230 GHz), 2 h with thermal noise: a protoplanetary disk (Planck brightness, T ∝ r−1/2, optically thick core, gaps and rings) built from 80 DiskSource rings, plus three background sources — sky, uv coverage, and the real part of the visibilities against deprojected uv distance.
Simulation ·
examples/scripts/simulation_components.py
Make a dirty map and PSF
Natural, uniform, or robust weights, then a dirty image and dirty beam.
Visibility weights ·
Gridding ·
examples/scripts/dirtymapper_components.py
Reconstruct a model
State χ² plus L1, TSV, or other regularizers; solve with FISTA, L-BFGS, or SDMM. The figures below are MFISTA (monotone FISTA) on χ² + L1 from zeros, natural weights, on the GPU (CuPy).
Dirty image → MFISTA reconstruction (Jy/pixel) → residual. Same ALMA disk simulation as above; square-root stretch.
MFISTA (monotone FISTA) iterates from a zero start.
Regenerate the gallery with python docs/scripts/generate_readme_figures.py.
Optimization ·
FISTA ·
examples/scripts/optimization_components.py
Image with closures, on GPU, or on a cluster
Closure-phase / closure-amplitude terms; the same stack on CuPy or a Dask cluster; read and write Measurement Sets, Zarr, and FITS.
Closures · Array backends · Pipelines · I/O
Notebooks without installing: Binder. How the pieces fit together: composability, flexibility, extensibility, adaptability.
Install
Python 3.11–3.13. The SKA extra index is required for a few dependencies.
pip install --extra-index-url https://artefact.skao.int/repository/pypi-internal/simple pyralysis[all]
GPU: micromamba create -f envs/cuda13.yml (Maxwell/Pascal/Volta: envs/cuda12.yml, Kepler: envs/cuda11.yml; see envs/README.md). Details: installation.
Minimal example
Simulate a 1 Jy point source at phase center, add thermal noise, natural-weight, and
form a dirty image. With geometry matched to the array (cellsize ≈ beam/3.5), the
dirty peak is ≈ 1 Jy/beam.
from importlib.resources import files
from astropy import units as u
from pyralysis.io.antenna_config_io import AntennaConfigurationIo
from pyralysis.simulation import Simulator
from pyralysis.models.sky import PointSource
from pyralysis.injectors import ThermalNoiseInjector
from pyralysis.transformers.weighting_schemes import Natural
from pyralysis.transformers import DirtyMapper
# Bundled VLA-C antenna table (same idea as a CASA .cfg)
cfg = files("pyralysis.simulation") / "antenna_configs" / "vla.c.cfg"
interferometer = AntennaConfigurationIo(input_name=str(cfg)).read()
# Pointing, band, and dump time for a short continuum observation
interferometer.configure_observation(
min_frequency=1e9 * u.Hz, max_frequency=1.1e9 * u.Hz, frequency_step=1e7 * u.Hz,
right_ascension="12h00m00s", declination="45d00m00s",
integration_time=10 * u.s, observation_time="1h",
)
# Unresolved source on-axis; intensity in Jy at the reference frequency
source = PointSource(
reference_intensity=1.0 * u.Jy, sky_position="12h00m00s 45d00m00s",
reference_frequency=1e9 * u.Hz,
)
# Visibilities → in-memory Dataset (Measurement Set–like); then SEFD-style noise
dataset = Simulator(interferometer=interferometer, sources=source).simulate(create_dataset=True)
dataset = ThermalNoiseInjector(system_temperature=50, integration_time=10, channel_bandwidth=1e6).apply(dataset)
# Pixel scale from theoretical resolution (~synthesized beam / 3.5)
imsize, cellsize = 128, dataset.theo_resolution / 3.5
Natural(imsize=imsize, cellsize=cellsize, input_data=dataset).transform() # imaging weights
dataset.calculate_psf() # dirty beam / PSF for the weighted uv coverage
dirty, _beam = DirtyMapper(
input_data=dataset, imsize=imsize, cellsize=cellsize, stokes=["I"]
).transform() # dirty image (Jy/beam) and beam; peak ≈ 1 for this setup
Reconstruction (χ² + L1, FISTA, GPU) is the same composition as the figures — optimization, quickstart.
Citation
Please cite the software (DOI — all versions) and, when relevant, the overview paper:
Cárcamo et al., URSI GASS 2026 — Pyralysis: An Open-Source Framework for Big Data Radio Interferometry.
@software{carcamo2021pyralysis,
author = {Cárcamo, Miguel and Guidotti, Valeria and Casassus, Simon
and Rannou, Fernando and Román, Pablo},
title = {Pyralysis},
year = {2026},
publisher = {Zenodo},
version = {3.1.0},
doi = {10.5281/zenodo.23541172},
url = {https://doi.org/10.5281/zenodo.23541172}
}
Stars, forks, and download charts live on the project activity page.
Links
Docs · API · Examples · Website · Contributing · Changelog · Issues
GPL-3.0-only — see LICENSE. Contact: miguel.carcamo@usach.cl
Metadata
Release files for pyralysis 3.2.0
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 | |
|---|---|---|---|---|
| pyralysis-3.2.0.tar.gz | 18.7 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyralysis-3.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.1 MB
Release files / pyralysis-3.2.0.tar.gz
| Download URL | pyralysis-3.2.0.tar.gz |
|---|---|
| Size | 18.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
af40f78d61e22cd374d7d4d7aa0c8022a7910cc78348168fbef1d5483e0ee5c2
|
|
BLAKE2b-256 checksum How to use checksums |
937509b3316507365dfeca924e268aa5e7f027b567f9bc41ccbb4c8924db961e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / pyralysis-3.2.0-py3-none-any.whl
| Download URL | pyralysis-3.2.0-py3-none-any.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f3929665a8721f281b1d0cd98b3b665fd0d3b1175ae1764bbeeb01952e01dc3
|
|
BLAKE2b-256 checksum How to use checksums |
c0cfe628678831a392ca6ca6da6e11adc46e55ea6cbb94e66bbd3734a8cf26cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Security for pyralysis 3.2.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.