예제 #1
0
    def test_phase_rotation(self):
        self.vis = create_visibility(
            self.lowcore,
            self.times,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.phasecentre,
            weight=1.0,
            polarisation_frame=PolarisationFrame("stokesIQUV"))
        self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
        # Predict visibilities with new phase centre independently
        ha_diff = -(self.compabsdirection.ra - self.phasecentre.ra).to(
            u.rad).value
        vispred = create_visibility(
            self.lowcore,
            self.times + ha_diff,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.compabsdirection,
            weight=1.0,
            polarisation_frame=PolarisationFrame("stokesIQUV"))
        vismodel2 = predict_skycomponent_visibility(vispred, self.comp)

        # Should yield the same results as rotation
        rotatedvis = phaserotate_visibility(
            self.vismodel, newphasecentre=self.compabsdirection, tangent=False)
        assert_allclose(rotatedvis.vis, vismodel2.vis, rtol=1e-7)
        assert_allclose(rotatedvis.uvw, vismodel2.uvw, rtol=1e-7)
예제 #2
0
 def ingest_visibility(self, freq=None, chan_width=None, times=None, reffrequency=None, add_errors=False,
                       block=True):
     if freq is None:
         freq = [1e8]
     if times is None:
         ntimes = 5
         times = numpy.linspace(-numpy.pi / 3.0, numpy.pi / 3.0, ntimes)
     if chan_width is None:
         chan_width = [1e6]
     
     if reffrequency is None:
         reffrequency = [1e8]
     lowcore = create_named_configuration('LOWBD2-CORE')
     frequency = numpy.array([freq])
     channel_bandwidth = numpy.array([chan_width])
     
     phasecentre = SkyCoord(ra=+180.0 * u.deg, dec=-60.0 * u.deg, frame='icrs', equinox='J2000')
     if block:
         vt = create_blockvisibility(lowcore, times, frequency, channel_bandwidth=channel_bandwidth,
                                     weight=1.0, phasecentre=phasecentre,
                                     polarisation_frame=PolarisationFrame("stokesI"))
     else:
         vt = create_visibility(lowcore, times, frequency, channel_bandwidth=channel_bandwidth,
                                weight=1.0, phasecentre=phasecentre,
                                polarisation_frame=PolarisationFrame("stokesI"))
     cellsize = 0.001
     model = create_image_from_visibility(vt, npixel=self.npixel, cellsize=cellsize, npol=1,
                                          frequency=reffrequency, phasecentre=phasecentre,
                                          polarisation_frame=PolarisationFrame("stokesI"))
     flux = numpy.array([[100.0]])
     facets = 4
     
     rpix = model.wcs.wcs.crpix - 1.0
     spacing_pixels = self.npixel // facets
     centers = [-1.5, -0.5, 0.5, 1.5]
     comps = list()
     for iy in centers:
         for ix in centers:
             p = int(round(rpix[0] + ix * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[0]))), \
                 int(round(rpix[1] + iy * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[1])))
             sc = pixel_to_skycoord(p[0], p[1], model.wcs, origin=1)
             comp = create_skycomponent(flux=flux, frequency=frequency, direction=sc,
                                        polarisation_frame=PolarisationFrame("stokesI"))
             comps.append(comp)
     if block:
         predict_skycomponent_blockvisibility(vt, comps)
     else:
         predict_skycomponent_visibility(vt, comps)
     insert_skycomponent(model, comps)
     self.model = copy_image(model)
     self.empty_model = create_empty_image_like(model)
     export_image_to_fits(model, '%s/test_pipeline_bags_model.fits' % self.dir)
     
     if add_errors:
         # These will be the same for all calls
         numpy.random.seed(180555)
         gt = create_gaintable_from_blockvisibility(vt)
         gt = simulate_gaintable(gt, phase_error=1.0, amplitude_error=0.0)
         vt = apply_gaintable(vt, gt)
     return vt
    def test_invert_2d(self):
        # Test if the 2D invert works with w set to zero
        # Set w=0 so that the two-dimensional transform should agree exactly with the model.
        # Good check on the grid correction in the vis->image direction

        self.actualSetUp()
        self.componentvis = create_visibility(
            self.lowcore,
            self.times,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.phasecentre,
            weight=1.0,
            polarisation_frame=self.vis_pol)
        self.componentvis.data['uvw'][:, 2] = 0.0
        self.componentvis.data['vis'] *= 0.0
        # Predict the visibility using direct evaluation
        for comp in self.components:
            predict_skycomponent_visibility(self.componentvis, comp)

        dirty2d = create_empty_image_like(self.model)
        dirty2d, sumwt = invert_2d(self.componentvis, dirty2d, **self.params)

        export_image_to_fits(
            dirty2d,
            '%s/test_imaging_functions_invert_2d_dirty.fits' % self.dir)

        self._checkcomponents(dirty2d)
