Beispiel #1
0
    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))
Beispiel #3
0
    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)
Beispiel #8
0
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
Beispiel #17
0
 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
Beispiel #19
0
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
Beispiel #22
0
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
Beispiel #23
0
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
Beispiel #24
0
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
Beispiel #25
0
    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)
Beispiel #27
0
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
Beispiel #28
0
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
Beispiel #29
0
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
Beispiel #30
0
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