Metadata-Version: 2.4
Name: pyralysis
Version: 2.1.0
Summary: PYthon Radio Astronomy anaLYSis and Image Synthesis
Author-email: Miguel Cárcamo <miguel.carcamo@usach.cl>
Maintainer-email: Miguel Cárcamo <miguel.carcamo@usach.cl>
License-Expression: GPL-3.0-only
Project-URL: Documentation, https://pyralysis.readthedocs.io/
Project-URL: Issues, https://gitlab.com/clirai/pyralysis/-/issues
Project-URL: Repository, https://gitlab.com/clirai/pyralysis
Project-URL: Source, https://gitlab.com/clirai/pyralysis
Keywords: radio,radio-interferometry,interferometry,radioastronomy,imaging,deconvolution,calibration,CASA,ALMA,SKA,visibility,synthesis,python,astronomy,science,data-analysis,signal-processing,high-performance-computing,simulation,image-reconstruction,radio-telescope,big data,big-data,big computing,compressed sensing,gridding,optimization
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Requires-Python: <3.13,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: astropy==6.1.0
Requires-Dist: autopep8==2.2.0
Requires-Dist: dafits==2.0.0
Requires-Dist: dask==2024.10.0
Requires-Dist: dask-ms[complete]>=0.2.29
Requires-Dist: distributed==2024.10.0
Requires-Dist: matplotlib==3.10.8
Requires-Dist: more-itertools==10.2.0
Requires-Dist: multimethod==1.11.2
Requires-Dist: numba>=0.59.1
Requires-Dist: numcodecs==0.15.1
Requires-Dist: numpy<3.0.0,>=2.0.0
Requires-Dist: psutil==6.1.1
Requires-Dist: python-casacore==3.7.1
Requires-Dist: radio-beam==0.3.7
Requires-Dist: scipy==1.15.0
Requires-Dist: ska-ost-array-config==4.5.0
Requires-Dist: snakeviz==2.2.0
Requires-Dist: spectral-cube==0.6.5
Requires-Dist: xarray==2024.9
Provides-Extra: all
Requires-Dist: pyfftw; extra == "all"
Requires-Dist: cmcrameri; extra == "all"
Requires-Dist: ipykernel; extra == "all"
Requires-Dist: seaborn; extra == "all"
Requires-Dist: six==1.17.0; extra == "all"
Requires-Dist: pytest==9.0.2; extra == "all"
Requires-Dist: pytest-cov==7.1.0; extra == "all"
Requires-Dist: pytest-xdist==3.8.0; extra == "all"
Provides-Extra: cupy
Requires-Dist: cupy-cuda13x<15,>=14.0; extra == "cupy"
Provides-Extra: cupy12
Requires-Dist: cupy-cuda12x<15,>=13.2; extra == "cupy12"
Provides-Extra: cupy13
Requires-Dist: cupy-cuda13x<15,>=14.0; extra == "cupy13"
Provides-Extra: dev
Requires-Dist: tox>=4.21.0; extra == "dev"
Provides-Extra: notebook
Requires-Dist: cmcrameri; extra == "notebook"
Requires-Dist: ipykernel; extra == "notebook"
Requires-Dist: seaborn; extra == "notebook"
Provides-Extra: pyfftw
Requires-Dist: pyfftw; extra == "pyfftw"
Provides-Extra: slurm
Requires-Dist: dask-jobqueue>=0.9.0; extra == "slurm"
Provides-Extra: test
Requires-Dist: six==1.17.0; extra == "test"
Requires-Dist: pytest==9.0.2; extra == "test"
Requires-Dist: pytest-cov==7.1.0; extra == "test"
Requires-Dist: pytest-xdist==3.8.0; extra == "test"
Dynamic: license-file

<div align="center">

<img src="https://gitlab.com/miguelcarcamov/pyralysis/-/wikis/uploads/fd40975ce0601b5c52a3cf8b92f385a5/Pyralisis-25.png" height="280" alt="Pyralysis logo">

# Pyralysis

**PYthon Radio Astronomy anaLYSis and Image Synthesis**

*Simulate, optimize, and reconstruct — with a Python toolkit built for modern interferometry.*

<br>