예제 #4
0
def calibrate_visibility(vt: Visibility,
                         model: Image = None,
                         components=None,
                         predict=predict_2d,
                         **kwargs) -> Visibility:
    """ calibrate Visibility with respect to model and optionally components

    :param vt: Visibility
    :param model: Model image
    :param components: Sky components
    :return: Calibrated visibility
    """
    assert model is not None or components is not None, "calibration requires a model or skycomponents"

    vtpred = copy_visibility(vt, zero=True)

    if model is not None:
        vtpred = predict(vtpred, model, **kwargs)
        if components is not None:
            vtpred = predict_skycomponent_visibility(vtpred, components)
    else:
        vtpred = predict_skycomponent_visibility(vtpred, components)

    bvt = decoalesce_visibility(vt)
    bvtpred = decoalesce_visibility(vtpred)
    gt = solve_gaintable(bvt, bvtpred, **kwargs)
    bvt = apply_gaintable(bvt,
                          gt,
                          inverse=get_parameter(kwargs, "inverse", False))
    return convert_blockvisibility_to_visibility(bvt)
예제 #5
0
    def ingest_visibility(self,
                          freq=1e8,
                          chan_width=1e6,
                          times=None,
                          reffrequency=None,
                          add_errors=False):
        if times is None:
            times = (numpy.pi / 12.0) * numpy.linspace(-3.0, 3.0, 5)

        if reffrequency is None:
            reffrequency = [1e8]
        lowcore = create_named_configuration('LOWBD2-CORE')
        frequency = numpy.array([freq])
        channel_bandwidth = numpy.array([chan_width])

        phasecentre = SkyCoord(ra=+180.0 * u.deg,
                               dec=-60.0 * u.deg,
                               frame='icrs',
                               equinox='J2000')
        vt = create_visibility(lowcore,
                               times,
                               frequency,
                               channel_bandwidth=channel_bandwidth,
                               weight=1.0,
                               phasecentre=phasecentre,
                               polarisation_frame=PolarisationFrame("stokesI"))
        cellsize = 0.001
        model = create_image_from_visibility(
            vt,
            npixel=self.npixel,
            cellsize=cellsize,
            npol=1,
            frequency=reffrequency,
            phasecentre=phasecentre,
            polarisation_frame=PolarisationFrame("stokesI"))
        flux = numpy.array([[100.0]])
        facets = 4

        rpix = model.wcs.wcs.crpix
        spacing_pixels = self.npixel // facets
        centers = [-1.5, -0.5, 0.5, 1.5]
        comps = list()
        for iy in centers:
            for ix in centers:
                p = int(round(rpix[0] + ix * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[0]))), \
                    int(round(rpix[1] + iy * spacing_pixels * numpy.sign(model.wcs.wcs.cdelt[1])))
                sc = pixel_to_skycoord(p[0], p[1], model.wcs, origin=0)
                comp = create_skycomponent(
                    flux=flux,
                    frequency=frequency,
                    direction=sc,
                    polarisation_frame=PolarisationFrame("stokesI"))
                comps.append(comp)
        predict_skycomponent_visibility(vt, comps)
        insert_skycomponent(model, comps)
        self.model = copy_image(model)
        export_image_to_fits(model,
                             '%s/test_bags_model.fits' % (self.results_dir))
        return vt
def sagecal_fit_gaintable(evis, theta, gain=0.1, niter=3, tol=1e-3, **kwargs):
    """Fit a gaintable to a visibility i.e. A13
    
    This is the update to the gain part of the window

    :param evis:
    :param theta:
    :param kwargs:
    :return:
    """
    previous_gt = copy_gaintable(theta[1])
    gt = copy_gaintable(theta[1])
    model_vis = copy_visibility(evis, zero=True)
    model_vis = predict_skycomponent_visibility(model_vis, theta[0])
    gt = solve_gaintable(evis,
                         model_vis,
                         gt=gt,
                         niter=niter,
                         phase_only=True,
                         gain=0.5,
                         tol=1e-4,
                         **kwargs)
    gt.data['gain'][...] = gain * gt.data['gain'][...] + \
                           (1 - gain) * previous_gt.data['gain'][...]
    gt.data['gain'][...] /= numpy.abs(previous_gt.data['gain'][...])
    return gt
