コード例 #1
0
ファイル: test_cbf.py プロジェクト: ska-sa/mkat_fpga_tests
 def setUp(self):
     self.receiver = CorrRx(port=8888)
     start_thread_with_cleanup(self, self.receiver, start_timeout=1)
     self.correlator = correlator_fixture.correlator
     self.corr_fix = correlator_fixture
     self.corr_freqs = CorrelatorFrequencyInfo(self.correlator.configd)
     dsim_conf = self.correlator.configd['dsimengine']
     dig_host = dsim_conf['host']
     self.dhost = FpgaDsimHost(dig_host, config=dsim_conf)
     self.dhost.get_system_information()
     # Increase the dump rate so tests can run faster
     self.correlator.xeng_set_acc_time(0.2)
     self.addCleanup(self.corr_fix.stop_x_data)
     self.corr_fix.start_x_data()
     self.corr_fix.issue_metadata()
コード例 #2
0
def SpeadRx(config_file, rx_port, dsim_start, capture_start, debug, verbose):
    """
    Receive data from Correlator and play
    """
    if config_file is None:
        sys.exit("Usage: %s --help" % __file__)

    try:
        assert verbose
        _level = 'DEBUG'
        logging.basicConfig(
            level=logging.DEBUG,
            format=
            '%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(pathname)s : '
            '%(lineno)d - %(message)s')
        corr_rx_logger.setLevel(logging.DEBUG)
        spead2_logger.setLevel(logging.DEBUG)
        logging.debug('DEBUG MODE ENABLED')
    except:
        _level = 'INFO'
        logging.basicConfig(
            level=logging.INFO,
            format=
            '%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(pathname)s : '
            '%(lineno)d - %(message)s')
        corr_rx_logger.setLevel(logging.INFO)
        spead2_logger.setLevel(logging.INFO)
    finally:
        logger = logging.getLogger(__name__)
        coloredlogs.install(level=_level, logger=logger)

    if dsim_start and config_file:
        corr_conf = utils.parse_ini_file(config_file, ['dsimengine'])
        dsim_conf = corr_conf['dsimengine']
        dhost = FpgaDsimHost(dsim_conf['host'], config=dsim_conf)
        try:
            assert dhost.is_running()
            dhost.get_system_information()
        except:
            logger.error('DEngine Not Running!')

    try:
        assert capture_start
    except AssertionError:

        @atexit.register
        def Cleanup():
            logger.info('baseline-correlation-products capture stopped!')
            receiver.stop()
            receiver.join()
            logger.info('Receiver stopped.')
            fab.local(
                "kcpcmd -t 60 -s localhost:$(kcpcmd array-list | grep -a array-list | cut -f3 -d ' ' ) capture-stop baseline-correlation-products"
            )
    else:
        logger.info('baseline-correlation-products capture started!')
        fab.local(
            "kcpcmd -t 60 -s localhost:$(kcpcmd array-list | grep -a array-list | cut -f3 -d ' ' ) capture-start baseline-correlation-products"
        )

    try:
        receiver = CorrRx(port=rx_port, queue_size=5)
        _multicast_ips = corr_conf['xengine'].get(
            'multicast_interface_address', '239.100.0.1')
        # import IPython; IPython.embed(header='Python Debugger')
    except Exception as ex:
        template = "An exception of type {0} occured while trying to instantiate receiver. Arguments:\n{1!r}"
        message = template.format(type(ex), ex.args)
        logger.info(message)
    else:
        logger.info('Waiting for receiver to report running')
        receiver.daemon = True
        receiver.start(timeout=10)
        if receiver.running_event.wait(timeout=10):
            logger.info('Receiver ready')
        else:
            msg = 'Receiver not ready'
            logger.info(msg)
            raise RuntimeError(msg)
        try:
            raw_input('Press Enter get clean dump')
            dump = receiver.get_clean_dump()
        except KeyboardInterrupt:
            logger.info('Keyboard interrupt')
        except Exception:
            raise
        else:
            logger.info('Dump received')
        if debug:
            corr_rx_logger.setLevel(logging.FATAL)
            spead2_logger.setLevel(logging.FATAL)
            import IPython
            IPython.embed(header='Python Debugger')
