def solve_gaintable(vis: BlockVisibility, modelvis: BlockVisibility = None, gt=None, phase_only=True, niter=30,
                    tol=1e-8,
                    crosspol=False, **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
    :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
    
    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)
    
    assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt
    
    assert_vis_gt_compatible(vis, gt)
    
    return gt
Пример #2
0
def apply_gaintable(vis: BlockVisibility,
                    gt: GainTable,
                    inverse=False,
                    **kwargs) -> BlockVisibility:
    """Apply a gain table to a block visibility
    
    The corrected visibility is::
    
        V_corrected = {g_i * g_j^*}^-1 V_obs
        
    If the visibility data are polarised e.g. polarisation_frame("linear") then the inverse operator
    represents an actual inverse of the gains.
    
    :param vis: Visibility to have gains applied
    :param gt: Gaintable to be applied
    :param inverse: Apply the inverse (default=False)
    :return: input vis with gains applied
    
    """
    assert type(
        vis) is BlockVisibility, "vis is not a BlockVisibility: %r" % vis
    assert type(gt) is GainTable, "gt is not a GainTable: %r" % gt

    assert_vis_gt_compatible(vis, gt)

    if inverse:
        log.debug('apply_gaintable: Apply inverse gaintable')
    else:
        log.debug('apply_gaintable: Apply gaintable')
    # 按照time对vis进行切片
    for chunk, rows in enumerate(vis_timeslice_iter(vis)):
        vistime = numpy.average(vis.time[rows])
        integration_time = numpy.average(vis.integration_time[rows])
        gaintable_rows = abs(gt.time - vistime) < integration_time / 2.0

        # Lookup the gain for this set of visibilities
        gain = gt.data['gain'][gaintable_rows]

        # The shape of the mueller matrix is
        ntimes, nant, nchan, nrec, _ = gain.shape

        original = vis.vis[rows]
        applied = copy.deepcopy(original)
        for time in range(ntimes):
            for a1 in range(vis.nants - 1):
                for a2 in range(a1 + 1, vis.nants):
                    for chan in range(nchan):
                        mueller = numpy.kron(
                            gain[time, a1, chan, :, :],
                            numpy.conjugate(gain[time, a2, chan, :, :]))
                        if inverse:
                            mueller = numpy.linalg.inv(mueller)

                        applied[time, a2, a1, chan, :] = numpy.matmul(
                            mueller, original[time, a2, a1, chan, :])

        vis.data['vis'][rows] = applied
    return vis
