Ejemplo n.º 1
0
def cbf_telstate_view(telstate: katsdptelstate.TelescopeState,
                      stream_name: str) -> katsdptelstate.TelescopeState:
    """Create a telstate view that allows querying properties from a stream.
    It supports only baseline-correlation-products and
    tied-array-channelised-voltage streams. Properties that don't exist on the
    stream are searched on the upstream antenna-channelised-voltage stream, and
    then the instrument of that stream.

    Returns
    -------
    view
        Telstate view that allows stream properties to be searched
    """
    prefixes = []
    stream_name = stream_name.replace('.', '_').replace('-', '_')
    prefixes.append(stream_name)
    # Generate a list of places to look for attributes:
    # - the stream itself
    # - the upstream antenna-channelised-voltage stream, and its instrument
    src = telstate.view(stream_name, exclusive=True)['src_streams'][0]
    prefixes.append(src)
    instrument = telstate.view(src, exclusive=True)['instrument_dev_name']
    prefixes.append(instrument)
    # Create a telstate view that has exactly the given prefixes (and no root prefix).
    for i, prefix in enumerate(reversed(prefixes)):
        telstate = telstate.view(prefix, exclusive=(i == 0))
    return telstate
Ejemplo n.º 2
0
def write_telstate(telstate: katsdptelstate.TelescopeState,
                   input_name: str, output_name: str, rename_src: Mapping[str, str],
                   s3_endpoint_url: Optional[str]) -> None:
    """Write telstate information about output stream."""
    telstate_out = telstate.view(output_name)
    if output_name != input_name:
        telstate_out['inherit'] = input_name
        if rename_src:
            telstate_in = telstate.view(input_name)
            src_streams_in = telstate_in['src_streams']
            src_streams_out = [rename_src.get(stream, stream) for stream in src_streams_in]
            telstate_out['src_streams'] = src_streams_out
    if s3_endpoint_url is not None:
        telstate_out['s3_endpoint_url'] = s3_endpoint_url
Ejemplo n.º 3
0
    def test_zero_vis_online(self):
        """Check online pipeline exits gracefully if all data is flagged
        """
        # Create flagged Mock dataset and wrap it in a KatdalAdapter
        ds = MockDataSet(timestamps=DEFAULT_TIMESTAMPS,
                         subarrays=DEFAULT_SUBARRAYS,
                         spws=self.spws,
                         dumps=self.scans,
                         flags=partial(flags, flagged=True))

        # Dummy CB_ID and Product ID and temp fits disk
        fd = kc.get_config()['fitsdirs']
        fd += [(None, '/tmp/FITS')]
        kc.set_config(output_id='OID', cb_id='CBID', fitsdirs=fd)

        setup_aips_disks()

        # Create the pipeline
        pipeline = pipeline_factory('online', ds, TelescopeState(),
                                    katdal_select=self.select,
                                    uvblavg_params=self.uvblavg_params,
                                    mfimage_params=self.mfimage_params)

        metadata = pipeline.execute()
        # Check metadata is empty and no exceptions are thrown
        assert_equal(metadata, {})

        # Get fits area
        cfg = kc.get_config()
        fits_area = cfg['fitsdirs'][-1][1]

        # Remove the tmp/FITS dir
        shutil.rmtree(fits_area)
Ejemplo n.º 4
0
def get_telstate(data, sub):
    """Get TelescopeState object associated with current data product."""
    subarray_product = 'array_%s_%s' % (sub.sensor.sub_nr.get_value(),
                                        sub.sensor.product.get_value())
    reply = data.req.spmc_telstate_endpoint(subarray_product)
    if not reply.succeeded:
        raise ValueError("Could not access telescope state for subarray_product %r",
                         subarray_product)
    return TelescopeState(reply.messages[0].arguments[1])
