Esempio n. 1
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)

        if len(newvis.vis.shape) > len(phasor.shape):
            phasor = phasor[:, numpy.newaxis]

        if inverse:
            newvis.data['vis'] *= phasor
        else:
            newvis.data['vis'] *= numpy.conj(phasor)

        # 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
Esempio n. 2
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)
def calculate_station_fringe_rotation(ants_xyz, times, frequency, phasecentre,
                                      pole):
    # Time corresponds to hour angle

    uvw = xyz_to_uvw(ants_xyz, times, phasecentre.dec.rad)
    nants, nuvw = uvw.shape
    ntimes = len(times)
    uvw = uvw.reshape([nants, ntimes, 3])
    lmn = skycoord_to_lmn(phasecentre, pole)
    delay = numpy.dot(uvw, lmn)
    nchan = len(frequency)
    phase = numpy.zeros([nants, ntimes, nchan])
    for ant in range(nants):
        for chan in range(nchan):
            phase[ant, :,
                  chan] = delay[ant] * frequency[chan] / constants.c.value
    return numpy.exp(2.0 * numpy.pi * 1j * phase)
Esempio n. 4
0
def find_pierce_points(station_locations, ha, dec, phasecentre, height):
    """Find the pierce points for a flat screen at specified height
    
    :param station_locations: All station locations [:3]
    :param ha: Hour angle
    :param dec: Declination
    :param phasecentre: Phase centre
    :param height: Height of screen
    :return:
    """
    source_direction = SkyCoord(ra=ha, dec=dec, frame='icrs', equinox='J2000')
    local_locations = xyz_to_uvw(station_locations, ha, dec)
    local_locations -= numpy.average(local_locations, axis=0)

    lmn = numpy.array(skycoord_to_lmn(source_direction, phasecentre))
    lmn[2] += 1.0
    pierce_points = local_locations + height * numpy.array(lmn)
    return pierce_points
Esempio n. 5
0
        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
Esempio n. 6
0
def create_visibility(config: Configuration,
                      times: numpy.array,
                      frequency: numpy.array,
                      channel_bandwidth,
                      phasecentre: SkyCoord,
                      weight: float,
                      polarisation_frame=PolarisationFrame('stokesI'),
                      integration_time=1.0,
                      zerow=False) -> Visibility:
    """ Create a Visibility from Configuration, hour angles, and direction of source

    Note that we keep track of the integration time for BDA purposes

    :param config: Configuration of antennas
    :param times: hour angles in radians
    :param frequency: frequencies (Hz] [nchan]
    :param weight: weight of a single sample
    :param phasecentre: phasecentre of observation
    :param channel_bandwidth: channel bandwidths: (Hz] [nchan]
    :param integration_time: Integration time ('auto' or value in s)
    :param polarisation_frame: PolarisationFrame('stokesI')
    :return: Visibility
    """
    assert phasecentre is not None, "Must specify phase centre"

    if polarisation_frame is None:
        polarisation_frame = correlate_polarisation(config.receptor_frame)

    nch = len(frequency)
    ants_xyz = config.data['xyz']
    nants = len(config.data['names'])
    nbaselines = int(nants * (nants - 1) / 2)
    ntimes = len(times)
    npol = polarisation_frame.npol
    nrows = nbaselines * ntimes * nch
    nrowsperintegration = nbaselines * nch
    row = 0
    rvis = numpy.zeros([nrows, npol], dtype='complex')
    rweight = weight * numpy.ones([nrows, npol])
    rtimes = numpy.zeros([nrows])
    rfrequency = numpy.zeros([nrows])
    rchannel_bandwidth = numpy.zeros([nrows])
    rantenna1 = numpy.zeros([nrows], dtype='int')
    rantenna2 = numpy.zeros([nrows], dtype='int')
    ruvw = numpy.zeros([nrows, 3])

    # Do each hour angle in turn
    for iha, ha in enumerate(times):

        # Calculate the positions of the antennas as seen for this hour angle
        # and declination
        ant_pos = xyz_to_uvw(ants_xyz, ha, phasecentre.dec.rad)
        rtimes[row:row + nrowsperintegration] = ha * 43200.0 / numpy.pi

        # Loop over all pairs of antennas. Note that a2>a1
        for a1 in range(nants):
            for a2 in range(a1 + 1, nants):
                rantenna1[row:row + nch] = a1
                rantenna2[row:row + nch] = a2

                # Loop over all frequencies and polarisations
                for ch in range(nch):
                    # noinspection PyUnresolvedReferences
                    k = frequency[ch] / constants.c.value
                    ruvw[row, :] = (ant_pos[a2, :] - ant_pos[a1, :]) * k
                    rfrequency[row] = frequency[ch]
                    rchannel_bandwidth[row] = channel_bandwidth[ch]
                    row += 1

    if zerow:
        ruvw[..., 2] = 0.0
    assert row == nrows
    rintegration_time = numpy.full_like(rtimes, integration_time)
    vis = Visibility(uvw=ruvw,
                     time=rtimes,
                     antenna1=rantenna1,
                     antenna2=rantenna2,
                     frequency=rfrequency,
                     vis=rvis,
                     weight=rweight,
                     imaging_weight=rweight,
                     integration_time=rintegration_time,
                     channel_bandwidth=rchannel_bandwidth,
                     polarisation_frame=polarisation_frame)
    vis.phasecentre = phasecentre
    vis.configuration = config
    log.info("create_visibility: %s" % (vis_summary(vis)))
    assert isinstance(vis, Visibility), "vis is not a Visibility: %r" % vis
    return vis
