Imaging API

SerialImager

Serial synthesis imager – the single-process imaging engine.

Wraps the four CASA synthesis C++ tools (synthesisimager, synthesisdeconvolver, synthesisnormalizer, iterbotsink) into a clean Python lifecycle that can be driven standalone or by the Dask-parallel engines.

Public API:

SerialImager(config)
.setup()           -- wires up all C++ tools
.make_psf()        -- compute PSF
.make_pb()         -- compute primary beam
.run_major_cycle() -- one major cycle (grid / degrid)
.run_minor_cycle() -- one round of deconvolution
.has_converged()   -- check convergence
.restore()         -- restore images
.pbcor()           -- PB-correct images
.teardown()        -- release tools
.run()             -- full end-to-end pipeline
class pclean.imaging.serial_imager.SerialImager(config, init_iter_control=True)[source]

Bases: object

Single-process CLEAN imaging pipeline.

Parameters:
  • config (PcleanConfig) – Validated hierarchical configuration.

  • init_iter_control (bool) – Whether to create an iterbotsink tool. Set to False when this imager is driven externally (e.g. by a Dask coordinator that manages convergence itself).

setup()[source]

Create and configure all synthesis tools.

Return type:

None

teardown()[source]

Release all C++ tool resources.

The CASA C++ table::done() internally calls table::name() for LogOrigin, which emits a spurious INFO name:: No table opened. message for every internal table reference that was already closed. We use casalog.filterMsg to suppress this specific message during teardown, then clear the filter list afterwards.

Return type:

None

make_psf()[source]

Compute the PSF (and gather/normalize for MFS).

Return type:

None

make_pb()[source]

Compute the primary beam.

Return type:

None

run_major_cycle(is_first=False)[source]

Execute one major cycle.

Parameters:

is_first (bool) – If True this is the initial residual computation (model is zero).

Return type:

None

run_minor_cycle()[source]

Execute one round of minor-cycle deconvolution on all fields.

Returns:

True if iterations were performed.

Return type:

bool

has_converged(nmajor_limit=-1)[source]

Check convergence (peak residual, niter, threshold …).

Calls initminorcycle internally (idempotent if already called via _init_minor_cycle()) then evaluates cleanComplete.

Returns:

True when cleaning should stop.

Parameters:

nmajor_limit (int)

Return type:

bool

update_mask()[source]

Update auto-multithresh mask (if configured).

When python_automask is enabled, runs the pure-numpy automasking algorithm and writes the result to .mask. Otherwise delegates to the C++ setupmask().

Return type:

None

restore()[source]

Restore the final CLEAN images.

Return type:

None

pbcor()[source]

Apply primary-beam correction.

Return type:

None

run()[source]

Run the full imaging + deconvolution pipeline.

Returns:

Convergence summary.

Return type:

dict

Deconvolver

Deconvolution wrapper.

Provides a standalone Deconvolver class that can be used independently of the full imaging pipeline – for example when the residual / PSF already exist on disk and only minor-cycle deconvolution is needed.

class pclean.imaging.deconvolver.Deconvolver(imagename, decpars, iterpars=None)[source]

Bases: object

Thin wrapper around synthesisdeconvolver.

Parameters:
  • imagename (str) – Image name prefix (images must already exist on disk).

  • decpars (dict) – Deconvolution parameters (deconvolver, scales, nterms, …).

  • iterpars (dict | None) – Iteration control parameters. If None, the caller must drive the minor cycle externally.

setup()[source]
Return type:

None

teardown()[source]
Return type:

None

init_minor()[source]

Return peak-residual info for the iterbot.

Return type:

dict

execute_minor(iterbotrecord=None)[source]

Run one minor cycle.

If iterbotrecord is not given and an iterbotsink was created, the record is obtained automatically.

Parameters:

iterbotrecord (dict | None)

Return type:

dict

setup_mask()[source]
Return type:

None

restore()[source]
Return type:

None

pbcor()[source]
Return type:

None

run_loop()[source]

Run the full minor-cycle loop (requires iterpars).

Returns:

Summary with iteration count, peak residual, etc.

Return type:

dict

Normalizer

Image normalizer wrapper.

Provides a standalone Normalizer class that handles the gather / scatter / divide-by-weight operations required for both serial and parallel imaging.

class pclean.imaging.normalizer.Normalizer(normpars, partimagenames=None)[source]

Bases: object

Wrapper around synthesisnormalizer.

In parallel continuum mode the normalizer gathers partial images produced by different workers, divides by weight, and scatters the model back.

Parameters:
  • normpars (dict) – Parameters for setupnormalizer (imagename, pblimit, …).

  • partimagenames (list[str] | None) – Paths to the partial (per-worker) images. When set, the normalizer will register them for gather/scatter operations.

setup()[source]
Return type:

None

teardown()[source]
Return type:

None

normalize_psf()[source]

Gather PSF weight, divide, fit beam, normalize weight image.

Return type:

None

gather_residual()[source]
Return type:

None

divide_residual_by_weight()[source]
Return type:

None

divide_model_by_weight()[source]
Return type:

None

multiply_model_by_weight()[source]
Return type:

None

scatter_model()[source]
Return type:

None

normalize_pb()[source]
Return type:

None

gather_weight_density()[source]
Return type:

None

