argosim.imaging_utils module#

Imaging utils.

This module contains functions to perform radio interferometric imaging.

The production forward model uses Kaiser-Bessel (KB) convolutional gridding (simulate_dirty_observation()). A legacy nearest-neighbour (NN) binary-mask path is kept at the bottom of the module for the GUI and for teaching; see the “Legacy / educational” section there.

Authors:

Ezequiel Centofanti <ezequiel.centofanti@cea.fr> Samuel Gullin <gullin@ia.forth.gr>

argosim.imaging_utils.add_noise_vis(vis, sigma=0.1, seed=None)[source]#

Add independent complex Gaussian noise to ungridded visibilities.

Adds independent complex noise to each visibility datum. Real and imaginary parts are each drawn from N(0, sigma/sqrt(2)) so that the total noise power per visibility is sigma^2. This prepares for the proper per-baseline noise model (radiometer equation) to be integrated later.

Parameters:
  • vis (np.ndarray) – Complex visibility values, shape (n_vis,).

  • sigma (float) – Standard deviation of the complex noise.

  • seed (int) – Optional seed for reproducibility.

Returns:

vis_noisy – Visibilities with added noise.

Return type:

np.ndarray

argosim.imaging_utils.check_uv_in_grid(uv_px, grid_shape, fov_size, on_out_of_bounds='warn')[source]#

Check that UV samples fall inside the uv grid.

Convolutional gridding silently drops any visibility whose target pixel falls outside the grid (grid_visibilities_conv uses mode="drop"), so a grid too small for the longest baselines quietly loses data. This function flags that case, using the continuous pixel coordinates returned by scale_uv_samples_continuous: a sample is out of the grid when its pixel coordinate is < 0 or > grid_shape along either axis.

The message therefore reports the largest field of view that keeps every sample on the grid for the chosen Npix and uv coverage.

Parameters:
  • uv_px (jnp.ndarray) – Continuous pixel coordinates (u, v) for each visibility, shape (n_vis, 2), as returned by scale_uv_samples_continuous.

  • grid_shape (tuple) – Shape of the uv grid (ny, nx).

  • fov_size (float or tuple) – Field of view in degrees corresponding to uv_px / grid_shape. A scalar is applied to both axes; a tuple is read as (fov_y, fov_x). Used to report the maximum field of view that keeps all samples on-grid.

  • on_out_of_bounds ({"warn", "error", "ignore"}) – Action when one or more samples fall outside the grid: "warn" (default) emits a UserWarning reporting the proportion of dropped samples, "error" raises a ValueError, and "ignore" returns silently (samples are still dropped downstream).

Raises:

ValueError – If on_out_of_bounds is not one of the accepted options, or if it is "error" and any sample falls outside the grid.

argosim.imaging_utils.check_uv_samples_range(uv_samples_indices, uv_samples, sky_uv_shape, fov_size)[source]#

Check uv samples range.

Function to check if the uv samples are within the uv-plane range.

Parameters:
  • uv_samples_indices (np.ndarray) – The indices of the uv samples in pixel coordinates.

  • sky_uv_shape (tuple) – The shape of the sky model in pixels.

  • uv_samples (np.ndarray) – The uv samples coordinates in meters.

  • fov_size (float or tuple) – The field of view size in degrees, scalar or (fov_y, fov_x).

argosim.imaging_utils.compute_visibilities_grid(sky_uv, uv_mask)[source]#

Compute visibilities gridded.

Function to compute the visibilities from the fourier sky and the uv sampling mask.

Parameters:
  • sky_uv (np.ndarray) – The sky model in Fourier/uv domain.

  • uv_mask (np.ndarray) – The uv sampling mask.

Returns:

visibilities – Gridded visibilities on the uv-plane.

Return type:

np.ndarray

argosim.imaging_utils.degrid_visibilities_conv(sky_uv, uv_px, grid_shape, W, beta)[source]#

Convolutional degridding with Kaiser-Bessel anti-aliasing kernel (JAX).

Interpolates complex visibility values from a gridded sky model at the given UV positions. This is the adjoint of grid_visibilities_conv(). Differentiable w.r.t. sky_uv.