Ejemplo n.º 5
0
    def __init__(self, host: str, port: int, loop: asyncio.AbstractEventLoop,
                 endpoints: List[Endpoint], flag_interface: Optional[str],
                 flags_ibv: bool, chunk_store: katdal.chunkstore.ChunkStore,
                 chunk_params: spead_write.ChunkParams,
                 telstate: katsdptelstate.TelescopeState, input_name: str,
                 output_name: str, rename_src: Mapping[str, str],
                 s3_endpoint_url: Optional[str], max_workers: int,
                 buffer_dumps: int) -> None:
        super().__init__(host, port, loop=loop)

        self._chunk_store = chunk_store
        self._telstate = telstate
        # track the status of each capture block we have seen to date
        self._capture_block_state = {}  # type: Dict[str, State]
        self._input_name = input_name
        self._output_name = output_name
        # rechunker group for each CBID
        self._flag_streams = {}  # type: Dict[str, RechunkerGroup]
        self._executor = ThreadPoolExecutor(max_workers=max_workers)

        self.sensors.add(
            Sensor(Status, "status",
                   "The current status of the flag writer process."))
        self.sensors.add(
            Sensor(
                str,
                "capture-block-state",
                "JSON dict with the state of each capture block seen in this session.",
                default='{}',
                initial_status=Sensor.Status.NOMINAL))
        for sensor in spead_write.io_sensors():
            self.sensors.add(sensor)
        self.sensors.add(spead_write.device_status_sensor())

        telstate_input = telstate.view(input_name)
        in_chunks = spead_write.chunks_from_telstate(telstate_input)
        DATA_LOST = 1 << FLAG_NAMES.index('data_lost')
        self._arrays = [
            spead_write.make_array('flags', in_chunks, DATA_LOST, np.uint8,
                                   chunk_params)
        ]
        dump_size = sum(array.nbytes for array in self._arrays)
        self._executor_queue_space = QueueSpace(buffer_dumps * dump_size,
                                                loop=self.loop)
        spead_write.write_telstate(telstate, input_name, output_name,
                                   rename_src, s3_endpoint_url)

        rx = spead_write.make_receiver(
            endpoints, self._arrays,
            katsdpservices.get_interface_address(flag_interface), flags_ibv)
        self._writer = FlagWriter(self.sensors, rx, self)
        self._capture_task = loop.create_task(self._do_capture())
Ejemplo n.º 6
0
    def __init__(self, host: str, port: int, loop: asyncio.AbstractEventLoop,
                 endpoints: List[Endpoint], interface: Optional[str],
                 ibv: bool, chunk_store: katdal.chunkstore.ChunkStore,
                 chunk_params: spead_write.ChunkParams,
                 telstate: katsdptelstate.TelescopeState, input_name: str,
                 output_name: str, rename_src: Mapping[str, str],
                 s3_endpoint_url: Optional[str], max_workers: int,
                 buffer_dumps: int) -> None:
        super().__init__(host, port, loop=loop)
        self._endpoints = endpoints
        self._interface_address = katsdpservices.get_interface_address(
            interface)
        self._ibv = ibv
        self._chunk_store = chunk_store
        self._input_name = input_name
        self._output_name = output_name
        self._telstate = telstate
        self._rx = None  # type: Optional[spead2.recv.asyncio.Stream]
        self._max_workers = max_workers

        telstate_input = telstate.view(input_name)
        in_chunks = spead_write.chunks_from_telstate(telstate_input)
        DATA_LOST = 1 << FLAG_NAMES.index('data_lost')
        self._arrays = [
            spead_write.make_array('correlator_data', in_chunks, 0,
                                   np.complex64, chunk_params),
            spead_write.make_array('flags', in_chunks, DATA_LOST, np.uint8,
                                   chunk_params),
            spead_write.make_array('weights', in_chunks, 0, np.uint8,
                                   chunk_params),
            spead_write.make_array('weights_channel', in_chunks[:2], 0,
                                   np.float32, chunk_params)
        ]
        dump_size = sum(array.nbytes for array in self._arrays)
        self._buffer_size = buffer_dumps * dump_size
        spead_write.write_telstate(telstate, input_name, output_name,
                                   rename_src, s3_endpoint_url)

        self._capture_task = None  # type: Optional[asyncio.Task]
        self._n_substreams = len(in_chunks[1])

        self.sensors.add(
            Sensor(Status,
                   'status',
                   'The current status of the capture process',
                   default=Status.IDLE,
                   initial_status=Sensor.Status.NOMINAL,
                   status_func=_status_status))
        for sensor in spead_write.io_sensors():
            self.sensors.add(sensor)
        self.sensors.add(spead_write.device_status_sensor())
