示例#1
0
 def test_bad_heap_address_bits(self):
     with pytest.raises(ValueError):
         spead2.Flavour(4, 64, 43, 0)  # Not multiple of 8
     with pytest.raises(ValueError):
         spead2.Flavour(4, 64, 0, 0)
     with pytest.raises(ValueError):
         spead2.Flavour(4, 64, 64, 0)
示例#2
0
 def test_equality(self):
     flavour1 = spead2.Flavour(4, 64, 40, 2)
     flavour1b = spead2.Flavour(4, 64, 40, 2)
     flavour2 = spead2.Flavour(4, 64, 48, 2)
     flavour3 = spead2.Flavour(4, 64, 40, 4)
     assert_true(flavour1 == flavour1b)
     assert_true(flavour1 != flavour2)
     assert_false(flavour1 != flavour1b)
     assert_false(flavour1 == flavour2)
     assert_false(flavour1 == flavour3)
示例#3
0
 def test_equality(self):
     flavour1 = spead2.Flavour(4, 64, 40, 2)
     flavour1b = spead2.Flavour(4, 64, 40, 2)
     flavour2 = spead2.Flavour(4, 64, 48, 2)
     flavour3 = spead2.Flavour(4, 64, 40, 4)
     assert flavour1 == flavour1b
     assert flavour1 != flavour2
     assert not (flavour1 != flavour1b)
     assert not (flavour1 == flavour2)
     assert not (flavour1 == flavour3)
    def _create_streams(self):
        """Construct streams, item group and item descriptions."""
        # Construct the SPEAD flavour description
        log = logging.getLogger(__name__)

        # Define the SPEAD flavour
        flavour_config = self._config.get('spead_flavour')
        flavour = spead2.Flavour(flavour_config.get('version', 4),
                                 flavour_config.get('item_pointer_bits', 64),
                                 flavour_config.get('heap_address_bits', 40),
                                 flavour_config.get('bug_compat_mask', 0))
        log.debug('Using SPEAD flavour = SPEAD-%d-%d v%d compat:%d',
                  flavour.item_pointer_bits, flavour.heap_address_bits,
                  flavour.version, flavour.bug_compat)

        # Create SPEAD streams
        streams_config = self._config.get('sender_node').get('streams')
        descriptor = get_heap_descriptor(self._frame_shape)
        streams = list()
        for i, config in enumerate(streams_config):
            log.debug('Configuring stream %d:', i)
            log.debug('  Address = %s:%d', config.get('host'),
                      config.get('port'))
            log.debug('  Threads = %d', config.get('threads', 1))
            streams.append(self._create_stream(config, flavour, descriptor))

        return streams
示例#5
0
    def __init__(self, spead_config, precision=None, oskar_settings=None):
        logger.info("Creating OSKAR interferometer")
        oskar.Interferometer.__init__(self, precision, oskar_settings)
        self._streams = []
        self._vis_pack = None
        self._write_ms = spead_config['write_ms']

        # Construct UDP streams and associated item groups.
        logger.info("Creating SPEAD2 stream config")
        stream_config = spead2.send.StreamConfig(
            spead_config['stream_config']['max_packet_size'],
            spead_config['stream_config']['rate'],
            spead_config['stream_config']['burst_size'],
            spead_config['stream_config']['max_heaps'])

        stream = spead_config['stream']
        threads = stream['threads'] if 'threads' in stream else 1
        logger.info("Creating SPEAD2 Thread pool")
        thread_pool = spead2.ThreadPool(threads=threads)
        logger.info("Creating SPEAD stream for host {} on port {}".format(
            stream['host'], stream['port']))
        udp_stream = spead2.send.TcpStream(thread_pool, stream['host'],
                                           stream['port'], stream_config)
        item_group = spead2.send.ItemGroup(
            flavour=spead2.Flavour(4, 64, 40, 0))

        # Append udp_stream and item_group to the stream list as a tuple.
        self._streams.append((udp_stream, item_group))
        self.abort = False
示例#6
0
    def _create_streams(self):
        """Construct streams, item group and item descriptions."""
        # Construct the SPEAD flavour description
        parent = 'spead_flavour'
        version = self._get_config([parent, 'version'], 4)
        item_pointer_bits = self._get_config([parent, 'item_pointer_bits'], 64)
        heap_address_bits = self._get_config([parent, 'heap_address_bits'], 40)
        bug_compat_mask = self._get_config([parent, 'bug_compat_mask'], 0)
        flavour = spead2.Flavour(version, item_pointer_bits, heap_address_bits,
                                 bug_compat_mask)

        # Construct UDP stream objects and associated heap_descriptor item
        # groups.
        streams = list()
        for i, stream in enumerate(self._config['sender_node']['streams']):
            host = stream['host']
            port = stream['port']
            threads = stream['threads'] if 'threads' in stream else 1
            stream_config = spead2.send.StreamConfig(rate=0)
            thread_pool = spead2.ThreadPool(threads=threads)
            # Blocking send
            stream = spead2.send.UdpStream(thread_pool, host, port,
                                           stream_config)
            item_group = spead2.send.ItemGroup(flavour=flavour)
            # Append stream & item group the stream list.
            streams.append((stream, item_group))

            self._log.debug('Configuring stream {}:'.format(i))
            self._log.debug('  Address = {}:{}'.format(host, port))
            self._log.debug('  Flavour = SPEAD-{}-{} v{} compat:{}'.format(
                flavour.item_pointer_bits, flavour.heap_address_bits,
                flavour.version, flavour.bug_compat))
            self._log.debug('  Threads = {}'.format(threads))

            # Add items to the item group based on the heap descriptor.
            for key, item in self._heap_descriptor.items():
                item_id = item['id']
                if isinstance(item_id, str):
                    item_id = int(item_id, 0)
                name = key
                desc = item['description']
                item_shape = item['shape'] if 'shape' in item else tuple()
                item_type = item['type'] if 'type' in item else None
                item_format = item['format'] if 'format' in item else None
                item_group.add_item(item_id,
                                    name,
                                    desc,
                                    shape=item_shape,
                                    dtype=item_type,
                                    format=item_format)
                self._log.debug('Adding item: {} {}'.format(item_id, name))
                self._log.debug('  description = {}'.format(desc))
                if item_type is not None:
                    self._log.debug('  type = {}'.format(item_type))
                if item_format is not None:
                    self._log.debug('  format = {}'.format(item_format))
                    self._log.debug('  shape = {}'.format(item_shape))

        self._streams = streams
