From 4eb862408081a48bf127a0eb251266592c1cf9c2 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Wed, 7 Oct 2026 19:45:14 +0530 Subject: [PATCH 1/9] Add @Avinash2Suresh as a code owner --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 17a4e6de4d..dac883d426 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @marcoskirsch @ni-jfitzger @vnktshr21 +* @marcoskirsch @ni-jfitzger @vnktshr21 @Avinash2Suresh From 8305ba26e923b280a766b480f52f77b1170c6fcd Mon Sep 17 00:00:00 2001 From: Divakar Date: Thu, 8 Oct 2026 16:17:45 +0530 Subject: [PATCH 2/9] Remove @Avinash2Suresh from CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dac883d426..17a4e6de4d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @marcoskirsch @ni-jfitzger @vnktshr21 @Avinash2Suresh +* @marcoskirsch @ni-jfitzger @vnktshr21 From 060842c3f158561e87941bf6c0e26e50d66dbd1e Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Tue, 20 Oct 2026 23:30:59 +0530 Subject: [PATCH 3/9] add: add Max DC Reading Rate at 7.5 Digits example --- CHANGELOG.md | 1 + build/templates/tox-system_tests.ini.mako | 3 + docs/nidmm/examples.rst | 9 ++ generated/nidmm/tox-system_tests.ini | 1 + ...nidmm_max_dc_reading_rate_at_7_5_digits.py | 101 ++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a8d9eb38..c90a762b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -799,6 +799,7 @@ #### [nidmm] Unreleased - Added - Added the `nidmm_measure_ac_volts.py` example. + - Added the `nidmm_max_dc_reading_rate_at_7_5_digits.py` example. - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. - Changed - Removed diff --git a/build/templates/tox-system_tests.ini.mako b/build/templates/tox-system_tests.ini.mako index c2b3d9131d..41e42c05b6 100644 --- a/build/templates/tox-system_tests.ini.mako +++ b/build/templates/tox-system_tests.ini.mako @@ -76,6 +76,9 @@ deps = % endif % if module_name == 'nidigital': ${module_name}-system_tests: nisync +% endif +% if module_name == 'nidmm': + ${module_name}-system_tests: matplotlib; sys_platform != "win32" % endif ${module_name}-system_tests: pytest ${module_name}-system_tests: coverage diff --git a/docs/nidmm/examples.rst b/docs/nidmm/examples.rst index ec6b3ee3e4..1d4f551340 100644 --- a/docs/nidmm/examples.rst +++ b/docs/nidmm/examples.rst @@ -12,6 +12,15 @@ nidmm_fetch_waveform.py :encoding: utf8 :caption: `(nidmm_fetch_waveform.py) `_ +nidmm_max_dc_reading_rate_at_7_5_digits.py +------------------------------------------ + +.. literalinclude:: ../../src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py + :language: python + :linenos: + :encoding: utf8 + :caption: `(nidmm_max_dc_reading_rate_at_7_5_digits.py) `_ + nidmm_measure_ac_volts.py ------------------------- diff --git a/generated/nidmm/tox-system_tests.ini b/generated/nidmm/tox-system_tests.ini index 7d155899ac..807c05d20d 100644 --- a/generated/nidmm/tox-system_tests.ini +++ b/generated/nidmm/tox-system_tests.ini @@ -32,6 +32,7 @@ commands = nidmm-coverage: coverage report --rcfile=../../tools/coverage_system_tests.rc deps = + nidmm-system_tests: matplotlib; sys_platform != "win32" nidmm-system_tests: pytest nidmm-system_tests: coverage nidmm-system_tests: numpy diff --git a/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py new file mode 100644 index 0000000000..d73869cd6f --- /dev/null +++ b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py @@ -0,0 +1,101 @@ +#!/usr/bin/python + +import argparse +import collections +import nidmm +import sys +import time + +import pytest + + +# adc_calibration and number_of_averages are documented for the NI 4070/4071/4072 only (nidmm.readthedocs.io) +SUPPORTED_MODELS = ('4071', '4081') + +CHART_HISTORY_SIZE = 2048 + + +def example(device_name, options, powerline_frequency, measurement_range, aperture_time, adc_calibration, auto_zero, number_of_averages, total_samples): + # Imported lazily because matplotlib is unavailable on some platforms (e.g. 32-bit Python) + import matplotlib.pyplot as plt + + with nidmm.Session(resource_name=device_name, reset_device=True, options=options) as session: + if not session.instrument_model.endswith(SUPPORTED_MODELS): + raise ValueError(f'{session.instrument_model} is not supported. This example requires an NI PXI-4071 or NI PXIe-4081.') + + # Timebase for the aperture time in PLCs + session.powerline_freq = powerline_frequency + session.configure_measurement_digits(measurement_function=nidmm.Function.DC_VOLTS, range=measurement_range, resolution_digits=7.5) + # A sample_count of 0 configures a continuous acquisition + session.configure_multi_point(trigger_count=1, sample_count=0) + # Averaging applies only with a fixed aperture and Auto Zero ON + session.aperture_time_units = nidmm.ApertureTimeUnits.POWER_LINE_CYCLES + session.aperture_time = aperture_time + session.number_of_averages = number_of_averages + session.auto_zero = nidmm.AutoZero[auto_zero] + # OFF skips the gain-reference measurement, which raises the reading rate + session.adc_calibration = nidmm.ADCCalibration[adc_calibration] + + measurements = collections.deque(maxlen=CHART_HISTORY_SIZE) + samples_fetched = 0 + figure = plt.figure() + start_time = time.perf_counter() + try: + with session.initiate(): + # Closing the chart window stops the acquisition, like the STOP button in the LabVIEW example + while plt.fignum_exists(figure.number) and (total_samples is None or samples_fetched < total_samples): + # Fetch only what is already acquired, so the chart stays responsive + backlog, _ = session.read_status() + if total_samples is not None: + backlog = min(backlog, total_samples - samples_fetched) + if backlog > 0: + measurements.extend(session.fetch_multi_point(array_size=backlog)) + samples_fetched += backlog + plt.cla() + plt.plot(measurements) + plt.title(f'Reads/sec: {samples_fetched / (time.perf_counter() - start_time):.0f}') + plt.pause(0.001) + + if total_samples is not None and plt.fignum_exists(figure.number): + plt.show() + except KeyboardInterrupt: + pass + finally: + plt.close(figure) + + +def _main(argsv): + parser = argparse.ArgumentParser(description='Achieves the higher DC voltage reading rate at 7.5 digits of resolution with a PXI-4071 or PXIe-4081 and charts the readings.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--device-name', default='PXI1Slot2', help='Contains the resource_name of the device to initialize.') + parser.add_argument('-p', '--powerline-frequency', default=60.0, type=float, choices=[50.0, 60.0], help='Specifies the powerline frequency.') + parser.add_argument('-r', '--range', default=10.0, type=float, help='Specifies the range for the function specified in the Measurement_Function parameter.') + parser.add_argument('-a', '--aperture-time', default=1.0, type=float, help='Specifies the measurement aperture time for the current configuration, in powerline cycles (PLCs).') + parser.add_argument('-c', '--adc-calibration', default='OFF', choices=nidmm.ADCCalibration.__members__.keys(), type=str.upper, help='Specifies the ADC calibration mode.') + parser.add_argument('-z', '--auto-zero', default='ON', choices=nidmm.AutoZero.__members__.keys(), type=str.upper, help='Specifies the AutoZero mode.') + parser.add_argument('-v', '--number-of-averages', default=4, type=int, help='Specifies the number of averages to perform in a measurement.') + parser.add_argument('--total-samples', default=None, type=int, help='Stops fetching after this many samples and keeps the chart open until its window is closed; omit to run until the chart window is closed.') + parser.add_argument('-op', '--option-string', default='', type=str, help='Sets the initial value of certain attributes for the session.') + args = parser.parse_args(argsv) + example(args.device_name, args.option_string, args.powerline_frequency, args.range, args.aperture_time, args.adc_calibration, args.auto_zero, args.number_of_averages, args.total_samples) + + +def main(): + _main(sys.argv[1:]) + + +def test_example(): + plt = pytest.importorskip('matplotlib.pyplot') + plt.switch_backend('Agg') # Avoid opening a chart window during the test + options = {'simulate': True, 'driver_setup': {'Model': '4081', 'BoardType': 'PXIe', }, } + example('PXI1Slot2', options, 60.0, 10.0, 1.0, 'OFF', 'ON', 4, 100) + + +def test_main(): + plt = pytest.importorskip('matplotlib.pyplot') + plt.switch_backend('Agg') # Avoid opening a chart window during the test + cmd_line = ['--option-string', 'Simulate=1, DriverSetup=Model:4081; BoardType:PXIe', '--total-samples', '100', ] + _main(cmd_line) + + +if __name__ == '__main__': + main() From eacc6d0b24f9eddc5ad01b75e513ecf34b80ad67 Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Tue, 20 Oct 2026 23:54:02 +0530 Subject: [PATCH 4/9] Trigger CI build From 09025cd6b0a2970a64a65bf77dffce021ad73572 Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Wed, 21 Oct 2026 12:35:51 +0530 Subject: [PATCH 5/9] Refine nidmm 7.5 digit reading rate example --- ...nidmm_max_dc_reading_rate_at_7_5_digits.py | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py index d73869cd6f..1b2c55eb19 100644 --- a/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py +++ b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py @@ -3,16 +3,37 @@ import argparse import collections import nidmm +import pytest import sys import time -import pytest - -# adc_calibration and number_of_averages are documented for the NI 4070/4071/4072 only (nidmm.readthedocs.io) SUPPORTED_MODELS = ('4071', '4081') -CHART_HISTORY_SIZE = 2048 +CHART_HISTORY_SIZE = 250 + + +def _create_chart(plt): + figure, axes = plt.subplots() + (line,) = axes.plot([]) + axes.set_xlabel('Sample Number') + axes.set_ylabel('Reading Value') + axes.grid(True) + return figure, axes, line + + +def _update_chart(plt, figure, axes, line, measurements, new_samples, samples_fetched, reads_per_sec): + measurements.extend(new_samples) + samples_fetched += len(new_samples) + if new_samples: + # Offset X values to account for readings removed from the history buffer + first_sample = samples_fetched - len(measurements) + line.set_data(range(first_sample, samples_fetched), measurements) + axes.set_title(f'Reads/sec: {reads_per_sec:.0f}') + axes.relim() + axes.autoscale_view() + plt.pause(0.001) + return samples_fetched, plt.fignum_exists(figure.number) def example(device_name, options, powerline_frequency, measurement_range, aperture_time, adc_calibration, auto_zero, number_of_averages, total_samples): @@ -23,39 +44,36 @@ def example(device_name, options, powerline_frequency, measurement_range, apertu if not session.instrument_model.endswith(SUPPORTED_MODELS): raise ValueError(f'{session.instrument_model} is not supported. This example requires an NI PXI-4071 or NI PXIe-4081.') - # Timebase for the aperture time in PLCs + # Powerline frequency defines the timebase for aperture values in PLCs. session.powerline_freq = powerline_frequency session.configure_measurement_digits(measurement_function=nidmm.Function.DC_VOLTS, range=measurement_range, resolution_digits=7.5) - # A sample_count of 0 configures a continuous acquisition + # A sample count of zero selects continuous acquisition. session.configure_multi_point(trigger_count=1, sample_count=0) - # Averaging applies only with a fixed aperture and Auto Zero ON session.aperture_time_units = nidmm.ApertureTimeUnits.POWER_LINE_CYCLES session.aperture_time = aperture_time session.number_of_averages = number_of_averages session.auto_zero = nidmm.AutoZero[auto_zero] - # OFF skips the gain-reference measurement, which raises the reading rate + # Disabling ADC calibration avoids the gain-reference measurement and increases reading rate. session.adc_calibration = nidmm.ADCCalibration[adc_calibration] + figure, axes, line = _create_chart(plt) measurements = collections.deque(maxlen=CHART_HISTORY_SIZE) samples_fetched = 0 - figure = plt.figure() start_time = time.perf_counter() try: with session.initiate(): - # Closing the chart window stops the acquisition, like the STOP button in the LabVIEW example - while plt.fignum_exists(figure.number) and (total_samples is None or samples_fetched < total_samples): - # Fetch only what is already acquired, so the chart stays responsive + chart_open = True + while chart_open and (total_samples is None or samples_fetched < total_samples): backlog, _ = session.read_status() if total_samples is not None: backlog = min(backlog, total_samples - samples_fetched) - if backlog > 0: - measurements.extend(session.fetch_multi_point(array_size=backlog)) - samples_fetched += backlog - plt.cla() - plt.plot(measurements) - plt.title(f'Reads/sec: {samples_fetched / (time.perf_counter() - start_time):.0f}') - plt.pause(0.001) + new_samples = session.fetch_multi_point(array_size=backlog) if backlog > 0 else () + reads_per_sec = (samples_fetched + len(new_samples)) / (time.perf_counter() - start_time) + samples_fetched, chart_open = _update_chart( + plt, figure, axes, line, measurements, new_samples, samples_fetched, reads_per_sec, + ) + # The acquisition has stopped; keep the final chart on screen until its window is closed if total_samples is not None and plt.fignum_exists(figure.number): plt.show() except KeyboardInterrupt: From c9a813b31e505e3818ce4472888ccfc4452be7c2 Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Wed, 21 Oct 2026 12:48:12 +0530 Subject: [PATCH 6/9] Trigger CI build From 93e5cadef50c85ee3a9edf7f34a0567f0a1af84d Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Wed, 21 Oct 2026 16:59:17 +0530 Subject: [PATCH 7/9] Trigger CI build From 817ace3d99fa588ac5fa1cdc4cdc191d9e627e10 Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Thu, 22 Oct 2026 23:29:02 +0530 Subject: [PATCH 8/9] Fix sample guard in 7.5-digit example Move sample-dependent updates inside the new_samples guard. --- src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py index 1b2c55eb19..7a4fbedf37 100644 --- a/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py +++ b/src/nidmm/examples/nidmm_max_dc_reading_rate_at_7_5_digits.py @@ -23,9 +23,9 @@ def _create_chart(plt): def _update_chart(plt, figure, axes, line, measurements, new_samples, samples_fetched, reads_per_sec): - measurements.extend(new_samples) - samples_fetched += len(new_samples) if new_samples: + measurements.extend(new_samples) + samples_fetched += len(new_samples) # Offset X values to account for readings removed from the history buffer first_sample = samples_fetched - len(measurements) line.set_data(range(first_sample, samples_fetched), measurements) From 92620172492a93733cbc48e87e112a6b2cbce43e Mon Sep 17 00:00:00 2001 From: "Selvam, Divakar" Date: Mon, 26 Oct 2026 17:43:59 +0530 Subject: [PATCH 9/9] Regenerate nirfsa enum documentation --- docs/nirfsa/enums.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/nirfsa/enums.rst b/docs/nirfsa/enums.rst index d365d2a06d..830ea32c0f 100644 --- a/docs/nirfsa/enums.rst +++ b/docs/nirfsa/enums.rst @@ -667,6 +667,7 @@ DownconverterPreselectorEnabled Disables the preselector. +