Ejemplo n.º 7
0
def set_telescope_state(h5_file: h5py.File,
                        tstate: katsdptelstate.TelescopeState,
                        base_path: str = _TSTATE_DATASET,
                        start_timestamp: float = 0.0) -> None:
    """Write raw pickled telescope state to an HDF5 file."""
    tstate_group = h5_file.create_group(base_path)
    # include the subarray product id for use by the crawler to identify which
    # system the file belongs to.
    tstate_group.attrs['subarray_product_id'] = tstate.get(
        'subarray_product_id', 'none')
    tstate_keys = tstate.keys()
    logger.info("Writing {} telescope state keys to {}".format(
        len(tstate_keys), base_path))

    sensor_dtype = np.dtype([('timestamp', np.float64),
                             ('value', h5py.special_dtype(vlen=np.uint8))])
    for key in tstate_keys:
        if tstate.key_type(key) == katsdptelstate.KeyType.MUTABLE:
            # retrieve all values for a particular key
            sensor_values = tstate.get_range(key,
                                             st=start_timestamp,
                                             include_previous=True,
                                             return_encoded=True)
            # swap value, timestamp to timestamp, value
            sensor_values = [(timestamp, np.frombuffer(value, dtype=np.uint8))
                             for (value, timestamp) in sensor_values]
            dset = np.rec.fromrecords(sensor_values,
                                      dtype=sensor_dtype,
                                      names='timestamp,value')
            tstate_group.create_dataset(key, data=dset)
            logger.debug(
                "TelescopeState: Written {} values for key {} to file".format(
                    len(dset), key))
        else:
            tstate_group.attrs[key] = np.void(
                tstate.get(key, return_encoded=True))
            logger.debug(
                "TelescopeState: Key {} written as an attribute".format(key))
Ejemplo n.º 8
0
    def test_new_online_pipeline(self):
        """
        Tests that a run of the online continuum pipeline exectues.
        """
        # Create Mock dataset and wrap it in a KatdalAdapter
        ds = MockDataSet(timestamps=DEFAULT_TIMESTAMPS,
                         subarrays=DEFAULT_SUBARRAYS,
                         spws=self.spws,
                         dumps=self.scans)

        # Create a FAKE object
        FAKE = object()

        # Test that metadata agrees
        for k, v in DEFAULT_METADATA.items():
            self.assertEqual(v, getattr(ds, k, FAKE))

        # Dummy CB_ID and Product ID and temp fits disk
        fd = kc.get_config()['fitsdirs']
        fd += [(None, '/tmp/FITS')]
        kc.set_config(output_id='OID', cb_id='CBID', fitsdirs=fd)

        setup_aips_disks()

        # Create the pipeline
        pipeline = pipeline_factory('online', ds, TelescopeState(),
                                    katdal_select=self.select,
                                    uvblavg_params=self.uvblavg_params,
                                    mfimage_params=self.mfimage_params)

        metadata = pipeline.execute()

        # Check that output FITS files exist and have the right names
        cfg = kc.get_config()
        cb_id = cfg['cb_id']
        out_id = cfg['output_id']
        fits_area = cfg['fitsdirs'][-1][1]

        for otarg in self.sanitised_target_names:
            out_strings = [cb_id, out_id, otarg, IMG_CLASS]
            filename = '_'.join(filter(None, out_strings)) + '.fits'
            assert_in(filename, metadata['FITSImageFilename'])
            filepath = os.path.join(fits_area, filename)
            assert os.path.isfile(filepath)
            _check_fits_headers(filepath)

        # Remove the tmp/FITS dir
        shutil.rmtree(fits_area)
