def test_DataAnalyzerProcess__processes_change_magnetometer_config_command( four_board_analyzer_process_beta_2_mode, ): da_process = four_board_analyzer_process_beta_2_mode["da_process"] from_main_queue = four_board_analyzer_process_beta_2_mode[ "from_main_queue"] test_num_wells = 24 expected_wells = [5, 6, 15, 16] test_config_dict = create_magnetometer_config_dict(test_num_wells) for well_idx in expected_wells: module_id = SERIAL_COMM_WELL_IDX_TO_MODULE_ID[well_idx] test_config_dict[module_id][3] = True expected_sampling_period = 15000 set_sampling_period_command = { "communication_type": "acquisition_manager", "command": "change_magnetometer_config", "magnetometer_config": test_config_dict, "sampling_period": expected_sampling_period, } put_object_into_queue_and_raise_error_if_eventually_still_empty( set_sampling_period_command, from_main_queue) invoke_process_run_and_check_errors(da_process) assert da_process.get_active_wells() == expected_wells expected_buffer_size = MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS * int( 1e6 / expected_sampling_period) assert da_process.get_buffer_size() == expected_buffer_size
def test_get_active_wells_from_config__returns_correct_values(): test_num_wells = 24 default_config_dict = create_magnetometer_config_dict(test_num_wells) assert get_active_wells_from_config(default_config_dict) == [] expected_wells = [0, 8, 9, 17] test_config_dict = copy.deepcopy(default_config_dict) for well_idx in expected_wells: module_id = SERIAL_COMM_WELL_IDX_TO_MODULE_ID[well_idx] test_config_dict[module_id][0] = True assert get_active_wells_from_config(test_config_dict) == expected_wells
def create_random_config() -> Dict[int, Dict[int, bool]]: random_config_dict: Dict[int, Dict[int, bool]] = create_magnetometer_config_dict(24) num_channels = 0 for module_dict in random_config_dict.values(): for cid in module_dict.keys(): enabled = random_bool() num_channels += int(enabled) module_dict[cid] = enabled # make sure at least one channel is on if num_channels == 0: random_config_dict[1][0] = True return random_config_dict
def test_McCommunicationProcess__processes_change_magnetometer_config_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) test_num_wells = 24 # set arbitrary configuration and sampling period expected_magnetometer_config = create_magnetometer_config_dict(test_num_wells) for key in expected_magnetometer_config[9].keys(): expected_magnetometer_config[9][key] = True expected_sampling_period = 14000 # send command to mc_process expected_response = { "communication_type": "acquisition_manager", "command": "change_magnetometer_config", "magnetometer_config": expected_magnetometer_config, "sampling_period": expected_sampling_period, } 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 sampling period and configuration were updated assert simulator.get_sampling_period_us() == expected_sampling_period assert simulator.get_magnetometer_config() == expected_magnetometer_config # 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
def test_MantarrayMcSimulator__class_attributes(): assert MantarrayMcSimulator.default_mantarray_nickname == "Mantarray Sim" assert MantarrayMcSimulator.default_mantarray_serial_number == "MA2022001000" assert MantarrayMcSimulator.default_main_firmware_version == "0.0.0" assert MantarrayMcSimulator.default_channel_firmware_version == "0.0.0" assert MantarrayMcSimulator.default_barcode == "ML2022001000" assert MantarrayMcSimulator.default_metadata_values == { BOOT_FLAGS_UUID: 0b00000000, MANTARRAY_SERIAL_NUMBER_UUID: MantarrayMcSimulator.default_mantarray_serial_number, MANTARRAY_NICKNAME_UUID: MantarrayMcSimulator.default_mantarray_nickname, MAIN_FIRMWARE_VERSION_UUID: MantarrayMcSimulator.default_main_firmware_version, CHANNEL_FIRMWARE_VERSION_UUID: MantarrayMcSimulator.default_channel_firmware_version, } assert MantarrayMcSimulator.default_24_well_magnetometer_config == create_magnetometer_config_dict( 24) assert MantarrayMcSimulator.global_timer_offset_secs == 2.5
def test_create_magnetometer_config_bytes__returns_correct_values_for_every_module_id( ): test_num_wells = 24 test_dict = create_magnetometer_config_dict(test_num_wells) # arbitrarily change values for key in test_dict[1].keys(): test_dict[1][key] = True test_dict[2] = convert_bitmask_to_config_dict(0b111000100) # create expected bit-masks expected_uint16_bitmasks = [0b111111111, 0b111000100] expected_uint16_bitmasks.extend([0 for _ in range(test_num_wells - 2)]) # test actual bytes actual = create_magnetometer_config_bytes(test_dict) for module_id in range(1, test_num_wells + 1): start_idx = (module_id - 1) * 3 assert actual[ start_idx] == module_id, f"Incorrect module_id at idx: {module_id}" bitmask_bytes = expected_uint16_bitmasks[module_id - 1].to_bytes( 2, byteorder="little") assert (actual[start_idx + 1:start_idx + 3] == bitmask_bytes ), f"Incorrect bitmask bytes for module_id: {module_id}"
def test_MantarrayProcessesMonitor__passes_magnetometer_config_dict_from_server_to_mc_comm_and__data_analyzer( test_process_manager_creator, test_monitor): test_process_manager = test_process_manager_creator( use_testing_queues=True) monitor_thread, *_ = 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) main_to_da_queue = (test_process_manager.queue_container(). get_communication_queue_from_main_to_data_analyzer()) test_num_wells = 24 expected_sampling_period = 10000 expected_config_dict = { "magnetometer_config": create_magnetometer_config_dict(test_num_wells), "sampling_period": expected_sampling_period, } test_dict_from_server = { "communication_type": "set_magnetometer_config", "magnetometer_config_dict": expected_config_dict, } put_object_into_queue_and_raise_error_if_eventually_still_empty( test_dict_from_server, server_to_main_queue) invoke_process_run_and_check_errors(monitor_thread) confirm_queue_is_eventually_of_size(main_to_ic_queue, 1) confirm_queue_is_eventually_of_size(main_to_da_queue, 1) expected_comm = { "communication_type": "acquisition_manager", "command": "change_magnetometer_config", } expected_comm.update(expected_config_dict) assert main_to_ic_queue.get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) == expected_comm assert main_to_da_queue.get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) == expected_comm
def test_DataAnalyzerProcess__data_analysis_stream_is_reconfigured_in_beta_2_mode_upon_receiving_change_magnetometer_config_command( four_board_analyzer_process_beta_2_mode, mantarray_mc_simulator, mocker): da_process = four_board_analyzer_process_beta_2_mode["da_process"] da_process.init_streams() # mock so waveform data doesn't populate outgoing data queue mocker.patch.object(da_process, "_dump_data_into_queue", autospec=True) mocker.patch.object(da_process, "_create_outgoing_beta_2_data", autospec=True) mocker.patch.object(da_process, "_handle_performance_logging", autospec=True) expected_sampling_period_us = 12000 set_magnetometer_config( four_board_analyzer_process_beta_2_mode, { "magnetometer_config": GENERIC_BOARD_MAGNETOMETER_CONFIGURATION, "sampling_period": expected_sampling_period_us, }, ) da_process = four_board_analyzer_process_beta_2_mode["da_process"] board_queues = four_board_analyzer_process_beta_2_mode["board_queues"] from_main_queue = four_board_analyzer_process_beta_2_mode[ "from_main_queue"] # make sure data analyzer knows that managed acquisition is running put_object_into_queue_and_raise_error_if_eventually_still_empty( START_MANAGED_ACQUISITION_COMMUNICATION, from_main_queue) single_second_of_data = mantarray_mc_simulator[ "simulator"].get_interpolated_data(expected_sampling_period_us) test_y_data = single_second_of_data.tolist( ) * MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS test_x_data = np.arange(0, expected_sampling_period_us * len(test_y_data), expected_sampling_period_us, dtype=np.uint64) # send first round of data through will all wells enabled test_packet_1 = copy.deepcopy(SIMPLE_BETA_2_CONSTRUCT_DATA_FROM_ALL_WELLS) test_packet_1["time_indices"] = test_x_data for well_idx in range(24): # Tanner (7/14/21): time offsets are currently unused in data analyzer so not modifying them here first_channel = list(test_packet_1[well_idx].keys())[1] test_packet_1[well_idx][first_channel] = np.array(test_y_data, dtype=np.uint16) put_object_into_queue_and_raise_error_if_eventually_still_empty( test_packet_1, board_queues[0][0]) invoke_process_run_and_check_errors(da_process) confirm_queue_is_eventually_of_size(board_queues[0][1], 1) # check all analyzable twitches are reported for each well outgoing_msg = board_queues[0][1].get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) outgoing_metrics = json.loads(outgoing_msg["data_json"]) for well_idx in range(24): actual_well_metric_dict = outgoing_metrics[str(well_idx)] assert list(actual_well_metric_dict.keys()) == [ str(AMPLITUDE_UUID), str(TWITCH_FREQUENCY_UUID) ] for metric_id, metric_list in actual_well_metric_dict.items(): assert (len(metric_list) == MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS - 2), f"Well: {well_idx}, Metric ID: {metric_id}" # change magnetometer config so that only wells 20-23 are enabled test_config = create_magnetometer_config_dict(24) for well_idx in range(20, 24): module_id = SERIAL_COMM_WELL_IDX_TO_MODULE_ID[well_idx] # enable arbitrary channel test_config[module_id][2] = True set_magnetometer_config( four_board_analyzer_process_beta_2_mode, { "magnetometer_config": test_config, "sampling_period": expected_sampling_period_us }, ) # send second round of data through will only some wells enabled test_packet_2 = copy.deepcopy(SIMPLE_BETA_2_CONSTRUCT_DATA_FROM_ALL_WELLS) test_packet_2["time_indices"] = test_x_data for well_idx in range(24): # Tanner (7/14/21): time offsets are currently unused in data analyzer so not modifying them here first_channel = list(test_packet_2[well_idx].keys())[1] test_packet_2[well_idx][first_channel] = np.array(test_y_data, dtype=np.uint16) put_object_into_queue_and_raise_error_if_eventually_still_empty( test_packet_2, board_queues[0][0]) invoke_process_run_and_check_errors(da_process) confirm_queue_is_eventually_of_size(board_queues[0][1], 1) # check all analyzable twitches are reported only for enabled wells outgoing_msg = board_queues[0][1].get(timeout=QUEUE_CHECK_TIMEOUT_SECONDS) outgoing_metrics = json.loads(outgoing_msg["data_json"]) for well_idx in range(24): if well_idx < 20: assert str(well_idx) not in outgoing_metrics, well_idx continue actual_well_metric_dict = outgoing_metrics[str(well_idx)] assert list(actual_well_metric_dict.keys()) == [ str(AMPLITUDE_UUID), str(TWITCH_FREQUENCY_UUID) ] for metric_id, metric_list in actual_well_metric_dict.items(): assert (len(metric_list) == MIN_NUM_SECONDS_NEEDED_FOR_ANALYSIS - 2), f"Well: {well_idx}, Metric ID: {metric_id}"