Source code for pclean.imaging.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.
"""
from __future__ import annotations
import logging
log = logging.getLogger(__name__)
_casatools = None
def _ct():
global _casatools
if _casatools is None:
import casatools as ct
_casatools = ct
return _casatools
[docs]
class Normalizer:
"""Wrapper around ``synthesisnormalizer``.
In parallel continuum mode the normalizer gathers partial images
produced by different workers, divides by weight, and scatters
the model back.
Args:
normpars: Parameters for ``setupnormalizer`` (imagename, pblimit, ...).
partimagenames: Paths to the partial (per-worker) images. When set, the
normalizer will register them for gather/scatter operations.
"""
def __init__(
self,
normpars: dict,
partimagenames: list[str] | None = None,
):
self.normpars = dict(normpars)
self.partimagenames = partimagenames or []
self._sn = None
[docs]
def setup(self) -> None:
ct = _ct()
self._sn = ct.synthesisnormalizer()
pars = dict(self.normpars)
if self.partimagenames:
pars['partimagenames'] = self.partimagenames
self._sn.setupnormalizer(normpars=pars)
[docs]
def teardown(self) -> None:
if self._sn is not None:
self._sn.done()
self._sn = None
# -- PSF normalization ---------------------------------------------
[docs]
def normalize_psf(self) -> None:
"""Gather PSF weight, divide, fit beam, normalize weight image."""
self._sn.gatherpsfweight()
self._sn.dividepsfbyweight()
self._sn.makepsfbeamset()
self._sn.divideweightbysumwt()
# -- Residual normalization ----------------------------------------
[docs]
def gather_residual(self) -> None:
self._sn.gatherresidual()
[docs]
def divide_residual_by_weight(self) -> None:
self._sn.divideresidualbyweight()
# -- Model normalization -------------------------------------------
[docs]
def divide_model_by_weight(self) -> None:
self._sn.dividemodelbyweight()
[docs]
def multiply_model_by_weight(self) -> None:
self._sn.multiplymodelbyweight()
[docs]
def scatter_model(self) -> None:
self._sn.scattermodel()
# -- Primary beam --------------------------------------------------
[docs]
def normalize_pb(self) -> None:
try:
self._sn.normalizeprimarybeam()
except Exception:
log.debug('normalizeprimarybeam not available; skipping.')
# -- Weight density ------------------------------------------------
[docs]
def gather_weight_density(self) -> None:
self._sn.gatherweightdensity()
[docs]
def scatter_weight_density(self) -> str:
return self._sn.scatterweightdensity()
# -- Convenience combos --------------------------------------------
[docs]
def post_major_mfs(self) -> None:
"""Post-major-cycle normalization for MFS imaging."""
self.gather_residual()
self.divide_residual_by_weight()
self.multiply_model_by_weight()
[docs]
def pre_major_mfs(self) -> None:
"""Pre-major-cycle normalization for MFS imaging."""
self.divide_model_by_weight()
self.scatter_model()