def make_e(vis, calskymodel, evis_all): # Return the estep for a given skymodel evis = copy_visibility(vis) tvis = copy_visibility(vis, zero=True) tvis = predict_skycomponent_visibility(tvis, calskymodel[0].components) tvis = apply_gaintable(tvis, calskymodel[1]) # E step is the data model for a window plus the difference between the observed data # and the summed data models or, put another way, its the observed data minus the # summed visibility for all other windows evis.data['vis'][...] = tvis.data['vis'][...] + vis.data['vis'][ ...] - evis_all.data['vis'][...] return evis
def zerovis(vis): if vis is not None: zerovis = copy_visibility(vis) zerovis.data['vis'][...] = 0.0 return zerovis else: return None
def core_solve(self, spf, dpf, phase_error=0.1, amplitude_error=0.0, leakage=0.0, phase_only=True, niter=200, crosspol=False, residual_tol=1e-6, f=[100.0, 50.0, -10.0, 40.0]): self.actualSetup(spf, dpf, f=f) gt = create_gaintable_from_blockvisibility(self.vis) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=phase_error, amplitude_error=amplitude_error, leakage=leakage) original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt) gtsol = solve_gaintable(self.vis, original, phase_only=phase_only, niter=niter, crosspol=crosspol, tol=1e-6) vis = apply_gaintable(vis, gtsol, inverse=True) residual = numpy.max(gtsol.residual) assert residual < residual_tol, "%s %s Max residual = %s" % (spf, dpf, residual) log.debug(qa_gaintable(gt))
def peel_skycomponent_blockvisibility(vis: BlockVisibility, sc: Skycomponent, remove=True) -> \ BlockVisibility: """ Peel a collection of components. Sequentially solve the gain towards each Skycomponent and optionally remove from the visibility. :param params: :param vis: Visibility to be processed :param sc: Skycomponent or list of Skycomponents :returns: subtracted visibility and list of GainTables """ assert type( vis) is BlockVisibility, "vis is not a BlockVisibility: %r" % vis if not isinstance(sc, collections.Iterable): sc = [sc] gtlist = [] for comp in sc: assert comp.shape == 'Point', "Cannot handle shape %s" % comp.shape modelvis = copy_visibility(vis) modelvis = predict_skycomponent_blockvisibility(modelvis, comp) gt = solve_gaintable(vis, modelvis, phase_only=False) modelvis = apply_gaintable(modelvis, gt) if remove: vis.data['vis'] -= modelvis.data['vis'] gtlist.append(gt) return vis, gtlist
def decoalesce_visibility(vis, overwrite=False): """ Decoalesce the visibilities to the original values (opposite of coalesce_visibility) This relies upon the block vis and the index being part of the vis. 'uv': Needs the original image used in coalesce_visibility 'tb': Needs the index generated by coalesce_visibility :param vis: (Coalesced visibility) :returns: BlockVisibility with vis and weight columns overwritten """ assert type(vis) is Visibility, "vis is not a Visibility: %r" % vis assert type(vis.blockvis) is BlockVisibility, "No blockvisibility in vis" assert vis.cindex is not None, "No reverse index in Visibility" if overwrite: log.debug('decoalesce_visibility: Created new Visibility for decoalesced data') decomp_vis = copy_visibility(vis.blockvis) else: log.debug('decoalesce_visibility: Filled decoalesced data into template') decomp_vis = vis.blockvis vshape = decomp_vis.data['vis'].shape npol = vshape[-1] dvis = numpy.zeros(vshape, dtype='complex') assert numpy.max(vis.cindex) < dvis.size for i in range(dvis.size // npol): decomp_vis.data['vis'].flat[i:i + npol] = vis.data['vis'][vis.cindex[i]] log.debug('decoalesce_visibility: Coalesced %s, decoalesced %s' % (vis_summary(vis), vis_summary(decomp_vis))) return decomp_vis
def skymodel_cal_e_step(vis: BlockVisibility, evis_all: BlockVisibility, calskymodel, **kwargs): """Calculates E step in equation A12 This is the data model for this window plus the difference between observed data and summed data models :param evis_all: Sum data models :param csm: csm element being fit :param kwargs: :return: Data model (i.e. visibility) for this csm """ evis = copy_visibility(evis_all) tvis = copy_visibility(vis, zero=True) tvis = predict_skycomponent_visibility(tvis, calskymodel[0].components) tvis = apply_gaintable(tvis, calskymodel[1]) evis.data['vis'][...] = tvis.data['vis'][...] + vis.data['vis'][...] - evis_all.data['vis'][...] return evis
def sagecal_fit_gaintable(evis, theta, gain=0.1, niter=3, tol=1e-3, **kwargs): """Fit a gaintable to a visibility i.e. A13 This is the update to the gain part of the window :param evis: :param theta: :param kwargs: :return: """ previous_gt = copy_gaintable(theta[1]) gt = copy_gaintable(theta[1]) model_vis = copy_visibility(evis, zero=True) model_vis = predict_skycomponent_visibility(model_vis, theta[0]) gt = solve_gaintable(evis, model_vis, gt=gt, niter=niter, phase_only=True, gain=0.5, tol=1e-4, **kwargs) gt.data['gain'][...] = gain * gt.data['gain'][...] + \ (1 - gain) * previous_gt.data['gain'][...] gt.data['gain'][...] /= numpy.abs(previous_gt.data['gain'][...]) return gt
def calibrate_visibility(vt: Visibility, model=None, components=None, predict=predict_2d, **kwargs): """ calibrate Visibility with respect to model and optionally components :param vt: Visibility :param model: Model image :param components: Sky components :returns: Calibrated visibility """ assert model is not None or components is not None, "calibration requires a model or skycomponents" vtpred = copy_visibility(vt, zero=True) if model is not None: vtpred = predict(vtpred, model, **kwargs) if components is not None: vtpred = predict_skycomponent_visibility(vtpred, components) else: vtpred = predict_skycomponent_visibility(vtpred, components) bvt = decoalesce_visibility(vt) bvtpred = decoalesce_visibility(vtpred) gt = solve_gaintable(bvt, bvtpred, **kwargs) bvt = apply_gaintable(bvt, gt, **kwargs) return convert_blockvisibility_to_visibility(bvt)[0]
def subtract_vis(vis, model_vis): if vis is not None and model_vis is not None: assert vis.vis.shape == model_vis.vis.shape subvis = copy_visibility(vis) subvis.data['vis'][...] -= model_vis.data['vis'][...] return subvis else: return None
def predict_facets_and_accumulate(vis, model, **kwargs): if vis is not None: predicted = copy_visibility(vis) predicted = predict(predicted, model, **kwargs) vis.data['vis'] += predicted.data['vis'] return vis else: return None
def predict_and_sum_wstack(vis, model, **kwargs): if vis is not None: predicted = copy_visibility(vis) predicted = predict(predicted, model, **kwargs) predicted.data['vis'] = vis.data['vis'] + predicted.data['vis'] return predicted else: return None
def skymodel_cal_e_all(vis: BlockVisibility, calskymodels): """Calculates E step in equation A12 This is the sum of the data models over all skymodel :param vis: Visibility :param csm: List of (skymodel, gaintable) tuples :param kwargs: :return: Sum of data models (i.e. a visibility) """ evis = copy_visibility(vis, zero=True) tvis = copy_visibility(vis, zero=True) for csm in calskymodels: tvis.data['vis'][...] = 0.0 tvis = predict_skycomponent_visibility(tvis, csm[0].components) tvis = apply_gaintable(tvis, csm[1]) evis.data['vis'][...] += tvis.data['vis'][...] return evis
def sagecal_e_all(vis: BlockVisibility, thetas, **kwargs): """Calculates E step in equation A12 This is the sum of the data models over all windows :param vis: :param thetas: :param kwargs: :return: """ evis = copy_visibility(vis, zero=True) tvis = copy_visibility(vis, zero=True) for i, theta in enumerate(thetas): tvis.data['vis'][...] = 0.0 tvis = predict_skycomponent_visibility(tvis, theta[0]) tvis = apply_gaintable(tvis, theta[1]) evis.data['vis'][...] += tvis.data['vis'][...] return evis
def selfcal_single(vis, model, **kwargs): if vis is not None: predicted = copy_visibility(vis) predicted = predict(predicted, model, **kwargs) gtsol = solve_gaintable(vis, predicted, **kwargs) vis = apply_gaintable(vis, gtsol, inverse=True, **kwargs) return vis else: return None
def test_create_gaintable_from_visibility(self): for spf, dpf in [('stokesIQUV', 'linear'), ('stokesIQUV', 'circular')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=0.1) original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt) assert numpy.max(numpy.abs(vis.vis - original.vis)) > 0.0
def test_solve_gaintable_scalar(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) vis = apply_gaintable(self.vis, gt) gtsol = solve_gaintable(self.vis, original, phase_only=True, niter=200) residual = numpy.max(gtsol.residual) assert residual < 3e-8, "Max residual = %s" % (residual)
def test_apply_gaintable_and_inverse_both(self): for spf, dpf in [('stokesIQUV', 'linear'), ('stokesIQUV', 'circular')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=0.1, amplitude_error=0.1) original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt) vis = apply_gaintable(self.vis, gt, inverse=True) error = numpy.max(numpy.abs(vis.vis - original.vis)) assert error < 1e-12, "Error = %s" % (error)
def sagecal_e_step(vis: BlockVisibility, evis_all: BlockVisibility, theta, beta=1.0, **kwargs): """Calculates E step in equation A12 This is the data model for this window plus the difference between observed data and summed data models :param vis: :param theta: :param kwargs: :return: """ evis = copy_visibility(evis_all) tvis = copy_visibility(vis, zero=True) tvis = predict_skycomponent_visibility(tvis, theta[0]) tvis = apply_gaintable(tvis, theta[1]) evis.data['vis'][...] = tvis.data['vis'][...] + \ beta * (vis.data['vis'][...] - evis_all.data['vis'][...]) return evis
def sagecal_solve(vis, components, niter=10, tol=1e-8, gain=0.25, callback=None, **kwargs): """ Solve Solve by iterating, performing E step and M step. :param vis: :param components: :param gaintables: :param kwargs: :return: The individual data models and the residual visibility """ thetas = create_sagecal_thetas(vis, components, **kwargs) for iter in range(niter): new_thetas = list() evis_all = sagecal_e_all(vis, thetas, **kwargs) print("Iteration %d" % (iter)) for window_index, theta in enumerate(thetas): evis = sagecal_e_step(vis, evis_all, theta, gain=gain, **kwargs) new_theta = sagecal_m_step(evis, theta, gain=gain, **kwargs) new_thetas.append(new_theta) if callback is not None: callback(iter, thetas) flux = new_theta[0].flux[0, 0] qa = qa_gaintable(new_theta[1]) residual = qa.data['residual'] rms_phase = qa.data['rms-phase'] print("\t Window %d, flux %s, residual %.3f, rms phase %.3f" % (window_index, str(flux), residual, rms_phase)) thetas = new_thetas residual_vis = copy_visibility(vis) final_vis = sagecal_e_all(vis, thetas, **kwargs) residual_vis.data['vis'][ ...] = vis.data['vis'][...] - final_vis.data['vis'][...] return thetas, residual_vis
def skymodel_cal_fit_gaintable(evis, calskymodel, gain=0.1, niter=3, tol=1e-3, **kwargs): """Fit a gaintable to a visibility This is the update to the gain part of the window :param evis: Expected vis for this ssm :param calskymodel: csm element being fit :param gain: Gain in step :param niter: Number of iterations :param kwargs: Gaintable """ previous_gt = copy_gaintable(calskymodel[1]) gt = copy_gaintable(calskymodel[1]) model_vis = copy_visibility(evis, zero=True) model_vis = predict_skycomponent_visibility(model_vis, calskymodel[0].components) gt = solve_gaintable(evis, model_vis, gt=gt, niter=niter, phase_only=True, gain=0.5, tol=1e-4, **kwargs) gt.data['gain'][...] = gain * gt.data['gain'][...] + \ (1 - gain) * previous_gt.data['gain'][...] gt.data['gain'][...] /= numpy.abs(previous_gt.data['gain'][...]) return gt
def skymodel_cal_solve(vis, skymodels, niter=10, tol=1e-8, gain=0.25, **kwargs): """ Solve Solve by iterating, performing E step and M step. :param vis: Initial visibility :param components: Initial components to be used :param gaintables: Initial gain tables to be used :param kwargs: :return: The individual data models and the residual visibility """ calskymodels = initialise_skymodel_cal_skymodel(vis, skymodels=skymodels, **kwargs) for iter in range(niter): new_calskymodels = list() evis_all = skymodel_cal_e_all(vis, calskymodels) log.debug("skymodel_cal_solve: Iteration %d" % (iter)) for window_index, csm in enumerate(calskymodels): evis = skymodel_cal_e_step(vis, evis_all, csm, gain=gain, **kwargs) new_csm = skymodel_cal_m_step(evis, csm, **kwargs) new_calskymodels.append((new_csm[0], new_csm[1])) flux = new_csm[0].components[0].flux[0, 0] qa = qa_gaintable(new_csm[1]) residual = qa.data['residual'] rms_phase = qa.data['rms-phase'] log.debug("skymodel_cal_solve:\t Window %d, flux %s, residual %.3f, rms phase %.3f" % (window_index, str(flux), residual, rms_phase)) calskymodels = [(copy_skymodel(csm[0]), copy_gaintable(csm[1])) for csm in new_calskymodels] residual_vis = copy_visibility(vis) final_vis = skymodel_cal_e_all(vis, calskymodels) residual_vis.data['vis'][...] = vis.data['vis'][...] - final_vis.data['vis'][...] return calskymodels, residual_vis
def predict_and_apply(ovis, calskymodel): tvis = copy_visibility(ovis, zero=True) tvis = predict_skycomponent_visibility(tvis, calskymodel[0].components) tvis = apply_gaintable(tvis, calskymodel[1]) return tvis
def res_vis(vis, final_vis): residual_vis = copy_visibility(vis) residual_vis.data['vis'][ ...] = vis.data['vis'][...] - final_vis.data['vis'][...] return residual_vis