Beispiel #1
0
def test_MantarrayMcSimulator__processes_set_stimulation_protocol_command__when_stimulation_not_running_on_any_wells(
    mantarray_mc_simulator_no_beacon,
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    test_protocol_ids = ("A", "B", "E", None)
    stim_info_dict = {
        "protocols": [
            {
                "protocol_id": protocol_id,
                "stimulation_type": choice(["C", "V"]),
                "run_until_stopped": choice([True, False]),
                "subprotocols": [
                    choice([get_random_subprotocol(), get_null_subprotocol(600)])
                    for _ in range(randint(1, 3))
                ],
            }
            for protocol_id in test_protocol_ids[:-1]
        ],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): choice(test_protocol_ids)
            for well_idx in range(24)
        },
    }

    expected_pc_timestamp = randint(0, SERIAL_COMM_MAX_TIMESTAMP_VALUE)
    set_protocols_command = create_data_packet(
        expected_pc_timestamp,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_SET_STIM_PROTOCOL_PACKET_TYPE,
        convert_stim_dict_to_bytes(stim_info_dict),
    )
    simulator.write(set_protocols_command)

    invoke_process_run_and_check_errors(simulator)
    # assert that stim info was stored
    actual = simulator.get_stim_info()
    for protocol_idx in range(len(test_protocol_ids) - 1):
        del stim_info_dict["protocols"][protocol_idx][
            "protocol_id"
        ]  # the actual protocol ID letter is not included
        assert actual["protocols"][protocol_idx] == stim_info_dict["protocols"][protocol_idx], protocol_idx
    assert actual["protocol_assignments"] == {  # indices of the protocol are used instead
        well_name: (None if protocol_id is None else test_protocol_ids.index(protocol_id))
        for well_name, protocol_id in stim_info_dict["protocol_assignments"].items()
    }
    # assert command response is correct
    stim_command_response = simulator.read(
        size=get_full_packet_size_from_packet_body_size(SERIAL_COMM_TIMESTAMP_LENGTH_BYTES + 1)
    )
    assert_serial_packet_is_expected(
        stim_command_response,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_COMMAND_RESPONSE_PACKET_TYPE,
        additional_bytes=convert_to_timestamp_bytes(expected_pc_timestamp)
        + bytes([SERIAL_COMM_COMMAND_SUCCESS_BYTE]),
    )
Beispiel #2
0
def test_MantarrayMcSimulator__processes_start_stimulation_command__after_protocols_have_been_set(
    mantarray_mc_simulator_no_beacon, mocker
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")
    # mock so no protocol status packets are sent
    mocker.patch.object(mc_simulator, "_get_us_since_subprotocol_start", autospec=True, return_value=0)

    # set single arbitrary protocol applied to wells randomly
    stim_info = simulator.get_stim_info()
    stim_info["protocols"] = [
        {
            "protocol_id": "A",
            "stimulation_type": "C",
            "run_until_stopped": True,
            "subprotocols": [get_random_subprotocol()],
        }
    ]
    stim_info["protocol_assignments"] = {
        GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): choice(["A", None])
        if well_idx
        else "A"
        for well_idx in range(24)
    }
    expected_stim_running_statuses = {
        well_name: bool(protocol_id) for well_name, protocol_id in stim_info["protocol_assignments"].items()
    }

    for response_byte_value in (
        SERIAL_COMM_COMMAND_SUCCESS_BYTE,
        SERIAL_COMM_COMMAND_FAILURE_BYTE,
    ):
        # send start stim command
        expected_pc_timestamp = randint(0, SERIAL_COMM_MAX_TIMESTAMP_VALUE)
        start_stimulation_command = create_data_packet(
            expected_pc_timestamp,
            SERIAL_COMM_MAIN_MODULE_ID,
            SERIAL_COMM_START_STIM_PACKET_TYPE,
        )
        simulator.write(start_stimulation_command)

        invoke_process_run_and_check_errors(simulator)
        # assert that stimulation was started on wells that were assigned a protocol
        assert simulator.get_stim_running_statuses() == expected_stim_running_statuses
        # assert command response is correct
        additional_bytes = convert_to_timestamp_bytes(expected_pc_timestamp) + bytes([response_byte_value])
        if not response_byte_value:
            additional_bytes += spied_global_timer.spy_return.to_bytes(8, byteorder="little")
        expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
        stim_command_response = simulator.read(size=expected_size)
        assert_serial_packet_is_expected(
            stim_command_response,
            SERIAL_COMM_MAIN_MODULE_ID,
            SERIAL_COMM_COMMAND_RESPONSE_PACKET_TYPE,
            additional_bytes=additional_bytes,
        )
Beispiel #3
0
def test_MantarrayMcSimulator__processes_set_stimulation_protocol_command__when_an_incorrect_amount_of_module_assignments_are_given(
    mantarray_mc_simulator_no_beacon, test_num_module_assignments, test_description
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    stim_info_dict = {
        "protocols": [
            {
                "protocol_id": "V",
                "stimulation_type": choice(["C", "V"]),
                "run_until_stopped": choice([True, False]),
                "subprotocols": [get_random_subprotocol()],
            }
        ],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): "V" for well_idx in range(24)
        },
    }
    stim_info_bytes = convert_stim_dict_to_bytes(stim_info_dict)
    # add or remove an assignment
    if test_num_module_assignments > 24:
        stim_info_bytes += bytes([0])
    else:
        stim_info_bytes = stim_info_bytes[:-1]

    expected_pc_timestamp = randint(0, SERIAL_COMM_MAX_TIMESTAMP_VALUE)
    set_protocols_command = create_data_packet(
        expected_pc_timestamp,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_SET_STIM_PROTOCOL_PACKET_TYPE,
        stim_info_bytes,
    )
    simulator.write(set_protocols_command)

    invoke_process_run_and_check_errors(simulator)
    # assert stim info was not updated
    assert simulator.get_stim_info() == {}
    # assert command response is correct
    stim_command_response = simulator.read(
        size=get_full_packet_size_from_packet_body_size(SERIAL_COMM_TIMESTAMP_LENGTH_BYTES + 1)
    )
    assert_serial_packet_is_expected(
        stim_command_response,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_COMMAND_RESPONSE_PACKET_TYPE,
        additional_bytes=convert_to_timestamp_bytes(expected_pc_timestamp)
        + bytes([SERIAL_COMM_COMMAND_FAILURE_BYTE]),
    )