Parameters:
  • sky_uv (jnp.ndarray) – Gridded sky model in UV domain, shape grid_shape, complex.

  • uv_px (jnp.ndarray) – Continuous pixel coordinates (u, v) for each visibility, shape (n_vis, 2).

  • grid_shape (tuple of int) – Shape of sky_uv (ny, nx). Must be a static argument.

  • W (int) – Kernel support width in pixels (odd). Must be a static argument.

  • beta (float) – KB shape parameter. Must be a static argument.

Returns:

vis – Interpolated complex visibilities, shape (n_vis,). Contributions from out-of-bounds grid points are clipped to the nearest edge pixel.

Return type:

jnp.ndarray

argosim.imaging_utils.grid_sampling_function(track, fov_size, npix, method='kb', kernel_support=7, beta=None, oversampling=2, weighting='natural')[source]#

Grid the unit sampling function and return the uv plane and dirty beam.

GUI helper. Grids unit visibilities (ones) at the uv sample positions to build the gridded sampling function, whose inverse Fourier transform is the dirty beam (impulse response). Supports the two gridding schemes offered in the GUI:

Parameters:
  • track (np.ndarray) – The uv sampling points, shape (n_vis, 3).

  • fov_size (float or tuple) – Field of view in degrees, scalar or (fov_y, fov_x).

  • npix (int) – Number of pixels per side of the native image / uv grid.

  • method ({"kb", "nn"}) – Gridding scheme.

  • kernel_support (int) – KB kernel support width in pixels (odd). Only used for method="kb".

  • beta (float, optional) – KB shape parameter. If None, uses 2.34 * kernel_support.

  • oversampling (float) – UV-grid oversampling factor for method="kb".

  • weighting ({"natural", "uniform"}) – Visibility weighting (see _visibility_weights()). For NN it selects the mask (natural -> histogram, uniform -> binary).

Returns:

  • uv_grid (jnp.ndarray) – The gridded sampling function on the uv plane. Shape (npix, npix) for NN, or the oversampled (n_os, n_os) for KB.

  • dirty_beam (jnp.ndarray) – The dirty beam (impulse response), shape (npix, npix).

argosim.imaging_utils.grid_uv_samples(uv_samples, sky_uv_shape, fov_size, mask_type='binary')[source]#

Grid uv samples.

Compute the uv sampling mask from the uv samples.

Parameters:
  • uv_samples (np.ndarray) – The uv samples coordinates in meters.

  • sky_uv_shape (tuple) – The shape of the sky model in pixels.

  • fov_size (tuple) – The field of view size in degrees.

  • mask_type (str) – The type of mask to use. Choose between ‘binary’ and ‘histogram’.

Returns:

  • uv_mask (np.ndarray) – The uv sampling mask.

  • uv_samples_indices (np.ndarray) – The indices of the uv samples in pixel coordinates.

argosim.imaging_utils.grid_visibilities_conv(vis, uv_px, grid_shape, W, beta)[source]#

Convolutional gridding with Kaiser-Bessel anti-aliasing kernel (JAX).

Distributes complex visibility values onto a regular grid using a Kaiser-Bessel convolution kernel. The Python loop over the W x W kernel support is unrolled by JAX at JIT-compile time, so the compiled kernel is fully vectorised over all visibilities. Differentiable w.r.t. vis.

Parameters:
  • vis (jnp.ndarray) – Complex visibility values to grid, shape (n_vis,).

  • uv_px (jnp.ndarray) – Continuous pixel coordinates (u, v) for each visibility, shape (n_vis, 2).

  • grid_shape (tuple of int) – Shape of the output grid (ny, nx). Must be a static argument.

  • W (int) – Kernel support width in pixels (odd). Must be a static argument. Typically W = 7.

  • beta (float) – KB shape parameter. Must be a static argument. Typically beta = 2.34 * W.

Returns:

grid – Gridded visibilities, shape grid_shape, complex dtype (complex64 by default, complex128 if JAX x64 is enabled). Out-of-bounds contributions are silently dropped.

Return type:

jnp.ndarray

argosim.imaging_utils.kaiser_bessel(x, W, beta)[source]#