Ejemplo n.º 9
0
def get_stats(dataset: katdal.DataSet,
              telstate: katsdptelstate.TelescopeState) -> Tuple[CommonStats, List[TargetStats]]:
    common = CommonStats(dataset, telstate)
    stats = [TargetStats(dataset, common, katpoint.Target(target))
             for target in telstate.get('targets', {})]
    stats_lookup = {target.description: target for target in stats}
    for ((target_desc, channel), status) in telstate.get('status', {}).items():
        stats_lookup[target_desc].status[channel] = status
    for ((target_desc, channel), peak) in telstate.get('peak', {}).items():
        stats_lookup[target_desc].peak[channel] = peak * (u.Jy / u.beam)
    for ((target_desc, channel, pol), total) in telstate.get('total', {}).items():
        stats_lookup[target_desc].totals[pol][channel] = total * u.Jy
    for ((target_desc, channel), noise) in telstate.get('noise', {}).items():
        stats_lookup[target_desc].noise[channel] = noise * (u.Jy / u.beam)
    for ((target_desc, channel), noise) in telstate.get('weights_noise', {}).items():
        stats_lookup[target_desc].weights_noise[channel] = noise * (u.Jy / u.beam)
    for ((target_desc, channel), normalized_noise) in telstate.get('normalized_noise', {}).items():
        stats_lookup[target_desc].normalized_noise[channel] = normalized_noise
    return common, stats
Ejemplo n.º 10
0
def main():
    setup_logging()
    parser = create_parser()
    args = parser.parse_args()

    # Open the observation
    if (args.access_key is not None) != (args.secret_key is not None):
        parser.error('--access-key and --secret-key must be used together')
    if args.access_key is not None and args.token is not None:
        parser.error('--access-key/--secret-key cannot be used with --token')
    open_kwargs = {}
    if args.access_key is not None:
        open_kwargs['credentials'] = (args.access_key, args.secret_key)
    elif args.token is not None:
        open_kwargs['token'] = args.token
    katdata = katdal.open(args.katdata, applycal='l1', **open_kwargs)

    post_process_args(args, katdata)

    uvblavg_args, mfimage_args, band = _infer_defaults_from_katdal(katdata)

    # Get config defaults for uvblavg and mfimage and merge user supplied ones
    uvblavg_parm_file = pjoin(CONFIG, f'uvblavg_MKAT_{band}.yaml')
    log.info('UVBlAvg parameter file for %s-band: %s', band, uvblavg_parm_file)
    mfimage_parm_file = pjoin(CONFIG, f'mfimage_MKAT_{band}.yaml')
    log.info('MFImage parameter file for %s-band: %s', band, mfimage_parm_file)

    user_uvblavg_args = get_and_merge_args(uvblavg_parm_file, args.uvblavg)
    user_mfimage_args = get_and_merge_args(mfimage_parm_file, args.mfimage)

    # Merge katdal defaults with user supplied defaults
    recursive_merge(user_uvblavg_args, uvblavg_args)
    recursive_merge(user_mfimage_args, mfimage_args)

    # Get the default config.
    dc = kc.get_config()
    # Set up aipsdisk configuration from args.workdir
    if args.workdir is not None:
        aipsdirs = [(None,
                     pjoin(args.workdir, args.capture_block_id + '_aipsdisk'))]
    else:
        aipsdirs = dc['aipsdirs']
    log.info('Using AIPS data area: %s', aipsdirs[0][1])

    # Set up output configuration from args.outputdir
    fitsdirs = dc['fitsdirs']

    outputname = args.capture_block_id + OUTDIR_SEPARATOR + args.telstate_id + \
        OUTDIR_SEPARATOR + START_TIME

    outputdir = pjoin(args.outputdir, outputname)
    # Set writing tag for duration of the pipeline
    work_outputdir = outputdir + WRITE_TAG
    # Append outputdir to fitsdirs
    # NOTE: Pipeline is set up to always place its output in the
    # highest numbered fits disk so we ensure that is the case
    # here.
    fitsdirs += [(None, work_outputdir)]
    log.info('Using output data area: %s', outputdir)

    kc.set_config(aipsdirs=aipsdirs, fitsdirs=fitsdirs)

    setup_aips_disks()

    # Add output_id and capture_block_id to configuration
    kc.set_config(cfg=kc.get_config(),
                  output_id=args.output_id,
                  cb_id=args.capture_block_id)

    # Set up telstate link then create
    # a view based the capture block ID and output ID
    telstate = TelescopeState(args.telstate)
    view = telstate.join(args.capture_block_id, args.telstate_id)
    ts_view = telstate.view(view)

    katdal_select = args.select
    katdal_select['nif'] = args.nif

    # Create Continuum Pipeline
    pipeline = pipeline_factory('online',
                                katdata,
                                ts_view,
                                katdal_select=katdal_select,
                                uvblavg_params=uvblavg_args,
                                mfimage_params=mfimage_args,
                                nvispio=args.nvispio)

    # Execute it
    metadata = pipeline.execute()

    # Create QA products if images were created
    if metadata:
        make_pbeam_images(metadata, outputdir, WRITE_TAG)
        make_qa_report(metadata, outputdir, WRITE_TAG)
        organise_qa_output(metadata, outputdir, WRITE_TAG)

        # Remove the writing tag from the output directory
        os.rename(work_outputdir, outputdir)
    else:
        os.rmdir(work_outputdir)
