def test_data_transfer(self):
        master = MockRingBufferMaster()
        master.create_buffer()

        jf_test_det = DetectorDefinition(
            detector_name="0.5 JF",
            detector_model=JUNGFRAU,
            geometry=[1, 1],
            bit_depth=16
        )

        writer = MockRingBufferClient(
            process_id=1,
            follower_ids=[],
            detector_def=jf_test_det,
            as_reader=False,
            use_assembly_buffer=True
        )

        writer.init_buffer()

        receiver = MockRingBufferClient(
            process_id=2,
            follower_ids=[1],
            detector_def=jf_test_det,
            use_assembly_buffer=True
        )

        receiver.init_buffer()

        writer_current_slot = rb.claim_next_slot(writer.rb_consumer_id)
        self.assertNotEqual(writer_current_slot, -1, "The writer should be able to get the slot.")

        receiver_current_slot = rb.claim_next_slot(receiver.rb_consumer_id)
        self.assertEqual(receiver_current_slot, -1, "The reader should not be able to get the slot yet.")

        sent_raw_data = numpy.random.randint(low=0, high=128,
                                             size=jf_test_det.raw_image_data_n_bytes, dtype="uint16")
        raw_write_pointer = rb.get_buffer_slot(writer.rb_raw_dbuffer_id, writer_current_slot)
        ctypes.memmove(raw_write_pointer, sent_raw_data.ctypes.data, sent_raw_data.nbytes)

        sent_assembled_data = numpy.random.randint(low=0, high=128,
                                                   size=jf_test_det.image_data_n_bytes, dtype="uint16")
        assembled_write_pointer = rb.get_buffer_slot(writer.rb_assembled_dbuffer_id, writer_current_slot)
        ctypes.memmove(assembled_write_pointer, sent_assembled_data.ctypes.data, sent_assembled_data.nbytes)

        rb.commit_slot(writer.rb_consumer_id, writer_current_slot)

        receiver_current_slot = rb.claim_next_slot(receiver.rb_consumer_id)
        self.assertEqual(receiver_current_slot, writer_current_slot, "Slot should be ready for the receiver.")

        raw_receive_pointer = rb.get_buffer_slot(receiver.rb_raw_dbuffer_id, receiver_current_slot)
        raw_received_data = get_frame_data(raw_receive_pointer, [jf_test_det.raw_image_data_n_bytes])
        numpy.testing.assert_array_equal(sent_raw_data, raw_received_data)

        assembled_receive_pointer = rb.get_buffer_slot(receiver.rb_assembled_dbuffer_id, receiver_current_slot)
        assembled_received_data = get_frame_data(assembled_receive_pointer, [jf_test_det.image_data_n_bytes])
        numpy.testing.assert_array_equal(sent_assembled_data, assembled_received_data)
def start_rb_assembler(name, detector_def: DetectorDefinition,
                       ringbuffer: MpiRingBufferClient, assembler_index,
                       n_total_assemblers):

    _logger.info("Starting assembler with name='%s'." % name)

    ringbuffer.init_buffer()

    control_client = MpiControlClient()

    mpi_ref_time = time()

    image_assembler = ImageAssembler(det_assembler=detector_def,
                                     assembler_index=assembler_index,
                                     n_total_assemblers=n_total_assemblers)

    # Function signature:
    # char* source_root, char* destination_root, size_t* dest_move_offsets, uint32_t n_moves, size_t n_bytes_per_move
    assemble_image = get_image_assembler_function()

    dest_move_offsets = image_assembler.move_offsets
    n_moves = image_assembler.n_moves
    n_bytes_per_move = image_assembler.n_bytes_per_move

    while True:

        if (time() - mpi_ref_time) > MPI_COMM_DELAY:

            # TODO: Currently the only message is a reset message.
            if control_client.is_message_ready():
                control_client.get_message()
                ringbuffer.reset()
                _logger.info("[%s] Ringbuffer reset." % name)

            mpi_ref_time = time()

        rb_current_slot = rb.claim_next_slot(ringbuffer.rb_consumer_id)
        if rb_current_slot == -1:
            sleep(config.RB_RETRY_DELAY)
            continue

        raw_data_pointer = rb.get_buffer_slot(ringbuffer.rb_raw_dbuffer_id,
                                              rb_current_slot)
        assembled_data_pointer = rb.get_buffer_slot(
            ringbuffer.rb_assembled_dbuffer_id, rb_current_slot)

        assemble_image(raw_data_pointer, assembled_data_pointer,
                       dest_move_offsets, n_moves, n_bytes_per_move)

        if not rb.commit_slot(ringbuffer.rb_consumer_id, rb_current_slot):
            error_message = "[%s] Cannot commit rb slot %d." % (
                name, rb_current_slot)
            _logger.error(error_message)

            raise RuntimeError(error_message)