Beispiel #4
0
def test_MantarrayProcessesMonitor__processes_set_stim_status_command(
        test_status, test_description, test_process_manager_creator,
        test_monitor):
    test_process_manager = test_process_manager_creator(
        use_testing_queues=True)
    monitor_thread, shared_values_dict, *_ = test_monitor(test_process_manager)
    server_to_main_queue = (test_process_manager.queue_container().
                            get_communication_queue_from_server_to_main())
    main_to_ic_queue = test_process_manager.queue_container(
    ).get_communication_to_instrument_comm_queue(0)

    test_well_names = ["A1", "A2", "B1"]
    test_well_indices = [
        GENERIC_24_WELL_DEFINITION.get_well_index_from_well_name(well_name)
        for well_name in test_well_names
    ]

    shared_values_dict["stimulation_running"] = [
        (not test_status if well_idx in test_well_indices else False)
        for well_idx in range(24)
    ]
    shared_values_dict["stimulation_info"] = {
        "protocols": [{
            "protocol_id": "A"
        }],
        "protocol_assignments":
        {well_name: "A"
         for well_name in test_well_names},
    }

    test_command = {
        "communication_type": "stimulation",
        "command": "set_stim_status",
        "status": test_status,
    }
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        test_command, server_to_main_queue)

    invoke_process_run_and_check_errors(monitor_thread)

    confirm_queue_is_eventually_of_size(main_to_ic_queue, 1)
    actual = main_to_ic_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    expected_command = "start_stimulation" if test_status else "stop_stimulation"
    assert actual == {
        "communication_type": "stimulation",
        "command": expected_command
    }
Beispiel #5
0
def create_random_stim_info():
    protocol_ids = (None, "A", "B", "C", "D")
    return {
        "protocols": [{
            "protocol_id":
            pid,
            "stimulation_type":
            choice(["C", "V"]),
            "run_until_stopped":
            choice([True, False]),
            "subprotocols": [
                choice([get_random_subprotocol(),
                        get_null_subprotocol(50000)])
                for _ in range(randint(1, 2))
            ],
        } for pid in protocol_ids[1:]],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            choice(protocol_ids)
            for well_idx in range(24)
        },
    }
Beispiel #6
0
def test_convert_stim_dict_to_bytes__return_expected_bytes():
    protocol_assignments_dict = {"D1": "A", "D2": "D"}
    protocol_assignments_dict.update({
        GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
        None
        for well_idx in range(24)
        if GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(
            well_idx) not in protocol_assignments_dict
    })
    expected_module_protocol_pairs = [0, 1]
    expected_module_protocol_pairs.extend([STIM_NO_PROTOCOL_ASSIGNED] * 22)

    stim_info_dict = {
        "protocols": [
            {
                "run_until_stopped":
                True,
                "protocol_id":
                "A",
                "stimulation_type":
                "C",
                "subprotocols": [
                    {
                        "phase_one_duration": randint(1, 50),
                        "phase_one_charge": randint(1, 100),
                        "interphase_interval": randint(1, 50),
                        "phase_two_duration": randint(1, 100),
                        "phase_two_charge": randint(1, 50),
                        "repeat_delay_interval": randint(0, 50),
                        "total_active_duration": randint(150, 300),
                    },
                    {
                        "phase_one_duration": 250,
                        "phase_one_charge": 0,
                        "interphase_interval": 0,
                        "phase_two_duration": 0,
                        "phase_two_charge": 0,
                        "repeat_delay_interval": 0,
                        "total_active_duration": 250,
                    },
                ],
            },
            {
                "protocol_id":
                "D",
                "stimulation_type":
                "V",
                "run_until_stopped":
                False,
                "subprotocols": [
                    {
                        "phase_one_duration": randint(1, 50),
                        "phase_one_charge": randint(1, 100),
                        "interphase_interval": randint(1, 50),
                        "phase_two_duration": randint(1, 100),
                        "phase_two_charge": randint(1, 50),
                        "repeat_delay_interval": randint(0, 50),
                        "total_active_duration": randint(150, 300),
                    },
                ],
            },
        ],
        "protocol_assignments":
        protocol_assignments_dict,
    }

    expected_bytes = bytes([2])  # num unique protocols
    # bytes for protocol A
    expected_bytes += bytes([2])  # num subprotocols in protocol A
    expected_bytes += convert_subprotocol_dict_to_bytes(
        stim_info_dict["protocols"][0]["subprotocols"][0], is_voltage=False)
    expected_bytes += convert_subprotocol_dict_to_bytes(
        stim_info_dict["protocols"][0]["subprotocols"][1], is_voltage=False)
    expected_bytes += bytes([0])  # control method
    expected_bytes += bytes([1])  # schedule mode
    expected_bytes += bytes(1)  # data type
    # bytes for protocol D
    expected_bytes += bytes([1])  # num subprotocols in protocol B
    expected_bytes += convert_subprotocol_dict_to_bytes(
        stim_info_dict["protocols"][1]["subprotocols"][0], is_voltage=True)
    expected_bytes += bytes([1])  # control method
    expected_bytes += bytes([0])  # schedule mode
    expected_bytes += bytes(1)  # data type
    # module/protocol pairs
    expected_bytes += bytes(expected_module_protocol_pairs)

    actual = convert_stim_dict_to_bytes(stim_info_dict)
    assert actual == expected_bytes