예제 #7
0
 def test_phase_rotation_identity(self):
     self.vis = create_visibility(
         self.lowcore,
         self.times,
         self.frequency,
         channel_bandwidth=self.channel_bandwidth,
         phasecentre=self.phasecentre,
         weight=1.0,
         polarisation_frame=PolarisationFrame("stokesIQUV"))
     self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
     newphasecenters = [
         SkyCoord(182, -35, unit=u.deg),
         SkyCoord(182, -30, unit=u.deg),
         SkyCoord(177, -30, unit=u.deg),
         SkyCoord(176, -35, unit=u.deg),
         SkyCoord(216, -35, unit=u.deg),
         SkyCoord(180, -70, unit=u.deg)
     ]
     for newphasecentre in newphasecenters:
         # Phase rotating back should not make a difference
         original_vis = self.vismodel.vis
         original_uvw = self.vismodel.uvw
         rotatedvis = phaserotate_visibility(phaserotate_visibility(
             self.vismodel, newphasecentre, tangent=False),
                                             self.phasecentre,
                                             tangent=False)
         assert_allclose(rotatedvis.uvw, original_uvw, rtol=1e-7)
         assert_allclose(rotatedvis.vis, original_vis, rtol=1e-7)
예제 #8
0
 def test_visibilitysum(self):
     self.vis = create_visibility(self.lowcore, self.times, self.frequency,
                                  channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, weight=1.0,
                                  polarisation_frame=PolarisationFrame("stokesIQUV"))
     self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
     # Sum the visibilities in the correct_visibility direction. This is limited by numerical precision
     summedflux, weight = sum_visibility(self.vismodel, self.compreldirection)
     assert_allclose(self.flux, summedflux, rtol=1e-7)
예제 #9
0
 def test_sum_visibility(self):
     self.vis = create_visibility(self.lowcore, self.times, self.frequency,
                                  channel_bandwidth=self.channel_bandwidth,
                                  phasecentre=self.phasecentre,
                                  polarisation_frame=PolarisationFrame("linear"),
                                  weight=1.0)
     self.vis = predict_skycomponent_visibility(self.vis, self.comp)
     flux, weight = sum_visibility(self.vis, self.comp.direction)
     assert numpy.max(numpy.abs(flux - self.flux)) < 1e-7
예제 #10
0
 def test_qa(self):
     self.vis = create_visibility(self.lowcore, self.times, self.frequency,
                                  channel_bandwidth=self.channel_bandwidth,
                                  phasecentre=self.phasecentre, weight=1.0,
                                  polarisation_frame=PolarisationFrame("stokesIQUV"))
     self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
     qa = qa_visibility(self.vis, context='test_qa')
     self.assertAlmostEqual(qa.data['maxabs'], 100.0, 7)
     self.assertAlmostEqual(qa.data['medianabs'], 11.0, 7)
     assert qa.context == 'test_qa'
예제 #11
0
    def test_predict_2d(self):
        # Test if the 2D prediction works
        #
        # Set w=0 so that the two-dimensional transform should agree exactly with the component transform.
        # Good check on the grid correction in the image->vis direction
        # Set all w to zero
        self.actualSetUp()
        self.componentvis = create_visibility(
            self.lowcore,
            self.times,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.phasecentre,
            weight=1.0)
        self.componentvis.data['uvw'][:, 2] = 0.0
        # Predict the visibility using direct evaluation
        predict_skycomponent_visibility(self.componentvis, self.components)

        self.modelvis = create_visibility(
            self.lowcore,
            self.times,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.phasecentre,
            weight=1.0,
            polarisation_frame=self.vis_pol)
        self.modelvis.data['uvw'][:, 2] = 0.0
        predict_2d(self.modelvis, self.model, **self.params)
        self.residualvis = create_visibility(
            self.lowcore,
            self.times,
            self.frequency,
            channel_bandwidth=self.channel_bandwidth,
            phasecentre=self.phasecentre,
            weight=1.0,
            polarisation_frame=self.vis_pol)
        self.residualvis.data['uvw'][:, 2] = 0.0
        self.residualvis.data[
            'vis'] = self.modelvis.data['vis'] - self.componentvis.data['vis']

        self._checkdirty(self.residualvis,
                         'test_predict_2d',
                         fluxthreshold=4.0)
예제 #12
0
 def test_insert_skycomponent_dft(self):
     sc = create_skycomponent(
         direction=self.phasecentre,
         flux=numpy.array([[1.0]]),
         frequency=self.frequency,
         polarisation_frame=PolarisationFrame('stokesI'))
     self.vis.data['vis'][...] = 0.0
     self.vis = predict_skycomponent_visibility(self.vis, sc)
     im, sumwt = invert_2d(self.vis, self.model)
     export_image_to_fits(im, '%s/test_skycomponent_dft.fits' % self.dir)
     assert numpy.max(numpy.abs(self.vis.vis.imag)) < 1e-3