コード例 #3
0
ファイル: test_cbf.py プロジェクト: ska-sa/mkat_fpga_tests
class test_CBF(unittest.TestCase):
    def setUp(self):
        self.receiver = CorrRx(port=8888)
        start_thread_with_cleanup(self, self.receiver, start_timeout=1)
        self.correlator = correlator_fixture.correlator
        self.corr_fix = correlator_fixture
        self.corr_freqs = CorrelatorFrequencyInfo(self.correlator.configd)
        dsim_conf = self.correlator.configd['dsimengine']
        dig_host = dsim_conf['host']
        self.dhost = FpgaDsimHost(dig_host, config=dsim_conf)
        self.dhost.get_system_information()
        # Increase the dump rate so tests can run faster
        self.correlator.xeng_set_acc_time(0.2)
        self.addCleanup(self.corr_fix.stop_x_data)
        self.corr_fix.start_x_data()
        self.corr_fix.issue_metadata()

    # TODO 2015-05-27 (NM) Do test using get_vacc_offset(test_dump['xeng_raw']) to see if
    # the VACC is rotated. Run this test first so that we know immediately that other
    # tests will be b0rked.

    def test_channelisation(self):
        """TP.C.1.19 CBF Channelisation Wideband Coarse L-band"""
        test_chan = 1500
        expected_fc = self.corr_freqs.chan_freqs[test_chan]

        init_dsim_sources(self.dhost)
        self.dhost.sine_sources.sin_0.set(frequency=expected_fc, scale=0.25)
        # The signal source is going to quantise the requested freqency, so see what we
        # actually got
        source_fc = self.dhost.sine_sources.sin_0.frequency

        # Get baseline 0 data, i.e. auto-corr of m000h
        test_baseline = 0
        test_data = self.receiver.get_clean_dump(DUMP_TIMEOUT)['xeng_raw']
        b_mag = normalised_magnitude(test_data[:, test_baseline, :])
        # find channel with max power
        max_chan = np.argmax(b_mag)
        # self.assertEqual(max_chan, test_chan,
        #                  'Channel with max power is not the test channel')

        requested_test_freqs = self.corr_freqs.calc_freq_samples(
            test_chan, samples_per_chan=101, chans_around=5)

        # Placeholder of actual frequencies that the signal generator produces
        actual_test_freqs = []
        # Channel magnitude responses for each frequency
        chan_responses = []
        last_source_freq = None
        for i, freq in enumerate(requested_test_freqs):
            # LOGGER.info('Getting channel response for freq {}/{}: {} MHz.'.format(
            #     i+1, len(requested_test_freqs), freq/1e6))
            print ('Getting channel response for freq {}/{}: {} MHz.'.format(
                i+1, len(requested_test_freqs), freq/1e6))
            if freq == expected_fc:
                # We've already done this one!
                this_source_freq = source_fc
                this_freq_result = b_mag
            else:
                self.dhost.sine_sources.sin_0.set(frequency=freq, scale=0.125)
                this_source_freq = self.dhost.sine_sources.sin_0.frequency
                if this_source_freq == last_source_freq:
                    LOGGER.info('Skipping channel response for freq {}/{}: {} MHz.\n'
                                'Digitiser frequency is same as previous.'.format(
                                    i+1, len(requested_test_freqs), freq/1e6))
                    continue    # Already calculated this one
                else:
                    last_source_freq = this_source_freq
                this_freq_data = self.receiver.get_clean_dump(DUMP_TIMEOUT)['xeng_raw']
                this_freq_response = normalised_magnitude(
                    this_freq_data[:, test_baseline, :])
            actual_test_freqs.append(this_source_freq)
            chan_responses.append(this_freq_response)
        self.corr_fix.stop_x_data()

        # Convert the lists to numpy arrays for easier working
        actual_test_freqs = np.array(actual_test_freqs)
        chan_responses = np.array(chan_responses)

        def plot_and_save(freqs, data, plot_filename):
            df = self.corr_freqs.delta_f
            fig = plt.plot(freqs, data)[0]
            axes = fig.get_axes()
            ybound = axes.get_ybound()
            yb_diff = abs(ybound[1] - ybound[0])
            new_ybound = [ybound[0] - yb_diff*1.1, ybound[1] + yb_diff * 1.1]
            plt.vlines(expected_fc, *new_ybound, colors='r', label='chan fc')
            plt.vlines(expected_fc - df / 2, *new_ybound, label='chan min/max')
            plt.vlines(expected_fc - 0.8*df / 2, *new_ybound, label='chan +-40%',
                       linestyles='dashed')
            plt.vlines(expected_fc + df / 2, *new_ybound, label='_chan max')
            plt.vlines(expected_fc + 0.8*df / 2, *new_ybound, label='_chan +40%',
                       linestyles='dashed')
            plt.legend()
            plt.title('Channel {} ({} MHz) response'.format(
                test_chan, expected_fc/1e6))
            axes.set_ybound(*new_ybound)
            plt.grid(True)
            plt.ylabel('dB relative to VACC max')
            # TODO Normalise plot to frequency bins
            plt.xlabel('Frequency (Hz)')
            plt.savefig(plot_filename)
            plt.close()

        graph_name = '{}.{}.channel_response.svg'.format(strclass(self.__class__),
                                                         self._testMethodName)
        plot_data_all  = loggerise(chan_responses[:, test_chan], dynamic_range=90)
        plot_and_save(actual_test_freqs, plot_data_all, graph_name)

        # Get responses for central 80% of channel
        df = self.corr_freqs.delta_f
        central_indices = (
            (actual_test_freqs <= expected_fc + 0.8*df) &
            (actual_test_freqs >= expected_fc - 0.8*df))
        central_chan_responses = chan_responses[central_indices]
        central_chan_test_freqs = actual_test_freqs[central_indices]

        # Test responses in central 80% of channel
        for i, freq in enumerate(central_chan_test_freqs):
            max_chan = np.argmax(np.abs(central_chan_responses[i]))
            self.assertEqual(max_chan, test_chan, 'Source freq {} peak not in channel '
                             '{} as expected but in {}.'
                             .format(freq, test_chan, max_chan))

        # TODO Graph the central 80%  too.
        self.assertLess(
            np.max(np.abs(central_chan_responses[:, test_chan])), 0.99,
            'VACC output at > 99% of maximum value, indicates that '
            'something, somewhere, is probably overranging.')
        max_central_chan_response = np.max(10*np.log10(central_chan_responses[:, test_chan]))
        min_central_chan_response = np.min(10*np.log10(central_chan_responses[:, test_chan]))
        chan_ripple = max_chan_response - min_chan_response
        acceptable_ripple_lt = 0.3


        self.assertLess(chan_ripple, acceptable_ripple_lt,
                        'ripple {} dB within 80% of channel fc is >= {} dB'
                        .format(chan_ripple, acceptable_ripple_lt))

        # from matplotlib import pyplot
        # colour_cycle = 'rgbyk'
        # style_cycle = ['-', '--']
        # linestyles = itertools.cycle(itertools.product(style_cycle, colour_cycle))
        # for i, freq in enumerate(actual_test_freqs):
        #     style, colour = linestyles.next()
        #     pyplot.plot(loggerise(chan_responses[:, i], dynamic_range=60), color=colour, ls=style)
        # pyplot.ion()
        # pyplot.show()
        # import IPython ; IPython.embed()

    def test_product_baselines(self):
        """CBF Baseline Correlation Products: VR.C.19, TP.C.1.3"""

        init_dsim_sources(self.dhost)
        # Put some correlated noise on both outputs
        self.dhost.noise_sources.noise_corr.set(scale=0.5)
        test_dump = self.receiver.get_clean_dump(DUMP_TIMEOUT)

        # Get list of all the correlator input labels
        input_labels = sorted(tuple(test_dump['input_labelling'][:,0]))
        # Get list of all the baselines present in the correlator output
        present_baselines = sorted(
            set(tuple(bl) for bl in test_dump['bls_ordering']))

        # Make a list of all possible baselines (including redundant baselines) for the
        # given list of inputs
        possible_baselines = set()
        for li in input_labels:
            for lj in input_labels:
                possible_baselines.add((li, lj))

        test_bl = sorted(list(possible_baselines))
        # Test that each baseline (or its reverse-order counterpart) is present in the
        # correlator output
        baseline_is_present = {}

        for test_bl in possible_baselines:
           baseline_is_present[test_bl] = (test_bl in present_baselines or
                                           test_bl[::-1] in present_baselines)
        self.assertTrue(all(baseline_is_present.values()),
                        "Not all baselines are present in correlator output.")

        test_data = test_dump['xeng_raw']
        # Expect all baselines and all channels to be non-zero
        self.assertFalse(zero_baselines(test_data))
        self.assertEqual(nonzero_baselines(test_data),
                         all_nonzero_baselines(test_data))

        # Save initial f-engine equalisations
        initial_equalisations = {input: eq_info['eq'] for input, eq_info
                                in self.correlator.feng_eq_get().items()}
        def restore_initial_equalisations():
            for input, eq in initial_equalisations.items():
                self.correlator.feng_eq_set(source_name=input, new_eq=eq)
        self.addCleanup(restore_initial_equalisations)

        # Set all inputs to zero, and check that output product is all-zero
        for input in input_labels:
            self.correlator.feng_eq_set(source_name=input, new_eq=0)
        test_data = self.receiver.get_clean_dump(DUMP_TIMEOUT)['xeng_raw']
        self.assertFalse(nonzero_baselines(test_data))
        #-----------------------------------
        all_inputs = sorted(set(input_labels))
        zero_inputs = set(input_labels)
        nonzero_inputs = set()

        def calc_zero_and_nonzero_baselines(nonzero_inputs):
            nonzeros = set()
            zeros = set()
            for inp_i in all_inputs:
                for inp_j in all_inputs:
                    if inp_i in nonzero_inputs and inp_j in nonzero_inputs:
                        nonzeros.add((inp_i, inp_j))
                    else:
                        zeros.add((inp_i, inp_j))
            return zeros, nonzeros

        #zero_baseline, nonzero_baseline = calc_zero_and_nonzero_baselines(nonzero_inputs)
        def print_baselines():
            print ('zeros: {}\n\nnonzeros: {}\n\nnonzero-baselines: {}\n\n '
                'zero-baselines: {}\n\n'.format(
                    sorted(zero_inputs), sorted(nonzero_inputs),
                    sorted(nonzero_baseline), sorted(zero_baseline)))
        #print_baselines()
        for inp in input_labels:
            old_eqs = initial_equalisations[inp]
            self.correlator.feng_eq_set(source_name=inp, new_eq=old_eqs)
            zero_inputs.remove(inp)
            nonzero_inputs.add(inp)