Beispiel #7
0
def test_MantarrayMcSimulator__sends_protocol_status_with_finished_status_correctly__and_stops_stim_on_the_finished_well(
    mantarray_mc_simulator_no_beacon, mocker
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")

    test_duration_ms = 63
    test_well_idx_to_stop = randint(0, 11)
    test_well_name_to_stop = GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(test_well_idx_to_stop)
    test_well_idx_to_continue = randint(12, 23)
    test_well_name_to_continue = GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(
        test_well_idx_to_continue
    )

    test_protocol_assignments = {
        GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): None for well_idx in range(24)
    }
    test_protocol_assignments[test_well_name_to_stop] = "A"
    test_protocol_assignments[test_well_name_to_continue] = "B"

    test_stim_info = create_converted_stim_info(
        {
            "protocols": [
                {
                    "protocol_id": "A",
                    "stimulation_type": "C",
                    "run_until_stopped": False,
                    "subprotocols": [
                        get_random_subprotocol(total_active_duration=test_duration_ms),
                    ],
                },
                {
                    "protocol_id": "B",
                    "stimulation_type": "C",
                    "run_until_stopped": False,
                    "subprotocols": [
                        get_random_subprotocol(total_active_duration=test_duration_ms * 2),
                    ],
                },
            ],
            "protocol_assignments": test_protocol_assignments,
        }
    )
    set_stim_info_and_start_stimulating(mantarray_mc_simulator_no_beacon, test_stim_info)

    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        side_effect=[
            test_duration_ms * int(1e3) - 1,
            test_duration_ms * int(1e3) - 1,
            test_duration_ms * int(1e3),
            test_duration_ms * int(1e3),
            test_duration_ms * int(1e3),
            test_duration_ms * int(1e3),
        ],
    )

    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting == 0
    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting > 0

    additional_bytes = (
        bytes([1])  # number of status updates in this packet
        + bytes([STIM_WELL_IDX_TO_MODULE_ID[test_well_idx_to_stop]])
        + bytes([StimStatuses.FINISHED])
        + (spied_global_timer.spy_return + test_duration_ms * int(1e3)).to_bytes(8, byteorder="little")
        + bytes([STIM_COMPLETE_SUBPROTOCOL_IDX])
    )
    expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
    stim_status_packet = simulator.read(size=expected_size)
    assert_serial_packet_is_expected(
        stim_status_packet,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_STIM_STATUS_PACKET_TYPE,
        additional_bytes=additional_bytes,
    )

    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting == 0
Beispiel #8
0
def test_MantarrayMcSimulator__sends_protocol_status_with_restarting_status_correctly(
    mantarray_mc_simulator_no_beacon, mocker
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")

    test_duration_ms = 59
    test_well_idx = randint(0, 23)

    test_stim_info = create_converted_stim_info(
        {
            "protocols": [
                {
                    "protocol_id": "A",
                    "stimulation_type": "C",
                    "run_until_stopped": True,
                    "subprotocols": [
                        get_random_subprotocol(total_active_duration=test_duration_ms),
                    ],
                }
            ],
            "protocol_assignments": {
                GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): "A"
                if well_idx == test_well_idx
                else None
                for well_idx in range(24)
            },
        }
    )
    set_stim_info_and_start_stimulating(mantarray_mc_simulator_no_beacon, test_stim_info)

    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        side_effect=[test_duration_ms * int(1e3) - 1, test_duration_ms * int(1e3), 0],
    )

    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting == 0
    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting > 0

    additional_bytes = (
        bytes([2])  # number of status updates in this packet
        + bytes([STIM_WELL_IDX_TO_MODULE_ID[test_well_idx]])
        + bytes([StimStatuses.RESTARTING])
        + (spied_global_timer.spy_return + test_duration_ms * int(1e3)).to_bytes(8, byteorder="little")
        + bytes([0])  # subprotocol idx
        + bytes([STIM_WELL_IDX_TO_MODULE_ID[test_well_idx]])
        + bytes([StimStatuses.ACTIVE])
        + (spied_global_timer.spy_return + test_duration_ms * int(1e3)).to_bytes(8, byteorder="little")
        + bytes([0])  # subprotocol idx
    )
    expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
    stim_status_packet = simulator.read(size=expected_size)
    assert_serial_packet_is_expected(
        stim_status_packet,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_STIM_STATUS_PACKET_TYPE,
        additional_bytes=additional_bytes,
    )