예제 #13
0
    def test_invert_2d(self):
        # Test if the 2D invert works with w set to zero
        # Set w=0 so that the two-dimensional transform should agree exactly with the model.
        # Good check on the grid correction in the vis->image direction

        self.actualSetUp()
        self.componentvis.data['uvw'][:, 2] = 0.0
        self.componentvis.data['vis'] *= 0.0
        # Predict the visibility using direct evaluation
        for comp in self.components:
            predict_skycomponent_visibility(self.componentvis, comp)

        dirty2d = create_empty_image_like(self.model)
        dirty2d, sumwt = invert_2d(self.componentvis, dirty2d, **self.params)

        export_image_to_fits(
            dirty2d,
            '%s/test_imaging_functions_invert_2d_dirty.fits' % self.dir)

        self._checkcomponents(dirty2d)
 def make_e(vis, calskymodel, evis_all):
     # Return the estep for a given skymodel
     evis = copy_visibility(vis)
     tvis = copy_visibility(vis, zero=True)
     tvis = predict_skycomponent_visibility(tvis, calskymodel[0].components)
     tvis = apply_gaintable(tvis, calskymodel[1])
     # E step is the data model for a window plus the difference between the observed data
     # and the summed data models or, put another way, its the observed data minus the
     # summed visibility for all other windows
     evis.data['vis'][...] = tvis.data['vis'][...] + vis.data['vis'][
         ...] - evis_all.data['vis'][...]
     return evis
예제 #15
0
 def test_phase_rotation_inverse(self):
     self.vis = create_visibility(self.lowcore, self.times, self.frequency,
                                  channel_bandwidth=self.channel_bandwidth,
                                  phasecentre=self.phasecentre, weight=1.0,
                                  polarisation_frame=PolarisationFrame("stokesIQUV"))
     self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
     there = SkyCoord(ra=+250.0 * u.deg, dec=-60.0 * u.deg, frame='icrs', equinox='J2000')
     # Phase rotating back should not make a difference
     original_vis = self.vismodel.vis
     original_uvw = self.vismodel.uvw
     rotatedvis = phaserotate_visibility(phaserotate_visibility(self.vismodel, there, tangent=False,
                                                                inverse=True),
                                         self.phasecentre, tangent=False, inverse=True)
     assert_allclose(rotatedvis.uvw, original_uvw, rtol=1e-7)
     assert_allclose(rotatedvis.vis, original_vis, rtol=1e-7)
예제 #16
0
def skymodel_cal_e_step(vis: BlockVisibility, evis_all: BlockVisibility, calskymodel, **kwargs):
    """Calculates E step in equation A12

    This is the data model for this window plus the difference between observed data and summed data models

    :param evis_all: Sum data models
    :param csm: csm element being fit
    :param kwargs:
    :return: Data model (i.e. visibility) for this csm
    """
    evis = copy_visibility(evis_all)
    tvis = copy_visibility(vis, zero=True)
    tvis = predict_skycomponent_visibility(tvis, calskymodel[0].components)
    tvis = apply_gaintable(tvis, calskymodel[1])
    evis.data['vis'][...] = tvis.data['vis'][...] + vis.data['vis'][...] - evis_all.data['vis'][...]
    return evis
예제 #17
0
def spectral_line_imaging(vis: Visibility,
                          model: Image,
                          continuum_model: Image = None,
                          continuum_components=None,
                          predict=predict_2d,
                          invert=invert_2d,
                          deconvolve_spectral=False,
                          **kwargs) -> (Image, Image, Image):
    """Spectral line imaging from calibrated (DIE) data
    
    A continuum model can be subtracted, and deconvolution is optional.
    
    If deconvolve_spectral is True then the solve_image is used to deconvolve.
    If deconvolve_spectral is False then the residual image after continuum subtraction is calculated
    
    :param vis: Visibility
    :param continuum_model: model continuum image to be subtracted
    :param continuum_components: mode components to be subtracted
    :param spectral_model: model spectral image
    :param predict: Predict fumction e.g. predict_2d
    :param invert: Invert function e.g. invert_wprojection
    :return: Residual visibility, spectral model image, spectral residual image
    """

    vis_no_continuum = copy_visibility(vis)
    if continuum_model is not None:
        vis_no_continuum = predict(vis_no_continuum, continuum_model, **kwargs)
    if continuum_components is not None:
        vis_no_continuum = predict_skycomponent_visibility(
            vis_no_continuum, continuum_components)
    vis_no_continuum.data[
        'vis'] = vis.data['vis'] - vis_no_continuum.data['vis']

    if deconvolve_spectral:
        log.info(
            "spectral_line_imaging: Deconvolving continuum subtracted visibility"
        )
        vis_no_continuum, spectral_model, spectral_residual = solve_image(
            vis_no_continuum, model, **kwargs)
    else:
        log.info(
            "spectral_line_imaging: Making dirty image from continuum subtracted visibility"
        )
        spectral_model, spectral_residual = \
            invert(vis_no_continuum, model, **kwargs)

    return vis_no_continuum, spectral_model, spectral_residual
    def test_fit_visibility(self):
        # Sum the visibilities in the correct_visibility direction. This is limited by numerical precision
        methods = ['CG', 'BFGS', 'Powell', 'trust-ncg', 'trust-exact', 'trust-krylov']
        for method in methods:
            self.actualSetup()
            self.vis = create_visibility(self.lowcore, self.times, self.frequency,
                                         channel_bandwidth=self.channel_bandwidth,
                                         phasecentre=self.phasecentre, weight=1.0,
                                         polarisation_frame=PolarisationFrame("stokesI"))
            self.vismodel = predict_skycomponent_visibility(self.vis, self.comp)
            initial_comp = Skycomponent(direction=self.comp_start_direction, frequency=self.frequency,
                                        flux=2.0 * self.flux, polarisation_frame=PolarisationFrame("stokesI"))
    
            sc, res = fit_visibility(self.vismodel, initial_comp, niter=200, tol=1e-5, method=method, verbose=False)
