def taper_visibility_tukey(vis: Visibility, tukey=0.1) -> Visibility: """ Taper the visibility weights This algorithm is present in WSClean. See https://sourceforge.net/p/wsclean/wiki/Tapering tukey, a circular taper that smooths the outer edge set by -maxuv-l inner-tukey, a circular taper that smooths the inner edge set by -minuv-l edge-tukey, a square-shaped taper that smooths the edge set by the uv grid and -taper-edge. These are cumulative. If You can reset the imaging_weights using :py:mod:`processing_components.imaging.weighting.weight_visibility` :param vis: Visibility with imaging_weight's to be tapered :return: visibility with imaging_weight column modified """ assert isinstance(vis, Visibility), vis uvdist = numpy.sqrt(vis.u**2 + vis.v**2) uvdistmax = numpy.max(uvdist) uvdist /= uvdistmax wt = numpy.array([tukey_filter(uv, tukey) for uv in uvdist]) vis.data['imaging_weight'][:, :] = vis.imaging_weight[:, :] * wt[:, numpy. newaxis] return vis
def visibility_gather(visibility_list: List[Visibility], vis: Visibility, vis_iter, vis_slices=None) -> Visibility: """Gather a list of subvisibilities back into a visibility The iterator setup must be the same as used in the scatter. :param visibility_list: List of subvisibilities :param vis: Output visibility :param vis_iter: visibility iterator :param vis_slices: Number of slices to be gathered (optional) :return: vis """ if vis_slices == 1: return visibility_list[0] if vis_slices is None: vis_slices = len(visibility_list) rowses = [] for i, rows in enumerate(vis_iter(vis, vis_slices=vis_slices)): rowses.append(rows) for i, rows in enumerate(rowses): assert i < len(visibility_list), "Gather not consistent with scatter for slice %d" % i sum_rows = numpy.sum(numpy.array(rows)).astype('int') if visibility_list[i] is not None and sum_rows > 0: assert sum_rows == visibility_list[i].nvis, \ "Mismatch in number of rows (%d, %d) in gather for slice %d" % \ (int(sum_rows), visibility_list[i].nvis, i) vis.data[rows] = visibility_list[i].data[...] return vis
def convert_blockvisibility_to_visibility(vis: BlockVisibility) -> Visibility: """ Convert the BlockVisibility data with no coalescence :param vis: BlockVisibility to be converted :return: Visibility with cindex and blockvis filled in """ assert isinstance( vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis cvis, cuvw, cwts, cimaging_wts, ctime, cfrequency, cchannel_bandwidth, ca1, ca2, cintegration_time, cindex \ = convert_blocks(vis.data['vis'], vis.data['uvw'], vis.data['weight'], vis.data['imaging_weight'], vis.time, vis.integration_time, vis.frequency, vis.channel_bandwidth) converted_vis = Visibility(uvw=cuvw, time=ctime, frequency=cfrequency, channel_bandwidth=cchannel_bandwidth, phasecentre=vis.phasecentre, antenna1=ca1, antenna2=ca2, vis=cvis, weight=cwts, imaging_weight=cimaging_wts, configuration=vis.configuration, integration_time=cintegration_time, polarisation_frame=vis.polarisation_frame, cindex=cindex, blockvis=vis, meta=vis.meta) log.debug('convert_visibility: Original %s, converted %s' % (vis_summary(vis), vis_summary(converted_vis))) return converted_vis
def taper_visibility_gaussian(vis: Visibility, beam=None) -> Visibility: """ Taper the visibility weights These are cumulative. If You can reset the imaging_weights using :py:mod:`processing_components.imaging.weighting.weight_visibility` :param vis: Visibility with imaging_weight's to be tapered :param beam: desired resolution (Full width half maximum, radians) :return: visibility with imaging_weight column modified """ assert isinstance(vis, Visibility), vis if beam is None: raise ValueError("Beam size not specified for Gaussian taper") uvdistsq = vis.u**2 + vis.v**2 # See http://mathworld.wolfram.com/FourierTransformGaussian.html scale_factor = numpy.pi**2 * beam**2 / (4.0 * numpy.log(2.0)) prior = vis.flagged_imaging_weight[:, :] wt = numpy.exp(-scale_factor * uvdistsq) vis.data[ 'imaging_weight'][:, :] = vis.flagged_imaging_weight[:, :] * wt[:, numpy. newaxis] return vis
def coalesce_visibility(vis: BlockVisibility, **kwargs) -> Visibility: """ Coalesce the BlockVisibility data_models. The output format is a Visibility, as needed for imaging Coalesce by baseline-dependent averaging (optional). The number of integrations averaged goes as the ratio of the maximum possible baseline length to that for this baseline. This number can be scaled by coalescence_factor and limited by max_coalescence. When faceting, the coalescence factors should be roughly the same as the number of facets on one axis. If coalescence_factor=0.0 then just a format conversion is done :param vis: BlockVisibility to be coalesced :return: Coalesced visibility with cindex and blockvis filled in """ assert isinstance( vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis time_coal = get_parameter(kwargs, 'time_coal', 0.0) max_time_coal = get_parameter(kwargs, 'max_time_coal', 100) frequency_coal = get_parameter(kwargs, 'frequency_coal', 0.0) max_frequency_coal = get_parameter(kwargs, 'max_frequency_coal', 100) if time_coal == 0.0 and frequency_coal == 0.0: return convert_blockvisibility_to_visibility((vis)) cvis, cuvw, cwts, cimwt, ctime, cfrequency, cchannel_bandwidth, ca1, ca2, cintegration_time, cindex \ = average_in_blocks(vis.data['vis'], vis.data['uvw'], vis.data['weight'], vis.data['imaging_weight'], vis.time, vis.integration_time, vis.frequency, vis.channel_bandwidth, time_coal, max_time_coal, frequency_coal, max_frequency_coal) coalesced_vis = Visibility(uvw=cuvw, time=ctime, frequency=cfrequency, channel_bandwidth=cchannel_bandwidth, phasecentre=vis.phasecentre, antenna1=ca1, antenna2=ca2, vis=cvis, weight=cwts, imaging_weight=cimwt, configuration=vis.configuration, integration_time=cintegration_time, polarisation_frame=vis.polarisation_frame, cindex=cindex, blockvis=vis, meta=vis.meta) log.debug( 'coalesce_visibility: Created new Visibility for coalesced data_models, coalescence factors (t,f) = (%.3f,%.3f)' % (time_coal, frequency_coal)) log.debug('coalesce_visibility: Maximum coalescence (t,f) = (%d, %d)' % (max_time_coal, max_frequency_coal)) log.debug('coalesce_visibility: Original %s, coalesced %s' % (vis_summary(vis), vis_summary(coalesced_vis))) return coalesced_vis
def convert_hdf_to_visibility(f): """ Convert HDF root to visibility :param f: :return: """ assert f.attrs['RASCIL_data_model'] == "Visibility", "Not a Visibility" s = f.attrs['phasecentre_coords'].split() ss = [float(s[0]), float(s[1])] * u.deg phasecentre = SkyCoord(ra=ss[0], dec=ss[1], frame=f.attrs['phasecentre_frame']) polarisation_frame = PolarisationFrame(f.attrs['polarisation_frame']) data = numpy.array(f['data']) source = str(f.attrs['source']) meta = ast.literal_eval(f.attrs['meta']) vis = Visibility(data=data, polarisation_frame=polarisation_frame, phasecentre=phasecentre, source=source, meta=meta) vis.configuration = convert_configuration_from_hdf(f) return vis
def convert_visibility_to_stokesI(vis): """Convert the polarisation frame data into Stokes I dropping other polarisations, return new Visibility :param vis: Visibility :return: Converted visibility data. """ polarisation_frame = PolarisationFrame('stokesI') poldef = vis.polarisation_frame if poldef == PolarisationFrame('linear'): vis_data = convert_linear_to_stokesI(vis.data['vis']) vis_flags = numpy.logical_or(vis.flags[..., 0], vis.flags[..., 3])[..., numpy.newaxis] vis_weight = (vis.flagged_weight[..., 0] + vis.flagged_weight[..., 3])[..., numpy.newaxis] vis_imaging_weight = ( vis.flagged_imaging_weight[..., 0] + vis.flagged_imaging_weight[..., 3])[..., numpy.newaxis] elif poldef == PolarisationFrame('circular'): vis_data = convert_circular_to_stokesI(vis.data['vis']) vis_flags = numpy.logical_or(vis.flags[..., 0], vis.flags[..., 3])[..., numpy.newaxis] vis_weight = (vis.flagged_weight[..., 0] + vis.flagged_weight[..., 3])[..., numpy.newaxis] vis_imaging_weight = ( vis.flagged_imaging_weight[..., 0] + vis.flagged_imaging_weight[..., 3])[..., numpy.newaxis] else: raise NameError("Polarisation frame %s unknown" % poldef) return Visibility(frequency=vis.frequency, channel_bandwidth=vis.channel_bandwidth, phasecentre=vis.phasecentre, configuration=vis.configuration, uvw=vis.uvw, time=vis.time, antenna1=vis.antenna1, antenna2=vis.antenna2, vis=vis_data, flags=vis_flags, weight=vis_weight, imaging_weight=vis_imaging_weight, integration_time=vis.integration_time, polarisation_frame=polarisation_frame, cindex=vis.cindex, blockvis=vis.blockvis, source=vis.source, meta=vis.meta)
def import_visibility_from_oskar(oskar_file: str) -> Visibility: """ Import a visibility set from an OSKAR visibility file :param oskar_file: Name of OSKAR visibility file :returns: Visibility """ # Extract data from Oskar file oskar_vis = OskarVis(oskar_file) ra, dec = oskar_vis.phase_centre() a1, a2 = oskar_vis.stations(flatten=True) # Make configuration location = EarthLocation(lon=oskar_vis.telescope_lon, lat=oskar_vis.telescope_lat, height=oskar_vis.telescope_alt) antxyz = numpy.transpose( [oskar_vis.station_x, oskar_vis.station_y, oskar_vis.station_z]) config = Configuration(name=oskar_vis.telescope_path, location=location, xyz=antxyz) # Construct visibilities return Visibility(frequency=[ oskar_vis.frequency(i) for i in range(oskar_vis.num_channels) ], phasecentre=SkyCoord(frame=ICRS, ra=ra, dec=dec, unit=u.deg), configuration=config, uvw=numpy.transpose(oskar_vis.uvw(flatten=True)), time=oskar_vis.times(flatten=True), antenna1=a1, antenna2=a2, vis=oskar_vis.amplitudes(flatten=True), weight=numpy.ones(a1.shape))
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, elevation_limit=15.0 * numpy.pi / 180.0, source='unknown', meta=None) -> 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) latitude = config.location.geodetic[1].to('rad').value nch = len(frequency) ants_xyz = config.data['xyz'] nants = len(config.data['names']) nbaselines = int(nants * (nants - 1) / 2) ntimes = 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 npol = polarisation_frame.npol nrows = nbaselines * ntimes * nch nrowsperintegration = nbaselines * nch 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]) n_flagged = 0 # Do each hour angle in turn row = 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): rtimes[row:row + nrowsperintegration] = ha * 43200.0 / numpy.pi # TODO: optimise loop # Loop over all pairs of antennas. Note that a2>a1 ant_pos = xyz_to_uvw(ants_xyz, ha, phasecentre.dec.rad) for a1 in range(nants): for a2 in range(a1 + 1, nants): rantenna1[row:row + nch] = a1 rantenna2[row:row + nch] = a2 rweight[row:row+nch,...] = 1.0 # 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, source=source, meta=meta) 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 if elevation_limit is not None: log.info('create_visibility: flagged %d/%d visibilities below elevation limit %f (rad)' % (n_flagged, vis.nvis, elevation_limit)) else: log.info('create_visibility: created %d visibilities' % (vis.nvis)) return vis