Beispiel #9
0
def test_MantarrayMcSimulator__sends_multiple_protocol_status_packets_if_subprotocol_updates_occur_for_two_wells_with_different_protocols(
    mantarray_mc_simulator_no_beacon, mocker
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")

    test_duration_ms_1 = 650
    test_duration_ms_2 = 670
    test_well_idxs = (4, 8)

    protocol_id_iter = iter(["A", "B"])
    test_stim_info = create_converted_stim_info(
        {
            "protocols": [
                {
                    "protocol_id": "A",
                    "stimulation_type": "C",
                    "run_until_stopped": True,
                    "subprotocols": [
                        get_random_subprotocol(total_active_duration=test_duration_ms_1),
                        get_random_subprotocol(),
                    ],
                },
                {
                    "protocol_id": "B",
                    "stimulation_type": "C",
                    "run_until_stopped": True,
                    "subprotocols": [
                        get_random_subprotocol(total_active_duration=test_duration_ms_2),
                        get_random_subprotocol(),
                    ],
                },
            ],
            "protocol_assignments": {
                GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): (
                    next(protocol_id_iter) if well_idx in test_well_idxs else None
                )
                for well_idx in range(24)
            },
        }
    )
    set_stim_info_and_start_stimulating(mantarray_mc_simulator_no_beacon, test_stim_info)

    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        side_effect=[
            test_duration_ms_1 * int(1e3) - 1,
            test_duration_ms_2 * int(1e3) - 1,
            test_duration_ms_1 * int(1e3),
            test_duration_ms_2 * int(1e3),
            0,
        ],
    )

    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting == 0
    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting > 0

    status_bytes_1 = (
        bytes([StimStatuses.ACTIVE])
        + (spied_global_timer.spy_return + test_duration_ms_1 * int(1e3)).to_bytes(8, byteorder="little")
        + bytes([1])  # subprotocol idx
    )
    status_bytes_2 = (
        bytes([StimStatuses.ACTIVE])
        + (spied_global_timer.spy_return + test_duration_ms_2 * int(1e3)).to_bytes(8, byteorder="little")
        + bytes([1])  # subprotocol idx
    )
    additional_bytes = (
        bytes([2])  # number of status updates in this packet
        + bytes([STIM_WELL_IDX_TO_MODULE_ID[test_well_idxs[0]]])
        + status_bytes_1
        + bytes([STIM_WELL_IDX_TO_MODULE_ID[test_well_idxs[1]]])
        + status_bytes_2
    )
    expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
    stim_status_packet = simulator.read(size=expected_size)
    assert_serial_packet_is_expected(
        stim_status_packet,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_STIM_STATUS_PACKET_TYPE,
        additional_bytes=additional_bytes,
    )
Beispiel #10
0
def test_McCommunicationProcess__handles_stimulation_status_comm_from_instrument__data_stream_begins_in_middle_of_protocol(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, to_main_queue, to_fw_queue = four_board_mc_comm_process_no_handshake[
        "board_queues"][0]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)
    set_magnetometer_config(four_board_mc_comm_process_no_handshake, simulator)

    total_active_duration_ms = 76
    test_well_indices = [randint(0, 11), randint(12, 23)]
    expected_stim_info = {
        "protocols": [{
            "protocol_id":
            "A",
            "stimulation_type":
            "V",
            "run_until_stopped":
            False,
            "subprotocols": [
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms),
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms),
            ],
        }],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            ("A" if well_idx in test_well_indices else None)
            for well_idx in range(24)
        },
    }
    # send command to mc_process
    set_protocols_command = {
        "communication_type": "stimulation",
        "command": "set_protocols",
        "stim_info": expected_stim_info,
    }
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        set_protocols_command, input_queue)
    # set protocols and process response
    invoke_process_run_and_check_errors(mc_process)
    invoke_process_run_and_check_errors(simulator)
    invoke_process_run_and_check_errors(mc_process)
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    # mock so no data packets are produced
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_last_data_packet",
        autospec=True,
        return_value=0,
    )
    # mock so one status update is produced
    mocked_get_us_subprotocol = mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        return_value=total_active_duration_ms * int(1e3),
    )
    spied_global_timer = mocker.spy(simulator, "_get_global_timer")

    # send start stimulation command
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and initial stimulator status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response only
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting > 0
    # remove message to main
    confirm_queue_is_eventually_of_size(to_main_queue, 1)
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    # process initial stim packet and make sure it was not sent to file writer
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting == 0
    confirm_queue_is_eventually_empty(to_fw_queue)

    expected_global_time_stim_start = spied_global_timer.spy_return

    # start data streaming
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        dict(START_MANAGED_ACQUISITION_COMMUNICATION), input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # send stimulator status packet after initial subprotocol completes
    mocked_get_us_subprotocol.return_value = total_active_duration_ms * int(
        1e3)
    invoke_process_run_and_check_errors(simulator)
    invoke_process_run_and_check_errors(mc_process)
    # process stim statuses and start data streaming command response
    invoke_process_run_and_check_errors(mc_process)

    expected_global_time_data_start = spied_global_timer.spy_return

    # check status packet sent to file writer
    confirm_queue_is_eventually_of_size(to_fw_queue, 2)
    expected_well_statuses = (
        [
            [
                expected_global_time_stim_start +
                total_active_duration_ms * int(1e3) -
                expected_global_time_data_start
            ],
            [1],
        ],
        [
            [
                expected_global_time_stim_start +
                (total_active_duration_ms * int(1e3) * 2) -
                expected_global_time_data_start
            ],
            [STIM_COMPLETE_SUBPROTOCOL_IDX],
        ],
    )
    for i, expected_well_status in enumerate(expected_well_statuses):
        msg_to_fw = to_fw_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
        assert msg_to_fw["data_type"] == "stimulation", i
        assert msg_to_fw["is_first_packet_of_stream"] is (i == 0), i
        assert set(
            msg_to_fw["well_statuses"].keys()) == set(test_well_indices), i
        np.testing.assert_array_equal(
            msg_to_fw["well_statuses"][test_well_indices[0]],
            expected_well_status,
            err_msg=f"Packet {i}")
        np.testing.assert_array_equal(
            msg_to_fw["well_statuses"][test_well_indices[1]],
            expected_well_status,
            err_msg=f"Packet {i}")