#            print(method, res)
            assert sc.direction.separation(self.comp_actual_direction).to('rad').value < 1e-6, \
                sc.direction.separation(self.comp_actual_direction).to('rad')
    def actualSetup(self,
                    sky_pol_frame='stokesIQUV',
                    data_pol_frame='linear',
                    f=None,
                    vnchan=3):
        self.lowcore = create_named_configuration('LOWBD2-CORE')
        self.times = (numpy.pi / 43200.0) * numpy.linspace(0.0, 30.0, 3)
        self.frequency = numpy.linspace(1.0e8, 1.1e8, vnchan)
        self.channel_bandwidth = numpy.array(
            vnchan * [self.frequency[1] - self.frequency[0]])

        if f is None:
            f = [100.0, 50.0, -10.0, 40.0]

        if sky_pol_frame == 'stokesI':
            f = [100.0]

        self.flux = numpy.outer(
            numpy.array(
                [numpy.power(freq / 1e8, -0.7) for freq in self.frequency]), f)

        # The phase centre is absolute and the component is specified relative (for now).
        # This means that the component should end up at the position phasecentre+compredirection
        self.phasecentre = SkyCoord(ra=+180.0 * u.deg,
                                    dec=-35.0 * u.deg,
                                    frame='icrs',
                                    equinox='J2000')
        self.compabsdirection = SkyCoord(ra=+181.0 * u.deg,
                                         dec=-35.0 * u.deg,
                                         frame='icrs',
                                         equinox='J2000')
        self.comp = Skycomponent(
            direction=self.compabsdirection,
            frequency=self.frequency,
            flux=self.flux,
            polarisation_frame=PolarisationFrame(sky_pol_frame))
        self.vis = create_blockvisibility(
            self.lowcore,
            self.times,
            self.frequency,
            phasecentre=self.phasecentre,
            channel_bandwidth=self.channel_bandwidth,
            weight=1.0,
            polarisation_frame=PolarisationFrame(data_pol_frame))
        self.vis = predict_skycomponent_visibility(self.vis, self.comp)
def sagecal_e_all(vis: BlockVisibility, thetas, **kwargs):
    """Calculates E step in equation A12
    
    This is the sum of the data models over all windows

    :param vis:
    :param thetas:
    :param kwargs:
    :return:
    """
    evis = copy_visibility(vis, zero=True)
    tvis = copy_visibility(vis, zero=True)
    for i, theta in enumerate(thetas):
        tvis.data['vis'][...] = 0.0
        tvis = predict_skycomponent_visibility(tvis, theta[0])
        tvis = apply_gaintable(tvis, theta[1])
        evis.data['vis'][...] += tvis.data['vis'][...]
    return evis
예제 #21
0
def skymodel_cal_e_all(vis: BlockVisibility, calskymodels):
    """Calculates E step in equation A12

    This is the sum of the data models over all skymodel

    :param vis: Visibility
    :param csm: List of (skymodel, gaintable) tuples
    :param kwargs:
    :return: Sum of data models (i.e. a visibility)
    """
    evis = copy_visibility(vis, zero=True)
    tvis = copy_visibility(vis, zero=True)
    for csm in calskymodels:
        tvis.data['vis'][...] = 0.0
        tvis = predict_skycomponent_visibility(tvis, csm[0].components)
        tvis = apply_gaintable(tvis, csm[1])
        evis.data['vis'][...] += tvis.data['vis'][...]
    return evis
def sagecal_e_step(vis: BlockVisibility,
                   evis_all: BlockVisibility,
                   theta,
                   beta=1.0,
                   **kwargs):
    """Calculates E step in equation A12
    
    This is the data model for this window plus the difference between observed data and summed data models

    :param vis:
    :param theta:
    :param kwargs:
    :return:
    """
    evis = copy_visibility(evis_all)
    tvis = copy_visibility(vis, zero=True)
    tvis = predict_skycomponent_visibility(tvis, theta[0])
    tvis = apply_gaintable(tvis, theta[1])
    evis.data['vis'][...] = tvis.data['vis'][...] + \
                            beta * (vis.data['vis'][...] - evis_all.data['vis'][...])
    return evis
