"""
The w-stacking or w-slicing approach is to partition the visibility data by slices in w. The measurement equation is
approximated as:
.. math::
V(u,v,w) =\\sum_i \\int \\frac{ I(l,m) e^{-2 \\pi j (w_i(\\sqrt{1-l^2-m^2}-1))})}{\\sqrt{1-l^2-m^2}} e^{-2 \\pi j (ul+vm)} dl dm
If images constructed from slices in w are added after applying a w-dependent image plane correction, the w term will be corrected.
"""
import numpy
from data_models.memory_data_models import Visibility, Image, BlockVisibility
from processing_library.image.operations import create_w_term_like
from ..image.operations import copy_image
from ..visibility.base import copy_visibility
from ..imaging.base import predict_2d, invert_2d
import logging
log = logging.getLogger(__name__)
[docs]def predict_wstack_single(vis, model, remove=True, gcfcf=None, **kwargs) -> Visibility:
""" Predict using a single w slices.
This processes a single w plane, rotating out the w beam for the average w
:param vis: Visibility to be predicted
:param model: model image
:return: resulting visibility (in place works)
"""
assert isinstance(vis, Visibility), vis
vis.data['vis'][...] = 0.0
log.debug("predict_wstack_single: predicting using single w slice")
# We might want to do wprojection so we remove the average w
w_average = numpy.average(vis.w)
if remove:
vis.data['uvw'][..., 2] -= w_average
tempvis = copy_visibility(vis)
# Calculate w beam and apply to the model. The imaginary part is not needed
workimage = copy_image(model)
w_beam = create_w_term_like(model, w_average, vis.phasecentre)
# Do the real part
workimage.data = w_beam.data.real * model.data
vis = predict_2d(vis, workimage, gcfcf=gcfcf, **kwargs)
# and now the imaginary part
workimage.data = w_beam.data.imag * model.data
tempvis = predict_2d(tempvis, workimage, gcfcf=gcfcf, **kwargs)
vis.data['vis'] -= 1j * tempvis.data['vis']
if remove:
vis.data['uvw'][..., 2] += w_average
return vis
[docs]def invert_wstack_single(vis: Visibility, im: Image, dopsf, normalize=True, remove=True,
gcfcf=None, **kwargs) -> (Image, numpy.ndarray):
"""Process single w slice
:param vis: Visibility to be inverted
:param im: image template (not changed)
:param dopsf: Make the psf instead of the dirty image
:param normalize: Normalize by the sum of weights (True)
"""
log.debug("invert_wstack_single: predicting using single w slice")
kwargs['imaginary'] = True
assert isinstance(vis, Visibility), vis
# We might want to do wprojection so we remove the average w
w_average = numpy.average(vis.w)
if remove:
vis.data['uvw'][..., 2] -= w_average
reWorkimage, sumwt, imWorkimage = invert_2d(vis, im, dopsf, normalize=normalize, gcfcf=gcfcf, **kwargs)
if remove:
vis.data['uvw'][..., 2] += w_average
# Calculate w beam and apply to the model. The imaginary part is not needed
w_beam = create_w_term_like(im, w_average, vis.phasecentre)
reWorkimage.data = w_beam.data.real * reWorkimage.data - w_beam.data.imag * imWorkimage.data
return reWorkimage, sumwt