Exemplo n.º 1
0
def predict_skycomponent_visibility(
    vis: Union[Visibility, BlockVisibility], sc: Union[Skycomponent,
                                                       List[Skycomponent]]
) -> Union[Visibility, BlockVisibility]:
    """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 sc is None:
        return vis

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

    if isinstance(vis, Visibility):

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

        for comp in sc:
            assert isinstance(comp, Skycomponent), comp

            assert_same_chan_pol(vis, comp)

            l, m, n = skycoord_to_lmn(comp.direction, vis.phasecentre)
            phasor = simulate_point(vis.uvw, l, m)

            comp = comp.flux[im_nchan, :]
            vis.data['vis'][...] += comp[:, :] * phasor[:, numpy.newaxis]

    elif isinstance(vis, BlockVisibility):

        ntimes, nant, _, nchan, npol = vis.vis.shape

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

        for comp in sc:
            #            assert isinstance(comp, Skycomponent), comp
            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)
            uvw = vis.uvw[..., numpy.newaxis] * k
            phasor = numpy.ones([ntimes, nant, nant, nchan, npol],
                                dtype='complex')
            for chan in range(nchan):
                phasor[:, :, :,
                       chan, :] = simulate_point(uvw[..., chan], l,
                                                 m)[..., numpy.newaxis]

            vis.data['vis'][..., :, :] += flux[:, :] * phasor[..., :]

    return vis
Exemplo n.º 2
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
Exemplo n.º 3
0
def simulate_rfi_block(bvis,
                       emitter_location,
                       emitter_power=5e3,
                       attenuation=1.0):
    """ Simulate RFI block

    :param config: ARL telescope Configuration
    :param times: observation times (hour angles)
    :param frequency: frequencies
    :param phasecentre:
    :param emitter_location: EarthLocation of emitter
    :param emitter_power: Power of emitter
    :param attenuation: Attenuation to be applied to signal
    :return:
    """

    # Calculate the power spectral density of the DTV station: Watts/Hz
    emitter = simulate_Noise(bvis.frequency,
                             bvis.time,
                             power=emitter_power,
                             timevariable=False)

    # Calculate the propagators for signals from Perth to the stations in low
    # These are fixed in time but vary with frequency. The ad hoc attenuation
    # is set to produce signal roughly equal to noise at LOW
    propagators = create_propagators(bvis.configuration,
                                     emitter_location,
                                     frequency=bvis.frequency,
                                     attenuation=attenuation)
    # Now calculate the RFI at the stations, based on the emitter and the propagators
    rfi_at_station = calculate_rfi_at_station(propagators, emitter)

    # Calculate the rfi correlation using the fringe rotation and the rfi at the station
    # [ntimes, nants, nants, nchan, npol]
    bvis.data['vis'][...] = calculate_station_correlation_rfi(rfi_at_station)

    ntimes, nant, _, nchan, npol = bvis.vis.shape

    # Observatory Hour angle & Declination
    pole = SkyCoord(ra=+0.0 * u.deg,
                    dec=-26.0 * u.deg,
                    frame='icrs',
                    equinox='J2000')

    # Calculate phasor needed to shift from the phasecentre to the pole
    l, m, n = skycoord_to_lmn(pole, bvis.phasecentre)
    k = numpy.array(bvis.frequency) / constants.c.to('m s^-1').value
    uvw = bvis.uvw[..., numpy.newaxis] * k
    phasor = numpy.ones([ntimes, nant, nant, nchan, npol], dtype='complex')
    for chan in range(nchan):
        phasor[:, :, :, chan, :] = simulate_point(uvw[..., chan], l,
                                                  m)[..., numpy.newaxis]

    # Now fill this into the BlockVisibility
    bvis.data['vis'] = bvis.data['vis'] * phasor

    return bvis
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)
Exemplo n.º 5
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
Exemplo n.º 6
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?

    assert isinstance(vis, Visibility) or isinstance(vis, BlockVisibility), vis

    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
Exemplo n.º 7
0
def simulate_rfi_block(bvis,
                       emitter_location,
                       emitter_power=5e4,
                       attenuation=1.0,
                       use_pole=False):
    """ Simulate RFI block

    :param config: ARL telescope Configuration
    :param times: observation times (hour angles)
    :param frequency: frequencies
    :param phasecentre:
    :param emitter_location: EarthLocation of emitter
    :param emitter_power: Power of emitter
    :param attenuation: Attenuation to be applied to signal
    :param use_pole: Set the emitter to nbe at the southern celestial pole
    :return:
    """

    # Calculate the power spectral density of the DTV station: Watts/Hz
    emitter = simulate_DTV(bvis.frequency,
                           bvis.time,
                           power=emitter_power,
                           timevariable=False)

    # Calculate the propagators for signals from Perth to the stations in low
    # These are fixed in time but vary with frequency. The ad hoc attenuation
    # is set to produce signal roughly equal to noise at LOW
    propagators = create_propagators(bvis.configuration,
                                     emitter_location,
                                     frequency=bvis.frequency,
                                     attenuation=attenuation)
    # Now calculate the RFI at the stations, based on the emitter and the propagators
    rfi_at_station = calculate_rfi_at_station(propagators, emitter)

    # Calculate the rfi correlation using the fringe rotation and the rfi at the station
    # [ntimes, nants, nants, nchan, npol]
    bvis.data['vis'][...] = calculate_station_correlation_rfi(rfi_at_station)

    ntimes, nant, _, nchan, npol = bvis.vis.shape

    s2r = numpy.pi / 43200.0
    k = numpy.array(bvis.frequency) / constants.c.to('m s^-1').value
    uvw = bvis.uvw[..., numpy.newaxis] * k

    pole = SkyCoord(ra=+0.0 * u.deg,
                    dec=-90.0 * u.deg,
                    frame='icrs',
                    equinox='J2000')

    if use_pole:
        # Calculate phasor needed to shift from the phasecentre to the pole
        l, m, n = skycoord_to_lmn(pole, bvis.phasecentre)
        phasor = numpy.ones([ntimes, nant, nant, nchan, npol], dtype='complex')
        for chan in range(nchan):
            phasor[:, :, :, chan, :] = simulate_point(uvw[..., chan], l,
                                                      m)[..., numpy.newaxis]

        # Now fill this into the BlockVisibility
        bvis.data['vis'] = bvis.data['vis'] * phasor
    else:
        # We know where the emitter is. Calculate the bearing to the emitter from
        # the site, generate az, el, and convert to ha, dec. ha, dec is static.
        site = bvis.configuration.location
        site_tup = (site.lat.deg, site.lon.deg)
        emitter_tup = (emitter_location.lat.deg, emitter_location.lon.deg)
        az = -calculate_initial_compass_bearing(site_tup,
                                                emitter_tup) * numpy.pi / 180.0
        el = 0.0
        hadec = azel_to_hadec(az, el, site.lat.rad)

        # Now step through the time stamps, calculating the effective
        # sky position for the emitter, and performing phase rotation
        # appropriately
        for itime, time in enumerate(bvis.time):
            ra = -hadec[0] + s2r * time
            dec = hadec[1]
            emitter_sky = SkyCoord(ra * u.rad, dec * u.rad)
            l, m, n = skycoord_to_lmn(emitter_sky, bvis.phasecentre)

            phasor = numpy.ones([nant, nant, nchan, npol], dtype='complex')
            for chan in range(nchan):
                phasor[:, :, chan, :] = simulate_point(uvw[itime, ..., chan],
                                                       l, m)[...,
                                                             numpy.newaxis]

            # Now fill this into the BlockVisibility
            bvis.data['vis'][itime,
                             ...] = bvis.data['vis'][itime, ...] * phasor

    return bvis
Exemplo n.º 8
0
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
Exemplo n.º 9
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")
Exemplo n.º 10
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)