Beispiel #11
0
def test_MantarrayMcSimulator__sends_protocol_status_packet_for_initial_subprotocol_on_each_well_when_stim_starts(
    mantarray_mc_simulator_no_beacon, mocker
):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    testing_queue = mantarray_mc_simulator_no_beacon["testing_queue"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        side_effect=[0, 1, 0],
    )

    test_well_idxs = (0, 5, 9)
    test_stim_info = create_converted_stim_info(
        {
            "protocols": [
                {
                    "protocol_id": "A",
                    "stimulation_type": "C",
                    "run_until_stopped": True,
                    "subprotocols": [get_random_subprotocol(), get_random_subprotocol()],
                }
            ],
            "protocol_assignments": {
                GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): (
                    "A" if well_idx in test_well_idxs else None
                )
                for well_idx in range(24)
            },
        }
    )

    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {"command": "set_stim_info", "stim_info": test_stim_info}, testing_queue
    )
    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting == 0

    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {"command": "set_stim_status", "status": True}, testing_queue
    )
    invoke_process_run_and_check_errors(simulator)
    assert simulator.in_waiting > 0

    num_status_updates = len(test_well_idxs)
    additional_bytes = bytes([num_status_updates])
    for well_idx in test_well_idxs:
        additional_bytes += (
            bytes([STIM_WELL_IDX_TO_MODULE_ID[well_idx]])
            + bytes([StimStatuses.ACTIVE])
            + (spied_global_timer.spy_return).to_bytes(8, byteorder="little")
            + bytes([0])  # subprotocol idx
        )
    expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
    stim_status_packet = simulator.read(size=expected_size)
    assert_serial_packet_is_expected(
        stim_status_packet,
        SERIAL_COMM_MAIN_MODULE_ID,
        SERIAL_COMM_STIM_STATUS_PACKET_TYPE,
        additional_bytes=additional_bytes,
    )
Beispiel #12
0
def test_MantarrayMcSimulator__processes_stop_stimulation_command(mantarray_mc_simulator_no_beacon, mocker):
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")

    # set single arbitrary protocol applied to wells randomly
    stim_info = simulator.get_stim_info()
    stim_info["protocols"] = [
        {
            "protocol_id": "B",
            "stimulation_type": "V",
            "run_until_stopped": True,
            "subprotocols": [get_random_subprotocol()],
        }
    ]
    stim_info["protocol_assignments"] = {
        GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): choice(["B", None])
        if well_idx
        else "B"
        for well_idx in range(24)
    }
    initial_stim_running_statuses = {
        well_name: bool(protocol_id) for well_name, protocol_id in stim_info["protocol_assignments"].items()
    }
    simulator.get_stim_running_statuses().update(initial_stim_running_statuses)

    for response_byte_value in (
        SERIAL_COMM_COMMAND_SUCCESS_BYTE,
        SERIAL_COMM_COMMAND_FAILURE_BYTE,
    ):
        # send start stim command
        expected_pc_timestamp = randint(0, SERIAL_COMM_MAX_TIMESTAMP_VALUE)
        stop_stimulation_command = create_data_packet(
            expected_pc_timestamp,
            SERIAL_COMM_MAIN_MODULE_ID,
            SERIAL_COMM_STOP_STIM_PACKET_TYPE,
        )
        simulator.write(stop_stimulation_command)
        invoke_process_run_and_check_errors(simulator)

        # make sure finished status updates are sent if command succeeded
        if response_byte_value == SERIAL_COMM_COMMAND_SUCCESS_BYTE:
            status_update_bytes = bytes([sum(initial_stim_running_statuses.values())])
            for well_name in simulator.get_stim_running_statuses().keys():
                if not initial_stim_running_statuses[well_name]:
                    continue
                well_idx = GENERIC_24_WELL_DEFINITION.get_well_index_from_well_name(well_name)
                status_update_bytes += (
                    bytes([STIM_WELL_IDX_TO_MODULE_ID[well_idx]])
                    + bytes([StimStatuses.FINISHED])
                    + (spied_global_timer.spy_return).to_bytes(8, byteorder="little")
                    + bytes([STIM_COMPLETE_SUBPROTOCOL_IDX])
                )
            expected_size = get_full_packet_size_from_packet_body_size(len(status_update_bytes))
            stim_command_response = simulator.read(size=expected_size)
            assert_serial_packet_is_expected(
                stim_command_response,
                SERIAL_COMM_MAIN_MODULE_ID,
                SERIAL_COMM_STIM_STATUS_PACKET_TYPE,
                additional_bytes=status_update_bytes,
            )
        # assert that stimulation was stopped on all wells
        assert simulator.get_stim_running_statuses() == {
            convert_module_id_to_well_name(module_id): False for module_id in range(1, 25)
        }
        # assert command response is correct
        additional_bytes = convert_to_timestamp_bytes(expected_pc_timestamp) + bytes([response_byte_value])
        expected_size = get_full_packet_size_from_packet_body_size(len(additional_bytes))
        stim_command_response = simulator.read(size=expected_size)
        assert_serial_packet_is_expected(
            stim_command_response,
            SERIAL_COMM_MAIN_MODULE_ID,
            SERIAL_COMM_COMMAND_RESPONSE_PACKET_TYPE,
            additional_bytes=additional_bytes,
        )