示例#7
0
def measure_connection_once(args, rate, num_heaps, required_heaps):
    reader, writer = yield From(trollius.open_connection(args.host, args.port))

    def write(s):
        writer.write(s.encode('ascii'))

    write(json.dumps({'cmd': 'start', 'args': vars(args)}) + '\n')
    # Wait for "ready" response
    response = yield From(reader.readline())
    assert response == b'ready\n'
    if args.send_affinity is not None and len(args.send_affinity) > 0:
        spead2.ThreadPool.set_affinity(args.send_affinity[0])
        thread_pool = spead2.ThreadPool(
            1, args.send_affinity[1:] + args.send_affinity[:1])
    else:
        thread_pool = spead2.ThreadPool()
    thread_pool = spead2.ThreadPool()
    config = spead2.send.StreamConfig(max_packet_size=args.packet,
                                      burst_size=args.burst,
                                      rate=rate,
                                      max_heaps=num_heaps + 1,
                                      burst_rate_ratio=args.burst_rate_ratio)
    host = args.host
    if args.multicast is not None:
        host = args.multicast
    if 'send_ibv' in args and args.send_ibv is not None:
        stream = spead2.send.trollius.UdpIbvStream(
            thread_pool, host, args.port, config, args.send_ibv,
            args.send_buffer, 1, args.send_ibv_vector, args.send_ibv_max_poll)
    else:
        stream = spead2.send.trollius.UdpStream(thread_pool, host, args.port,
                                                config, args.send_buffer)
    item_group = spead2.send.ItemGroup(
        flavour=spead2.Flavour(4, 64, args.addr_bits, 0))
    item_group.add_item(id=None,
                        name='Test item',
                        description='A test item with arbitrary value',
                        shape=(args.heap_size, ),
                        dtype=np.uint8,
                        value=np.zeros((args.heap_size, ), dtype=np.uint8))

    start = timeit.default_timer()
    transferred = yield From(send_stream(item_group, stream, num_heaps))
    end = timeit.default_timer()
    elapsed = end - start
    actual_rate = transferred / elapsed
    # Give receiver time to catch up with any queue
    yield From(trollius.sleep(0.1))
    write(json.dumps({'cmd': 'stop'}) + '\n')
    # Read number of heaps received
    response = yield From(reader.readline())
    response = json.loads(response.decode('ascii'))
    received_heaps = response['received_heaps']
    yield From(trollius.sleep(0.5))
    yield From(writer.drain())
    writer.close()
    logging.debug("Received %d/%d heaps in %f seconds, rate %.3f Gbps",
                  received_heaps, num_heaps, elapsed, actual_rate * 8e-9)
    raise Return(received_heaps >= required_heaps, actual_rate)
示例#8
0
def main():
    """Runs the test sender."""
    stream_config = spead2.send.StreamConfig(
        max_packet_size=16356, rate=1000e6, burst_size=10, max_heaps=1)
    item_group = spead2.send.ItemGroup(flavour=spead2.Flavour(4, 64, 48, 0))

    # Add item descriptors to the heap.
    num_baselines = (512 * 513) // 2
    dtype = [('TCI', 'i1'), ('FD', 'u1'), ('VIS', '<c8', 4)]
    item_group.add_item(
        id=0x6000, name='visibility_timestamp_count', description='',
        shape=tuple(), format=None, dtype='<u4')
    item_group.add_item(
        id=0x6001, name='visibility_timestamp_fraction', description='',
        shape=tuple(), format=None, dtype='<u4')
    item_group.add_item(
        id=0x6005, name='visibility_baseline_count', description='',
        shape=tuple(), format=None, dtype='<u4')
    item_group.add_item(
        id=0x6008, name='scan_id', description='',
        shape=tuple(), format=None, dtype='<u8')
    item_group.add_item(
        id=0x600A, name='correlator_output_data', description='',
        shape=(num_baselines,), dtype=dtype)

    # Create streams and send start-of-stream message.
    streams = []
    num_streams = 2
    for i in range(num_streams):
        stream = spead2.send.UdpStream(
            thread_pool=spead2.ThreadPool(threads=1),
            hostname='127.0.0.1', port=41000 + i, config=stream_config)
        stream.send_heap(item_group.get_start())
        streams.append(stream)

    vis = numpy.zeros(shape=(num_baselines,), dtype=dtype)
    num_heaps = 200
    start_time = time.time()
    for stream in streams:
        # Update values in the heap.
        item_group['visibility_timestamp_count'].value = 1
        item_group['visibility_timestamp_fraction'].value = 0
        item_group['visibility_baseline_count'].value = num_baselines
        item_group['scan_id'].value = 100000000
        item_group['correlator_output_data'].value = vis
        # Iterate heaps.
        for i in range(num_heaps):
            # Send heap.
            stream.send_heap(item_group.get_heap(descriptors='all', data='all'))

    # Print time taken.
    duration = time.time() - start_time
    data_size = num_streams * num_heaps * (vis.nbytes / 1e6)
    print("Sent %.3f MB in %.3f sec (%.3f MB/sec)" % (
        data_size, duration, (data_size/duration)))

    # Send end-of-stream message.
    for stream in streams:
        stream.send_heap(item_group.get_end())