Esempio n. 7
0
def create_blockvisibility(config: Configuration,
                           times: numpy.array,
                           frequency: numpy.array,
                           phasecentre: SkyCoord,
                           weight: float = 1.0,
                           polarisation_frame: PolarisationFrame = None,
                           integration_time=1.0,
                           channel_bandwidth=1e6,
                           zerow=False,
                           **kwargs) -> BlockVisibility:
    """ Create a BlockVisibility from Configuration, hour angles, and direction of source

    Note that we keep track of the integration time for BDA purposes

    :param config: Configuration of antennas
    :param times: hour angles in radians
    :param frequency: frequencies (Hz] [nchan]
    :param weight: weight of a single sample
    :param phasecentre: phasecentre of observation
    :param channel_bandwidth: channel bandwidths: (Hz] [nchan]
    :param integration_time: Integration time ('auto' or value in s)
    :param polarisation_frame:
    :return: BlockVisibility
    """
    assert phasecentre is not None, "Must specify phase centre"

    if polarisation_frame is None:
        polarisation_frame = correlate_polarisation(config.receptor_frame)

    nch = len(frequency)
    ants_xyz = config.data['xyz']
    nants = len(config.data['names'])
    ntimes = len(times)
    npol = polarisation_frame.npol
    visshape = [ntimes, nants, nants, nch, npol]
    rvis = numpy.zeros(visshape, dtype='complex')
    rweight = weight * numpy.ones(visshape)
    rtimes = numpy.zeros([ntimes])
    ruvw = numpy.zeros([ntimes, nants, nants, 3])

    # Do each hour angle in turn
    for iha, ha in enumerate(times):

        # Calculate the positions of the antennas as seen for this hour angle
        # and declination
        ant_pos = xyz_to_uvw(ants_xyz, ha, phasecentre.dec.rad)
        rtimes[iha] = ha * 43200.0 / numpy.pi

        # Loop over all pairs of antennas. Note that a2>a1
        for a1 in range(nants):
            for a2 in range(a1 + 1, nants):
                ruvw[iha, a2, a1, :] = (ant_pos[a2, :] - ant_pos[a1, :])
                ruvw[iha, a1, a2, :] = (ant_pos[a1, :] - ant_pos[a2, :])

    rintegration_time = numpy.full_like(rtimes, integration_time)
    rchannel_bandwidth = numpy.full_like(frequency, channel_bandwidth)
    if zerow:
        ruvw[..., 2] = 0.0
    vis = BlockVisibility(uvw=ruvw,
                          time=rtimes,
                          frequency=frequency,
                          vis=rvis,
                          weight=rweight,
                          integration_time=rintegration_time,
                          channel_bandwidth=rchannel_bandwidth,
                          polarisation_frame=polarisation_frame)
    vis.phasecentre = phasecentre
    vis.configuration = config
    log.info("create_blockvisibility: %s" % (vis_summary(vis)))
    assert isinstance(
        vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis

    return vis
Esempio n. 8
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
    """
    l, m, n = skycoord_to_lmn(newphasecentre, vis.phasecentre)

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

    # Make a new copy
    newvis = copy_visibility(vis)

    if isinstance(vis, Visibility):
        phasor = simulate_point(newvis.uvw, l, m)
        
        if len(newvis.vis.shape) > len(phasor.shape):
            phasor = phasor[:, numpy.newaxis]
        
        if inverse:
            newvis.data['vis'] *= phasor
        else:
            newvis.data['vis'] *= numpy.conj(phasor)
        
        # 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

    elif isinstance(vis, BlockVisibility):
        
        k = numpy.array(vis.frequency) / constants.c.to('m s^-1').value

        uvw = vis.uvw[..., numpy.newaxis] * k
        phasor = numpy.ones_like(vis.vis, dtype='complex')
        _, _, _, nchan, npol = vis.vis.shape
        for chan in range(nchan):
            phasor[:, :, :, chan, :] = simulate_point(uvw[..., chan], l, m)[..., numpy.newaxis]

        if inverse:
            newvis.data['vis'] *= phasor
        else:
            newvis.data['vis'] *= numpy.conj(phasor)
        
        # 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:
            # UVW is shape [nants, nants, 3], we want [nants * nants, 3]
            nrows, nants, _, _ = vis.uvw.shape
            uvw_linear = vis.uvw.reshape([nrows * nants * nants, 3])
            if inverse:
                xyz = uvw_to_xyz(uvw_linear, ha=-newvis.phasecentre.ra.rad, dec=newvis.phasecentre.dec.rad)
                uvw_linear = \
                    xyz_to_uvw(xyz, ha=-newphasecentre.ra.rad, dec=newphasecentre.dec.rad)[...]
            else:
                # This is the original (non-inverse) code
                xyz = uvw_to_xyz(uvw_linear, ha=-newvis.phasecentre.ra.rad, dec=newvis.phasecentre.dec.rad)
                uvw_linear = \
                    xyz_to_uvw(xyz, ha=-newphasecentre.ra.rad, dec=newphasecentre.dec.rad)[...]
            newvis.phasecentre = newphasecentre
            newvis.data['uvw'][...] = uvw_linear.reshape([nrows, nants, nants, 3])
        return newvis
    else:
        raise ValueError("vis argument neither Visibility or BlockVisibility")
Esempio n. 9
0
def create_blockvisibility(config: Configuration,
                           times: numpy.array,
                           frequency: numpy.array,
                           phasecentre: SkyCoord,
                           weight: float = 1.0,
                           polarisation_frame: PolarisationFrame = None,
                           integration_time=1.0,
                           channel_bandwidth=1e6,
                           zerow=False,
                           elevation_limit=None,
                           source='unknown',
                           meta=None,
                           **kwargs) -> BlockVisibility:
    """ Create a BlockVisibility from Configuration, hour angles, and direction of source

    Note that we keep track of the integration time for BDA purposes

    :param config: Configuration of antennas
    :param times: hour angles in radians
    :param frequency: frequencies (Hz] [nchan]
    :param weight: weight of a single sample
    :param phasecentre: phasecentre of observation
    :param channel_bandwidth: channel bandwidths: (Hz] [nchan]
    :param integration_time: Integration time ('auto' or value in s)
    :param polarisation_frame:
    :return: BlockVisibility
    """
    assert phasecentre is not None, "Must specify phase centre"
    
    if polarisation_frame is None:
        polarisation_frame = correlate_polarisation(config.receptor_frame)
    
    latitude = config.location.geodetic[1].to('rad').value
    nch = len(frequency)
    ants_xyz = config.data['xyz']
    nants = len(config.data['names'])

    ntimes = 0
    n_flagged = 0
    for iha, ha in enumerate(times):
    
        # Calculate the positions of the antennas as seen for this hour angle
        # and declination
        _, elevation = hadec_to_azel(ha, phasecentre.dec.rad, latitude)
        if elevation_limit is None or (elevation > elevation_limit):
            ntimes +=1
        else:
            n_flagged += 1

    assert ntimes > 0, "No unflagged points"
    if elevation_limit is not None:
        log.info('create_visibility: flagged %d/%d times below elevation limit %f (rad)' %
                (n_flagged, ntimes, elevation_limit))
    else:
        log.info('create_visibility: created %d times' % (ntimes))
    
    npol = polarisation_frame.npol
    visshape = [ntimes, nants, nants, nch, npol]
    rvis = numpy.zeros(visshape, dtype='complex')
    rweight = weight * numpy.ones(visshape)
    rimaging_weight = numpy.ones(visshape)
    rtimes = numpy.zeros([ntimes])
    ruvw = numpy.zeros([ntimes, nants, nants, 3])
    
    # Do each hour angle in turn
    itime = 0
    for iha, ha in enumerate(times):
        
        # Calculate the positions of the antennas as seen for this hour angle
        # and declination
        ant_pos = xyz_to_uvw(ants_xyz, ha, phasecentre.dec.rad)
        _, elevation = hadec_to_azel(ha, phasecentre.dec.rad, latitude)
        if elevation_limit is None or (elevation > elevation_limit):
            rtimes[itime] = ha * 43200.0 / numpy.pi
            rweight[itime, ...] = 1.0

            # Loop over all pairs of antennas. Note that a2>a1
            for a1 in range(nants):
                for a2 in range(a1 + 1, nants):
                    ruvw[itime, a2, a1, :] = (ant_pos[a2, :] - ant_pos[a1, :])
                    ruvw[itime, a1, a2, :] = (ant_pos[a1, :] - ant_pos[a2, :])
            itime += 1
    
    rintegration_time = numpy.full_like(rtimes, integration_time)
    rchannel_bandwidth = channel_bandwidth
    if zerow:
        ruvw[..., 2] = 0.0
    vis = BlockVisibility(uvw=ruvw, time=rtimes, frequency=frequency, vis=rvis, weight=rweight,
                          imaging_weight=rimaging_weight,
                          integration_time=rintegration_time, channel_bandwidth=rchannel_bandwidth,
                          polarisation_frame=polarisation_frame, source=source, meta=meta)
    vis.phasecentre = phasecentre
    vis.configuration = config
    log.info("create_blockvisibility: %s" % (vis_summary(vis)))
    assert isinstance(vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis

    return vis