예제 #23
0
def skymodel_cal_fit_gaintable(evis, calskymodel, gain=0.1, niter=3, tol=1e-3, **kwargs):
    """Fit a gaintable to a visibility
    
    This is the update to the gain part of the window

    :param evis: Expected vis for this ssm
    :param calskymodel: csm element being fit
    :param gain: Gain in step
    :param niter: Number of iterations
    :param kwargs: Gaintable
    """
    previous_gt = copy_gaintable(calskymodel[1])
    gt = copy_gaintable(calskymodel[1])
    model_vis = copy_visibility(evis, zero=True)
    model_vis = predict_skycomponent_visibility(model_vis, calskymodel[0].components)
    gt = solve_gaintable(evis, model_vis, gt=gt, niter=niter, phase_only=True, gain=0.5,
                         tol=1e-4, **kwargs)
    gt.data['gain'][...] = gain * gt.data['gain'][...] + \
                           (1 - gain) * previous_gt.data['gain'][...]
    gt.data['gain'][...] /= numpy.abs(previous_gt.data['gain'][...])
    return gt
def spectral_line_imaging(vis: BlockVisibility,
                          model: Image,
                          continuum_model: Image = None,
                          continuum_components=None,
                          context='2d',
                          **kwargs) -> (Image, Image, Image):
    """Spectral line imaging from calibrated (DIE) data
    
    A continuum model can be subtracted, and the residual image deconvolved.
    
    :param vis: Visibility
    :param model: Image specify details of model
    :param continuum_model: model continuum image to be subtracted
    :param continuum_components: mode components to be subtracted
    :param spectral_model: model spectral image
    :param predict: Predict fumction e.g. predict_2d
    :param invert: Invert function e.g. invert_wprojection
    :return: Residual visibility, spectral model image, spectral residual image
    """

    vis_no_continuum = copy_visibility(vis)
    if continuum_model is not None:
        vis_no_continuum = predict_function(vis_no_continuum,
                                            continuum_model,
                                            context=context,
                                            **kwargs)
    if continuum_components is not None:
        vis_no_continuum = predict_skycomponent_visibility(
            vis_no_continuum, continuum_components)
    vis_no_continuum.data[
        'vis'] = vis.data['vis'] - vis_no_continuum.data['vis']

    log.info(
        "spectral_line_imaging: Deconvolving continuum subtracted visibility")
    return ical(vis_no_continuum.data,
                model,
                components=None,
                context=context,
                do_selfcal=False,
                **kwargs)
예제 #25
0
    def test_predict_2d(self):
        # Test if the 2D prediction works
        #
        # Set w=0 so that the two-dimensional transform should agree exactly with the component transform.
        # Good check on the grid correction in the image->vis direction
        # Set all w to zero
        self.actualSetUp()
        self.componentvis.data['uvw'][:, 2] = 0.0
        # Predict the visibility using direct evaluation
        self.componentvis.data['vis'][...] = 0.0
        self.componentvis = predict_skycomponent_visibility(
            self.componentvis, self.components)

        self.modelvis = copy_visibility(self.componentvis, zero=True)
        self.modelvis.data['uvw'][:, 2] = 0.0
        self.modelvis = predict_2d(self.modelvis, self.model, **self.params)
        self.residualvis = copy_visibility(self.componentvis, zero=True)
        self.residualvis.data['uvw'][:, 2] = 0.0
        self.residualvis.data[
            'vis'] = self.modelvis.data['vis'] - self.componentvis.data['vis']

        self._checkdirty(self.residualvis, 'predict_2d')
def rcal(vis: BlockVisibility, components, **kwargs) -> GainTable:
    """ Real-time calibration pipeline.

    Reads visibilities through a BlockVisibility iterator, calculates model visibilities according to a
    component-based sky model, and performs calibration solution, writing a gaintable for each chunk of
    visibilities.

    :param vis: Visibility or Union(Visibility, Iterable)
    :param components: Component-based sky model
    :param kwargs: Parameters
    :return: gaintable
   """

    if not isinstance(vis, collections.Iterable):
        vis = [vis]

    from arl.calibration.solvers import solve_gaintable
    for ichunk, vischunk in enumerate(vis):
        vispred = copy_visibility(vischunk, zero=True)
        vispred = predict_skycomponent_visibility(vispred, components)
        gt = solve_gaintable(vischunk, vispred, **kwargs)
        yield gt