def start_h5_writer(name, detector_def: DetectorDefinition,
                    ringbuffer: MpiRingBufferClient):

    _logger.info("Starting h5 writer with name='%s'" % name)

    ringbuffer.init_buffer()

    writer = H5Writer(detector_def)
    control_client = MpiControlClient()

    mpi_ref_time = time()

    while True:

        if (time() - mpi_ref_time) > MPI_COMM_DELAY:

            # TODO: Currently the only message is a reset message.
            if control_client.is_message_ready():
                control_client.get_message()

                writer.close()
                writer = H5Writer(detector_def)

                _logger.info("[%s] Ringbuffer reset." % name)

            mpi_ref_time = time()

        rb_current_slot = rb.claim_next_slot(ringbuffer.rb_consumer_id)
        if rb_current_slot == -1:
            sleep(config.RB_RETRY_DELAY)
            continue

        metadata, data = read_data_from_rb(
            rb_current_slot=rb_current_slot,
            rb_hbuffer_id=ringbuffer.rb_hbuffer_id,
            rb_dbuffer_id=ringbuffer.rb_consumer_id,
            n_submodules=detector_def.n_submodules_total,
            image_size=detector_def.detector_size)

        writer.write_image(data.tobytes())
        writer.write_metadata(metadata)

        if not rb.commit_slot(ringbuffer.rb_consumer_id, rb_current_slot):
            error_message = "[%s] Cannot commit rb slot %d." % (
                name, rb_current_slot)
            _logger.error(error_message)

            raise RuntimeError(error_message)
Example #4
0
def start_writer_sender(name, bind_url, zmq_mode,
                        detector_def: DetectorDefinition,
                        ringbuffer: MpiRingBufferClient):
    _logger.info(
        "Starting sender with name='%s', bind_url='%s', zmq_mode='%s'" %
        (name, bind_url, zmq_mode))

    ringbuffer.init_buffer()

    context = zmq.Context(io_threads=ZMQ_IO_THREADS)
    socket = context.socket(zmq.__getattribute__(zmq_mode))
    socket.bind(bind_url)

    zmq_sender = DetectorZMQSender(name, socket, ringbuffer, detector_def)
    control_client = MpiControlClient()

    mpi_ref_time = time()

    while True:

        if (time() - mpi_ref_time) > MPI_COMM_DELAY:

            # TODO: Currently the only message is a reset message.
            if control_client.is_message_ready():
                control_client.get_message()
                ringbuffer.reset()
                zmq_sender.reset()
                _logger.info("[%s] Ringbuffer reset." % name)

            mpi_ref_time = time()

        rb_current_slot = rb.claim_next_slot(ringbuffer.rb_consumer_id)
        if rb_current_slot == -1:
            sleep(config.RB_RETRY_DELAY)
            continue

        metadata, data = zmq_sender.read_data(rb_current_slot)

        zmq_sender.send_data(metadata, data)

        if not rb.commit_slot(ringbuffer.rb_consumer_id, rb_current_slot):
            error_message = "[%s] Cannot commit rb slot %d." % (
                name, rb_current_slot)
            _logger.error(error_message)

            raise RuntimeError(error_message)