Ejemplo n.º 11
0
    def test_gains_export(self):
        """Check l2 export to telstate"""
        nchan = 128
        nif = 4
        dump_period = 1.0
        centre_freq = 1200.e6
        bandwidth = 100.e6
        solPint = dump_period / 2.
        solAint = dump_period
        AP_telstate = 'product_GAMP_PHASE'
        P_telstate = 'product_GPHASE'

        spws = [{'centre_freq': centre_freq,
                 'num_chans': nchan,
                 'channel_width': bandwidth / nchan,
                 'sideband': 1,
                 'band': 'L'}]
        ka_select = {'pol': 'HH,VV', 'scans': 'track',
                     'corrprods': 'cross', 'nif': nif}
        uvblavg_params = {'maxFact': 1.0, 'avgFreq': 0,
                          'FOV': 100.0, 'maxInt': 1.e-6}
        mfimage_params = {'Niter': 50, 'FOV': 0.1,
                          'xCells': 5., 'yCells': 5.,
                          'doGPU': False, 'Robust': -1.5,
                          'minFluxPSC': 0.1, 'solPInt': solPint / 60.,
                          'solPMode': 'P', 'minFluxASC': 0.1,
                          'solAInt': solAint / 60., 'maxFBW': 0.02}

        # Simulate a '10Jy' source at the phase center
        cat = katpoint.Catalogue()
        cat.add(katpoint.Target(
            "Alberich lord of the Nibelungs, radec, 20.0, -30.0, (856. 1712. 1. 0. 0.)"))

        telstate = TelescopeState()

        # Set up a scratch space in /tmp
        fd = kc.get_config()['fitsdirs']
        fd += [(None, '/tmp/FITS')]
        kc.set_config(cb_id='CBID', fitsdirs=fd)
        setup_aips_disks()

        scan = [('track', 4, cat.targets[0])]

        # Construct a simulated dataset with our
        # point source at the centre of the field
        ds = MockDataSet(timestamps={'start_time': 0.0, 'dump_period': dump_period},
                         subarrays=DEFAULT_SUBARRAYS,
                         spws=spws,
                         dumps=scan,
                         vis=partial(vis, sources=cat),
                         weights=weights,
                         flags=flags)

        # Try one round of phase only self-cal & Amp+Phase self-cal
        mfimage_params['maxPSCLoop'] = 1
        mfimage_params['maxASCLoop'] = 1

        # Run the pipeline
        pipeline = pipeline_factory('online', ds, telstate, katdal_select=ka_select,
                                    uvblavg_params=uvblavg_params,
                                    mfimage_params=mfimage_params)
        pipeline.execute()

        ts = telstate.view('selfcal')
        # Check what we have in telstate agrees with what we put in
        self.assertEqual(len(ts['antlist']), len(ANTENNA_DESCRIPTIONS))
        self.assertEqual(ts['bandwidth'], bandwidth)
        self.assertEqual(ts['n_chans'], nif)
        pol_ordering = [pol[0] for pol in sorted(CORR_ID_MAP, key=CORR_ID_MAP.get)
                        if pol[0] == pol[1]]
        self.assertEqual(ts['pol_ordering'], pol_ordering)
        if_width = bandwidth / nif
        center_if = nif // 2
        start_freq = centre_freq - (bandwidth / 2.)
        self.assertEqual(ts['center_freq'], start_freq + if_width * (center_if + 0.5))

        self.assertIn(ts.join('selfcal', P_telstate), ts.keys())
        self.assertIn(ts.join('selfcal', AP_telstate), ts.keys())

        def check_gains_timestamps(gains, expect_timestamps):
            timestamps = []
            for gain, timestamp in gains:
                np.testing.assert_array_almost_equal(np.abs(gain), 1.0, decimal=3)
                np.testing.assert_array_almost_equal(np.angle(gain), 0.0)
                timestamps.append(timestamp)
            np.testing.assert_array_almost_equal(timestamps, expect_timestamps, decimal=1)

        # Check phase-only gains and timestamps
        P_times = np.arange(solPint, ds.end_time.secs, 2. * solPint)
        check_gains_timestamps(ts.get_range(P_telstate, st=0), P_times)
        # Check Amp+Phase gains
        AP_times = np.arange(solAint, ds.end_time.secs, 2. * solAint)
        check_gains_timestamps(ts.get_range(AP_telstate, st=0), AP_times)

        # Check with no Amp+Phase self-cal
        mfimage_params['maxASCLoop'] = 0
        telstate.clear()
        pipeline = pipeline_factory('online', ds, telstate, katdal_select=ka_select,
                                    uvblavg_params=uvblavg_params,
                                    mfimage_params=mfimage_params)
        pipeline.execute()
        self.assertIn(telstate.join('selfcal', P_telstate), ts.keys())
        self.assertNotIn(telstate.join('selfcal', AP_telstate), ts.keys())

        # Check with no self-cal
        mfimage_params['maxPSCLoop'] = 0
        telstate.clear()
        pipeline = pipeline_factory('online', ds, telstate, katdal_select=ka_select,
                                    uvblavg_params=uvblavg_params,
                                    mfimage_params=mfimage_params)
        pipeline.execute()
        self.assertNotIn(telstate.join('selfcal', P_telstate), ts.keys())
        self.assertNotIn(telstate.join('selfcal', AP_telstate), ts.keys())

        # Cleanup workspace
        shutil.rmtree(fd[-1][1])