<!-- Status & quality (RTD/pre-commit URLs match legacy README badge assets) -->
[![Pipeline Status](https://gitlab.com/clirai/pyralysis/badges/development/pipeline.svg)](https://gitlab.com/clirai/pyralysis/-/pipelines?ref=development)
[![codecov](https://codecov.io/gl/clirai/pyralysis/branch/development/graph/badge.svg?token=MVFAA1YKC7)](https://codecov.io/gl/clirai/pyralysis)
[![Documentation Status](https://readthedocs.org/projects/pyralysis/badge/)](https://pyralysis.readthedocs.io/)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
[![License](https://img.shields.io/static/v1?label=License&message=GPL-3.0-only&color=blue&labelColor=1a1a2e)](https://www.gnu.org/licenses/gpl-3.0)

<br>

<!-- Distribution & discoverability (PyPI badge image URLs match legacy README) -->
[![PyPI Version](https://img.shields.io/pypi/v/pyralysis)](https://pypi.org/project/pyralysis)
[![Python Version](https://img.shields.io/badge/python-3.11%20|%203.12-blue)](https://www.python.org/)
[![PyPI Wheel](https://img.shields.io/pypi/wheel/pyralysis)](https://pypi.org/project/pyralysis/#files)
[![PyPI Downloads](https://img.shields.io/pypi/dm/pyralysis)](https://pypi.org/project/pyralysis/)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gl/clirai%2Fpyralysis/release?urlpath=lab%2Ftree%2Fexamples%2Fnotebooks)

<br>

<!-- Community (GitLab) -->
[![GitLab stars](https://img.shields.io/gitlab/stars/clirai%2Fpyralysis?logo=gitlab&label=stars)](https://gitlab.com/clirai/pyralysis/-/starrers)
[![GitLab forks](https://img.shields.io/gitlab/forks/clirai%2Fpyralysis?logo=gitlab&label=forks)](https://gitlab.com/clirai/pyralysis/-/forks)
[![GitLab open issues](https://img.shields.io/gitlab/issues/open/clirai%2Fpyralysis?logo=gitlab&label=issues)](https://gitlab.com/clirai/pyralysis/-/issues)
[![GitLab merge requests](https://img.shields.io/gitlab/merge-requests/open/clirai%2Fpyralysis?logo=gitlab&label=MRs)](https://gitlab.com/clirai/pyralysis/-/merge_requests)
[![Docker](https://img.shields.io/badge/Docker-2496ED?logo=docker&logoColor=fff)](https://gitlab.com/clirai/pyralysis/container_registry)

<br>

<!-- Core stack (libraries this project is built around) -->
[![Dask](https://img.shields.io/badge/Dask-FFC107?logo=dask&logoColor=1a1a2e)](https://www.dask.org/)
[![Xarray](https://img.shields.io/badge/Xarray-013243?logo=xarray&logoColor=white)](https://xarray.dev/)
[![NumPy](https://img.shields.io/badge/NumPy-4DABCF?logo=numpy&logoColor=white)](https://numpy.org/)
[![Astropy](https://img.shields.io/badge/Astropy-FF6B00?logo=astropy&logoColor=white)](https://www.astropy.org/)
[![Numba](https://img.shields.io/badge/Numba-00A3E0?logo=llvm&logoColor=white)](https://numba.pydata.org/)
[![SciPy](https://img.shields.io/badge/SciPy-8CAAE6?logo=scipy&logoColor=white)](https://scipy.org/)

<br>

<!-- Developer workflow -->
[![pytest](https://img.shields.io/badge/pytest-tested-0A9EDC?logo=pytest&logoColor=white)](https://pytest.org/)
[![yapf](https://img.shields.io/badge/code%20style-yapf-222222)](https://github.com/google/yapf)
[![isort](https://img.shields.io/badge/imports-isort-ef8336)](https://pycqa.github.io/isort/)
[![Commitizen](https://img.shields.io/badge/commits-Commitizen-ff69b4?logo=conventionalcommits&logoColor=white)](https://github.com/commitizen-tools/commitizen)
[![Read the Docs](https://img.shields.io/badge/Read%20the%20Docs-8CA1AF?logo=readthedocs&logoColor=fff)](https://pyralysis.readthedocs.io/)
[![ReadMe](https://img.shields.io/badge/ReadMe-018EF5?logo=readme&logoColor=fff)](https://gitlab.com/clirai/pyralysis/-/blob/release/README.md)

</div>

---

## Why Pyralysis?

Whether you are **prototyping a simulation**, **studying optimization for imaging**, or **pipelining large visibility sets**, Pyralysis aims to meet you where you work: clear APIs, lazy evaluation where it matters, and documentation you can actually read.

- **Interferometric imaging and simulation** in one coherent library.
- **Dask-friendly** workflows for scaling from a laptop to a cluster (including optional SLURM-backed workers).
- **Documented** user guides, API reference, and runnable examples — try them locally, on **Binder**, or from a full install (see below).

If you prefer to dive straight in, open the **[documentation on Read the Docs](https://pyralysis.readthedocs.io/)**.

---

<a id="binder"></a>

## Try Pyralysis in your browser (Binder)

[**Binder**](https://mybinder.org) builds a short-lived JupyterLab session with Pyralysis checked out from the **`release`** branch, so you can run the project **without installing anything** on your machine. After the environment starts, open the file browser and work through the notebooks under **`examples/notebooks/`** — small simulations, toy datasets, and walkthroughs that mirror the written guides.

Binder is ideal when you want to **peek at the API**, **follow a tutorial cell by cell**, or **share a reproducible link** with a colleague. Sessions run on shared infrastructure with finite RAM and CPU, and the image tracks the **`release`** branch (not every commit on `development`), so treat it as **exploration and teaching**, not a substitute for HPC or production-scale imaging. For install paths, SLURM-backed Dask, and heavier workflows, use a local or cluster environment (see **Install** below) and the [repository examples](https://pyralysis.readthedocs.io/examples.html) page on Read the Docs.

**Launch:** [Open Pyralysis on Binder](https://mybinder.org/v2/gl/clirai%2Fpyralysis/release?urlpath=lab%2Ftree%2Fexamples%2Fnotebooks) (same target as the Binder badge above).

---

## Install in three steps

Stable releases live on **[PyPI](https://pypi.org/project/pyralysis/)** (pin `pyralysis==X.Y.Z` when you need a reproducible version).
For commits that are not yet released, install from GitLab (see the installation guide).

1. **Create a Python environment** (Python 3.11–3.12; `requires-python` is `>=3.11,<3.13`).
   Use `conda`, `mamba`, `micromamba`, or plain `venv` — whatever fits your stack.

2. **Install from PyPI using the SKA extra index** (needed so pip can resolve some dependencies).

```bash
pip install --extra-index-url https://artefact.skao.int/repository/pypi-internal/simple pyralysis[all]
```

This pulls the **latest published** release plus common optional pieces (FFT helpers, notebooks, tests). For **GPU**, prefer `micromamba create -f environment_cuda13.yml` (conda CUDA + CuPy, then `pip install -e .`); Pascal: `environment_cuda12.yml`. Pip-only CuPy wheels: `pyralysis[cupy13]` or `[cupy12]` — see the [installation guide](https://pyralysis.readthedocs.io/installation.html).
For **SLURM**-backed Dask workers (`dask-jobqueue`, used when `SetupDaskCluster` uses `dask_cluster_backend="slurm"`), add `pyralysis[slurm]` (see [Optional: SLURM](https://pyralysis.readthedocs.io/installation.html#optional-slurm)).

Simulation and imaging **pipelines** can attach a local cluster, SLURM, or an existing Dask `Client` via context configuration — see [Pipelines and distributed Dask](https://pyralysis.readthedocs.io/pipelines_distributed.html).

For editable installs, conda environment files, or Docker images:

- **[Installation guide](https://pyralysis.readthedocs.io/installation.html)**

Want to explore first without pip? Use **[Binder](#binder)** above.

### GPU imaging (optional)

With a CUDA-capable environment (`environment_cuda13.yml` / `environment_cuda12.yml`, or `pyralysis[cupy13]`), you can keep the **same imaging APIs** while visibilities live on **CuPy-backed Dask** collections:

```python
from pyralysis.io import DaskMS

dataset = DaskMS("observation.ms").read(
    array_backend="cupy",
    calculate_psf=True,
)
dataset.calculate_theoretical_noise(per_field=True, per_spw=True)
# Forward model, Mask(dataset=...), ObjectiveFunction, optimizers — same as CPU.
```

The pipeline **follows the measurement set**: a CPU image is promoted to GPU during `transform()` / gradients. **Simulation** on GPU is not supported yet — simulate on CPU, then `with_array_backend(..., "cupy")` if needed.

- **Guide:** [Array backends](https://pyralysis.readthedocs.io/array_backend.html)
- **Notebook:** `examples/notebooks/optimization_sandbox_gpu.ipynb` (masked χ² + LBFGS on a real MS)

---

## Minimal example

Simulate a small dataset and add thermal noise:

```python
from pyralysis.io.antenna_config_io import AntennaConfigurationIo
from pyralysis.simulation import Simulator
from pyralysis.models.sky import PointSource
from pyralysis.injectors import ThermalNoiseInjector

# Load array configuration
interferometer = AntennaConfigurationIo(input_name="path/to/array.cfg").read()
interferometer.configure_observation(
    min_frequency_hz=1e9, max_frequency_hz=1.1e9, frequency_step_hz=1e7,
    right_ascension="12:00:00", declination="45:00:00",
    integration_time=10, observation_time="1h"
)

# Define a source and simulate
source = PointSource(
    reference_intensity=1.0,
    sky_position="12:00:00 45:00:00",
    reference_frequency=1e9,
)
sim = Simulator(interferometer=interferometer, sources=source)
dataset = sim.simulate(create_dataset=True)

# Add thermal noise
thermal = ThermalNoiseInjector(system_temperature=50, integration_time=10, channel_bandwidth=1e6)
noisy_dataset = thermal.apply(dataset)
```

More simulation patterns (arrays, sky models, injectors, I/O):

- **[Simulation guide](https://pyralysis.readthedocs.io/simulation.html)**

### Reconstruction example

Reconstruct an image from visibilities with an objective and L-BFGS:

```python
from pyralysis.reconstruction import Image
from pyralysis.optimization import ObjectiveFunction
from pyralysis.optimization.terms import ChiSquared, L1Norm
from pyralysis.optimization.optimizer import LBFGS
from pyralysis.measurement import ModelVisibility

# Create initial image (e.g. empty sky model)
image = Image.empty(imsize=(512, 512), cellsize=0.001)  # adjust to your case

# Build model visibility from dataset and image
model_visibility = ModelVisibility(dataset=noisy_dataset, image=image)

# Objective: data fidelity + simple L1 regularization
terms = [
    ChiSquared(model_visibility=model_visibility, penalization_factor=1.0),
    L1Norm(penalization_factor=0.01),
]
objective = ObjectiveFunction(term_list=terms, image=image, persist_gradient=True)

optimizer = LBFGS(objective_function=objective, parameter=image)
reconstructed_image = optimizer.optimize()
```

Deeper reading:

- **[Optimization](https://pyralysis.readthedocs.io/optimization.html)**
- **[Measurement operator](https://pyralysis.readthedocs.io/measurement_operator.html)**

---

## Examples in this repository

| Location | What you will find |
|----------|-------------------|
| `examples/notebooks/` | Jupyter notebooks (CPU and GPU optimization sandboxes) |
| `examples/notebooks/optimization_sandbox_gpu.ipynb` | CuPy MS read, mask, and masked optimization on HD142527 |
| `examples/scripts/*_components.py` | Explicit class composition |
| `examples/scripts/*_pipeline.py` | Pipeline-style orchestration |

Paired scripts include `dirtymapper`, `optimization`, and `simulation` (components vs pipeline variants).

- **[Repository examples](https://pyralysis.readthedocs.io/examples.html)**

---

## Learn more

| Topic | Link |
|-------|------|
| User guide and tutorials | [pyralysis.readthedocs.io](https://pyralysis.readthedocs.io/) |
| NumPy / CuPy array backends (GPU imaging) | [array_backend](https://pyralysis.readthedocs.io/array_backend.html) |
| Binder (JupyterLab, no install) | [Launch Binder](https://mybinder.org/v2/gl/clirai%2Fpyralysis/release?urlpath=lab%2Ftree%2Fexamples%2Fnotebooks) |
| Pipelines and distributed Dask | [pipelines_distributed](https://pyralysis.readthedocs.io/pipelines_distributed.html) |
| API reference | [api/index](https://pyralysis.readthedocs.io/api/index.html) |
| Data model and measurement operator | [data_model](https://pyralysis.readthedocs.io/data_model.html) |
| Versioning policy | [versioning](https://pyralysis.readthedocs.io/versioning.html) |

---

## Contributing and development

| Resource | Link |
|----------|------|
| Contribution guide | [CONTRIBUTING.md](CONTRIBUTING.md) |
| Changelog | [CHANGELOG.md](CHANGELOG.md) |
| New issue | [Open an issue](https://gitlab.com/clirai/pyralysis/-/issues/new) |
| Issue tracker | [GitLab issues](https://gitlab.com/clirai/pyralysis/-/issues) |
| Testing and QA | [Testing docs](https://pyralysis.readthedocs.io/testing.html) |
| Versioning and releases | [Versioning](https://pyralysis.readthedocs.io/versioning.html) |

Pull requests and bug reports are welcome. If you are unsure where to start, open an issue and we can point you to the right part of the codebase.

---

## Citation and license

If Pyralysis supports your research, a citation is appreciated:

```bibtex
@software{carcamo2021pyralysis,
  author = {Miguel Cárcamo},
  title = {Pyralysis: A Python framework for radio interferometric imaging and simulation},
  year = {2021},
  url = {https://gitlab.com/clirai/pyralysis},
  note = {https://pyralysis.readthedocs.io/}
}
```

Pyralysis is distributed under the **GNU General Public License v3.0**; see the `LICENSE` file in this repository.

---

## Contact

- **Documentation:** [pyralysis.readthedocs.io](https://pyralysis.readthedocs.io/)
- **Issues:** [gitlab.com/clirai/pyralysis/-/issues](https://gitlab.com/clirai/pyralysis/-/issues)
- **Lead developer:** [miguel.carcamo@usach.cl](mailto:miguel.carcamo@usach.cl)