Beispiel #13
0
def test_McCommunicationProcess__handles_stimulation_status_comm_from_instrument__stim_completing_before_data_stream_starts(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, to_main_queue, to_fw_queue = four_board_mc_comm_process_no_handshake[
        "board_queues"][0]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    total_active_duration_ms = 74
    test_well_indices = [randint(0, 11), randint(12, 23)]
    expected_stim_info = {
        "protocols": [{
            "protocol_id":
            "A",
            "stimulation_type":
            "C",
            "run_until_stopped":
            False,
            "subprotocols": [
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms)
            ],
        }],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            ("A" if well_idx in test_well_indices else None)
            for well_idx in range(24)
        },
    }
    # send command to mc_process
    set_protocols_command = {
        "communication_type": "stimulation",
        "command": "set_protocols",
        "stim_info": expected_stim_info,
    }
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        set_protocols_command, input_queue)
    # set protocols and process response
    invoke_process_run_and_check_errors(mc_process)
    invoke_process_run_and_check_errors(simulator)
    invoke_process_run_and_check_errors(mc_process)
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    # mock so protocol will complete in first iteration
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        return_value=total_active_duration_ms * int(1e3),
    )
    invoke_process_run_and_check_errors(simulator)

    # send start stimulation command
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and initial stimulator status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response only
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting > 0
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    # process both stim packet and make sure it was not sent to file writer
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting == 0
    confirm_queue_is_eventually_empty(to_fw_queue)

    # confirm stimulation complete message sent to main
    confirm_queue_is_eventually_of_size(to_main_queue, 1)
    msg_to_main = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert msg_to_main["communication_type"] == "stimulation"
    assert msg_to_main["command"] == "status_update"
    assert set(msg_to_main["wells_done_stimulating"]) == set(test_well_indices)

    # mock so no data packets are sent
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_last_data_packet",
        autospec=True,
        return_value=0,
    )
    # start data streaming
    set_magnetometer_config_and_start_streaming(
        four_board_mc_comm_process_no_handshake, simulator)
    # check no status packets sent to file writer
    confirm_queue_is_eventually_empty(to_fw_queue)
Beispiel #14
0
def test_McCommunicationProcess__processes_set_protocols_command(
    four_board_mc_comm_process_no_handshake,
    mantarray_mc_simulator_no_beacon,
):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    board_queues = four_board_mc_comm_process_no_handshake["board_queues"]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]
    input_queue = board_queues[0][0]
    output_queue = board_queues[0][1]
    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake, mantarray_mc_simulator_no_beacon
    )
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    # confirm preconditions
    assert simulator.get_stim_info() == {}

    expected_protocol_ids = (None, "A", "B", "C")
    test_num_wells = 24
    expected_stim_info = {
        "protocols": [
            {
                "protocol_id": protocol_id,
                "stimulation_type": choice(["V", "C"]),
                "run_until_stopped": choice([False, True]),
                "subprotocols": [
                    choice([get_random_subprotocol(), get_null_subprotocol(500)]) for _ in range(2)
                ],
            }
            for protocol_id in expected_protocol_ids[1:]
        ],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx): choice(expected_protocol_ids)
            for well_idx in range(test_num_wells)
        },
    }
    # send command to mc_process
    expected_response = {
        "communication_type": "stimulation",
        "command": "set_protocols",
        "stim_info": expected_stim_info,
    }
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        copy.deepcopy(expected_response), input_queue
    )
    # run mc_process to send command
    invoke_process_run_and_check_errors(mc_process)
    # run simulator to process command and send response
    invoke_process_run_and_check_errors(simulator)
    # assert that protocols were updated
    actual = simulator.get_stim_info()
    for protocol_idx in range(len(expected_protocol_ids) - 1):
        expected_protocol_copy = copy.deepcopy(expected_stim_info["protocols"][protocol_idx])
        del expected_protocol_copy["protocol_id"]  # the actual protocol ID letter is not included
        assert actual["protocols"][protocol_idx] == expected_protocol_copy, protocol_idx
    assert actual["protocol_assignments"] == {  # indices of the protocol are used instead
        well_name: (None if protocol_id is None else expected_protocol_ids.index(protocol_id) - 1)
        for well_name, protocol_id in expected_stim_info["protocol_assignments"].items()
    }
    # run mc_process to process command response and send message back to main
    invoke_process_run_and_check_errors(mc_process)
    # confirm correct message sent to main
    confirm_queue_is_eventually_of_size(output_queue, 1)
    message_to_main = output_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert message_to_main == expected_response