def _create_streams(config, log):
    """Construct streams, item group and item descriptions."""
    # Construct the SPEAD flavour description
    # Flavour(version, item_pointer_bits, heap_address_bits, bug_compat_mask)
    version = config['spead_flavour']['version']
    item_pointer_bits = config['spead_flavour']['item_pointer_bits']
    heap_address_bits = config['spead_flavour']['heap_address_bits']
    bug_compat_mask = config['spead_flavour']['bug_compat_mask']
    flavour = spead2.Flavour(version, item_pointer_bits, heap_address_bits,
                             bug_compat_mask)

    # Construct UDP stream objects and associated heap item groups.
    streams = list()
    for i, stream in enumerate(config['sender_node']['streams']):
        host = stream['host']
        port = stream['port']
        rate = stream['rate'] if 'rate' in stream else 0
        threads = stream['threads'] if 'threads' in stream else 1
        stream_config = spead2.send.StreamConfig(rate=rate)
        thread_pool = spead2.ThreadPool(threads=threads)
        stream = spead2.send.UdpStream(thread_pool, host, port, stream_config)
        item_group = spead2.send.ItemGroup(flavour=flavour)

        # Append stream & item group the stream list.
        streams.append((stream, item_group))

        log.debug('Configuring stream {}:'.format(i))
        log.debug('  Address = {}:{}'.format(host, port))
        log.debug('  Flavour = SPEAD-{}-{} v{} compat:{}'.format(
            flavour.item_pointer_bits, flavour.heap_address_bits,
            flavour.version, flavour.bug_compat))
        log.debug('  Threads = {}'.format(threads))
        log.debug('  Rate    = {}'.format(rate))

        # Add items to the item group based on the heap description.
        for j, item in enumerate(__heap__):
            item_id = item['id']
            if isinstance(item_id, str):
                item_id = int(item_id, 0)
            name = item['name']
            desc = item['description']
            item_type = item['type'] if 'type' in item else None
            item_format = item['format'] if 'format' in item else None
            shape = item['shape']
            item_group.add_item(item_id,
                                name,
                                desc,
                                shape=shape,
                                dtype=item_type,
                                format=item_format)
            log.debug('Adding item {} : {} {}'.format(j, item_id, name))
            log.debug('  description = {}'.format(desc))
            if item_type is not None:
                log.debug('  type = {}'.format(item_type))
            if item_format is not None:
                log.debug('  format = {}'.format(item_format))
            log.debug('  shape = {}'.format(shape))
    return streams
示例#10
0
def main():
    args = get_args()
    logging.basicConfig(level=getattr(logging, args.log.upper()))

    dtype = np.dtype(args.dtype)
    elements = args.heap_size // (args.items * dtype.itemsize)
    heap_size = elements * args.items * dtype.itemsize
    if heap_size != args.heap_size:
        logging.warn(
            'Heap size is not an exact multiple: using %d instead of %d',
            heap_size, args.heap_size)
    bug_compat = spead2.BUG_COMPAT_PYSPEAD_0_5_2 if args.pyspead else 0
    item_group = spead2.send.ItemGroup(descriptor_frequency=args.descriptors,
                                       flavour=spead2.Flavour(
                                           4, 64, args.addr_bits, bug_compat))
    for i in range(args.items):
        item_group.add_item(id=None,
                            name='Test item {}'.format(i),
                            description='A test item with arbitrary value',
                            shape=(elements, ),
                            dtype=dtype,
                            value=np.zeros((elements, ), dtype=dtype))
    if args.affinity is not None and len(args.affinity) > 0:
        spead2.ThreadPool.set_affinity(args.affinity[0])
        thread_pool = spead2.ThreadPool(args.threads,
                                        args.affinity[1:] + args.affinity[:1])
    else:
        thread_pool = spead2.ThreadPool(args.threads)
    config = spead2.send.StreamConfig(max_packet_size=args.packet,
                                      burst_size=args.burst,
                                      rate=args.rate * 10**9 / 8,
                                      burst_rate_ratio=args.burst_rate_ratio)
    if 'ibv' in args and args.ibv is not None:
        stream = spead2.send.trollius.UdpIbvStream(thread_pool, args.host,
                                                   args.port, config, args.ibv,
                                                   args.buffer, args.ttl or 1,
                                                   args.ibv_vector,
                                                   args.ibv_max_poll)
    elif args.ttl is not None:
        stream = spead2.send.trollius.UdpStream(thread_pool,
                                                args.host,
                                                args.port,
                                                config,
                                                args.buffer,
                                                ttl=args.ttl)
    else:
        # This is handled as a separate case, because passing TTL is only
        # valid for multicast addresses.
        stream = spead2.send.trollius.UdpStream(thread_pool, args.host,
                                                args.port, config, args.buffer)

    try:
        trollius.get_event_loop().run_until_complete(
            run(item_group, stream, args))
    except KeyboardInterrupt:
        sys.exit(1)
