From 462eaeed7e9aab284e8477d52c0ec7b78998987a Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Mon, 24 Nov 2025 16:44:07 -0600 Subject: [PATCH 01/12] configure all CHAN_FOR_ALL_LINES tasks to use MSB instead of LSB --- tests/component/_digital_utils.py | 12 +++--- tests/component/conftest.py | 32 +++++++-------- .../test_digital_multi_channel_reader.py | 28 ++++++------- .../test_digital_single_channel_reader.py | 37 ++++++++++------- .../test_digital_multi_channel_writer.py | 11 +++-- .../test_digital_single_channel_writer.py | 9 +---- .../task/test_task_read_waveform_di.py | 40 +++++++++++-------- .../task/test_task_write_waveform_do.py | 19 ++++----- 8 files changed, 95 insertions(+), 93 deletions(-) diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index 80be6526f..d1c105d53 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -119,9 +119,9 @@ def _get_digital_port_data_sample_major(task: nidaqmx.Task, num_samples: int) -> return numpy.transpose(result).tolist() -def _bool_array_to_int(bool_array: numpy.typing.NDArray[numpy.bool_]) -> int: +def _bool_array_to_int_lsb(bool_array: numpy.typing.NDArray[numpy.bool_]) -> int: result = 0 - # Simulated data is little-endian + # Interpret data as little-endian for bit in bool_array[::-1]: result = (result << 1) | int(bit) return result @@ -129,7 +129,7 @@ def _bool_array_to_int(bool_array: numpy.typing.NDArray[numpy.bool_]) -> int: def _bool_array_to_int_msb(bool_array: numpy.typing.NDArray[numpy.bool_]) -> int: result = 0 - # Data from ports is big-endian (see AB#3178052) + # Interpret data as big-endian for bit in bool_array: result = (result << 1) | int(bit) return result @@ -144,12 +144,12 @@ def _int_to_bool_array(num_lines: int, input: int) -> numpy.typing.NDArray[numpy def _get_waveform_data(waveform: DigitalWaveform[Any]) -> list[int]: assert isinstance(waveform, DigitalWaveform) - return [_bool_array_to_int(sample) for sample in waveform.data] + return [_bool_array_to_int_msb(sample) for sample in waveform.data] -def _get_waveform_data_msb(waveform: DigitalWaveform[Any]) -> list[int]: +def _get_waveform_bitstrings(waveform: DigitalWaveform[Any]) -> list[str]: assert isinstance(waveform, DigitalWaveform) - return [_bool_array_to_int_msb(sample) for sample in waveform.data] + return ["".join("1" if bit else "0" for bit in sample) for sample in waveform.data] def _create_digital_waveform_uint8( diff --git a/tests/component/conftest.py b/tests/component/conftest.py index 9cfd5225c..fab954b3b 100644 --- a/tests/component/conftest.py +++ b/tests/component/conftest.py @@ -156,7 +156,7 @@ def di_single_channel_multi_line_task( ) -> nidaqmx.Task: """Configure a single-channel multi-line digital input task.""" task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[:8]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) return task @@ -192,7 +192,7 @@ def di_single_chan_lines_and_port_task( """Configure a single-channel multi-line digital input task.""" task.di_channels.add_di_chan( flatten_channel_string( - sim_6363_device.di_lines.channel_names[0:3] + [sim_6363_device.di_ports[1].name] + sim_6363_device.di_lines.channel_names[0:3][::-1] + [sim_6363_device.di_ports[1].name] ), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) @@ -231,15 +231,15 @@ def di_multi_chan_diff_lines_timing_task( This task has three channels made up of different numbers of lines. """ task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.timing.cfg_samp_clk_timing( @@ -257,15 +257,15 @@ def di_multi_chan_lines_and_port_task( This task has three channels made up of lines and one channel made up of a port. """ task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( @@ -575,7 +575,7 @@ def do_single_channel_multi_line_task( """Configure a single-channel DO task.""" task = generate_task() chan = task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[:8]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, num_chans=chan.do_num_lines) @@ -589,7 +589,7 @@ def do_single_channel_multi_line_task_with_timing( """Configure a single-channel multi-line DO task with timing for waveform testing.""" task = generate_task() task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_multiplexed_device.do_lines.channel_names[:8]), + flatten_channel_string(real_x_series_multiplexed_device.do_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.timing.cfg_samp_clk_timing( @@ -635,15 +635,15 @@ def do_multi_channel_mixed_line_task( """Configure a multi-channel DO task with a mix of lines.""" task = generate_task() task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[2:5]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[2:5][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[0:2]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[0:2][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[5:8]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[5:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, num_chans=task.number_of_channels) @@ -713,7 +713,7 @@ def do_multi_channel_port_and_lines_task( line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[:8]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, is_port=True, num_chans=task.number_of_channels) @@ -741,7 +741,7 @@ def di_multi_line_loopback_task( """Configure a multi-line DI loopback task.""" task = generate_task() task.di_channels.add_di_chan( - flatten_channel_string(real_x_series_device.di_lines.channel_names[:8]), + flatten_channel_string(real_x_series_device.di_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_di_task(task) @@ -861,7 +861,7 @@ def di_multi_channel_port_and_lines_loopback_task( line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(real_x_series_device.di_lines.channel_names[:8]), + flatten_channel_string(real_x_series_device.di_lines.channel_names[:8][::-1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_di_task(task) diff --git a/tests/component/stream_readers/test_digital_multi_channel_reader.py b/tests/component/stream_readers/test_digital_multi_channel_reader.py index 186674321..5b90a8e72 100644 --- a/tests/component/stream_readers/test_digital_multi_channel_reader.py +++ b/tests/component/stream_readers/test_digital_multi_channel_reader.py @@ -23,7 +23,7 @@ from nidaqmx.stream_readers import DaqError, DigitalMultiChannelReader from nidaqmx.utils import flatten_channel_string from tests.component._digital_utils import ( - _bool_array_to_int, + _bool_array_to_int_lsb, _get_expected_data_for_line, _get_digital_data, _get_expected_digital_port_data_port_major, @@ -45,7 +45,7 @@ def test___digital_multi_channel_reader___read_one_sample_one_line___returns_val data = [_read_and_copy(reader.read_one_sample_one_line, sample) for _ in range(samples_to_read)] - assert [_bool_array_to_int(sample) for sample in data] == _get_digital_data( + assert [_bool_array_to_int_lsb(sample) for sample in data] == _get_digital_data( num_lines, samples_to_read ) @@ -75,7 +75,7 @@ def test___digital_multi_channel_reader___read_one_sample_multi_line___returns_v _read_and_copy(reader.read_one_sample_multi_line, sample) for _ in range(samples_to_read) ] - assert [_bool_array_to_int(sample[:, 0]) for sample in data] == _get_digital_data( + assert [_bool_array_to_int_lsb(sample[:, 0]) for sample in data] == _get_digital_data( num_channels, samples_to_read ) @@ -93,7 +93,7 @@ def test___digital_multi_channel_reader___read_one_sample_multi_line_jagged___re ] assert [ - [_bool_array_to_int(sample[chan, :]) for chan in range(num_channels)] for sample in data + [_bool_array_to_int_lsb(sample[chan, :]) for chan in range(num_channels)] for sample in data ] == _get_expected_digital_port_data_sample_major( di_multi_channel_port_uint32_task, samples_to_read ) @@ -387,8 +387,8 @@ def test___digital_multi_channel_different_lines_reader___read_waveforms___retur assert waveforms[1].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, ] assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) @@ -396,10 +396,10 @@ def test___digital_multi_channel_different_lines_reader___read_waveforms___retur assert waveforms[2].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[3].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[5].name, sim_6363_device.di_lines[6].name, + sim_6363_device.di_lines[5].name, + sim_6363_device.di_lines[4].name, + sim_6363_device.di_lines[3].name, ] @@ -437,22 +437,20 @@ def test___digital_multi_channel_lines_and_port_reader___read_waveforms___return assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, ] assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[3].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[5].name, sim_6363_device.di_lines[6].name, + sim_6363_device.di_lines[5].name, + sim_6363_device.di_lines[4].name, + sim_6363_device.di_lines[3].name, ] - # Note, the data on the port's waveform is MSB instead of LSB because of bug AB#3178052 - # When that bug is fixed, these asserts should be updated - assert _get_waveform_data(waveforms[3]) == [0, 128, 64, 192, 32, 160, 96, 224, 16, 144] + assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert _is_timestamp_close_to_now(waveforms[3].timing.timestamp) assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name diff --git a/tests/component/stream_readers/test_digital_single_channel_reader.py b/tests/component/stream_readers/test_digital_single_channel_reader.py index 1a01b5609..d740bd0cb 100644 --- a/tests/component/stream_readers/test_digital_single_channel_reader.py +++ b/tests/component/stream_readers/test_digital_single_channel_reader.py @@ -13,9 +13,9 @@ import nidaqmx.system from nidaqmx._feature_toggles import WAVEFORM_SUPPORT, FeatureNotSupportedError from nidaqmx.constants import ( + READ_ALL_AVAILABLE, AcquisitionType, LineGrouping, - READ_ALL_AVAILABLE, ReallocationPolicy, WaveformAttributeMode, ) @@ -23,12 +23,12 @@ from nidaqmx.stream_readers import DaqError, DigitalSingleChannelReader from nidaqmx.utils import flatten_channel_string from tests.component._digital_utils import ( - _bool_array_to_int, + _bool_array_to_int_msb, _get_digital_data, _get_expected_data_for_line, _get_num_di_lines_in_task, + _get_waveform_bitstrings, _get_waveform_data, - _get_waveform_data_msb, _read_and_copy, ) from tests.component._utils import _is_timestamp_close_to_now @@ -58,7 +58,7 @@ def test___digital_single_channel_reader___read_one_sample_multi_line___returns_ _read_and_copy(reader.read_one_sample_multi_line, sample) for _ in range(samples_to_read) ] - assert [_bool_array_to_int(sample) for sample in data] == _get_digital_data( + assert [_bool_array_to_int_msb(sample) for sample in data] == _get_digital_data( num_lines, samples_to_read ) @@ -352,7 +352,7 @@ def _make_single_channel_multi_line_reader(lines_start, rate): task = generate_task() task.di_channels.add_di_chan( flatten_channel_string( - sim_6363_device.di_lines.channel_names[lines_start : lines_start + 4] + sim_6363_device.di_lines.channel_names[lines_start : lines_start + 4][::-1] ), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) @@ -369,13 +369,13 @@ def _make_single_channel_multi_line_reader(lines_start, rate): timestamp0 = waveform.timing.timestamp assert _get_waveform_data(waveform) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) - assert waveform.channel_name == f"{sim_6363_device.di_lines[0].name}..." + assert waveform.channel_name == f"{sim_6363_device.di_lines[3].name}..." reader1.read_waveform(waveform, sample_count) timestamp1 = waveform.timing.timestamp assert _get_waveform_data(waveform) == [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) - assert waveform.channel_name == f"{sim_6363_device.di_lines[1].name}..." + assert waveform.channel_name == f"{sim_6363_device.di_lines[4].name}..." assert timestamp1 > timestamp0 @@ -545,9 +545,7 @@ def test___digital_single_channel_port_uint32_reader___read_waveform___returns_v samples_read = reader.read_waveform(waveform, num_samples) assert samples_read == num_samples - assert _get_waveform_data_msb(waveform) == _get_digital_data( - num_lines, num_samples - ) # TODO: AB#3178052 - change to _get_waveform_data() + assert _get_waveform_data(waveform) == _get_digital_data(num_lines, num_samples) assert _is_timestamp_close_to_now(waveform.timing.timestamp) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR @@ -566,15 +564,24 @@ def test___digital_single_channel_lines_and_port___read_waveform___returns_valid samples_read = reader.read_waveform(waveform, samples_to_read) assert samples_read == samples_to_read - # Note, the data on the port's waveform is MSB instead of LSB because of bug AB#3178052 - # When that bug is fixed, these asserts should be updated - assert _get_waveform_data(waveform) == [0, 1025, 514, 1539, 260, 1285, 774, 1799, 128, 1153] + assert _get_waveform_bitstrings(waveform) == [ + "00000000000", + "00100000001", + "01000000010", + "01100000011", + "10000000100", + "10100000101", + "11000000110", + "11100000111", + "00000001000", + "00100001001", + ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name assert waveform._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, + sim_6363_device.di_lines[0].name, sim_6363_device.di_lines[39].name, sim_6363_device.di_lines[38].name, sim_6363_device.di_lines[37].name, diff --git a/tests/component/stream_writers/test_digital_multi_channel_writer.py b/tests/component/stream_writers/test_digital_multi_channel_writer.py index 22c520c72..c5f136c9b 100644 --- a/tests/component/stream_writers/test_digital_multi_channel_writer.py +++ b/tests/component/stream_writers/test_digital_multi_channel_writer.py @@ -24,7 +24,6 @@ _get_digital_port_data_sample_major, _get_num_do_lines_in_task, _get_waveform_data, - _get_waveform_data_msb, _int_to_bool_array, _start_do_task, ) @@ -369,9 +368,9 @@ def test___digital_multi_channel_writer___write_waveforms_ports___outputs_match_ actual_value = di_multi_channel_port_loopback_task.read() assert actual_value[0] != actual_value[1] assert actual_value == [ - _get_waveform_data_msb(waveforms[0])[-1], - _get_waveform_data_msb(waveforms[1])[-1], - ] # TODO: AB#3178052 - change to _get_waveform_data() + _get_waveform_data(waveforms[0])[-1], + _get_waveform_data(waveforms[1])[-1], + ] def test___digital_multi_channel_writer___write_waveforms_port_and_lines___outputs_match_final_values( @@ -395,9 +394,9 @@ def test___digital_multi_channel_writer___write_waveforms_port_and_lines___outpu assert samples_written == num_samples actual_value = di_multi_channel_port_and_lines_loopback_task.read() assert actual_value == [ - _get_waveform_data_msb(waveforms[0])[-1], + _get_waveform_data(waveforms[0])[-1], _get_waveform_data(waveforms[1])[-1], - ] # TODO: AB#3178052 - change to _get_waveform_data() + ] def test___digital_multi_channel_writer___write_waveforms_with_non_contiguous_data___outputs_match_final_values( diff --git a/tests/component/stream_writers/test_digital_single_channel_writer.py b/tests/component/stream_writers/test_digital_single_channel_writer.py index a786463c4..446ae10ee 100644 --- a/tests/component/stream_writers/test_digital_single_channel_writer.py +++ b/tests/component/stream_writers/test_digital_single_channel_writer.py @@ -17,7 +17,6 @@ _get_digital_data, _get_num_do_lines_in_task, _get_waveform_data, - _get_waveform_data_msb, _int_to_bool_array, ) @@ -426,9 +425,7 @@ def test___digital_single_channel_writer___write_waveform_port_uint8___outputs_m actual_value = di_port1_loopback_task.read() assert samples_written == num_samples assert waveform.signal_count == num_lines - assert ( - actual_value == _get_waveform_data_msb(waveform)[i - 1] - ) # TODO: AB#3178052 - change to _get_waveform_data() + assert actual_value == _get_waveform_data(waveform)[i - 1] def test___digital_single_channel_writer___write_waveform_port_uint32___outputs_match_final_values( @@ -450,6 +447,4 @@ def test___digital_single_channel_writer___write_waveform_port_uint32___outputs_ actual_value = di_port0_loopback_task.read() assert samples_written == num_samples assert waveform.signal_count == num_lines - assert ( - actual_value == _get_waveform_data_msb(waveform)[i - 1] - ) # TODO: AB#3178052 - change to _get_waveform_data() + assert actual_value == _get_waveform_data(waveform)[i - 1] diff --git a/tests/component/task/test_task_read_waveform_di.py b/tests/component/task/test_task_read_waveform_di.py index d141044ab..70a638190 100644 --- a/tests/component/task/test_task_read_waveform_di.py +++ b/tests/component/task/test_task_read_waveform_di.py @@ -7,6 +7,7 @@ from nidaqmx.constants import READ_ALL_AVAILABLE from tests.component._digital_utils import ( _get_expected_data_for_line, + _get_waveform_bitstrings, _get_waveform_data, ) @@ -61,15 +62,24 @@ def test___digital_single_channel___read_waveform_lines_and_port___returns_valid waveform = di_single_chan_lines_and_port_task.read_waveform(samples_to_read) - # Note, the data on the port's waveform is MSB instead of LSB because of bug AB#3178052 - # When that bug is fixed, these asserts should be updated - assert _get_waveform_data(waveform) == [0, 1025, 514, 1539, 260, 1285, 774, 1799, 128, 1153] + assert _get_waveform_bitstrings(waveform) == [ + "00000000000", + "00100000001", + "01000000010", + "01100000011", + "10000000100", + "10100000101", + "11000000110", + "11100000111", + "00000001000", + "00100001001", + ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name assert waveform._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, + sim_6363_device.di_lines[0].name, sim_6363_device.di_lines[39].name, sim_6363_device.di_lines[38].name, sim_6363_device.di_lines[37].name, @@ -162,16 +172,16 @@ def test___digital_multi_channel___read_waveform_different_lines___returns_valid assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, ] assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[3].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[5].name, sim_6363_device.di_lines[6].name, + sim_6363_device.di_lines[5].name, + sim_6363_device.di_lines[4].name, + sim_6363_device.di_lines[3].name, ] @@ -197,21 +207,19 @@ def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_ assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[1].name, sim_6363_device.di_lines[2].name, + sim_6363_device.di_lines[1].name, ] assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[3].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[5].name, sim_6363_device.di_lines[6].name, + sim_6363_device.di_lines[5].name, + sim_6363_device.di_lines[4].name, + sim_6363_device.di_lines[3].name, ] - # Note, the data on the port's waveform is MSB instead of LSB because of bug AB#3178052 - # When that bug is fixed, these asserts should be updated - assert _get_waveform_data(waveforms[3]) == [0, 128, 64, 192, 32, 160, 96, 224, 16, 144] + assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name assert waveforms[3]._get_signal_names() == [ diff --git a/tests/component/task/test_task_write_waveform_do.py b/tests/component/task/test_task_write_waveform_do.py index b07d991ee..6a738bb58 100644 --- a/tests/component/task/test_task_write_waveform_do.py +++ b/tests/component/task/test_task_write_waveform_do.py @@ -14,7 +14,6 @@ _create_waveforms_for_mixed_lines, _get_digital_data, _get_waveform_data, - _get_waveform_data_msb, ) @@ -279,9 +278,7 @@ def test___task___write_waveform_port_uint8___outputs_match_final_values( assert samples_written == num_samples actual_value = di_port1_loopback_task.read() - assert ( - actual_value == _get_waveform_data_msb(waveform)[i - 1] - ) # TODO: AB#3178052 - change to _get_waveform_data() + assert actual_value == _get_waveform_data(waveform)[i - 1] def test___task___write_waveform_port_uint32___outputs_match_final_values( @@ -300,9 +297,7 @@ def test___task___write_waveform_port_uint32___outputs_match_final_values( assert samples_written == num_samples actual_value = di_port0_loopback_task.read() - assert ( - actual_value == _get_waveform_data_msb(waveform)[i - 1] - ) # TODO: AB#3178052 - change to _get_waveform_data() + assert actual_value == _get_waveform_data(waveform)[i - 1] @pytest.mark.disable_feature_toggle(WAVEFORM_SUPPORT) @@ -417,9 +412,9 @@ def test___task___write_waveforms_ports___outputs_match_final_values( actual_value = di_multi_channel_port_loopback_task.read() assert actual_value[0] != actual_value[1] assert actual_value == [ - _get_waveform_data_msb(waveforms[0])[-1], - _get_waveform_data_msb(waveforms[1])[-1], - ] # TODO: AB#3178052 - change to _get_waveform_data() + _get_waveform_data(waveforms[0])[-1], + _get_waveform_data(waveforms[1])[-1], + ] def test___task___write_waveforms_port_and_lines___outputs_match_final_values( @@ -442,9 +437,9 @@ def test___task___write_waveforms_port_and_lines___outputs_match_final_values( assert samples_written == num_samples actual_value = di_multi_channel_port_and_lines_loopback_task.read() assert actual_value == [ - _get_waveform_data_msb(waveforms[0])[-1], + _get_waveform_data(waveforms[0])[-1], _get_waveform_data(waveforms[1])[-1], - ] # TODO: AB#3178052 - change to _get_waveform_data() + ] def test___task___write_waveforms_with_non_contiguous_data___outputs_match_final_values( From 745fbd036ecee59109d21bf89bb84b129f3c8fb0 Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Tue, 25 Nov 2025 13:04:08 -0600 Subject: [PATCH 02/12] fix digital output tests --- tests/component/_digital_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index d1c105d53..cf2e9e255 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -78,8 +78,9 @@ def _get_expected_data_for_lines(num_samples: int, first_line: int, num_lines: i line_index = line_num % 8 bit_value = (sample_num >> line_index) & 1 # Set the bit at position (line_num - first_line) in the result + # (Note that we reverse the order to match line numbering, so the ints are MSB first) if bit_value: - result |= 1 << (line_num - first_line) + result |= 1 << (first_line + num_lines - 1 - line_num) data.append(result) return data From f5c7c5612b87739deeecfe3c7dec9574a3cbd9e9 Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Tue, 25 Nov 2025 15:42:56 -0600 Subject: [PATCH 03/12] _validate_waveform_signals() --- tests/component/_digital_utils.py | 19 +++++ .../test_digital_multi_channel_reader.py | 73 ++++++++++--------- .../test_digital_single_channel_reader.py | 56 +++++++++----- 3 files changed, 95 insertions(+), 53 deletions(-) diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index cf2e9e255..150ec55aa 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -233,3 +233,22 @@ def _read_and_copy( ) -> numpy.typing.NDArray[_D]: read_func(array) return array.copy() + + +def _validate_waveform_signals( + device: nidaqmx.system.device.Device, + waveform: DigitalWaveform[Any], + lines: list[int] | range, # signal index to line index mapping +) -> None: + lines_list = list( + lines[::-1] + ) # TODO: AB#3178052 - remove reversal when signal/line ordering is fixed + signal_count = waveform.signal_count + sample_count = waveform.sample_count + assert signal_count == len(lines_list) + for signal_index in range(signal_count): + line_index = lines_list[signal_index] + signal = waveform.signals[signal_index] + assert signal.signal_index == signal_index + assert signal.name == device.di_lines[line_index].name + assert signal.data.tolist() == _get_expected_data_for_line(sample_count, line_index) diff --git a/tests/component/stream_readers/test_digital_multi_channel_reader.py b/tests/component/stream_readers/test_digital_multi_channel_reader.py index 5b90a8e72..f1b999ba5 100644 --- a/tests/component/stream_readers/test_digital_multi_channel_reader.py +++ b/tests/component/stream_readers/test_digital_multi_channel_reader.py @@ -31,6 +31,7 @@ _get_num_di_lines_in_task, _get_waveform_data, _read_and_copy, + _validate_waveform_signals, ) from tests.component._utils import _is_timestamp_close_to_now @@ -330,6 +331,7 @@ def test___digital_multi_channel_multi_line_reader___read_waveforms_feature_disa def test___digital_multi_channel_multi_line_reader___read_waveforms___returns_valid_waveforms( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalMultiChannelReader(di_multi_chan_multi_line_timing_task.in_stream) num_channels = di_multi_chan_multi_line_timing_task.number_of_channels @@ -350,6 +352,7 @@ def test___digital_multi_channel_multi_line_reader___read_waveforms___returns_va assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_to_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_different_lines_reader___read_waveforms___returns_valid_waveforms( @@ -378,29 +381,19 @@ def test___digital_multi_channel_different_lines_reader___read_waveforms___retur assert waveforms[0].sample_count == samples_to_read assert waveforms[0].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[0].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[0].name - assert waveforms[0]._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert _is_timestamp_close_to_now(waveforms[1].timing.timestamp) assert waveforms[1].sample_count == samples_to_read assert waveforms[1].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name - assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[6].name, - sim_6363_device.di_lines[5].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[3].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) def test___digital_multi_channel_lines_and_port_reader___read_waveforms___returns_valid_waveforms( @@ -429,41 +422,22 @@ def test___digital_multi_channel_lines_and_port_reader___read_waveforms___return assert _is_timestamp_close_to_now(waveforms[0].timing.timestamp) assert waveforms[0].sample_count == samples_to_read assert waveforms[0].channel_name == di_multi_chan_lines_and_port_task.di_channels[0].name - assert waveforms[0]._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert _is_timestamp_close_to_now(waveforms[1].timing.timestamp) assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name - assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[6].name, - sim_6363_device.di_lines[5].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[3].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert _is_timestamp_close_to_now(waveforms[3].timing.timestamp) assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name - assert waveforms[3]._get_signal_names() == [ - sim_6363_device.di_lines[39].name, - sim_6363_device.di_lines[38].name, - sim_6363_device.di_lines[37].name, - sim_6363_device.di_lines[36].name, - sim_6363_device.di_lines[35].name, - sim_6363_device.di_lines[34].name, - sim_6363_device.di_lines[33].name, - sim_6363_device.di_lines[32].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[3], list(range(32, 40))) def test___digital_multi_channel_different_lines_reader___read_mismatched_waveforms___throws_exception( @@ -488,6 +462,7 @@ def test___digital_multi_channel_different_lines_reader___read_mismatched_wavefo def test___digital_multi_channel_multi_line_reader___read_waveforms_no_args___returns_valid_waveforms( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalMultiChannelReader(di_multi_chan_multi_line_timing_task.in_stream) num_channels = di_multi_chan_multi_line_timing_task.number_of_channels @@ -507,10 +482,12 @@ def test___digital_multi_channel_multi_line_reader___read_waveforms_no_args___re assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == 50 + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_multi_line_reader___read_waveforms_in_place___populates_valid_waveforms( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalMultiChannelReader(di_multi_chan_multi_line_timing_task.in_stream) num_channels = di_multi_chan_multi_line_timing_task.number_of_channels @@ -531,6 +508,7 @@ def test___digital_multi_channel_multi_line_reader___read_waveforms_in_place___p assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_to_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_multi_line_reader___reuse_waveform_in_place___overwrites_data_timing_and_attributes( @@ -559,6 +537,7 @@ def _make_multi_channel_multi_line_reader(lines_start, rate): assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, chan) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == sim_6363_device.di_lines[chan].name + _validate_waveform_signals(sim_6363_device, waveform, [chan]) reader1.read_waveforms(waveforms, sample_count) timestamps1 = [wf.timing.timestamp for wf in waveforms] @@ -566,6 +545,8 @@ def _make_multi_channel_multi_line_reader(lines_start, rate): assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, chan + 1) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == sim_6363_device.di_lines[chan + 1].name + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveform, [chan + 1]) for ts0, ts1 in zip(timestamps0, timestamps1): assert ts1 > ts0 @@ -588,6 +569,7 @@ def test___digital_multi_channel_multi_line_reader___read_into_undersized_wavefo def test___digital_multi_channel_multi_line_reader___read_into_undersized_waveforms___returns_valid_waveforms( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalMultiChannelReader(di_multi_chan_multi_line_timing_task.in_stream) num_channels = di_multi_chan_multi_line_timing_task.number_of_channels @@ -608,6 +590,7 @@ def test___digital_multi_channel_multi_line_reader___read_into_undersized_wavefo assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_to_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_reader___reuse_waveform_in_place_with_different_sample_counts___populates_valid_waveforms( @@ -639,25 +622,35 @@ def _make_multi_channel_reader(chan_a_index, chan_b_index, samps_per_chan): reader0.read_waveforms(waveforms, 5) assert waveforms[0].sample_count == 5 assert _get_waveform_data(waveforms[0]) == _get_expected_data_for_line(5, 0) + _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert waveforms[0].channel_name == f"{sim_6363_device.name}/port0/line0" assert waveforms[1].sample_count == 5 assert _get_waveform_data(waveforms[1]) == _get_expected_data_for_line(5, 1) + _validate_waveform_signals(sim_6363_device, waveforms[1], [1]) assert waveforms[1].channel_name == f"{sim_6363_device.name}/port0/line1" reader1.read_waveforms(waveforms, 10) assert waveforms[0].sample_count == 10 assert _get_waveform_data(waveforms[0]) == _get_expected_data_for_line(10, 2) + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveforms[0], [2]) assert waveforms[0].channel_name == f"{sim_6363_device.name}/port0/line2" assert waveforms[1].sample_count == 10 assert _get_waveform_data(waveforms[1]) == _get_expected_data_for_line(10, 3) + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveforms[1], [3]) assert waveforms[1].channel_name == f"{sim_6363_device.name}/port0/line3" reader2.read_waveforms(waveforms, 15) assert waveforms[0].sample_count == 15 assert _get_waveform_data(waveforms[0]) == _get_expected_data_for_line(15, 4) + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveforms[0], [4]) assert waveforms[0].channel_name == f"{sim_6363_device.name}/port0/line4" assert waveforms[1].sample_count == 15 assert _get_waveform_data(waveforms[1]) == _get_expected_data_for_line(15, 5) + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveforms[1], [5]) assert waveforms[1].channel_name == f"{sim_6363_device.name}/port0/line5" @@ -705,6 +698,7 @@ def test___digital_multi_channel_multi_line_reader_with_timing_flag___read_wavef def test___digital_multi_channel_multi_line_reader_with_extended_properties_flag___read_waveforms___only_includes_extended_properties( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: in_stream = di_multi_chan_multi_line_timing_task.in_stream in_stream.waveform_attribute_mode = WaveformAttributeMode.EXTENDED_PROPERTIES @@ -726,10 +720,12 @@ def test___digital_multi_channel_multi_line_reader_with_extended_properties_flag assert waveform.timing.sample_interval_mode == SampleIntervalMode.NONE assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_to_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_multi_line_reader_with_both_flags___read_waveforms___includes_both_timing_and_extended_properties( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: in_stream = di_multi_chan_multi_line_timing_task.in_stream in_stream.waveform_attribute_mode = ( @@ -755,6 +751,7 @@ def test___digital_multi_channel_multi_line_reader_with_both_flags___read_wavefo assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_to_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_multi_line_reader_with_none_flag___read_waveforms___minimal_waveform_data( @@ -793,6 +790,7 @@ def test___digital_multi_channel_multi_line_reader_with_none_flag___read_wavefor def test___digital_multi_channel_multi_line_reader___read_waveform_all_dtypes___returns_valid_waveform( di_multi_chan_multi_line_timing_task: nidaqmx.Task, dtype, + sim_6363_device: nidaqmx.system.Device, ) -> None: in_stream = di_multi_chan_multi_line_timing_task.in_stream reader = DigitalMultiChannelReader(in_stream) @@ -807,10 +805,12 @@ def test___digital_multi_channel_multi_line_reader___read_waveform_all_dtypes___ assert len(waveforms) == num_channels for chan, waveform in enumerate(waveforms): assert _get_waveform_data(waveform) == _get_expected_data_for_line(num_samples, chan) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel_multi_line_reader___read_waveforms_read_all_available___returns_valid_waveforms( di_multi_chan_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalMultiChannelReader(di_multi_chan_multi_line_timing_task.in_stream) num_channels = di_multi_chan_multi_line_timing_task.number_of_channels @@ -830,3 +830,4 @@ def test___digital_multi_channel_multi_line_reader___read_waveforms_read_all_ava assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_multi_chan_multi_line_timing_task.di_channels[chan].name assert waveform.sample_count == samples_read + _validate_waveform_signals(sim_6363_device, waveform, [chan]) diff --git a/tests/component/stream_readers/test_digital_single_channel_reader.py b/tests/component/stream_readers/test_digital_single_channel_reader.py index d740bd0cb..7569fe2b8 100644 --- a/tests/component/stream_readers/test_digital_single_channel_reader.py +++ b/tests/component/stream_readers/test_digital_single_channel_reader.py @@ -30,6 +30,7 @@ _get_waveform_bitstrings, _get_waveform_data, _read_and_copy, + _validate_waveform_signals, ) from tests.component._utils import _is_timestamp_close_to_now @@ -216,6 +217,7 @@ def test___digital_single_line_reader___read_waveform_feature_disabled___raises_ def test___digital_single_line_reader___read_waveform___returns_valid_waveform( di_single_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_line_timing_task.in_stream) samples_to_read = 10 @@ -229,10 +231,12 @@ def test___digital_single_line_reader___read_waveform___returns_valid_waveform( assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel_multi_line_reader___read_waveform___returns_valid_waveform( di_single_channel_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_channel_multi_line_timing_task.in_stream) samples_to_read = 10 @@ -247,10 +251,12 @@ def test___digital_single_channel_multi_line_reader___read_waveform___returns_va assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) def test___digital_single_line_reader___read_waveform_no_args___returns_valid_waveform( di_single_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_line_timing_task.in_stream) waveform = DigitalWaveform(50) @@ -263,10 +269,12 @@ def test___digital_single_line_reader___read_waveform_no_args___returns_valid_wa assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel_multi_line_reader___read_waveform_no_args___returns_valid_waveform( di_single_channel_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_channel_multi_line_timing_task.in_stream) num_lines = _get_num_di_lines_in_task(di_single_channel_multi_line_timing_task) @@ -280,10 +288,12 @@ def test___digital_single_channel_multi_line_reader___read_waveform_no_args___re assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) def test___digital_single_line_reader___read_waveform_in_place___returns_valid_waveform( di_single_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_line_timing_task.in_stream) waveform = DigitalWaveform(50) @@ -295,10 +305,12 @@ def test___digital_single_line_reader___read_waveform_in_place___returns_valid_w assert _is_timestamp_close_to_now(waveform.timing.timestamp) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel_multi_line_reader___read_waveform_in_place___returns_valid_waveform( di_single_channel_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_channel_multi_line_timing_task.in_stream) num_lines = _get_num_di_lines_in_task(di_single_channel_multi_line_timing_task) @@ -311,6 +323,7 @@ def test___digital_single_channel_multi_line_reader___read_waveform_in_place___r assert _is_timestamp_close_to_now(waveform.timing.timestamp) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) def test___digital_single_line_reader___reuse_waveform_in_place___overwrites_data_timing_and_attributes( @@ -335,12 +348,15 @@ def _make_single_line_reader(chan_index, rate): assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, 0) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == sim_6363_device.di_lines[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) reader1.read_waveform(waveform, sample_count) timestamp1 = waveform.timing.timestamp assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, 1) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == sim_6363_device.di_lines[1].name + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveform, [1]) assert timestamp1 > timestamp0 @@ -370,12 +386,15 @@ def _make_single_channel_multi_line_reader(lines_start, rate): assert _get_waveform_data(waveform) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == f"{sim_6363_device.di_lines[3].name}..." + _validate_waveform_signals(sim_6363_device, waveform, range(0, 4)) reader1.read_waveform(waveform, sample_count) timestamp1 = waveform.timing.timestamp assert _get_waveform_data(waveform) == [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == f"{sim_6363_device.di_lines[4].name}..." + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveform, range(1, 5)) assert timestamp1 > timestamp0 @@ -398,6 +417,7 @@ def test___digital_single_line_reader___read_into_undersized_waveform_without_re def test___digital_single_line_reader___read_into_undersized_waveform___returns_valid_waveform( di_single_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_line_timing_task.in_stream) samples_to_read = 10 @@ -411,6 +431,7 @@ def test___digital_single_line_reader___read_into_undersized_waveform___returns_ assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel_reader___reuse_waveform_in_place_with_different_sample_counts___populates_valid_waveforms( @@ -435,20 +456,25 @@ def _make_single_channel_reader(chan_index, samps_per_chan): assert waveform.sample_count == 5 assert _get_waveform_data(waveform) == _get_expected_data_for_line(5, 0) assert waveform.channel_name == f"{sim_6363_device.name}/port0/line0" + _validate_waveform_signals(sim_6363_device, waveform, [0]) reader1.read_waveform(waveform, 10) assert waveform.sample_count == 10 assert _get_waveform_data(waveform) == _get_expected_data_for_line(10, 1) assert waveform.channel_name == f"{sim_6363_device.name}/port0/line1" + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveform, [1]) reader2.read_waveform(waveform, 15) assert waveform.sample_count == 15 assert _get_waveform_data(waveform) == _get_expected_data_for_line(15, 2) assert waveform.channel_name == f"{sim_6363_device.name}/port0/line2" + # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed + # _validate_waveform_signals(sim_6363_device, waveform, [2]) def test___digital_single_line_reader___read_waveform_high_sample_rate___returns_correct_sample_interval( - di_single_line_high_rate_task: nidaqmx.Task, + di_single_line_high_rate_task: nidaqmx.Task, sim_6363_device: nidaqmx.system.Device ) -> None: reader = DigitalSingleChannelReader(di_single_line_high_rate_task.in_stream) samples_to_read = 50 @@ -462,6 +488,7 @@ def test___digital_single_line_reader___read_waveform_high_sample_rate___returns assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 10_000_000) assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_line_high_rate_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_line_reader_with_timing_flag___read_waveform___only_includes_timing_data( @@ -483,7 +510,7 @@ def test___digital_single_line_reader_with_timing_flag___read_waveform___only_in def test___digital_single_line_reader_with_extended_properties_flag___read_waveform___only_includes_extended_properties( - di_single_line_timing_task: nidaqmx.Task, + di_single_line_timing_task: nidaqmx.Task, sim_6363_device: nidaqmx.system.Device ) -> None: in_stream = di_single_line_timing_task.in_stream in_stream.waveform_attribute_mode = WaveformAttributeMode.EXTENDED_PROPERTIES @@ -496,10 +523,11 @@ def test___digital_single_line_reader_with_extended_properties_flag___read_wavef assert _get_waveform_data(waveform) == _get_digital_data(1, 50) assert waveform.timing.sample_interval_mode == SampleIntervalMode.NONE assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_line_reader_with_both_flags___read_waveform___includes_both_timing_and_extended_properties( - di_single_line_timing_task: nidaqmx.Task, + di_single_line_timing_task: nidaqmx.Task, sim_6363_device: nidaqmx.system.Device ) -> None: in_stream = di_single_line_timing_task.in_stream in_stream.waveform_attribute_mode = ( @@ -516,6 +544,7 @@ def test___digital_single_line_reader_with_both_flags___read_waveform___includes assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_line_reader_with_none_flag___read_waveform___minimal_waveform_data( @@ -535,7 +564,7 @@ def test___digital_single_line_reader_with_none_flag___read_waveform___minimal_w def test___digital_single_channel_port_uint32_reader___read_waveform___returns_valid_waveform( - di_single_channel_port_uint32_timing_task: nidaqmx.Task, + di_single_channel_port_uint32_timing_task: nidaqmx.Task, sim_6363_device: nidaqmx.system.Device ) -> None: reader = DigitalSingleChannelReader(di_single_channel_port_uint32_timing_task.in_stream) num_lines = 32 @@ -550,6 +579,7 @@ def test___digital_single_channel_port_uint32_reader___read_waveform___returns_v assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_channel_port_uint32_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) def test___digital_single_channel_lines_and_port___read_waveform___returns_valid_waveform( @@ -578,19 +608,7 @@ def test___digital_single_channel_lines_and_port___read_waveform___returns_valid ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name - assert waveform._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - sim_6363_device.di_lines[0].name, - sim_6363_device.di_lines[39].name, - sim_6363_device.di_lines[38].name, - sim_6363_device.di_lines[37].name, - sim_6363_device.di_lines[36].name, - sim_6363_device.di_lines[35].name, - sim_6363_device.di_lines[34].name, - sim_6363_device.di_lines[33].name, - sim_6363_device.di_lines[32].name, - ] + _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2]) @pytest.mark.parametrize( @@ -603,6 +621,7 @@ def test___digital_single_channel_lines_and_port___read_waveform___returns_valid ) def test___digital_single_channel_multi_line_reader___read_waveform_all_dtypes___returns_valid_waveform( di_single_channel_multi_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, dtype, ) -> None: reader = DigitalSingleChannelReader(di_single_channel_multi_line_timing_task.in_stream) @@ -614,10 +633,12 @@ def test___digital_single_channel_multi_line_reader___read_waveform_all_dtypes__ assert samples_read == num_samples assert _get_waveform_data(waveform) == _get_digital_data(num_lines, num_samples) + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) def test___digital_single_line_reader___read_waveform_read_all_available___returns_valid_waveform( di_single_line_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: reader = DigitalSingleChannelReader(di_single_line_timing_task.in_stream) waveform = DigitalWaveform(100) @@ -630,3 +651,4 @@ def test___digital_single_line_reader___read_waveform_read_all_available___retur assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_line_timing_task.di_channels[0].name + _validate_waveform_signals(sim_6363_device, waveform, [0]) From 604253671c7acdfde53d3e347cbc0a1f812ca49c Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Wed, 26 Nov 2025 09:56:48 -0600 Subject: [PATCH 04/12] more _validate_waveform_signals() --- .../task/test_task_read_waveform_di.py | 78 +++++++------------ 1 file changed, 29 insertions(+), 49 deletions(-) diff --git a/tests/component/task/test_task_read_waveform_di.py b/tests/component/task/test_task_read_waveform_di.py index 70a638190..66737f3ee 100644 --- a/tests/component/task/test_task_read_waveform_di.py +++ b/tests/component/task/test_task_read_waveform_di.py @@ -9,29 +9,35 @@ _get_expected_data_for_line, _get_waveform_bitstrings, _get_waveform_data, + _validate_waveform_signals, ) def test___digital_single_channel___read_waveform___returns_valid_waveform( di_single_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: waveform = di_single_channel_timing_task.read_waveform() assert isinstance(waveform, DigitalWaveform) assert _get_waveform_data(waveform) == _get_expected_data_for_line(50, 0) + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel___read_waveform_one_sample___returns_waveform_with_one_sample( di_single_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: waveform = di_single_channel_timing_task.read_waveform(1) assert isinstance(waveform, DigitalWaveform) assert _get_waveform_data(waveform) == _get_expected_data_for_line(1, 0) + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel___read_waveform_many_sample___returns_waveform_with_many_samples( di_single_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: samples_to_read = 10 @@ -39,10 +45,12 @@ def test___digital_single_channel___read_waveform_many_sample___returns_waveform assert isinstance(waveform, DigitalWaveform) assert _get_waveform_data(waveform) == _get_expected_data_for_line(samples_to_read, 0) + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel___read_waveform_too_many_samples___returns_waveform_with_correct_number_of_samples( di_single_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: samples_to_read = 100 samples_available = 50 @@ -52,6 +60,7 @@ def test___digital_single_channel___read_waveform_too_many_samples___returns_wav assert isinstance(waveform, DigitalWaveform) assert waveform.sample_count == samples_available assert _get_waveform_data(waveform) == _get_expected_data_for_line(samples_available, 0) + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_single_channel___read_waveform_lines_and_port___returns_valid_waveform( @@ -76,23 +85,12 @@ def test___digital_single_channel___read_waveform_lines_and_port___returns_valid ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name - assert waveform._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - sim_6363_device.di_lines[0].name, - sim_6363_device.di_lines[39].name, - sim_6363_device.di_lines[38].name, - sim_6363_device.di_lines[37].name, - sim_6363_device.di_lines[36].name, - sim_6363_device.di_lines[35].name, - sim_6363_device.di_lines[34].name, - sim_6363_device.di_lines[33].name, - sim_6363_device.di_lines[32].name, - ] + _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2]) def test___digital_multi_channel___read_waveform___returns_valid_waveforms( di_multi_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: num_channels = di_multi_channel_timing_task.number_of_channels @@ -103,10 +101,12 @@ def test___digital_multi_channel___read_waveform___returns_valid_waveforms( assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) for chan_index, waveform in enumerate(waveforms): assert _get_waveform_data(waveform) == _get_expected_data_for_line(50, chan_index) + _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) def test___digital_multi_channel___read_waveform_one_sample___returns_waveforms_with_single_sample( di_multi_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: num_channels = di_multi_channel_timing_task.number_of_channels @@ -117,10 +117,12 @@ def test___digital_multi_channel___read_waveform_one_sample___returns_waveforms_ assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) for chan_index, waveform in enumerate(waveforms): assert _get_waveform_data(waveform) == _get_expected_data_for_line(1, chan_index) + _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) def test___digital_multi_channel___read_waveform_many_samples___returns_waveforms_with_many_samples( di_multi_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: num_channels = di_multi_channel_timing_task.number_of_channels samples_to_read = 10 @@ -132,10 +134,12 @@ def test___digital_multi_channel___read_waveform_many_samples___returns_waveform assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) for chan_index, waveform in enumerate(waveforms): assert _get_waveform_data(waveform) == _get_expected_data_for_line(10, chan_index) + _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) def test___digital_multi_channel___read_waveform_too_many_samples___returns_waveforms_with_correct_number_of_samples( di_multi_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: num_channels = di_multi_channel_timing_task.number_of_channels samples_to_read = 100 @@ -149,6 +153,7 @@ def test___digital_multi_channel___read_waveform_too_many_samples___returns_wave for chan, waveform in enumerate(waveforms): assert waveform.sample_count == samples_available assert _get_waveform_data(waveform) == _get_expected_data_for_line(samples_available, chan) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel___read_waveform_different_lines___returns_valid_waveforms( @@ -166,23 +171,13 @@ def test___digital_multi_channel___read_waveform_different_lines___returns_valid assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) assert _get_waveform_data(waveforms[0]) == [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] assert waveforms[0].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[0].name - assert waveforms[0]._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name - assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[6].name, - sim_6363_device.di_lines[5].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[3].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_waveforms( @@ -200,52 +195,36 @@ def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_ assert _get_waveform_data(waveforms[0]) == [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] assert waveforms[0].sample_count == samples_to_read assert waveforms[0].channel_name == di_multi_chan_lines_and_port_task.di_channels[0].name - assert waveforms[0]._get_signal_names() == [ - sim_6363_device.di_lines[0].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name - assert waveforms[1]._get_signal_names() == [ - sim_6363_device.di_lines[2].name, - sim_6363_device.di_lines[1].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - assert waveforms[2]._get_signal_names() == [ - sim_6363_device.di_lines[6].name, - sim_6363_device.di_lines[5].name, - sim_6363_device.di_lines[4].name, - sim_6363_device.di_lines[3].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name - assert waveforms[3]._get_signal_names() == [ - sim_6363_device.di_lines[39].name, - sim_6363_device.di_lines[38].name, - sim_6363_device.di_lines[37].name, - sim_6363_device.di_lines[36].name, - sim_6363_device.di_lines[35].name, - sim_6363_device.di_lines[34].name, - sim_6363_device.di_lines[33].name, - sim_6363_device.di_lines[32].name, - ] + _validate_waveform_signals(sim_6363_device, waveforms[3], [32, 33, 34, 35, 36, 37, 38, 39]) def test___digital_single_channel___read_waveform_read_all_available___returns_valid_waveform( di_single_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: waveform = di_single_channel_timing_task.read_waveform(READ_ALL_AVAILABLE) assert isinstance(waveform, DigitalWaveform) assert waveform.sample_count == 50 assert _get_waveform_data(waveform) == _get_expected_data_for_line(waveform.sample_count, 0) + _validate_waveform_signals(sim_6363_device, waveform, [0]) def test___digital_multi_channel___read_waveform_read_all_available___returns_valid_waveforms( di_multi_channel_timing_task: nidaqmx.Task, + sim_6363_device: nidaqmx.system.Device, ) -> None: waveforms = di_multi_channel_timing_task.read_waveform(READ_ALL_AVAILABLE) @@ -257,3 +236,4 @@ def test___digital_multi_channel___read_waveform_read_all_available___returns_va assert _get_waveform_data(waveform) == _get_expected_data_for_line( waveform.sample_count, chan_index ) + _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) From 300ed63743d3233152dc9975d0432b0722907d8e Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Wed, 26 Nov 2025 14:36:09 -0600 Subject: [PATCH 05/12] cleanup --- .../test_digital_multi_channel_reader.py | 6 ++-- .../task/test_task_read_waveform_di.py | 30 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/component/stream_readers/test_digital_multi_channel_reader.py b/tests/component/stream_readers/test_digital_multi_channel_reader.py index f1b999ba5..140746a5f 100644 --- a/tests/component/stream_readers/test_digital_multi_channel_reader.py +++ b/tests/component/stream_readers/test_digital_multi_channel_reader.py @@ -393,7 +393,7 @@ def test___digital_multi_channel_different_lines_reader___read_waveforms___retur assert waveforms[2].sample_count == samples_to_read assert waveforms[2].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) + _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) def test___digital_multi_channel_lines_and_port_reader___read_waveforms___returns_valid_waveforms( @@ -432,12 +432,12 @@ def test___digital_multi_channel_lines_and_port_reader___read_waveforms___return assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) + _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert _is_timestamp_close_to_now(waveforms[3].timing.timestamp) assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name - _validate_waveform_signals(sim_6363_device, waveforms[3], list(range(32, 40))) + _validate_waveform_signals(sim_6363_device, waveforms[3], range(32, 40)) def test___digital_multi_channel_different_lines_reader___read_mismatched_waveforms___throws_exception( diff --git a/tests/component/task/test_task_read_waveform_di.py b/tests/component/task/test_task_read_waveform_di.py index 66737f3ee..519b8e4d0 100644 --- a/tests/component/task/test_task_read_waveform_di.py +++ b/tests/component/task/test_task_read_waveform_di.py @@ -99,9 +99,9 @@ def test___digital_multi_channel___read_waveform___returns_valid_waveforms( assert isinstance(waveforms, list) assert len(waveforms) == num_channels assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) - for chan_index, waveform in enumerate(waveforms): - assert _get_waveform_data(waveform) == _get_expected_data_for_line(50, chan_index) - _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) + for chan, waveform in enumerate(waveforms): + assert _get_waveform_data(waveform) == _get_expected_data_for_line(50, chan) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel___read_waveform_one_sample___returns_waveforms_with_single_sample( @@ -115,9 +115,9 @@ def test___digital_multi_channel___read_waveform_one_sample___returns_waveforms_ assert isinstance(waveforms, list) assert len(waveforms) == num_channels assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) - for chan_index, waveform in enumerate(waveforms): - assert _get_waveform_data(waveform) == _get_expected_data_for_line(1, chan_index) - _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) + for chan, waveform in enumerate(waveforms): + assert _get_waveform_data(waveform) == _get_expected_data_for_line(1, chan) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel___read_waveform_many_samples___returns_waveforms_with_many_samples( @@ -132,9 +132,9 @@ def test___digital_multi_channel___read_waveform_many_samples___returns_waveform assert isinstance(waveforms, list) assert len(waveforms) == num_channels assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) - for chan_index, waveform in enumerate(waveforms): - assert _get_waveform_data(waveform) == _get_expected_data_for_line(10, chan_index) - _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) + for chan, waveform in enumerate(waveforms): + assert _get_waveform_data(waveform) == _get_expected_data_for_line(10, chan) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) def test___digital_multi_channel___read_waveform_too_many_samples___returns_waveforms_with_correct_number_of_samples( @@ -177,7 +177,7 @@ def test___digital_multi_channel___read_waveform_different_lines___returns_valid _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) + _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_waveforms( @@ -203,11 +203,11 @@ def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_ assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], [3, 4, 5, 6]) + _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name - _validate_waveform_signals(sim_6363_device, waveforms[3], [32, 33, 34, 35, 36, 37, 38, 39]) + _validate_waveform_signals(sim_6363_device, waveforms[3], range(32, 40)) def test___digital_single_channel___read_waveform_read_all_available___returns_valid_waveform( @@ -231,9 +231,9 @@ def test___digital_multi_channel___read_waveform_read_all_available___returns_va assert isinstance(waveforms, list) assert len(waveforms) == di_multi_channel_timing_task.number_of_channels assert all(isinstance(waveform, DigitalWaveform) for waveform in waveforms) - for chan_index, waveform in enumerate(waveforms): + for chan, waveform in enumerate(waveforms): assert waveform.sample_count == 50 assert _get_waveform_data(waveform) == _get_expected_data_for_line( - waveform.sample_count, chan_index + waveform.sample_count, chan ) - _validate_waveform_signals(sim_6363_device, waveform, [chan_index]) + _validate_waveform_signals(sim_6363_device, waveform, [chan]) From 221d2d710ddad933641ded796875b37bac881b26 Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Mon, 8 Dec 2025 15:58:00 -0600 Subject: [PATCH 06/12] revert line order for test fixtures and use _get_waveform_port_data() instead --- tests/component/_digital_utils.py | 9 ++-- tests/component/conftest.py | 32 ++++++------ .../test_digital_multi_channel_reader.py | 15 +++--- .../test_digital_single_channel_reader.py | 50 +++++++++---------- .../task/test_task_read_waveform_di.py | 36 ++++++------- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index 150ec55aa..52130b0ae 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -78,9 +78,8 @@ def _get_expected_data_for_lines(num_samples: int, first_line: int, num_lines: i line_index = line_num % 8 bit_value = (sample_num >> line_index) & 1 # Set the bit at position (line_num - first_line) in the result - # (Note that we reverse the order to match line numbering, so the ints are MSB first) if bit_value: - result |= 1 << (first_line + num_lines - 1 - line_num) + result |= 1 << (line_num - first_line) data.append(result) return data @@ -145,12 +144,12 @@ def _int_to_bool_array(num_lines: int, input: int) -> numpy.typing.NDArray[numpy def _get_waveform_data(waveform: DigitalWaveform[Any]) -> list[int]: assert isinstance(waveform, DigitalWaveform) - return [_bool_array_to_int_msb(sample) for sample in waveform.data] + return [_bool_array_to_int_lsb(sample) for sample in waveform.data] -def _get_waveform_bitstrings(waveform: DigitalWaveform[Any]) -> list[str]: +def _get_waveform_port_data(waveform: DigitalWaveform[Any]) -> list[int]: assert isinstance(waveform, DigitalWaveform) - return ["".join("1" if bit else "0" for bit in sample) for sample in waveform.data] + return [_bool_array_to_int_msb(sample) for sample in waveform.data] def _create_digital_waveform_uint8( diff --git a/tests/component/conftest.py b/tests/component/conftest.py index fab954b3b..9cfd5225c 100644 --- a/tests/component/conftest.py +++ b/tests/component/conftest.py @@ -156,7 +156,7 @@ def di_single_channel_multi_line_task( ) -> nidaqmx.Task: """Configure a single-channel multi-line digital input task.""" task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[:8][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) return task @@ -192,7 +192,7 @@ def di_single_chan_lines_and_port_task( """Configure a single-channel multi-line digital input task.""" task.di_channels.add_di_chan( flatten_channel_string( - sim_6363_device.di_lines.channel_names[0:3][::-1] + [sim_6363_device.di_ports[1].name] + sim_6363_device.di_lines.channel_names[0:3] + [sim_6363_device.di_ports[1].name] ), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) @@ -231,15 +231,15 @@ def di_multi_chan_diff_lines_timing_task( This task has three channels made up of different numbers of lines. """ task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.timing.cfg_samp_clk_timing( @@ -257,15 +257,15 @@ def di_multi_chan_lines_and_port_task( This task has three channels made up of lines and one channel made up of a port. """ task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[0:1]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[1:3]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7][::-1]), + flatten_channel_string(sim_6363_device.di_lines.channel_names[3:7]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( @@ -575,7 +575,7 @@ def do_single_channel_multi_line_task( """Configure a single-channel DO task.""" task = generate_task() chan = task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[:8][::-1]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, num_chans=chan.do_num_lines) @@ -589,7 +589,7 @@ def do_single_channel_multi_line_task_with_timing( """Configure a single-channel multi-line DO task with timing for waveform testing.""" task = generate_task() task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_multiplexed_device.do_lines.channel_names[:8][::-1]), + flatten_channel_string(real_x_series_multiplexed_device.do_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.timing.cfg_samp_clk_timing( @@ -635,15 +635,15 @@ def do_multi_channel_mixed_line_task( """Configure a multi-channel DO task with a mix of lines.""" task = generate_task() task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[2:5][::-1]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[2:5]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[0:2][::-1]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[0:2]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[5:8][::-1]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[5:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, num_chans=task.number_of_channels) @@ -713,7 +713,7 @@ def do_multi_channel_port_and_lines_task( line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.do_channels.add_do_chan( - flatten_channel_string(real_x_series_device.do_lines.channel_names[:8][::-1]), + flatten_channel_string(real_x_series_device.do_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_do_task(task, is_port=True, num_chans=task.number_of_channels) @@ -741,7 +741,7 @@ def di_multi_line_loopback_task( """Configure a multi-line DI loopback task.""" task = generate_task() task.di_channels.add_di_chan( - flatten_channel_string(real_x_series_device.di_lines.channel_names[:8][::-1]), + flatten_channel_string(real_x_series_device.di_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_di_task(task) @@ -861,7 +861,7 @@ def di_multi_channel_port_and_lines_loopback_task( line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) task.di_channels.add_di_chan( - flatten_channel_string(real_x_series_device.di_lines.channel_names[:8][::-1]), + flatten_channel_string(real_x_series_device.di_lines.channel_names[:8]), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) _start_di_task(task) diff --git a/tests/component/stream_readers/test_digital_multi_channel_reader.py b/tests/component/stream_readers/test_digital_multi_channel_reader.py index 140746a5f..ae96a3806 100644 --- a/tests/component/stream_readers/test_digital_multi_channel_reader.py +++ b/tests/component/stream_readers/test_digital_multi_channel_reader.py @@ -13,9 +13,9 @@ import nidaqmx.system from nidaqmx._feature_toggles import WAVEFORM_SUPPORT, FeatureNotSupportedError from nidaqmx.constants import ( + READ_ALL_AVAILABLE, AcquisitionType, LineGrouping, - READ_ALL_AVAILABLE, ReallocationPolicy, WaveformAttributeMode, ) @@ -24,12 +24,13 @@ from nidaqmx.utils import flatten_channel_string from tests.component._digital_utils import ( _bool_array_to_int_lsb, - _get_expected_data_for_line, _get_digital_data, + _get_expected_data_for_line, _get_expected_digital_port_data_port_major, _get_expected_digital_port_data_sample_major, _get_num_di_lines_in_task, _get_waveform_data, + _get_waveform_port_data, _read_and_copy, _validate_waveform_signals, ) @@ -387,13 +388,13 @@ def test___digital_multi_channel_different_lines_reader___read_waveforms___retur assert waveforms[1].sample_count == samples_to_read assert waveforms[1].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name - _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [2, 1]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) + _validate_waveform_signals(sim_6363_device, waveforms[2], [6, 5, 4, 3]) def test___digital_multi_channel_lines_and_port_reader___read_waveforms___returns_valid_waveforms( @@ -427,13 +428,13 @@ def test___digital_multi_channel_lines_and_port_reader___read_waveforms___return assert _is_timestamp_close_to_now(waveforms[1].timing.timestamp) assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name - _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [2, 1]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert _is_timestamp_close_to_now(waveforms[2].timing.timestamp) assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) - assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + _validate_waveform_signals(sim_6363_device, waveforms[2], [6, 5, 4, 3]) + assert _get_waveform_port_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert _is_timestamp_close_to_now(waveforms[3].timing.timestamp) assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name diff --git a/tests/component/stream_readers/test_digital_single_channel_reader.py b/tests/component/stream_readers/test_digital_single_channel_reader.py index 7569fe2b8..208c497c6 100644 --- a/tests/component/stream_readers/test_digital_single_channel_reader.py +++ b/tests/component/stream_readers/test_digital_single_channel_reader.py @@ -23,12 +23,12 @@ from nidaqmx.stream_readers import DaqError, DigitalSingleChannelReader from nidaqmx.utils import flatten_channel_string from tests.component._digital_utils import ( - _bool_array_to_int_msb, + _bool_array_to_int_lsb, _get_digital_data, _get_expected_data_for_line, _get_num_di_lines_in_task, - _get_waveform_bitstrings, _get_waveform_data, + _get_waveform_port_data, _read_and_copy, _validate_waveform_signals, ) @@ -59,7 +59,7 @@ def test___digital_single_channel_reader___read_one_sample_multi_line___returns_ _read_and_copy(reader.read_one_sample_multi_line, sample) for _ in range(samples_to_read) ] - assert [_bool_array_to_int_msb(sample) for sample in data] == _get_digital_data( + assert [_bool_array_to_int_lsb(sample) for sample in data] == _get_digital_data( num_lines, samples_to_read ) @@ -251,7 +251,7 @@ def test___digital_single_channel_multi_line_reader___read_waveform___returns_va assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name - _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) + _validate_waveform_signals(sim_6363_device, waveform, [7, 6, 5, 4, 3, 2, 1, 0]) def test___digital_single_line_reader___read_waveform_no_args___returns_valid_waveform( @@ -288,7 +288,7 @@ def test___digital_single_channel_multi_line_reader___read_waveform_no_args___re assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name - _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)[::-1]) def test___digital_single_line_reader___read_waveform_in_place___returns_valid_waveform( @@ -323,7 +323,7 @@ def test___digital_single_channel_multi_line_reader___read_waveform_in_place___r assert _is_timestamp_close_to_now(waveform.timing.timestamp) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.channel_name == di_single_channel_multi_line_timing_task.di_channels[0].name - _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) + _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)[::-1]) def test___digital_single_line_reader___reuse_waveform_in_place___overwrites_data_timing_and_attributes( @@ -368,7 +368,7 @@ def _make_single_channel_multi_line_reader(lines_start, rate): task = generate_task() task.di_channels.add_di_chan( flatten_channel_string( - sim_6363_device.di_lines.channel_names[lines_start : lines_start + 4][::-1] + sim_6363_device.di_lines.channel_names[lines_start : lines_start + 4] ), line_grouping=LineGrouping.CHAN_FOR_ALL_LINES, ) @@ -385,16 +385,16 @@ def _make_single_channel_multi_line_reader(lines_start, rate): timestamp0 = waveform.timing.timestamp assert _get_waveform_data(waveform) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) - assert waveform.channel_name == f"{sim_6363_device.di_lines[3].name}..." - _validate_waveform_signals(sim_6363_device, waveform, range(0, 4)) + assert waveform.channel_name == f"{sim_6363_device.di_lines[0].name}..." + _validate_waveform_signals(sim_6363_device, waveform, [3, 2, 1, 0]) reader1.read_waveform(waveform, sample_count) timestamp1 = waveform.timing.timestamp assert _get_waveform_data(waveform) == [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) - assert waveform.channel_name == f"{sim_6363_device.di_lines[4].name}..." + assert waveform.channel_name == f"{sim_6363_device.di_lines[1].name}..." # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, range(1, 5)) + # _validate_waveform_signals(sim_6363_device, waveform, [4, 3, 2, 1]) assert timestamp1 > timestamp0 @@ -574,7 +574,7 @@ def test___digital_single_channel_port_uint32_reader___read_waveform___returns_v samples_read = reader.read_waveform(waveform, num_samples) assert samples_read == num_samples - assert _get_waveform_data(waveform) == _get_digital_data(num_lines, num_samples) + assert _get_waveform_port_data(waveform) == _get_digital_data(num_lines, num_samples) assert _is_timestamp_close_to_now(waveform.timing.timestamp) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 1000) assert waveform.timing.sample_interval_mode == SampleIntervalMode.REGULAR @@ -594,21 +594,21 @@ def test___digital_single_channel_lines_and_port___read_waveform___returns_valid samples_read = reader.read_waveform(waveform, samples_to_read) assert samples_read == samples_to_read - assert _get_waveform_bitstrings(waveform) == [ - "00000000000", - "00100000001", - "01000000010", - "01100000011", - "10000000100", - "10100000101", - "11000000110", - "11100000111", - "00000001000", - "00100001001", + assert _get_waveform_port_data(waveform) == [ + 0b00000000000, + 0b10000000001, + 0b01000000010, + 0b11000000011, + 0b00100000100, + 0b10100000101, + 0b01100000110, + 0b11100000111, + 0b00000001000, + 0b10000001001, ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name - _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2]) + _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 2, 1, 0]) @pytest.mark.parametrize( @@ -633,7 +633,7 @@ def test___digital_single_channel_multi_line_reader___read_waveform_all_dtypes__ assert samples_read == num_samples assert _get_waveform_data(waveform) == _get_digital_data(num_lines, num_samples) - _validate_waveform_signals(sim_6363_device, waveform, range(num_lines)) + _validate_waveform_signals(sim_6363_device, waveform, [7, 6, 5, 4, 3, 2, 1, 0]) def test___digital_single_line_reader___read_waveform_read_all_available___returns_valid_waveform( diff --git a/tests/component/task/test_task_read_waveform_di.py b/tests/component/task/test_task_read_waveform_di.py index 519b8e4d0..f17570918 100644 --- a/tests/component/task/test_task_read_waveform_di.py +++ b/tests/component/task/test_task_read_waveform_di.py @@ -7,8 +7,8 @@ from nidaqmx.constants import READ_ALL_AVAILABLE from tests.component._digital_utils import ( _get_expected_data_for_line, - _get_waveform_bitstrings, _get_waveform_data, + _get_waveform_port_data, _validate_waveform_signals, ) @@ -71,21 +71,21 @@ def test___digital_single_channel___read_waveform_lines_and_port___returns_valid waveform = di_single_chan_lines_and_port_task.read_waveform(samples_to_read) - assert _get_waveform_bitstrings(waveform) == [ - "00000000000", - "00100000001", - "01000000010", - "01100000011", - "10000000100", - "10100000101", - "11000000110", - "11100000111", - "00000001000", - "00100001001", + assert _get_waveform_port_data(waveform) == [ + 0b00000000000, + 0b10000000001, + 0b01000000010, + 0b11000000011, + 0b00100000100, + 0b10100000101, + 0b01100000110, + 0b11100000111, + 0b00000001000, + 0b10000001001, ] assert waveform.sample_count == samples_to_read assert waveform.channel_name == di_single_chan_lines_and_port_task.di_channels[0].name - _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2]) + _validate_waveform_signals(sim_6363_device, waveform, [32, 33, 34, 35, 36, 37, 38, 39, 2, 1, 0]) def test___digital_multi_channel___read_waveform___returns_valid_waveforms( @@ -174,10 +174,10 @@ def test___digital_multi_channel___read_waveform_different_lines___returns_valid _validate_waveform_signals(sim_6363_device, waveforms[0], [0]) assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert waveforms[1].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[1].name - _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [2, 1]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].channel_name == di_multi_chan_diff_lines_timing_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) + _validate_waveform_signals(sim_6363_device, waveforms[2], [6, 5, 4, 3]) def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_waveforms( @@ -199,12 +199,12 @@ def test___digital_multi_channel___read_waveform_lines_and_port___returns_valid_ assert _get_waveform_data(waveforms[1]) == [0, 0, 1, 1, 2, 2, 3, 3, 0, 0] assert waveforms[1].sample_count == samples_to_read assert waveforms[1].channel_name == di_multi_chan_lines_and_port_task.di_channels[1].name - _validate_waveform_signals(sim_6363_device, waveforms[1], [1, 2]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [2, 1]) assert _get_waveform_data(waveforms[2]) == [0, 0, 0, 0, 0, 0, 0, 0, 1, 1] assert waveforms[2].sample_count == samples_to_read assert waveforms[2].channel_name == di_multi_chan_lines_and_port_task.di_channels[2].name - _validate_waveform_signals(sim_6363_device, waveforms[2], range(3, 7)) - assert _get_waveform_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + _validate_waveform_signals(sim_6363_device, waveforms[2], [6, 5, 4, 3]) + assert _get_waveform_port_data(waveforms[3]) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] assert waveforms[3].sample_count == samples_to_read assert waveforms[3].channel_name == di_multi_chan_lines_and_port_task.di_channels[3].name _validate_waveform_signals(sim_6363_device, waveforms[3], range(32, 40)) From 622c48c7e201a176314efb6286466d368c8a19db Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Mon, 8 Dec 2025 16:08:14 -0600 Subject: [PATCH 07/12] update output tests --- .../stream_writers/test_digital_multi_channel_writer.py | 7 ++++--- .../stream_writers/test_digital_single_channel_writer.py | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/component/stream_writers/test_digital_multi_channel_writer.py b/tests/component/stream_writers/test_digital_multi_channel_writer.py index c5f136c9b..02355c9f5 100644 --- a/tests/component/stream_writers/test_digital_multi_channel_writer.py +++ b/tests/component/stream_writers/test_digital_multi_channel_writer.py @@ -24,6 +24,7 @@ _get_digital_port_data_sample_major, _get_num_do_lines_in_task, _get_waveform_data, + _get_waveform_port_data, _int_to_bool_array, _start_do_task, ) @@ -368,8 +369,8 @@ def test___digital_multi_channel_writer___write_waveforms_ports___outputs_match_ actual_value = di_multi_channel_port_loopback_task.read() assert actual_value[0] != actual_value[1] assert actual_value == [ - _get_waveform_data(waveforms[0])[-1], - _get_waveform_data(waveforms[1])[-1], + _get_waveform_port_data(waveforms[0])[-1], + _get_waveform_port_data(waveforms[1])[-1], ] @@ -394,7 +395,7 @@ def test___digital_multi_channel_writer___write_waveforms_port_and_lines___outpu assert samples_written == num_samples actual_value = di_multi_channel_port_and_lines_loopback_task.read() assert actual_value == [ - _get_waveform_data(waveforms[0])[-1], + _get_waveform_port_data(waveforms[0])[-1], _get_waveform_data(waveforms[1])[-1], ] diff --git a/tests/component/stream_writers/test_digital_single_channel_writer.py b/tests/component/stream_writers/test_digital_single_channel_writer.py index 446ae10ee..371b35741 100644 --- a/tests/component/stream_writers/test_digital_single_channel_writer.py +++ b/tests/component/stream_writers/test_digital_single_channel_writer.py @@ -17,6 +17,7 @@ _get_digital_data, _get_num_do_lines_in_task, _get_waveform_data, + _get_waveform_port_data, _int_to_bool_array, ) @@ -425,7 +426,7 @@ def test___digital_single_channel_writer___write_waveform_port_uint8___outputs_m actual_value = di_port1_loopback_task.read() assert samples_written == num_samples assert waveform.signal_count == num_lines - assert actual_value == _get_waveform_data(waveform)[i - 1] + assert actual_value == _get_waveform_port_data(waveform)[i - 1] def test___digital_single_channel_writer___write_waveform_port_uint32___outputs_match_final_values( @@ -447,4 +448,4 @@ def test___digital_single_channel_writer___write_waveform_port_uint32___outputs_ actual_value = di_port0_loopback_task.read() assert samples_written == num_samples assert waveform.signal_count == num_lines - assert actual_value == _get_waveform_data(waveform)[i - 1] + assert actual_value == _get_waveform_port_data(waveform)[i - 1] From 20f7544808e0ce59506d51b0e838a12f3f051ff6 Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Mon, 8 Dec 2025 16:10:28 -0600 Subject: [PATCH 08/12] import nidaqmx.system --- tests/component/_digital_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index 52130b0ae..c21b6ae56 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -10,6 +10,7 @@ from nitypes.waveform.typing import AnyDigitalState, TDigitalState import nidaqmx +import nidaqmx.system _D = TypeVar("_D", bound=numpy.generic) From 65c4afe431e30be99497b1030d9bdf4eb4c6f14b Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Wed, 10 Dec 2025 13:24:51 -0600 Subject: [PATCH 09/12] update task output tests --- tests/component/task/test_task_write_waveform_do.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/component/task/test_task_write_waveform_do.py b/tests/component/task/test_task_write_waveform_do.py index 6a738bb58..e1c5c5f3e 100644 --- a/tests/component/task/test_task_write_waveform_do.py +++ b/tests/component/task/test_task_write_waveform_do.py @@ -14,6 +14,7 @@ _create_waveforms_for_mixed_lines, _get_digital_data, _get_waveform_data, + _get_waveform_port_data, ) @@ -278,7 +279,7 @@ def test___task___write_waveform_port_uint8___outputs_match_final_values( assert samples_written == num_samples actual_value = di_port1_loopback_task.read() - assert actual_value == _get_waveform_data(waveform)[i - 1] + assert actual_value == _get_waveform_port_data(waveform)[i - 1] def test___task___write_waveform_port_uint32___outputs_match_final_values( @@ -297,7 +298,7 @@ def test___task___write_waveform_port_uint32___outputs_match_final_values( assert samples_written == num_samples actual_value = di_port0_loopback_task.read() - assert actual_value == _get_waveform_data(waveform)[i - 1] + assert actual_value == _get_waveform_port_data(waveform)[i - 1] @pytest.mark.disable_feature_toggle(WAVEFORM_SUPPORT) @@ -412,8 +413,8 @@ def test___task___write_waveforms_ports___outputs_match_final_values( actual_value = di_multi_channel_port_loopback_task.read() assert actual_value[0] != actual_value[1] assert actual_value == [ - _get_waveform_data(waveforms[0])[-1], - _get_waveform_data(waveforms[1])[-1], + _get_waveform_port_data(waveforms[0])[-1], + _get_waveform_port_data(waveforms[1])[-1], ] @@ -437,7 +438,7 @@ def test___task___write_waveforms_port_and_lines___outputs_match_final_values( assert samples_written == num_samples actual_value = di_multi_channel_port_and_lines_loopback_task.read() assert actual_value == [ - _get_waveform_data(waveforms[0])[-1], + _get_waveform_port_data(waveforms[0])[-1], _get_waveform_data(waveforms[1])[-1], ] From baed5c512e122a598af57cf06d483a924a1a6d6a Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Wed, 10 Dec 2025 16:09:49 -0600 Subject: [PATCH 10/12] update to latest nitypes and remove all TODO: AB#3178052 --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- tests/component/_digital_utils.py | 4 +--- .../test_digital_multi_channel_reader.py | 15 +++++---------- .../test_digital_single_channel_reader.py | 12 ++++-------- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6e8e8b840..ab1886630 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -2348,14 +2348,14 @@ toml = ">=0.10.1" [[package]] name = "nitypes" -version = "1.0.0" +version = "1.1.0.dev1" description = "Data types for NI Python APIs" optional = false python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "nitypes-1.0.0-py3-none-any.whl", hash = "sha256:545dff978040fd92a68876023b8b6ff666c1d861ead1b3e7771108754bd57345"}, - {file = "nitypes-1.0.0.tar.gz", hash = "sha256:dc5ecb8b5f52570c2311daaa60ce6dca9712d7151236ef1f5314ad6ac02e0bdc"}, + {file = "nitypes-1.1.0.dev1-py3-none-any.whl", hash = "sha256:d98ad6e3f8b92db76b5c1c584431fa27d3e74cce6e20464e43ee0117b02fe089"}, + {file = "nitypes-1.1.0.dev1.tar.gz", hash = "sha256:50b23e00cc6960996656c4c9ef0ca71dd267fc5c9ca481077b682c29190aa2d3"}, ] [package.dependencies] @@ -4004,4 +4004,4 @@ grpc = ["grpcio", "ni-grpcdevice-v1-proto", "ni-protobuf-types", "protobuf"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "e9f6cc911b27ee31ef28a1a777ff8f7a2344f6ff511e9be21188f6148c9769a1" +content-hash = "efbcdf25a58172af2dcddc57ed74b5b012f85144f5c19a545966b4811e7306b2" diff --git a/pyproject.toml b/pyproject.toml index b69186fae..2166b3253 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,7 @@ click = ">=8.0.0" distro = { version = ">=1.9.0", platform = "linux" } requests = ">=2.25.0" typing_extensions = { version = ">=4.0.0" } -nitypes = {version=">=1.0.0"} +nitypes = {version=">=1.1.0.dev1"} [tool.poetry.group.codegen.dependencies] Mako = "^1.2" diff --git a/tests/component/_digital_utils.py b/tests/component/_digital_utils.py index c21b6ae56..423933319 100644 --- a/tests/component/_digital_utils.py +++ b/tests/component/_digital_utils.py @@ -240,9 +240,7 @@ def _validate_waveform_signals( waveform: DigitalWaveform[Any], lines: list[int] | range, # signal index to line index mapping ) -> None: - lines_list = list( - lines[::-1] - ) # TODO: AB#3178052 - remove reversal when signal/line ordering is fixed + lines_list = list(lines) signal_count = waveform.signal_count sample_count = waveform.sample_count assert signal_count == len(lines_list) diff --git a/tests/component/stream_readers/test_digital_multi_channel_reader.py b/tests/component/stream_readers/test_digital_multi_channel_reader.py index ae96a3806..5d25593e1 100644 --- a/tests/component/stream_readers/test_digital_multi_channel_reader.py +++ b/tests/component/stream_readers/test_digital_multi_channel_reader.py @@ -546,8 +546,7 @@ def _make_multi_channel_multi_line_reader(lines_start, rate): assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, chan + 1) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == sim_6363_device.di_lines[chan + 1].name - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, [chan + 1]) + _validate_waveform_signals(sim_6363_device, waveform, [chan + 1]) for ts0, ts1 in zip(timestamps0, timestamps1): assert ts1 > ts0 @@ -633,25 +632,21 @@ def _make_multi_channel_reader(chan_a_index, chan_b_index, samps_per_chan): reader1.read_waveforms(waveforms, 10) assert waveforms[0].sample_count == 10 assert _get_waveform_data(waveforms[0]) == _get_expected_data_for_line(10, 2) - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveforms[0], [2]) + _validate_waveform_signals(sim_6363_device, waveforms[0], [2]) assert waveforms[0].channel_name == f"{sim_6363_device.name}/port0/line2" assert waveforms[1].sample_count == 10 assert _get_waveform_data(waveforms[1]) == _get_expected_data_for_line(10, 3) - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveforms[1], [3]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [3]) assert waveforms[1].channel_name == f"{sim_6363_device.name}/port0/line3" reader2.read_waveforms(waveforms, 15) assert waveforms[0].sample_count == 15 assert _get_waveform_data(waveforms[0]) == _get_expected_data_for_line(15, 4) - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveforms[0], [4]) + _validate_waveform_signals(sim_6363_device, waveforms[0], [4]) assert waveforms[0].channel_name == f"{sim_6363_device.name}/port0/line4" assert waveforms[1].sample_count == 15 assert _get_waveform_data(waveforms[1]) == _get_expected_data_for_line(15, 5) - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveforms[1], [5]) + _validate_waveform_signals(sim_6363_device, waveforms[1], [5]) assert waveforms[1].channel_name == f"{sim_6363_device.name}/port0/line5" diff --git a/tests/component/stream_readers/test_digital_single_channel_reader.py b/tests/component/stream_readers/test_digital_single_channel_reader.py index 208c497c6..bdbc83faf 100644 --- a/tests/component/stream_readers/test_digital_single_channel_reader.py +++ b/tests/component/stream_readers/test_digital_single_channel_reader.py @@ -355,8 +355,7 @@ def _make_single_line_reader(chan_index, rate): assert _get_waveform_data(waveform) == _get_expected_data_for_line(sample_count, 1) assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == sim_6363_device.di_lines[1].name - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, [1]) + _validate_waveform_signals(sim_6363_device, waveform, [1]) assert timestamp1 > timestamp0 @@ -393,8 +392,7 @@ def _make_single_channel_multi_line_reader(lines_start, rate): assert _get_waveform_data(waveform) == [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] assert waveform.timing.sample_interval == ht_timedelta(seconds=1 / 2000) assert waveform.channel_name == f"{sim_6363_device.di_lines[1].name}..." - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, [4, 3, 2, 1]) + _validate_waveform_signals(sim_6363_device, waveform, [4, 3, 2, 1]) assert timestamp1 > timestamp0 @@ -462,15 +460,13 @@ def _make_single_channel_reader(chan_index, samps_per_chan): assert waveform.sample_count == 10 assert _get_waveform_data(waveform) == _get_expected_data_for_line(10, 1) assert waveform.channel_name == f"{sim_6363_device.name}/port0/line1" - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, [1]) + _validate_waveform_signals(sim_6363_device, waveform, [1]) reader2.read_waveform(waveform, 15) assert waveform.sample_count == 15 assert _get_waveform_data(waveform) == _get_expected_data_for_line(15, 2) assert waveform.channel_name == f"{sim_6363_device.name}/port0/line2" - # TODO: AB#3178052 - enable this check when the signal name caching issue is fixed - # _validate_waveform_signals(sim_6363_device, waveform, [2]) + _validate_waveform_signals(sim_6363_device, waveform, [2]) def test___digital_single_line_reader___read_waveform_high_sample_rate___returns_correct_sample_interval( From 3eb2b7fa2e08500f486a90d1d63e258fa0bc3996 Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Wed, 10 Dec 2025 16:52:03 -0600 Subject: [PATCH 11/12] poetry.lock hash --- poetry.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 78697988e..86a0e70f3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4121,4 +4121,4 @@ grpc = ["grpcio", "ni-grpcdevice-v1-proto", "ni-protobuf-types", "protobuf"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "f7d53512dc12a25658f1a2bb319e6f2c4fe1c2c037b19f7b6de53646f9f72ed8" +content-hash = "80db624a7860c7c0497305f8f9d2c685b6745075dc55ae030381d12157129d22" From e6b8fd69e080b6f1b368690ebe7738f600e69b1e Mon Sep 17 00:00:00 2001 From: Mike Prosser Date: Thu, 11 Dec 2025 09:34:02 -0600 Subject: [PATCH 12/12] Poetry 2.1.4 --- poetry.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 86a0e70f3..4518cc663 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "alabaster"