예제 #27
0
    def actualSetup(self, sky_pol_frame='stokesIQUV', data_pol_frame='linear'):
        self.lowcore = create_named_configuration('LOWBD2-CORE')
        self.times = (numpy.pi / 43200.0) * numpy.arange(0.0, 300.0, 30.0)
        vnchan = 3
        self.frequency = numpy.linspace(1.0e8, 1.1e8, vnchan)
        self.channel_bandwidth = numpy.array(
            vnchan * [self.frequency[1] - self.frequency[0]])

        # Define the component and give it some spectral behaviour
        f = numpy.array([100.0, 20.0, -10.0, 1.0])
        self.flux = numpy.array([f, 0.8 * f, 0.6 * f])

        self.phasecentre = SkyCoord(ra=+180.0 * u.deg,
                                    dec=-35.0 * u.deg,
                                    frame='icrs',
                                    equinox='J2000')
        self.compabsdirection = SkyCoord(ra=+181.0 * u.deg,
                                         dec=-35.0 * u.deg,
                                         frame='icrs',
                                         equinox='J2000')
        if sky_pol_frame == 'stokesI':
            self.flux = self.flux[:, 0][:, numpy.newaxis]

        self.comp = Skycomponent(
            direction=self.compabsdirection,
            frequency=self.frequency,
            flux=self.flux,
            polarisation_frame=PolarisationFrame(sky_pol_frame))
        self.vis = create_blockvisibility(
            self.lowcore,
            self.times,
            self.frequency,
            phasecentre=self.phasecentre,
            channel_bandwidth=self.channel_bandwidth,
            weight=1.0,
            polarisation_frame=PolarisationFrame(data_pol_frame))
        self.vis = predict_skycomponent_visibility(self.vis, self.comp)
예제 #28
0
def create_blockvisibility_iterator(
        config: Configuration,
        times: numpy.array,
        frequency: numpy.array,
        channel_bandwidth,
        phasecentre: SkyCoord,
        weight: float = 1,
        polarisation_frame=PolarisationFrame('stokesI'),
        integration_time=1.0,
        number_integrations=1,
        predict=predict_timeslice,
        model=None,
        components=None,
        phase_error=0.0,
        amplitude_error=0.0,
        sleep=0.0,
        **kwargs):
    """ Create a sequence of Visibilities and optionally predicting and coalescing

    This is useful mainly for performing large simulations. Do something like::
    
        vis_iter = create_blockvisibility_iterator(config, times, frequency, channel_bandwidth, phasecentre=phasecentre,
                                              weight=1.0, integration_time=30.0, number_integrations=3)

        for i, vis in enumerate(vis_iter):
        if i == 0:
            fullvis = vis
        else:
            fullvis = append_visibility(fullvis, vis)


    :param config: Configuration of antennas
    :param times: hour angles in radians
    :param frequency: frequencies (Hz] Shape [nchan]
    :param weight: weight of a single sample
    :param phasecentre: phasecentre of observation
    :param npol: Number of polarizations
    :param integration_time: Integration time ('auto' or value in s)
    :param number_integrations: Number of integrations to be created at each time.
    :param model: Model image to be inserted
    :param components: Components to be inserted
    :param sleep_time: Time to sleep between yields
    :return: Visibility

    """
    for time in times:
        actualtimes = time + numpy.arange(
            0, number_integrations) * integration_time * numpy.pi / 43200.0
        bvis = create_blockvisibility(config,
                                      actualtimes,
                                      frequency=frequency,
                                      phasecentre=phasecentre,
                                      weight=weight,
                                      polarisation_frame=polarisation_frame,
                                      integration_time=integration_time,
                                      channel_bandwidth=channel_bandwidth)

        if model is not None:
            vis = predict(bvis, model, **kwargs)
            bvis = convert_visibility_to_blockvisibility(vis)

        if components is not None:
            bvis = predict_skycomponent_visibility(bvis, components)

        # Add phase errors
        if phase_error > 0.0 or amplitude_error > 0.0:
            gt = create_gaintable_from_blockvisibility(bvis)
            gt = simulate_gaintable(gt=gt,
                                    phase_error=phase_error,
                                    amplitude_error=amplitude_error)
            bvis = apply_gaintable(bvis, gt)

        import time
        time.sleep(sleep)

        yield bvis
    def test_peel_skycomponent_blockvisibility(self):
        df = 1e6
        frequency = numpy.array([1e8 - df, 1e8, 1e8 + df])
        channel_bandwidth = numpy.array([df, df, df])

        # Define the component and give it some spectral behaviour
        f = numpy.array([100.0, 20.0, -10.0, 1.0])
        flux = numpy.array([f, 0.8 * f, 0.6 * f])
        phasecentre = SkyCoord(0 * u.deg, -60.0 * u.deg)

        config = create_named_configuration('LOWBD2-CORE')
        peeldirection = SkyCoord(+15 * u.deg, -60.0 * u.deg)
        times = numpy.linspace(-3.0, 3.0, 7) * numpy.pi / 12.0

        # Make the visibility
        vis = create_blockvisibility(
            config,
            times,
            frequency,
            phasecentre=phasecentre,
            weight=1.0,
            polarisation_frame=PolarisationFrame('linear'),
            channel_bandwidth=channel_bandwidth)
        vis.data['vis'][...] = 0.0

        # First add in the source to be peeled.
        peel = Skycomponent(direction=peeldirection,
                            frequency=frequency,
                            flux=flux,
                            polarisation_frame=PolarisationFrame("stokesIQUV"))
        vis = predict_skycomponent_visibility(vis, peel)

        # Make a gaintable and apply it to the visibility of the peeling source
        gt = create_gaintable_from_blockvisibility(vis, timeslice='auto')
        gt = simulate_gaintable(gt,
                                phase_error=0.01,
                                amplitude_error=0.01,
                                timeslice='auto')
        gt.data['gain'] *= 0.3
        vis = apply_gaintable(vis, gt, timeslice='auto')

        # Now create a plausible field using the GLEAM sources
        model = create_image_from_visibility(
            vis,
            cellsize=0.001,
            frequency=frequency,
            polarisation_frame=PolarisationFrame('stokesIQUV'))

        bm = create_low_test_beam(model=model)
        sc = create_low_test_skycomponents_from_gleam(
            flux_limit=1.0,
            polarisation_frame=PolarisationFrame("stokesIQUV"),
            frequency=frequency,
            kind='cubic',
            phasecentre=phasecentre,
            radius=0.1)
        sc = apply_beam_to_skycomponent(sc, bm)
        # Add in the visibility due to these sources
        vis = predict_skycomponent_visibility(vis, sc)
        assert numpy.max(numpy.abs(vis.vis)) > 0.0

        # Now we can peel
        vis, peel_gts = peel_skycomponent_blockvisibility(vis, peel)

        assert len(peel_gts) == 1
        residual = numpy.max(peel_gts[0].residual)
        assert residual < 0.7, "Peak residual %.6f too large" % (residual)

        im, sumwt = invert_timeslice(vis, model, timeslice='auto')
        qa = qa_image(im)

        assert numpy.abs(qa.data['max'] - 14.2) < 1.0, str(qa)
