Using Pyralysis#
What this guide covers#
This guide provides a practical workflow for using Pyralysis for radio astronomy imaging (also called image synthesis / image formation). You’ll learn how to load data, simulate visibilities, grid, optimize (reconstruct) an image, and save results. Pyralysis often says reconstruction or optimization for the imaging step; see Glossary.
Tip
Best practice: Start with small datasets to get familiar with the workflow, then scale up to larger data using Dask.
For pipeline workflows (SimulationPipeline, ImagerPipeline), optional local or cluster Dask setup is described in Pipelines and distributed Dask.
Note
Common mistake: Forgetting to set the correct cell size or image size for your data. Double-check these parameters!
—
Basic Workflow#
A typical workflow in Pyralysis involves:
Loading Measurement Sets
Simulating visibilities from an image (optional)
Applying gridding techniques
Imaging / reconstruction — run an optimization algorithm (or form a dirty image)
Saving the final image
Note
Want the fastest way to generate a dataset? See Creating a dataset for the minimal example.
—
Loading Measurement Sets#
Pyralysis processes radio interferometric data stored in Measurement Set (MS) format.
Under the hood, it leverages dask-ms for efficient handling of large datasets.
Example: Loading a Measurement Set
from pyralysis.io import DaskMS
# Define the path to your Measurement Set file
ms_file = "/path/to/data.ms"
# Load the dataset using Dask-MS (lazy loading enabled)
dataset = DaskMS(input_name=ms_file).read()
print("Loaded dataset structure:", dataset)
—
Simulating a Synthetic Dataset#
You can use Pyralysis to generate synthetic radio interferometric datasets for testing and benchmarking. This is useful for developing and validating imaging algorithms.
Example: Simulate an in-memory dataset (and optionally write a Measurement Set)
Note
The simulator returns a Dataset in memory. To
choose the output .ms path, pass output_name to
DaskMS and call write (not an argument on
Simulator). See Creating a dataset and I/O Operations & Data Formats.
from pyralysis.io.antenna_config_io import AntennaConfigurationIo
from pyralysis.simulation import Simulator
from pyralysis.models.sky import PointSource
from pyralysis.io import DaskMS
# 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 simple sky model (point source)
source = PointSource(reference_intensity=1.0, sky_position="12:00:00 45:00:00")
# Run the simulation (Dataset stays in memory until you write)
sim = Simulator(interferometer=interferometer, sources=source)
dataset = sim.simulate(create_dataset=True)
# Write to disk — this is where you set the Measurement Set name/path
ms_io = DaskMS(output_name="/path/to/simulated.ms")
ms_io.write(dataset=dataset, tables="ALL")
Tip
See Simulation Framework for more advanced simulation options, including Gaussian sources, composite models, and noise injection.
—
Simulating Non-Parametric Sources#
Pyralysis allows simulating non-parametric sources, meaning we compute visibilities from an image without assuming any predefined model.
Methods for estimating visibilities from an image:
Nearest Neighbor Interpolation – Fastest but least accurate.
Bilinear Interpolation – Uses linear interpolation for smoother results.
Degridding (Convolutional Gridding with a Half-Kernel) – Most accurate method.
Example: Simulating Model Visibilities
from pyralysis.estimators import NearestNeighbor, BilinearInterpolation, Degridding
from pyralysis.convolution import PSWF1
# Use Degridding (Convolutional Gridding)
kernel = PSWF1(size=3, cellsize=0.003, oversampling_factor=3)
mv_degridding = Degridding(input_data=dataset, image=image, cellsize=0.003, ckernel_object=kernel)
# Compute visibilities
mv_degridding.transform()
—
Gridding Visibilities#
Gridding is essential for transforming irregularly sampled visibilities into a uniform Fourier grid. Pyralysis provides DirtyMapper to compute a dirty image and dirty beam.
Example: Applying Gridding
from pyralysis.transformers import DirtyMapper
from pyralysis.convolution import PSWF1
# Define a convolution kernel
kernel = PSWF1(size=3, cellsize=0.003, oversampling_factor=3)
# Create a DirtyMapper object for gridding
dirty_mapper = DirtyMapper(input_data=dataset, imsize=512, cellsize=0.003, padding_factor=1.2, ckernel_object=kernel)
# Compute dirty image and dirty beam
dirty_images, dirty_beam = dirty_mapper.transform()
Both dirty_images and dirty_beam are returned as Image objects.
🔹 For more details on gridding, see Gridding Techniques in Pyralysis. For image processing and I/O operations, see Image Processing and I/O Operations & Data Formats.
—
Performing Image Reconstruction#
To reconstruct an image, Pyralysis uses gradient-based optimization techniques.
Example: Running an Optimizer
from pyralysis.optimization.optimizer import HagerZhang
from pyralysis.optimization.terms import ChiSquared, L1Norm
from pyralysis.optimization import ObjectiveFunction
# Define the objective function
term_list = [ChiSquared(model_visibility=mv, normalize=True), L1Norm(penalization_factor=0.005)]
of = ObjectiveFunction(term_list=term_list, image=image, persist_gradient=True)
# Run the optimizer
optim = HagerZhang(image=image, objective_function=of, max_iter=100)
reconstructed_image = optim.optimize()
🔹 For details on optimizers, line searchers, and seeders, see Optimizers, Line Searchers, and Step Size Seeders (overview: Optimization in Pyralysis).
—
Phase Center Shifting#
Pyralysis provides the Shifter transformer for changing the effective phase center of observations. This is essential for:
Multi-field imaging where different fields have different phase centers
Phase center corrections for proper source positioning
Wide-field imaging with non-coplanar baselines
Source positioning in visibility space
Example: Shifting Phase Center
from pyralysis.transformers import Shifter
from astropy.coordinates import SkyCoord
import astropy.units as u
# Shift to a new phase center
new_center = SkyCoord(ra=12.5*u.deg, dec=-45.2*u.deg)
shifter = Shifter(phase_center=new_center)
shifter.transform()
# Shift relative to a specific reference
ref_center = SkyCoord(ra=12.0*u.deg, dec=-45.0*u.deg)
shifter = Shifter(phase_center=new_center, reference_phase_center=ref_center)
shifter.transform()
The phase shift is applied using the full UVW coordinate system:
where \((l_0, m_0, n_0)\) are the direction cosines of the phase center offset.
Tip
The Shifter automatically handles visibility-like columns (DATA, MODEL_DATA,
CORRECTED_DATA, RESIDUAL_DATA, and other *_DATA columns) and updates
both the visibility data and field phase center information.
—
Saving Reconstructed Images#
Pyralysis provides I/O handlers to save reconstructed images.
Example: Saving Images in FITS or Zarr Format
from pyralysis.io import FITS, ZarrArray
ioh_fits = FITS() # FITS format
ioh_zarr = ZarrArray() # Zarr format
# Use the chosen I/O handler when running the optimizer
optim = HagerZhang(image=image, objective_function=of, max_iter=100, io_handler=ioh_fits)
🔹 For details on I/O handlers, see pyralysis.
—
Next Steps#
Now that you’ve seen the basic usage of Pyralysis, explore the advanced topics:
Gridding techniques: Gridding Techniques in Pyralysis
Optimization methods: Optimization in Pyralysis
API reference:
pyralysis