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
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)
def transform(x, y, z, ha, dec): """ :param x: :param y: :param z: :param ha: :param dec: :return: """ res = xyz_to_uvw(numpy.array([x, y, z]), numpy.radians(ha), numpy.radians(dec)) assert_allclose(numpy.linalg.norm(res), numpy.linalg.norm([x, y, z])) assert_allclose(uvw_to_xyz(res, numpy.radians(ha), numpy.radians(dec)), [x, y, z]) return res