示例#11
0
 def __init__(self,
              item_group,
              descriptor_frequency=None,
              flavour=_spead2.Flavour()):
     self._item_group = item_group
     self._info = {}  # Maps ID to _ItemInfo
     self._descriptor_frequency = descriptor_frequency
     # Counter for calls to add_to_heap. This is independent of the
     # protocol-level heap count.
     self._descriptor_cnt = 0
     self._flavour = flavour
示例#12
0
 def __init__(self,
              item_group,
              descriptor_frequency=None,
              flavour=_spead2.Flavour()):
     # Workaround to avoid creating a self-reference when it's bundled into
     # the same class.
     self._item_group = item_group if item_group is not self else None
     self._info = {}  # Maps ID to _ItemInfo
     self._descriptor_frequency = descriptor_frequency
     # Counter for calls to add_to_heap. This is independent of the
     # protocol-level heap count.
     self._descriptor_cnt = 0
     self._flavour = flavour
示例#13
0
async def async_main():
    args = get_args()
    logging.basicConfig(level=getattr(logging, args.log.upper()))

    dtype = np.dtype(args.dtype)
    elements = args.heap_size // (args.items * dtype.itemsize)
    heap_size = elements * args.items * dtype.itemsize
    if heap_size != args.heap_size:
        logging.warn('Heap size is not an exact multiple: using %d instead of %d',
                     heap_size, args.heap_size)
    bug_compat = spead2.BUG_COMPAT_PYSPEAD_0_5_2 if args.pyspead else 0
    item_group = spead2.send.ItemGroup(
        descriptor_frequency=args.descriptors,
        flavour=spead2.Flavour(4, 64, args.addr_bits, bug_compat))
    for i in range(args.items):
        item_group.add_item(id=None, name='Test item {}'.format(i),
                            description='A test item with arbitrary value',
                            shape=(elements,), dtype=dtype,
                            value=np.zeros((elements,), dtype=dtype))
    if args.affinity is not None and len(args.affinity) > 0:
        spead2.ThreadPool.set_affinity(args.affinity[0])
        thread_pool = spead2.ThreadPool(args.threads, args.affinity[1:] + args.affinity[:1])
    else:
        thread_pool = spead2.ThreadPool(args.threads)
    config = spead2.send.StreamConfig(
        max_packet_size=args.packet,
        burst_size=args.burst,
        rate=args.rate * 10**9 / 8,
        burst_rate_ratio=args.burst_rate_ratio,
        max_heaps=args.max_heaps)
    if args.tcp:
        stream = await spead2.send.asyncio.TcpStream.connect(
            thread_pool, args.host, args.port, config, args.buffer, args.bind)
    elif 'ibv' in args and args.ibv:
        stream = spead2.send.asyncio.UdpIbvStream(
            thread_pool, args.host, args.port, config, args.bind,
            args.buffer, args.ttl or 1, args.ibv_vector, args.ibv_max_poll)
    else:
        kwargs = {}
        if args.ttl is not None:
            kwargs['ttl'] = args.ttl
        if args.bind:
            kwargs['interface_address'] = args.bind
        stream = spead2.send.asyncio.UdpStream(
            thread_pool, args.host, args.port, config, args.buffer, **kwargs)

    await run(item_group, stream, args)
示例#14
0
    def __init__(self, spead_config):
        self._config = spead_config
        self._log = logging.getLogger('sip.sender')
        self._streams = []
        self._buffer = []

        # Construct UDP streams and associated item groups.
        stream_config = spead2.send.StreamConfig(
            self._config['stream_config']['max_packet_size'],
            self._config['stream_config']['rate'],
            self._config['stream_config']['burst_size'],
            self._config['stream_config']['max_heaps'])
        for i_stream in range(self._config['num_streams']):
            host = self._config['destination_host']
            port = self._config['destination_port_start'] + i_stream
            # It's much faster to have a thread pool of one thread per stream!
            thread_pool = spead2.ThreadPool(threads=1)
            self._log.info('Creating SPEAD stream on %s:%i ...', host, port)
            udp_stream = spead2.send.asyncio.UdpStream(thread_pool, host, port,
                                                       stream_config)
            item_group = spead2.send.ItemGroup(
                flavour=spead2.Flavour(4, 64, 48, 0))
            self._streams.append((udp_stream, item_group))