Пример #3
0
def solve_gaintable(vis: BlockVisibility, modelvis: BlockVisibility=None, phase_only=True, niter=30, tol=1e-8,
                    crosspol=False, **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
    :param modelvis: BlockVisibility containing the visibility predicted by a model
    :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 type(vis) is BlockVisibility, "vis is not a BlockVisibility: %r" % vis
    assert type(modelvis) is BlockVisibility or type(modelvis) is None, "modelvis is not None or a " \
                                                                            "BlockVisibility: %r" % vis
    
    if phase_only:
        log.info('solve_gaintable: Solving for phase only')
    else:
        log.info('solve_gaintable: Solving for complex gain')

    # 根据blockvisibility的元数据初始化一个gaintable
    gt = create_gaintable_from_blockvisibility(vis)
    for chunk, rows in enumerate(vis_timeslice_iter(vis, **kwargs)): # 对visibility按照time切片
        # 切片好的visibility shape: [1,nant,nant,nchan,npol]
        subvis = create_visibility_from_rows(vis, rows)
        #若存在model
        if modelvis is not None:
            # model_visibility也要以相同的方式按time切片
            model_subvis = create_visibility_from_rows(modelvis, rows)
            # 两个vis相除计算得到新的block_vis,其中的元数据未改变,只有vis和weight发生了改变
            pointvis = divide_visibility(subvis, model_subvis)
            # 此处因为第0个axis是time轴,并且vis已经按照time分片,所以按照第0axis做了average以后值不发生变化
            x = numpy.average(pointvis.vis, axis=0)
            xwt = numpy.average(pointvis.weight, axis=0)

        else:
            x = numpy.average(subvis.vis, axis=0)
            xwt = numpy.average(subvis.weight, axis=0)

        # 将数据填入gaintable中
        # solve 和 timeslot的分界线
        gt = solve_from_X(gt, x, xwt, chunk, crosspol, niter, phase_only,
                        tol, npol=vis.polarisation_frame.npol)


    assert type(gt) is GainTable, "gt is not a GainTable: %r" % gt
    
    assert_vis_gt_compatible(vis, gt)

    
    return gt
Пример #4
0
def create_gaintable_from_blockvisibility(vis: BlockVisibility,
                                          time_width: float = None,
                                          frequency_width: float = None,
                                          **kwargs) -> GainTable:
    """ Create gain table from visibility.
    
    This makes an empty gain table consistent with the BlockVisibility.
    
    :param vis: BlockVisibilty
    :param time_width: Time interval between solutions (s)
    :param frequency_width: Frequency solution width (Hz)
    :return: GainTable
    
    """
    assert isinstance(
        vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis

    nants = vis.nants
    utimes = numpy.unique(vis.time)
    ntimes = len(utimes)
    ufrequency = numpy.unique(vis.frequency)
    nfrequency = len(ufrequency)

    receptor_frame = ReceptorFrame(vis.polarisation_frame.type)
    nrec = receptor_frame.nrec

    gainshape = [ntimes, nants, nfrequency, nrec, nrec]
    gain = numpy.ones(gainshape, dtype='complex')
    if nrec > 1:
        gain[..., 0, 1] = 0.0
        gain[..., 1, 0] = 0.0

    gain_weight = numpy.ones(gainshape)
    gain_time = utimes
    gain_frequency = ufrequency
    gain_residual = numpy.zeros([ntimes, nfrequency, nrec, nrec])

    gt = GainTable(gain=gain,
                   time=gain_time,
                   weight=gain_weight,
                   residual=gain_residual,
                   frequency=gain_frequency,
                   receptor_frame=receptor_frame)

    assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt
    assert_vis_gt_compatible(vis, gt)

    return gt
Пример #5
0
def apply_gaintable(vis: BlockVisibility,
                    gt: GainTable,
                    inverse=False,
                    **kwargs) -> BlockVisibility:
    """Apply a gain table to a block visibility
    
    The corrected visibility is::
    
        V_corrected = {g_i * g_j^*}^-1 V_obs
        
    If the visibility data are polarised e.g. polarisation_frame("linear") then the inverse operator
    represents an actual inverse of the gains.
    
    :param vis: Visibility to have gains applied
    :param gt: Gaintable to be applied
    :param inverse: Apply the inverse (default=False)
    :return: input vis with gains applied
    
    """
    assert isinstance(
        vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis
    assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt

    assert_vis_gt_compatible(vis, gt)

    if inverse:
        log.debug('apply_gaintable: Apply inverse gaintable')
    else:
        log.debug('apply_gaintable: Apply gaintable')

    is_scalar = gt.gain.shape[-2:] == (1, 1)
    if is_scalar:
        log.debug('apply_gaintable: scalar gains')

    for chunk, rows in enumerate(vis_timeslice_iter(vis, **kwargs)):
        if numpy.sum(rows) > 0:
            vistime = numpy.average(vis.time[rows])
            gaintable_rows = abs(gt.time - vistime) < gt.interval / 2.0

            # Lookup the gain for this set of visibilities
            gain = gt.data['gain'][gaintable_rows]

            # The shape of the mueller matrix is
            ntimes, nant, nchan, nrec, _ = gain.shape

            original = vis.vis[rows]
            applied = copy.deepcopy(original)
            for time in range(ntimes):
                for a1 in range(vis.nants - 1):
                    for a2 in range(a1 + 1, vis.nants):
                        if is_scalar:
                            smueller = gain[time, a1, :, 0] * numpy.conjugate(
                                gain[time, a2, :, 0])
                            if inverse:
                                if numpy.abs(smueller).all() > 0.0:
                                    applied[time, a2, a1, :,
                                            0][..., numpy.newaxis] = original[
                                                time, a2, a1, :,
                                                0][...,
                                                   numpy.newaxis] / smueller
                            else:
                                applied[time, a2, a1, :,
                                        0][..., numpy.newaxis] = original[
                                            time, a2, a1, :,
                                            0][..., numpy.newaxis] * smueller
                        else:
                            for chan in range(nchan):
                                mueller = numpy.kron(
                                    gain[time, a1, chan, :, :],
                                    numpy.conjugate(gain[time, a2,
                                                         chan, :, :]))
                                if inverse:
                                    # If the Mueller is singular, ignore it
                                    try:
                                        mueller = numpy.linalg.inv(mueller)
                                        applied[time, a2, a1,
                                                chan, :] = numpy.matmul(
                                                    mueller,
                                                    original[time, a2, a1,
                                                             chan, :])
                                    except numpy.linalg.linalg.LinAlgError:
                                        applied[time, a2, a1,
                                                chan, :] = original[time, a2,
                                                                    a1,
                                                                    chan, :]
                                else:
                                    applied[time, a2, a1,
                                            chan, :] = numpy.matmul(
                                                mueller, original[time, a2, a1,
                                                                  chan, :])

            vis.data['vis'][rows] = applied
    return vis
Пример #6
0
def create_gaintable_from_blockvisibility(vis: BlockVisibility,
                                          timeslice: float = None,
                                          frequencyslice: float = None,
                                          **kwargs) -> GainTable:
    """ Create gain table from visibility.
    
    This makes an empty gain table consistent with the BlockVisibility.
    
    :param vis: BlockVisibilty
    :param timeslice: Time interval between solutions (s)
    :param frequency_width: Frequency solution width (Hz)
    :return: GainTable
    
    """
    assert isinstance(
        vis, BlockVisibility), "vis is not a BlockVisibility: %r" % vis

    nants = vis.nants

    if timeslice is None or timeslice == 'auto':
        utimes = numpy.unique(vis.time)
        ntimes = len(utimes)
        gain_interval = numpy.zeros([ntimes])
        if ntimes > 1:
            gain_interval[:-1] = utimes[1:] - utimes[0:-1]
            gain_interval[-1] = utimes[-1] - utimes[-2]
        else:
            gain_interval[...] = 1.0

    else:
        ntimes = numpy.ceil((numpy.max(vis.time) - numpy.min(vis.time)) /
                            timeslice).astype('int')
        utimes = numpy.linspace(numpy.min(vis.time), numpy.max(vis.time),
                                ntimes)
        gain_interval = timeslice * numpy.ones([ntimes])

    log.debug('create_gaintable_from_blockvisibility: times are %s' %
              str(utimes))
    log.debug('create_gaintable_from_blockvisibility: intervals are %s' %
              str(gain_interval))

    ntimes = len(utimes)
    ufrequency = numpy.unique(vis.frequency)
    nfrequency = len(ufrequency)

    receptor_frame = ReceptorFrame(vis.polarisation_frame.type)
    nrec = receptor_frame.nrec

    gainshape = [ntimes, nants, nfrequency, nrec, nrec]
    gain = numpy.ones(gainshape, dtype='complex')
    if nrec > 1:
        gain[..., 0, 1] = 0.0
        gain[..., 1, 0] = 0.0

    gain_weight = numpy.ones(gainshape)
    gain_time = utimes
    gain_frequency = ufrequency
    gain_residual = numpy.zeros([ntimes, nfrequency, nrec, nrec])

    gt = GainTable(gain=gain,
                   time=gain_time,
                   interval=gain_interval,
                   weight=gain_weight,
                   residual=gain_residual,
                   frequency=gain_frequency,
                   receptor_frame=receptor_frame)

    assert isinstance(gt, GainTable), "gt is not a GainTable: %r" % gt
    assert_vis_gt_compatible(vis, gt)

    return gt