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_flux = comp.flux[im_nchan, :] vis.data['vis'][...] += comp_flux[:, :] * 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
def idft_visibility_skycomponent(vis: Union[Visibility, BlockVisibility], sc: Union[Skycomponent, List[Skycomponent]]) -> \ ([Skycomponent, List[Skycomponent]], List[numpy.ndarray]): """Inverse DFT a Skycomponent from Visibility or BlockVisibility :param vis: Visibility or BlockVisibility :param sc: Skycomponent or list of SkyComponents :return: Skycomponent or list of SkyComponents, array of weights """ if sc is None: return sc if not isinstance(sc, collections.abc.Iterable): sc = [sc] newsc = list() weights_list = list() for comp in sc: assert isinstance(comp, Skycomponent), comp assert_same_chan_pol(vis, comp) newcomp = copy_skycomponent(comp) if isinstance(vis, Visibility): flux = numpy.zeros_like(comp.flux, dtype='complex') weight = numpy.zeros_like(comp.flux, dtype='float') _, im_nchan = list(get_frequency_map(vis, None)) phasor = numpy.conjugate( calculate_visibility_phasor(comp.direction, vis)) fvwp = vis.flagged_weight * vis.flagged_vis * phasor fw = vis.flagged_weight for row in range(vis.nvis): ic = im_nchan[row] flux[ic, :] += fvwp[row, :] weight[ic, :] += fw[row, :] elif isinstance(vis, BlockVisibility): phasor = numpy.conjugate( calculate_blockvisibility_phasor(comp.direction, vis)) flux = numpy.sum(vis.flagged_weight * vis.flagged_vis * phasor, axis=(0, 1, 2)) weight = numpy.sum(vis.flagged_weight, axis=(0, 1, 2)) flux[weight > 0.0] = flux[weight > 0.0] / weight[weight > 0.0] flux[weight <= 0.0] = 0.0 if comp.polarisation_frame != vis.polarisation_frame: flux = convert_pol_frame(flux, vis.polarisation_frame, comp.polarisation_frame) newcomp.flux = flux newsc.append(newcomp) weights_list.append(weight) return newsc, weights_list
def apply_beam_to_skycomponent(sc: Union[Skycomponent, List[Skycomponent]], beam: Image) \ -> Union[Skycomponent, List[Skycomponent]]: """ Insert a Skycomponent into an image :param beam: :param sc: SkyComponent or list of SkyComponents :return: List of skycomponents """ assert isinstance(beam, Image) single = not isinstance(sc, collections.Iterable) if single: sc = [sc] nchan, npol, ny, nx = beam.shape log.debug('apply_beam_to_skycomponent: Processing %d components' % (len(sc))) ras = [comp.direction.ra.radian for comp in sc] decs = [comp.direction.dec.radian for comp in sc] skycoords = SkyCoord(ras * u.rad, decs * u.rad, frame='icrs') pixlocs = skycoord_to_pixel(skycoords, beam.wcs, origin=1, mode='wcs') newsc = [] total_flux = numpy.zeros([nchan, npol]) for icomp, comp in enumerate(sc): assert comp.shape == 'Point', "Cannot handle shape %s" % comp.shape assert_same_chan_pol(beam, comp) pixloc = (pixlocs[0][icomp], pixlocs[1][icomp]) if not numpy.isnan(pixloc).any(): x, y = int(round(float(pixloc[0]))), int(round(float(pixloc[1]))) if 0 <= x < nx and 0 <= y < ny: comp.flux[:, :] *= beam.data[:, :, y, x] total_flux += comp.flux newsc.append( Skycomponent(comp.direction, comp.frequency, comp.name, comp.flux, shape=comp.shape, polarisation_frame=comp.polarisation_frame)) log.debug('apply_beam_to_skycomponent: %d components with total flux %s' % (len(newsc), total_flux)) if single: return newsc[0] else: return newsc
def dft_skycomponent_visibility(vis: Union[Visibility, BlockVisibility], sc: Union[Skycomponent, List[Skycomponent]]) \ -> Union[Visibility, BlockVisibility]: """DFT to get the visibility from a Skycomponent, 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.abc.Iterable): sc = [sc] for comp in sc: assert_same_chan_pol(vis, comp) assert isinstance(comp, Skycomponent), comp flux = comp.flux if comp.polarisation_frame != vis.polarisation_frame: flux = convert_pol_frame(flux, comp.polarisation_frame, vis.polarisation_frame) if isinstance(vis, Visibility): _, im_nchan = list(get_frequency_map(vis, None)) phasor = calculate_visibility_phasor(comp.direction, vis) for row in range(vis.nvis): ic = im_nchan[row] vis.data['vis'][row, :] += flux[ic, :] * phasor[row] elif isinstance(vis, BlockVisibility): phasor = calculate_blockvisibility_phasor(comp.direction, vis) vis.data['vis'] += flux * phasor return vis
def insert_skycomponent(im: Image, sc: Union[Skycomponent, List[Skycomponent]], insert_method='Nearest', bandwidth=1.0, support=8) -> Image: """ Insert a Skycomponent into an image :param im: :param sc: SkyComponent or list of SkyComponents :param insert_method: '' | 'Sinc' | 'Lanczos' :param bandwidth: Fractional of uv plane to optimise over (1.0) :param support: Support of kernel (7) :return: image """ assert isinstance(im, Image) support = int(support / bandwidth) nchan, npol, ny, nx = im.data.shape if not isinstance(sc, collections.Iterable): sc = [sc] log.debug("insert_skycomponent: Using insert method %s" % insert_method) image_frequency = im.frequency ras = [comp.direction.ra.radian for comp in sc] decs = [comp.direction.dec.radian for comp in sc] skycoords = SkyCoord(ras * u.rad, decs * u.rad, frame='icrs') pixlocs = skycoord_to_pixel(skycoords, im.wcs, origin=0, mode='wcs') for icomp, comp in enumerate(sc): assert comp.shape == 'Point', "Cannot handle shape %s" % comp.shape assert_same_chan_pol(im, comp) pixloc = (pixlocs[0][icomp], pixlocs[1][icomp]) flux = numpy.zeros([nchan, npol]) if comp.flux.shape[0] > 1: for pol in range(npol): fint = interpolate.interp1d(comp.frequency, comp.flux[:, pol], kind="cubic") flux[:, pol] = fint(image_frequency) else: flux = comp.flux if insert_method == "Lanczos": insert_array(im.data, pixloc[0], pixloc[1], flux, bandwidth, support, insert_function=insert_function_L) elif insert_method == "Sinc": insert_array(im.data, pixloc[0], pixloc[1], flux, bandwidth, support, insert_function=insert_function_sinc) elif insert_method == "PSWF": insert_array(im.data, pixloc[0], pixloc[1], flux, bandwidth, support, insert_function=insert_function_pswf) else: insert_method = 'Nearest' y, x = numpy.round(pixloc[1]).astype('int'), numpy.round( pixloc[0]).astype('int') if 0 <= x < nx and 0 <= y < ny: im.data[:, :, y, x] += flux[...] return im
def apply_voltage_pattern_to_skycomponent(sc: Union[Skycomponent, List[Skycomponent]], vp: Image, inverse=False) \ -> Union[Skycomponent, List[Skycomponent]]: """ Apply a voltage pattern to a Skycomponent For inverse==False, input polarisation_frame must be stokesIQUV, and output polarisation_frame is same as voltage pattern For inverse==True, input polarisation_frame must be same as voltage pattern, and output polarisation_frame is "stokesIQUV" Requires a complex Image with the correct ordering of polarisation axes: e.g. RR, LL, RL, LR or XX, YY, XY, YX :param vp: voltage pattern as complex image :param sc: SkyComponent or list of SkyComponents :return: List of skycomponents """ assert isinstance(vp, Image) assert (vp.polarisation_frame == PolarisationFrame("linear")) or \ (vp.polarisation_frame == PolarisationFrame("circular")) assert vp.data.dtype == "complex128" single = not isinstance(sc, collections.abc.Iterable) if single: sc = [sc] nchan, npol, ny, nx = vp.shape log.debug('apply_vp_to_skycomponent: Processing %d components' % (len(sc))) ras = [comp.direction.ra.radian for comp in sc] decs = [comp.direction.dec.radian for comp in sc] skycoords = SkyCoord(ras * u.rad, decs * u.rad, frame='icrs') pixlocs = skycoord_to_pixel(skycoords, vp.wcs, origin=1, mode='wcs') newsc = [] total_flux = numpy.zeros([nchan, npol], dtype="complex") for icomp, comp in enumerate(sc): assert comp.shape == 'Point', "Cannot handle shape %s" % comp.shape assert_same_chan_pol(vp, comp) # Convert to linear (xx, xy, yx, yy) or circular (rr, rl, lr, ll) nchan, npol = comp.flux.shape assert npol == 4 if not inverse: assert comp.polarisation_frame == PolarisationFrame("stokesIQUV") comp_flux_cstokes = \ convert_pol_frame(comp.flux, comp.polarisation_frame, vp.polarisation_frame).reshape([nchan, 2, 2]) comp_flux = numpy.zeros([nchan, npol], dtype='complex') pixloc = (pixlocs[0][icomp], pixlocs[1][icomp]) if not numpy.isnan(pixloc).any(): x, y = int(round(float(pixloc[0]))), int(round(float(pixloc[1]))) if 0 <= x < nx and 0 <= y < ny: # Now we want to left and right multiply by the Jones matrices # comp_flux = vp.data[:, :, y, x] * comp_flux_cstokes * numpy.vp.data[:, :, y, x] for chan in range(nchan): ej = vp.data[chan, :, y, x].reshape([2, 2]) cfs = comp_flux_cstokes[chan].reshape([2, 2]) comp_flux[chan, :] = apply_jones(ej, cfs, inverse).reshape([4]) total_flux += comp_flux if inverse: comp_flux = convert_pol_frame( comp_flux, vp.polarisation_frame, PolarisationFrame("stokesIQUV")) comp.polarisation_frame = PolarisationFrame("stokesIQUV") newsc.append( Skycomponent(comp.direction, comp.frequency, comp.name, comp_flux, shape=comp.shape, polarisation_frame=vp.polarisation_frame)) log.debug('apply_vp_to_skycomponent: %d components with total flux %s' % (len(newsc), total_flux)) if single: return newsc[0] else: return newsc