示例#15
0
    def __init__(self, log, spead_config, precision=None, oskar_settings=None):
        oskar.Interferometer.__init__(self, precision, oskar_settings)
        self._log = log
        self._streams = []
        self._vis_pack = None

        # Construct UDP streams and associated item groups.
        stream_config = spead2.send.StreamConfig(
            spead_config['stream_config']['max_packet_size'],
            spead_config['stream_config']['rate'],
            spead_config['stream_config']['burst_size'],
            spead_config['stream_config']['max_heaps'])
        for stream in spead_config['streams']:
            threads = stream['threads'] if 'threads' in stream else 1
            thread_pool = spead2.ThreadPool(threads=threads)
            log.info("Creating SPEAD stream for host {} on port {} ...".format(
                stream['host'], stream['port']))
            udp_stream = spead2.send.UdpStream(thread_pool, stream['host'],
                                               stream['port'], stream_config)
            item_group = spead2.send.ItemGroup(
                flavour=spead2.Flavour(4, 64, 40, 0))

            # Append udp_stream and item_group to the stream list as a tuple.
            self._streams.append((udp_stream, item_group))
示例#16
0
 def test_nonascii_description(self):
     """Description with non-ASCII characters must fail"""
     with pytest.raises(UnicodeEncodeError):
         item = spead2.Item(0x1000, 'name', '\u0200', (), np.int32)
         item.to_raw(spead2.Flavour())
示例#17
0
文件: test_send.py 项目: zhuww/spead2
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import spead2
import spead2.send
import sys
import logging
import numpy as np

logging.basicConfig(level=logging.INFO)

thread_pool = spead2.ThreadPool()
stream = spead2.send.UdpStream(thread_pool, "127.0.0.1", 8888,
                               spead2.send.StreamConfig(rate=1e7))
del thread_pool

shape = (40, 50)
ig = spead2.send.ItemGroup(
    flavour=spead2.Flavour(4, 64, 48, spead2.BUG_COMPAT_PYSPEAD_0_5_2))
item = ig.add_item(0x1234, 'foo', 'a foo item', shape=shape, dtype=np.int32)
item.value = np.zeros(shape, np.int32)
stream.send_heap(ig.get_heap())
stream.send_heap(ig.get_end())
示例#18
0
class TestPassthroughLegacyReceive64_48(BaseTestPassthroughLegacyReceive):
    spead = spead64_48
    flavour = spead2.Flavour(4, 64, 48, spead2.BUG_COMPAT_PYSPEAD_0_5_2)
