Example #1
0
    def test_phase_rotate(self):

        uvw = numpy.array([(1, 0, 0), (0, 1, 0), (0, 0, 1)])

        pos = [
            SkyCoord(17, 35, unit=u.deg),
            SkyCoord(17, 30, unit=u.deg),
            SkyCoord(12, 30, unit=u.deg),
            SkyCoord(11, 35, unit=u.deg),
            SkyCoord(51, 35, unit=u.deg),
            SkyCoord(15, 70, unit=u.deg)
        ]

        # Sky coordinates to reproject to
        for phasecentre in pos:
            for newphasecentre in pos:

                # Rotate UVW
                xyz = uvw_to_xyz(uvw, -phasecentre.ra.rad, phasecentre.dec.rad)
                uvw_rotated = xyz_to_uvw(xyz, -newphasecentre.ra.rad,
                                         newphasecentre.dec.rad)

                # Determine phasor
                l_p, m_p, n_p = skycoord_to_lmn(phasecentre, newphasecentre)
                phasor = simulate_point(uvw_rotated, l_p, m_p)

                for sourcepos in pos:
                    # Simulate visibility at old and new phase centre
                    l, m, _ = skycoord_to_lmn(sourcepos, phasecentre)
                    vis = simulate_point(uvw, l, m)
                    l_r, m_r, _ = skycoord_to_lmn(sourcepos, newphasecentre)
                    vis_rotated = simulate_point(uvw_rotated, l_r, m_r)

                    # Difference should be given by phasor
                    assert_allclose(vis * phasor, vis_rotated, atol=1e-10)
Example #2
0
def predict_skycomponent_visibility(
        vis: Union[Visibility, BlockVisibility],
        sc: Union[Skycomponent, List[Skycomponent]]) -> Visibility:
    """Predict the visibility from a Skycomponent, add to existing visibility, for Visibility or BlockVisibility

    :param vis: Visibility or BlockVisibility
    :param sc: Skycomponent or list of SkyComponents
    :return: Visibility or BlockVisibility
    """
    if not isinstance(sc, collections.Iterable):
        sc = [sc]

    if isinstance(vis, Visibility):

        _, im_nchan = list(get_frequency_map(vis, None))
        npol = vis.polarisation_frame.npol

        for comp in sc:

            assert_same_chan_pol(vis, comp)

            l, m, n = skycoord_to_lmn(comp.direction, vis.phasecentre)
            phasor = simulate_point(vis.uvw, l, m)
            for ivis in range(vis.nvis):
                for pol in range(npol):
                    vis.data['vis'][ivis, pol] += comp.flux[im_nchan[ivis],
                                                            pol] * phasor[ivis]

    elif isinstance(vis, BlockVisibility):

        nchan = vis.nchan
        npol = vis.npol

        k = numpy.array(vis.frequency) / constants.c.to('m/s').value

        for comp in sc:
            assert_same_chan_pol(vis, comp)

            flux = comp.flux
            if comp.polarisation_frame != vis.polarisation_frame:
                flux = convert_pol_frame(flux, comp.polarisation_frame,
                                         vis.polarisation_frame)

            l, m, n = skycoord_to_lmn(comp.direction, vis.phasecentre)
            for chan in range(nchan):
                phasor = simulate_point(vis.uvw * k[chan], l, m)
                for pol in range(npol):
                    vis.data['vis'][..., chan,
                                    pol] += flux[chan, pol] * phasor[...]

    return vis