Kaiser-Bessel anti-aliasing kernel.

Evaluates the Kaiser-Bessel window function used as a gridding convolution kernel to suppress aliasing artefacts from non-uniform sampling.

Parameters:
  • x (jnp.ndarray) – Offset from the kernel centre in pixels.

  • W (int) – Kernel support width in pixels (number of pixels the kernel spans).

  • beta (float) – Shape parameter controlling the trade-off between main-lobe width and side-lobe suppression. A standard choice is beta = 2.34 * W.

Returns:

Kaiser-Bessel kernel values at x. Evaluates to zero outside [-W/2, W/2] by the clip operation on the argument.

Return type:

jnp.ndarray

Notes

The epsilon inside the square root keeps its argument strictly positive. Without it sqrt has an infinite derivative at arg == 0 (the support edge |x| = W/2, always hit by the gridding stencil), giving a NaN gradient in single precision. The value change is negligible (~1e-12).

argosim.imaging_utils.kb_correction(grid_shape, W, beta)[source]#

Image-domain correction for Kaiser-Bessel convolutional gridding.

Computes the 2D correction image C(l, m) such that multiplying the dirty image by C compensates for the amplitude taper introduced by the KB convolution kernel. The correction is separable: C(l, m) = C_1d(l) * C_1d(m), where C_1d is the reciprocal of the discrete Fourier transform of the 1D KB kernel.

Parameters:
  • grid_shape (tuple) – Shape of the grid (ny, nx).

  • W (int) – Kernel support width in pixels.

  • beta (float) – KB shape parameter.

Returns:

correction – 2D image-domain correction array, shape grid_shape.

Return type:

jnp.ndarray

argosim.imaging_utils.scale_uv_samples(uv_samples, sky_uv_shape, fov_size)[source]#

Scale uv samples to nearest integer pixel coordinates (NN snap).

Function to scale the uv samples to pixel coordinates, rounding to the nearest cell.

Parameters:
  • uv_samples (np.ndarray) – The uv samples coordinates in meters.

  • sky_uv_shape (tuple) – The shape of the sky model in pixels.

  • fov_size (float or tuple) – The field of view size in degrees, scalar or (fov_y, fov_x).

Returns:

uv_samples_indices – The indices of the uv samples in pixel coordinates.

Return type:

np.ndarray

argosim.imaging_utils.scale_uv_samples_continuous(uv_samples, sky_uv_shape, fov_size)[source]#

Scale UV samples to continuous pixel coordinates.

Returns floating-point (non-rounded) pixel positions, required for sub-pixel-accurate convolutional gridding.

Parameters:
  • uv_samples (jnp.ndarray) – UV samples in wavelengths, shape (n_vis, 3).

  • sky_uv_shape (tuple) – Shape of the UV grid (ny, nx).

  • fov_size (float or tuple) – Field of view in degrees, scalar or (fov_y, fov_x).

Returns:

uv_px – Continuous pixel coordinates (u, v) for each visibility, shape (n_vis, 2).

Return type:

jnp.ndarray

argosim.imaging_utils.simulate_dirty_observation(sky, track, fov_size, multi_band=False, freqs=None, beam=None, sigma=0.2, seed=None, kernel_support=7, beta=None, oversampling=2, on_out_of_bounds='warn', weighting='natural')[source]#

Simulate dirty observation.

Function to simulate a radio observation of the sky model from the track uv-samples using convolutional gridding with a Kaiser-Bessel anti-aliasing kernel. The forward model is: degrid true visibilities from the sky FFT, add per-visibility complex Gaussian noise, re-grid with the KB kernel, and apply the image-domain correction.

