def test_readwritegaintable(self): self.vis = create_blockvisibility( self.midcore, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, polarisation_frame=PolarisationFrame("linear"), weight=1.0) gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') gt = simulate_gaintable(gt, phase_error=1.0, amplitude_error=0.1) config = { "buffer": { "directory": self.dir }, "gaintable": { "name": "test_buffergaintable.hdf", "data_model": "GainTable" } } bdm = BufferGainTable(config["buffer"], config["gaintable"], gt) bdm.sync() new_bdm = BufferGainTable(config["buffer"], config["gaintable"]) new_bdm.sync() newgt = bdm.memory_data_model assert gt.data.shape == newgt.data.shape assert numpy.max(numpy.abs(gt.gain - newgt.gain)) < 1e-15
def test_create_gaintable_from_rows_makecopy(self): self.actualSetup('stokesIQUV', 'linear') gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') rows = gt.time > 150.0 for makecopy in [True, False]: selected_gt = create_gaintable_from_rows(gt, rows, makecopy=makecopy) assert selected_gt.ntimes == numpy.sum(numpy.array(rows))
def test_readwriteskymodel_no_image(self): vis = create_blockvisibility( self.midcore, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, polarisation_frame=PolarisationFrame("linear"), weight=1.0) gt = create_gaintable_from_blockvisibility(vis, timeslice='auto') gt = simulate_gaintable(gt, phase_error=1.0, amplitude_error=0.1) sm = SkyModel(components=[self.comp], gaintable=gt) config = { "buffer": { "directory": self.dir }, "skymodel": { "name": "test_bufferskymodel.hdf", "data_model": "SkyModel" } } bdm = BufferSkyModel(config["buffer"], config["skymodel"], sm) bdm.sync() new_bdm = BufferSkyModel(config["buffer"], config["skymodel"]) new_bdm.sync() newsm = bdm.memory_data_model assert newsm.components[0].flux.shape == self.comp.flux.shape assert newsm.gaintable.data.shape == gt.data.shape
def test_create_gaintable_from_other(self): for timeslice in [10.0, 'auto', 1e5]: for spf, dpf in[('stokesIQUV', 'linear')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis, timeslice=timeslice) log.info("Created gain table: %s" % (gaintable_summary(gt))) new_gt = GainTable(data=gt.data) assert new_gt.data.shape == gt.data.shape
def test_plot_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=0.1, amplitude_error=0.1) plt.clf() gaintable_plot(gt) plt.show(block=False)
def test_apply_gaintable_null(self): for spf, dpf in[('stokesI', 'stokesI'), ('stokesIQUV', 'linear'), ('stokesIQUV', 'circular')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') gt.data['gain']*=0.0 original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt, inverse=True) error = numpy.max(numpy.abs(vis.vis[:,0,1,...] - original.vis[:,0,1,...])) assert error < 1e-12, "Error = %s" % (error)
def test_apply_gaintable_only(self): for spf, dpf in[('stokesI', 'stokesI'), ('stokesIQUV', 'linear'), ('stokesIQUV', 'circular')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=0.1, amplitude_error=0.01) original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt) error = numpy.max(numpy.abs(vis.vis - original.vis)) assert error > 10.0, "Error = %f" % (error)
def solve_calibrate_chain(vis, model_vis, calibration_context='T', controls=None, iteration=0, tol=1e-6, **kwargs): """ Calibrate using algorithm specified by calibration_context The context string can denote a sequence of calibrations e.g. TGB with different timescales. :param vis: :param model_vis: :param calibration_context: calibration contexts in order of correction e.g. 'TGB' :param controls: controls dictionary, modified as necessary :param iteration: Iteration number to be compared to the 'first_selfcal' field. :param kwargs: :return: Calibrated data_models, dict(gaintables) """ gaintables = {} if controls is None: controls = create_calibration_controls() isVis = isinstance(vis, Visibility) if isVis: avis = convert_visibility_to_blockvisibility(vis) else: avis = vis isMVis = isinstance(model_vis, Visibility) if isMVis: amvis = convert_visibility_to_blockvisibility(model_vis) else: amvis = model_vis assert isinstance(avis, BlockVisibility), avis assert amvis.__repr__() != avis.__repr__(), "Vis and model vis are the same object: convert problem" # Always return a gain table, even if null for c in calibration_context: gaintables[c] = \ create_gaintable_from_blockvisibility(avis, timeslice=controls[c]['timeslice']) if iteration >= controls[c]['first_selfcal']: if numpy.max(numpy.abs(vis.weight)) > 0.0 and (amvis is None or numpy.max(numpy.abs(amvis.vis)) > 0.0): gaintables[c] = solve_gaintable(avis, amvis, timeslice=controls[c]['timeslice'], phase_only=controls[c]['phase_only'], crosspol=controls[c]['shape'] == 'matrix', tol=tol) log.debug('calibrate_chain: Jones matrix %s, iteration %d' % (c, iteration)) log.debug(qa_gaintable(gaintables[c], context='Jones matrix %s, iteration %d' % (c, iteration))) avis = apply_gaintable(avis, gaintables[c], inverse=True, timeslice=controls[c]['timeslice']) else: log.debug('calibrate_chain: Jones matrix %s not solved, iteration %d' % (c, iteration)) else: log.debug('calibrate_chain: Jones matrix %s not solved, iteration %d' % (c, iteration)) return gaintables
def test_solve_gaintable_scalar_timeslice(self): self.actualSetup('stokesI', 'stokesI', f=[100.0], ntimes=10) gt = create_gaintable_from_blockvisibility(self.vis, timeslice=120.0) 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) gtsol = solve_gaintable(self.vis, original, phase_only=True, 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 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 test_create_gaintable_from_visibility_interval(self): for timeslice in [10.0, 'auto', 1e5]: for spf, dpf in[('stokesIQUV', 'linear')]: self.actualSetup(spf, dpf) gt = create_gaintable_from_blockvisibility(self.vis, timeslice=timeslice) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=1.0) original = copy_visibility(self.vis) vis = apply_gaintable(self.vis, gt) assert numpy.max(numpy.abs(original.vis)) > 0.0 assert numpy.max(numpy.abs(vis.vis)) > 0.0 assert numpy.max(numpy.abs(vis.vis - original.vis)) > 0.0
def actualSetUp(self, times=None): if times is not None: self.times = times self.vis = create_blockvisibility( self.lowcore, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, weight=1.0) self.gaintable = create_gaintable_from_blockvisibility(self.vis)
def test_solve_gaintable_stokesI_small_n_large_t(self): # Select only 6 stations self.actualSetup('stokesI', 'stokesI', f=[100.0], ntimes=4000, rmax=83) 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) gt.data['gain'] = gt.gain[1, ...] original = copy_visibility(self.vis) self.vis = apply_gaintable(self.vis, gt) gtsol = solve_gaintable(self.vis, original, phase_only=True, niter=200) self.vis = apply_gaintable(self.vis, gtsol) 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 test_readwriteskymodel(self): self.vis = create_blockvisibility(self.mid, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, polarisation_frame=PolarisationFrame("linear"), weight=1.0) im = create_test_image() gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') sm = SkyModel(components=[self.comp], image=im, gaintable=gt) export_skymodel_to_hdf5(sm, '%s/test_data_model_helpers_skymodel.hdf' % self.dir) newsm = import_skymodel_from_hdf5('%s/test_data_model_helpers_skymodel.hdf' % self.dir) assert newsm.components[0].flux.shape == self.comp.flux.shape assert newsm.image.data.shape == im.data.shape assert numpy.max(numpy.abs(newsm.image.data - im.data)) < 1e-15
def test_solve_gaintable_scalar_normalise(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=0.0, amplitude_error=0.1) gt.data['gain'] *= 2.0 original = copy_visibility(self.vis) self.vis = apply_gaintable(self.vis, gt) gtsol = solve_gaintable(self.vis, original, phase_only=False, niter=200, normalise_gains=True) 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 test_readwritegaintable(self): self.vis = create_blockvisibility(self.mid, self.times, self.frequency, channel_bandwidth=self.channel_bandwidth, phasecentre=self.phasecentre, polarisation_frame=PolarisationFrame("linear"), weight=1.0) gt = create_gaintable_from_blockvisibility(self.vis, timeslice='auto') gt = simulate_gaintable(gt, phase_error=1.0, amplitude_error=0.1) export_gaintable_to_hdf5(gt, '%s/test_data_model_helpers_gaintable.hdf' % self.dir) newgt = import_gaintable_from_hdf5('%s/test_data_model_helpers_gaintable.hdf' % self.dir) for key in gt.data.dtype.fields: assert numpy.max(numpy.abs(newgt.data[key] - gt.data[key])) < 1e-15 assert gt.data.shape == newgt.data.shape assert numpy.max(numpy.abs(gt.gain - newgt.gain)) < 1e-15
def test_calibrate_G_function(self): self.actualSetup('stokesIQUV', 'linear', f=[100.0, 0.0, 0.0, 50.0]) # Prepare the corrupted visibility data_models gt = create_gaintable_from_blockvisibility(self.vis) log.info("Created gain table: %s" % (gaintable_summary(gt))) gt = simulate_gaintable(gt, phase_error=0.0, amplitude_error=0.1) original = copy_visibility(self.vis) self.vis = apply_gaintable(self.vis, gt) # Now get the control dictionary and calibrate controls = create_calibration_controls() controls['G']['first_selfcal'] = 0 calibrated_vis, gaintables = calibrate_chain(self.vis, original, calibration_context='G', controls=controls) residual = numpy.max(gaintables['G'].residual) assert residual < 1e-8, "Max T residual = %s" % residual
def test_solve_gaintable_stokesI_bandpass(self): self.actualSetup('stokesI', 'stokesI', f=[100.0], vnchan=128) 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.01, smooth_channels=8) original = copy_visibility(self.vis) self.vis = apply_gaintable(self.vis, gt) gtsol = solve_gaintable(self.vis, original, phase_only=False, niter=200, damping=0.5) 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 insert_unittest_errors(vt, seed=180555, calibration_context="TG", amp_errors=None, phase_errors=None): """Simulate gain errors and apply :param vt: :param seed: Random number seed, set to big integer repeat values from run to run :param phase_errors: e.g. {'T': 1.0, 'G': 0.1, 'B': 0.01} :param amp_errors: e.g. {'T': 0.0, 'G': 0.01, 'B': 0.01} :return: """ controls = create_calibration_controls() if amp_errors is None: amp_errors = {'T': 0.0, 'G': 0.01, 'B': 0.01} if phase_errors is None: phase_errors = {'T': 1.0, 'G': 0.1, 'B': 0.01} for c in calibration_context: gaintable = create_gaintable_from_blockvisibility( vt, timeslice=controls[c]['timeslice']) gaintable = simulate_gaintable( gaintable, phase_error=phase_errors[c], amplitude_error=amp_errors[c], timeslice=controls[c]['timeslice'], phase_only=controls[c]['phase_only'], crosspol=controls[c]['shape'] == 'matrix') vt = apply_gaintable(vt, gaintable, inverse=True, timeslice=controls[c]['timeslice']) return vt
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=None, vnchan=3, timeslice='auto'): if f is None: f = [100.0, 50.0, -10.0, 40.0] self.actualSetup(spf, dpf, f=f, vnchan=vnchan) gt = create_gaintable_from_blockvisibility(self.vis, timeslice=timeslice) 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)) assert numpy.max(numpy.abs(gtsol.gain - 1.0)) > 0.1
def calibrate_chain(vis, model_vis, gaintables=None, calibration_context='T', controls=None, iteration=0, tol=1e-8, **kwargs): """ Calibrate using algorithm specified by calibration_context The context string can denote a sequence of calibrations e.g. TGB with different timescales. :param vis: :param model_vis: :param calibration_context: calibration contexts in order of correction e.g. 'TGB' :param controls: controls dictionary, modified as necessary :param iteration: Iteration number to be compared to the 'first_selfcal' field. :param kwargs: :return: Calibrated data_models, dict(gaintables) """ if controls is None: controls = create_calibration_controls() # Check to see if changes are required changes = False for c in calibration_context: if iteration >= controls[c]['first_selfcal']: changes = True if changes: isVis = isinstance(vis, Visibility) if isVis: avis = convert_visibility_to_blockvisibility(vis) else: avis = vis isMVis = isinstance(model_vis, Visibility) if isMVis: amvis = convert_visibility_to_blockvisibility(model_vis) else: amvis = model_vis assert isinstance(avis, BlockVisibility), avis if gaintables is None: gaintables = dict() for c in calibration_context: if iteration >= controls[c]['first_selfcal']: if c not in gaintables.keys(): log.info("Creating new {} gaintable".format(c)) gaintables[c] = \ create_gaintable_from_blockvisibility(avis, timeslice=controls[c]['timeslice']) gaintables[c] = solve_gaintable( avis, amvis, gt=gaintables[c], timeslice=controls[c]['timeslice'], phase_only=controls[c]['phase_only'], crosspol=controls[c]['shape'] == 'matrix', tol=tol) log.debug('calibrate_chain: Jones matrix %s, iteration %d' % (c, iteration)) log.debug( qa_gaintable(gaintables[c], context='Jones matrix %s, iteration %d' % (c, iteration))) avis = apply_gaintable(avis, gaintables[c], inverse=True, timeslice=controls[c]['timeslice']) else: log.debug( 'calibrate_chain: Jones matrix %s not solved, iteration %d' % (c, iteration)) if isVis: return convert_blockvisibility_to_visibility(avis), gaintables else: return avis, gaintables else: return vis, gaintables
def create_gaintable_from_screen(vis, sc, screen, height=3e5, vis_slices=None, scale=1.0, **kwargs): """ Create gaintables from a screen calculated using ARatmospy Screen axes are ['XX', 'YY', 'TIME', 'FREQ'] :param vis: :param sc: Sky components for which pierce points are needed :param screen: :param height: Height (in m) of screen above telescope e.g. 3e5 :param scale: Multiply the screen by this factor :return: """ assert isinstance(vis, BlockVisibility) station_locations = vis.configuration.xyz # Convert to TEC # phase = image[pixel] * -8.44797245e9 / frequency nant = station_locations.shape[0] t2r = numpy.pi / 43200.0 gaintables = [ create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc ] # The time in the Visibility is hour angle in seconds! for iha, rows in enumerate(vis_timeslice_iter(vis, vis_slices=vis_slices)): v = create_visibility_from_rows(vis, rows) ha = numpy.average(v.time) tec2phase = -8.44797245e9 / numpy.array(vis.frequency) number_bad = 0 number_good = 0 for icomp, comp in enumerate(sc): pp = find_pierce_points(station_locations, (comp.direction.ra.rad + t2r * ha) * u.rad, comp.direction.dec, height=height, phasecentre=vis.phasecentre) scr = numpy.zeros([nant]) for ant in range(nant): pp0 = pp[ant][0:2] worldloc = [pp0[0], pp0[1], ha, 1e8] try: pixloc = screen.wcs.wcs_world2pix([worldloc], 0)[0].astype('int') scr[ant] = scale * screen.data[pixloc[3], pixloc[2], pixloc[1], pixloc[0]] number_good += 1 except: number_bad += 1 scr[ant] = 0.0 scr = scr[:, numpy.newaxis] * tec2phase[numpy.newaxis, :] # axes of gaintable.gain are time, ant, nchan, nrec gaintables[icomp].gain[iha, :, :, :] = numpy.exp( 1j * scr[..., numpy.newaxis, numpy.newaxis]) gaintables[icomp].phasecentre = comp.direction if number_bad > 0: log.warning( "create_gaintable_from_screen: %d pierce points are inside the screen image" % (number_good)) log.warning( "create_gaintable_from_screen: %d pierce points are outside the screen image" % (number_bad)) return gaintables
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
def create_gaintable_from_screen(vis, sc, screen, height=3e5, vis_slices=None, scale=1.0, r0=5e3, type_atmosphere='ionosphere', **kwargs): """ Create gaintables from a screen calculated using ARatmospy Screen axes are ['XX', 'YY', 'TIME', 'FREQ'] :param vis: :param sc: Sky components for which pierce points are needed :param screen: :param height: Height (in m) of screen above telescope e.g. 3e5 :param r0: r0 in meters :param type_atmosphere: 'ionosphere' or 'troposphere' :param scale: Multiply the screen by this factor :return: """ assert isinstance(vis, BlockVisibility) station_locations = vis.configuration.xyz scale = numpy.power(r0 / 5000.0, -5.0 / 3.0) if type_atmosphere == 'troposphere': # In troposphere files, the units are phase in radians. screen_to_phase = scale else: # In the ionosphere file, the units are dTEC. screen_to_phase = -scale * 8.44797245e9 / numpy.array(vis.frequency) nant = station_locations.shape[0] t2r = numpy.pi / 43200.0 gaintables = [ create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc ] number_bad = 0 number_good = 0 ha_zero = numpy.average(calculate_blockvisibility_hourangles(vis)) for iha, rows in enumerate(vis_timeslice_iter(vis, vis_slices=vis_slices)): v = create_visibility_from_rows(vis, rows) ha = numpy.average(calculate_blockvisibility_hourangles(v) - ha_zero).to('rad').value for icomp, comp in enumerate(sc): pp = find_pierce_points(station_locations, (comp.direction.ra.rad + t2r * ha) * units.rad, comp.direction.dec, height=height, phasecentre=vis.phasecentre) scr = numpy.zeros([nant]) for ant in range(nant): pp0 = pp[ant][0:2] # Using narrow band approach - we should loop over frequency try: worldloc = [ pp0[0], pp0[1], ha, numpy.average(vis.frequency) ] pixloc = screen.wcs.wcs_world2pix([worldloc], 0)[0].astype('int') if type_atmosphere == 'troposphere': pixloc[3] = 0 scr[ant] = screen_to_phase * screen.data[ pixloc[3], pixloc[2], pixloc[1], pixloc[0]] number_good += 1 except (ValueError, IndexError): number_bad += 1 scr[ant] = 0.0 # axes of gaintable.gain are time, ant, nchan, nrec gaintables[icomp].gain[iha, :, :, :] = numpy.exp( 1j * scr)[..., numpy.newaxis, numpy.newaxis, numpy.newaxis] gaintables[icomp].phasecentre = comp.direction assert number_good > 0, "create_gaintable_from_screen: There are no pierce points inside the atmospheric screen image" if number_bad > 0: log.warning( "create_gaintable_from_screen: %d pierce points are inside the atmospheric screen image" % (number_good)) log.warning( "create_gaintable_from_screen: %d pierce points are outside the atmospheric screen image" % (number_bad)) return gaintables
def actualSetUp(self, nfreqwin=3, dospectral=True, dopol=False, amp_errors=None, phase_errors=None, zerow=True): if amp_errors is None: amp_errors = {'T': 0.0, 'G': 0.1} if phase_errors is None: phase_errors = {'T': 1.0, 'G': 0.0} self.npixel = 512 self.low = create_named_configuration('LOWBD2', rmax=750.0) self.freqwin = nfreqwin self.vis_list = list() self.ntimes = 1 self.times = numpy.linspace(-3.0, +3.0, self.ntimes) * numpy.pi / 12.0 self.frequency = numpy.linspace(0.8e8, 1.2e8, self.freqwin) if self.freqwin > 1: self.channelwidth = numpy.array( self.freqwin * [self.frequency[1] - self.frequency[0]]) else: self.channelwidth = numpy.array([1e6]) if dopol: self.vis_pol = PolarisationFrame('linear') self.image_pol = PolarisationFrame('stokesIQUV') f = numpy.array([100.0, 20.0, -10.0, 1.0]) else: self.vis_pol = PolarisationFrame('stokesI') self.image_pol = PolarisationFrame('stokesI') f = numpy.array([100.0]) if dospectral: flux = numpy.array( [f * numpy.power(freq / 1e8, -0.7) for freq in self.frequency]) else: flux = numpy.array([f]) self.phasecentre = SkyCoord(ra=+180.0 * u.deg, dec=-60.0 * u.deg, frame='icrs', equinox='J2000') self.blockvis_list = [ ingest_unittest_visibility(self.low, [self.frequency[i]], [self.channelwidth[i]], self.times, self.vis_pol, self.phasecentre, block=True, zerow=zerow) for i in range(nfreqwin) ] for v in self.blockvis_list: v.data['vis'][...] = 1.0 + 0.0j self.error_blockvis_list = [ copy_visibility(v) for v in self.blockvis_list ] gt = create_gaintable_from_blockvisibility(self.blockvis_list[0]) gt = simulate_gaintable(gt, phase_error=0.1, amplitude_error=0.0, smooth_channels=1, leakage=0.0) self.error_blockvis_list = [ apply_gaintable(self.error_blockvis_list[i], gt) for i in range(self.freqwin) ] assert numpy.max( numpy.abs(self.error_blockvis_list[0].vis - self.blockvis_list[0].vis)) > 0.0
def actualSetUp(self, add_errors=False, nfreqwin=7, dospectral=True, dopol=False, zerow=True): self.npixel = 512 self.low = create_named_configuration('LOWBD2', rmax=750.0) self.freqwin = nfreqwin self.vis_list = list() self.ntimes = 5 self.times = numpy.linspace(-3.0, +3.0, self.ntimes) * numpy.pi / 12.0 self.frequency = numpy.linspace(0.8e8, 1.2e8, self.freqwin) if self.freqwin > 1: self.channelwidth = numpy.array( self.freqwin * [self.frequency[1] - self.frequency[0]]) else: self.channelwidth = numpy.array([1e6]) if dopol: self.vis_pol = PolarisationFrame('linear') self.image_pol = PolarisationFrame('stokesIQUV') f = numpy.array([100.0, 20.0, 0.0, 0.0]) else: self.vis_pol = PolarisationFrame('stokesI') self.image_pol = PolarisationFrame('stokesI') f = numpy.array([100.0]) if dospectral: flux = numpy.array( [f * numpy.power(freq / 1e8, -0.7) for freq in self.frequency]) else: flux = numpy.array([f]) self.phasecentre = SkyCoord(ra=+180.0 * u.deg, dec=-60.0 * u.deg, frame='icrs', equinox='J2000') self.blockvis_list = \ [rsexecute.execute(ingest_unittest_visibility, nout=1)(self.low, [self.frequency[i]], [self.channelwidth[i]], self.times, self.vis_pol, self.phasecentre, block=True, zerow=zerow) for i in range(nfreqwin)] self.blockvis_list = rsexecute.compute(self.blockvis_list, sync=True) self.blockvis_list = rsexecute.scatter(self.blockvis_list) self.vis_list = [ rsexecute.execute(convert_blockvisibility_to_visibility, nout=1)(bv) for bv in self.blockvis_list ] self.vis_list = rsexecute.compute(self.vis_list, sync=True) self.vis_list = rsexecute.scatter(self.vis_list) self.model_imagelist = [ rsexecute.execute(create_unittest_model, nout=1)(self.vis_list[i], self.image_pol, npixel=self.npixel, cellsize=0.0005) for i in range(nfreqwin) ] self.model_imagelist = rsexecute.compute(self.model_imagelist, sync=True) self.model_imagelist = rsexecute.scatter(self.model_imagelist) self.components_list = [ rsexecute.execute(create_unittest_components)( self.model_imagelist[freqwin], flux[freqwin, :][numpy.newaxis, :]) for freqwin, m in enumerate(self.model_imagelist) ] self.components_list = rsexecute.compute(self.components_list, sync=True) self.components_list = rsexecute.scatter(self.components_list) self.blockvis_list = [ rsexecute.execute(dft_skycomponent_visibility)( self.blockvis_list[freqwin], self.components_list[freqwin]) for freqwin, _ in enumerate(self.blockvis_list) ] self.blockvis_list = rsexecute.compute(self.blockvis_list, sync=True) self.vis = self.blockvis_list[0] self.blockvis_list = rsexecute.scatter(self.blockvis_list) self.model_imagelist = [ rsexecute.execute(insert_skycomponent, nout=1)(self.model_imagelist[freqwin], self.components_list[freqwin]) for freqwin in range(nfreqwin) ] self.model_imagelist = rsexecute.compute(self.model_imagelist, sync=True) model = self.model_imagelist[0] self.cmodel = smooth_image(model) if self.persist: export_image_to_fits( model, '%s/test_pipelines_rsexecute_model.fits' % self.dir) export_image_to_fits( self.cmodel, '%s/test_pipelines_rsexecute_cmodel.fits' % self.dir) if add_errors: gt = create_gaintable_from_blockvisibility(self.vis) gt = simulate_gaintable(gt, phase_error=0.1, amplitude_error=0.0, smooth_channels=1, leakage=0.0) self.blockvis_list = [ rsexecute.execute(apply_gaintable, nout=1)(self.blockvis_list[i], gt) for i in range(self.freqwin) ] self.blockvis_list = rsexecute.compute(self.blockvis_list, sync=True) self.blockvis_list = rsexecute.scatter(self.blockvis_list) self.vis_list = [ rsexecute.execute(convert_blockvisibility_to_visibility)(bv) for bv in self.blockvis_list ] self.vis_list = rsexecute.compute(self.vis_list, sync=True) self.vis_list = rsexecute.scatter(self.vis_list) self.model_imagelist = [ rsexecute.execute(create_unittest_model, nout=1)(self.vis_list[i], self.image_pol, npixel=self.npixel, cellsize=0.0005) for i in range(nfreqwin) ] self.model_imagelist = rsexecute.compute(self.model_imagelist, sync=True) self.model_imagelist = rsexecute.scatter(self.model_imagelist)
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 simulate_gaintable_from_voltage_pattern(vis, sc, vp, vis_slices=None, scale=1.0, order=3, use_radec=False, elevation_limit=15.0 * numpy.pi / 180.0, **kwargs): """ Create gaintables from a list of components and voltagr patterns :param elevation_limit: :param use_radec: :param vis_slices: :param vis: :param sc: Sky components for which pierce points are needed :param vp: Voltage pattern in AZELGEO frame :param scale: Multiply the screen by this factor :param order: order of spline (default is 3) :return: """ nant = vis.vis.shape[1] gaintables = [ create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc ] nchan, npol, ny, nx = vp.data.shape real_spline = [ RectBivariateSpline(range(ny), range(nx), vp.data[0, pol, ...].real, kx=order, ky=order) for pol in range(npol) ] imag_spline = [ RectBivariateSpline(range(ny), range(nx), vp.data[0, pol, ...].imag, kx=order, ky=order) for pol in range(npol) ] if not use_radec: assert isinstance(vis, BlockVisibility) assert vp.wcs.wcs.ctype[0] == 'AZELGEO long', vp.wcs.wcs.ctype[0] assert vp.wcs.wcs.ctype[1] == 'AZELGEO lati', vp.wcs.wcs.ctype[1] assert vis.configuration.mount[ 0] == 'azel', "Mount %s not supported yet" % vis.configuration.mount[ 0] number_bad = 0 number_good = 0 # For each hourangle, we need to calculate the location of a component # in AZELGEO. With that we can then look up the relevant gain from the # voltage pattern for iha, rows in enumerate( vis_timeslice_iter(vis, vis_slices=vis_slices)): v = create_visibility_from_rows(vis, rows) if v is not None: utc_time = Time([numpy.average(v.time) / 86400.0], format='mjd', scale='utc') azimuth_centre, elevation_centre = calculate_azel( v.configuration.location, utc_time, vis.phasecentre) azimuth_centre = azimuth_centre[0].to('deg').value elevation_centre = elevation_centre[0].to('deg').value # Calculate the az el for this time wcs_azel = vp.wcs.sub(2).deepcopy() for icomp, comp in enumerate(sc): if elevation_centre >= elevation_limit: antgain = numpy.zeros([nant, npol], dtype='complex') antwt = numpy.zeros([nant, npol]) # Calculate the azel of this component azimuth_comp, elevation_comp = calculate_azel( v.configuration.location, utc_time, comp.direction) cosel = numpy.cos(elevation_comp[0]).value azimuth_comp = azimuth_comp[0].to('deg').value elevation_comp = elevation_comp[0].to('deg').value if azimuth_comp - azimuth_centre > 180.0: azimuth_centre += 360.0 elif azimuth_comp - azimuth_centre < -180.0: azimuth_centre -= 360.0 try: worldloc = [[ (azimuth_comp - azimuth_centre) * cosel, elevation_comp - elevation_centre ]] # radius = numpy.sqrt(((azimuth_comp-azimuth_centre)*cosel)**2 + # (elevation_comp-elevation_centre)**2) pixloc = wcs_azel.wcs_world2pix(worldloc, 1)[0] assert pixloc[0] > 2 assert pixloc[0] < nx - 3 assert pixloc[1] > 2 assert pixloc[1] < ny - 3 for pol in range(npol): gain = real_spline[pol].ev(pixloc[1], pixloc[0]) \ + 1j * imag_spline[pol].ev(pixloc[1], pixloc[0]) antgain[:, pol] = gain for ant in range(nant): ag = antgain[ant, :].reshape([2, 2]) ag = numpy.linalg.inv(ag) antgain[ant, :] = ag.reshape([4]) number_good += 1 except (ValueError, AssertionError): number_bad += 1 antgain[...] = 0.0 antwt[...] = 0.0 gaintables[icomp].gain[ iha, :, :, :] = antgain[:, numpy.newaxis, :].reshape( [nant, nchan, 2, 2]) gaintables[icomp].weight[ iha, :, :, :] = antwt[:, numpy.newaxis, :].reshape( [nant, nchan, 2, 2]) gaintables[icomp].phasecentre = comp.direction else: gaintables[icomp].gain[...] = 1.0 + 0.0j gaintables[icomp].weight[iha, :, :, :] = 0.0 gaintables[icomp].phasecentre = comp.direction number_bad += nant else: assert isinstance(vis, BlockVisibility) assert vp.wcs.wcs.ctype[0] == 'RA---SIN', vp.wcs.wcs.ctype[0] assert vp.wcs.wcs.ctype[1] == 'DEC--SIN', vp.wcs.wcs.ctype[1] # The time in the Visibility is hour angle in seconds! number_bad = 0 number_good = 0 d2r = numpy.pi / 180.0 ra_centre = vp.wcs.wcs.crval[0] * d2r dec_centre = vp.wcs.wcs.crval[1] * d2r r2d = 180.0 / numpy.pi s2r = numpy.pi / 43200.0 # For each hourangle, we need to calculate the location of a component # in AZELGEO. With that we can then look up the relevant gain from the # voltage pattern for iha, rows in enumerate( vis_timeslice_iter(vis, vis_slices=vis_slices)): v = create_visibility_from_rows(vis, rows) ha = numpy.average(v.time) for icomp, comp in enumerate(sc): antgain = numpy.zeros([nant, npol], dtype='complex') antwt = numpy.zeros([nant, npol]) # Calculate the location of the component in AZELGEO, then add the pointing offset # for each antenna ra_comp = comp.direction.ra.rad dec_comp = comp.direction.dec.rad for ant in range(nant): wcs_azel = vp.wcs.deepcopy() ra_pointing = ra_centre * r2d dec_pointing = dec_centre * r2d # We use WCS sensible coordinate handling by labelling the axes misleadingly wcs_azel.wcs.crval[0] = ra_pointing wcs_azel.wcs.crval[1] = dec_pointing wcs_azel.wcs.ctype[0] = 'RA---SIN' wcs_azel.wcs.ctype[1] = 'DEC--SIN' for pol in range(npol): worldloc = [ ra_comp * r2d, dec_comp * r2d, vp.wcs.wcs.crval[2], vp.wcs.wcs.crval[3] ] try: pixloc = wcs_azel.sub(2).wcs_world2pix( [worldloc[:2]], 1)[0] assert pixloc[0] > 2 assert pixloc[0] < nx - 3 assert pixloc[1] > 2 assert pixloc[1] < ny - 3 gain = real_spline[pol].ev( pixloc[1], pixloc[0] ) + 1j * imag_spline[pol].ev(pixloc[1], pixloc[0]) if numpy.abs(gain) > 0.0: antgain[ant, pol] = 1.0 / (scale * gain) antwt[ant, pol] = 1.0 else: antgain[ant, pol] = 0.0 antwt[ant, pol] = 0.0 antwt[ant, pol] = 1.0 number_good += 1 except (ValueError, AssertionError): number_bad += 1 antgain[ant, pol] = 1e15 antwt[ant, pol] = 0.0 gaintables[icomp].gain[ iha, :, :, :] = antgain[:, numpy.newaxis, :].reshape( [nant, nchan, 2, 2]) gaintables[icomp].weight[ iha, :, :, :] = antwt[:, numpy.newaxis, :].reshape( [nant, nchan, 2, 2]) gaintables[icomp].phasecentre = comp.direction assert number_good > 0, "simulate_gaintable_from_voltage_pattern: No points inside the voltage pattern image" if number_bad > 0: log.warning( "simulate_gaintable_from_voltage_pattern: %d points are inside the voltage pattern image" % (number_good)) log.warning( "simulate_gaintable_from_voltage_pattern: %d points are outside the voltage pattern image" % (number_bad)) return gaintables
def simulate_gaintable_from_zernikes(vis, sc, vp_list, vp_coeffs, vis_slices=None, order=3, use_radec=False, elevation_limit=15.0 * numpy.pi / 180.0, **kwargs): """ Create gaintables for a set of zernikes :param vis: :param sc: Sky components for which pierce points are needed :param vp: List of Voltage patterns in AZELGEO frame :param vp_coeffs: Fractional contribution [nants, nvp] :param order: order of spline (default is 3) :return: """ ntimes, nant = vis.vis.shape[0:2] vp_coeffs = numpy.array(vp_coeffs) gaintables = [ create_gaintable_from_blockvisibility(vis, **kwargs) for i in sc ] if not use_radec: assert isinstance(vis, BlockVisibility) assert vis.configuration.mount[ 0] == 'azel', "Mount %s not supported yet" % vis.configuration.mount[ 0] # The time in the Visibility is hour angle in seconds! number_bad = 0 number_good = 0 # Cache the splines, one per voltage pattern real_splines = list() imag_splines = list() for ivp, vp in enumerate(vp_list): assert vp.wcs.wcs.ctype[0] == 'AZELGEO long', vp.wcs.wcs.ctype[0] assert vp.wcs.wcs.ctype[1] == 'AZELGEO lati', vp.wcs.wcs.ctype[1] nchan, npol, ny, nx = vp.data.shape real_splines.append( RectBivariateSpline(range(ny), range(nx), vp.data[0, 0, ...].real, kx=order, ky=order)) imag_splines.append( RectBivariateSpline(range(ny), range(nx), vp.data[0, 0, ...].imag, kx=order, ky=order)) latitude = vis.configuration.location.lat.rad r2d = 180.0 / numpy.pi s2r = numpy.pi / 43200.0 # For each hourangle, we need to calculate the location of a component # in AZELGEO. With that we can then look up the relevant gain from the # voltage pattern for iha, rows in enumerate( vis_timeslice_iter(vis, vis_slices=vis_slices)): v = create_visibility_from_rows(vis, rows) ha = numpy.average( calculate_blockvisibility_hourangles(v).to('rad').value) # Calculate the az el for this hourangle and the phasecentre declination utc_time = Time([numpy.average(v.time) / 86400.0], format='mjd', scale='utc') azimuth_centre, elevation_centre = calculate_azel( v.configuration.location, utc_time, vis.phasecentre) azimuth_centre = azimuth_centre[0].to('deg').value elevation_centre = elevation_centre[0].to('deg').value for icomp, comp in enumerate(sc): if elevation_centre >= elevation_limit: antgain = numpy.zeros([nant], dtype='complex') # Calculate the location of the component in AZELGEO, then add the pointing offset # for each antenna hacomp = comp.direction.ra.rad - vis.phasecentre.ra.rad + ha deccomp = comp.direction.dec.rad azimuth_comp, elevation_comp = hadec_to_azel( hacomp, deccomp, latitude) for ant in range(nant): for ivp, vp in enumerate(vp_list): nchan, npol, ny, nx = vp.data.shape wcs_azel = vp.wcs.deepcopy() # We use WCS sensible coordinate handling by labelling the axes misleadingly wcs_azel.wcs.crval[0] = azimuth_centre wcs_azel.wcs.crval[1] = elevation_centre wcs_azel.wcs.ctype[0] = 'RA---SIN' wcs_azel.wcs.ctype[1] = 'DEC--SIN' worldloc = [ azimuth_comp * r2d, elevation_comp * r2d, vp.wcs.wcs.crval[2], vp.wcs.wcs.crval[3] ] try: pixloc = wcs_azel.sub(2).wcs_world2pix( [worldloc[:2]], 1)[0] assert pixloc[0] > 2 assert pixloc[0] < nx - 3 assert pixloc[1] > 2 assert pixloc[1] < ny - 3 gain = real_splines[ivp].ev(pixloc[1], pixloc[0]) \ + 1j * imag_splines[ivp](pixloc[1], pixloc[0]) antgain[ant] += vp_coeffs[ant, ivp] * gain number_good += 1 except (ValueError, AssertionError): number_bad += 1 antgain[ant] = 1.0 antgain[ant] = 1.0 / antgain[ant] gaintables[icomp].gain[ iha, :, :, :] = antgain[:, numpy.newaxis, numpy.newaxis, numpy.newaxis] gaintables[icomp].phasecentre = comp.direction else: gaintables[icomp].gain[...] = 1.0 + 0.0j gaintables[icomp].phasecentre = comp.direction number_bad += nant else: assert isinstance(vis, BlockVisibility) number_bad = 0 number_good = 0 # Cache the splines, one per voltage pattern real_splines = list() imag_splines = list() for ivp, vp in enumerate(vp_list): nchan, npol, ny, nx = vp.data.shape real_splines.append( RectBivariateSpline(range(ny), range(nx), vp.data[0, 0, ...].real, kx=order, ky=order)) imag_splines.append( RectBivariateSpline(range(ny), range(nx), vp.data[0, 0, ...].imag, kx=order, ky=order)) for iha, rows in enumerate( vis_timeslice_iter(vis, vis_slices=vis_slices)): # The time in the Visibility is hour angle in seconds! r2d = 180.0 / numpy.pi # For each hourangle, we need to calculate the location of a component # in AZELGEO. With that we can then look up the relevant gain from the # voltage pattern v = create_visibility_from_rows(vis, rows) ha = numpy.average(calculate_blockvisibility_hourangles(v)) for icomp, comp in enumerate(sc): antgain = numpy.zeros([nant], dtype='complex') antwt = numpy.zeros([nant]) ra_comp = comp.direction.ra.rad dec_comp = comp.direction.dec.rad for ant in range(nant): for ivp, vp in enumerate(vp_list): assert vp.wcs.wcs.ctype[ 0] == 'RA---SIN', vp.wcs.wcs.ctype[0] assert vp.wcs.wcs.ctype[ 1] == 'DEC--SIN', vp.wcs.wcs.ctype[1] worldloc = [ ra_comp * r2d, dec_comp * r2d, vp.wcs.wcs.crval[2], vp.wcs.wcs.crval[3] ] nchan, npol, ny, nx = vp.data.shape try: pixloc = vp.wcs.sub(2).wcs_world2pix( [worldloc[:2]], 1)[0] assert pixloc[0] > 2 assert pixloc[0] < nx - 3 assert pixloc[1] > 2 assert pixloc[1] < ny - 3 gain = real_splines[ivp].ev(pixloc[1], pixloc[0]) \ + 1j * imag_splines[ivp](pixloc[1], pixloc[0]) antgain[ant] += vp_coeffs[ant, ivp] * gain antwt[ant] = 1.0 number_good += 1 except (ValueError, AssertionError): number_bad += 1 antgain[ant] = 1e15 antwt[ant] = 0.0 antgain[ant] = 1.0 / antgain[ant] gaintables[icomp].gain[ iha, :, :, :] = antgain[:, numpy.newaxis, numpy.newaxis, numpy.newaxis] gaintables[icomp].weight[ iha, :, :, :] = antwt[:, numpy.newaxis, numpy.newaxis, numpy.newaxis] gaintables[icomp].phasecentre = comp.direction if number_bad > 0: log.warning( "simulate_gaintable_from_zernikes: %d points are inside the voltage pattern image" % (number_good)) log.warning( "simulate_gaintable_from_zernikes: %d points are outside the voltage pattern image" % (number_bad)) return gaintables
def create_blockvisibility_iterator( config: Configuration, times: numpy.array, frequency: numpy.array, channel_bandwidth, phasecentre: SkyCoord, weight: float = 1, polarisation_frame=PolarisationFrame('stokesI'), integration_time=1.0, number_integrations=1, predict=predict_2d, model=None, components=None, phase_error=0.0, amplitude_error=0.0, sleep=0.0, **kwargs): """ Create a sequence of Visibilities and optionally predicting and coalescing This is useful mainly for performing large simulations. Do something like:: vis_iter = create_blockvisibility_iterator(config, times, frequency, channel_bandwidth, phasecentre=phasecentre, weight=1.0, integration_time=30.0, number_integrations=3) for i, vis in enumerate(vis_iter): if i == 0: fullvis = vis else: fullvis = append_visibility(fullvis, vis) :param config: Configuration of antennas :param times: hour angles in radians :param frequency: frequencies (Hz] Shape [nchan] :param weight: weight of a single sample :param phasecentre: phasecentre of observation :param npol: Number of polarizations :param integration_time: Integration time ('auto' or value in s) :param number_integrations: Number of integrations to be created at each time. :param model: Model image to be inserted :param components: Components to be inserted :param sleep_time: Time to sleep between yields :return: Visibility """ for time in times: actualtimes = time + numpy.arange( 0, number_integrations) * integration_time * numpy.pi / 43200.0 bvis = create_blockvisibility(config, actualtimes, frequency=frequency, phasecentre=phasecentre, weight=weight, polarisation_frame=polarisation_frame, integration_time=integration_time, channel_bandwidth=channel_bandwidth) if model is not None: vis = convert_blockvisibility_to_visibility(bvis) vis = predict(vis, model, **kwargs) bvis = convert_visibility_to_blockvisibility(vis) if components is not None: vis = dft_skycomponent_visibility(bvis, components) # Add phase errors if phase_error > 0.0 or amplitude_error > 0.0: gt = create_gaintable_from_blockvisibility(bvis) gt = simulate_gaintable(gt=gt, phase_error=phase_error, amplitude_error=amplitude_error) bvis = apply_gaintable(bvis, gt) import time time.sleep(sleep) yield bvis