示例#19
0
def main():
    """Runs the test sender."""
    num_stations = 4
    num_heaps = 1500
    num_streams = 1
    rate = 1.0e5  # Bytes/s
    target = ('127.0.0.1' if len(sys.argv) < 2 else sys.argv[1])
    target_port = int('41000' if len(sys.argv) < 3 else sys.argv[2])
    antenna_file = ('' if len(sys.argv) < 4 else sys.argv[3])

    if (len(antenna_file) > 1):
        coords = read_coordinates(antenna_file)
        num_stations = len(coords)

    num_baselines = (num_stations * (num_stations + 1)) // 2

    print(f'no. stations      : {num_stations}')
    print(f'no. baselines     : {num_baselines}')
    print(f'no. times (heaps) : {num_heaps}')
    print(f'host              : {target}')
    print(f'port              : {target_port}')

    stream_config = spead2.send.StreamConfig(max_packet_size=16356,
                                             rate=rate,
                                             burst_size=10,
                                             max_heaps=1)
    item_group = spead2.send.ItemGroup(flavour=spead2.Flavour(4, 64, 48, 0))

    # Add item descriptors to the heap.
    dtype = [('TCI', 'i1'), ('FD', 'u1'), ('VIS', '<c8', 4)]
    item_group.add_item(id=0x6000,
                        name='visibility_timestamp_count',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6001,
                        name='visibility_timestamp_fraction',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6002,
                        name='visibility_channel_id',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6003,
                        name='visibility_channel_count',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6004,
                        name='visibility_polarisation_id',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6005,
                        name='visibility_baseline_count',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u4')
    item_group.add_item(id=0x6008,
                        name='scan_id',
                        description='',
                        shape=tuple(),
                        format=None,
                        dtype='<u8')
    item_group.add_item(id=0x600A,
                        name='correlator_output_data',
                        description='',
                        shape=(num_baselines, ),
                        dtype=dtype)

    # Create streams and send start-of-stream message.
    streams = []
    for i in range(num_streams):
        port = target_port + i
        print("Sending to {}:{}".format(target, port))
        stream = spead2.send.UdpStream(
            thread_pool=spead2.ThreadPool(threads=1),
            hostname=target,
            port=port,
            config=stream_config)
        stream.send_heap(item_group.get_start())
        streams.append(stream)

    vis = numpy.zeros(shape=(num_baselines, ), dtype=dtype)
    vis_amps = numpy.arange(num_baselines * 4, dtype='c8').reshape(
        (num_baselines, 4)) / 1000.0
    start_time = time.time()
    for stream in streams:
        # Update values in the heap.
        item_group['visibility_timestamp_count'].value = 1
        item_group['visibility_timestamp_fraction'].value = 0
        item_group['visibility_baseline_count'].value = num_baselines
        item_group['visibility_channel_id'].value = 12345
        item_group['visibility_channel_count'].value = 0
        item_group['visibility_polarisation_id'].value = 0
        item_group['scan_id'].value = 100000000
        item_group['correlator_output_data'].value = vis
        # Iterate heaps.
        for i in range(num_heaps):
            item_group['correlator_output_data'].value['VIS'] = vis_amps + i
            # Send heap.
            stream.send_heap(item_group.get_heap(descriptors='all',
                                                 data='all'))

    # Print time taken.
    duration = time.time() - start_time
    data_size = num_streams * num_heaps * (vis.nbytes / 1e6)
    print("Sent %.3f MB in %.3f sec (%.3f MB/sec)" % (data_size, duration,
                                                      (data_size / duration)))

    # Send end-of-stream message.
    for stream in streams:
        stream.send_heap(item_group.get_end())
示例#20
0
    async def _test_stream(self, end: bool, write: bool) -> None:
        n_heaps = 30  # number of heaps in time
        n_spectra = self.spectra_per_heap * n_heaps
        # Pick some heaps to drop, including an entire slice and
        # an entire channel for one stats dump
        drop = np.zeros((self.n_bengs, n_heaps), np.bool_)
        drop[:, 4] = True
        drop[2, 9] = True
        drop[7, 24] = True
        drop[10, 12:18] = True
        if not write:
            self.args.file_base = None

        # Start a receiver to get the signal display stream.
        # It needs a deep queue because we don't service it while it is
        # running.
        rx = spead2.recv.Stream(
            spead2.ThreadPool(),
            spead2.recv.StreamConfig(max_heaps=2, stop_on_stop_item=False),
            spead2.recv.RingStreamConfig(heaps=100))
        rx.add_udp_reader(self.args.stats.host,
                          self.args.stats.port,
                          interface_address='127.0.0.1')

        # Start up the server
        server = bf_ingest_server.CaptureServer(self.args, self.loop)
        filename = await server.start_capture('1122334455')
        # Send it a SPEAD stream. Use small packets to ensure that each heap is
        # split into multiple packets, to check that the data scatter works.
        config = spead2.send.StreamConfig(max_packet_size=256)
        flavour = spead2.Flavour(4, 64, 48, 0)
        ig = spead2.send.ItemGroup(flavour=flavour)
        ig.add_item(name='timestamp',
                    id=0x1600,
                    description='Timestamp',
                    shape=(),
                    format=[('u', 48)])
        ig.add_item(
            name='frequency',
            id=0x4103,
            description='The frequency channel of the data in this HEAP.',
            shape=(),
            format=[('u', 48)])
        ig.add_item(name='bf_raw',
                    id=0x5000,
                    description='Beamformer data',
                    shape=(self.channels_per_heap, self.spectra_per_heap, 2),
                    dtype=np.dtype(np.int8))
        # To guarantee in-order delivery (and hence make the test
        # reliable/reproducible), we send all the data for the channels of
        # interest through a single TCP socket. Data for channels outside the
        # subscribed range is discarded. Note that giving multiple TcpStream's
        # the same socket is dangerous because individual write() calls could
        # interleave; it's safe only because we use only blocking calls so
        # there is no concurrency between the streams.
        subscribed_streams = self.args.channels // self.channels_per_endpoint
        subscribed_bengs = self.args.channels // self.channels_per_heap
        expected_heaps = 0
        streams = []  # type: List[Optional[spead2.send.TcpStream]]
        primary_ep = self.tcp_endpoints[subscribed_streams.start]
        sock = socket.socket()
        sock.setblocking(False)
        await self.loop.sock_connect(sock, (primary_ep.host, primary_ep.port))
        for i in range(len(self.endpoints)):
            if i not in subscribed_streams:
                streams.append(None)
                continue
            stream = spead2.send.TcpStream(spead2.ThreadPool(), sock, config)
            streams.append(stream)
            stream.set_cnt_sequence(i, len(self.endpoints))
            stream.send_heap(ig.get_heap(descriptors='all'))
            stream.send_heap(ig.get_start())
            expected_heaps += 2
        sock.close()
        ts = 1234567890
        for i in range(n_heaps):
            data = np.zeros((self.n_channels, self.spectra_per_heap, 2),
                            np.int8)
            for channel in range(self.n_channels):
                data[channel, :, 0] = channel % 255 - 128
            for t in range(self.spectra_per_heap):
                data[:, t, 1] = (i * self.spectra_per_heap + t) % 255 - 128
            for j in range(self.n_bengs):
                ig['timestamp'].value = ts
                ig['frequency'].value = j * self.channels_per_heap
                ig['bf_raw'].value = data[j * self.channels_per_heap:(j + 1) *
                                          self.channels_per_heap, ...]
                if not drop[j, i]:
                    heap = ig.get_heap()
                    # The receiver looks at inline items in each packet to place
                    # data correctly.
                    heap.repeat_pointers = True
                    if j in subscribed_bengs:
                        out_stream = streams[j // (self.n_bengs //
                                                   len(self.endpoints))]
                        assert out_stream is not None
                        out_stream.send_heap(heap)
                        expected_heaps += 1
            ts += self.spectra_per_heap * self.ticks_between_spectra
        if end:
            for out_stream in streams:
                if out_stream is not None:
                    out_stream.send_heap(ig.get_end())
                    # They're all pointing at the same receiver, which will
                    # shut down after the first stop heap
                    break
        streams = []

        if not end:
            # We only want to stop the capture once all the heaps we expect
            # have been received, but time out after 5 seconds to avoid
            # hanging the test.
            for i in range(100):
                if server.counters['heaps'] >= expected_heaps:
                    break
                else:
                    print('Only {} / {} heaps received so far'.format(
                        server.counters['heaps'], expected_heaps))
                    await asyncio.sleep(0.05)
            else:
                print('Giving up waiting for heaps')
        await server.stop_capture(force=not end)

        expected_data = np.zeros((self.n_channels, n_spectra, 2), np.int8)
        expected_weight = np.ones((self.n_channels, n_spectra), np.int8)
        for channel in range(self.n_channels):
            expected_data[channel, :, 0] = channel % 255 - 128
        for t in range(n_spectra):
            expected_data[:, t, 1] = t % 255 - 128
        for i in range(self.n_bengs):
            for j in range(n_heaps):
                if drop[i, j]:
                    channel0 = i * self.channels_per_heap
                    spectrum0 = j * self.spectra_per_heap
                    index = np.s_[channel0:channel0 + self.channels_per_heap,
                                  spectrum0:spectrum0 + self.spectra_per_heap]
                    expected_data[index] = 0
                    expected_weight[index] = 0
        expected_data = expected_data[self.args.channels.asslice()]
        expected_weight = expected_weight[self.args.channels.asslice()]

        # Validate the output
        if write:
            h5file = h5py.File(filename, 'r')
            with contextlib.closing(h5file):
                bf_raw = h5file['/Data/bf_raw']
                np.testing.assert_equal(expected_data, bf_raw)

                timestamps = h5file['/Data/timestamps']
                expected = 1234567890 \
                    + self.ticks_between_spectra * np.arange(self.spectra_per_heap * n_heaps)
                np.testing.assert_equal(expected, timestamps)

                flags = h5file['/Data/flags']
                expected = np.where(drop, 8, 0).astype(np.uint8)
                expected = expected[self.args.channels.start //
                                    self.channels_per_heap:self.args.channels.
                                    stop // self.channels_per_heap]
                np.testing.assert_equal(expected, flags)

                data_set = h5file['/Data']
                assert_equal('i0_tied_array_channelised_voltage_0x',
                             data_set.attrs['stream_name'])
                assert_equal(self.args.channels.start,
                             data_set.attrs['channel_offset'])
        else:
            assert_is_none(filename)

        # Validate the signal display stream
        rx.stop()
        heaps = list(rx)
        # Note: would need updating if n_heaps is not a multiple of heaps_per_stats
        assert_equal(n_heaps // self.heaps_per_stats + 2, len(heaps))
        assert_true(heaps[0].is_start_of_stream())
        assert_true(heaps[-1].is_end_of_stream())
        ig = spead2.send.ItemGroup()
        spectrum = 0
        spectra_per_stats = self.heaps_per_stats * self.spectra_per_heap
        for rx_heap in heaps[1:-1]:
            updated = ig.update(rx_heap)
            rx_data = updated['sd_data'].value
            rx_flags = updated['sd_flags'].value
            rx_timestamp = updated['sd_timestamp'].value

            # Check types and shapes
            assert_equal((len(self.args.channels), 2, 2), rx_data.shape)
            assert_equal(np.float32, rx_data.dtype)
            assert_equal((len(self.args.channels), 2), rx_flags.shape)
            assert_equal(np.uint8, rx_flags.dtype)
            np.testing.assert_equal(0, rx_data[..., 1])  # Should be real only

            rx_power = rx_data[:, 0, 0]
            rx_saturated = rx_data[:, 1, 0]

            # Check calculations
            ts_unix = (spectrum + 0.5 * spectra_per_stats) * self.ticks_between_spectra \
                / self.adc_sample_rate + 111111111.0
            np.testing.assert_allclose(ts_unix * 100.0, rx_timestamp)

            index = np.s_[:, spectrum:spectrum + spectra_per_stats]
            frame_data = expected_data[index]
            frame_weight = expected_weight[index]
            weight_sum = np.sum(frame_weight, axis=1)
            power = np.sum(frame_data.astype(np.float64)**2,
                           axis=2)  # Sum real+imag
            saturated = (frame_data == -128) | (frame_data == 127)
            saturated = np.logical_or.reduce(saturated,
                                             axis=2)  # Combine real+imag
            saturated = saturated.astype(np.float64)
            # Average over time. Can't use np.average because it complains if
            # weights sum to zero instead of giving a NaN.
            with np.errstate(divide='ignore', invalid='ignore'):
                power = np.sum(power * frame_weight, axis=1) / weight_sum
                saturated = np.sum(saturated * frame_weight,
                                   axis=1) / weight_sum
            power = np.where(weight_sum, power, 0)
            saturated = np.where(weight_sum, saturated, 0)
            np.testing.assert_allclose(power, rx_power)
            np.testing.assert_allclose(saturated, rx_saturated)
            flags = np.where(weight_sum, 0, DATA_LOST)
            np.testing.assert_equal(flags, rx_flags[:, 0])

            spectrum += spectra_per_stats
示例#21
0
 def test_nonascii_name(self):
     """Name with non-ASCII characters must fail"""
     with assert_raises(UnicodeEncodeError):
         item = spead2.Item(0x1000, '\u0200', 'description', (), np.int32)
         item.to_raw(spead2.Flavour())
示例#22
0
 def test_attributes(self):
     flavour = spead2.Flavour(4, 64, 40, 2)
     assert_equal(4, flavour.version)
     assert_equal(64, flavour.item_pointer_bits)
     assert_equal(40, flavour.heap_address_bits)
     assert_equal(2, flavour.bug_compat)
示例#23
0
 def test_attributes(self):
     flavour = spead2.Flavour(4, 64, 40, 2)
     assert flavour.version == 4
     assert flavour.item_pointer_bits == 64
     assert flavour.heap_address_bits == 40
     assert flavour.bug_compat == 2
示例#24
0
    def __init__(self,
                 spead_config,
                 disconnect_tolerance=0,
                 mpi_comm=None,
                 ports=None):
        self._streams = []
        self._ports = []
        self.mpi_comm = mpi_comm
        self._num_stream = len(spead_config['streams'])
        self._num_stream_disconnect = 0
        self._disconnect_tolerance = disconnect_tolerance

        # Relay attributes
        self._relay_stream = None
        self._descriptor = None

        self._measurement_set = None
        self._header = {}

        self._baseline_exclude = set()
        self._baseline_map = []

        try:
            if spead_config['as_relay'] == 1:
                self.as_relay = True
            else:
                self.as_relay = False
                self.use_adios2 = spead_config.get('use_adios2', False)
                self._file_name = spead_config.get('output_ms', 'output.ms')
                try:
                    os.mkdir(os.path.dirname(self._file_name))
                except OSError:
                    pass

            if self.as_relay:
                # NOTE: Don't do baseline exclusion if its a relay  as it shares a codebase with the MS writer
                # which will exclude baselines multiple times causing array dimension mismatches.
                # So as a relay just average and pass on all baselines.

                # Construct TCP streams and associated item groups.
                stream_config = spead2.send.StreamConfig(
                    spead_config['relay']['stream_config']['max_packet_size'],
                    spead_config['relay']['stream_config']['rate'],
                    spead_config['relay']['stream_config']['burst_size'],
                    spead_config['relay']['stream_config']['max_heaps'])

                stream = spead_config['relay']['stream']
                threads = stream['threads'] if 'threads' in stream else 1
                thread_pool = spead2.ThreadPool(threads=threads)
                logger.info(
                    "Relaying visibilities to host {} on port {}".format(
                        stream['host'], stream['port']))
                tcp_stream = spead2.send.TcpStream(thread_pool, stream['host'],
                                                   stream['port'],
                                                   stream_config)

                item_group = spead2.send.ItemGroup(
                    flavour=spead2.Flavour(4, 64, 40, 0))

                # Append udp_stream and item_group to the stream list as a tuple.
                self._relay_stream = (tcp_stream, item_group)
            else:
                baseline_file = spead_config['baseline_map_filename']
                if baseline_file:
                    full_baseline_map = parse_baseline_file(baseline_file)

                    index = 0
                    for b in full_baseline_map:
                        if b[2] == 0:
                            self._baseline_map.append(b)
                        else:
                            self._baseline_exclude.add(index)
                        index += 1

                    logger.info(
                        'Baseline count: total=%d, used=%d, excluded=%d',
                        len(full_baseline_map), len(self._baseline_map),
                        len(self._baseline_exclude))

            # Ports can be given explicitly or taken from the config file
            if not ports:
                ports = (c['port'] for c in spead_config['streams'])

            for port in ports:
                logger.info('Adding TCP stream reader: port %d', port)
                try:
                    stream = spead2.recv.Stream(spead2.ThreadPool(), 0)
                    stream.stop_on_stop_item = False
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                    sock.bind(('', port))
                    sock.listen(1)
                    stream.add_tcp_reader(sock)
                    self._ports.append(port)
                    self._streams.append(stream)
                except Exception as e:
                    logger.error(
                        'Failed adding TCP stream reader: error %s port %d',
                        str(e), port)
                    raise
        except:
            self.close(graceful=False)
            raise
示例#25
0
 def test_bad_item_pointer_bits(self):
     with pytest.raises(ValueError):
         spead2.Flavour(4, 32, 24, 0)
示例#26
0
import logging
import asyncio

import numpy as np

import spead2
import spead2.send
import spead2.send.asyncio


logging.basicConfig(level=logging.INFO)

thread_pool = spead2.ThreadPool()
stream = spead2.send.asyncio.UdpStream(
    thread_pool, [("127.0.0.1", 8888)], spead2.send.StreamConfig(rate=1e7))
del thread_pool  # Make sure this doesn't crash anything

shape = (40, 50)
ig = spead2.send.ItemGroup(flavour=spead2.Flavour(4, 64, 48, 0))
item = ig.add_item(0x1234, 'foo', 'a foo item', shape=shape, dtype=np.int32)
item.value = np.zeros(shape, np.int32)
futures = [
    stream.async_send_heap(ig.get_heap()),
    stream.async_send_heap(ig.get_end())
]
# Delete things to check that there are no refcounting bugs
del ig
del stream
asyncio.get_event_loop().run_until_complete(asyncio.wait(futures))
示例#27
0
 def test_bad_version(self):
     with pytest.raises(ValueError):
         spead2.Flavour(3, 64, 40, 0)