def test_divide_visibility(self): self.vis = create_blockvisibility( self.lowcore, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, weight=1.0, polarisation_frame=PolarisationFrame("stokesIQUV")) self.vis.data['vis'][..., :] = [2.0 + 0.0j, 0.0j, 0.0j, 2.0 + 0.0j] self.othervis = create_blockvisibility( self.lowcore, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, weight=1.0, polarisation_frame=PolarisationFrame("stokesIQUV")) self.othervis.data['vis'][..., :] = [ 1.0 + 0.0j, 0.0j, 0.0j, 1.0 + 0.0j ] self.ratiovis = divide_visibility(self.vis, self.othervis) assert self.ratiovis.nvis == self.vis.nvis assert numpy.max(numpy.abs(self.ratiovis.vis)) == 2.0, numpy.max( numpy.abs(self.ratiovis.vis))
def test_solve_gaintable_stokesI_pointsource(self): self.actualSetup('stokesI', 'stokesI', f=[100.0]) gt = create_gaintable_from_blockvisibility(self.vis) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=10.0, amplitude_error=0.0) original = copy_visibility(self.vis) self.vis = apply_gaintable(self.vis, gt) point_vis = divide_visibility(self.vis, original) gtsol = solve_gaintable(point_vis, phase_only=False, niter=200) residual = numpy.max(gtsol.residual) assert residual < 3e-8, "Max residual = %s" % (residual) assert numpy.max(numpy.abs(gtsol.gain - 1.0)) > 0.1
def solve_gaintable(vis: BlockVisibility, modelvis: BlockVisibility = None, gt=None, phase_only=True, niter=30, tol=1e-8, crosspol=False, normalise_gains=True, **kwargs) -> GainTable: """Solve a gain table by fitting an observed visibility to a model visibility If modelvis is None, a point source model is assumed. :param vis: BlockVisibility containing the observed data_models :param modelvis: BlockVisibility containing the visibility predicted by a model :param gt: Existing gaintable :param phase_only: Solve only for the phases (default=True) :param niter: Number of iterations (default 30) :param tol: Iteration stops when the fractional change in the gain solution is below this tolerance :param crosspol: Do solutions including cross polarisations i.e. XY, YX or RL, LR :return: GainTable containing solution """ assert isinstance(vis, BlockVisibility), vis if modelvis is not None: assert isinstance(modelvis, BlockVisibility), modelvis assert numpy.max(numpy.abs( modelvis.vis)) > 0.0, "Model visibility is zero" if phase_only: log.debug('solve_gaintable: Solving for phase only') else: log.debug('solve_gaintable: Solving for complex gain') if gt is None: log.debug("solve_gaintable: creating new gaintable") gt = create_gaintable_from_blockvisibility(vis, **kwargs) else: log.debug("solve_gaintable: starting from existing gaintable") if modelvis is not None: pointvis = divide_visibility(vis, modelvis) else: pointvis = vis for row in range(gt.ntimes): vis_rows = numpy.abs(vis.time - gt.time[row]) < gt.interval[row] / 2.0 if numpy.sum(vis_rows) > 0: x = numpy.sum( (pointvis.vis[vis_rows] * pointvis.weight[vis_rows]) * (1 - pointvis.flags[vis_rows]), axis=0) xwt = numpy.sum(pointvis.weight[vis_rows] * (1 - pointvis.flags[vis_rows]), axis=0) mask = numpy.abs(xwt) > 0.0 if numpy.sum(mask) > 0: x_shape = x.shape x[mask] = x[mask] / xwt[mask] x[~mask] = 0.0 xwt[mask] = xwt[mask] / numpy.max(xwt[mask]) x = x.reshape(x_shape) if vis.npol == 1: gt.data['gain'][row, ...], gt.data['weight'][row, ...], gt.data['residual'][row, ...] = \ solve_antenna_gains_itsubs_scalar(gt.data['gain'][row, ...], gt.data['weight'][row, ...], x, xwt, phase_only=phase_only, niter=niter, tol=tol) elif vis.npol == 2: gt.data['gain'][row, ...], gt.data['weight'][row, ...], gt.data['residual'][row, ...] = \ solve_antenna_gains_itsubs_nocrossdata(gt.data['gain'][row, ...], gt.data['weight'][row, ...], x, xwt, phase_only=phase_only, niter=niter, tol=tol) elif vis.npol == 4: if crosspol: gt.data['gain'][row, ...], gt.data['weight'][row, ...], gt.data['residual'][row, ...] = \ solve_antenna_gains_itsubs_matrix(gt.data['gain'][row, ...], gt.data['weight'][row, ...], x, xwt, phase_only=phase_only, niter=niter, tol=tol) else: gt.data['gain'][row, ...], gt.data['weight'][row, ...], gt.data['residual'][row, ...] = \ solve_antenna_gains_itsubs_vector(gt.data['gain'][row, ...], gt.data['weight'][row, ...], x, xwt, phase_only=phase_only, niter=niter, tol=tol) else: gt.data['gain'][row, ...], gt.data['weight'][row, ...], \ gt.data['residual'][row, ...] = \ solve_antenna_gains_itsubs_scalar(gt.data['gain'][row, ...], gt.data['weight'][row, ...], x, xwt, phase_only=phase_only, niter=niter, tol=tol) if normalise_gains and not phase_only: gabs = numpy.average(numpy.abs(gt.data['gain'][row])) gt.data['gain'][row] /= gabs else: gt.data['gain'][row, ...] = 1.0 + 0.0j gt.data['weight'][row, ...] = 0.0 gt.data['residual'][row, ...] = 0.0 else: log.warning("Gaintable {0}, vis time mismatch {1}".format( gt.time, vis.time)) assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt assert_vis_gt_compatible(vis, gt) return gt
def solve_gaintable(vis: BlockVisibility, modelvis: BlockVisibility = None, gt=None, phase_only=True, niter=30, tol=1e-8, crosspol=False, normalise_gains=True, **kwargs) -> GainTable: """Solve a gain table by fitting an observed visibility to a model visibility If modelvis is None, a point source model is assumed. :param vis: BlockVisibility containing the observed data_models :param modelvis: BlockVisibility containing the visibility predicted by a model :param gt: Existing gaintable :param phase_only: Solve only for the phases (default=True) :param niter: Number of iterations (default 30) :param tol: Iteration stops when the fractional change in the gain solution is below this tolerance :param crosspol: Do solutions including cross polarisations i.e. XY, YX or RL, LR :return: GainTable containing solution """ assert isinstance(vis, BlockVisibility), vis if modelvis is not None: assert isinstance(modelvis, BlockVisibility), modelvis assert numpy.max(numpy.abs( modelvis.vis)) > 0.0, "Model visibility is zero" if phase_only: log.debug('solve_gaintable: Solving for phase only') else: log.debug('solve_gaintable: Solving for complex gain') if gt is None: log.debug("solve_gaintable: creating new gaintable") gt = create_gaintable_from_blockvisibility(vis, **kwargs) else: log.debug("solve_gaintable: starting from existing gaintable") for row in range(gt.ntimes): vis_rows = numpy.abs(vis.time - gt.time[row]) < gt.interval[row] / 2.0 if numpy.sum(vis_rows) > 0: subvis = create_visibility_from_rows(vis, vis_rows) if modelvis is not None: model_subvis = create_visibility_from_rows(modelvis, vis_rows) pointvis = divide_visibility(subvis, model_subvis) x = numpy.sum(pointvis.vis * pointvis.weight, axis=0) xwt = numpy.sum(pointvis.weight, axis=0) else: x = numpy.sum(subvis.vis * subvis.weight, axis=0) xwt = numpy.sum(subvis.weight, axis=0) mask = numpy.abs(xwt) > 0.0 x_shape = x.shape x[mask] = x[mask] / xwt[mask] x[~mask] = 0.0 x = x.reshape(x_shape) gt = solve_from_X(gt, x, xwt, row, crosspol, niter, phase_only, tol, npol=vis.polarisation_frame.npol) if normalise_gains and not phase_only: gabs = numpy.average(numpy.abs(gt.data['gain'][row])) gt.data['gain'][row] /= gabs assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt assert_vis_gt_compatible(vis, gt) return gt