scatter_weight_density()[source]
Return type:

str

post_major_mfs()[source]

Post-major-cycle normalization for MFS imaging.

Return type:

None

pre_major_mfs()[source]

Pre-major-cycle normalization for MFS imaging.

Return type:

None

Auto-Masking

Pure-numpy auto-multithresh masking.

Re-implements CASA’s SDMaskHandler::autoMaskByMultiThreshold algorithm using numpy/scipy, eliminating:

  • Repeated full-cube copy to TempImage

  • Per-plane TempImage allocations (~8 per chan per iteration)

  • casacore TableCache interactions (mask0 subtable bug)

  • Multiple statistics passes

The algorithm faithfully reproduces the six stages of the C++ implementation: threshold → prune → smooth → grow → combine → negative mask.

Memory optimisation notes:

All intermediate masks use np.bool_ (1 byte/pixel) instead of float32 (4 bytes/pixel), giving a 4× footprint reduction on mask arrays. Only the final mask returned to the caller is float32 (CASA image format). AutoMaskState.posmask and .prevmask are stored as bool_ between iterations. When pb is None no PB-mask array is allocated at all (pb_mask = None sentinel).

References

SDMaskHandler.cc autoMaskByMultiThreshold() (CASA 6.x) Kepley et al. 2020, PASP 132, 024505

class pclean.imaging.automask.AutoMaskConfig(sidelobethreshold=3.0, noisethreshold=5.0, lownoisethreshold=1.5, negativethreshold=0.0, smoothfactor=1.0, minbeamfrac=0.3, cutthreshold=0.01, growiterations=100, dogrowprune=True, minpercentchange=0.0, fastnoise=True)[source]

Bases: object

Parameters mirroring CASA’s auto-multithresh knobs.

Defaults match CASA’s tclean defaults.

Parameters:
sidelobethreshold: float = 3.0
noisethreshold: float = 5.0
lownoisethreshold: float = 1.5
negativethreshold: float = 0.0
smoothfactor: float = 1.0
minbeamfrac: float = 0.3
cutthreshold: float = 0.01
growiterations: int = 100
dogrowprune: bool = True
minpercentchange: float = 0.0
fastnoise: bool = True
classmethod from_pclean_config(dec)[source]

Build from a DeconvolutionConfig object.

Return type:

AutoMaskConfig

class pclean.imaging.automask.AutoMaskState(posmask=None, prevmask=None, iteration=0, skip=False)[source]

Bases: object

Mutable state carried across major-cycle iterations.

The C++ implementation keeps posmask and prevmask inside SIImageStore. Here we keep lightweight numpy arrays per channel so the Python caller can stash them between cycles.

Parameters:
posmask: ndarray[tuple[Any, ...], dtype[bool]] | None = None
prevmask: ndarray[tuple[Any, ...], dtype[bool]] | None = None
iteration: int = 0
skip: bool = False
pclean.imaging.automask.automask_plane(residual, sidelobe_level, beam_area_pix, beam_sigma_pix, cfg, state, pb=None, pblimit=0.2, beam_pa_rad=0.0)[source]

Compute the auto-multithresh mask for a single 2-D plane.

This is the numpy equivalent of SDMaskHandler::autoMaskByMultiThreshold operating on one (pol, chan) slice.

Memory strategy:
  • All intermediate masks are np.bool_ (1 byte/pixel).

  • pb_mask is None when no PB is provided (zero alloc).

  • state.posmask / state.prevmask stored as bool_.

  • In-place |= replaces np.maximum chains.

  • Only the final return value is cast to float32 for CASA I/O.

Parameters:
  • residual (ndarray[tuple[Any, ...], dtype[float32]]) – 2-D residual image (float32).

  • sidelobe_level (float) – PSF sidelobe level (scalar, from getPSFSidelobeLevel).

  • beam_area_pix (float) – Restoring beam area in pixels.

  • beam_sigma_pix (tuple[float, float]) – (sigma_major, sigma_minor) of the restoring beam in pixels (for Gaussian smoothing).

  • cfg (AutoMaskConfig) – Automasking parameters.

  • state (AutoMaskState) – Mutable per-channel state (updated in-place).

  • pb (ndarray[tuple[Any, ...], dtype[float32]] | None) – Primary beam image (same shape as residual). If given, regions with pb < pblimit are excluded.

  • pblimit (float) – PB cutoff for the mask region.

  • beam_pa_rad (float) – Beam position angle in radians (East from North).

Returns:

The updated binary mask (float32, 0/1).

Return type:

ndarray[tuple[Any, …], dtype[float32]]

pclean.imaging.automask.beam_info_from_image(imagename)[source]

Read beam area, sidelobe level, sigma, and PA from a CASA image.

Returns:

(beam_area_pix, sidelobe_level, (sigma_major_pix, sigma_minor_pix), pa_rad)

Parameters:

imagename (str)

Return type:

tuple[float, float, tuple[float, float], float]

pclean.imaging.automask.read_plane(imagename)[source]

Read a single-channel CASA image into a 2-D numpy array.

Parameters:

imagename (str)

Return type:

ndarray[tuple[Any, …], dtype[float32]]

pclean.imaging.automask.write_plane(imagename, data)[source]

Write a 2-D numpy array to an existing single-channel CASA image.

Parameters:
Return type:

None