Parameters:
  • sky (np.ndarray) – The sky model image.

  • track (np.ndarray) – The uv sampling points.

  • fov_size (float) – The field of view size in degrees.

  • multi_band (bool) – If True, simulate a multi-band observation.

  • freqs (list) – The frequency list for the multi-band simulation.

  • beam (Beam) – The beam object to apply to the sky, only used in multi-band simulations.

  • sigma (float) – Standard deviation of the complex Gaussian noise added independently to each visibility (radiometer-style), in sky/flux units. The dirty image is normalised so a point source of flux S peaks at S (Jy/beam), so the image noise scales roughly as sigma / sqrt(n_vis).

  • seed (int) – Optional seed to set for reproducibility in noise realisation.

  • kernel_support (int) – KB kernel support width in pixels (odd). Default is 7. Larger values give better anti-aliasing at the cost of more compute.

  • beta (float, optional) – KB kernel shape parameter. If None (default), uses the standard heuristic beta = 2.34 * kernel_support. Expose it to experiment with different main-lobe/side-lobe trade-offs.

  • oversampling (float) – UV-grid oversampling factor. The sky is zero-padded to oversampling * N pixels before gridding (finer UV cells, same angular pixel scale, FoV scaled by oversampling), and the dirty image/beam are cropped back to the original N x N afterwards. This discards the image borders where the KB correction amplifies noise and aliasing. Default is 2, matching the beta = 2.34 * W heuristic. Set to 1 to recover the un-padded native-resolution behaviour.

  • on_out_of_bounds ({"warn", "error", "ignore"}) – Behaviour when UV samples fall outside the (oversampled) uv grid and would be silently dropped by the convolutional gridding. "warn" (default) emits a UserWarning reporting the proportion of dropped samples, "error" raises a ValueError, and "ignore" disables the check. See check_uv_in_grid().

  • weighting ({"natural", "uniform"}) – Visibility weighting scheme (see _visibility_weights()). "natural" (default) weights every visibility equally (best sensitivity, broadest PSF); "uniform" weights each by 1/count of its uv cell (finer PSF, higher noise).

Returns:

  • obs (np.ndarray) – The dirty observation(s).

  • dirty_beam (np.ndarray) – The dirty beam(s).

argosim.imaging_utils.simulate_dirty_observation_nn(sky, track, fov_size, multi_band=False, freqs=None, beam=None, sigma=0.2, seed=None, weighting='natural')[source]#

Simulate a dirty observation with nearest-neighbour (NN) gridding.

Educational counterpart to simulate_dirty_observation() (which uses Kaiser-Bessel convolutional gridding). Here each visibility is snapped to its nearest uv-grid cell: the sky FFT is multiplied by the sampling mask, per-visibility (per-cell) noise is added, and the result is inverse Fourier-transformed. Intended to contrast NN vs KB gridding in the GUI; the KB forward model is the one to use for prototyping and applications.

Parameters:
  • sky (np.ndarray) – The sky model image.

  • track (np.ndarray) – The uv sampling points.

  • fov_size (float or tuple) – The field of view size in degrees, scalar or (fov_y, fov_x).

  • multi_band (bool) – If True, simulate a multi-band observation.

  • freqs (list) – The frequency list for the multi-band simulation.

  • beam (Beam) – The beam object to apply to the sky, only used in multi-band simulations.

  • sigma (float) – Standard deviation of the complex Gaussian noise added independently to each sampled uv cell (visibility domain, matching the KB forward model), in sky/flux units. The dirty image is normalised so a point source of flux S peaks at S (Jy/beam). See _add_cell_noise().

  • seed (int) – Optional seed to set for reproducibility in the noise realisation.

  • weighting ({"natural", "uniform"}) – Visibility weighting. For NN this is exactly the sampling-mask choice: "natural" uses the "histogram" mask (each cell weighted by its sample count), "uniform" uses the "binary" mask (each sampled cell weighted equally). See simulate_dirty_observation().

Returns:

  • obs (np.ndarray) – The dirty observation(s).

  • dirty_beam (np.ndarray) – The dirty beam(s).

argosim.imaging_utils.sky2uv(sky)[source]#

Sky to uv plane (JAX version).

Function to compute the Fourier transform of the sky.

Parameters:

sky (np.ndarray) – The sky image.

Returns:

sky_uv – The Fourier transform of the sky.

Return type:

np.ndarray

argosim.imaging_utils.uv2sky(uv)[source]#

Uv to sky (JAX version).

Function to compute the inverse Fourier transform of the uv plane.

Parameters:

uv (np.ndarray) – The image in the uv/Fourier domain.

Returns:

sky – The image in the sky domain.

Return type:

np.ndarray