Example #3
0
def predict_skycomponent_visibility(
        vis: Visibility, sc: Union[Skycomponent,
                                   List[Skycomponent]]) -> Visibility:
    """Predict the visibility from a Skycomponent, add to existing visibility, for Visibility

    :param vis: Visibility
    :param sc: Skycomponent or list of SkyComponents
    :return: Visibility
    """
    assert type(vis) is Visibility, "vis is not a Visibility: %r" % vis

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

    _, ichan = list(get_frequency_map(vis, None))

    npol = vis.polarisation_frame.npol

    for comp in sc:

        l, m, n = skycoord_to_lmn(comp.direction, vis.phasecentre)
        phasor = simulate_point(vis.uvw, l, m)
        for ivis in range(vis.nvis):
            for pol in range(npol):
                vis.data['vis'][ivis, pol] += comp.flux[ichan[ivis],
                                                        pol] * phasor[ivis]

            # coords = phasor, ichan
            # for pol in range(npol):
            #     vis.data['vis'][:,pol] += [comp.flux[ic, pol] * p for p, ic in zip(*coords)]

    return vis
Example #4
0
def sum_visibility(vis: Visibility, direction: SkyCoord) -> numpy.array:
    """ Direct Fourier summation in a given direction

    :param vis: Visibility to be summed
    :param direction: Direction of summation
    :return: flux[nch,npol], weight[nch,pol]
    """
    # TODO: Convert to Visibility or remove?

    svis = copy_visibility(vis)

    l, m, n = skycoord_to_lmn(direction, svis.phasecentre)
    phasor = numpy.conjugate(simulate_point(svis.uvw, l, m))

    # Need to put correct mapping here
    _, frequency = get_frequency_map(svis, None)

    frequency = list(frequency)

    nchan = max(frequency) + 1
    npol = svis.polarisation_frame.npol

    flux = numpy.zeros([nchan, npol])
    weight = numpy.zeros([nchan, npol])

    coords = svis.vis, svis.weight, phasor, list(frequency)
    for v, wt, p, ic in zip(*coords):
        for pol in range(npol):
            flux[ic, pol] += numpy.real(wt[pol] * v[pol] * p)
            weight[ic, pol] += wt[pol]

    flux[weight > 0.0] = flux[weight > 0.0] / weight[weight > 0.0]
    flux[weight <= 0.0] = 0.0
    return flux, weight
Example #5
0
def phaserotate_visibility(vis: Visibility, newphasecentre: SkyCoord, tangent=True, inverse=False) -> Visibility:
    """
    Phase rotate from the current phase centre to a new phase centre

    If tangent is False the uvw are recomputed and the visibility phasecentre is updated.
    Otherwise only the visibility phases are adjusted

    :param vis: Visibility to be rotated
    :param newphasecentre:
    :param tangent: Stay on the same tangent plane? (True)
    :param inverse: Actually do the opposite
    :return: Visibility
    """
    assert isinstance(vis, Visibility), "vis is not a Visibility: %r" % vis

    l, m, n = skycoord_to_lmn(newphasecentre, vis.phasecentre)

    # No significant change?
    if numpy.abs(n) > 1e-15:

        # Make a new copy
        newvis = copy_visibility(vis)

        phasor = simulate_point(newvis.uvw, l, m)
        nvis, npol = vis.vis.shape
        # TODO: Speed up (broadcast rules not obvious to me)
        if inverse:
            for i in range(nvis):
                for pol in range(npol):
                    newvis.data['vis'][i, pol] *= phasor[i]
        else:
            for i in range(nvis):
                for pol in range(npol):
                    newvis.data['vis'][i, pol] *= numpy.conj(phasor[i])
        
        # To rotate UVW, rotate into the global XYZ coordinate system and back. We have the option of
        # staying on the tangent plane or not. If we stay on the tangent then the raster will
        # join smoothly at the edges. If we change the tangent then we will have to reproject to get
        # the results on the same image, in which case overlaps or gaps are difficult to deal with.
        if not tangent:
            if inverse:
                xyz = uvw_to_xyz(vis.data['uvw'], ha=-newvis.phasecentre.ra.rad, dec=newvis.phasecentre.dec.rad)
                newvis.data['uvw'][...] = \
                    xyz_to_uvw(xyz, ha=-newphasecentre.ra.rad, dec=newphasecentre.dec.rad)[...]
            else:
                # This is the original (non-inverse) code
                xyz = uvw_to_xyz(newvis.data['uvw'], ha=-newvis.phasecentre.ra.rad, dec=newvis.phasecentre.dec.rad)
                newvis.data['uvw'][...] = xyz_to_uvw(xyz, ha=-newphasecentre.ra.rad, dec=newphasecentre.dec.rad)[
                    ...]
            newvis.phasecentre = newphasecentre
        return newvis
    else:
        return vis
