Repository navigation
Adding Measurement Library example in NI-Scope #2245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
NI-velmurugan
wants to merge
4
commits into
ni:master
Choose a base branch
from
NI-velmurugan:users/velmurugan/add-niscope-measurement-library
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
dc608b9
Adding Measurement Library example in NI-Scope
NI-velmurugan 5b21e43
Removing error handling for the trigger source
NI-velmurugan 8b77fbd
Resolving PR comments
NI-velmurugan c2c0089
Merge branch 'master' into users/velmurugan/add-niscope-measurement-l…
NI-velmurugan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| #!/usr/bin/python | ||
|
|
||
| import argparse | ||
| import niscope | ||
| import pytest | ||
| import sys | ||
|
|
||
|
|
||
| def _create_chart(plt): | ||
| figure, axes = plt.subplots() | ||
| axes.set_title('Waveform Graph') | ||
| axes.set_xlabel('Time (s)') | ||
| axes.set_ylabel('Amplitude (V)') | ||
| axes.grid(True) | ||
| figure.tight_layout() | ||
| return figure, axes | ||
|
|
||
|
|
||
| def _update_chart(axes, 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))] | ||
| # read() returns samples as a memoryview, which matplotlib cannot copy | ||
| line.set_data(x, list(waveform.samples)) | ||
| axes.relim() | ||
| axes.autoscale_view() | ||
|
|
||
|
|
||
| def example(resource_name, channels, options, vertical_range, vertical_coupling, | ||
| min_sample_rate, min_record_length, enforce_realtime, trigger_type, trigger_source, | ||
| trigger_level, trigger_slope, trigger_coupling, timeout, scalar_measurement, | ||
| reference_level_units, low_ref, mid_ref, high_ref, iterations): | ||
| import matplotlib.pyplot as plt | ||
|
|
||
| with niscope.Session(resource_name=resource_name, options=options) as session: | ||
| session.configure_vertical(range=vertical_range, coupling=niscope.VerticalCoupling[vertical_coupling]) | ||
| 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=enforce_realtime) | ||
| if trigger_type == 'EDGE': | ||
| session.configure_trigger_edge(trigger_source, trigger_level, niscope.TriggerCoupling[trigger_coupling], niscope.TriggerSlope[trigger_slope]) | ||
| else: | ||
| session.configure_trigger_immediate() | ||
|
|
||
| channel = session.channels[channels] | ||
| channel.meas_ref_level_units = niscope.RefLevelUnits[reference_level_units] | ||
| channel.meas_chan_low_ref_level = low_ref | ||
| channel.meas_chan_mid_ref_level = mid_ref | ||
| channel.meas_chan_high_ref_level = high_ref | ||
|
|
||
| figure, axes = _create_chart(plt) | ||
|
|
||
| acquisition_count = 1 | ||
| try: | ||
| # Run until the chart is closed, Ctrl+C is pressed, or the iteration limit is reached. | ||
| while plt.fignum_exists(figure.number) and (iterations is None or acquisition_count <= iterations): | ||
| # The statistics accumulate once per acquisition, so read a new waveform before each fetch. | ||
| waveforms = channel.read(num_samples=min_record_length, timeout=timeout) | ||
| _update_chart(axes, waveforms) | ||
| stats = channel.fetch_measurement_stats(niscope.ScalarMeasurement[scalar_measurement]) | ||
| print(f'Acquisition {acquisition_count}: {scalar_measurement}') | ||
| for stat in stats: | ||
| print(stat) | ||
| acquisition_count += 1 | ||
| plt.pause(0.02) | ||
|
|
||
| # Keep the final plot window open after acquisition stops until the user closes it. | ||
| if 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='Fetches scalar measurements and their statistics from an NI digitizer.', 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('-m', '--scalar-measurement', default='FFT_FREQUENCY', choices=niscope.ScalarMeasurement.__members__.keys(), type=str.upper, help='The scalar measurement to be performed on each fetched waveform.') | ||
| parser.add_argument('--reference-level-units', default='PERCENTAGE', choices=niscope.RefLevelUnits.__members__.keys(), type=str.upper, help='Specifies the units of the reference levels.') | ||
| parser.add_argument('--low-ref', default=10.0, type=float, help='Stores the low reference level used in many scalar measurements.') | ||
|
NI-velmurugan marked this conversation as resolved.
|
||
| parser.add_argument('--mid-ref', default=50.0, type=float, help='Stores the mid reference level used in many scalar measurements.') | ||
| parser.add_argument('--high-ref', default=90.0, type=float, help='Stores the high reference level used in many scalar measurements.') | ||
| parser.add_argument('-s', '--min-sample-rate', default=1000000.0, type=float, help='Specify the sampling rate for the acquisition in Samples per second.') | ||
| parser.add_argument('-l', '--min-record-length', default=1000, type=int, help='Specifies the minimum number of points you require in the waveform record for each channel.') | ||
| parser.add_argument('--enforce-realtime', action=argparse.BooleanOptionalAction, default=True, help='Indicates whether the digitizer enforces real-time measurements or allows equivalent-time measurements.') | ||
| parser.add_argument('-c', '--channels', default='0', help='Comma-separated list of channels to plot, one line per channel') | ||
| parser.add_argument('-v', '--vertical-range', default=2.0, type=float, help='Specifies the absolute value of the input range for a channel in volts.') | ||
| parser.add_argument('--vertical-coupling', default='DC', choices=niscope.VerticalCoupling.__members__.keys(), type=str.upper, help='Specifies how the digitizer couples the input signal for the channel.') | ||
| parser.add_argument('--trigger-type', default='EDGE', choices=['EDGE', 'IMMEDIATE'], type=str.upper, help='Selects edge or immediate triggering.') | ||
| parser.add_argument('--trigger-source', default='0', help='Specifies the source the digitizer monitors for the trigger event.') | ||
| parser.add_argument('--trigger-level', default=0.0, type=float, help='Specifies the voltage threshold for the trigger subsystem.') | ||
| parser.add_argument('--trigger-slope', default='POSITIVE', choices=niscope.TriggerSlope.__members__.keys(), type=str.upper, help='Specifies if a rising or a falling edge triggers the digitizer.') | ||
| parser.add_argument('--trigger-coupling', default='DC', choices=niscope.TriggerCoupling.__members__.keys(), type=str.upper, help='Specifies how the digitizer couples the trigger source.') | ||
| parser.add_argument('-t', '--timeout', default=5.0, type=float, help='The time to wait in seconds for data to be acquired; using 0 for this parameter tells NI-SCOPE to fetch whatever is currently available.') | ||
| parser.add_argument('--total-iterations', default=None, type=int, help='Specifies the maximum number of acquisitions; omit to run until the chart closes or Ctrl+C is pressed.') | ||
| parser.add_argument('-op', '--option-string', default='', type=str, help='Specifies the initial value of certain properties for the session.') | ||
| args = parser.parse_args(argsv) | ||
| example(args.resource_name, args.channels, args.option_string, args.vertical_range, args.vertical_coupling, | ||
| args.min_sample_rate, args.min_record_length, args.enforce_realtime, args.trigger_type, args.trigger_source, | ||
| args.trigger_level, args.trigger_slope, args.trigger_coupling, args.timeout, args.scalar_measurement, | ||
| args.reference_level_units, args.low_ref, args.mid_ref, args.high_ref, 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, 2.0, 'DC', 1000000.0, 1000, True, 'IMMEDIATE', '0', 0.0, 'POSITIVE', 'DC', 5.0, | ||
| 'FREQUENCY', 'PERCENTAGE', 10.0, 50.0, 90.0, 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', '--trigger-type', 'immediate', '--total-iterations', '2', ] | ||
| _main(cmd_line) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| main() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.