def ical(block_vis: BlockVisibility,
         model: Image,
         components=None,
         context='2d',
         controls=None,
         **kwargs):
    """ Post observation image, deconvolve, and self-calibrate
   
    :param vis:
    :param model: Model image
    :param components: Initial components
    :param context: Imaging context
    :param controls: Calibration controls dictionary
    :return: model, residual, restored
    """
    nmajor = get_parameter(kwargs, 'nmajor', 5)
    log.info("ical: Performing %d major cycles" % nmajor)

    do_selfcal = get_parameter(kwargs, "do_selfcal", False)

    if controls is None:
        controls = create_calibration_controls(**kwargs)

    # The model is added to each major cycle and then the visibilities are
    # calculated from the full model
    vis = convert_blockvisibility_to_visibility(block_vis)
    block_vispred = copy_visibility(block_vis, zero=True)
    vispred = convert_blockvisibility_to_visibility(block_vispred)
    vispred.data['vis'][...] = 0.0
    visres = copy_visibility(vispred)

    vispred = predict_function(vispred, model, context=context, **kwargs)

    if components is not None:
        vispred = predict_skycomponent_visibility(vispred, components)

    if do_selfcal:
        vis, gaintables = calibrate_function(vis,
                                             vispred,
                                             'TGB',
                                             controls,
                                             iteration=-1)

    visres.data['vis'] = vis.data['vis'] - vispred.data['vis']
    dirty, sumwt = invert_function(visres, model, context=context, **kwargs)
    log.info("Maximum in residual image is %.6f" %
             (numpy.max(numpy.abs(dirty.data))))

    psf, sumwt = invert_function(visres,
                                 model,
                                 dopsf=True,
                                 context=context,
                                 **kwargs)

    thresh = get_parameter(kwargs, "threshold", 0.0)

    for i in range(nmajor):
        log.info("ical: Start of major cycle %d of %d" % (i, nmajor))
        cc, res = deconvolve_cube(dirty, psf, **kwargs)
        model.data += cc.data
        vispred.data['vis'][...] = 0.0
        vispred = predict_function(vispred, model, context=context, **kwargs)
        if do_selfcal:
            vis, gaintables = calibrate_function(vis,
                                                 vispred,
                                                 'TGB',
                                                 controls,
                                                 iteration=i)
        visres.data['vis'] = vis.data['vis'] - vispred.data['vis']

        dirty, sumwt = invert_function(visres,
                                       model,
                                       context=context,
                                       **kwargs)
        log.info("Maximum in residual image is %s" %
                 (numpy.max(numpy.abs(dirty.data))))
        if numpy.abs(dirty.data).max() < 1.1 * thresh:
            log.info("ical: Reached stopping threshold %.6f Jy" % thresh)
            break
        log.info("ical: End of major cycle")

    log.info("ical: End of major cycles")
    restored = restore_cube(model, psf, dirty, **kwargs)

    return model, dirty, restored