Example #6
0
def predict_skycomponent_blockvisibility(vis: BlockVisibility,
                                         sc: Union[Skycomponent,
                                                   List[Skycomponent]],
                                         **kwargs) -> BlockVisibility:
    """Predict the visibility from a Skycomponent, add to existing visibility, for BlockVisibility

    :param vis: BlockVisibility
    :param sc: Skycomponent or list of SkyComponents
    :param spectral_mode: {mfs|channel} (channel)
    :return: BlockVisibility
    """
    assert type(
        vis) is BlockVisibility, "vis is not a BlockVisibility: %r" % vis

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

    nchan = vis.nchan
    npol = vis.npol

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

    k = vis.frequency / constants.c.to('m/s').value

    for comp in sc:

        assert_same_chan_pol(vis, comp)

        flux = comp.flux
        if comp.polarisation_frame != vis.polarisation_frame:
            flux = convert_pol_frame(flux, comp.polarisation_frame,
                                     vis.polarisation_frame)

        l, m, n = skycoord_to_lmn(comp.direction, vis.phasecentre)
        for chan in range(nchan):
            phasor = simulate_point(vis.uvw * k[chan], l, m)
            for pol in range(npol):
                vis.data['vis'][..., chan,
                                pol] += flux[chan, pol] * phasor[...]

    return vis