Ejemplo n.º 12
0
    def test_table_versions(self):
        """Check correct SN table versions are exported to telstate"""
        # Make a dummy AIPS UV and attach some SN Tables
        with obit_context():
            nif = 1
            ap = AIPSPath("Woglinde")
            # Make a list of 4 SN tables with gains equal to version number
            row = partial(construct_SN_default_rows, [0.5], [1], nif)
            sn_tables = [construct_SN_desc(nif, row(gain=float(ver)), version=ver)
                         for ver in range(1, 5)]
            # Create empty UV object and attach the tables
            for sn in sn_tables:
                uvf = uv_factory(aips_path=ap, mode="w", table_cmds=sn)
                # Flush the added table to disk
                uvf.Close()

            # Dummy telstate
            ts = TelescopeState()
            AP_telstate = ts.join('selfcal', 'product_GAMP_PHASE')
            P_telstate = ts.join('selfcal', 'product_GPHASE')
            # A basic MockDataSet
            spw = [{'centre_freq': 1200.e6,
                    'num_chans': 1,
                    'channel_width': 1.e6}]
            targ = katpoint.construct_radec_target(0., 0.)
            scan = [('track', 1, targ)]
            suba = {}
            # Only need 1 antenna
            suba['antenna'] = DEFAULT_SUBARRAYS[0]['antenna'][0:1]
            ka = KatdalAdapter(MockDataSet(spws=spw, dumps=scan, subarrays=[suba]))

            # Fake input parameters with 2 phase and 2 amp+phase self-cal
            mfimage_parms = {'maxPSCLoop': 2,
                             'maxASCLoop': 2}
            export_calibration_solutions([ap], ka, mfimage_parms, ts)
            # Should have solns from SN:2 in 'product_GPHASE'
            # and from SN:4 in 'product_GAMP_PHASE'
            self.assertEqual(ts[P_telstate][0, 0, 0], 2.+2.j)
            self.assertEqual(ts[AP_telstate][0, 0, 0], 4.+4.j)
            ts.clear()

            # Fake input parameters with 2 phase and 3 amp+phase self-cal
            mfimage_parms = {'maxPSCLoop': 2,
                             'maxASCLoop': 3}
            export_calibration_solutions([ap], ka, mfimage_parms, ts)
            # Should have solns from SN:2 in 'product_GPHASE'
            # and from SN:4 in 'product_GAMP_PHASE'
            self.assertEqual(ts[P_telstate][0, 0, 0], 2.+2.j)
            self.assertEqual(ts[AP_telstate][0, 0, 0], 4.+4.j)
            ts.clear()

            # Fake input parameters with 5 phase and 1 amp+phase self-cal
            mfimage_parms = {'maxPSCLoop': 5,
                             'maxASCLoop': 1}
            export_calibration_solutions([ap], ka, mfimage_parms, ts)
            # Should have solns from SN:4 in 'product_GPHASE'
            # and no solutions in 'product_GAMP_PHASE'
            self.assertEqual(ts[P_telstate][0, 0, 0], 4.+4.j)
            self.assertNotIn(AP_telstate, ts.keys())
            ts.clear()

            # Fake input parameters with 4 phase and 0 amp+phase self-cal
            mfimage_parms = {'maxPSCLoop': 4,
                             'maxASCLoop': 0}
            export_calibration_solutions([ap], ka, mfimage_parms, ts)
            # Should have solns from SN:4 in 'product_GPHASE'
            # and no solutions in 'product_GAMP_PHASE'
            self.assertEqual(ts[P_telstate][0, 0, 0], 4.+4.j)
            self.assertNotIn(AP_telstate, ts.keys())
            ts.clear()
            uvf.Zap()

            # Check that nothing is exported when the AIPS SN table versions
            # are not sequential starting from 1
            for sn in sn_tables[1:4:2]:
                uvf = uv_factory(aips_path=ap, mode="w", table_cmds=sn)
                # Flush the added table to disk
                uvf.Close()

            mfimage_parms = {'maxPSCLoop': 2,
                             'maxASCLoop': 2}
            export_calibration_solutions([ap], ka, mfimage_parms, ts)
            # Should have no solutions in 'product_GPHASE'
            # and no solutions in 'product_GAMP_PHASE'
            self.assertNotIn(P_telstate, ts.keys())
            self.assertNotIn(AP_telstate, ts.keys())
            ts.clear()
            uvf.Zap()