Beispiel #15
0
def test_McCommunicationProcess__stim_packets_sent_to_file_writer_after_restarting_data_stream(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, to_main_queue, to_fw_queue = four_board_mc_comm_process_no_handshake[
        "board_queues"][0]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    total_active_duration_ms = 1100
    test_well_idx = randint(0, 23)
    test_stim_info = {
        "protocols": [{
            "protocol_id":
            "A",
            "stimulation_type":
            "C",
            "run_until_stopped":
            True,
            "subprotocols": [
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms)
            ],
        }],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            ("A" if well_idx == test_well_idx else None)
            for well_idx in range(24)
        },
    }
    set_stimulation_protocols(four_board_mc_comm_process_no_handshake,
                              simulator, test_stim_info)

    # mock so status update will be sent each iteration
    mocked_us_since_subprotocol_start = mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        return_value=total_active_duration_ms * int(1e3),
    )

    # send start stimulation command
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and both stim status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response and both stim packets
    invoke_process_run_and_check_errors(mc_process, num_iterations=2)
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    # mock so no data packets are sent
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_last_data_packet",
        autospec=True,
        return_value=0,
    )
    # update this value so no stim statuses sent while starting data stream
    mocked_us_since_subprotocol_start.return_value = 0

    # start data streaming
    set_magnetometer_config_and_start_streaming(
        four_board_mc_comm_process_no_handshake, simulator)
    # confirm most recent packet sent to file writer
    confirm_queue_is_eventually_of_size(to_fw_queue, 1)
    to_fw_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    # stop data streaming
    stop_data_stream(four_board_mc_comm_process_no_handshake, simulator)

    # run simulator and make sure no packets are sent to file writer
    mocked_us_since_subprotocol_start.return_value = total_active_duration_ms * int(
        1e3)
    invoke_process_run_and_check_errors(simulator)
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting == 0
    confirm_queue_is_eventually_empty(to_fw_queue)

    # update this value so no stim statuses sent while starting data stream
    mocked_us_since_subprotocol_start.return_value = 0
    # restart data stream
    start_data_stream(four_board_mc_comm_process_no_handshake, simulator)
    # confirm most recent packet sent to file writer and marked as first stim packet of the stream
    confirm_queue_is_eventually_of_size(to_fw_queue, 1)
    actual = to_fw_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert actual["is_first_packet_of_stream"] is True
Beispiel #16
0
def test_McCommunicationProcess__protocols_can_be_updated_and_stimulation_can_be_restarted_after_initial_run_completes(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, to_main_queue, _ = four_board_mc_comm_process_no_handshake[
        "board_queues"][0]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    total_active_duration_ms = 1400
    test_well_indices = [randint(0, 11), randint(12, 23)]
    test_stim_info = {
        "protocols": [{
            "protocol_id":
            "A",
            "stimulation_type":
            "C",
            "run_until_stopped":
            False,
            "subprotocols": [
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms)
            ],
        }],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            ("A" if well_idx in test_well_indices else None)
            for well_idx in range(24)
        },
    }
    set_stimulation_protocols(four_board_mc_comm_process_no_handshake,
                              simulator, test_stim_info)

    # mock so protocol will complete in first iteration
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        return_value=total_active_duration_ms * int(1e3),
    )

    # send start stimulation command
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and both stim status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response and both stim packets
    invoke_process_run_and_check_errors(mc_process, num_iterations=2)
    assert simulator.in_waiting == 0
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    # confirm stimulation complete message sent to main
    confirm_queue_is_eventually_of_size(to_main_queue, 1)
    msg_to_main = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert set(msg_to_main["wells_done_stimulating"]) == set(test_well_indices)

    # update protocols
    set_stimulation_protocols(four_board_mc_comm_process_no_handshake,
                              simulator, create_random_stim_info())
    # restart stimulation
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and both stim status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response and both stim packets
    invoke_process_run_and_check_errors(mc_process)
    # confirm start stim response send to main

    start_stim_response = to_main_queue.get(
        timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert start_stim_response["communication_type"] == "stimulation"
    assert start_stim_response["command"] == "start_stimulation"
Beispiel #17
0
def test_McCommunicationProcess__handles_stimulation_status_comm_from_instrument__stim_starting_while_data_is_streaming(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, to_main_queue, to_fw_queue = four_board_mc_comm_process_no_handshake[
        "board_queues"][0]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)

    total_active_duration_ms = 74
    test_well_indices = [randint(0, 11), randint(12, 23)]
    expected_stim_info = {
        "protocols": [{
            "protocol_id":
            "A",
            "stimulation_type":
            "C",
            "run_until_stopped":
            False,
            "subprotocols": [
                get_random_subprotocol(
                    total_active_duration=total_active_duration_ms)
            ],
        }],
        "protocol_assignments": {
            GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
            ("A" if well_idx in test_well_indices else None)
            for well_idx in range(24)
        },
    }
    # send command to mc_process
    set_protocols_command = {
        "communication_type": "stimulation",
        "command": "set_protocols",
        "stim_info": expected_stim_info,
    }
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        set_protocols_command, input_queue)
    # set protocols and process response
    invoke_process_run_and_check_errors(mc_process)
    invoke_process_run_and_check_errors(simulator)
    invoke_process_run_and_check_errors(mc_process)
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    spied_global_timer = mocker.spy(simulator, "_get_global_timer")
    # mock so full second of data is sent
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_last_data_packet",
        autospec=True,
        return_value=MICRO_TO_BASE_CONVERSION,
    )
    # start data streaming
    set_magnetometer_config_and_start_streaming(
        four_board_mc_comm_process_no_handshake, simulator)
    # check no status packets sent to file writer
    confirm_queue_is_eventually_empty(to_fw_queue)

    expected_global_time_data_start = spied_global_timer.spy_return

    # mock so protocol will complete in first iteration
    mocker.patch.object(
        mc_simulator,
        "_get_us_since_subprotocol_start",
        autospec=True,
        return_value=total_active_duration_ms * int(1e3),
    )

    # send start stimulation command
    put_object_into_queue_and_raise_error_if_eventually_still_empty(
        {
            "communication_type": "stimulation",
            "command": "start_stimulation"
        }, input_queue)
    invoke_process_run_and_check_errors(mc_process)
    # process command, send back response and both stim status packet
    invoke_process_run_and_check_errors(simulator)
    # process command response and both stim packets
    invoke_process_run_and_check_errors(mc_process)
    assert simulator.in_waiting == 0
    # remove message to main
    to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)

    expected_global_time_stim_start = spied_global_timer.spy_return

    # confirm stimulation complete message sent to main
    confirm_queue_is_eventually_of_size(to_main_queue, 1)
    msg_to_main = to_main_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
    assert msg_to_main["communication_type"] == "stimulation"
    assert msg_to_main["command"] == "status_update"
    assert set(msg_to_main["wells_done_stimulating"]) == set(test_well_indices)

    # check status packet sent to file writer
    stim_status_msg = drain_queue(to_fw_queue)[-1]
    assert stim_status_msg["data_type"] == "stimulation"
    assert stim_status_msg["is_first_packet_of_stream"] is True
    assert set(
        stim_status_msg["well_statuses"].keys()) == set(test_well_indices)
    expected_well_statuses = [
        [
            expected_global_time_stim_start - expected_global_time_data_start,
            expected_global_time_stim_start +
            total_active_duration_ms * int(1e3) -
            expected_global_time_data_start,
        ],
        [0, STIM_COMPLETE_SUBPROTOCOL_IDX],
    ]
    np.testing.assert_array_equal(
        stim_status_msg["well_statuses"][test_well_indices[0]],
        expected_well_statuses)
    np.testing.assert_array_equal(
        stim_status_msg["well_statuses"][test_well_indices[1]],
        expected_well_statuses)