def fit_visibility(vis,
                   sc,
                   tol=1e-6,
                   niter=20,
                   verbose=False,
                   method='trust-exact',
                   **kwargs):
    """Fit a single component to a visibility
    
    Uses the scipy.optimize.minimize function.
    
    :param vis:
    :param sc: Initial component
    :param tol: Tolerance of fit
    :param niter: Number of iterations
    :param verbose:
    :param method: 'CG', 'BFGS', 'Powell', 'trust-ncg', 'trust-exact', 'trust-krylov': default 'trust-exact'
    :param kwargs:
    :return: component, convergence info as a dictionary
    """

    assert vis.polarisation_frame.type == 'stokesI', "Currently restricted to stokesI"

    # These derivative have been calculated using sympy. See visibility_fitting_sympy.py
    def J(params):
        # Params are flux, l, m
        S = params[0]
        l = params[1]
        m = params[2]
        u = vis.u[:, numpy.newaxis]
        v = vis.v[:, numpy.newaxis]
        vobs = vis.vis
        p = numpy.exp(-2j * numpy.pi * (u * l + v * m))
        vres = vobs - S * p
        J = numpy.sum(vis.weight * (vres * numpy.conjugate(vres)).real)
        return J

    def Jboth(params):
        # Params are flux, l, m
        S = params[0]
        l = params[1]
        m = params[2]
        u = vis.u[:, numpy.newaxis]
        v = vis.v[:, numpy.newaxis]
        vobs = vis.vis
        p = numpy.exp(-2j * numpy.pi * (u * l + v * m))
        vres = vobs - S * p
        Vrp = vres * numpy.conjugate(p) * vis.weight
        J = numpy.sum(vis.weight * (vres * numpy.conjugate(vres)).real)
        gradJ = numpy.array([
            -2.0 * numpy.sum(Vrp.real),
            +4.0 * numpy.pi * S * numpy.sum(u * Vrp.imag),
            +4.0 * numpy.pi * S * numpy.sum(v * Vrp.imag)
        ])
        return J, gradJ

    def hessian(params):
        S = params[0]
        l = params[1]
        m = params[2]

        u = vis.u[:, numpy.newaxis]
        v = vis.v[:, numpy.newaxis]
        w = vis.w[:, numpy.newaxis]
        wt = vis.weight

        vobs = vis.vis
        p = numpy.exp(-2j * numpy.pi * (u * l + v * m))
        vres = vobs - S * p
        Vrp = vres * numpy.conjugate(p)

        hess = numpy.zeros([3, 3])
        hess[0, 0] = 2.0 * numpy.sum(wt)

        hess[0, 1] = 4.0 * numpy.pi * numpy.sum(wt * u * Vrp.imag)
        hess[0, 2] = 4.0 * numpy.pi * numpy.sum(wt * v * Vrp.imag)

        hess[1,
             1] = 8.0 * numpy.pi**2 * S * numpy.sum(wt * u**2 * (S + Vrp.real))
        hess[1, 2] = 8.0 * numpy.pi**2 * S * numpy.sum(wt * u * v *
                                                       (S + Vrp.real))
        hess[2,
             2] = 8.0 * numpy.pi**2 * S * numpy.sum(wt * v**2 * (S + Vrp.real))

        hess[1, 0] = hess[0, 1]
        hess[2, 0] = hess[0, 2]
        hess[2, 1] = hess[1, 2]

        return hess

    # Initialize l,m,n to be in the direction of the component as defined in the frame of
    # visibility phasecentre
    l, m, n = skycoord_to_lmn(sc.direction, vis.phasecentre)

    x0 = numpy.array([sc.flux[0, 0], l, m])

    bounds = ((None, None), (-0.1, -0.1), (-0.1, 0.1))
    options = {'maxiter': niter, 'disp': verbose}
    res = {}
    import time
    start = time.time()
    if method == 'BFGS' or method == 'CG' or method == 'Powell':
        res = minimize(J, x0, method=method, options=options, tol=tol)
    elif method == 'Nelder-Mead':
        res = minimize(Jboth, x0, method=method, options=options, tol=tol)
    elif method == 'L-BFGS-B':
        res = minimize(Jboth,
                       x0,
                       method=method,
                       jac=True,
                       bounds=bounds,
                       options=options,
                       tol=tol)
    else:
        res = minimize(Jboth,
                       x0,
                       method=method,
                       jac=True,
                       hess=hessian,
                       options=options,
                       tol=tol)

    if verbose:
        print("Solution for %s took %.6f seconds" %
              (method, time.time() - start))
        print("Solution = %s" % str(res.x))
        print(res)

    sc.flux[...] = res.x[0]
    lmn = (res.x[1], res.x[2], 0.0)
    sc.direction = lmn_to_skycoord(lmn, vis.phasecentre)

    return sc, res
Example #8
0
 def test_skycoord_to_lmn(self):
     center = SkyCoord(ra=0, dec=0, unit=u.deg)
     north = SkyCoord(ra=0, dec=90, unit=u.deg)
     south = SkyCoord(ra=0, dec=-90, unit=u.deg)
     east = SkyCoord(ra=90, dec=0, unit=u.deg)
     west = SkyCoord(ra=-90, dec=0, unit=u.deg)
     assert_allclose(skycoord_to_lmn(center, center), (0, 0, 0))
     assert_allclose(skycoord_to_lmn(north, center), (0, 1, -1))
     assert_allclose(skycoord_to_lmn(south, center), (0, -1, -1))
     assert_allclose(skycoord_to_lmn(south, north), (0, 0, -2), atol=1e-14)
     assert_allclose(skycoord_to_lmn(east, center), (1, 0, -1))
     assert_allclose(skycoord_to_lmn(west, center), (-1, 0, -1))
     assert_allclose(skycoord_to_lmn(center, west), (1, 0, -1))
     assert_allclose(skycoord_to_lmn(north, west), (0, 1, -1), atol=1e-14)
     assert_allclose(skycoord_to_lmn(south, west), (0, -1, -1), atol=1e-14)
     assert_allclose(skycoord_to_lmn(north, east), (0, 1, -1), atol=1e-14)
     assert_allclose(skycoord_to_lmn(south, east), (0, -1, -1), atol=1e-14)