From 119c95dfbf48c45aba1dd4ce528abbea5c7cc09e Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 22 Oct 2026 13:05:53 +0000 Subject: [PATCH 01/13] Adding Digital Filtering in NI-Scope --- CHANGELOG.md | 1 + build/templates/tox-system_tests.ini.mako | 3 + docs/niscope/examples.rst | 9 ++ generated/niscope/tox-system_tests.ini | 1 + .../examples/niscope_digital_filtering.py | 145 ++++++++++++++++++ 5 files changed, 159 insertions(+) create mode 100644 src/niscope/examples/niscope_digital_filtering.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a8d9eb38..6b36767dc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1895,6 +1895,7 @@ #### [niscope] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. + - Added the `niscope_digital_filtering.py` example. - Changed - Removed diff --git a/build/templates/tox-system_tests.ini.mako b/build/templates/tox-system_tests.ini.mako index c2b3d9131d..9c7f07cb3e 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 == 'niscope': + ${module_name}-system_tests: matplotlib; sys_platform != "win32" % endif ${module_name}-system_tests: pytest ${module_name}-system_tests: coverage diff --git a/docs/niscope/examples.rst b/docs/niscope/examples.rst index 71f84c469c..68b5402487 100644 --- a/docs/niscope/examples.rst +++ b/docs/niscope/examples.rst @@ -3,6 +3,15 @@ Examples `You can download all niscope examples for latest version here `_ +niscope_digital_filtering.py +---------------------------- + +.. literalinclude:: ../../src/niscope/examples/niscope_digital_filtering.py + :language: python + :linenos: + :encoding: utf8 + :caption: `(niscope_digital_filtering.py) `_ + niscope_fetch.py ---------------- diff --git a/generated/niscope/tox-system_tests.ini b/generated/niscope/tox-system_tests.ini index 2f232d27ab..afadc34815 100644 --- a/generated/niscope/tox-system_tests.ini +++ b/generated/niscope/tox-system_tests.ini @@ -39,6 +39,7 @@ commands = deps = niscope-wheel_dep: build + niscope-system_tests: matplotlib; sys_platform != "win32" niscope-system_tests: pytest niscope-system_tests: coverage niscope-system_tests: numpy diff --git a/src/niscope/examples/niscope_digital_filtering.py b/src/niscope/examples/niscope_digital_filtering.py new file mode 100644 index 0000000000..241a08da08 --- /dev/null +++ b/src/niscope/examples/niscope_digital_filtering.py @@ -0,0 +1,145 @@ +#!/usr/bin/python + +import argparse +import niscope +import pytest +import sys + +FILTERS = { + 'NONE': niscope.ArrayMeasurement.NO_MEASUREMENT, + 'FIR': niscope.ArrayMeasurement.WINDOWED_FIR_FILTER, + 'BESSEL': niscope.ArrayMeasurement.BESSEL_FILTER, + 'BUTTERWORTH': niscope.ArrayMeasurement.BUTTERWORTH_FILTER, + 'CHEBYSHEV': niscope.ArrayMeasurement.CHEBYSHEV_FILTER, +} +FFT_FUNCTIONS = { + 'VOLTS_RMS': niscope.ArrayMeasurement.FFT_AMP_SPECTRUM_VOLTS_RMS, + 'DB': niscope.ArrayMeasurement.FFT_AMP_SPECTRUM_DB, +} + + +def _create_chart(plt): + figure, (waveform_axes, spectrum_axes) = plt.subplots(2, 1) + (waveform_line,) = waveform_axes.plot([]) + (spectrum_line,) = spectrum_axes.plot([]) + waveform_axes.set_title('Filtered Waveform') + waveform_axes.set_xlabel('Time (s)') + waveform_axes.set_ylabel('Amplitude') + spectrum_axes.set_title('Spectrum') + spectrum_axes.set_xlabel('Frequency (Hz)') + spectrum_axes.set_ylabel('Amplitude') + for axes in (waveform_axes, spectrum_axes): + axes.grid(True) + figure.tight_layout() + return figure, waveform_axes, waveform_line, spectrum_axes, spectrum_line + + +def _update_chart(waveform_axes, waveform_line, filtered, spectrum_axes, spectrum_line, spectrum): + for axes, line, waveforms in ((waveform_axes, waveform_line, filtered), (spectrum_axes, spectrum_line, spectrum)): + for waveform in waveforms: + x = [waveform.relative_initial_x + i * waveform.x_increment for i in range(len(waveform.samples))] + line.set_data(x, waveform.samples) + axes.relim() + axes.autoscale_view() + + +def example( + resource_name, channels, options, min_sample_rate, min_record_length, + filter_name, filter_type, cutoff_frequency, center_frequency, width, + fir_taps, fir_window, iir_order, fft_function, total_iterations, +): + # Imported lazily because matplotlib is unavailable on some platforms (e.g. 32-bit Python) + import matplotlib.pyplot as plt + + with niscope.Session(resource_name=resource_name, options=options) as session: + session.configure_vertical(range=2.0, coupling=niscope.VerticalCoupling.DC) + session.configure_horizontal_timing(min_sample_rate=min_sample_rate, min_num_pts=min_record_length, ref_position=50.0, num_records=1, enforce_realtime=True) + + channel_session = session.channels[channels] + channel_session.meas_filter_type = niscope.FilterType[filter_type] + channel_session.meas_filter_cutoff_freq = cutoff_frequency + channel_session.meas_filter_center_freq = center_frequency + channel_session.meas_filter_width = width + channel_session.meas_filter_taps = fir_taps + channel_session.meas_fir_filter_window = niscope.FIRFilterWindow[fir_window] + channel_session.meas_filter_order = iir_order + channel_session.meas_filter_transient_waveform_percent = 20.0 + channel_session.meas_filter_ripple = 0.5 + + figure, waveform_axes, waveform_line, spectrum_axes, spectrum_line = _create_chart(plt) + + iterations = 0 + try: + # A total_iterations of None runs until the chart window is closed or Ctrl+C is pressed + while plt.fignum_exists(figure.number) and (total_iterations is None or iterations < total_iterations): + # The filter runs as a processing step before any other measurement; it is added and cleared on every acquisition + channel_session.add_waveform_processing(FILTERS[filter_name]) + try: + with session.initiate(): + filtered = channel_session.fetch_array_measurement(niscope.ArrayMeasurement.NO_MEASUREMENT) + spectrum = channel_session.fetch_array_measurement(FFT_FUNCTIONS[fft_function]) + finally: + channel_session.clear_waveform_processing() + + _update_chart(waveform_axes, waveform_line, filtered, spectrum_axes, spectrum_line, spectrum) + iterations += 1 + plt.pause(0.02) + + # The acquisition has stopped; keep the final chart on screen until its window is closed + if total_iterations 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='Continuously applies a digital filter to acquired waveforms and plots the filtered waveform and its FFT amplitude spectrum.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='PXI1Slot3', help='Specifies the resource name of the device to initialize.') + parser.add_argument('-c', '--channels', default='0', help='Channel to plot') + parser.add_argument('-sr', '--min-sample-rate', default=10000000.0, type=float, help='Specify the sampling rate for the acquisition in Samples per second.') + parser.add_argument('-l', '--min-record-length', default=4096, type=int, help='Specifies the minimum number of points you require in the waveform record for each channel.') + parser.add_argument('-f', '--filter', default='CHEBYSHEV', choices=FILTERS.keys(), type=str.upper, help='Filter to apply') + parser.add_argument('-ft', '--filter-type', default='LOWPASS', choices=niscope.FilterType.__members__.keys(), type=str.upper, help='Specifies the type of filter, for both IIR and FIR filters.') + parser.add_argument('-cf', '--cutoff-frequency', default=2500000.0, type=float, help='Specifies the cutoff frequency in hertz for filters of type lowpass and highpass.') + parser.add_argument('-cc', '--center-frequency', default=500000.0, type=float, help='The center frequency in hertz for filters of type bandpass and bandstop.') + parser.add_argument('-w', '--width', default=100000.0, type=float, help='Specifies the width of bandpass and bandstop type filters in hertz.') + parser.add_argument('-t', '--fir-taps', default=25, type=int, help='Defines the number of taps (coefficients) for an FIR filter.') + parser.add_argument('-fw', '--fir-window', default='HANNING', choices=niscope.FIRFilterWindow.__members__.keys(), type=str.upper, help='Specifies the FIR window type.') + parser.add_argument('-o', '--iir-order', default=2, type=int, help='Specifies the order of an IIR filter.') + parser.add_argument('-fft', '--fft-function', default='DB', choices=FFT_FUNCTIONS.keys(), type=str.upper, help='FFT amplitude spectrum function') + parser.add_argument('--total-iterations', default=None, type=int, help='Stops after this many acquisitions and keeps the chart open until its window is closed; omit to run until the chart window is closed or Ctrl+C is pressed.') + parser.add_argument('-op', '--option-string', default='', type=str, help='Specifies initialization commands.') + args = parser.parse_args(argsv) + example( + args.resource_name, args.channels, args.option_string, args.min_sample_rate, args.min_record_length, + args.filter, args.filter_type, args.cutoff_frequency, args.center_frequency, args.width, + args.fir_taps, args.fir_window, args.iir_order, args.fft_function, args.total_iterations, + ) + + +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': '5164', 'BoardType': 'PXIe', }, } + example( + 'PXI1Slot2', '0', options, 10000000.0, 4096, + 'CHEBYSHEV', 'LOWPASS', 2500000.0, 500000.0, 100000.0, + 25, 'HANNING', 2, 'DB', 2, + ) + + +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:5164; BoardType:PXIe', '--total-iterations', '2', ] + _main(cmd_line) + + +if __name__ == '__main__': + main() From 45bc8264bc9834272b9235202667fe6133fb2bb9 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Fri, 23 Oct 2026 12:46:20 +0000 Subject: [PATCH 02/13] Fixing PR comments --- .../examples/niscope_digital_filtering.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/niscope/examples/niscope_digital_filtering.py b/src/niscope/examples/niscope_digital_filtering.py index 241a08da08..ee18b9f5ef 100644 --- a/src/niscope/examples/niscope_digital_filtering.py +++ b/src/niscope/examples/niscope_digital_filtering.py @@ -20,8 +20,6 @@ def _create_chart(plt): figure, (waveform_axes, spectrum_axes) = plt.subplots(2, 1) - (waveform_line,) = waveform_axes.plot([]) - (spectrum_line,) = spectrum_axes.plot([]) waveform_axes.set_title('Filtered Waveform') waveform_axes.set_xlabel('Time (s)') waveform_axes.set_ylabel('Amplitude') @@ -31,12 +29,17 @@ def _create_chart(plt): for axes in (waveform_axes, spectrum_axes): axes.grid(True) figure.tight_layout() - return figure, waveform_axes, waveform_line, spectrum_axes, spectrum_line + return figure, waveform_axes, spectrum_axes -def _update_chart(waveform_axes, waveform_line, filtered, spectrum_axes, spectrum_line, spectrum): - for axes, line, waveforms in ((waveform_axes, waveform_line, filtered), (spectrum_axes, spectrum_line, spectrum)): - for waveform in waveforms: +def _update_chart(waveform_axes, filtered, spectrum_axes, spectrum): + for axes, waveforms in ((waveform_axes, filtered), (spectrum_axes, spectrum)): + # One line per channel is created on the first acquisition and updated afterwards + if len(axes.lines) < len(waveforms): + while len(axes.lines) < len(waveforms): + axes.plot([], [], label=waveforms[len(axes.lines)].channel) + axes.legend(loc='upper right') + for line, waveform in zip(axes.lines, waveforms): x = [waveform.relative_initial_x + i * waveform.x_increment for i in range(len(waveform.samples))] line.set_data(x, waveform.samples) axes.relim() @@ -66,7 +69,7 @@ def example( channel_session.meas_filter_transient_waveform_percent = 20.0 channel_session.meas_filter_ripple = 0.5 - figure, waveform_axes, waveform_line, spectrum_axes, spectrum_line = _create_chart(plt) + figure, waveform_axes, spectrum_axes = _create_chart(plt) iterations = 0 try: @@ -81,7 +84,7 @@ def example( finally: channel_session.clear_waveform_processing() - _update_chart(waveform_axes, waveform_line, filtered, spectrum_axes, spectrum_line, spectrum) + _update_chart(waveform_axes, filtered, spectrum_axes, spectrum) iterations += 1 plt.pause(0.02) @@ -97,10 +100,11 @@ def example( def _main(argsv): parser = argparse.ArgumentParser(description='Continuously applies a digital filter to acquired waveforms and plots the filtered waveform and its FFT amplitude spectrum.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('-n', '--resource-name', default='PXI1Slot3', help='Specifies the resource name of the device to initialize.') - parser.add_argument('-c', '--channels', default='0', help='Channel to plot') - parser.add_argument('-sr', '--min-sample-rate', default=10000000.0, type=float, help='Specify the sampling rate for the acquisition in Samples per second.') + parser.add_argument('-c', '--channels', default='0', help='Comma-separated list of channels to plot, one line per channel') parser.add_argument('-l', '--min-record-length', default=4096, type=int, help='Specifies the minimum number of points you require in the waveform record for each channel.') + parser.add_argument('-sr', '--min-sample-rate', default=10000000.0, type=float, help='Specify the sampling rate for the acquisition in Samples per second.') parser.add_argument('-f', '--filter', default='CHEBYSHEV', choices=FILTERS.keys(), type=str.upper, help='Filter to apply') + parser.add_argument('-fft', '--fft-function', default='DB', choices=FFT_FUNCTIONS.keys(), type=str.upper, help='FFT amplitude spectrum function') parser.add_argument('-ft', '--filter-type', default='LOWPASS', choices=niscope.FilterType.__members__.keys(), type=str.upper, help='Specifies the type of filter, for both IIR and FIR filters.') parser.add_argument('-cf', '--cutoff-frequency', default=2500000.0, type=float, help='Specifies the cutoff frequency in hertz for filters of type lowpass and highpass.') parser.add_argument('-cc', '--center-frequency', default=500000.0, type=float, help='The center frequency in hertz for filters of type bandpass and bandstop.') @@ -108,7 +112,6 @@ def _main(argsv): parser.add_argument('-t', '--fir-taps', default=25, type=int, help='Defines the number of taps (coefficients) for an FIR filter.') parser.add_argument('-fw', '--fir-window', default='HANNING', choices=niscope.FIRFilterWindow.__members__.keys(), type=str.upper, help='Specifies the FIR window type.') parser.add_argument('-o', '--iir-order', default=2, type=int, help='Specifies the order of an IIR filter.') - parser.add_argument('-fft', '--fft-function', default='DB', choices=FFT_FUNCTIONS.keys(), type=str.upper, help='FFT amplitude spectrum function') parser.add_argument('--total-iterations', default=None, type=int, help='Stops after this many acquisitions and keeps the chart open until its window is closed; omit to run until the chart window is closed or Ctrl+C is pressed.') parser.add_argument('-op', '--option-string', default='', type=str, help='Specifies initialization commands.') args = parser.parse_args(argsv) From 6cbab9f654b7584bb4fadd524bce9dd874634bb3 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 05:19:11 +0000 Subject: [PATCH 03/13] Trigger CI build From 005888be6f93f29ed3e0d8e1b6c7549ebdc74338 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 07:02:14 +0000 Subject: [PATCH 04/13] Updating the graph label and order --- src/niscope/examples/niscope_digital_filtering.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/niscope/examples/niscope_digital_filtering.py b/src/niscope/examples/niscope_digital_filtering.py index ee18b9f5ef..1d9f4f9323 100644 --- a/src/niscope/examples/niscope_digital_filtering.py +++ b/src/niscope/examples/niscope_digital_filtering.py @@ -19,13 +19,13 @@ def _create_chart(plt): - figure, (waveform_axes, spectrum_axes) = plt.subplots(2, 1) - waveform_axes.set_title('Filtered Waveform') - waveform_axes.set_xlabel('Time (s)') - waveform_axes.set_ylabel('Amplitude') + figure, (spectrum_axes, waveform_axes) = plt.subplots(2, 1) spectrum_axes.set_title('Spectrum') spectrum_axes.set_xlabel('Frequency (Hz)') - spectrum_axes.set_ylabel('Amplitude') + spectrum_axes.set_ylabel('Amplitude (dB)') + waveform_axes.set_title('Filtered Waveform') + waveform_axes.set_xlabel('Time (s)') + waveform_axes.set_ylabel('Amplitude (V)') for axes in (waveform_axes, spectrum_axes): axes.grid(True) figure.tight_layout() From 33f169020a15be94f96d2b1ad5de097735d44e40 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 07:14:10 +0000 Subject: [PATCH 05/13] Trigger CI build From 31cef6d7b5ab2cdb4b7b945093317d64b5529909 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 09:05:08 +0000 Subject: [PATCH 06/13] Trigger CI build From b1831f44a4301eca856b55692bf7e3ad9ae0bfb6 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 10:12:40 +0000 Subject: [PATCH 07/13] Trigger CI build From f09fa96255c3ff98f9ccea6232259711c8661a15 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 26 Oct 2026 12:36:45 +0000 Subject: [PATCH 08/13] Trigger CI build From 32c678915d47dd906d0b96a58963a8d6ebb27ca9 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 2 Nov 2026 11:24:31 +0000 Subject: [PATCH 09/13] Removed Graph plotting --- build/templates/tox-system_tests.ini.mako | 3 - generated/niscope/tox-system_tests.ini | 1 - .../examples/niscope_digital_filtering.py | 67 ++++--------------- 3 files changed, 12 insertions(+), 59 deletions(-) diff --git a/build/templates/tox-system_tests.ini.mako b/build/templates/tox-system_tests.ini.mako index 9c7f07cb3e..c2b3d9131d 100644 --- a/build/templates/tox-system_tests.ini.mako +++ b/build/templates/tox-system_tests.ini.mako @@ -76,9 +76,6 @@ deps = % endif % if module_name == 'nidigital': ${module_name}-system_tests: nisync -% endif -% if module_name == 'niscope': - ${module_name}-system_tests: matplotlib; sys_platform != "win32" % endif ${module_name}-system_tests: pytest ${module_name}-system_tests: coverage diff --git a/generated/niscope/tox-system_tests.ini b/generated/niscope/tox-system_tests.ini index afadc34815..2f232d27ab 100644 --- a/generated/niscope/tox-system_tests.ini +++ b/generated/niscope/tox-system_tests.ini @@ -39,7 +39,6 @@ commands = deps = niscope-wheel_dep: build - niscope-system_tests: matplotlib; sys_platform != "win32" niscope-system_tests: pytest niscope-system_tests: coverage niscope-system_tests: numpy diff --git a/src/niscope/examples/niscope_digital_filtering.py b/src/niscope/examples/niscope_digital_filtering.py index 1d9f4f9323..cb18d87b88 100644 --- a/src/niscope/examples/niscope_digital_filtering.py +++ b/src/niscope/examples/niscope_digital_filtering.py @@ -2,7 +2,6 @@ import argparse import niscope -import pytest import sys FILTERS = { @@ -18,42 +17,12 @@ } -def _create_chart(plt): - figure, (spectrum_axes, waveform_axes) = plt.subplots(2, 1) - spectrum_axes.set_title('Spectrum') - spectrum_axes.set_xlabel('Frequency (Hz)') - spectrum_axes.set_ylabel('Amplitude (dB)') - waveform_axes.set_title('Filtered Waveform') - waveform_axes.set_xlabel('Time (s)') - waveform_axes.set_ylabel('Amplitude (V)') - for axes in (waveform_axes, spectrum_axes): - axes.grid(True) - figure.tight_layout() - return figure, waveform_axes, spectrum_axes - - -def _update_chart(waveform_axes, filtered, spectrum_axes, spectrum): - for axes, waveforms in ((waveform_axes, filtered), (spectrum_axes, spectrum)): - # One line per channel is created on the first acquisition and updated afterwards - if len(axes.lines) < len(waveforms): - while len(axes.lines) < len(waveforms): - axes.plot([], [], label=waveforms[len(axes.lines)].channel) - axes.legend(loc='upper right') - for line, waveform in zip(axes.lines, waveforms): - x = [waveform.relative_initial_x + i * waveform.x_increment for i in range(len(waveform.samples))] - line.set_data(x, waveform.samples) - axes.relim() - axes.autoscale_view() - - def example( resource_name, channels, options, min_sample_rate, min_record_length, filter_name, filter_type, cutoff_frequency, center_frequency, width, fir_taps, fir_window, iir_order, fft_function, total_iterations, ): - # Imported lazily because matplotlib is unavailable on some platforms (e.g. 32-bit Python) - import matplotlib.pyplot as plt - + print(f'Starting acquisition on resource {resource_name}, for {total_iterations if total_iterations is not None else "continuous"} iterations.') with niscope.Session(resource_name=resource_name, options=options) as session: session.configure_vertical(range=2.0, coupling=niscope.VerticalCoupling.DC) session.configure_horizontal_timing(min_sample_rate=min_sample_rate, min_num_pts=min_record_length, ref_position=50.0, num_records=1, enforce_realtime=True) @@ -69,38 +38,29 @@ def example( channel_session.meas_filter_transient_waveform_percent = 20.0 channel_session.meas_filter_ripple = 0.5 - figure, waveform_axes, spectrum_axes = _create_chart(plt) - iterations = 0 try: - # A total_iterations of None runs until the chart window is closed or Ctrl+C is pressed - while plt.fignum_exists(figure.number) and (total_iterations is None or iterations < total_iterations): + # A total_iterations of None runs until Ctrl+C is pressed + while total_iterations is None or iterations < total_iterations: # The filter runs as a processing step before any other measurement; it is added and cleared on every acquisition channel_session.add_waveform_processing(FILTERS[filter_name]) try: with session.initiate(): - filtered = channel_session.fetch_array_measurement(niscope.ArrayMeasurement.NO_MEASUREMENT) - spectrum = channel_session.fetch_array_measurement(FFT_FUNCTIONS[fft_function]) + channel_session.fetch_array_measurement(niscope.ArrayMeasurement.NO_MEASUREMENT) + channel_session.fetch_array_measurement(FFT_FUNCTIONS[fft_function]) finally: channel_session.clear_waveform_processing() - - _update_chart(waveform_axes, filtered, spectrum_axes, spectrum) iterations += 1 - plt.pause(0.02) - - # The acquisition has stopped; keep the final chart on screen until its window is closed - if total_iterations is not None and plt.fignum_exists(figure.number): - plt.show() except KeyboardInterrupt: pass - finally: - plt.close(figure) + + print('Completed {} acquisitions.'.format(iterations)) def _main(argsv): - parser = argparse.ArgumentParser(description='Continuously applies a digital filter to acquired waveforms and plots the filtered waveform and its FFT amplitude spectrum.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser = argparse.ArgumentParser(description='Applies a digital filter to acquired waveforms and computes the filtered waveform and its FFT amplitude spectrum.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('-n', '--resource-name', default='PXI1Slot3', help='Specifies the resource name of the device to initialize.') - parser.add_argument('-c', '--channels', default='0', help='Comma-separated list of channels to plot, one line per channel') + parser.add_argument('-c', '--channels', default='0', help='Comma-separated list of channels to acquire') parser.add_argument('-l', '--min-record-length', default=4096, type=int, help='Specifies the minimum number of points you require in the waveform record for each channel.') parser.add_argument('-sr', '--min-sample-rate', default=10000000.0, type=float, help='Specify the sampling rate for the acquisition in Samples per second.') parser.add_argument('-f', '--filter', default='CHEBYSHEV', choices=FILTERS.keys(), type=str.upper, help='Filter to apply') @@ -112,13 +72,14 @@ def _main(argsv): parser.add_argument('-t', '--fir-taps', default=25, type=int, help='Defines the number of taps (coefficients) for an FIR filter.') parser.add_argument('-fw', '--fir-window', default='HANNING', choices=niscope.FIRFilterWindow.__members__.keys(), type=str.upper, help='Specifies the FIR window type.') parser.add_argument('-o', '--iir-order', default=2, type=int, help='Specifies the order of an IIR filter.') - parser.add_argument('--total-iterations', default=None, type=int, help='Stops after this many acquisitions and keeps the chart open until its window is closed; omit to run until the chart window is closed or Ctrl+C is pressed.') + parser.add_argument('--total-iterations', default=100, type=int, help='Number of acquisitions to perform before stopping.') + parser.add_argument('--continuous', action='store_true', help='Acquire until Ctrl+C is pressed; overrides --total-iterations.') parser.add_argument('-op', '--option-string', default='', type=str, help='Specifies initialization commands.') args = parser.parse_args(argsv) example( args.resource_name, args.channels, args.option_string, args.min_sample_rate, args.min_record_length, args.filter, args.filter_type, args.cutoff_frequency, args.center_frequency, args.width, - args.fir_taps, args.fir_window, args.iir_order, args.fft_function, args.total_iterations, + args.fir_taps, args.fir_window, args.iir_order, args.fft_function, None if args.continuous else args.total_iterations, ) @@ -127,8 +88,6 @@ def main(): 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': '5164', 'BoardType': 'PXIe', }, } example( 'PXI1Slot2', '0', options, 10000000.0, 4096, @@ -138,8 +97,6 @@ def test_example(): 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:5164; BoardType:PXIe', '--total-iterations', '2', ] _main(cmd_line) From 6260ae17dd9f6a4032d83104e4c4ca4420608601 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Mon, 2 Nov 2026 13:22:50 +0000 Subject: [PATCH 10/13] removing continuous option --- .../examples/niscope_digital_filtering.py | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/niscope/examples/niscope_digital_filtering.py b/src/niscope/examples/niscope_digital_filtering.py index cb18d87b88..54fa650860 100644 --- a/src/niscope/examples/niscope_digital_filtering.py +++ b/src/niscope/examples/niscope_digital_filtering.py @@ -22,7 +22,7 @@ def example( filter_name, filter_type, cutoff_frequency, center_frequency, width, fir_taps, fir_window, iir_order, fft_function, total_iterations, ): - print(f'Starting acquisition on resource {resource_name}, for {total_iterations if total_iterations is not None else "continuous"} iterations.') + print(f'Starting acquisition on resource {resource_name}, for {total_iterations} iterations.') with niscope.Session(resource_name=resource_name, options=options) as session: session.configure_vertical(range=2.0, coupling=niscope.VerticalCoupling.DC) session.configure_horizontal_timing(min_sample_rate=min_sample_rate, min_num_pts=min_record_length, ref_position=50.0, num_records=1, enforce_realtime=True) @@ -39,20 +39,16 @@ def example( channel_session.meas_filter_ripple = 0.5 iterations = 0 - try: - # A total_iterations of None runs until Ctrl+C is pressed - while total_iterations is None or iterations < total_iterations: - # The filter runs as a processing step before any other measurement; it is added and cleared on every acquisition - channel_session.add_waveform_processing(FILTERS[filter_name]) - try: - with session.initiate(): - channel_session.fetch_array_measurement(niscope.ArrayMeasurement.NO_MEASUREMENT) - channel_session.fetch_array_measurement(FFT_FUNCTIONS[fft_function]) - finally: - channel_session.clear_waveform_processing() - iterations += 1 - except KeyboardInterrupt: - pass + while iterations < total_iterations: + # The filter runs as a processing step before any other measurement; it is added and cleared on every acquisition + channel_session.add_waveform_processing(FILTERS[filter_name]) + try: + with session.initiate(): + channel_session.fetch_array_measurement(niscope.ArrayMeasurement.NO_MEASUREMENT) + channel_session.fetch_array_measurement(FFT_FUNCTIONS[fft_function]) + finally: + channel_session.clear_waveform_processing() + iterations += 1 print('Completed {} acquisitions.'.format(iterations)) @@ -73,13 +69,12 @@ def _main(argsv): parser.add_argument('-fw', '--fir-window', default='HANNING', choices=niscope.FIRFilterWindow.__members__.keys(), type=str.upper, help='Specifies the FIR window type.') parser.add_argument('-o', '--iir-order', default=2, type=int, help='Specifies the order of an IIR filter.') parser.add_argument('--total-iterations', default=100, type=int, help='Number of acquisitions to perform before stopping.') - parser.add_argument('--continuous', action='store_true', help='Acquire until Ctrl+C is pressed; overrides --total-iterations.') parser.add_argument('-op', '--option-string', default='', type=str, help='Specifies initialization commands.') args = parser.parse_args(argsv) example( args.resource_name, args.channels, args.option_string, args.min_sample_rate, args.min_record_length, args.filter, args.filter_type, args.cutoff_frequency, args.center_frequency, args.width, - args.fir_taps, args.fir_window, args.iir_order, args.fft_function, None if args.continuous else args.total_iterations, + args.fir_taps, args.fir_window, args.iir_order, args.fft_function, args.total_iterations, ) From 5ff15cc9e36b661b2d5a1e2b4883e79b02153f63 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 5 Nov 2026 15:45:42 +0000 Subject: [PATCH 11/13] Adding Source Waveform example in NI-Digital --- CHANGELOG.md | 1 + docs/nidigital/examples.rst | 9 ++ .../examples/source_waveform/Pattern.digipat | Bin 0 -> 5413 bytes .../source_waveform/PinLevels.digilevels | 15 +++ .../examples/source_waveform/PinMap.pinmap | 51 +++++++++ .../source_waveform/SourceWaveform.tdms | Bin 0 -> 1619 bytes .../source_waveform/Specifications.specs | 9 ++ .../source_waveform/Timing.digitiming | 23 ++++ .../nidigital_source_waveform.py | 100 ++++++++++++++++++ .../source_waveform/source_waveform.digiproj | 39 +++++++ 10 files changed, 247 insertions(+) create mode 100644 src/nidigital/examples/source_waveform/Pattern.digipat create mode 100644 src/nidigital/examples/source_waveform/PinLevels.digilevels create mode 100644 src/nidigital/examples/source_waveform/PinMap.pinmap create mode 100644 src/nidigital/examples/source_waveform/SourceWaveform.tdms create mode 100644 src/nidigital/examples/source_waveform/Specifications.specs create mode 100644 src/nidigital/examples/source_waveform/Timing.digitiming create mode 100644 src/nidigital/examples/source_waveform/nidigital_source_waveform.py create mode 100644 src/nidigital/examples/source_waveform/source_waveform.digiproj diff --git a/CHANGELOG.md b/CHANGELOG.md index 83d1d3267b..7fefe411b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -558,6 +558,7 @@ #### [nidigital] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. + - Added the `nidigital_source_waveform.py` example. - Changed - Removed diff --git a/docs/nidigital/examples.rst b/docs/nidigital/examples.rst index b8c8cc689a..303dcff661 100644 --- a/docs/nidigital/examples.rst +++ b/docs/nidigital/examples.rst @@ -30,3 +30,12 @@ nidigital_ppmu_source_and_measure.py :encoding: utf8 :caption: `(nidigital_ppmu_source_and_measure.py) `_ +nidigital_source_waveform.py +---------------------------- + +.. literalinclude:: ../../src/nidigital/examples/source_waveform/nidigital_source_waveform.py + :language: python + :linenos: + :encoding: utf8 + :caption: `(nidigital_source_waveform.py) `_ + diff --git a/src/nidigital/examples/source_waveform/Pattern.digipat b/src/nidigital/examples/source_waveform/Pattern.digipat new file mode 100644 index 0000000000000000000000000000000000000000..0ee9d4fef983edd6c923bfa0c4eeb74e1a9f9bf2 GIT binary patch literal 5413 zcmcgwTXP#V6y9(x<&uWN3^Ux6;bDhPr*2vb<=zk%aGTOh?KV7-S=(}~va2<+T(@uG zjTv6~A^Zz|Ryp79IgXsz9dCj;6XjdW(sw>dM@L$>>dow>D2mLRQPd`c39isHO6@7x z3-o|ulT0hZm#OR|-fL%HrN^!wcAOb_lUsZXdy$GaJ}sJ~0)CQ_@8?e8BUvl(ezB~I z1gE^?L+BkYtsd_UN(CX$W#$n)#&ez;Y~|U&q`JFneE)%VLz0aFk)02@J}&Db!DC#n zQ3LLOCwZ7Vkf70tNsOIM@+B(~Jf`FWYH-I`lZ`SAF7c+F>bf(Jw3{B_N~lff1Q(;d z*)=|Y7VQ_TR`3|@`_!PGkL|uox_UQp*4X{KwwXNAQ)17pg<@qz1;P3Xm0J9xCK?wb zPEk20Ai?zpeT`T*gfKyLLtsp}YB5b?rmc_PqiRJ3O^(`gR58aJsz=uNy`gtBI>lYX z0c~)dAUvF#WM!|4N-< zf*^aFN-Y+$;^_yMj|NLzf7wiekn!#u8QgzNqil2*<_1R-R7u8@1Wr=7MP-7Tb`Av%bi?lf^sBM4?Bk8ny$MWHb^x-Ll+cnk_~!SJ*cqWL4A< zB4HePrIcMNUcTk#=w5MSh(~6aN=0&Q-VEs1={bzC!+kd=+@~CbiLS}4^?0mN4~yOrNCCy;L=|GfAp; z>2$5_Xu569jj7lfZ8$X`T;4H&@wBjS+4Zh-z*f zVFQPBSNMzY0H@$ literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/source_waveform/PinLevels.digilevels b/src/nidigital/examples/source_waveform/PinLevels.digilevels new file mode 100644 index 0000000000..1908b117fa --- /dev/null +++ b/src/nidigital/examples/source_waveform/PinLevels.digilevels @@ -0,0 +1,15 @@ + + + + + + 0 + 3.3 + 0.8 + 2 + 0 + HighZ + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/PinMap.pinmap b/src/nidigital/examples/source_waveform/PinMap.pinmap new file mode 100644 index 0000000000..46d985a9f9 --- /dev/null +++ b/src/nidigital/examples/source_waveform/PinMap.pinmap @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/SourceWaveform.tdms b/src/nidigital/examples/source_waveform/SourceWaveform.tdms new file mode 100644 index 0000000000000000000000000000000000000000..4f85ffcdff1deaa6c969a39131b2c23dc77153ea GIT binary patch literal 1619 zcmeHHO-sW-5RD&IL{L!CYi_yq<6_T-C{~CTQtdG;$=VJyA8fYv>Oa>vX%^N(iQ=^b z!`sg8yf?ee%p{1iBgb**0uE#|xQ8`+?+bQ_1$!pH-QL$8soQexlM{)z>w2n!!^{*zbxRh zN!h{f1?(=lZ=Sg4*rKsxin46R#R-UfRfseZm9|wzwT9yuY*E>`$@-ZdFqnmQ!BqdzGNJ6} bRs2T8V2cRmsr_7UQdP~Y?_g)p?RWd%nF`^h literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/source_waveform/Specifications.specs b/src/nidigital/examples/source_waveform/Specifications.specs new file mode 100644 index 0000000000..65c615cfd6 --- /dev/null +++ b/src/nidigital/examples/source_waveform/Specifications.specs @@ -0,0 +1,9 @@ + + +
+ + 1 µs + +
+ +
\ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/Timing.digitiming b/src/nidigital/examples/source_waveform/Timing.digitiming new file mode 100644 index 0000000000..b5908eabfb --- /dev/null +++ b/src/nidigital/examples/source_waveform/Timing.digitiming @@ -0,0 +1,23 @@ + + + + + + timing.period + + + + 0 ns + timing.period / 2 + timing.period + + + (3 * timing.period) / 4 + + Pattern + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py new file mode 100644 index 0000000000..266d731ca5 --- /dev/null +++ b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py @@ -0,0 +1,100 @@ +#!/usr/bin/python + +import argparse +import nidigital +import os +import sys + + +def example(resource_name, options, source_waveform_type='PARALLEL', data_mapping='BROADCAST', waveform_name='new_waveform', start_label='new_pattern', + parallel_channel_list='PinGroup1', serial_channel_list='DUTPin1', sample_width=32, bit_order='MSB', waveform_file=None, write_waveform_data=True): + + with nidigital.Session(resource_name=resource_name, options=options) as session: + + dir = os.path.join(os.path.dirname(__file__)) + if waveform_file is None: + waveform_file = os.path.join(dir, 'SourceWaveform.tdms') + + session.load_pin_map(os.path.join(dir, 'PinMap.pinmap')) + + spec_filename = os.path.join(dir, 'Specifications.specs') + levels_filename = os.path.join(dir, 'PinLevels.digilevels') + timing_filename = os.path.join(dir, 'Timing.digitiming') + session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) + + session.apply_levels_and_timing(levels_filename, timing_filename) + + session.load_pattern(os.path.join(dir, 'Pattern.digipat')) + + mapping = nidigital.SourceDataMapping[data_mapping] + + # Configure the source waveform type + if source_waveform_type == 'PARALLEL': + session.pins[parallel_channel_list].create_source_waveform_parallel(waveform_name, mapping) + elif source_waveform_type == 'SERIAL': + session.pins[serial_channel_list].create_source_waveform_serial(waveform_name, mapping, sample_width, nidigital.BitOrder[bit_order]) + elif source_waveform_type == 'TDMS': + # Waveform configuration and data are read from the TDMS file + session.create_source_waveform_from_file_tdms(waveform_name, waveform_file, write_waveform_data) + + # Write the source waveform data + if source_waveform_type != 'TDMS': + # Placeholder ramp data for illustration; replace with your own waveform samples + sample_count = 2 ** min(sample_width, 8) if source_waveform_type == 'SERIAL' else 256 + samples = [i % sample_count for i in range(sample_count)] + if mapping == nidigital.SourceDataMapping.BROADCAST: + session.write_source_waveform_broadcast(waveform_name, samples) + else: + # Site-unique data is a dict of site number to samples; both sites use the same placeholder data here + session.write_source_waveform_site_unique(waveform_name, {0: samples, 1: samples}) + + print('Start bursting pattern') + session.burst_pattern(start_label=start_label) + + session.selected_function = nidigital.SelectedFunction.DISCONNECT + print('Done bursting pattern') + + +def _main(argsv): + parser = argparse.ArgumentParser(description='Demonstrates how to configure, write, and burst a source waveform using NI-Digital source memory.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='The specified resource name shown in Measurement & Automation Explorer (MAX) for a digital pattern instrument, for example, PXI1Slot3, where PXI1Slot3 is an instrument resource name.') + parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware') + parser.add_argument('-w', '--waveform-name', default='new_waveform', help='The name to assign to the waveform. Use the waveform_name with source_start opcode in your pattern.') + parser.add_argument('-l', '--start-label', default='new_pattern', help='Pattern name or exported pattern label from which to start bursting the pattern.') + parser.add_argument('-d', '--data-mapping', default='BROADCAST', choices=nidigital.SourceDataMapping.__members__.keys(), type=str.upper, help='Parameter that specifies how to map data on multiple sites.') + parser.add_argument('-t', '--source-waveform-type', default='PARALLEL', choices=['PARALLEL', 'SERIAL', 'TDMS'], type=str.upper, help='Type of source waveform to configure.') + parser.add_argument('--parallel-channel-list', default='PinGroup1', help='Pins that source data for a parallel waveform.') + parser.add_argument('--serial-channel-list', default='DUTPin1', help='Pins that source data for a serial waveform.') + parser.add_argument('--sample-width', default=32, type=int, help='Width in bits of each serial sample. Valid values are between 1 and 32.') + parser.add_argument('--bit-order', default='MSB', choices=nidigital.BitOrder.__members__.keys(), type=str.upper, help='Order in which to shift the bits.') + parser.add_argument('--waveform-file', default=None, help='Absolute file path to the load source waveform file (.tdms). Defaults to SourceWaveform.tdms next to this example.') + parser.add_argument('--write-waveform-data', default='True', choices=['True', 'False'], help='A Boolean that writes waveform data to source memory if True and the waveform data is in the file.') + args = parser.parse_args(argsv) + + example(args.resource_name, + 'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '', + args.source_waveform_type, args.data_mapping, args.waveform_name, args.start_label, + args.parallel_channel_list, args.serial_channel_list, args.sample_width, args.bit_order, + args.waveform_file, args.write_waveform_data == 'True') + + +def main(): + _main(sys.argv[1:]) + + +def test_main(): + _main([]) + _main(['--source-waveform-type', 'SERIAL', '--data-mapping', 'SITE_UNIQUE']) + _main(['--source-waveform-type', 'TDMS']) + + +def test_example(): + resource_name = 'PXI1Slot2,PXI1Slot3' + options = {'simulate': True, 'driver_setup': {'Model': '6571'}, } + example(resource_name, options) + example(resource_name, options, 'SERIAL', 'SITE_UNIQUE') + example(resource_name, options, 'TDMS') + + +if __name__ == '__main__': + main() diff --git a/src/nidigital/examples/source_waveform/source_waveform.digiproj b/src/nidigital/examples/source_waveform/source_waveform.digiproj new file mode 100644 index 0000000000..971b8ff9b9 --- /dev/null +++ b/src/nidigital/examples/source_waveform/source_waveform.digiproj @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From b151b5e8b7604a4af3dfd2d50237b939146de0b8 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 5 Nov 2026 15:46:25 +0000 Subject: [PATCH 12/13] Revert "Adding Source Waveform example in NI-Digital" This reverts commit 5ff15cc9e36b661b2d5a1e2b4883e79b02153f63. --- CHANGELOG.md | 1 - docs/nidigital/examples.rst | 9 -- .../examples/source_waveform/Pattern.digipat | Bin 5413 -> 0 bytes .../source_waveform/PinLevels.digilevels | 15 --- .../examples/source_waveform/PinMap.pinmap | 51 --------- .../source_waveform/SourceWaveform.tdms | Bin 1619 -> 0 bytes .../source_waveform/Specifications.specs | 9 -- .../source_waveform/Timing.digitiming | 23 ---- .../nidigital_source_waveform.py | 100 ------------------ .../source_waveform/source_waveform.digiproj | 39 ------- 10 files changed, 247 deletions(-) delete mode 100644 src/nidigital/examples/source_waveform/Pattern.digipat delete mode 100644 src/nidigital/examples/source_waveform/PinLevels.digilevels delete mode 100644 src/nidigital/examples/source_waveform/PinMap.pinmap delete mode 100644 src/nidigital/examples/source_waveform/SourceWaveform.tdms delete mode 100644 src/nidigital/examples/source_waveform/Specifications.specs delete mode 100644 src/nidigital/examples/source_waveform/Timing.digitiming delete mode 100644 src/nidigital/examples/source_waveform/nidigital_source_waveform.py delete mode 100644 src/nidigital/examples/source_waveform/source_waveform.digiproj diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fefe411b8..83d1d3267b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -558,7 +558,6 @@ #### [nidigital] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. - - Added the `nidigital_source_waveform.py` example. - Changed - Removed diff --git a/docs/nidigital/examples.rst b/docs/nidigital/examples.rst index 303dcff661..b8c8cc689a 100644 --- a/docs/nidigital/examples.rst +++ b/docs/nidigital/examples.rst @@ -30,12 +30,3 @@ nidigital_ppmu_source_and_measure.py :encoding: utf8 :caption: `(nidigital_ppmu_source_and_measure.py) `_ -nidigital_source_waveform.py ----------------------------- - -.. literalinclude:: ../../src/nidigital/examples/source_waveform/nidigital_source_waveform.py - :language: python - :linenos: - :encoding: utf8 - :caption: `(nidigital_source_waveform.py) `_ - diff --git a/src/nidigital/examples/source_waveform/Pattern.digipat b/src/nidigital/examples/source_waveform/Pattern.digipat deleted file mode 100644 index 0ee9d4fef983edd6c923bfa0c4eeb74e1a9f9bf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5413 zcmcgwTXP#V6y9(x<&uWN3^Ux6;bDhPr*2vb<=zk%aGTOh?KV7-S=(}~va2<+T(@uG zjTv6~A^Zz|Ryp79IgXsz9dCj;6XjdW(sw>dM@L$>>dow>D2mLRQPd`c39isHO6@7x z3-o|ulT0hZm#OR|-fL%HrN^!wcAOb_lUsZXdy$GaJ}sJ~0)CQ_@8?e8BUvl(ezB~I z1gE^?L+BkYtsd_UN(CX$W#$n)#&ez;Y~|U&q`JFneE)%VLz0aFk)02@J}&Db!DC#n zQ3LLOCwZ7Vkf70tNsOIM@+B(~Jf`FWYH-I`lZ`SAF7c+F>bf(Jw3{B_N~lff1Q(;d z*)=|Y7VQ_TR`3|@`_!PGkL|uox_UQp*4X{KwwXNAQ)17pg<@qz1;P3Xm0J9xCK?wb zPEk20Ai?zpeT`T*gfKyLLtsp}YB5b?rmc_PqiRJ3O^(`gR58aJsz=uNy`gtBI>lYX z0c~)dAUvF#WM!|4N-< zf*^aFN-Y+$;^_yMj|NLzf7wiekn!#u8QgzNqil2*<_1R-R7u8@1Wr=7MP-7Tb`Av%bi?lf^sBM4?Bk8ny$MWHb^x-Ll+cnk_~!SJ*cqWL4A< zB4HePrIcMNUcTk#=w5MSh(~6aN=0&Q-VEs1={bzC!+kd=+@~CbiLS}4^?0mN4~yOrNCCy;L=|GfAp; z>2$5_Xu569jj7lfZ8$X`T;4H&@wBjS+4Zh-z*f zVFQPBSNMzY0H@$ diff --git a/src/nidigital/examples/source_waveform/PinLevels.digilevels b/src/nidigital/examples/source_waveform/PinLevels.digilevels deleted file mode 100644 index 1908b117fa..0000000000 --- a/src/nidigital/examples/source_waveform/PinLevels.digilevels +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - 0 - 3.3 - 0.8 - 2 - 0 - HighZ - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/PinMap.pinmap b/src/nidigital/examples/source_waveform/PinMap.pinmap deleted file mode 100644 index 46d985a9f9..0000000000 --- a/src/nidigital/examples/source_waveform/PinMap.pinmap +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/SourceWaveform.tdms b/src/nidigital/examples/source_waveform/SourceWaveform.tdms deleted file mode 100644 index 4f85ffcdff1deaa6c969a39131b2c23dc77153ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1619 zcmeHHO-sW-5RD&IL{L!CYi_yq<6_T-C{~CTQtdG;$=VJyA8fYv>Oa>vX%^N(iQ=^b z!`sg8yf?ee%p{1iBgb**0uE#|xQ8`+?+bQ_1$!pH-QL$8soQexlM{)z>w2n!!^{*zbxRh zN!h{f1?(=lZ=Sg4*rKsxin46R#R-UfRfseZm9|wzwT9yuY*E>`$@-ZdFqnmQ!BqdzGNJ6} bRs2T8V2cRmsr_7UQdP~Y?_g)p?RWd%nF`^h diff --git a/src/nidigital/examples/source_waveform/Specifications.specs b/src/nidigital/examples/source_waveform/Specifications.specs deleted file mode 100644 index 65c615cfd6..0000000000 --- a/src/nidigital/examples/source_waveform/Specifications.specs +++ /dev/null @@ -1,9 +0,0 @@ - - -
- - 1 µs - -
- -
\ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/Timing.digitiming b/src/nidigital/examples/source_waveform/Timing.digitiming deleted file mode 100644 index b5908eabfb..0000000000 --- a/src/nidigital/examples/source_waveform/Timing.digitiming +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - timing.period - - - - 0 ns - timing.period / 2 - timing.period - - - (3 * timing.period) / 4 - - Pattern - - - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py deleted file mode 100644 index 266d731ca5..0000000000 --- a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/python - -import argparse -import nidigital -import os -import sys - - -def example(resource_name, options, source_waveform_type='PARALLEL', data_mapping='BROADCAST', waveform_name='new_waveform', start_label='new_pattern', - parallel_channel_list='PinGroup1', serial_channel_list='DUTPin1', sample_width=32, bit_order='MSB', waveform_file=None, write_waveform_data=True): - - with nidigital.Session(resource_name=resource_name, options=options) as session: - - dir = os.path.join(os.path.dirname(__file__)) - if waveform_file is None: - waveform_file = os.path.join(dir, 'SourceWaveform.tdms') - - session.load_pin_map(os.path.join(dir, 'PinMap.pinmap')) - - spec_filename = os.path.join(dir, 'Specifications.specs') - levels_filename = os.path.join(dir, 'PinLevels.digilevels') - timing_filename = os.path.join(dir, 'Timing.digitiming') - session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) - - session.apply_levels_and_timing(levels_filename, timing_filename) - - session.load_pattern(os.path.join(dir, 'Pattern.digipat')) - - mapping = nidigital.SourceDataMapping[data_mapping] - - # Configure the source waveform type - if source_waveform_type == 'PARALLEL': - session.pins[parallel_channel_list].create_source_waveform_parallel(waveform_name, mapping) - elif source_waveform_type == 'SERIAL': - session.pins[serial_channel_list].create_source_waveform_serial(waveform_name, mapping, sample_width, nidigital.BitOrder[bit_order]) - elif source_waveform_type == 'TDMS': - # Waveform configuration and data are read from the TDMS file - session.create_source_waveform_from_file_tdms(waveform_name, waveform_file, write_waveform_data) - - # Write the source waveform data - if source_waveform_type != 'TDMS': - # Placeholder ramp data for illustration; replace with your own waveform samples - sample_count = 2 ** min(sample_width, 8) if source_waveform_type == 'SERIAL' else 256 - samples = [i % sample_count for i in range(sample_count)] - if mapping == nidigital.SourceDataMapping.BROADCAST: - session.write_source_waveform_broadcast(waveform_name, samples) - else: - # Site-unique data is a dict of site number to samples; both sites use the same placeholder data here - session.write_source_waveform_site_unique(waveform_name, {0: samples, 1: samples}) - - print('Start bursting pattern') - session.burst_pattern(start_label=start_label) - - session.selected_function = nidigital.SelectedFunction.DISCONNECT - print('Done bursting pattern') - - -def _main(argsv): - parser = argparse.ArgumentParser(description='Demonstrates how to configure, write, and burst a source waveform using NI-Digital source memory.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='The specified resource name shown in Measurement & Automation Explorer (MAX) for a digital pattern instrument, for example, PXI1Slot3, where PXI1Slot3 is an instrument resource name.') - parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware') - parser.add_argument('-w', '--waveform-name', default='new_waveform', help='The name to assign to the waveform. Use the waveform_name with source_start opcode in your pattern.') - parser.add_argument('-l', '--start-label', default='new_pattern', help='Pattern name or exported pattern label from which to start bursting the pattern.') - parser.add_argument('-d', '--data-mapping', default='BROADCAST', choices=nidigital.SourceDataMapping.__members__.keys(), type=str.upper, help='Parameter that specifies how to map data on multiple sites.') - parser.add_argument('-t', '--source-waveform-type', default='PARALLEL', choices=['PARALLEL', 'SERIAL', 'TDMS'], type=str.upper, help='Type of source waveform to configure.') - parser.add_argument('--parallel-channel-list', default='PinGroup1', help='Pins that source data for a parallel waveform.') - parser.add_argument('--serial-channel-list', default='DUTPin1', help='Pins that source data for a serial waveform.') - parser.add_argument('--sample-width', default=32, type=int, help='Width in bits of each serial sample. Valid values are between 1 and 32.') - parser.add_argument('--bit-order', default='MSB', choices=nidigital.BitOrder.__members__.keys(), type=str.upper, help='Order in which to shift the bits.') - parser.add_argument('--waveform-file', default=None, help='Absolute file path to the load source waveform file (.tdms). Defaults to SourceWaveform.tdms next to this example.') - parser.add_argument('--write-waveform-data', default='True', choices=['True', 'False'], help='A Boolean that writes waveform data to source memory if True and the waveform data is in the file.') - args = parser.parse_args(argsv) - - example(args.resource_name, - 'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '', - args.source_waveform_type, args.data_mapping, args.waveform_name, args.start_label, - args.parallel_channel_list, args.serial_channel_list, args.sample_width, args.bit_order, - args.waveform_file, args.write_waveform_data == 'True') - - -def main(): - _main(sys.argv[1:]) - - -def test_main(): - _main([]) - _main(['--source-waveform-type', 'SERIAL', '--data-mapping', 'SITE_UNIQUE']) - _main(['--source-waveform-type', 'TDMS']) - - -def test_example(): - resource_name = 'PXI1Slot2,PXI1Slot3' - options = {'simulate': True, 'driver_setup': {'Model': '6571'}, } - example(resource_name, options) - example(resource_name, options, 'SERIAL', 'SITE_UNIQUE') - example(resource_name, options, 'TDMS') - - -if __name__ == '__main__': - main() diff --git a/src/nidigital/examples/source_waveform/source_waveform.digiproj b/src/nidigital/examples/source_waveform/source_waveform.digiproj deleted file mode 100644 index 971b8ff9b9..0000000000 --- a/src/nidigital/examples/source_waveform/source_waveform.digiproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 9c0be70020a7fb4d82b085708fa2b55fbd0e60fa Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Wed, 11 Nov 2026 14:35:39 +0000 Subject: [PATCH 13/13] Trigger CI build