def test_prefilled_buffer(n_buffer_slots, rb_folder,
                          detector: DetectorDefinition, n_slots_to_fill):

    create_rb_files(n_buffer_slots,
                    detector.image_header_n_bytes,
                    detector.image_data_n_bytes,
                    rb_folder=rb_folder)

    rb_master = MockRingBufferMaster(rb_folder=rb_folder)
    rb_master.create_buffer()

    rb_client_writer = MockRingBufferClient(process_id=0,
                                            follower_ids=[],
                                            detector_def=detector,
                                            as_reader=False,
                                            rb_folder=rb_folder)

    rb_client_reader = MockRingBufferClient(process_id=1,
                                            follower_ids=[0],
                                            detector_def=detector,
                                            as_reader=True,
                                            rb_folder=rb_folder)

    rb_client_writer.init_buffer()
    rb_client_reader.init_buffer()

    for i_slot in range(n_slots_to_fill):

        rb_current_slot = rb.claim_next_slot(rb_client_writer.rb_consumer_id)
        if rb_current_slot == -1:
            raise RuntimeError(
                "Cannot get next slot from ringbuffer. Are the RB files available?"
            )

        if not rb.commit_slot(rb_client_writer.rb_consumer_id,
                              rb_current_slot):
            raise RuntimeError("Cannot commit rb slot %d." % rb_current_slot)
    def test_multi_module_placement(self):
        udp_ip = "127.0.0.1"
        udp_port = [12001, 12002, 12003, 12004]
        bit_depth = 16
        udp_receiver_ranks = [0, 1, 2, 3]
        n_frames = 10

        test_eiger = DetectorDefinition(detector_name="Test Eiger 0.5M",
                                        detector_model=EIGER,
                                        geometry=[1, 1],
                                        bit_depth=bit_depth)

        test_control_client = MockControlClient()

        ringbuffer_master = MockRingBufferMaster()
        ringbuffer_master.create_buffer()

        ringbuffer_client = MockRingBufferClient(
            process_id=4,
            follower_ids=udp_receiver_ranks,
            detector_def=test_eiger,
            as_reader=True)
        ringbuffer_client.init_buffer()

        def start_receiver(process_id, process_udp_port):
            ringbuffer_client_udp = MockRingBufferClient(
                process_id=process_id,
                follower_ids=[4],
                detector_def=test_eiger,
                as_reader=False)

            ringbuffer_client.init_buffer()

            start_udp_receiver(udp_ip=udp_ip,
                               udp_port=process_udp_port,
                               detector_def=test_eiger,
                               submodule_index=process_id,
                               ringbuffer=ringbuffer_client_udp,
                               control_client=test_control_client)

        self.receive_process.append(
            Process(target=start_receiver, args=(0, udp_port[0])))
        self.receive_process[-1].start()

        self.receive_process.append(
            Process(target=start_receiver, args=(1, udp_port[1])))
        self.receive_process[-1].start()

        self.receive_process.append(
            Process(target=start_receiver, args=(2, udp_port[2])))
        self.receive_process[-1].start()

        self.receive_process.append(
            Process(target=start_receiver, args=(3, udp_port[3])))
        self.receive_process[-1].start()

        rb_current_slot = rb.claim_next_slot(ringbuffer_client.rb_consumer_id)
        self.assertEqual(rb_current_slot, -1,
                         "You should not be able to get this RB slice yet.")

        sleep(0.2)

        # Receiver 0
        generate_udp_stream(udp_ip,
                            udp_port[0],
                            message_generator=generate_submodule_eiger_packets(
                                bit_depth, n_frames, 0))

        rb_current_slot = rb.claim_next_slot(ringbuffer_client.rb_consumer_id)
        self.assertEqual(rb_current_slot, -1,
                         "You should not be able to get this RB slice yet.")

        # Receiver 1
        generate_udp_stream(udp_ip,
                            udp_port[1],
                            message_generator=generate_submodule_eiger_packets(
                                bit_depth, n_frames, 1))

        rb_current_slot = rb.claim_next_slot(ringbuffer_client.rb_consumer_id)
        self.assertEqual(rb_current_slot, -1,
                         "You should not be able to get this RB slice yet.")

        # Receiver 2
        generate_udp_stream(udp_ip,
                            udp_port[2],
                            message_generator=generate_submodule_eiger_packets(
                                bit_depth, n_frames, 2))

        rb_current_slot = rb.claim_next_slot(ringbuffer_client.rb_consumer_id)
        self.assertEqual(rb_current_slot, -1,
                         "You should not be able to get this RB slice yet.")

        # Receiver 3
        generate_udp_stream(udp_ip,
                            udp_port[3],
                            message_generator=generate_submodule_eiger_packets(
                                bit_depth, n_frames, 3))

        sleep(0.2)

        rb_current_slot = rb.claim_next_slot(ringbuffer_client.rb_consumer_id)
        self.assertNotEqual(rb_current_slot, -1,
                            "No frames found in ringbuffer.")

        self.assertListEqual(list(rb.get_header_info(0).committed_slots[:2]),
                             [n_frames, n_frames])

        for i in range(n_frames):
            self.assertEqual(i, rb_current_slot)

            metadata_pointer = rb.get_buffer_slot(
                ringbuffer_client.rb_hbuffer_id, rb_current_slot)
            metadata = get_frame_metadata(metadata_pointer, len(udp_port))

            self.assertListEqual(metadata["framenums"],
                                 [i + 1] * len(udp_port))
            self.assertListEqual(metadata["missing_packets_1"],
                                 [0] * len(udp_port))
            self.assertListEqual(metadata["missing_packets_2"],
                                 [0] * len(udp_port))
            self.assertListEqual(metadata["pulse_ids"], [0] * len(udp_port))
            self.assertListEqual(metadata["daq_recs"], [0] * len(udp_port))
            self.assertListEqual(metadata["module_number"],
                                 list(range(len(udp_port))))
            self.assertListEqual(metadata["module_enabled"],
                                 [1] * len(udp_port))
            self.assertEqual(metadata["frame"], i + 1)
            self.assertEqual(metadata["daq_rec"], 0)
            self.assertEqual(metadata["pulse_id"], 0)
            self.assertEqual(metadata["is_good_frame"], 1)
            self.assertListEqual(metadata["pulse_id_diff"],
                                 [0] * len(udp_port))
            self.assertListEqual(metadata["framenum_diff"],
                                 [0] * len(udp_port))

            data_pointer = rb.get_buffer_slot(
                ringbuffer_client.rb_raw_dbuffer_id, rb_current_slot)

            data_shape = [test_eiger.n_submodules_total
                          ] + test_eiger.detector_model.submodule_size
            data = get_frame_data(data_pointer, data_shape)

            n_lines_per_packet = get_n_lines_per_packet(test_eiger)
            n_packets_per_frame = get_n_packets_per_frame(test_eiger)

            for submodule_index in range(test_eiger.n_submodules_total):
                for packet_index in range(n_packets_per_frame):
                    packet_line_offset = n_lines_per_packet * packet_index
                    submodule_data = data[submodule_index][
                        packet_line_offset:packet_line_offset +
                        n_lines_per_packet]

                    submodule_indexes = submodule_data // 1000
                    self.assertEqual(submodule_indexes.min(), submodule_index)
                    self.assertEqual(submodule_indexes.max(), submodule_index)

                    packet_indexes = (submodule_data % 1000) // 10
                    self.assertEqual(packet_indexes.min(), packet_index)
                    self.assertEqual(packet_indexes.max(), packet_index)

                    frame_indexes = submodule_data % 10
                    self.assertEqual(frame_indexes.min(), i)
                    self.assertEqual(frame_indexes.max(), i)

            self.assertTrue(
                rb.commit_slot(ringbuffer_client.rb_consumer_id,
                               rb_current_slot))
            rb_current_slot = rb.claim_next_slot(
                ringbuffer_client.rb_consumer_id)

        self.assertEqual(-1,
                         rb.claim_next_slot(ringbuffer_client.rb_consumer_id))