Beispiel #18
0
        "C",
        "subprotocols": [
            {
                "phase_one_duration": 10000,
                "phase_one_charge": 50000,
                "interphase_interval": 10000,
                "phase_two_duration": 10000,
                "phase_two_charge": -50000,
                "repeat_delay_interval": 50000,
                "total_active_duration": 5000,
            },
            # get_null_subprotocol(1000),  # type: ignore
        ],
    }],
    "protocol_assignments": {
        GENERIC_24_WELL_DEFINITION.get_well_name_from_well_index(well_idx):
        ("A" if well_idx in (0, 3, 20, 23) else None)
        for well_idx in range(24)
    },
}
RANDOM_STIM_INFO_2 = create_random_stim_info()  # type: ignore

COMMAND_RESPONSE_SEQUENCE = [
    ("change_magnetometer_config_1", "magnetometer_config_1"),
    ("get_metadata", "get_metadata"),
    # MAGNETOMETERS
    ("start_managed_acquisition", "start_md_1"),
    ("start_managed_acquisition", "start_md_2"),
    ("stop_managed_acquisition", "stop_md_1"),
    ("stop_managed_acquisition", "stop_md_2"),
    ("change_magnetometer_config_2", "magnetometer_config_2"),
Beispiel #19
0
def test_McCommunicationProcess__processes_start_and_stop_stimulation_commands__when_commands_are_successful(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon, mocker):
    mc_process = four_board_mc_comm_process_no_handshake["mc_process"]
    input_queue, output_queue = four_board_mc_comm_process_no_handshake[
        "board_queues"][0][:2]
    simulator = mantarray_mc_simulator_no_beacon["simulator"]

    set_connection_and_register_simulator(
        four_board_mc_comm_process_no_handshake,
        mantarray_mc_simulator_no_beacon)
    set_simulator_idle_ready(mantarray_mc_simulator_no_beacon)
    expected_stim_info = create_random_stim_info()
    set_stimulation_protocols(four_board_mc_comm_process_no_handshake,
                              simulator, expected_stim_info)
    expected_stim_running_statuses = (
        {
            well_name: bool(protocol_id)
            for well_name, protocol_id in
            expected_stim_info["protocol_assignments"].items()
        },
        {
            well_name: False
            for well_name in expected_stim_info["protocol_assignments"].keys()
        },
    )

    spied_reset_stim_buffers = mocker.spy(mc_process,
                                          "_reset_stim_status_buffers")

    for command, stim_running_statuses in (
        ("start_stimulation", expected_stim_running_statuses[0]),
        ("stop_stimulation", expected_stim_running_statuses[1]),
    ):
        # send command to mc_process
        expected_response = {
            "communication_type": "stimulation",
            "command": command
        }
        put_object_into_queue_and_raise_error_if_eventually_still_empty(
            copy.deepcopy(expected_response), input_queue)
        # run mc_process to send command
        invoke_process_run_and_check_errors(mc_process)
        # run simulator to process command and send response
        invoke_process_run_and_check_errors(simulator)
        # assert that stim statuses were updated correctly
        assert simulator.get_stim_running_statuses() == stim_running_statuses
        # run mc_process to process command response and send message back to main
        invoke_process_run_and_check_errors(mc_process)
        # confirm correct message sent to main
        expected_size = 1 if command == "start_stimulation" else 2
        confirm_queue_is_eventually_of_size(output_queue, expected_size)
        message_to_main = output_queue.get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
        if command == "start_stimulation":
            spied_reset_stim_buffers.assert_not_called()
            expected_response["timestamp"] = datetime.datetime(
                year=2021,
                month=10,
                day=24,
                hour=13,
                minute=7,
                second=23,
                microsecond=173814)
        else:
            spied_reset_stim_buffers.assert_called_once()
            # also check that stim complete message was sent to main
            stim_status_update_msg = output_queue.get(
                timeout=QUEUE_CHECK_TIMEOUT_SECONDS)
            assert stim_status_update_msg[
                "communication_type"] == "stimulation"
            assert stim_status_update_msg["command"] == "status_update"
            assert set(
                stim_status_update_msg["wells_done_stimulating"]) == set(
                    GENERIC_24_WELL_DEFINITION.get_well_index_from_well_name(
                        well_name) for well_name, stim_running_status in
                    expected_stim_running_statuses[0].items()
                    if stim_running_status)
        assert message_to_main == expected_response