Ejemplo n.º 13
0
    def test_cc_export(self):
        """Check CC models returned by MFImage
        """
        nchan = 128

        spws = [{'centre_freq': .856e9 + .856e9 / 2.,
                 'num_chans': nchan,
                 'channel_width': .856e9 / nchan,
                 'sideband': 1,
                 'band': 'L'}]

        katdal_select = {'pol': 'HH,VV', 'scans': 'track',
                         'corrprods': 'cross'}
        uvblavg_params = {'FOV': 0.2, 'avgFreq': 0,
                          'chAvg': 1, 'maxInt': 2.0}

        cat = katpoint.Catalogue()
        cat.add(katpoint.Target("Amfortas, radec, 0.0, -90.0, (856. 1712. 1. 0. 0.)"))
        cat.add(katpoint.Target("Klingsor, radec, 0.0, 0.0, (856. 1712. 2. -0.7 0.1)"))
        cat.add(katpoint.Target("Kundry, radec, 100.0, -35.0, (856. 1712. -1.0 1. -0.1)"))

        ts = TelescopeState()

        # Set up a scratch space in /tmp
        fd = kc.get_config()['fitsdirs']
        fd += [(None, '/tmp/FITS')]
        kc.set_config(cb_id='CBID', fitsdirs=fd)

        setup_aips_disks()

        # Point sources with various flux models
        for targ in cat:
            scans = [('track', 5, targ)]
            ds = MockDataSet(timestamps={'start_time': 1.0, 'dump_period': 4.0},
                             subarrays=DEFAULT_SUBARRAYS,
                             spws=spws,
                             dumps=scans,
                             vis=partial(vis, sources=[targ]),
                             weights=weights,
                             flags=flags)

            # 100 clean components
            mfimage_params = {'Niter': 100, 'maxFBW': 0.05,
                              'FOV': 0.1, 'xCells': 5.,
                              'yCells': 5., 'doGPU': False}

            pipeline = pipeline_factory('online', ds, ts, katdal_select=katdal_select,
                                        uvblavg_params=uvblavg_params,
                                        mfimage_params=mfimage_params)
            pipeline.execute()

            # Get the fitted CCs from telstate
            fit_cc = ts.get('target0_clean_components')
            ts.delete('target0_clean_components')

            all_ccs = katpoint.Catalogue(fit_cc['components'])
            # Should have one merged and fitted component
            self.assertEqual(len(all_ccs), 1)

            cc = all_ccs.targets[0]
            out_fluxmodel = cc.flux_model
            in_fluxmodel = targ.flux_model

            # Check the flux densities of the flux model in the fitted CC's
            test_freqs = np.linspace(out_fluxmodel.min_freq_MHz, out_fluxmodel.max_freq_MHz, 5)
            in_flux = in_fluxmodel.flux_density(test_freqs)
            out_flux = out_fluxmodel.flux_density(test_freqs)
            np.testing.assert_allclose(out_flux, in_flux, rtol=1.e-3)

        # A field with some off axis sources to check positions
        offax_cat = katpoint.Catalogue()
        offax_cat.add(katpoint.Target("Titurel, radec, 100.1, -35.05, (856. 1712. 1.1 0. 0.)"))
        offax_cat.add(katpoint.Target("Gurmenanz, radec, 99.9, -34.95, (856. 1712. 1. 0. 0.)"))

        scans = [('track', 5, cat.targets[2])]
        ds = MockDataSet(timestamps={'start_time': 1.0, 'dump_period': 4.0},
                         subarrays=DEFAULT_SUBARRAYS,
                         spws=spws,
                         dumps=scans,
                         vis=partial(vis, sources=offax_cat),
                         weights=weights,
                         flags=flags)

        # Small number of CC's and high gain (not checking flux model)
        mfimage_params['Niter'] = 4
        mfimage_params['FOV'] = 0.2
        mfimage_params['Gain'] = 0.5
        mfimage_params['Robust'] = -5

        pipeline = pipeline_factory('online', ds, ts, katdal_select=katdal_select,
                                    uvblavg_params=uvblavg_params,
                                    mfimage_params=mfimage_params)
        pipeline.execute()
        fit_cc = ts.get('target0_clean_components')
        ts.delete('target0_clean_components')
        all_ccs = katpoint.Catalogue(fit_cc['components'])
        # We should have 2 merged clean components for two source positions
        self.assertEqual(len(all_ccs), 2)

        # Check the positions of the clean components
        # These will be ordered by decreasing flux density of the inputs
        # Position should be accurate to within a 5" pixel
        delta_dec = np.deg2rad(5./3600.)
        for model, cc in zip(offax_cat.targets, all_ccs.targets):
            delta_ra = delta_dec/np.cos(model.radec()[1])
            self.assertAlmostEqual(cc.radec()[0], model.radec()[0], delta=delta_ra)
            self.assertAlmostEqual(cc.radec()[1], model.radec()[1], delta=delta_dec)

        # Empty the scratch space
        shutil.rmtree(fd[-1][1])