From b7abc39cf611a83a9a24e62ce33d434313889559 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 19 Jun 2025 06:53:29 -0500 Subject: [PATCH 01/50] Analog Input - Voltage and Thermocouple Single Task --- .../nidaqmx_continuous_analog_input.py | 38 ++++ .../nidaqmx_continuous_analog_input_panel.py | 168 ++++++++++++++++ examples/sample/sample.py | 2 +- poetry.lock | 187 +++++++++++++++++- pyproject.toml | 1 + 5 files changed, 394 insertions(+), 2 deletions(-) create mode 100644 examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py create mode 100644 examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py diff --git a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py new file mode 100644 index 0000000..246e053 --- /dev/null +++ b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -0,0 +1,38 @@ +"""This example demonstrates how to open/update a Streamlit application using nipanel package.""" + +import nipanel +import nidaqmx +import pathlib +import time + +script_path = pathlib.Path(__file__) +panel_script_path = str(script_path.with_name("nidaqmx_continuous_analog_input_panel.py")) + +panel = nipanel.StreamlitPanel( + panel_id="nidaqmx_continuous_analog_input_panel", + streamlit_script_path=panel_script_path, +) + +data_arr = [] +with nidaqmx.Task() as task: + task.ai_channels.add_ai_voltage_chan("Mod1/ai2") + task.ai_channels.add_ai_thrmcpl_chan("Mod1/ai3") + try: + total_read = 0 + while True: + data = task.read(number_of_samples_per_channel=3) + read = len(data) + total_read += read + + data_arr.append(data) + time.sleep(1) + panel.set_value("amplitude",data_arr[-1][-1]) + panel.set_value("Volts",data_arr[-1][0]) + except KeyboardInterrupt: + pass + finally: + task.stop() + print(f"\nAcquired {total_read} total samples.") + + + diff --git a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py new file mode 100644 index 0000000..b83f09b --- /dev/null +++ b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py @@ -0,0 +1,168 @@ +"""Streamlit application script for displaying values using nipanel package.""" +import nipanel +import streamlit as st +import streamlit.components.v1 as components +from streamlit_echarts import st_echarts + +panel = nipanel.StreamlitPanelValueAccessor(panel_id="nidaqmx_continuous_analog_input_panel") + +add_refresh_component = components.declare_component( + "panelRefreshComponent", + url=f"http://localhost:42001/panels/refresh/{panel.panel_id}",) +add_refresh_component() + + +st.title("Analog Input - Voltage and Thermocouple in a Single Task") +voltage_tab, thermocouple_tab = st.tabs(["Voltage", "Thermocouple"]) + +st.markdown( + """ + + """, + unsafe_allow_html=True +) + + +list_of_therm_amp = panel.get_value("amplitude") +list_of_voltage_amp = panel.get_value("Volts") + +if "therm_history" not in st.session_state: + st.session_state.therm_history = [] +if "volts_history" not in st.session_state: + st.session_state.volts_history = [] + +for therm_amp in list_of_therm_amp: + st.session_state.therm_history.append(therm_amp) +for voltage_amp in list_of_voltage_amp: + st.session_state.volts_history.append(voltage_amp) + +therm_amp_graph = { + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["thermocouple_amplitude"]}, + "xAxis": { + "type": "category", + "data":list(range(len(st.session_state.therm_history))), + "name": "Time" + }, + "yAxis": { + "type": "value", + "name": "Thermocouple Amplitude" + }, + "series": [ + { + "name": "thermocouple_amplitude", + "type": "line", + "data": st.session_state.therm_history, + "color": "red" + }, + + + ], +} +st_echarts(options=therm_amp_graph, height="400px") + +voltage_amp_graph = { + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["voltage_amplitude"]}, + "xAxis": { + "type": "category", + "data": list(range(len(st.session_state.volts_history))), + "name": "Time" + }, + "yAxis": { + "type": "value", + "name": "Voltage Amplitude" + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": st.session_state.volts_history, + }, + + ], +} +st_echarts(options=voltage_amp_graph, height="400px") + +st.header("Voltage & Thermocouple") +voltage_therm_graph = { + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["voltage_amplitude", "thermocouple_amplitude"]}, + "xAxis": { + "type": "category", + "data": list(range(len(st.session_state.volts_history))), + "name": "Time" + }, + "yAxis": { + "type": "value", + "name": "Voltage and Thermocouple Amplitude" + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": st.session_state.volts_history, + "emphasis": {"focus":"series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + { + "name": "thermocouple_amplitude", + "type": "line", + "data": st.session_state.therm_history, + "color": "red", + "emphasis": {"focus":"series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], +} +st_echarts(options=voltage_therm_graph, height="400px") + +with voltage_tab: + left_volt_tab, center_volt_tab, right_volt_tab = st.columns(3) + with left_volt_tab: + st.selectbox(options=["Mod1/ai2"], label="Physical Channels", disabled=True) + st.selectbox(options=["Off"], label="Logging Modes", disabled=False) + with center_volt_tab: + st.selectbox(options=["-5"],label="Min Value") + st.selectbox(options=["5"],label="Max Value") + st.selectbox(options=["1000"], label="Samples per Loops", disabled=False) + with right_volt_tab: + st.selectbox(options=["default"], label="Terminal Configurations") + st.selectbox(options=["OnboardClock"], label="Sample Clock Sources", disabled=False) + + +thermocouple_tab.header("Thermocouple") +with thermocouple_tab: + left, middle, right = st.columns(3) + with left: + st.selectbox(options=["Mod1/ai3"], label="Physical Channel", disabled=True) + st.selectbox(options=["0"], label="Min", disabled=False) + st.selectbox(options=["100"], label="Max", disabled=False) + st.selectbox(options=["Off"], label="Logging Mode", disabled=False) + + with middle: + st.selectbox(options=["Deg C"], label = "Units", disabled=False) + st.selectbox(options=["J"], label="Thermocouple Type", disabled=False) + st.selectbox(options=["Constant Value"], label="CJC Source", disabled=False) + st.selectbox(options=["1000"], label="Samples per Loop", disabled=False) + with right: + st.selectbox(options=["25"],label="CJC Value", disabled=False) + st.selectbox(options=["OnboardClock"], label="Sample Clock Source", disabled=False) + st.selectbox(options=[" "], label="Actual Sample Rate", disabled=True) + + + + + + + + + + + diff --git a/examples/sample/sample.py b/examples/sample/sample.py index 09977e4..188c1f2 100644 --- a/examples/sample/sample.py +++ b/examples/sample/sample.py @@ -12,7 +12,7 @@ streamlit_script_path=panel_script_path, ) panel.set_value("sample_string", "Hello, World!") -panel.set_value("sample_int", 42) +panel.set_value("sample_int", 6) panel.set_value("sample_float", 3.14) panel.set_value("sample_bool", True) panel.set_value("float_values", [1.1, 2.2, 3.3]) diff --git a/poetry.lock b/poetry.lock index 2adc8d0..deb5730 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1700,6 +1700,23 @@ files = [ dev = ["pre-commit", "tox"] testing = ["coverage", "pytest", "pytest-benchmark"] +[[package]] +name = "prettytable" +version = "3.16.0" +description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" +optional = false +python-versions = ">=3.9" +files = [ + {file = "prettytable-3.16.0-py3-none-any.whl", hash = "sha256:b5eccfabb82222f5aa46b798ff02a8452cf530a352c31bddfa29be41242863aa"}, + {file = "prettytable-3.16.0.tar.gz", hash = "sha256:3c64b31719d961bf69c9a7e03d0c1e477320906a98da63952bc6698d6164ff57"}, +] + +[package.dependencies] +wcwidth = "*" + +[package.extras] +tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"] + [[package]] name = "protobuf" version = "4.25.8" @@ -1865,6 +1882,28 @@ snowballstemmer = ">=2.2.0" [package.extras] toml = ["tomli (>=1.2.3)"] +[[package]] +name = "pyecharts" +version = "2.0.8" +description = "Python options, make charting easier" +optional = false +python-versions = "*" +files = [ + {file = "pyecharts-2.0.8-py3-none-any.whl", hash = "sha256:8b711ba139f39f89bc1b2a869d7adda89dc74c910d158a1f9063109fe66bc985"}, + {file = "pyecharts-2.0.8.tar.gz", hash = "sha256:908dbd939862dd3c76bb53697bdb41d3cdd0b5ba48ca69a76a6085d0aa27dbdf"}, +] + +[package.dependencies] +jinja2 = "*" +prettytable = "*" +simplejson = "*" + +[package.extras] +images = ["PIL"] +phantomjs = ["snapshot-phantomjs"] +pyppeteer = ["snapshot-pyppeteer"] +selenium = ["snapshot-selenium"] + [[package]] name = "pyflakes" version = "2.5.0" @@ -2299,6 +2338,125 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +[[package]] +name = "simplejson" +version = "3.20.1" +description = "Simple, fast, extensible JSON encoder/decoder for Python" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.5" +files = [ + {file = "simplejson-3.20.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f5272b5866b259fe6c33c4a8c5073bf8b359c3c97b70c298a2f09a69b52c7c41"}, + {file = "simplejson-3.20.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5c0de368f3052a59a1acf21f8b2dd28686a9e4eba2da7efae7ed9554cb31e7bc"}, + {file = "simplejson-3.20.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0821871404a537fd0e22eba240c74c0467c28af6cc435903eca394cfc74a0497"}, + {file = "simplejson-3.20.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c939a1e576bded47d7d03aa2afc2ae90b928b2cf1d9dc2070ceec51fd463f430"}, + {file = "simplejson-3.20.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:3c4f0a61cdc05550782ca4a2cdb311ea196c2e6be6b24a09bf71360ca8c3ca9b"}, + {file = "simplejson-3.20.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:6c21f5c026ca633cfffcb6bc1fac2e99f65cb2b24657d3bef21aed9916cc3bbf"}, + {file = "simplejson-3.20.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:8d23b7f8d6b72319d6d55a0261089ff621ce87e54731c2d3de6a9bf7be5c028c"}, + {file = "simplejson-3.20.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:cda5c32a98f392909088111ecec23f2b0d39346ceae1a0fea23ab2d1f84ec21d"}, + {file = "simplejson-3.20.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e580aa65d5f6c3bf41b9b4afe74be5d5ddba9576701c107c772d936ea2b5043a"}, + {file = "simplejson-3.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4a586ce4f78cec11f22fe55c5bee0f067e803aab9bad3441afe2181693b5ebb5"}, + {file = "simplejson-3.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74a1608f9e6e8c27a4008d70a54270868306d80ed48c9df7872f9f4b8ac87808"}, + {file = "simplejson-3.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03db8cb64154189a92a7786209f24e391644f3a3fa335658be2df2af1960b8d8"}, + {file = "simplejson-3.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eea7e2b7d858f6fdfbf0fe3cb846d6bd8a45446865bc09960e51f3d473c2271b"}, + {file = "simplejson-3.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e66712b17d8425bb7ff8968d4c7c7fd5a2dd7bd63728b28356223c000dd2f91f"}, + {file = "simplejson-3.20.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2cc4f6486f9f515b62f5831ff1888886619b84fc837de68f26d919ba7bbdcbc"}, + {file = "simplejson-3.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a3c2df555ee4016148fa192e2b9cd9e60bc1d40769366134882685e90aee2a1e"}, + {file = "simplejson-3.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:78520f04b7548a5e476b5396c0847e066f1e0a4c0c5e920da1ad65e95f410b11"}, + {file = "simplejson-3.20.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f4bd49ecde87b0fe9f55cc971449a32832bca9910821f7072bbfae1155eaa007"}, + {file = "simplejson-3.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7eaae2b88eb5da53caaffdfa50e2e12022553949b88c0df4f9a9663609373f72"}, + {file = "simplejson-3.20.1-cp310-cp310-win32.whl", hash = "sha256:e836fb88902799eac8debc2b642300748f4860a197fa3d9ea502112b6bb8e142"}, + {file = "simplejson-3.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a19b552b212fc3b5b96fc5ce92333d4a9ac0a800803e1f17ebb16dac4be5"}, + {file = "simplejson-3.20.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:325b8c107253d3217e89d7b50c71015b5b31e2433e6c5bf38967b2f80630a8ca"}, + {file = "simplejson-3.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88a7baa8211089b9e58d78fbc1b0b322103f3f3d459ff16f03a36cece0d0fcf0"}, + {file = "simplejson-3.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:299b1007b8101d50d95bc0db1bf5c38dc372e85b504cf77f596462083ee77e3f"}, + {file = "simplejson-3.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ec618ed65caab48e81e3ed29586236a8e57daef792f1f3bb59504a7e98cd10"}, + {file = "simplejson-3.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2cdead1d3197f0ff43373cf4730213420523ba48697743e135e26f3d179f38"}, + {file = "simplejson-3.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3466d2839fdc83e1af42e07b90bc8ff361c4e8796cd66722a40ba14e458faddd"}, + {file = "simplejson-3.20.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d492ed8e92f3a9f9be829205f44b1d0a89af6582f0cf43e0d129fa477b93fe0c"}, + {file = "simplejson-3.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f924b485537b640dc69434565463fd6fc0c68c65a8c6e01a823dd26c9983cf79"}, + {file = "simplejson-3.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e8eacf6a3491bf76ea91a8d46726368a6be0eb94993f60b8583550baae9439e"}, + {file = "simplejson-3.20.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d04bf90b4cea7c22d8b19091633908f14a096caa301b24c2f3d85b5068fb8"}, + {file = "simplejson-3.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:69dd28d4ce38390ea4aaf212902712c0fd1093dc4c1ff67e09687c3c3e15a749"}, + {file = "simplejson-3.20.1-cp311-cp311-win32.whl", hash = "sha256:dfe7a9da5fd2a3499436cd350f31539e0a6ded5da6b5b3d422df016444d65e43"}, + {file = "simplejson-3.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:896a6c04d7861d507d800da7642479c3547060bf97419d9ef73d98ced8258766"}, + {file = "simplejson-3.20.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f31c4a3a7ab18467ee73a27f3e59158255d1520f3aad74315edde7a940f1be23"}, + {file = "simplejson-3.20.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:884e6183d16b725e113b83a6fc0230152ab6627d4d36cb05c89c2c5bccfa7bc6"}, + {file = "simplejson-3.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03d7a426e416fe0d3337115f04164cd9427eb4256e843a6b8751cacf70abc832"}, + {file = "simplejson-3.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:000602141d0bddfcff60ea6a6e97d5e10c9db6b17fd2d6c66199fa481b6214bb"}, + {file = "simplejson-3.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af8377a8af78226e82e3a4349efdde59ffa421ae88be67e18cef915e4023a595"}, + {file = "simplejson-3.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15c7de4c88ab2fbcb8781a3b982ef883696736134e20b1210bca43fb42ff1acf"}, + {file = "simplejson-3.20.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:455a882ff3f97d810709f7b620007d4e0aca8da71d06fc5c18ba11daf1c4df49"}, + {file = "simplejson-3.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fc0f523ce923e7f38eb67804bc80e0a028c76d7868500aa3f59225574b5d0453"}, + {file = "simplejson-3.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76461ec929282dde4a08061071a47281ad939d0202dc4e63cdd135844e162fbc"}, + {file = "simplejson-3.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ab19c2da8c043607bde4d4ef3a6b633e668a7d2e3d56f40a476a74c5ea71949f"}, + {file = "simplejson-3.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2578bedaedf6294415197b267d4ef678fea336dd78ee2a6d2f4b028e9d07be3"}, + {file = "simplejson-3.20.1-cp312-cp312-win32.whl", hash = "sha256:339f407373325a36b7fd744b688ba5bae0666b5d340ec6d98aebc3014bf3d8ea"}, + {file = "simplejson-3.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:627d4486a1ea7edf1f66bb044ace1ce6b4c1698acd1b05353c97ba4864ea2e17"}, + {file = "simplejson-3.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:71e849e7ceb2178344998cbe5ade101f1b329460243c79c27fbfc51c0447a7c3"}, + {file = "simplejson-3.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b63fdbab29dc3868d6f009a59797cefaba315fd43cd32ddd998ee1da28e50e29"}, + {file = "simplejson-3.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1190f9a3ce644fd50ec277ac4a98c0517f532cfebdcc4bd975c0979a9f05e1fb"}, + {file = "simplejson-3.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1336ba7bcb722ad487cd265701ff0583c0bb6de638364ca947bb84ecc0015d1"}, + {file = "simplejson-3.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e975aac6a5acd8b510eba58d5591e10a03e3d16c1cf8a8624ca177491f7230f0"}, + {file = "simplejson-3.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a6dd11ee282937ad749da6f3b8d87952ad585b26e5edfa10da3ae2536c73078"}, + {file = "simplejson-3.20.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab980fcc446ab87ea0879edad41a5c28f2d86020014eb035cf5161e8de4474c6"}, + {file = "simplejson-3.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f5aee2a4cb6b146bd17333ac623610f069f34e8f31d2f4f0c1a2186e50c594f0"}, + {file = "simplejson-3.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:652d8eecbb9a3b6461b21ec7cf11fd0acbab144e45e600c817ecf18e4580b99e"}, + {file = "simplejson-3.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:8c09948f1a486a89251ee3a67c9f8c969b379f6ffff1a6064b41fea3bce0a112"}, + {file = "simplejson-3.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cbbd7b215ad4fc6f058b5dd4c26ee5c59f72e031dfda3ac183d7968a99e4ca3a"}, + {file = "simplejson-3.20.1-cp313-cp313-win32.whl", hash = "sha256:ae81e482476eaa088ef9d0120ae5345de924f23962c0c1e20abbdff597631f87"}, + {file = "simplejson-3.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:1b9fd15853b90aec3b1739f4471efbf1ac05066a2c7041bf8db821bb73cd2ddc"}, + {file = "simplejson-3.20.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c7edf279c1376f28bf41e916c015a2a08896597869d57d621f55b6a30c7e1e6d"}, + {file = "simplejson-3.20.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9202b9de38f12e99a40addd1a8d508a13c77f46d87ab1f9095f154667f4fe81"}, + {file = "simplejson-3.20.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:391345b4157cc4e120027e013bd35c45e2c191e2bf48b8913af488cdc3b9243c"}, + {file = "simplejson-3.20.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6fdcc9debb711ddd2ad6d69f9386a3d9e8e253234bbb30513e0a7caa9510c51"}, + {file = "simplejson-3.20.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9daf8cdc7ee8a9e9f7a3b313ba0a003391857e90d0e82fbcd4d614aa05cb7c3b"}, + {file = "simplejson-3.20.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:c02f4868a3a46ffe284a51a88d134dc96feff6079a7115164885331a1ba8ed9f"}, + {file = "simplejson-3.20.1-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:3d7310172d5340febd258cb147f46aae30ad57c445f4d7e1ae8461c10aaf43b0"}, + {file = "simplejson-3.20.1-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:4762e05577955312a4c6802f58dd02e040cc79ae59cda510aa1564d84449c102"}, + {file = "simplejson-3.20.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:8bb98fdf318c05aefd08a92583bd6ee148e93c6756fb1befb7b2d5f27824be78"}, + {file = "simplejson-3.20.1-cp36-cp36m-win32.whl", hash = "sha256:9a74e70818818981294b8e6956ce3496c5e1bd4726ac864fae473197671f7b85"}, + {file = "simplejson-3.20.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e041add470e8f8535cc05509485eb7205729a84441f03b25cde80ad48823792e"}, + {file = "simplejson-3.20.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7e9d73f46119240e4f4f07868241749d67d09873f40cb968d639aa9ccc488b86"}, + {file = "simplejson-3.20.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae6e637dc24f8fee332ed23dd070e81394138e42cd4fd9d0923e5045ba122e27"}, + {file = "simplejson-3.20.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:efd3bc6c6b17e3d4620eb6be5196f0d1c08b6ce7c3101fa8e292b79e0908944b"}, + {file = "simplejson-3.20.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87fc623d457173a0213bc9ca4e346b83c9d443f63ed5cca847fb0cacea3cfc95"}, + {file = "simplejson-3.20.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec6a1e0a7aff76f0e008bebfa950188b9c50b58c1885d898145f48fc8e189a56"}, + {file = "simplejson-3.20.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:9c079606f461a6e950099167e21e13985147c8a24be8eea66c9ad68f73fad744"}, + {file = "simplejson-3.20.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:9faceb68fba27ef17eda306e4cd97a7b4b14fdadca5fbb15790ba8b26ebeec0c"}, + {file = "simplejson-3.20.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:7ceed598e4bacbf5133fe7a418f7991bb2df0683f3ac11fbf9e36a2bc7aa4b85"}, + {file = "simplejson-3.20.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:ede69c765e9901861ad7c6139023b7b7d5807c48a2539d817b4ab40018002d5f"}, + {file = "simplejson-3.20.1-cp37-cp37m-win32.whl", hash = "sha256:d8853c269a4c5146ddca4aa7c70e631795e9d11239d5fedb1c6bbc91ffdebcac"}, + {file = "simplejson-3.20.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ed6a17fd397f0e2b3ad668fc9e19253ed2e3875ad9086bd7f795c29a3223f4a1"}, + {file = "simplejson-3.20.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7551682b60bba3a9e2780742e101cf0a64250e76de7d09b1c4b0c8a7c7cc6834"}, + {file = "simplejson-3.20.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd9577ec1c8c3a43040e3787711e4c257c70035b7551a21854b5dec88dad09e1"}, + {file = "simplejson-3.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8e197e4cf6d42c2c57e7c52cd7c1e7b3e37c5911df1314fb393320131e2101"}, + {file = "simplejson-3.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bd09c8c75666e7f62a33d2f1fb57f81da1fcbb19a9fe7d7910b5756e1dd6048"}, + {file = "simplejson-3.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bd6bfe5678d73fbd5328eea6a35216503796428fc47f1237432522febaf3a0c"}, + {file = "simplejson-3.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b75d448fd0ceb2e7c90e72bb82c41f8462550d48529980bc0bab1d2495bfbb"}, + {file = "simplejson-3.20.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7e15b716d09f318c8cda3e20f82fae81684ce3d3acd1d7770fa3007df1769de"}, + {file = "simplejson-3.20.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3e7963197d958fcf9e98b212b80977d56c022384621ff463d98afc3b6b1ce7e8"}, + {file = "simplejson-3.20.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2e671dd62051129185d3a9a92c60101f56cbc174854a1a3dfb69114ebd9e1699"}, + {file = "simplejson-3.20.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e25b2a0c396f3b84fb89573d07b0e1846ed563eb364f2ea8230ca92b8a8cb786"}, + {file = "simplejson-3.20.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:489c3a43116082bad56795215786313832ba3991cca1f55838e52a553f451ab6"}, + {file = "simplejson-3.20.1-cp38-cp38-win32.whl", hash = "sha256:4a92e948bad8df7fa900ba2ba0667a98303f3db206cbaac574935c332838208e"}, + {file = "simplejson-3.20.1-cp38-cp38-win_amd64.whl", hash = "sha256:49d059b8363327eee3c94799dd96782314b2dbd7bcc293b4ad48db69d6f4d362"}, + {file = "simplejson-3.20.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a8011f1dd1d676befcd4d675ebdbfdbbefd3bf350052b956ba8c699fca7d8cef"}, + {file = "simplejson-3.20.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e91703a4c5fec53e36875ae426ad785f4120bd1d93b65bed4752eeccd1789e0c"}, + {file = "simplejson-3.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e39eaa57c7757daa25bcd21f976c46be443b73dd6c3da47fe5ce7b7048ccefe2"}, + {file = "simplejson-3.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceab2ce2acdc7fbaa433a93006758db6ba9a659e80c4faa13b80b9d2318e9b17"}, + {file = "simplejson-3.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d4f320c33277a5b715db5bf5b10dae10c19076bd6d66c2843e04bd12d1f1ea5"}, + {file = "simplejson-3.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b6436c48e64378fa844d8c9e58a5ed0352bbcfd4028369a9b46679b7ab79d2d"}, + {file = "simplejson-3.20.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e18345c8dda5d699be8166b61f9d80aaee4545b709f1363f60813dc032dac53"}, + {file = "simplejson-3.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:90b573693d1526bed576f6817e2a492eaaef68f088b57d7a9e83d122bbb49e51"}, + {file = "simplejson-3.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:272cc767826e924a6bd369ea3dbf18e166ded29059c7a4d64d21a9a22424b5b5"}, + {file = "simplejson-3.20.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:51b41f284d603c4380732d7d619f8b34bd04bc4aa0ed0ed5f4ffd0539b14da44"}, + {file = "simplejson-3.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6e6697a3067d281f01de0fe96fc7cba4ea870d96d7deb7bfcf85186d74456503"}, + {file = "simplejson-3.20.1-cp39-cp39-win32.whl", hash = "sha256:6dd3a1d5aca87bf947f3339b0f8e8e329f1badf548bdbff37fac63c17936da8e"}, + {file = "simplejson-3.20.1-cp39-cp39-win_amd64.whl", hash = "sha256:463f1fca8fbf23d088e5850fdd0dd4d5faea8900a9f9680270bd98fd649814ca"}, + {file = "simplejson-3.20.1-py3-none-any.whl", hash = "sha256:8a6c1bbac39fa4a79f83cbf1df6ccd8ff7069582a9fd8db1e52cea073bc2c697"}, + {file = "simplejson-3.20.1.tar.gz", hash = "sha256:e64139b4ec4f1f24c142ff7dcafe55a22b811a74d86d66560c8815687143037d"}, +] + [[package]] name = "six" version = "1.17.0" @@ -2581,6 +2739,22 @@ watchdog = {version = ">=2.1.5,<7", markers = "platform_system != \"Darwin\""} [package.extras] snowflake = ["snowflake-connector-python (>=3.3.0)", "snowflake-snowpark-python[modin] (>=1.17.0)"] +[[package]] +name = "streamlit-echarts" +version = "0.4.0" +description = "Echarts custom component for Streamlit" +optional = false +python-versions = ">=3.6" +files = [ + {file = "streamlit-echarts-0.4.0.tar.gz", hash = "sha256:33cc5329b99ddce8b64ce6c4607733e02db575c379af6394a8c78ae5df14934d"}, + {file = "streamlit_echarts-0.4.0-py3-none-any.whl", hash = "sha256:aa86679da0e7680ee43b7a6def31439273a686a8d71de522c55655047e80ec9b"}, +] + +[package.dependencies] +pyecharts = ">=1.9" +simplejson = ">=3.0" +streamlit = ">=0.63" + [[package]] name = "tenacity" version = "9.1.2" @@ -2783,7 +2957,18 @@ files = [ [package.extras] watchmedo = ["PyYAML (>=3.10)"] +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0,!=3.9.7" -content-hash = "2405bfc23e77ee98c4fe58845fa73632b884c4bf6acded29ece6c9380a168675" +content-hash = "7239a2757fe3a06c6ddafa7f51763d7ee77976a7d5f96b05ea1f9fbfa631c801" diff --git a/pyproject.toml b/pyproject.toml index 11ecccc..0b8cfc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ ni-measurement-plugin-sdk = {version=">=2.3"} typing-extensions = ">=4.13.2" streamlit = ">=1.24" nitypes = {version=">=0.1.0dev1", allow-prereleases=true} +streamlit-echarts = "^0.4.0" [tool.poetry.group.dev.dependencies] types-grpcio = ">=1.0" From 871f6e192778ddeb9bd8ee9d35b70b766a2ab609 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 24 Jun 2025 14:51:29 -0500 Subject: [PATCH 02/50] add niscope Signed-off-by: Dilmi Wickramanayake --- examples/nidaqmx/niscope_example.py | 194 ++++++++++++++++++++++++++++ examples/nidaqmx/niscope_panel.py | 39 ++++++ pyproject.toml | 7 + 3 files changed, 240 insertions(+) create mode 100644 examples/nidaqmx/niscope_example.py create mode 100644 examples/nidaqmx/niscope_panel.py diff --git a/examples/nidaqmx/niscope_example.py b/examples/nidaqmx/niscope_example.py new file mode 100644 index 0000000..2f88b80 --- /dev/null +++ b/examples/nidaqmx/niscope_example.py @@ -0,0 +1,194 @@ +import argparse +import niscope +import numpy +import pprint +import sys +import nipanel +from pathlib import Path +import time +pp = pprint.PrettyPrinter(indent=4, width=80) +panel_script_path = Path(__file__).with_name("niscope_panel.py") +panel = nipanel.create_panel(panel_script_path) + +# def example( +# resource_name, +# options, +# +# ): +# + +def example(resource_name, channels, options, length, total_acquisition_time_in_seconds, voltage, sample_rate_in_hz, samples_per_fetch,): + # fetch_into() allows you to preallocate and reuse the destination of the fetched waveforms, which can result in better performance at the expense of the usability of fetch(). + channels = [ch.strip() for ch in channels.split(",")] + num_channels = len(channels) + num_records = 1000 + total_num_wfms = num_channels * num_records + # preallocate a single array for all samples in all waveforms + # Supported array types are: numpy.float64, numpy.int8, numpy.int16, numpy.int32 + # int8, int16, int32 are for fetching unscaled data, which is the fastest way to fetch. + # Gain and Offset are stored in the returned WaveformInfo objects and can be applied to the data by the user later. + + wfm = numpy.ndarray(length * total_num_wfms, dtype=numpy.float64) + with niscope.Session(resource_name=resource_name, options=options) as session: + session.configure_vertical(range=2, coupling=niscope.VerticalCoupling.AC) + session.configure_horizontal_timing(min_sample_rate=100000000, min_num_pts=length, ref_position=50.0, num_records=num_records, enforce_realtime=True) + total_samples = int(total_acquisition_time_in_seconds * sample_rate_in_hz) + with session.initiate(): + waveforms = session.channels[channels].fetch_into(waveform=wfm, num_records=num_records) + for i in range(len(waveforms)): + time.sleep(0.2) + panel.set_value("samples", total_samples) + panel.set_value("Waveform", waveforms[i].samples.tolist()) + + +def _main(argsv): + parser = argparse.ArgumentParser(description='Fetches data directly into a preallocated numpy array.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='Dev2', help='Resource name of an NI digitizer.') + parser.add_argument('-c', '--channels', default='0', help='Channel(s) to use') + parser.add_argument('-l', '--length', default=100, type=int, help='Measure record length') + parser.add_argument('-v', '--voltage', default=1.0, type=float, help='Voltage range (V)') + parser.add_argument('-op', '--option-string', default='', type=str, help='Option string') + parser.add_argument("-t", "--time", default=10, type=int, help="Time to sample (s)") + parser.add_argument("-r", "--sample-rate", default=1000.0, type=float, help="Sample Rate (Hz)") + parser.add_argument( + "-s", "--samples-per-fetch", default=100, type=int, help="Samples per fetch" + ) + args = parser.parse_args(argsv) + example(args.resource_name, args.channels, args.option_string, args.length, args.voltage, args.time, + args.sample_rate, + args.samples_per_fetch) + + + +def main(): + _main(sys.argv[1:]) + + +def test_example(): + options = {'simulate': True, 'driver_setup': {'Model': '5124', 'BoardType': 'PXI', }, } + example('Dev2', '0, 1', options, 100, 1.0) + + +def test_main(): + cmd_line = ['--option-string', 'Simulate=1, DriverSetup=Model:5164; BoardType:PXIe', ] + _main(cmd_line) + + +if __name__ == '__main__': + main() + +# # We use fetch_into which allows us to allocate a single buffer per channel and "fetch into" it a section at a time without having to +# # reconstruct the waveform once we are done +# def example( +# resource_name, +# options, +# total_acquisition_time_in_seconds, +# voltage, +# sample_rate_in_hz, +# samples_per_fetch, +# ): +# total_samples = int(total_acquisition_time_in_seconds * sample_rate_in_hz) +# # 1. Opening session +# with niscope.Session(resource_name=resource_name, options=options) as session: +# # We will acquire on all channels of the device +# channel_list = [ +# c for c in range(session.channel_count) +# ] # Need an actual list and not a range + +# # 2. Creating numpy arrays +# waveforms = [np.ndarray(total_samples, dtype=np.float64) for c in channel_list] +# offset = session._fetch_offset + +# # 3. Configuring +# session.configure_horizontal_timing( +# min_sample_rate=sample_rate_in_hz, +# min_num_pts=1, +# ref_position=0.0, +# num_records=1, +# enforce_realtime=True, +# ) +# session.channels[channel_list].configure_vertical( +# voltage, coupling=niscope.VerticalCoupling.DC, enabled=True +# ) +# # Configure software trigger, but never send the trigger. +# # This starts an infinite acquisition, until you call session.abort() or session.close() +# session.configure_trigger_software() +# current_pos = 0 + +# # 4. initiating +# with session.initiate(): +# while current_pos < total_samples: +# # We fetch each channel at a time so we don't have to de-interleave afterwards +# # We do not keep the wfm_info returned from fetch_into +# for channel, waveform in zip(channel_list, waveforms): +# data = waveform.tolist() +# panel.set_value("total", current_pos) +# time.sleep(0.2) +# panel.set_value("Waveform", data) +# panel.set_value("samples", total_samples) +# # session.channels[channel].fetch(num_samples=1000) +# # 5. fetching - we return the slice of the waveform array that we want to "fetch into" +# session.channels[channel].fetch_into( +# waveform[current_pos : current_pos + samples_per_fetch], +# relative_to=niscope.FetchRelativeTo.READ_POINTER, +# offset=0, +# record_number=0, +# num_records=1, +# timeout=hightime.timedelta(seconds=5.0), +# ) +# current_pos += samples_per_fetch + + +# def _main(argsv): +# parser = argparse.ArgumentParser( +# description="Fetch more samples than will fit in memory.", +# formatter_class=argparse.ArgumentDefaultsHelpFormatter, +# ) +# parser.add_argument( +# "-n", "--resource-name", default="Dev2", help="Resource name of an NI digitizer." +# ) +# parser.add_argument("-t", "--time", default=10, type=int, help="Time to sample (s)") +# parser.add_argument("-v", "--voltage", default=1.0, type=float, help="Voltage range (V)") +# parser.add_argument("-op", "--option-string", default="", type=str, help="Option string") +# parser.add_argument("-r", "--sample-rate", default=1000.0, type=float, help="Sample Rate (Hz)") +# parser.add_argument( +# "-s", "--samples-per-fetch", default=100, type=int, help="Samples per fetch" +# ) +# args = parser.parse_args(argsv) +# example( +# args.resource_name, +# args.option_string, +# args.time, +# args.voltage, +# args.sample_rate, +# args.samples_per_fetch, +# ) + + +# def main(): +# _main(sys.argv[1:]) + + +# def test_example(): +# options = { +# "simulate": True, +# "driver_setup": { +# "Model": "5124", +# "BoardType": "PXI", +# }, +# } +# example("Dev2", options, 10, 1.0, 1000.0, 100) + + +# def test_main(): +# cmd_line = [ +# "--option-string", +# "Simulate=1, DriverSetup=Model:5124; BoardType:PXI", +# ] +# _main(cmd_line) + + +# if __name__ == "__main__": +# main() + + diff --git a/examples/nidaqmx/niscope_panel.py b/examples/nidaqmx/niscope_panel.py new file mode 100644 index 0000000..7fae255 --- /dev/null +++ b/examples/nidaqmx/niscope_panel.py @@ -0,0 +1,39 @@ +import streamlit as st +from streamlit_echarts import st_echarts + +import nipanel + +panel = nipanel.get_panel_accessor() + +waveform = panel.get_value("Waveform") +samples = panel.get_value("samples") +graph = { + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Amplitude (V)"]}, + "xAxis": { + "type": "category", + "data": samples, + "name": "Samples", + "nameLocation": "center", + "nameGap": 40, + }, + "yAxis": { + "type": "value", + "name": "Amplitude(V)", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "niscope data", + "type": "line", + "data": waveform, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + + ], +} +st_echarts(options=graph, height="400px") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 0b8cfc7..15808cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,13 @@ sphinx-autoapi = ">=1.8.4" m2r2 = ">=0.3.2" toml = ">=0.10.2" +[tool.poetry.group.examples] +optional = true + +[tool.poetry.group.examples.dependencies] +streamlit-echarts = ">=0.4.0" +nidaqmx = ">=0.8.0" + [build-system] requires = ["poetry-core>=1.8.0"] build-backend = "poetry.core.masonry.api" From 336d7b5af4575a41bd92958151e04214b8f6a43a Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 25 Jun 2025 14:22:35 -0500 Subject: [PATCH 03/50] Rename Signed-off-by: Dilmi Wickramanayake --- examples/nidaqmx/niscope_example.py | 194 ------------------ .../nidaqmx_continuous_analog_input.py | 38 ---- .../nidaqmx_continuous_analog_input_panel.py | 168 --------------- examples/niscope/niscope_example.py | 95 +++++++++ .../{nidaqmx => niscope}/niscope_panel.py | 0 5 files changed, 95 insertions(+), 400 deletions(-) delete mode 100644 examples/nidaqmx/niscope_example.py delete mode 100644 examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py delete mode 100644 examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py create mode 100644 examples/niscope/niscope_example.py rename examples/{nidaqmx => niscope}/niscope_panel.py (100%) diff --git a/examples/nidaqmx/niscope_example.py b/examples/nidaqmx/niscope_example.py deleted file mode 100644 index 2f88b80..0000000 --- a/examples/nidaqmx/niscope_example.py +++ /dev/null @@ -1,194 +0,0 @@ -import argparse -import niscope -import numpy -import pprint -import sys -import nipanel -from pathlib import Path -import time -pp = pprint.PrettyPrinter(indent=4, width=80) -panel_script_path = Path(__file__).with_name("niscope_panel.py") -panel = nipanel.create_panel(panel_script_path) - -# def example( -# resource_name, -# options, -# -# ): -# - -def example(resource_name, channels, options, length, total_acquisition_time_in_seconds, voltage, sample_rate_in_hz, samples_per_fetch,): - # fetch_into() allows you to preallocate and reuse the destination of the fetched waveforms, which can result in better performance at the expense of the usability of fetch(). - channels = [ch.strip() for ch in channels.split(",")] - num_channels = len(channels) - num_records = 1000 - total_num_wfms = num_channels * num_records - # preallocate a single array for all samples in all waveforms - # Supported array types are: numpy.float64, numpy.int8, numpy.int16, numpy.int32 - # int8, int16, int32 are for fetching unscaled data, which is the fastest way to fetch. - # Gain and Offset are stored in the returned WaveformInfo objects and can be applied to the data by the user later. - - wfm = numpy.ndarray(length * total_num_wfms, dtype=numpy.float64) - with niscope.Session(resource_name=resource_name, options=options) as session: - session.configure_vertical(range=2, coupling=niscope.VerticalCoupling.AC) - session.configure_horizontal_timing(min_sample_rate=100000000, min_num_pts=length, ref_position=50.0, num_records=num_records, enforce_realtime=True) - total_samples = int(total_acquisition_time_in_seconds * sample_rate_in_hz) - with session.initiate(): - waveforms = session.channels[channels].fetch_into(waveform=wfm, num_records=num_records) - for i in range(len(waveforms)): - time.sleep(0.2) - panel.set_value("samples", total_samples) - panel.set_value("Waveform", waveforms[i].samples.tolist()) - - -def _main(argsv): - parser = argparse.ArgumentParser(description='Fetches data directly into a preallocated numpy array.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('-n', '--resource-name', default='Dev2', help='Resource name of an NI digitizer.') - parser.add_argument('-c', '--channels', default='0', help='Channel(s) to use') - parser.add_argument('-l', '--length', default=100, type=int, help='Measure record length') - parser.add_argument('-v', '--voltage', default=1.0, type=float, help='Voltage range (V)') - parser.add_argument('-op', '--option-string', default='', type=str, help='Option string') - parser.add_argument("-t", "--time", default=10, type=int, help="Time to sample (s)") - parser.add_argument("-r", "--sample-rate", default=1000.0, type=float, help="Sample Rate (Hz)") - parser.add_argument( - "-s", "--samples-per-fetch", default=100, type=int, help="Samples per fetch" - ) - args = parser.parse_args(argsv) - example(args.resource_name, args.channels, args.option_string, args.length, args.voltage, args.time, - args.sample_rate, - args.samples_per_fetch) - - - -def main(): - _main(sys.argv[1:]) - - -def test_example(): - options = {'simulate': True, 'driver_setup': {'Model': '5124', 'BoardType': 'PXI', }, } - example('Dev2', '0, 1', options, 100, 1.0) - - -def test_main(): - cmd_line = ['--option-string', 'Simulate=1, DriverSetup=Model:5164; BoardType:PXIe', ] - _main(cmd_line) - - -if __name__ == '__main__': - main() - -# # We use fetch_into which allows us to allocate a single buffer per channel and "fetch into" it a section at a time without having to -# # reconstruct the waveform once we are done -# def example( -# resource_name, -# options, -# total_acquisition_time_in_seconds, -# voltage, -# sample_rate_in_hz, -# samples_per_fetch, -# ): -# total_samples = int(total_acquisition_time_in_seconds * sample_rate_in_hz) -# # 1. Opening session -# with niscope.Session(resource_name=resource_name, options=options) as session: -# # We will acquire on all channels of the device -# channel_list = [ -# c for c in range(session.channel_count) -# ] # Need an actual list and not a range - -# # 2. Creating numpy arrays -# waveforms = [np.ndarray(total_samples, dtype=np.float64) for c in channel_list] -# offset = session._fetch_offset - -# # 3. Configuring -# session.configure_horizontal_timing( -# min_sample_rate=sample_rate_in_hz, -# min_num_pts=1, -# ref_position=0.0, -# num_records=1, -# enforce_realtime=True, -# ) -# session.channels[channel_list].configure_vertical( -# voltage, coupling=niscope.VerticalCoupling.DC, enabled=True -# ) -# # Configure software trigger, but never send the trigger. -# # This starts an infinite acquisition, until you call session.abort() or session.close() -# session.configure_trigger_software() -# current_pos = 0 - -# # 4. initiating -# with session.initiate(): -# while current_pos < total_samples: -# # We fetch each channel at a time so we don't have to de-interleave afterwards -# # We do not keep the wfm_info returned from fetch_into -# for channel, waveform in zip(channel_list, waveforms): -# data = waveform.tolist() -# panel.set_value("total", current_pos) -# time.sleep(0.2) -# panel.set_value("Waveform", data) -# panel.set_value("samples", total_samples) -# # session.channels[channel].fetch(num_samples=1000) -# # 5. fetching - we return the slice of the waveform array that we want to "fetch into" -# session.channels[channel].fetch_into( -# waveform[current_pos : current_pos + samples_per_fetch], -# relative_to=niscope.FetchRelativeTo.READ_POINTER, -# offset=0, -# record_number=0, -# num_records=1, -# timeout=hightime.timedelta(seconds=5.0), -# ) -# current_pos += samples_per_fetch - - -# def _main(argsv): -# parser = argparse.ArgumentParser( -# description="Fetch more samples than will fit in memory.", -# formatter_class=argparse.ArgumentDefaultsHelpFormatter, -# ) -# parser.add_argument( -# "-n", "--resource-name", default="Dev2", help="Resource name of an NI digitizer." -# ) -# parser.add_argument("-t", "--time", default=10, type=int, help="Time to sample (s)") -# parser.add_argument("-v", "--voltage", default=1.0, type=float, help="Voltage range (V)") -# parser.add_argument("-op", "--option-string", default="", type=str, help="Option string") -# parser.add_argument("-r", "--sample-rate", default=1000.0, type=float, help="Sample Rate (Hz)") -# parser.add_argument( -# "-s", "--samples-per-fetch", default=100, type=int, help="Samples per fetch" -# ) -# args = parser.parse_args(argsv) -# example( -# args.resource_name, -# args.option_string, -# args.time, -# args.voltage, -# args.sample_rate, -# args.samples_per_fetch, -# ) - - -# def main(): -# _main(sys.argv[1:]) - - -# def test_example(): -# options = { -# "simulate": True, -# "driver_setup": { -# "Model": "5124", -# "BoardType": "PXI", -# }, -# } -# example("Dev2", options, 10, 1.0, 1000.0, 100) - - -# def test_main(): -# cmd_line = [ -# "--option-string", -# "Simulate=1, DriverSetup=Model:5124; BoardType:PXI", -# ] -# _main(cmd_line) - - -# if __name__ == "__main__": -# main() - - diff --git a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py deleted file mode 100644 index 246e053..0000000 --- a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ /dev/null @@ -1,38 +0,0 @@ -"""This example demonstrates how to open/update a Streamlit application using nipanel package.""" - -import nipanel -import nidaqmx -import pathlib -import time - -script_path = pathlib.Path(__file__) -panel_script_path = str(script_path.with_name("nidaqmx_continuous_analog_input_panel.py")) - -panel = nipanel.StreamlitPanel( - panel_id="nidaqmx_continuous_analog_input_panel", - streamlit_script_path=panel_script_path, -) - -data_arr = [] -with nidaqmx.Task() as task: - task.ai_channels.add_ai_voltage_chan("Mod1/ai2") - task.ai_channels.add_ai_thrmcpl_chan("Mod1/ai3") - try: - total_read = 0 - while True: - data = task.read(number_of_samples_per_channel=3) - read = len(data) - total_read += read - - data_arr.append(data) - time.sleep(1) - panel.set_value("amplitude",data_arr[-1][-1]) - panel.set_value("Volts",data_arr[-1][0]) - except KeyboardInterrupt: - pass - finally: - task.stop() - print(f"\nAcquired {total_read} total samples.") - - - diff --git a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py deleted file mode 100644 index b83f09b..0000000 --- a/examples/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py +++ /dev/null @@ -1,168 +0,0 @@ -"""Streamlit application script for displaying values using nipanel package.""" -import nipanel -import streamlit as st -import streamlit.components.v1 as components -from streamlit_echarts import st_echarts - -panel = nipanel.StreamlitPanelValueAccessor(panel_id="nidaqmx_continuous_analog_input_panel") - -add_refresh_component = components.declare_component( - "panelRefreshComponent", - url=f"http://localhost:42001/panels/refresh/{panel.panel_id}",) -add_refresh_component() - - -st.title("Analog Input - Voltage and Thermocouple in a Single Task") -voltage_tab, thermocouple_tab = st.tabs(["Voltage", "Thermocouple"]) - -st.markdown( - """ - - """, - unsafe_allow_html=True -) - - -list_of_therm_amp = panel.get_value("amplitude") -list_of_voltage_amp = panel.get_value("Volts") - -if "therm_history" not in st.session_state: - st.session_state.therm_history = [] -if "volts_history" not in st.session_state: - st.session_state.volts_history = [] - -for therm_amp in list_of_therm_amp: - st.session_state.therm_history.append(therm_amp) -for voltage_amp in list_of_voltage_amp: - st.session_state.volts_history.append(voltage_amp) - -therm_amp_graph = { - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["thermocouple_amplitude"]}, - "xAxis": { - "type": "category", - "data":list(range(len(st.session_state.therm_history))), - "name": "Time" - }, - "yAxis": { - "type": "value", - "name": "Thermocouple Amplitude" - }, - "series": [ - { - "name": "thermocouple_amplitude", - "type": "line", - "data": st.session_state.therm_history, - "color": "red" - }, - - - ], -} -st_echarts(options=therm_amp_graph, height="400px") - -voltage_amp_graph = { - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["voltage_amplitude"]}, - "xAxis": { - "type": "category", - "data": list(range(len(st.session_state.volts_history))), - "name": "Time" - }, - "yAxis": { - "type": "value", - "name": "Voltage Amplitude" - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": st.session_state.volts_history, - }, - - ], -} -st_echarts(options=voltage_amp_graph, height="400px") - -st.header("Voltage & Thermocouple") -voltage_therm_graph = { - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["voltage_amplitude", "thermocouple_amplitude"]}, - "xAxis": { - "type": "category", - "data": list(range(len(st.session_state.volts_history))), - "name": "Time" - }, - "yAxis": { - "type": "value", - "name": "Voltage and Thermocouple Amplitude" - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": st.session_state.volts_history, - "emphasis": {"focus":"series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - { - "name": "thermocouple_amplitude", - "type": "line", - "data": st.session_state.therm_history, - "color": "red", - "emphasis": {"focus":"series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - ], -} -st_echarts(options=voltage_therm_graph, height="400px") - -with voltage_tab: - left_volt_tab, center_volt_tab, right_volt_tab = st.columns(3) - with left_volt_tab: - st.selectbox(options=["Mod1/ai2"], label="Physical Channels", disabled=True) - st.selectbox(options=["Off"], label="Logging Modes", disabled=False) - with center_volt_tab: - st.selectbox(options=["-5"],label="Min Value") - st.selectbox(options=["5"],label="Max Value") - st.selectbox(options=["1000"], label="Samples per Loops", disabled=False) - with right_volt_tab: - st.selectbox(options=["default"], label="Terminal Configurations") - st.selectbox(options=["OnboardClock"], label="Sample Clock Sources", disabled=False) - - -thermocouple_tab.header("Thermocouple") -with thermocouple_tab: - left, middle, right = st.columns(3) - with left: - st.selectbox(options=["Mod1/ai3"], label="Physical Channel", disabled=True) - st.selectbox(options=["0"], label="Min", disabled=False) - st.selectbox(options=["100"], label="Max", disabled=False) - st.selectbox(options=["Off"], label="Logging Mode", disabled=False) - - with middle: - st.selectbox(options=["Deg C"], label = "Units", disabled=False) - st.selectbox(options=["J"], label="Thermocouple Type", disabled=False) - st.selectbox(options=["Constant Value"], label="CJC Source", disabled=False) - st.selectbox(options=["1000"], label="Samples per Loop", disabled=False) - with right: - st.selectbox(options=["25"],label="CJC Value", disabled=False) - st.selectbox(options=["OnboardClock"], label="Sample Clock Source", disabled=False) - st.selectbox(options=[" "], label="Actual Sample Rate", disabled=True) - - - - - - - - - - - diff --git a/examples/niscope/niscope_example.py b/examples/niscope/niscope_example.py new file mode 100644 index 0000000..3429bd3 --- /dev/null +++ b/examples/niscope/niscope_example.py @@ -0,0 +1,95 @@ +import argparse +import niscope +import numpy as np +import pprint +import sys +import nipanel +from pathlib import Path +import time +import hightime +pp = pprint.PrettyPrinter(indent=4, width=80) +panel_script_path = Path(__file__).with_name("niscope_panel.py") +panel = nipanel.create_panel(panel_script_path) + + + +def example(resource_name, channels, options, length, total_acquisition_time_in_seconds, voltage, sample_rate_in_hz, samples_per_fetch,): + channels = [ch.strip() for ch in channels.split(",")] + num_channels = len(channels) + + num_records = 1000 + total_num_wfms = num_channels * num_records + current_pos = 0 + # preallocate a single array for all samples in all waveforms + # Supported array types are: numpy.float64, numpy.int8, numpy.int16, numpy.int32 + # int8, int16, int32 are for fetching unscaled data, which is the fastest way to fetch. + # Gain and Offset are stored in the returned WaveformInfo objects and can be applied to the data by the user later. + total_samples = int(total_acquisition_time_in_seconds * sample_rate_in_hz) + wfm = np.ndarray(length * total_num_wfms, dtype=np.int8) + with niscope.Session(resource_name=resource_name, options=options) as session: + + session.configure_vertical(range=10, coupling=niscope.VerticalCoupling.DC, enabled=True) + session.configure_horizontal_timing(min_sample_rate=100000000, min_num_pts=length, ref_position=50.0, num_records=num_records, enforce_realtime=True) + max_points_per_fetch = 1000 + session._fetch_meas_num_samples = max_points_per_fetch + session.configure_trigger_software() + + with session.initiate(): + waveforms = session.channels[channels].fetch_into( relative_to=niscope.FetchRelativeTo.READ_POINTER, + offset=0, record_number=0, timeout=hightime.timedelta(seconds=5.0), waveform=wfm, num_records=num_records) + offset = session._fetch_offset + gain = session.meas_array_gain + for i in range(len(waveforms)): + time.sleep(1) + amplitude_list = [] + current_pos += samples_per_fetch + panel.set_value("samples", total_samples) + + total_data = waveforms[i].samples.tolist() + print(waveforms[i]) + for amplitude in total_data: + amplitude = (amplitude * 10) * gain + offset + amplitude_list.append(amplitude) + panel.set_value("Waveform", amplitude_list) + +def _main(argsv): + parser = argparse.ArgumentParser(description='Fetches data directly into a preallocated numpy array.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='Dev2', help='Resource name of an NI digitizer.') + parser.add_argument('-c', '--channels', default='0', help='Channel(s) to use') + parser.add_argument('-l', '--length', default=100, type=int, help='Measure record length') + parser.add_argument('-v', '--voltage', default=1.0, type=float, help='Voltage range (V)') + parser.add_argument('-op', '--option-string', default='', type=str, help='Option string') + parser.add_argument("-t", "--time", default=1, type=int, help="Time to sample (s)") + parser.add_argument("-r", "--sample-rate", default=1000.0, type=float, help="Sample Rate (Hz)") + parser.add_argument( + "-s", "--samples-per-fetch", default=1000, type=int, help="Samples per fetch" + ) + args = parser.parse_args(argsv) + example(args.resource_name, + args.channels, + args.option_string, + args.length, + args.voltage, + args.time, + args.sample_rate, + args.samples_per_fetch) + + + +def main(): + _main(sys.argv[1:]) + + +def test_example(): + options = {'simulate': True, 'driver_setup': {'Model': '5124', 'BoardType': 'PXI', }, } + example("Dev2", options, 1, 1.0, 1000.0, 1000) + + +def test_main(): + cmd_line = ['--option-string', 'Simulate=1, RangeCheck=1, DriverSetup=Model:5124; BoardType:PXI', ] + _main(cmd_line) + + +if __name__ == '__main__': + main() + diff --git a/examples/nidaqmx/niscope_panel.py b/examples/niscope/niscope_panel.py similarity index 100% rename from examples/nidaqmx/niscope_panel.py rename to examples/niscope/niscope_panel.py From a8f847ba0ac70c06d608e81a1049791024382f89 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 8 Jul 2025 09:40:10 -0500 Subject: [PATCH 04/50] Analog Input Filtering --- .../nidaqmx_continuous_analog_input.py | 4 +- .../nidaqmx_analog_input_filtering.py | 64 +++--- .../nidaqmx_analog_input_filtering_panel.py | 193 +++++++++++++++--- .../settings_enum.py | 12 +- 4 files changed, 220 insertions(+), 53 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input.py index f3ab592..6abbfda 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input.py @@ -11,8 +11,8 @@ panel = nipanel.create_panel(panel_script_path) with nidaqmx.Task() as task: - task.ai_channels.add_ai_voltage_chan("Dev1/ai0") - task.ai_channels.add_ai_thrmcpl_chan("Dev1/ai1") + task.ai_channels.add_ai_voltage_chan("Mod1/ai0") + task.ai_channels.add_ai_thrmcpl_chan("Mod1/ai1") task.timing.cfg_samp_clk_timing( rate=1000.0, sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=3000 ) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 83f9d1c..a55a076 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -4,8 +4,8 @@ import nidaqmx -from nidaqmx.constants import AcquisitionType, ExcitationSource, Edge, Slope -from settings_enum import DigitalEdge, PauseWhen, Slopes, AnalogPause +from nidaqmx.constants import AcquisitionType, ExcitationSource, Edge, Slope, Timescale, TerminalConfiguration +from settings_enum import DigitalEdge, PauseWhen, Slopes, AnalogPause, TerminalConfig import nipanel import time @@ -13,18 +13,45 @@ panel = nipanel.create_panel(panel_script_path) - with nidaqmx.Task() as task: - chan_voltage = task.ai_channels.add_ai_voltage_chan("Mod3/ai10") - chan_strain_gage = task.ai_channels.add_ai_strain_gage_chan("Mod3/ai7", voltage_excit_source=ExcitationSource.EXTERNAL) - chan_current = task.ai_channels.add_ai_current_chan("Mod3/ai9") + terminal_config = TerminalConfig(panel.get_value("terminal_config", TerminalConfig.RSE.value)) + chan_voltage = task.ai_channels.add_ai_voltage_chan("Mod3/ai10", terminal_config=TerminalConfiguration.DEFAULT) + chan_strain_gage = task.ai_channels.add_ai_strain_gage_chan("Mod3/ai7", voltage_excit_source=ExcitationSource.EXTERNAL, max_val=0.001, min_val=-0.001) + chan_current = task.ai_channels.add_ai_current_chan("Mod3/ai9", max_val = 0.01, min_val= -0.01, ext_shunt_resistor_val=249) task.timing.cfg_samp_clk_timing( - rate = 1000.0, sample_mode = AcquisitionType.CONTINUOUS, samps_per_chan = 3000 + rate = 1000.0, sample_mode = AcquisitionType.CONTINUOUS, samps_per_chan = 1000 ) - + task.timing.samp_clk_dig_fltr_min_pulse_width = 20.0e-6 task.timing.samp_clk_dig_fltr_enable = True chan_voltage.ai_filter_response + filter = panel.get_value("filter", "No Filtering") + if filter == "No Filtering": + chan_voltage.ai_filter_freq = 0.0 + chan_current.ai_filter_freq = 0.0 + chan_strain_gage.ai_filter_freq = 0.0 + + chan_voltage.ai_filter_order = 0 + chan_current.ai_filter_order = 0 + chan_strain_gage.ai_filter_order = 0 + + chan_voltage.ai_filter_response = panel.get_value("filter_response", "Comb") + chan_current.ai_filter_response = panel.get_value("filter_response", "Comb") + chan_strain_gage.ai_filter_response = panel.get_value("filter_response", "Comb") + else: + chan_voltage.ai_filter_freq = panel.get_value("filter_freq", 1000.0) + chan_current.ai_filter_freq = panel.get_value("filter_freq", 1000.0) + chan_strain_gage.ai_filter_freq = panel.get_value("filter_freq", 1000.0) + + chan_voltage.ai_filter_order = panel.get_value("filter_order", 1) + chan_current.ai_filter_order = panel.get_value("filter_order", 1) + chan_strain_gage.ai_filter_order = panel.get_value("filter_order", 1) + + chan_voltage.ai_filter_response = panel.get_value("filter_response", "Comb") + chan_current.ai_filter_response = panel.get_value("filter_response", "Comb") + chan_strain_gage.ai_filter_response = panel.get_value("filter_response", "Comb") + + panel.set_value("source", [task.triggers.pause_trigger.dig_lvl_src]) panel.set_value("analog_source", [task.triggers.start_trigger.anlg_edge_src]) @@ -49,7 +76,11 @@ print(f"Press Ctrl + C to stop") while True: + date = panel.get_value("date", None) + time_input = panel.get_value("time", None) + hysteriresis = panel.get_value("hysteriesis", 0.0) + task.triggers.start_trigger.cfg_time_start_trig(when = date, timescale=Timescale.USE_HOST) level = panel.get_value("level", 0.0) new_slope = Slopes(panel.get_value("slope",Slopes.FALLING.value)) if slope != new_slope: @@ -59,6 +90,7 @@ task.triggers.start_trigger.cfg_anlg_edge_start_trig(trigger_source="APFI0", trigger_level=level, trigger_slope= Slope.RISING) else: task.triggers.start_trigger.cfg_anlg_edge_start_trig(trigger_source="APFI0", trigger_level=level, trigger_slope= Slope.FALLING) + task.triggers.start_trigger.anlg_edge_hyst = hysteriresis task.start() slope = new_slope @@ -88,21 +120,7 @@ task.triggers.start_trigger.cfg_dig_edge_start_trig - # task.triggers.start_trigger.cfg_dig_edge_start_trig(trigger_source="/Dev2/te1/SampleClock") - # task.triggers.start_trigger.cfg_time_start_trig(10) - # task.triggers.start_trigger.cfg_anlg_edge_start_trig(trigger_source="APFI0") - # Configure a digital pause trigger (example) - # Replace "PFI0" with your actual trigger source if needed - - # task.triggers.pause_trigger.trig_type = TriggerType.DIGITAL_LEVEL - # task.triggers.pause_trigger.dig_lvl_src = "/Dev2/PFI0" - - # task.triggers.pause_trigger.dig_lvl_when - # task.triggers.pause_trigger.trig_type = TriggerType.ANALOG_LEVEL - # task.triggers.pause_trigger.anlg_lvl_src - # task.triggers.pause_trigger.anlg_lvl_when - - + data = task.read(number_of_samples_per_channel=100) panel.set_value("voltage_data", data[0]) panel.set_value("current_data", data[2]) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 6c7c312..eff6cd4 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -2,7 +2,7 @@ import streamlit as st from streamlit_echarts import st_echarts -from settings_enum import DigitalEdge, PauseWhen, Slopes, AnalogPause +from settings_enum import DigitalEdge, PauseWhen, Slopes, AnalogPause, TerminalConfig import time import nipanel @@ -13,8 +13,6 @@ panel = nipanel.get_panel_accessor() -tabs = st.tabs(["Voltage", "Current", "Strain Gage"]) - st.markdown( """ """ -st.markdown(streamlit_style, unsafe_allow_html=True) - -source = panel.get_value("source", []) -analog_source = panel.get_value("analog_source", []) +st.markdown(streamlit_style, unsafe_allow_html=True) -voltage_data = panel.get_value("voltage_data", [1.0]) -current_data = panel.get_value("current_data", [1.0]) -strain_data = panel.get_value("strain_data", [1.0]) -sample_rate = panel.get_value("sample_rate", 0.0) -data_type = "" -with right_col: +with left_col: with st.container(border=True): st.title("Channel Settings") st.selectbox(options=["Mod3/ai10"], index=0, label="Physical Channels", disabled=True) - terminal_config = st.selectbox( - "terminal_config", - options=[(e.name, e.value) for e in TerminalConfig], - format_func=lambda x: x[0], - index=0, - ) - terminal_config = TerminalConfig[terminal_config[0]] - - panel.set_value("terminal_config", terminal_config) + enum_selectbox( + panel, + label="Terminal Configuration", + value=TerminalConfiguration.DEFAULT, + disabled=panel.get_value("is_running", False), + key="terminal_configuration", + ) st.title("Timing Settings") - st.selectbox("Sample Clock Source", options=["Onboard Clock"], index=0) - st.number_input("Sample Rate", value=1000, min_value=1, step=1) - st.number_input("Number of Samples", value=100, min_value=1, step=1) - st.selectbox("Actual Sample Rate", options=[""], disabled=True) + + st.selectbox("Sample Clock Source", options=["Onboard Clock"], index=0, disabled=True) + st.number_input( + "Sample Rate", + value=1000, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + ) + st.number_input( + "Number of Samples", + value=100, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + ) + st.selectbox("Actual Sample Rate", options=[panel.get_value("sample_rate")], disabled=True) st.title("Logging Settings") - st.selectbox("Logging Mode", options=["Off", "Log and Read"], index=0) - st.text_input("TDMS File Path", value="data.tdms") - + enum_selectbox( + panel, + label="Logging Mode", + value=LoggingMode.OFF, + disabled=panel.get_value("is_running", False), + key="logging_mode", + ) + tdms_file_path = st.text_input( + label="TDMS File Path", + disabled=panel.get_value("is_running", False), + value="data.tdms", + key="tdms_file_path", + ) st.title("Filtering Settings") - filter = st.selectbox("Filter", options = ["No Filtering", "Filter"]) + + filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) panel.set_value("filter", filter) - - filter_freq = st.number_input("Filtering Frequency", value = 1000.0, step = 1.0) - st.write(filter_freq) + enum_selectbox( + panel, + label="Filter Response", + value=FilterResponse.COMB, + disabled=panel.get_value("is_running", False), + key="filter_response", + ) + + filter_freq = st.number_input( + "Filtering Frequency", + value=1000.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + filter_order = st.number_input( + "Filter Order", + min_value=0, + max_value=1, + value=0, + disabled=panel.get_value("is_running", False), + ) + if filter == "No Filtering": + filter_freq = 0.0 + filter_order = 0 panel.set_value("filter_freq", filter_freq) - filter_order = st.number_input("Filter Order", min_value=0, max_value=1, value=0) + panel.set_value("filter_order", filter_order) - filter_response = st.selectbox("Filter Response", options=["Comb"]) - panel.set_value("filter_response", filter_response) - if filter == "No Filtering": - panel.set_value("filter_freq", 0.0) - st.selectbox("Actual Filter Frequency", options=[""], disabled=True) + st.selectbox("Actual Filter Frequency", options=[filter_freq], disabled=True) st.selectbox("Actual Filter Order", options=[filter_order], disabled=True) - st.selectbox("Actual Filter Response", options=[filter_response], disabled=True) - +with right_col: + voltage_data = panel.get_value("voltage_data", [1.0]) + current_data = panel.get_value("current_data", [1.0]) + strain_data = panel.get_value("strain_data", [1.0]) -with left_col: +sample_rate = panel.get_value("sample_rate", 0.0) +with right_col: with st.container(border=True): graph = { "animation": False, @@ -151,49 +191,124 @@ def run_update(): ], } st_echarts(options=graph, height="400px", key="graph", width="100%") -with left_col: + + +with right_col: with st.container(border=True): - tabs = st.tabs(["Voltage", "Current", "Strain Gage"]) -with left_col: + st.title("Trigger Settings") + tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs( + [ + "No Trigger", + "Digital Start", + "Digital Pause", + "Digital Reference", + "Analog Start", + "Analog Pause", + "Analog Reference", + "Time Start", + ] + ) + with tab1: + st.write( + "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." + ) + with tab2: + st.selectbox("Source->", " /Dev1/PFI0") + enum_selectbox( + panel, + label="Edge", + value=Edge.FALLING, + disabled=panel.get_value("is_running", False), + key="edge", + ) + with tab3: + st.selectbox("Source-", "/Dev1/PFI0") + pause_when = st.selectbox( + "Pause When", + options=[(e.name, e.value) for e in PauseWhen], + format_func=lambda x: x[0], + index=0, + ) + pause_when = PauseWhen[pause_when[0]] + panel.set_value("pause_when", pause_when) + with tab4: + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + with tab5: + st.selectbox("Source:", "APFI0") + enum_selectbox( + panel, + label="Slope", + value=Slope.FALLING, + disabled=panel.get_value("is_running", False), + key="slope", + ) + + level = st.number_input("Level") + panel.set_value("level", level) + hysteriesis = st.number_input( + "Hysteriesis", disabled=panel.get_value("is_running", False) + ) + panel.set_value("hysteriesis", hysteriesis) + + with tab6: + st.selectbox("source:", "APFI0") + analog_pause = st.selectbox( + "analog_pause", + options=[(e.name, e.value) for e in AnalogPause], + format_func=lambda x: x[0], + index=0, + ) + analog_pause = AnalogPause[analog_pause[0]] + panel.set_value("analog_pause", analog_pause) + + with tab7: + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + ) + +with right_col: + tabs = st.tabs(["Voltage", "Current", "Strain Gage"]) with st.container(border=True): with tabs[0]: - data_type = "Voltage" st.title("Voltage Data") channel_left, channel_right = st.columns(2) with channel_left: - max_value_voltage = st.number_input( - "Max Value", - value=5.0, - step=0.1, + max_value_voltage = st.number_input( + "Max Value", value=5.0, step=0.1, disabled=panel.get_value("is_running", False) ) - panel.set_value("max_value_voltage",max_value_voltage) + panel.set_value("max_value_voltage", max_value_voltage) min_value_voltage = st.number_input( - "Min Value", - value=-5.0, - step=0.1, + "Min Value", value=-5.0, step=0.1, disabled=panel.get_value("is_running", False) ) panel.set_value("min_value_voltage", min_value_voltage) with tabs[1]: st.title("Current Data") - data_type = "Current" channel_left, channel_right = st.columns(2) with channel_left: - shunt_location = st.selectbox( - "shunt_location", - options=[(e.name, e.value) for e in ShuntLocation], - format_func=lambda x: x[0], - index=0, + enum_selectbox( + panel, + label="Shunt Resistor Location", + value=CurrentShuntResistorLocation.EXTERNAL, + disabled=panel.get_value("is_running", False), + key="shunt_location", + ) + enum_selectbox( + panel, + label="Units", + value=CurrentUnits.AMPS, + disabled=panel.get_value("is_running", False), + key="units", ) - shunt_location = ShuntLocation[shunt_location[0]] - panel.set_value("shunt_location", shunt_location) - st.selectbox(options=["Amps"], label="Units", index=0, disabled=True) with st.expander("More current info", expanded=False): min_value_current = st.number_input( "Min Value", value=-0.01, step=0.001, + disabled=panel.get_value("is_running", False), ) panel.set_value("min_value_current", min_value_current) max_value_current = st.number_input( @@ -201,16 +316,17 @@ def run_update(): value=0.01, step=1.0, key="max_value_current", + disabled=panel.get_value("is_running", False), ) current = panel.set_value("max_value_current", max_value_current) shunt_resistor_value = st.number_input( "Shunt Resistor Value", value=249.0, step=1.0, - ) + disabled=panel.get_value("is_running", False), + ) panel.set_value("shunt_resistor_value", shunt_resistor_value) with tabs[2]: - data_type = "Strain" st.title("Strain Gage Data") channel_left, channel_right = st.columns(2) with channel_left: @@ -221,36 +337,48 @@ def run_update(): ) panel.set_value("min_value_strain", min_value_strain) max_value_strain = st.number_input( - "Max Value", - value=0.01, - step=0.01, - max_value=2.0 + "Max Value", value=0.01, step=0.01, max_value=2.0 ) panel.set_value("max_value_strain", max_value_strain) - with st.expander("strain gage information", expanded=False): - st.title("strain gage information") + enum_selectbox( + panel, + label="Strain Units", + value=CurrentUnits.AMPS, + disabled=panel.get_value("is_running", False), + key="strain_units", + ) + with st.expander("Strain Gage Information", expanded=False): + st.title("Strain Gage Information") gage_factor = st.number_input( "Gage Factor", value=2.0, step=1.0, + disabled=panel.get_value("is_running", False), ) panel.set_value("gage_factor", gage_factor) nominal_gage = st.number_input( "nominal gage resistance", value=350.0, step=1.0, + disabled=panel.get_value("is_running", False), ) - panel.set_value("gage_resistance",nominal_gage) + panel.set_value("gage_resistance", nominal_gage) poisson_ratio = st.number_input( "poisson ratio", value=0.3, step=1.0, + disabled=panel.get_value("is_running", False), ) panel.set_value("poisson_ratio", poisson_ratio) - with st.expander("strain gage information", expanded=False): - st.title("bridge information") - st.selectbox(label="strain configuration", options=["Full Bridge I", "Quarter Bridge", "Half Bridge II", "Half Bridge I", "Full Bridge III", "Full Bridge II"], key="strain_config",index=0, disabled=False) - panel.set_value("strain_config", "strain_config") + with st.expander("Bridge Information", expanded=False): + st.title("Bridge Information") + enum_selectbox( + panel, + label="Strain Configuration", + value=StrainGageBridgeType.FULL_BRIDGE_I, + disabled=panel.get_value("is_running", False), + key="strain_configuration", + ) wire_resistance = st.number_input( "lead wire resistance", value=0.0, @@ -261,144 +389,22 @@ def run_update(): "initial bridge voltage", value=0.0, step=1.0, + disabled=panel.get_value("is_running", False), ) - panel.set_value("initial_voltage",initial_voltage) + panel.set_value("initial_voltage", initial_voltage) - st.selectbox(label="voltage excitation source", key = "voltage_excit",options=["External"], disabled=True) + st.selectbox( + label="voltage excitation source", + key="voltage_excit", + options=["External"], + disabled=True, + ) panel.set_value("voltage_excitation_source", "voltage_excit") voltage_excit = st.number_input( "voltage excitation value", value=2.5, step=1.0, key="voltage_excitation_value", + disabled=panel.get_value("is_running", False), ) - panel.set_value("voltage_excitation_value",voltage_excit) - -tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs(["No Trigger","Digital Start","Digital Pause","Digital Reference","Analog Start","Analog Pause", "Analog Reference", "Time Start"]) -with tab1: - st.write("To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information.") -with tab2: - st.selectbox("Source->", source) - edge_digital = st.selectbox( - "Edge", - options=[(e.name, e.value) for e in DigitalEdge], - format_func=lambda x: x[0], - index=0, - ) - edge_digital = DigitalEdge[edge_digital[0]] - panel.set_value("edge_digital", edge_digital) - -with tab3: - st.selectbox("Source-", source) - pause_when = st.selectbox( - "Pause When", - options=[(e.name, e.value) for e in PauseWhen], - format_func=lambda x: x[0], - index=0, - ) - pause_when = PauseWhen[pause_when[0]] - panel.set_value("pause_when", pause_when) -with tab4: - st.write("This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported") -with tab5: - st.selectbox("Source:", analog_source) - slope = st.selectbox( - "Slope", - options=[(e.name, e.value) for e in Slopes], - format_func=lambda x: x[0], - index=0, - ) - slope = Slopes[slope[0]] - panel.set_value("slope", slope) - - level = st.number_input("Level") - panel.set_value("level", level) - hysteriesis = st.number_input("Hysteriesis") - panel.set_value("hysteriesis", hysteriesis) - -with tab6: - st.selectbox("source:", analog_source) - analog_pause = st.selectbox( - "analog_pause", - options=[(e.name, e.value) for e in AnalogPause], - format_func=lambda x: x[0], - index=0, - ) - analog_pause = AnalogPause[analog_pause[0]] - panel.set_value("analog_pause", analog_pause) - -with tab7: - st.write("This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported.") -with tab8: - date = st.date_input("Date", value=None) - time_input = st.time_input("Time", value=None) - st.write("If time is not manually set, task will begin after 10 seconds") - - - -# graph_2= { -# "animation": False, -# "tooltip": {"trigger": "axis"}, -# "legend": {"data": ["Voltage (V)"]}, -# "xAxis": { -# "type": "category", -# "data": [x / sample_rate for x in range(len(current_data))], -# "name": "Time", -# "nameLocation": "center", -# "nameGap": 40, -# }, -# "yAxis": { -# "type": "value", -# "name": "Volts", -# "nameRotate": 90, -# "nameLocation": "center", -# "nameGap": 40, -# }, -# "series": [ -# { -# "name": "voltage_amplitude", -# "type": "line", -# "data": current_data, -# "emphasis": {"focus": "series"}, -# "smooth": True, -# "seriesLayoutBy": "row", -# }, -# ], -# } -# with tabs[1]: -# st_echarts(options=graph_2, height="400px", key="graph_2", width="100%") -# graph_3 = { -# "animation": False, -# "tooltip": {"trigger": "axis"}, -# "legend": {"data": ["Voltage (V)"]}, -# "xAxis": { -# "type": "category", -# "data": [x / sample_rate for x in range(len(strain_data))], -# "name": "Time", -# "nameLocation": "center", -# "nameGap": 40, -# }, -# "yAxis": { -# "type": "value", -# "name": "Volts", -# "nameRotate": 90, -# "nameLocation": "center", -# "nameGap": 40, -# }, -# "series": [ -# { -# "name": "voltage_amplitude", -# "type": "line", -# "data": strain_data, -# "emphasis": {"focus": "series"}, -# "smooth": True, -# "seriesLayoutBy": "row", -# }, -# ], -# } -# with tabs[2]: -# st_echarts(options=graph_3, height="400px", key="graph_3", width="100%") - - - - + panel.set_value("voltage_excitation_value", voltage_excit) diff --git a/examples/nidaqmx_analog_input_filtering/settings_enum.py b/examples/nidaqmx_analog_input_filtering/settings_enum.py index 09f2630..a2f208f 100644 --- a/examples/nidaqmx_analog_input_filtering/settings_enum.py +++ b/examples/nidaqmx_analog_input_filtering/settings_enum.py @@ -1,30 +1,13 @@ - """Enumeration for amplitude values used in the simple graph example.""" import enum -from nidaqmx.constants import Edge, Slope, Timescale, TerminalConfiguration -class DigitalEdge(enum.StrEnum): - FALLING = "FALLING" - RISING = "RISING" + class PauseWhen(enum.StrEnum): HIGH = "High" LOW = "Low" -class Slopes(enum.StrEnum): - FALLING = "Falling" - RISING = "Rising" class AnalogPause(enum.StrEnum): ABOVE = "ABOVE" BELOW = "BELOW" - -class TerminalConfig(enum.StrEnum): - DEFAULT = "DEFAULT" - RSE = "RSE" - NRSE = "NRSE" - DIFF = "DIFF" - PSEUDO_DIFF = "PSEUDO_DIFF" -class ShuntLocation(enum.StrEnum): - DEFAULT = "DEFAULT" - EXTERNAL = "EXTERNAL" \ No newline at end of file diff --git a/examples/niscope/niscope_ex_fetch_forever.py b/examples/niscope/niscope_ex_fetch_forever.py index e7da446..5f2a5ab 100644 --- a/examples/niscope/niscope_ex_fetch_forever.py +++ b/examples/niscope/niscope_ex_fetch_forever.py @@ -46,11 +46,7 @@ try: print(f"Press Ctrl + C to stop") while True: -<<<<<<< HEAD offset = session._fetch_offset -======= - offset = session.meas_array_offset ->>>>>>> main gain = session.meas_array_gain for i in range(len(waveforms)): time.sleep(0.2) From 0f7ddc176c0951ebd88d8910f8ab938a1c8dfdac Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 10:28:46 -0500 Subject: [PATCH 06/50] Added README.md --- .../nidaqmx_analog_input_filtering/README.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 examples/nidaqmx_analog_input_filtering/README.md diff --git a/examples/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx_analog_input_filtering/README.md new file mode 100644 index 0000000..5bd4314 --- /dev/null +++ b/examples/nidaqmx_analog_input_filtering/README.md @@ -0,0 +1,20 @@ +Prerequisites +=============== +Requires a Physical or Simulated Device. Refer to the [Getting Started Section](https://github.com/ni/nidaqmx-python/blob/master/README.rst) to learn how to create a simulated device. +## Sample + +This is a nipanel example that displays an interactive Streamlit app and updates and fetches data from device. + +### Feature + +Script demonstrates analog input data getting continuously acquired, and being filtered. +- Supports various data types + +### Required Software + +- Python 3.9 or later + +### Usage + +Run `poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py` + From 79ae4db9992ef4347e0e4ec0f07e885c8edb0f64 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 11:23:16 -0500 Subject: [PATCH 07/50] fixed mypy & lint errors --- .../nidaqmx_analog_input_filtering.py | 3 +- .../nidaqmx_analog_input_filtering_panel.py | 29 +++++++++---------- .../settings_enum.py | 4 +++ examples/simple_graph/simple_graph_panel.py | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index d15973a..562b2ef 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -3,7 +3,6 @@ from pathlib import Path import nidaqmx -import numpy as numpy from nidaqmx.constants import ( AcquisitionType, CurrentShuntResistorLocation, @@ -16,7 +15,6 @@ Slope, StrainGageBridgeType, TerminalConfiguration, - Timescale, ) from settings_enum import AnalogPause, PauseWhen @@ -35,6 +33,7 @@ panel.set_value("is_running", True) panel.set_value("stop_button", False) + # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: chan_type = panel.get_value("chan_type", "1") if chan_type == "1": diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 853890f..28311aa 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -1,21 +1,20 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_continuous_analog_input.py.""" +"""Streamlit visualization script to display data acquired by nidaqmx_analog_input_filtering.py.""" +import extra_streamlit_components as stx # type: ignore[import-untyped] import streamlit as st -from streamlit_echarts import st_echarts -import extra_streamlit_components as stx -from settings_enum import PauseWhen, AnalogPause from nidaqmx.constants import ( - TerminalConfiguration, - SampleTimingType, - FilterResponse, CurrentShuntResistorLocation, + CurrentUnits, Edge, - Slope, + FilterResponse, LoggingMode, - CurrentUnits, + Slope, StrainGageBridgeType, + TerminalConfiguration, ) -import time +from settings_enum import AnalogPause, PauseWhen +from streamlit_echarts import st_echarts + import nipanel from nipanel.controls import enum_selectbox @@ -47,9 +46,9 @@ with left_col: st.write(panel.get_value("is_running", False)) if is_running: - st.button(r"⏹️ Stop", key="stop_button") + st.button("Stop", key="stop_button") else: - st.button(r"▶️ Run", key="run_button") + st.button("Run", key="run_button") st.markdown( @@ -229,7 +228,7 @@ format_func=lambda x: x[0], index=0, ) - pause_when = PauseWhen[pause_when[0]] + pause_when = PauseWhen[pause_when[0]] # type: ignore panel.set_value("pause_when", pause_when) with tab4: st.write( @@ -260,7 +259,7 @@ format_func=lambda x: x[0], index=0, ) - analog_pause = AnalogPause[analog_pause[0]] + analog_pause = AnalogPause[analog_pause[0]] # type: ignore panel.set_value("analog_pause", analog_pause) with tab7: @@ -318,7 +317,7 @@ key="max_value_current", disabled=panel.get_value("is_running", False), ) - current = panel.set_value("max_value_current", max_value_current) + current = panel.set_value("max_value_current", max_value_current) # type:ignore shunt_resistor_value = st.number_input( "Shunt Resistor Value", value=249.0, diff --git a/examples/nidaqmx_analog_input_filtering/settings_enum.py b/examples/nidaqmx_analog_input_filtering/settings_enum.py index a2f208f..6a484b5 100644 --- a/examples/nidaqmx_analog_input_filtering/settings_enum.py +++ b/examples/nidaqmx_analog_input_filtering/settings_enum.py @@ -4,10 +4,14 @@ class PauseWhen(enum.StrEnum): + """Pause When Trigger Setting.""" + HIGH = "High" LOW = "Low" class AnalogPause(enum.StrEnum): + """Analog Pause Trigger.""" + ABOVE = "ABOVE" BELOW = "BELOW" diff --git a/examples/simple_graph/simple_graph_panel.py b/examples/simple_graph/simple_graph_panel.py index 4d24259..a3afd9f 100644 --- a/examples/simple_graph/simple_graph_panel.py +++ b/examples/simple_graph/simple_graph_panel.py @@ -1,7 +1,6 @@ """A Streamlit visualization panel for the simple_graph.py example script.""" import streamlit as st -from amplitude_enum import AmplitudeEnum from streamlit_echarts import st_echarts import nipanel @@ -25,8 +24,7 @@ with col5: st.metric("Max Value", f"{max(sine_values):.3f}") -with col6: - st.metric("Data Points", len(sine_values)) + # Prepare data for echarts data = [{"value": [x, y]} for x, y in zip(time_points, sine_values)] From 957ef545236c7ccaf13860bda22bdc8849201564 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 11:23:16 -0500 Subject: [PATCH 08/50] fixed mypy & lint errors --- .../nidaqmx_analog_input_filtering.py | 3 +- .../nidaqmx_analog_input_filtering_panel.py | 29 +++++++++---------- .../settings_enum.py | 4 +++ examples/simple_graph/simple_graph_panel.py | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index d15973a..562b2ef 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -3,7 +3,6 @@ from pathlib import Path import nidaqmx -import numpy as numpy from nidaqmx.constants import ( AcquisitionType, CurrentShuntResistorLocation, @@ -16,7 +15,6 @@ Slope, StrainGageBridgeType, TerminalConfiguration, - Timescale, ) from settings_enum import AnalogPause, PauseWhen @@ -35,6 +33,7 @@ panel.set_value("is_running", True) panel.set_value("stop_button", False) + # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: chan_type = panel.get_value("chan_type", "1") if chan_type == "1": diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 853890f..28311aa 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -1,21 +1,20 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_continuous_analog_input.py.""" +"""Streamlit visualization script to display data acquired by nidaqmx_analog_input_filtering.py.""" +import extra_streamlit_components as stx # type: ignore[import-untyped] import streamlit as st -from streamlit_echarts import st_echarts -import extra_streamlit_components as stx -from settings_enum import PauseWhen, AnalogPause from nidaqmx.constants import ( - TerminalConfiguration, - SampleTimingType, - FilterResponse, CurrentShuntResistorLocation, + CurrentUnits, Edge, - Slope, + FilterResponse, LoggingMode, - CurrentUnits, + Slope, StrainGageBridgeType, + TerminalConfiguration, ) -import time +from settings_enum import AnalogPause, PauseWhen +from streamlit_echarts import st_echarts + import nipanel from nipanel.controls import enum_selectbox @@ -47,9 +46,9 @@ with left_col: st.write(panel.get_value("is_running", False)) if is_running: - st.button(r"⏹️ Stop", key="stop_button") + st.button("Stop", key="stop_button") else: - st.button(r"▶️ Run", key="run_button") + st.button("Run", key="run_button") st.markdown( @@ -229,7 +228,7 @@ format_func=lambda x: x[0], index=0, ) - pause_when = PauseWhen[pause_when[0]] + pause_when = PauseWhen[pause_when[0]] # type: ignore panel.set_value("pause_when", pause_when) with tab4: st.write( @@ -260,7 +259,7 @@ format_func=lambda x: x[0], index=0, ) - analog_pause = AnalogPause[analog_pause[0]] + analog_pause = AnalogPause[analog_pause[0]] # type: ignore panel.set_value("analog_pause", analog_pause) with tab7: @@ -318,7 +317,7 @@ key="max_value_current", disabled=panel.get_value("is_running", False), ) - current = panel.set_value("max_value_current", max_value_current) + current = panel.set_value("max_value_current", max_value_current) # type:ignore shunt_resistor_value = st.number_input( "Shunt Resistor Value", value=249.0, diff --git a/examples/nidaqmx_analog_input_filtering/settings_enum.py b/examples/nidaqmx_analog_input_filtering/settings_enum.py index a2f208f..6a484b5 100644 --- a/examples/nidaqmx_analog_input_filtering/settings_enum.py +++ b/examples/nidaqmx_analog_input_filtering/settings_enum.py @@ -4,10 +4,14 @@ class PauseWhen(enum.StrEnum): + """Pause When Trigger Setting.""" + HIGH = "High" LOW = "Low" class AnalogPause(enum.StrEnum): + """Analog Pause Trigger.""" + ABOVE = "ABOVE" BELOW = "BELOW" diff --git a/examples/simple_graph/simple_graph_panel.py b/examples/simple_graph/simple_graph_panel.py index 4d24259..a3afd9f 100644 --- a/examples/simple_graph/simple_graph_panel.py +++ b/examples/simple_graph/simple_graph_panel.py @@ -1,7 +1,6 @@ """A Streamlit visualization panel for the simple_graph.py example script.""" import streamlit as st -from amplitude_enum import AmplitudeEnum from streamlit_echarts import st_echarts import nipanel @@ -25,8 +24,7 @@ with col5: st.metric("Max Value", f"{max(sine_values):.3f}") -with col6: - st.metric("Data Points", len(sine_values)) + # Prepare data for echarts data = [{"value": [x, y]} for x, y in zip(time_points, sine_values)] From 886623e92d42938ec6babb8812ccc7b8648a759e Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 15:19:30 -0500 Subject: [PATCH 09/50] Revert changes --- .../nidaqmx_analog_input_filtering/README.md | 2 ++ examples/niscope/niscope_ex_fetch_forever.py | 2 +- examples/simple_graph/amplitude_enum.py | 11 ----------- examples/simple_graph/simple_graph.py | 18 +++++------------- examples/simple_graph/simple_graph_panel.py | 12 +++++------- 5 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 examples/simple_graph/amplitude_enum.py diff --git a/examples/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx_analog_input_filtering/README.md index 5bd4314..6de4443 100644 --- a/examples/nidaqmx_analog_input_filtering/README.md +++ b/examples/nidaqmx_analog_input_filtering/README.md @@ -16,5 +16,7 @@ Script demonstrates analog input data getting continuously acquired, and being f ### Usage +poetry install --with examples +poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py Run `poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py` diff --git a/examples/niscope/niscope_ex_fetch_forever.py b/examples/niscope/niscope_ex_fetch_forever.py index 5f2a5ab..68d7316 100644 --- a/examples/niscope/niscope_ex_fetch_forever.py +++ b/examples/niscope/niscope_ex_fetch_forever.py @@ -46,7 +46,7 @@ try: print(f"Press Ctrl + C to stop") while True: - offset = session._fetch_offset + offset = session.meas_array_offset gain = session.meas_array_gain for i in range(len(waveforms)): time.sleep(0.2) diff --git a/examples/simple_graph/amplitude_enum.py b/examples/simple_graph/amplitude_enum.py deleted file mode 100644 index b1f12ca..0000000 --- a/examples/simple_graph/amplitude_enum.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Enumeration for amplitude values used in the simple graph example.""" - -import enum - - -class AmplitudeEnum(enum.IntEnum): - """Enumeration for amplitude values.""" - - SMALL = 1 - MEDIUM = 5 - BIG = 10 diff --git a/examples/simple_graph/simple_graph.py b/examples/simple_graph/simple_graph.py index 73f7832..f5208c5 100644 --- a/examples/simple_graph/simple_graph.py +++ b/examples/simple_graph/simple_graph.py @@ -1,43 +1,35 @@ """Example of using nipanel to display a sine wave graph using st_echarts.""" - import math import time from pathlib import Path import numpy as np -from amplitude_enum import AmplitudeEnum import nipanel + panel_script_path = Path(__file__).with_name("simple_graph_panel.py") panel = nipanel.create_panel(panel_script_path) amplitude = 1.0 frequency = 1.0 num_points = 100 - try: print(f"Panel URL: {panel.panel_url}") print("Press Ctrl+C to exit") # Generate and update the sine wave data periodically while True: - amplitude_enum = AmplitudeEnum(panel.get_value("amplitude_enum", AmplitudeEnum.SMALL.value)) - base_frequency = panel.get_value("base_frequency", 1.0) - - # Slowly vary the total frequency for a more dynamic visualization - frequency = base_frequency + 0.5 * math.sin(time.time() / 5.0) time_points = np.linspace(0, num_points, num_points) - sine_values = amplitude_enum.value * np.sin(frequency * time_points) - - panel.set_value("frequency", frequency) + sine_values = amplitude * np.sin(frequency * time_points) panel.set_value("time_points", time_points.tolist()) panel.set_value("sine_values", sine_values.tolist()) + panel.set_value("amplitude", amplitude) + panel.set_value("frequency", frequency) # Slowly vary the frequency for a more dynamic visualization frequency = 1.0 + 0.5 * math.sin(time.time() / 5.0) time.sleep(0.1) - except KeyboardInterrupt: - print("Exiting...") + print("Exiting...") \ No newline at end of file diff --git a/examples/simple_graph/simple_graph_panel.py b/examples/simple_graph/simple_graph_panel.py index a3afd9f..01e057c 100644 --- a/examples/simple_graph/simple_graph_panel.py +++ b/examples/simple_graph/simple_graph_panel.py @@ -1,10 +1,10 @@ """A Streamlit visualization panel for the simple_graph.py example script.""" - import streamlit as st from streamlit_echarts import st_echarts import nipanel + st.set_page_config(page_title="Simple Graph Example", page_icon="📈", layout="wide") st.title("Simple Graph Example") @@ -13,7 +13,6 @@ sine_values = panel.get_value("sine_values", [0.0]) amplitude = panel.get_value("amplitude", 1.0) frequency = panel.get_value("frequency", 1.0) - col1, col2, col3, col4, col5 = st.columns(5) with col1: st.metric("Amplitude", f"{amplitude:.2f}") @@ -21,13 +20,13 @@ st.metric("Frequency", f"{frequency:.2f} Hz") with col3: st.metric("Min Value", f"{min(sine_values):.3f}") - -with col5: +with col4: st.metric("Max Value", f"{max(sine_values):.3f}") +with col5: + st.metric("Data Points", len(sine_values)) # Prepare data for echarts data = [{"value": [x, y]} for x, y in zip(time_points, sine_values)] - # Configure the chart options options = { "animation": False, # Disable animation for smoother updates @@ -52,6 +51,5 @@ } ], } - # Display the chart -st_echarts(options=options, height="400px", key="graph") +st_echarts(options=options, height="400px", key="graph") \ No newline at end of file From 28f2209cef94976c94d45898fe97aee6723edb29 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 15:23:01 -0500 Subject: [PATCH 10/50] simple graph changes --- examples/simple_graph/simple_graph.py | 6 +++++- examples/simple_graph/simple_graph_panel.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/simple_graph/simple_graph.py b/examples/simple_graph/simple_graph.py index f5208c5..324cf7c 100644 --- a/examples/simple_graph/simple_graph.py +++ b/examples/simple_graph/simple_graph.py @@ -1,4 +1,5 @@ """Example of using nipanel to display a sine wave graph using st_echarts.""" + import math import time from pathlib import Path @@ -14,6 +15,7 @@ amplitude = 1.0 frequency = 1.0 num_points = 100 + try: print(f"Panel URL: {panel.panel_url}") print("Press Ctrl+C to exit") @@ -31,5 +33,7 @@ # Slowly vary the frequency for a more dynamic visualization frequency = 1.0 + 0.5 * math.sin(time.time() / 5.0) time.sleep(0.1) + except KeyboardInterrupt: - print("Exiting...") \ No newline at end of file + print("Exiting...") + \ No newline at end of file diff --git a/examples/simple_graph/simple_graph_panel.py b/examples/simple_graph/simple_graph_panel.py index 01e057c..6550627 100644 --- a/examples/simple_graph/simple_graph_panel.py +++ b/examples/simple_graph/simple_graph_panel.py @@ -1,4 +1,5 @@ """A Streamlit visualization panel for the simple_graph.py example script.""" + import streamlit as st from streamlit_echarts import st_echarts @@ -13,6 +14,7 @@ sine_values = panel.get_value("sine_values", [0.0]) amplitude = panel.get_value("amplitude", 1.0) frequency = panel.get_value("frequency", 1.0) + col1, col2, col3, col4, col5 = st.columns(5) with col1: st.metric("Amplitude", f"{amplitude:.2f}") @@ -27,6 +29,7 @@ # Prepare data for echarts data = [{"value": [x, y]} for x, y in zip(time_points, sine_values)] + # Configure the chart options options = { "animation": False, # Disable animation for smoother updates @@ -51,5 +54,6 @@ } ], } + # Display the chart -st_echarts(options=options, height="400px", key="graph") \ No newline at end of file +st_echarts(options=options, height="400px", key="graph") From 709d47eefa1525e77df66b072170cb9eb737cd43 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 15:23:01 -0500 Subject: [PATCH 11/50] simple graph changes --- examples/simple_graph/simple_graph.py | 3 +++ examples/simple_graph/simple_graph_panel.py | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/simple_graph/simple_graph.py b/examples/simple_graph/simple_graph.py index f5208c5..97a27b2 100644 --- a/examples/simple_graph/simple_graph.py +++ b/examples/simple_graph/simple_graph.py @@ -1,4 +1,5 @@ """Example of using nipanel to display a sine wave graph using st_echarts.""" + import math import time from pathlib import Path @@ -14,6 +15,7 @@ amplitude = 1.0 frequency = 1.0 num_points = 100 + try: print(f"Panel URL: {panel.panel_url}") print("Press Ctrl+C to exit") @@ -31,5 +33,6 @@ # Slowly vary the frequency for a more dynamic visualization frequency = 1.0 + 0.5 * math.sin(time.time() / 5.0) time.sleep(0.1) + except KeyboardInterrupt: print("Exiting...") \ No newline at end of file diff --git a/examples/simple_graph/simple_graph_panel.py b/examples/simple_graph/simple_graph_panel.py index 01e057c..6550627 100644 --- a/examples/simple_graph/simple_graph_panel.py +++ b/examples/simple_graph/simple_graph_panel.py @@ -1,4 +1,5 @@ """A Streamlit visualization panel for the simple_graph.py example script.""" + import streamlit as st from streamlit_echarts import st_echarts @@ -13,6 +14,7 @@ sine_values = panel.get_value("sine_values", [0.0]) amplitude = panel.get_value("amplitude", 1.0) frequency = panel.get_value("frequency", 1.0) + col1, col2, col3, col4, col5 = st.columns(5) with col1: st.metric("Amplitude", f"{amplitude:.2f}") @@ -27,6 +29,7 @@ # Prepare data for echarts data = [{"value": [x, y]} for x, y in zip(time_points, sine_values)] + # Configure the chart options options = { "animation": False, # Disable animation for smoother updates @@ -51,5 +54,6 @@ } ], } + # Display the chart -st_echarts(options=options, height="400px", key="graph") \ No newline at end of file +st_echarts(options=options, height="400px", key="graph") From 219c2de5cc18fa933a5d39921c946a8f5b86639f Mon Sep 17 00:00:00 2001 From: DilmiWickramanayake <155610400+DilmiWickramanayake@users.noreply.github.com> Date: Tue, 15 Jul 2025 15:31:27 -0500 Subject: [PATCH 12/50] Update simple_graph.py --- examples/simple_graph/simple_graph.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/simple_graph/simple_graph.py b/examples/simple_graph/simple_graph.py index 324cf7c..4b63530 100644 --- a/examples/simple_graph/simple_graph.py +++ b/examples/simple_graph/simple_graph.py @@ -36,4 +36,3 @@ except KeyboardInterrupt: print("Exiting...") - \ No newline at end of file From 809ced38086648b4d9788b2308d4053817f3ce44 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 15 Jul 2025 15:41:48 -0500 Subject: [PATCH 13/50] Poetry lock --- poetry.lock | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9f7e6d6..24c02a2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1427,7 +1427,7 @@ files = [ [[package]] name = "numpy" -version = "2.2.6" +version = "2.0.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" @@ -1484,7 +1484,7 @@ name = "numpy" version = "2.2.6" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.10" +python-versions = ">=3.9" files = [ {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, @@ -2787,6 +2787,7 @@ astroid = [ Jinja2 = "*" PyYAML = "*" sphinx = ">=7.4.0" +stdlib_list = {version = "*", markers = "python_version < \"3.10\""} [[package]] name = "sphinx-rtd-theme" @@ -2915,6 +2916,24 @@ lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] +[[package]] +name = "stdlib-list" +version = "0.11.1" +description = "A list of Python Standard Libraries (2.7 through 3.13)." +optional = false +python-versions = ">=3.9" +files = [ + {file = "stdlib_list-0.11.1-py3-none-any.whl", hash = "sha256:9029ea5e3dfde8cd4294cfd4d1797be56a67fc4693c606181730148c3fd1da29"}, + {file = "stdlib_list-0.11.1.tar.gz", hash = "sha256:95ebd1d73da9333bba03ccc097f5bac05e3aa03e6822a0c0290f87e1047f1857"}, +] + +[package.extras] +dev = ["build", "stdlib-list[doc,lint,test]"] +doc = ["furo", "sphinx"] +lint = ["mypy", "ruff"] +support = ["sphobjinv"] +test = ["coverage[toml]", "pytest", "pytest-cov"] + [[package]] name = "stevedore" version = "5.4.1" From ffca8c166b3cf9de94f07bc7ec59954669c20874 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 16 Jul 2025 07:19:54 -0500 Subject: [PATCH 14/50] update lint errors --- .../nidaqmx_analog_input_filtering.py | 9 ++++----- .../nidaqmx_analog_input_filtering_panel.py | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 72f7e95..ec67448 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -16,7 +16,6 @@ StrainGageBridgeType, TerminalConfiguration, ) -from settings_enum import AnalogPause, PauseWhen import nipanel @@ -32,8 +31,8 @@ panel.set_value("is_running", False) panel.set_value("is_running", True) panel.set_value("stop_button", False) - - # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ + + # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: chan_type = panel.get_value("chan_type", "1") if chan_type == "1": @@ -84,7 +83,7 @@ chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) chan.ai_filter_response = panel.get_value("filter_response", FilterResponse.COMB) chan.ai_filter_order = 1 - + task.timing.cfg_samp_clk_timing( rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, @@ -108,7 +107,7 @@ task.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source="/Dev2/PFI0", trigger_edge=panel.get_value("edge", Edge.FALLING) ) - task.triggers.start_trigger.anlg_edge_hyst = hysteresis = panel.get_value( + task.triggers.start_trigger.anlg_edge_hyst = hysteresis = panel.get_value( "hysteresis", 0.0 ) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index dc389b3..c2ef4ee 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -92,7 +92,7 @@ min_value=1.0, step=1.0, disabled=panel.get_value("is_running", False), - key = "rate" + key="rate", ) st.number_input( "Number of Samples", @@ -100,7 +100,7 @@ min_value=1, step=1, disabled=panel.get_value("is_running", False), - key = "total_samples" + key="total_samples", ) st.selectbox("Actual Sample Rate", options=[panel.get_value("sample_rate")], disabled=True) @@ -207,7 +207,6 @@ stx.TabBarItemData(id=7, title="Analog Reference", description=""), ], default=1, - ) trigger_type = id panel.set_value("trigger_type", trigger_type) From 66faa592a6537d0b0578e045b688d8fbcfb9eea4 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 16 Jul 2025 07:19:54 -0500 Subject: [PATCH 15/50] update lint errors --- .../nidaqmx_analog_input_filtering.py | 9 ++++----- .../nidaqmx_analog_input_filtering_panel.py | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 72f7e95..ec67448 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -16,7 +16,6 @@ StrainGageBridgeType, TerminalConfiguration, ) -from settings_enum import AnalogPause, PauseWhen import nipanel @@ -32,8 +31,8 @@ panel.set_value("is_running", False) panel.set_value("is_running", True) panel.set_value("stop_button", False) - - # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ + + # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: chan_type = panel.get_value("chan_type", "1") if chan_type == "1": @@ -84,7 +83,7 @@ chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) chan.ai_filter_response = panel.get_value("filter_response", FilterResponse.COMB) chan.ai_filter_order = 1 - + task.timing.cfg_samp_clk_timing( rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, @@ -108,7 +107,7 @@ task.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source="/Dev2/PFI0", trigger_edge=panel.get_value("edge", Edge.FALLING) ) - task.triggers.start_trigger.anlg_edge_hyst = hysteresis = panel.get_value( + task.triggers.start_trigger.anlg_edge_hyst = hysteresis = panel.get_value( "hysteresis", 0.0 ) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index dc389b3..c2ef4ee 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -92,7 +92,7 @@ min_value=1.0, step=1.0, disabled=panel.get_value("is_running", False), - key = "rate" + key="rate", ) st.number_input( "Number of Samples", @@ -100,7 +100,7 @@ min_value=1, step=1, disabled=panel.get_value("is_running", False), - key = "total_samples" + key="total_samples", ) st.selectbox("Actual Sample Rate", options=[panel.get_value("sample_rate")], disabled=True) @@ -207,7 +207,6 @@ stx.TabBarItemData(id=7, title="Analog Reference", description=""), ], default=1, - ) trigger_type = id panel.set_value("trigger_type", trigger_type) From c385fb23297ac9f399efbbbee411560a9ae10a26 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 08:51:22 -0500 Subject: [PATCH 16/50] changes to poetry lock file --- poetry.lock | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 1114bd8..fd847b2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -502,6 +502,20 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "extra-streamlit-components" +version = "0.1.80" +description = "An all-in-one place, to find complex or just natively unavailable components on streamlit." +optional = false +python-versions = ">=3.6" +files = [ + {file = "extra_streamlit_components-0.1.80-py3-none-any.whl", hash = "sha256:7a8c151da5dcd1f1f97b6c29caa812a1d77928d20fc4bf42a3a4fd788274dd9e"}, + {file = "extra_streamlit_components-0.1.80.tar.gz", hash = "sha256:87d6c38e07381501d8882796adef17d1c1d4e3a79615864d95c1163d2bc136f6"}, +] + +[package.dependencies] +streamlit = ">=1.40.1" + [[package]] name = "flake8" version = "5.0.4" @@ -3263,4 +3277,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0,!=3.9.7" -content-hash = "45dc36d0ef51734fbde48be7f49ed705209f3b0d46c827cd0de4115fbf15ce62" +content-hash = "1b4c4105e78ce7eca099f1a45a130c93565d568f2263e70d6389ab59ed3bbe27" From 1ab9fa685fd039320683120ba35668dde97d7bb1 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 08:51:22 -0500 Subject: [PATCH 17/50] changes to poetry lock file --- .../nidaqmx_analog_input_filtering.py | 2 - .../nidaqmx_analog_input_filtering_panel.py | 37 +++++++++++++------ poetry.lock | 16 +++++++- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 3bcae84..849a184 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -32,8 +32,6 @@ panel.set_value("is_running", True) panel.set_value("stop_button", False) - # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ - # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: chan_type = panel.get_value("chan_type", "1") diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 3c5b8d4..1dc6c57 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -42,12 +42,18 @@ channel_left, channel_right = st.columns(2) with channel_left: max_value_voltage = st.number_input( - "Max Value", value=5.0, step=0.1, disabled=panel.get_value("is_running", False) + "Max Value", + value=5.0, + step=0.1, + disabled=panel.get_value("is_running", False), ) panel.set_value("max_value_voltage", max_value_voltage) min_value_voltage = st.number_input( - "Min Value", value=-5.0, step=0.1, disabled=panel.get_value("is_running", False) + "Min Value", + value=-5.0, + step=0.1, + disabled=panel.get_value("is_running", False), ) panel.set_value("min_value_voltage", min_value_voltage) @@ -84,7 +90,9 @@ key="max_value_current", disabled=panel.get_value("is_running", False), ) - current = panel.set_value("max_value_current", max_value_current) # type:ignore + current = panel.set_value( + "max_value_current", max_value_current + ) # type:ignore shunt_resistor_value = st.number_input( "Shunt Resistor Value", value=249.0, @@ -243,12 +251,12 @@ ) st.number_input( "Actual Sample Rate", - value= panel.get_value("actual_sample_rate", 1000.0), - key = "actual_sample_rate", - step = 1.0, - disabled= True + value=panel.get_value("actual_sample_rate", 1000.0), + key="actual_sample_rate", + step=1.0, + disabled=True, ) - + st.title("Logging Settings") enum_selectbox( panel, @@ -288,9 +296,14 @@ value=1, disabled=panel.get_value("is_running", False), ) - st.selectbox("Actual Filter Frequency", options=[panel.get_value("actual_filter_freq")], disabled=True) - st.selectbox("Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True) - + st.selectbox( + "Actual Filter Frequency", + options=[panel.get_value("actual_filter_freq")], + disabled=True, + ) + st.selectbox( + "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True + ) with right_col: @@ -381,7 +394,7 @@ "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." ) - + with right_col: with st.container(border=True): acquired_data = panel.get_value("acquired_data", [0.0]) diff --git a/poetry.lock b/poetry.lock index 1114bd8..fd847b2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -502,6 +502,20 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "extra-streamlit-components" +version = "0.1.80" +description = "An all-in-one place, to find complex or just natively unavailable components on streamlit." +optional = false +python-versions = ">=3.6" +files = [ + {file = "extra_streamlit_components-0.1.80-py3-none-any.whl", hash = "sha256:7a8c151da5dcd1f1f97b6c29caa812a1d77928d20fc4bf42a3a4fd788274dd9e"}, + {file = "extra_streamlit_components-0.1.80.tar.gz", hash = "sha256:87d6c38e07381501d8882796adef17d1c1d4e3a79615864d95c1163d2bc136f6"}, +] + +[package.dependencies] +streamlit = ">=1.40.1" + [[package]] name = "flake8" version = "5.0.4" @@ -3263,4 +3277,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0,!=3.9.7" -content-hash = "45dc36d0ef51734fbde48be7f49ed705209f3b0d46c827cd0de4115fbf15ce62" +content-hash = "1b4c4105e78ce7eca099f1a45a130c93565d568f2263e70d6389ab59ed3bbe27" From 6354786cf76b97f3b435929c2bd00030844e948e Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 08:57:27 -0500 Subject: [PATCH 18/50] Pyright error --- .../nidaqmx_analog_input_filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 849a184..171ecd3 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -120,7 +120,7 @@ try: task.start() while not panel.get_value("stop_button", False): - data = task.read(number_of_samples_per_channel=100) + data = task.read(number_of_samples_per_channel=100) # pyright: ignore[reportArgumentType] panel.set_value("acquired_data", data) except KeyboardInterrupt: pass From 722c3d5d2bc217ac054cac43a678ebbf9c7d5ebc Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 09:02:55 -0500 Subject: [PATCH 19/50] lint error --- .../nidaqmx_analog_input_filtering.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 171ecd3..c0783a4 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -120,7 +120,9 @@ try: task.start() while not panel.get_value("stop_button", False): - data = task.read(number_of_samples_per_channel=100) # pyright: ignore[reportArgumentType] + data = task.read( + number_of_samples_per_channel=100 # pyright: ignore[reportArgumentType] + ) panel.set_value("acquired_data", data) except KeyboardInterrupt: pass From bbdeb81e25007214d678f72de6f976234c59b726 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 09:04:37 -0500 Subject: [PATCH 20/50] fixed errors --- .../nidaqmx_analog_input_filtering.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index c0783a4..17f7643 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -121,8 +121,8 @@ task.start() while not panel.get_value("stop_button", False): data = task.read( - number_of_samples_per_channel=100 # pyright: ignore[reportArgumentType] - ) + number_of_samples_per_channel=100 # pyright: ignore[reportArgumentType] + ) panel.set_value("acquired_data", data) except KeyboardInterrupt: pass From 065d6f44cb2b334b189265345176d1000412291a Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 15:16:21 -0500 Subject: [PATCH 21/50] Fixed panel comments --- .../nidaqmx_analog_input_filtering/README.md | 5 +- .../nidaqmx_analog_input_filtering.py | 41 +- .../nidaqmx_analog_input_filtering_panel.py | 439 +++++++++--------- .../README.md | 0 .../nidaqmx_continuous_analog_input.py | 2 +- .../nidaqmx_continuous_analog_input_panel.py | 0 .../settings_enum.py | 17 - 7 files changed, 240 insertions(+), 264 deletions(-) rename examples/{ => nidaqmx}/nidaqmx_analog_input_filtering/README.md (76%) rename examples/{ => nidaqmx}/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py (87%) rename examples/{ => nidaqmx}/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py (71%) rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/README.md (100%) rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/nidaqmx_continuous_analog_input.py (97%) rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/nidaqmx_continuous_analog_input_panel.py (100%) delete mode 100644 examples/nidaqmx_analog_input_filtering/settings_enum.py diff --git a/examples/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md similarity index 76% rename from examples/nidaqmx_analog_input_filtering/README.md rename to examples/nidaqmx/nidaqmx_analog_input_filtering/README.md index 6de4443..dcd518a 100644 --- a/examples/nidaqmx_analog_input_filtering/README.md +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md @@ -16,7 +16,8 @@ Script demonstrates analog input data getting continuously acquired, and being f ### Usage +```pwsh poetry install --with examples -poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py -Run `poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py` +poetry run python examples/all_types/all_types.py +``` diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py similarity index 87% rename from examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py rename to examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 17f7643..98a0e2f 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -10,18 +10,31 @@ Edge, ExcitationSource, FilterResponse, - LoggingMode, - LoggingOperation, Slope, StrainGageBridgeType, TerminalConfiguration, ) +import time +import nidaqmx.system import nipanel - panel_script_path = Path(__file__).with_name("nidaqmx_analog_input_filtering_panel.py") panel = nipanel.create_panel(panel_script_path) panel.set_value("is_running", False) + +system = nidaqmx.system.System.local() + +channel_name = [] +for dev in system.devices: + for chan in dev.ai_physical_chans: + channel_name.append(chan.name) +panel.set_value("channel_name", channel_name) +trigger_sources = [] +for dev in system.devices: + if hasattr(dev, "terminals"): + for term in dev.terminals: + trigger_sources.append(term) +panel.set_value("trigger_sources", trigger_sources) try: print(f"Panel URL: {panel.panel_url}") print(f"Waiting for the 'Run' button to be pressed...") @@ -29,16 +42,18 @@ while True: while not panel.get_value("run_button", False): panel.set_value("is_running", False) + # time.sleep(0.1) panel.set_value("is_running", True) panel.set_value("stop_button", False) # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: + chan_type = panel.get_value("chan_type", "1") if chan_type == "2": chan = task.ai_channels.add_ai_current_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), max_val=panel.get_value("max_value_current", 0.01), min_val=panel.get_value("min_value_current", -0.01), ext_shunt_resistor_val=panel.get_value("shunt_resistor_value", 249.0), @@ -50,7 +65,7 @@ elif chan_type == "3": chan = task.ai_channels.add_ai_strain_gage_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), nominal_gage_resistance=panel.get_value("gage_resistance", 350.0), voltage_excit_source=ExcitationSource.EXTERNAL, # Only mode that works max_val=panel.get_value("max_value_strain", 0.001), @@ -66,27 +81,23 @@ ) else: chan = task.ai_channels.add_ai_voltage_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), terminal_config=panel.get_value( "terminal_configuration", TerminalConfiguration.DEFAULT ), max_val=panel.get_value("max_value_voltage", 5.0), min_val=panel.get_value("min_value_voltage", -5.0), ) + task.timing.cfg_samp_clk_timing( rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), ) - panel.set_value("actual_sample_rate", task._timing.samp_clk_rate) + panel.set_value("actual_sample_rate", task.timing.samp_clk_rate) panel.set_value("sample_rate", panel.get_value("rate", 100.0)) - - task.in_stream.configure_logging( - file_path=panel.get_value("tdms_file_path", "data.tdms"), - logging_mode=panel.get_value("logging_mode", LoggingMode.OFF), - operation=LoggingOperation.OPEN_OR_CREATE, - ) + if panel.get_value("filter", "Filter") == "Filter": chan.ai_filter_enable = True chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) @@ -101,7 +112,7 @@ panel.set_value("actual_filter_freq", 0.0) panel.set_value("actual_filter_response", FilterResponse.COMB) panel.set_value("actual_filter_order", 0) - + trigger_type = panel.get_value("trigger_type") if trigger_type == "5": task.triggers.start_trigger.cfg_anlg_edge_start_trig( @@ -109,6 +120,8 @@ trigger_slope=panel.get_value("slope", Slope.FALLING), trigger_level=panel.get_value("level", 0.0), ) + + if trigger_type == "2": task.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source="/Dev2/PFI0", trigger_edge=panel.get_value("edge", Edge.FALLING) diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py similarity index 71% rename from examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py rename to examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 1dc6c57..73f0034 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -12,7 +12,6 @@ StrainGageBridgeType, TerminalConfiguration, ) -from settings_enum import AnalogPause, PauseWhen from streamlit_echarts import st_echarts import nipanel @@ -24,8 +23,122 @@ left_col, right_col = st.columns(2) -with right_col: + +st.markdown( + """ + + """, + unsafe_allow_html=True, +) + +streamlit_style = """ + + """ +st.markdown(streamlit_style, unsafe_allow_html=True) + + + +with left_col: with st.container(border=True): + is_running = panel.get_value("is_running", True) + if is_running: + st.button("Stop", key="stop_button") + else: + st.button("Run", key="run_button") + + st.title("Channel Settings") + physical_channel = st.selectbox(options=panel.get_value("channel_name", ["Mod2/ai0"]), index=0, label="Physical Channels", disabled=panel.get_value("is_running", False)) + panel.set_value("physical_channel", physical_channel) + enum_selectbox( + panel, + label="Terminal Configuration", + value=TerminalConfiguration.DEFAULT, + disabled=panel.get_value("is_running", False), + key="terminal_configuration", + ) + + st.title("Timing Settings") + + st.selectbox("Sample Clock Source", options=panel.get_value("trigger_sources", [""]), index=0, disabled=panel.get_value("is_running", False)) + st.number_input( + "Sample Rate", + value=1000.0, + min_value=1.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="rate", + ) + st.number_input( + "Number of Samples", + value=100, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + key="total_samples", + ) + st.number_input( + "Actual Sample Rate", + value=panel.get_value("actual_sample_rate", 1000.0), + key="actual_sample_rate", + step=1.0, + disabled=True, + ) + + st.title("Logging Settings") + enum_selectbox( + panel, + label="Logging Mode", + value=LoggingMode.OFF, + disabled=panel.get_value("is_running", False), + key="logging_mode", + ) + tdms_file_path = st.text_input( + label="TDMS File Path", + disabled=panel.get_value("is_running", False), + value="data.tdms", + key="tdms_file_path", + ) + st.title("Filtering Settings") + + filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) + panel.set_value("filter", filter) + enum_selectbox( + panel, + label="Filter Response", + value=FilterResponse.COMB, + disabled=panel.get_value("is_running", False), + key="filter_response", + ) + + filter_freq = st.number_input( + "Filtering Frequency", + value=1000.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + filter_order = st.number_input( + "Filter Order", + min_value=0, + max_value=1, + value=1, + disabled=panel.get_value("is_running", False), + ) + st.selectbox( + "Actual Filter Frequency", + options=[panel.get_value("actual_filter_freq")], + disabled=True, + ) + st.selectbox( + "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True + ) + +with right_col: st.title("Task Types") chosen_id = stx.tab_bar( data=[ @@ -35,9 +148,12 @@ ], default=1, ) - tabs = st.tabs(["Voltage", "Current", "Strain Gage"]) - with st.container(border=True): - with tabs[0]: + + chan_type = chosen_id + panel.set_value("chan_type", chan_type) + + if chosen_id == "1": + with st.container(border=True): st.title("Voltage Data") channel_left, channel_right = st.columns(2) with channel_left: @@ -57,7 +173,8 @@ ) panel.set_value("min_value_voltage", min_value_voltage) - with tabs[1]: + if chosen_id == "2": + with st.container(border=True): st.title("Current Data") channel_left, channel_right = st.columns(2) with channel_left: @@ -100,7 +217,8 @@ disabled=panel.get_value("is_running", False), ) panel.set_value("shunt_resistor_value", shunt_resistor_value) - with tabs[2]: + if chosen_id == "3": + with st.container(border=True): st.title("Strain Gage Data") channel_left, channel_right = st.columns(2) with channel_left: @@ -183,131 +301,10 @@ ) panel.set_value("voltage_excitation_value", voltage_excit) -panel.set_value("chan_type", "1") - -pages = st.container() -chan_type = chosen_id -panel.set_value("chan_type", chan_type) - -is_running = panel.get_value("is_running", True) -with left_col: - if is_running: - st.button("Stop", key="stop_button") - else: - st.button("Run", key="run_button") - -st.markdown( - """ - - """, - unsafe_allow_html=True, -) - -streamlit_style = """ - - """ -st.markdown(streamlit_style, unsafe_allow_html=True) - - -with left_col: - with st.container(border=True): - - st.title("Channel Settings") - st.selectbox(options=["Mod3/ai10"], index=0, label="Physical Channels", disabled=True) - - enum_selectbox( - panel, - label="Terminal Configuration", - value=TerminalConfiguration.DEFAULT, - disabled=panel.get_value("is_running", False), - key="terminal_configuration", - ) - - st.title("Timing Settings") - - st.selectbox("Sample Clock Source", options=["Onboard Clock"], index=0, disabled=True) - st.number_input( - "Sample Rate", - value=1000.0, - min_value=1.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="rate", - ) - st.number_input( - "Number of Samples", - value=100, - min_value=1, - step=1, - disabled=panel.get_value("is_running", False), - key="total_samples", - ) - st.number_input( - "Actual Sample Rate", - value=panel.get_value("actual_sample_rate", 1000.0), - key="actual_sample_rate", - step=1.0, - disabled=True, - ) + - st.title("Logging Settings") - enum_selectbox( - panel, - label="Logging Mode", - value=LoggingMode.OFF, - disabled=panel.get_value("is_running", False), - key="logging_mode", - ) - tdms_file_path = st.text_input( - label="TDMS File Path", - disabled=panel.get_value("is_running", False), - value="data.tdms", - key="tdms_file_path", - ) - st.title("Filtering Settings") - filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) - panel.set_value("filter", filter) - enum_selectbox( - panel, - label="Filter Response", - value=FilterResponse.COMB, - disabled=panel.get_value("is_running", False), - key="filter_response", - ) - - filter_freq = st.number_input( - "Filtering Frequency", - value=1000.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - filter_order = st.number_input( - "Filter Order", - min_value=0, - max_value=1, - value=1, - disabled=panel.get_value("is_running", False), - ) - st.selectbox( - "Actual Filter Frequency", - options=[panel.get_value("actual_filter_freq")], - disabled=True, - ) - st.selectbox( - "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True - ) - - -with right_col: - with st.container(border=True): st.title("Trigger Settings") id = stx.tab_bar( data=[ @@ -323,109 +320,91 @@ ) trigger_type = id panel.set_value("trigger_type", trigger_type) - tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs( - [ - "No Trigger", - "Digital Start", - "Digital Pause", - "Digital Reference", - "Analog Start", - "Analog Pause", - "Analog Reference", - ] - ) - with tab1: - st.write( - "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." - ) - with tab2: - st.selectbox("Source->", " /Dev1/PFI0") - enum_selectbox( - panel, - label="Edge", - value=Edge.FALLING, - disabled=panel.get_value("is_running", False), - key="edge", - ) - with tab3: - st.selectbox("Source-", "/Dev1/PFI0") - pause_when = st.selectbox( - "Pause When", - options=[(e.name, e.value) for e in PauseWhen], - format_func=lambda x: x[0], - index=0, - ) - pause_when = PauseWhen[pause_when[0]] # type: ignore - panel.set_value("pause_when", pause_when) - with tab4: - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" - ) - with tab5: - st.selectbox("Source:", "APFI0") - enum_selectbox( - panel, - label="Slope", - value=Slope.FALLING, - disabled=panel.get_value("is_running", False), - key="slope", - ) - - level = st.number_input("Level") - panel.set_value("level", level) - hysteriesis = st.number_input( - "Hysteriesis", disabled=panel.get_value("is_running", False) - ) - panel.set_value("hysteriesis", hysteriesis) + + if trigger_type == "1": + with st.container(border=True): + st.write( + "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." + ) + if trigger_type == "2": + with st.container(border=True): + st.selectbox("Source->", " /Dev1/PFI0") + enum_selectbox( + panel, + label="Edge", + value=Edge.FALLING, + disabled=panel.get_value("is_running", False), + key="edge", + ) + if trigger_type == "3": + with st.container(border=True): + st.selectbox("Source-", "/Dev1/PFI0") + st.selectbox("PauseWhen", options=["High", "Low"]) + if trigger_type == "4": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + if trigger_type == "5": + with st.container(border=True): + st.selectbox("Source:", "APFI0") + enum_selectbox( + panel, + label="Slope", + value=Slope.FALLING, + disabled=panel.get_value("is_running", False), + key="slope", + ) - with tab6: - st.selectbox("source:", "APFI0") - analog_pause = st.selectbox( - "analog_pause", - options=[(e.name, e.value) for e in AnalogPause], - format_func=lambda x: x[0], - index=0, - ) - analog_pause = AnalogPause[analog_pause[0]] # type: ignore - panel.set_value("analog_pause", analog_pause) + level = st.number_input("Level") + panel.set_value("level", level) + hysteriesis = st.number_input( + "Hysteriesis", disabled=panel.get_value("is_running", False) + ) + panel.set_value("hysteriesis", hysteriesis) - with tab7: - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." - ) + if trigger_type == "6": + with st.container(border=True): + st.selectbox("source:", "APFI0") + st.selectbox("Pause When", options=["Above Level", "Below level"]) + st.number_input("level", value=0.0) + if trigger_type == "7": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + ) -with right_col: - with st.container(border=True): - acquired_data = panel.get_value("acquired_data", [0.0]) - sample_rate = panel.get_value("sample_rate", 0.0) - acquired_data_graph = { - "animation": False, - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["Voltage (V)"]}, - "xAxis": { - "type": "category", - "data": [x / sample_rate for x in range(len(acquired_data))], - "name": "Time", - "nameLocation": "center", - "nameGap": 40, - }, - "yAxis": { - "type": "value", - "name": "Volts", - "nameRotate": 90, - "nameLocation": "center", - "nameGap": 40, - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": acquired_data, - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", + with st.container(border=True): + acquired_data = panel.get_value("acquired_data", [0.0]) + sample_rate = panel.get_value("sample_rate", 0.0) + acquired_data_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Voltage (V)"]}, + "xAxis": { + "type": "category", + "data": [x / sample_rate for x in range(len(acquired_data))], + "name": "Time", + "nameLocation": "center", + "nameGap": 40, }, - ], - } - st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") + "yAxis": { + "type": "value", + "name": "Volts", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": acquired_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") diff --git a/examples/nidaqmx/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md similarity index 100% rename from examples/nidaqmx/README.md rename to examples/nidaqmx/nidaqmx_continuous_analog_input/README.md diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py similarity index 97% rename from examples/nidaqmx/nidaqmx_continuous_analog_input.py rename to examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index bed43eb..5f2470a 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -59,7 +59,7 @@ logging_mode=panel.get_value("logging_mode", LoggingMode.OFF), operation=LoggingOperation.OPEN_OR_CREATE, ) - panel.set_value("sample_rate", task._timing.samp_clk_rate) + panel.set_value("sample_rate", task.timing.samp_clk_rate) try: print(f"Starting data acquisition...") task.start() diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py similarity index 100% rename from examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py rename to examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py diff --git a/examples/nidaqmx_analog_input_filtering/settings_enum.py b/examples/nidaqmx_analog_input_filtering/settings_enum.py deleted file mode 100644 index 6a484b5..0000000 --- a/examples/nidaqmx_analog_input_filtering/settings_enum.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Enumeration for amplitude values used in the simple graph example.""" - -import enum - - -class PauseWhen(enum.StrEnum): - """Pause When Trigger Setting.""" - - HIGH = "High" - LOW = "Low" - - -class AnalogPause(enum.StrEnum): - """Analog Pause Trigger.""" - - ABOVE = "ABOVE" - BELOW = "BELOW" From 3a22846b8ec313b0bead91400a6ba5eb7efd4b26 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 15:16:21 -0500 Subject: [PATCH 22/50] Fixed panel comments --- .../nidaqmx_analog_input_filtering/README.md | 5 +- .../nidaqmx_analog_input_filtering.py | 34 +- .../nidaqmx_analog_input_filtering_panel.py | 418 +++++++++++++++++ .../README.md | 0 .../nidaqmx_continuous_analog_input.py | 2 +- .../nidaqmx_continuous_analog_input_panel.py | 0 .../nidaqmx_analog_input_filtering_panel.py | 431 ------------------ .../settings_enum.py | 17 - 8 files changed, 445 insertions(+), 462 deletions(-) rename examples/{ => nidaqmx}/nidaqmx_analog_input_filtering/README.md (76%) rename examples/{ => nidaqmx}/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py (88%) create mode 100644 examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/README.md (100%) rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/nidaqmx_continuous_analog_input.py (97%) rename examples/nidaqmx/{ => nidaqmx_continuous_analog_input}/nidaqmx_continuous_analog_input_panel.py (100%) delete mode 100644 examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py delete mode 100644 examples/nidaqmx_analog_input_filtering/settings_enum.py diff --git a/examples/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md similarity index 76% rename from examples/nidaqmx_analog_input_filtering/README.md rename to examples/nidaqmx/nidaqmx_analog_input_filtering/README.md index 6de4443..dcd518a 100644 --- a/examples/nidaqmx_analog_input_filtering/README.md +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md @@ -16,7 +16,8 @@ Script demonstrates analog input data getting continuously acquired, and being f ### Usage +```pwsh poetry install --with examples -poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py -Run `poetry run examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py` +poetry run python examples/all_types/all_types.py +``` diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py similarity index 88% rename from examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py rename to examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 17f7643..a0f608b 100644 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -1,8 +1,10 @@ """Data acquisition script that continuously acquires analog input data.""" +import time from pathlib import Path import nidaqmx +import nidaqmx.system from nidaqmx.constants import ( AcquisitionType, CurrentShuntResistorLocation, @@ -10,8 +12,6 @@ Edge, ExcitationSource, FilterResponse, - LoggingMode, - LoggingOperation, Slope, StrainGageBridgeType, TerminalConfiguration, @@ -22,6 +22,20 @@ panel_script_path = Path(__file__).with_name("nidaqmx_analog_input_filtering_panel.py") panel = nipanel.create_panel(panel_script_path) panel.set_value("is_running", False) + +system = nidaqmx.system.System.local() + +channel_name = [] +for dev in system.devices: + for chan in dev.ai_physical_chans: + channel_name.append(chan.name) +panel.set_value("channel_name", channel_name) +trigger_sources = [] +for dev in system.devices: + if hasattr(dev, "terminals"): + for term in dev.terminals: + trigger_sources.append(term) +panel.set_value("trigger_sources", trigger_sources) try: print(f"Panel URL: {panel.panel_url}") print(f"Waiting for the 'Run' button to be pressed...") @@ -29,16 +43,18 @@ while True: while not panel.get_value("run_button", False): panel.set_value("is_running", False) + # time.sleep(0.1) panel.set_value("is_running", True) panel.set_value("stop_button", False) # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: + chan_type = panel.get_value("chan_type", "1") if chan_type == "2": chan = task.ai_channels.add_ai_current_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), max_val=panel.get_value("max_value_current", 0.01), min_val=panel.get_value("min_value_current", -0.01), ext_shunt_resistor_val=panel.get_value("shunt_resistor_value", 249.0), @@ -50,7 +66,7 @@ elif chan_type == "3": chan = task.ai_channels.add_ai_strain_gage_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), nominal_gage_resistance=panel.get_value("gage_resistance", 350.0), voltage_excit_source=ExcitationSource.EXTERNAL, # Only mode that works max_val=panel.get_value("max_value_strain", 0.001), @@ -66,7 +82,7 @@ ) else: chan = task.ai_channels.add_ai_voltage_chan( - "Mod3/ai10", + panel.get_value("physical_channel", ""), terminal_config=panel.get_value( "terminal_configuration", TerminalConfiguration.DEFAULT ), @@ -79,14 +95,9 @@ sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), ) - panel.set_value("actual_sample_rate", task._timing.samp_clk_rate) + panel.set_value("actual_sample_rate", task.timing.samp_clk_rate) panel.set_value("sample_rate", panel.get_value("rate", 100.0)) - task.in_stream.configure_logging( - file_path=panel.get_value("tdms_file_path", "data.tdms"), - logging_mode=panel.get_value("logging_mode", LoggingMode.OFF), - operation=LoggingOperation.OPEN_OR_CREATE, - ) if panel.get_value("filter", "Filter") == "Filter": chan.ai_filter_enable = True chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) @@ -109,6 +120,7 @@ trigger_slope=panel.get_value("slope", Slope.FALLING), trigger_level=panel.get_value("level", 0.0), ) + if trigger_type == "2": task.triggers.start_trigger.cfg_dig_edge_start_trig( trigger_source="/Dev2/PFI0", trigger_edge=panel.get_value("edge", Edge.FALLING) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py new file mode 100644 index 0000000..68116f0 --- /dev/null +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -0,0 +1,418 @@ +"""Streamlit visualization script to display data acquired by nidaqmx_analog_input_filtering.py.""" + +import extra_streamlit_components as stx # type: ignore[import-untyped] +import streamlit as st +from nidaqmx.constants import ( + CurrentShuntResistorLocation, + CurrentUnits, + Edge, + FilterResponse, + LoggingMode, + Slope, + StrainGageBridgeType, + TerminalConfiguration, +) +from streamlit_echarts import st_echarts + +import nipanel +from nipanel.controls import enum_selectbox + +st.set_page_config(page_title="Analog Input Filtering", page_icon="📈", layout="wide") +st.title("Analog Input - Filtering") +panel = nipanel.get_panel_accessor() + +left_col, right_col = st.columns(2) + + +st.markdown( + """ + + """, + unsafe_allow_html=True, +) + +streamlit_style = """ + + """ +st.markdown(streamlit_style, unsafe_allow_html=True) + + +with left_col: + with st.container(border=True): + is_running = panel.get_value("is_running", True) + if is_running: + st.button("Stop", key="stop_button") + else: + st.button("Run", key="run_button") + + st.title("Channel Settings") + physical_channel = st.selectbox( + options=panel.get_value("channel_name", ["Mod2/ai0"]), + index=0, + label="Physical Channels", + disabled=panel.get_value("is_running", False), + ) + panel.set_value("physical_channel", physical_channel) + enum_selectbox( + panel, + label="Terminal Configuration", + value=TerminalConfiguration.DEFAULT, + disabled=panel.get_value("is_running", False), + key="terminal_configuration", + ) + + st.title("Timing Settings") + + st.selectbox( + "Sample Clock Source", + options=panel.get_value("trigger_sources", [""]), + index=0, + disabled=panel.get_value("is_running", False), + ) + st.number_input( + "Sample Rate", + value=1000.0, + min_value=1.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="rate", + ) + st.number_input( + "Number of Samples", + value=100, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + key="total_samples", + ) + st.number_input( + "Actual Sample Rate", + value=panel.get_value("actual_sample_rate", 1000.0), + key="actual_sample_rate", + step=1.0, + disabled=True, + ) + + st.title("Logging Settings") + enum_selectbox( + panel, + label="Logging Mode", + value=LoggingMode.OFF, + disabled=panel.get_value("is_running", False), + key="logging_mode", + ) + tdms_file_path = st.text_input( + label="TDMS File Path", + disabled=panel.get_value("is_running", False), + value="data.tdms", + key="tdms_file_path", + ) + st.title("Filtering Settings") + + filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) + panel.set_value("filter", filter) + enum_selectbox( + panel, + label="Filter Response", + value=FilterResponse.COMB, + disabled=panel.get_value("is_running", False), + key="filter_response", + ) + + filter_freq = st.number_input( + "Filtering Frequency", + value=1000.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + filter_order = st.number_input( + "Filter Order", + min_value=0, + max_value=1, + value=1, + disabled=panel.get_value("is_running", False), + ) + st.selectbox( + "Actual Filter Frequency", + options=[panel.get_value("actual_filter_freq")], + disabled=True, + ) + st.selectbox( + "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True + ) + +with right_col: + st.title("Task Types") + chosen_id = stx.tab_bar( + data=[ + stx.TabBarItemData(id=1, title="Voltage", description=""), + stx.TabBarItemData(id=2, title="Current", description=""), + stx.TabBarItemData(id=3, title="Strain Gage", description=""), + ], + default=1, + ) + + chan_type = chosen_id + panel.set_value("chan_type", chan_type) + + if chosen_id == "1": + with st.container(border=True): + st.title("Voltage Data") + channel_left, channel_right = st.columns(2) + with channel_left: + max_value_voltage = st.number_input( + "Max Value", + value=5.0, + step=0.1, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("max_value_voltage", max_value_voltage) + + min_value_voltage = st.number_input( + "Min Value", + value=-5.0, + step=0.1, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("min_value_voltage", min_value_voltage) + + if chosen_id == "2": + with st.container(border=True): + st.title("Current Data") + channel_left, channel_right = st.columns(2) + with channel_left: + enum_selectbox( + panel, + label="Shunt Resistor Location", + value=CurrentShuntResistorLocation.EXTERNAL, + disabled=panel.get_value("is_running", False), + key="shunt_location", + ) + enum_selectbox( + panel, + label="Units", + value=CurrentUnits.AMPS, + disabled=panel.get_value("is_running", False), + key="units", + ) + with st.expander("More current info", expanded=False): + min_value_current = st.number_input( + "Min Value", + value=-0.01, + step=0.001, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("min_value_current", min_value_current) + max_value_current = st.number_input( + "Max Value", + value=0.01, + step=1.0, + key="max_value_current", + disabled=panel.get_value("is_running", False), + ) + current = panel.set_value("max_value_current", max_value_current) # type:ignore + shunt_resistor_value = st.number_input( + "Shunt Resistor Value", + value=249.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("shunt_resistor_value", shunt_resistor_value) + if chosen_id == "3": + with st.container(border=True): + st.title("Strain Gage Data") + channel_left, channel_right = st.columns(2) + with channel_left: + min_value_strain = st.number_input( + "Min Value", + value=-0.01, + step=0.01, + ) + panel.set_value("min_value_strain", min_value_strain) + max_value_strain = st.number_input( + "Max Value", value=0.01, step=0.01, max_value=2.0 + ) + panel.set_value("max_value_strain", max_value_strain) + enum_selectbox( + panel, + label="Strain Units", + value=CurrentUnits.AMPS, + disabled=panel.get_value("is_running", False), + key="strain_units", + ) + with st.expander("Strain Gage Information", expanded=False): + st.title("Strain Gage Information") + gage_factor = st.number_input( + "Gage Factor", + value=2.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("gage_factor", gage_factor) + nominal_gage = st.number_input( + "nominal gage resistance", + value=350.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("gage_resistance", nominal_gage) + poisson_ratio = st.number_input( + "poisson ratio", + value=0.3, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("poisson_ratio", poisson_ratio) + with st.expander("Bridge Information", expanded=False): + st.title("Bridge Information") + enum_selectbox( + panel, + label="Strain Configuration", + value=StrainGageBridgeType.FULL_BRIDGE_I, + disabled=panel.get_value("is_running", False), + key="strain_configuration", + ) + wire_resistance = st.number_input( + "lead wire resistance", + value=0.0, + step=1.0, + ) + panel.set_value("wire_resistance", wire_resistance) + initial_voltage = st.number_input( + "initial bridge voltage", + value=0.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("initial_voltage", initial_voltage) + + st.selectbox( + label="voltage excitation source", + key="voltage_excit", + options=["External"], + disabled=True, + ) + panel.set_value("voltage_excitation_source", "voltage_excit") + voltage_excit = st.number_input( + "voltage excitation value", + value=2.5, + step=1.0, + key="voltage_excitation_value", + disabled=panel.get_value("is_running", False), + ) + panel.set_value("voltage_excitation_value", voltage_excit) + + st.title("Trigger Settings") + id = stx.tab_bar( + data=[ + stx.TabBarItemData(id=1, title="No Trigger", description=""), + stx.TabBarItemData(id=2, title="Digital Start", description=""), + stx.TabBarItemData(id=3, title="Digital Pause", description=""), + stx.TabBarItemData(id=4, title="Digital Reference", description=""), + stx.TabBarItemData(id=5, title="Analog Start", description=""), + stx.TabBarItemData(id=6, title="Analog Pause", description=""), + stx.TabBarItemData(id=7, title="Analog Reference", description=""), + ], + default=1, + ) + trigger_type = id + panel.set_value("trigger_type", trigger_type) + + if trigger_type == "1": + with st.container(border=True): + st.write( + "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." + ) + if trigger_type == "2": + with st.container(border=True): + st.selectbox("Source->", " /Dev1/PFI0") + enum_selectbox( + panel, + label="Edge", + value=Edge.FALLING, + disabled=panel.get_value("is_running", False), + key="edge", + ) + if trigger_type == "3": + with st.container(border=True): + st.selectbox("Source-", "/Dev1/PFI0") + st.selectbox("PauseWhen", options=["High", "Low"]) + if trigger_type == "4": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + if trigger_type == "5": + with st.container(border=True): + st.selectbox("Source:", "APFI0") + enum_selectbox( + panel, + label="Slope", + value=Slope.FALLING, + disabled=panel.get_value("is_running", False), + key="slope", + ) + + level = st.number_input("Level") + panel.set_value("level", level) + hysteriesis = st.number_input( + "Hysteriesis", disabled=panel.get_value("is_running", False) + ) + panel.set_value("hysteriesis", hysteriesis) + + if trigger_type == "6": + with st.container(border=True): + st.selectbox("source:", "APFI0") + st.selectbox("Pause When", options=["Above Level", "Below level"]) + st.number_input("level", value=0.0) + if trigger_type == "7": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + ) + + with st.container(border=True): + acquired_data = panel.get_value("acquired_data", [0.0]) + sample_rate = panel.get_value("sample_rate", 0.0) + acquired_data_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Voltage (V)"]}, + "xAxis": { + "type": "category", + "data": [x / sample_rate for x in range(len(acquired_data))], + "name": "Time", + "nameLocation": "center", + "nameGap": 40, + }, + "yAxis": { + "type": "value", + "name": "Volts", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": acquired_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") diff --git a/examples/nidaqmx/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md similarity index 100% rename from examples/nidaqmx/README.md rename to examples/nidaqmx/nidaqmx_continuous_analog_input/README.md diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py similarity index 97% rename from examples/nidaqmx/nidaqmx_continuous_analog_input.py rename to examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index bed43eb..5f2470a 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -59,7 +59,7 @@ logging_mode=panel.get_value("logging_mode", LoggingMode.OFF), operation=LoggingOperation.OPEN_OR_CREATE, ) - panel.set_value("sample_rate", task._timing.samp_clk_rate) + panel.set_value("sample_rate", task.timing.samp_clk_rate) try: print(f"Starting data acquisition...") task.start() diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py similarity index 100% rename from examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py rename to examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py diff --git a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py deleted file mode 100644 index 1dc6c57..0000000 --- a/examples/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ /dev/null @@ -1,431 +0,0 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_analog_input_filtering.py.""" - -import extra_streamlit_components as stx # type: ignore[import-untyped] -import streamlit as st -from nidaqmx.constants import ( - CurrentShuntResistorLocation, - CurrentUnits, - Edge, - FilterResponse, - LoggingMode, - Slope, - StrainGageBridgeType, - TerminalConfiguration, -) -from settings_enum import AnalogPause, PauseWhen -from streamlit_echarts import st_echarts - -import nipanel -from nipanel.controls import enum_selectbox - -st.set_page_config(page_title="Analog Input Filtering", page_icon="📈", layout="wide") -st.title("Analog Input - Filtering") -panel = nipanel.get_panel_accessor() - -left_col, right_col = st.columns(2) - -with right_col: - with st.container(border=True): - st.title("Task Types") - chosen_id = stx.tab_bar( - data=[ - stx.TabBarItemData(id=1, title="Voltage", description=""), - stx.TabBarItemData(id=2, title="Current", description=""), - stx.TabBarItemData(id=3, title="Strain Gage", description=""), - ], - default=1, - ) - tabs = st.tabs(["Voltage", "Current", "Strain Gage"]) - with st.container(border=True): - with tabs[0]: - st.title("Voltage Data") - channel_left, channel_right = st.columns(2) - with channel_left: - max_value_voltage = st.number_input( - "Max Value", - value=5.0, - step=0.1, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("max_value_voltage", max_value_voltage) - - min_value_voltage = st.number_input( - "Min Value", - value=-5.0, - step=0.1, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("min_value_voltage", min_value_voltage) - - with tabs[1]: - st.title("Current Data") - channel_left, channel_right = st.columns(2) - with channel_left: - enum_selectbox( - panel, - label="Shunt Resistor Location", - value=CurrentShuntResistorLocation.EXTERNAL, - disabled=panel.get_value("is_running", False), - key="shunt_location", - ) - enum_selectbox( - panel, - label="Units", - value=CurrentUnits.AMPS, - disabled=panel.get_value("is_running", False), - key="units", - ) - with st.expander("More current info", expanded=False): - min_value_current = st.number_input( - "Min Value", - value=-0.01, - step=0.001, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("min_value_current", min_value_current) - max_value_current = st.number_input( - "Max Value", - value=0.01, - step=1.0, - key="max_value_current", - disabled=panel.get_value("is_running", False), - ) - current = panel.set_value( - "max_value_current", max_value_current - ) # type:ignore - shunt_resistor_value = st.number_input( - "Shunt Resistor Value", - value=249.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("shunt_resistor_value", shunt_resistor_value) - with tabs[2]: - st.title("Strain Gage Data") - channel_left, channel_right = st.columns(2) - with channel_left: - min_value_strain = st.number_input( - "Min Value", - value=-0.01, - step=0.01, - ) - panel.set_value("min_value_strain", min_value_strain) - max_value_strain = st.number_input( - "Max Value", value=0.01, step=0.01, max_value=2.0 - ) - panel.set_value("max_value_strain", max_value_strain) - enum_selectbox( - panel, - label="Strain Units", - value=CurrentUnits.AMPS, - disabled=panel.get_value("is_running", False), - key="strain_units", - ) - with st.expander("Strain Gage Information", expanded=False): - st.title("Strain Gage Information") - gage_factor = st.number_input( - "Gage Factor", - value=2.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("gage_factor", gage_factor) - nominal_gage = st.number_input( - "nominal gage resistance", - value=350.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("gage_resistance", nominal_gage) - poisson_ratio = st.number_input( - "poisson ratio", - value=0.3, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("poisson_ratio", poisson_ratio) - with st.expander("Bridge Information", expanded=False): - st.title("Bridge Information") - enum_selectbox( - panel, - label="Strain Configuration", - value=StrainGageBridgeType.FULL_BRIDGE_I, - disabled=panel.get_value("is_running", False), - key="strain_configuration", - ) - wire_resistance = st.number_input( - "lead wire resistance", - value=0.0, - step=1.0, - ) - panel.set_value("wire_resistance", wire_resistance) - initial_voltage = st.number_input( - "initial bridge voltage", - value=0.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("initial_voltage", initial_voltage) - - st.selectbox( - label="voltage excitation source", - key="voltage_excit", - options=["External"], - disabled=True, - ) - panel.set_value("voltage_excitation_source", "voltage_excit") - voltage_excit = st.number_input( - "voltage excitation value", - value=2.5, - step=1.0, - key="voltage_excitation_value", - disabled=panel.get_value("is_running", False), - ) - panel.set_value("voltage_excitation_value", voltage_excit) - -panel.set_value("chan_type", "1") - -pages = st.container() -chan_type = chosen_id -panel.set_value("chan_type", chan_type) - -is_running = panel.get_value("is_running", True) -with left_col: - if is_running: - st.button("Stop", key="stop_button") - else: - st.button("Run", key="run_button") - - -st.markdown( - """ - - """, - unsafe_allow_html=True, -) - -streamlit_style = """ - - """ -st.markdown(streamlit_style, unsafe_allow_html=True) - - -with left_col: - with st.container(border=True): - - st.title("Channel Settings") - st.selectbox(options=["Mod3/ai10"], index=0, label="Physical Channels", disabled=True) - - enum_selectbox( - panel, - label="Terminal Configuration", - value=TerminalConfiguration.DEFAULT, - disabled=panel.get_value("is_running", False), - key="terminal_configuration", - ) - - st.title("Timing Settings") - - st.selectbox("Sample Clock Source", options=["Onboard Clock"], index=0, disabled=True) - st.number_input( - "Sample Rate", - value=1000.0, - min_value=1.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="rate", - ) - st.number_input( - "Number of Samples", - value=100, - min_value=1, - step=1, - disabled=panel.get_value("is_running", False), - key="total_samples", - ) - st.number_input( - "Actual Sample Rate", - value=panel.get_value("actual_sample_rate", 1000.0), - key="actual_sample_rate", - step=1.0, - disabled=True, - ) - - st.title("Logging Settings") - enum_selectbox( - panel, - label="Logging Mode", - value=LoggingMode.OFF, - disabled=panel.get_value("is_running", False), - key="logging_mode", - ) - tdms_file_path = st.text_input( - label="TDMS File Path", - disabled=panel.get_value("is_running", False), - value="data.tdms", - key="tdms_file_path", - ) - st.title("Filtering Settings") - - filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) - panel.set_value("filter", filter) - enum_selectbox( - panel, - label="Filter Response", - value=FilterResponse.COMB, - disabled=panel.get_value("is_running", False), - key="filter_response", - ) - - filter_freq = st.number_input( - "Filtering Frequency", - value=1000.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - filter_order = st.number_input( - "Filter Order", - min_value=0, - max_value=1, - value=1, - disabled=panel.get_value("is_running", False), - ) - st.selectbox( - "Actual Filter Frequency", - options=[panel.get_value("actual_filter_freq")], - disabled=True, - ) - st.selectbox( - "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True - ) - - -with right_col: - with st.container(border=True): - st.title("Trigger Settings") - id = stx.tab_bar( - data=[ - stx.TabBarItemData(id=1, title="No Trigger", description=""), - stx.TabBarItemData(id=2, title="Digital Start", description=""), - stx.TabBarItemData(id=3, title="Digital Pause", description=""), - stx.TabBarItemData(id=4, title="Digital Reference", description=""), - stx.TabBarItemData(id=5, title="Analog Start", description=""), - stx.TabBarItemData(id=6, title="Analog Pause", description=""), - stx.TabBarItemData(id=7, title="Analog Reference", description=""), - ], - default=1, - ) - trigger_type = id - panel.set_value("trigger_type", trigger_type) - tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs( - [ - "No Trigger", - "Digital Start", - "Digital Pause", - "Digital Reference", - "Analog Start", - "Analog Pause", - "Analog Reference", - ] - ) - with tab1: - st.write( - "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." - ) - with tab2: - st.selectbox("Source->", " /Dev1/PFI0") - enum_selectbox( - panel, - label="Edge", - value=Edge.FALLING, - disabled=panel.get_value("is_running", False), - key="edge", - ) - with tab3: - st.selectbox("Source-", "/Dev1/PFI0") - pause_when = st.selectbox( - "Pause When", - options=[(e.name, e.value) for e in PauseWhen], - format_func=lambda x: x[0], - index=0, - ) - pause_when = PauseWhen[pause_when[0]] # type: ignore - panel.set_value("pause_when", pause_when) - with tab4: - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" - ) - with tab5: - st.selectbox("Source:", "APFI0") - enum_selectbox( - panel, - label="Slope", - value=Slope.FALLING, - disabled=panel.get_value("is_running", False), - key="slope", - ) - - level = st.number_input("Level") - panel.set_value("level", level) - hysteriesis = st.number_input( - "Hysteriesis", disabled=panel.get_value("is_running", False) - ) - panel.set_value("hysteriesis", hysteriesis) - - with tab6: - st.selectbox("source:", "APFI0") - analog_pause = st.selectbox( - "analog_pause", - options=[(e.name, e.value) for e in AnalogPause], - format_func=lambda x: x[0], - index=0, - ) - analog_pause = AnalogPause[analog_pause[0]] # type: ignore - panel.set_value("analog_pause", analog_pause) - - with tab7: - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." - ) - - -with right_col: - with st.container(border=True): - acquired_data = panel.get_value("acquired_data", [0.0]) - sample_rate = panel.get_value("sample_rate", 0.0) - acquired_data_graph = { - "animation": False, - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["Voltage (V)"]}, - "xAxis": { - "type": "category", - "data": [x / sample_rate for x in range(len(acquired_data))], - "name": "Time", - "nameLocation": "center", - "nameGap": 40, - }, - "yAxis": { - "type": "value", - "name": "Volts", - "nameRotate": 90, - "nameLocation": "center", - "nameGap": 40, - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": acquired_data, - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - ], - } - st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") diff --git a/examples/nidaqmx_analog_input_filtering/settings_enum.py b/examples/nidaqmx_analog_input_filtering/settings_enum.py deleted file mode 100644 index 6a484b5..0000000 --- a/examples/nidaqmx_analog_input_filtering/settings_enum.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Enumeration for amplitude values used in the simple graph example.""" - -import enum - - -class PauseWhen(enum.StrEnum): - """Pause When Trigger Setting.""" - - HIGH = "High" - LOW = "Low" - - -class AnalogPause(enum.StrEnum): - """Analog Pause Trigger.""" - - ABOVE = "ABOVE" - BELOW = "BELOW" From 92b3260d3c98b12fe25f06fd7f1c7314de1d0eb5 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 15:29:25 -0500 Subject: [PATCH 23/50] format number input --- .../nidaqmx_analog_input_filtering.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index a0f608b..5430890 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -16,9 +16,10 @@ StrainGageBridgeType, TerminalConfiguration, ) +import time +import nidaqmx.system import nipanel - panel_script_path = Path(__file__).with_name("nidaqmx_analog_input_filtering_panel.py") panel = nipanel.create_panel(panel_script_path) panel.set_value("is_running", False) @@ -89,6 +90,7 @@ max_val=panel.get_value("max_value_voltage", 5.0), min_val=panel.get_value("min_value_voltage", -5.0), ) + task.timing.cfg_samp_clk_timing( rate=panel.get_value("rate", 1000.0), @@ -97,7 +99,7 @@ ) panel.set_value("actual_sample_rate", task.timing.samp_clk_rate) panel.set_value("sample_rate", panel.get_value("rate", 100.0)) - + if panel.get_value("filter", "Filter") == "Filter": chan.ai_filter_enable = True chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) @@ -112,7 +114,7 @@ panel.set_value("actual_filter_freq", 0.0) panel.set_value("actual_filter_response", FilterResponse.COMB) panel.set_value("actual_filter_order", 0) - + trigger_type = panel.get_value("trigger_type") if trigger_type == "5": task.triggers.start_trigger.cfg_anlg_edge_start_trig( @@ -120,6 +122,7 @@ trigger_slope=panel.get_value("slope", Slope.FALLING), trigger_level=panel.get_value("level", 0.0), ) + if trigger_type == "2": task.triggers.start_trigger.cfg_dig_edge_start_trig( From 68db2a411aecc17d53473f01219daa192525eb58 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 18 Jul 2025 15:31:36 -0500 Subject: [PATCH 24/50] adding number format --- .../nidaqmx_analog_input_filtering_panel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 68116f0..940d605 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -27,12 +27,13 @@ st.markdown( """ - """, - unsafe_allow_html=True, -) - -streamlit_style = """ - """ -st.markdown(streamlit_style, unsafe_allow_html=True) + """, + unsafe_allow_html=True, +) with left_col: @@ -60,7 +56,7 @@ st.title("Channel Settings") physical_channel = st.selectbox( - options=panel.get_value("channel_name", ["Mod2/ai0"]), + options=panel.get_value("available_channel_name", ["Mod2/ai0"]), index=0, label="Physical Channels", disabled=panel.get_value("is_running", False), @@ -78,7 +74,7 @@ st.selectbox( "Sample Clock Source", - options=panel.get_value("trigger_sources", [""]), + options=panel.get_value("available_trigger_sources", [""]), index=0, disabled=panel.get_value("is_running", False), ) @@ -100,7 +96,7 @@ ) st.number_input( "Actual Sample Rate", - value=panel.get_value("actual_sample_rate", 1000.0), + value=panel.get_value("sample_rate", 1000.0), key="actual_sample_rate", step=1.0, disabled=True, @@ -178,16 +174,16 @@ value=5.0, step=0.1, disabled=panel.get_value("is_running", False), + key="max_value_voltage", ) - panel.set_value("max_value_voltage", max_value_voltage) min_value_voltage = st.number_input( "Min Value", value=-5.0, step=0.1, disabled=panel.get_value("is_running", False), + key="min_value_voltage", ) - panel.set_value("min_value_voltage", min_value_voltage) if chosen_id == "2": with st.container(border=True): @@ -215,7 +211,6 @@ step=0.001, disabled=panel.get_value("is_running", False), ) - panel.set_value("min_value_current", min_value_current) max_value_current = st.number_input( "Max Value", value=0.01, @@ -223,14 +218,12 @@ key="max_value_current", disabled=panel.get_value("is_running", False), ) - current = panel.set_value("max_value_current", max_value_current) # type:ignore shunt_resistor_value = st.number_input( "Shunt Resistor Value", value=249.0, step=1.0, disabled=panel.get_value("is_running", False), ) - panel.set_value("shunt_resistor_value", shunt_resistor_value) if chosen_id == "3": with st.container(border=True): st.title("Strain Gage Data") @@ -240,12 +233,15 @@ "Min Value", value=-0.01, step=0.01, + key="min_value_strain", ) - panel.set_value("min_value_strain", min_value_strain) max_value_strain = st.number_input( - "Max Value", value=0.01, step=0.01, max_value=2.0 + "Max Value", + value=0.01, + step=0.01, + max_value=2.0, + key="max_value_strain", ) - panel.set_value("max_value_strain", max_value_strain) enum_selectbox( panel, label="Strain Units", @@ -260,22 +256,22 @@ value=2.0, step=1.0, disabled=panel.get_value("is_running", False), + key="gage_factor", ) - panel.set_value("gage_factor", gage_factor) nominal_gage = st.number_input( "nominal gage resistance", value=350.0, step=1.0, disabled=panel.get_value("is_running", False), + key="gage_resistance", ) - panel.set_value("gage_resistance", nominal_gage) poisson_ratio = st.number_input( "poisson ratio", value=0.3, step=1.0, disabled=panel.get_value("is_running", False), + key="poisson_ratio", ) - panel.set_value("poisson_ratio", poisson_ratio) with st.expander("Bridge Information", expanded=False): st.title("Bridge Information") enum_selectbox( @@ -289,15 +285,15 @@ "lead wire resistance", value=0.0, step=1.0, + key="wire_resistance", ) - panel.set_value("wire_resistance", wire_resistance) initial_voltage = st.number_input( "initial bridge voltage", value=0.0, step=1.0, disabled=panel.get_value("is_running", False), + key="initial_voltage", ) - panel.set_value("initial_voltage", initial_voltage) st.selectbox( label="voltage excitation source", @@ -313,7 +309,6 @@ key="voltage_excitation_value", disabled=panel.get_value("is_running", False), ) - panel.set_value("voltage_excitation_value", voltage_excit) st.title("Trigger Settings") id = stx.tab_bar( @@ -349,8 +344,9 @@ ) if trigger_type == "3": with st.container(border=True): - st.selectbox("Source-", options=panel.get_value("trigger_sources", [""])) - st.selectbox("PauseWhen", options=["High", "Low"]) + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) if trigger_type == "4": with st.container(border=True): st.write( @@ -368,18 +364,18 @@ key="slope", ) - level = st.number_input("Level") - panel.set_value("level", level) + level = st.number_input("Level", key="level") hysteriesis = st.number_input( - "Hysteriesis", disabled=panel.get_value("is_running", False) + "Hysteriesis", + disabled=panel.get_value("is_running", False), + key="hysteriesis", ) - panel.set_value("hysteriesis", hysteriesis) if trigger_type == "6": with st.container(border=True): - st.text_input("source:", "APFI0") - st.selectbox("Pause When", options=["Above Level", "Below level"]) - st.number_input("level", value=0.0) + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) if trigger_type == "7": with st.container(border=True): st.write( From ded87ceec98110ee262f61d74e943c2d95c8bd6e Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 21 Jul 2025 14:06:27 -0500 Subject: [PATCH 31/50] deleting unecessary variables --- .../nidaqmx_analog_input_filtering_panel.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index af48541..2a6bbe6 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -152,7 +152,7 @@ with right_col: st.title("Task Types") - chosen_id = stx.tab_bar( + chan_type = stx.tab_bar( data=[ stx.TabBarItemData(id=1, title="Voltage", description=""), stx.TabBarItemData(id=2, title="Current", description=""), @@ -161,10 +161,9 @@ default=1, ) - chan_type = chosen_id panel.set_value("chan_type", chan_type) - if chosen_id == "1": + if chan_type == "1": with st.container(border=True): st.title("Voltage Data") channel_left, channel_right = st.columns(2) @@ -185,7 +184,7 @@ key="min_value_voltage", ) - if chosen_id == "2": + if chan_type == "2": with st.container(border=True): st.title("Current Data") channel_left, channel_right = st.columns(2) @@ -224,7 +223,7 @@ step=1.0, disabled=panel.get_value("is_running", False), ) - if chosen_id == "3": + if chan_type == "3": with st.container(border=True): st.title("Strain Gage Data") channel_left, channel_right = st.columns(2) @@ -311,7 +310,7 @@ ) st.title("Trigger Settings") - id = stx.tab_bar( + trigger_type = stx.tab_bar( data=[ stx.TabBarItemData(id=1, title="No Trigger", description=""), stx.TabBarItemData(id=2, title="Digital Start", description=""), @@ -323,7 +322,6 @@ ], default=1, ) - trigger_type = id panel.set_value("trigger_type", trigger_type) if trigger_type == "1": @@ -333,7 +331,9 @@ ) if trigger_type == "2": with st.container(border=True): - source = st.selectbox("Source->", options=panel.get_value("trigger_sources", [""])) + source = st.selectbox( + "Source->", options=panel.get_value("available_trigger_sources", [""]) + ) panel.set_value("digital_source", source) enum_selectbox( panel, @@ -354,8 +354,7 @@ ) if trigger_type == "5": with st.container(border=True): - analog_source = st.text_input("Source:", "APFI0") - panel.set_value("analog_source", analog_source) + analog_source = st.text_input("Source:", "APFI0", key="analog_source") enum_selectbox( panel, label="Slope", From f158a15533adeb3759527263b31dfc439550ddf2 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 23 Jul 2025 09:44:38 -0500 Subject: [PATCH 32/50] updated run button and panel methods --- .../nidaqmx_analog_input_filtering.py | 11 +++++------ .../nidaqmx_analog_input_filtering_panel.py | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 2cd4041..9c4bb21 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -20,7 +20,7 @@ import nipanel panel_script_path = Path(__file__).with_name("nidaqmx_analog_input_filtering_panel.py") -panel = nipanel.create_panel(panel_script_path) +panel = nipanel.create_streamlit_panel(panel_script_path) panel.set_value("is_running", False) system = nidaqmx.system.System.local() @@ -42,12 +42,9 @@ print(f"Waiting for the 'Run' button to be pressed...") print(f"(Press Ctrl + C to quit)") while True: + panel.set_value("run_button", False) while not panel.get_value("run_button", False): - panel.set_value("is_running", False) time.sleep(0.1) - panel.set_value("is_running", True) - panel.set_value("stop_button", False) - # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: @@ -132,6 +129,9 @@ try: task.start() + panel.set_value("is_running", True) + + panel.set_value("stop_button", False) while not panel.get_value("stop_button", False): data = task.read( number_of_samples_per_channel=100 # pyright: ignore[reportArgumentType] @@ -142,7 +142,6 @@ finally: task.stop() panel.set_value("is_running", False) - panel.set_value("run_button", False) except KeyboardInterrupt: diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 2a6bbe6..664fc76 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -19,7 +19,7 @@ st.set_page_config(page_title="Analog Input Filtering", page_icon="📈", layout="wide") st.title("Analog Input - Filtering") -panel = nipanel.get_panel_accessor() +panel = nipanel.get_streamlit_panel_accessor() left_col, right_col = st.columns(2) From be3c739131295cad913a812e6048c21e5f3f0908 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 23 Jul 2025 13:21:42 -0500 Subject: [PATCH 33/50] setting default values --- .../nidaqmx_analog_input_filtering_panel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 664fc76..59b0177 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -143,11 +143,11 @@ ) st.selectbox( "Actual Filter Frequency", - options=[panel.get_value("actual_filter_freq")], + options=[panel.get_value("actual_filter_freq", 0.0)], disabled=True, ) st.selectbox( - "Actual Filter Order", options=[panel.get_value("actual_filter_order")], disabled=True + "Actual Filter Order", options=[panel.get_value("actual_filter_order", 0)], disabled=True ) with right_col: @@ -383,7 +383,7 @@ with st.container(border=True): acquired_data = panel.get_value("acquired_data", [0.0]) - sample_rate = panel.get_value("sample_rate", 0.0) + sample_rate = panel.get_value("sample_rate", 100.0) acquired_data_graph = { "animation": False, "tooltip": {"trigger": "axis"}, From 207fe57bd70eeec5ef17ca117f62127fb03b8f64 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Wed, 23 Jul 2025 14:46:38 -0500 Subject: [PATCH 34/50] adding daq errors --- .../nidaqmx_analog_input_filtering.py | 19 ++++++++++++------- .../nidaqmx_analog_input_filtering_panel.py | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 9c4bb21..7f86030 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -16,6 +16,7 @@ StrainGageBridgeType, TerminalConfiguration, ) +from nidaqmx.errors import DaqError import nipanel @@ -25,11 +26,11 @@ system = nidaqmx.system.System.local() -available_channel_name = [] +available_channel_names = [] for dev in system.devices: for chan in dev.ai_physical_chans: - available_channel_name.append(chan.name) -panel.set_value("available_channel_name", available_channel_name) + available_channel_names.append(chan.name) +panel.set_value("available_channel_names", available_channel_names) available_trigger_sources = [] for dev in system.devices: @@ -94,14 +95,13 @@ samps_per_chan=panel.get_value("total_samples", 100), ) panel.set_value("sample_rate", task.timing.samp_clk_rate) - + # Not all hardware supports all filter types. + # Refer to your device documentation for more information. if panel.get_value("filter", "Filter") == "Filter": chan.ai_filter_enable = True chan.ai_filter_freq = panel.get_value("filter_freq", 0.0) chan.ai_filter_response = panel.get_value("filter_response", FilterResponse.COMB) chan.ai_filter_order = panel.get_value("filter_order", 1) - # Not all hardware supports all filter types. - # Refer to your device documentation for more information. panel.set_value("actual_filter_freq", chan.ai_filter_freq) panel.set_value("actual_filter_response", chan.ai_filter_response) panel.set_value("actual_filter_order", chan.ai_filter_order) @@ -109,7 +109,8 @@ panel.set_value("actual_filter_freq", 0.0) panel.set_value("actual_filter_response", FilterResponse.COMB) panel.set_value("actual_filter_order", 0) - + # Not all hardware supports all filter types. + # Refer to your device documentation for more information. trigger_type = panel.get_value("trigger_type") if trigger_type == "5": task.triggers.start_trigger.cfg_anlg_edge_start_trig( @@ -128,6 +129,7 @@ ) try: + panel.set_value("daq_errors", "") task.start() panel.set_value("is_running", True) @@ -143,6 +145,9 @@ task.stop() panel.set_value("is_running", False) +except DaqError as e: + daq_errors = str(e) + panel.set_value("daq_errors", daq_errors) except KeyboardInterrupt: pass diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 59b0177..46bee1d 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -56,7 +56,7 @@ st.title("Channel Settings") physical_channel = st.selectbox( - options=panel.get_value("available_channel_name", ["Mod2/ai0"]), + options=panel.get_value("available_channel_names", ["Mod2/ai0"]), index=0, label="Physical Channels", disabled=panel.get_value("is_running", False), @@ -118,7 +118,11 @@ ) st.title("Filtering Settings") - filter = st.selectbox("Filter", options=["No Filtering", "Filter"]) + filter = st.selectbox( + "Filter", + options=["No Filtering", "Filter"], + disabled=panel.get_value("is_running", False), + ) panel.set_value("filter", filter) enum_selectbox( panel, @@ -147,7 +151,9 @@ disabled=True, ) st.selectbox( - "Actual Filter Order", options=[panel.get_value("actual_filter_order", 0)], disabled=True + "Actual Filter Order", + options=[panel.get_value("actual_filter_order", 0)], + disabled=True, ) with right_col: @@ -414,3 +420,8 @@ ], } st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") + with st.container(border=True): + if panel.get_value("daq_errors", "") == "": + st.write("No DAQ Errors Found") + else: + st.error(panel.get_value("daq_errors", "")) From f19d60863f9c8416e2795b7114aedd5bb044a265 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 07:55:21 -0500 Subject: [PATCH 35/50] README.md changes --- examples/nidaqmx/nidaqmx_analog_input_filtering/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md index 4fab4bd..caf340c 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md @@ -18,6 +18,6 @@ Script demonstrates analog input data getting continuously acquired, and being f ```pwsh poetry install --with examples -poetry run python examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +poetry run python examples\nidaqmx\nidaqmx_analog_input_filtering\nidaqmx_analog_input_filtering.py ``` From d06a4fd44334b9c16ae22ac6aab23c4e2177b8b8 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 10:46:58 -0500 Subject: [PATCH 36/50] error handling --- .../nidaqmx_analog_input_filtering.py | 1 + .../nidaqmx_analog_input_filtering_panel.py | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 7f86030..73da621 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -147,6 +147,7 @@ except DaqError as e: daq_errors = str(e) + print(daq_errors) panel.set_value("daq_errors", daq_errors) except KeyboardInterrupt: diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 46bee1d..0038d27 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -53,6 +53,10 @@ st.button("Stop", key="stop_button") else: st.button("Run", key="run_button") + if panel.get_value("daq_errors", "") == "": + pass + else: + st.error(panel.get_value("daq_errors", "")) st.title("Channel Settings") physical_channel = st.selectbox( @@ -420,8 +424,3 @@ ], } st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") - with st.container(border=True): - if panel.get_value("daq_errors", "") == "": - st.write("No DAQ Errors Found") - else: - st.error(panel.get_value("daq_errors", "")) From 338424d9e4b3f19c89e913e6109d43e2b062e95c Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 10:57:43 -0500 Subject: [PATCH 37/50] rename daq_errors -> daq_error --- .../nidaqmx_analog_input_filtering.py | 6 +++--- .../nidaqmx_analog_input_filtering_panel.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 73da621..985b683 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -146,9 +146,9 @@ panel.set_value("is_running", False) except DaqError as e: - daq_errors = str(e) - print(daq_errors) - panel.set_value("daq_errors", daq_errors) + daq_error = str(e) + print(daq_error) + panel.set_value("daq_error", daq_error) except KeyboardInterrupt: pass diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 0038d27..fd5c3b7 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -53,10 +53,10 @@ st.button("Stop", key="stop_button") else: st.button("Run", key="run_button") - if panel.get_value("daq_errors", "") == "": + if panel.get_value("daq_error", "") == "": pass else: - st.error(panel.get_value("daq_errors", "")) + st.error(panel.get_value("daq_error", "")) st.title("Channel Settings") physical_channel = st.selectbox( From 2b1af62c285be5150addaa8fe5ab05156dac8887 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 11:00:50 -0500 Subject: [PATCH 38/50] rename daq_error --- .../nidaqmx_analog_input_filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 985b683..f3b262d 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -129,7 +129,7 @@ ) try: - panel.set_value("daq_errors", "") + panel.set_value("daq_error", "") task.start() panel.set_value("is_running", True) From 25294c4461ed607bb2bef905b30c8cac382b4c30 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 11:09:08 -0500 Subject: [PATCH 39/50] source now works --- .../nidaqmx_analog_input_filtering.py | 2 +- .../nidaqmx_analog_input_filtering_panel.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index f3b262d..23f99d7 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -88,8 +88,8 @@ max_val=panel.get_value("max_value_voltage", 5.0), min_val=panel.get_value("min_value_voltage", -5.0), ) - task.timing.cfg_samp_clk_timing( + source= panel.get_value("source", "/Dev3/PFI0"), # fix source rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index fd5c3b7..8e9ca7d 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -76,12 +76,13 @@ st.title("Timing Settings") - st.selectbox( + source = st.selectbox( "Sample Clock Source", options=panel.get_value("available_trigger_sources", [""]), index=0, disabled=panel.get_value("is_running", False), ) + panel.set_value("source", source) st.number_input( "Sample Rate", value=1000.0, From ec42095f8824d652e8e980cd95b9c2f2979db8f8 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 11:29:26 -0500 Subject: [PATCH 40/50] fix lint errors --- .../nidaqmx_analog_input_filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 23f99d7..8b28957 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -89,7 +89,7 @@ min_val=panel.get_value("min_value_voltage", -5.0), ) task.timing.cfg_samp_clk_timing( - source= panel.get_value("source", "/Dev3/PFI0"), # fix source + source=panel.get_value("source", "/Dev3/PFI0"), # fix source rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), From 4721e33055e5ae96ec2281791be1a749673182d5 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 11:33:35 -0500 Subject: [PATCH 41/50] remove comment --- .../nidaqmx_analog_input_filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index 8b28957..fbff346 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -89,7 +89,7 @@ min_val=panel.get_value("min_value_voltage", -5.0), ) task.timing.cfg_samp_clk_timing( - source=panel.get_value("source", "/Dev3/PFI0"), # fix source + source=panel.get_value("source", "/Dev3/PFI0"), rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), From 9105a3aca4b362fd9e03de605fc6219619b57ca9 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 11:41:14 -0500 Subject: [PATCH 42/50] remove logging --- .../nidaqmx_analog_input_filtering.py | 2 +- .../nidaqmx_analog_input_filtering_panel.py | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index fbff346..a885e02 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -89,7 +89,7 @@ min_val=panel.get_value("min_value_voltage", -5.0), ) task.timing.cfg_samp_clk_timing( - source=panel.get_value("source", "/Dev3/PFI0"), + source=panel.get_value("source", "/Dev3/PFI0"), rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 8e9ca7d..6adf1f0 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -106,21 +106,6 @@ step=1.0, disabled=True, ) - - st.title("Logging Settings") - enum_selectbox( - panel, - label="Logging Mode", - value=LoggingMode.OFF, - disabled=panel.get_value("is_running", False), - key="logging_mode", - ) - tdms_file_path = st.text_input( - label="TDMS File Path", - disabled=panel.get_value("is_running", False), - value="data.tdms", - key="tdms_file_path", - ) st.title("Filtering Settings") filter = st.selectbox( From e4a9179f2d8559dd611217e3d728d874cad70711 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 14:09:23 -0500 Subject: [PATCH 43/50] disable run button --- .../nidaqmx_analog_input_filtering.py | 2 +- .../nidaqmx_analog_input_filtering_panel.py | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index a885e02..c8e8dbb 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -39,6 +39,7 @@ available_trigger_sources.append(term) panel.set_value("available_trigger_sources", available_trigger_sources) try: + panel.set_value("daq_error", "") print(f"Panel URL: {panel.panel_url}") print(f"Waiting for the 'Run' button to be pressed...") print(f"(Press Ctrl + C to quit)") @@ -129,7 +130,6 @@ ) try: - panel.set_value("daq_error", "") task.start() panel.set_value("is_running", True) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 6adf1f0..609f3ef 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -7,7 +7,6 @@ CurrentUnits, Edge, FilterResponse, - LoggingMode, Slope, StrainGageBridgeType, TerminalConfiguration, @@ -46,17 +45,31 @@ ) +def hide_buttons(): + st.markdown( + """ + + """, + unsafe_allow_html=True, + ) + + with left_col: with st.container(border=True): is_running = panel.get_value("is_running", True) if is_running: st.button("Stop", key="stop_button") else: - st.button("Run", key="run_button") + run_button = st.button("Run", key="run_button") if panel.get_value("daq_error", "") == "": pass else: - st.error(panel.get_value("daq_error", "")) + hide_buttons() + st.error(panel.get_value("daq_error", "") + " Please re-run script") st.title("Channel Settings") physical_channel = st.selectbox( From 8440772c0128ece86c21ab50dc3f771538ff6a1e Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 14:33:06 -0500 Subject: [PATCH 44/50] added onboard clock --- .../nidaqmx_analog_input_filtering.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py index c8e8dbb..62b6511 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py @@ -32,7 +32,7 @@ available_channel_names.append(chan.name) panel.set_value("available_channel_names", available_channel_names) -available_trigger_sources = [] +available_trigger_sources = [""] for dev in system.devices: if hasattr(dev, "terminals"): for term in dev.terminals: @@ -90,7 +90,7 @@ min_val=panel.get_value("min_value_voltage", -5.0), ) task.timing.cfg_samp_clk_timing( - source=panel.get_value("source", "/Dev3/PFI0"), + source=panel.get_value("source", ""), # "" - means Onboard Clock (default value) rate=panel.get_value("rate", 1000.0), sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=panel.get_value("total_samples", 100), From 76a8d262865fe3038abef4874dd549a80a60b5bf Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 24 Jul 2025 14:55:04 -0500 Subject: [PATCH 45/50] renaming hide_button method --- .../nidaqmx_analog_input_filtering_panel.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index 609f3ef..5fa9d9e 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -45,7 +45,8 @@ ) -def hide_buttons(): +def hide_run_button(): + """hide_run_button is used to disable run button when DAQ error pops up.""" st.markdown( """ + + """, + unsafe_allow_html=True, +) + + +with left_col: + with st.container(border=True): + if panel.get_value("is_running", True): + st.button("Stop", key="stop_button") + elif not panel.get_value("is_running", True) and panel.get_value("daq_error", "") == "": + run_button = st.button("Run", key="run_button") + else: + st.markdown( + """ + + """, + unsafe_allow_html=True, + ) + st.error( + f"There was an error running the script. Fix the issue and re-run nidaqmx_analog_input_filtering.py \n\n {panel.get_value('daq_error', '')}" + ) + + st.title("Channel Settings") + physical_channel = st.selectbox( + options=panel.get_value("available_channel_names", ["Mod2/ai0"]), + index=0, + label="Physical Channels", + disabled=panel.get_value("is_running", False), + ) + panel.set_value("physical_channel", physical_channel) + + max_value_voltage = st.number_input( + "Max Value", + value=5.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="max_value_voltage", + ) + + min_value_voltage = st.number_input( + "Min Value", + value=-5.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="min_value_voltage", + ) + st.title("Timing and Buffer Settings") + + source = st.selectbox( + "Sample Clock Source", + options=panel.get_value("available_trigger_sources", [""]), + index=0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("source", source) + st.number_input( + "Sample Rate", + value=1000.0, + min_value=1.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="rate", + ) + st.number_input( + "Number of Samples", + value=1000, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + key="total_samples", + ) + st.number_input( + "Actual Sample Rate", + value=panel.get_value("actual_sample_rate", 1000.0), + key="actual_sample_rate", + step=1.0, + disabled=True, + ) + st.title("Waveform Settings") + st.number_input( + "Frequency", + value=panel.get_value("frequency", 10.0), + key="frequency", + step=1.0, + disabled=panel.get_value("is_running", False), + ) + st.number_input( + "Amplitude", + value=panel.get_value("amplitude", 1.0), + key="amplitude", + step=1.0, + disabled=panel.get_value("is_running", False), + ) + st.selectbox( + label="Wave Type", + options=["Sine Wave", "Triangle Wave", "Square Wave"], + key="wave_type", + disabled=panel.get_value("is_running", False), + ) + +with right_col: + with st.container(border=True): + st.title("Trigger Settings") + trigger_type = stx.tab_bar( + data=[ + stx.TabBarItemData(id=1, title="No Trigger", description=""), + stx.TabBarItemData(id=2, title="Digital Start", description=""), + stx.TabBarItemData(id=3, title="Digital Pause", description=""), + stx.TabBarItemData(id=4, title="Digital Reference", description=""), + stx.TabBarItemData(id=5, title="Analog Start", description=""), + stx.TabBarItemData(id=6, title="Analog Pause", description=""), + stx.TabBarItemData(id=7, title="Analog Reference", description=""), + ], + default=1, + ) + panel.set_value("trigger_type", trigger_type) + + if trigger_type == "2": + with st.container(border=True): + source = st.selectbox( + "Source:", options=panel.get_value("available_trigger_sources", [""]) + ) + panel.set_value("digital_source", source) + enum_selectbox( + panel, + label="Edge", + value=Edge.FALLING, + disabled=panel.get_value("is_running", False), + key="edge", + ) + else: + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + ) + + with st.container(border=True): + acquired_data = panel.get_value("data", [0.0]) + sample_rate = panel.get_value("sample_rate", 1000.0) + acquired_data_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Voltage (V)"]}, + "xAxis": { + "type": "category", + "data": [x / sample_rate for x in range(len(acquired_data))], + "name": "Time", + "nameLocation": "center", + "nameGap": 40, + }, + "yAxis": { + "type": "value", + "name": "Amplitude", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": acquired_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") From 2d4b95e075832c4a43e196c30527a2c038f27ecd Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 25 Jul 2025 10:17:32 -0500 Subject: [PATCH 49/50] remove analog output and markdown --- .../nidaqmx_analog_input_filtering_panel.py | 200 ++++++++--------- .../nidaqmx_analog_output_voltage_panel.py | 206 ------------------ 2 files changed, 92 insertions(+), 314 deletions(-) delete mode 100644 examples/nidaqmx/nidaqmx_analog_output_voltage/nidaqmx_analog_output_voltage_panel.py diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index f1cb03c..bfb5f46 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -45,120 +45,104 @@ ) -def hide_run_button() -> None: - """hide_run_button is used to disable run button when DAQ error pops up.""" - st.markdown( - """ - - """, - unsafe_allow_html=True, - ) - - with left_col: with st.container(border=True): - is_running = panel.get_value("is_running", True) - if is_running: - st.button("Stop", key="stop_button") - else: - run_button = st.button("Run", key="run_button") - if panel.get_value("daq_error", "") == "": - pass - else: - hide_run_button() - st.error(panel.get_value("daq_error", "") + " Please re-run script") - - st.title("Channel Settings") - physical_channel = st.selectbox( - options=panel.get_value("available_channel_names", ["Mod2/ai0"]), - index=0, - label="Physical Channels", - disabled=panel.get_value("is_running", False), - ) - panel.set_value("physical_channel", physical_channel) - enum_selectbox( - panel, - label="Terminal Configuration", - value=TerminalConfiguration.DEFAULT, - disabled=panel.get_value("is_running", False), - key="terminal_configuration", - ) + with st.container(border=True): + if panel.get_value("is_running", True): + st.button("Stop", key="stop_button") + elif not panel.get_value("is_running", True) and panel.get_value("daq_error", "") == "": + run_button = st.button("Run", key="run_button") + else: + st.error( + f"There was an error running the script. Fix the issue and re-run nidaqmx_analog_input_filtering.py \n\n {panel.get_value('daq_error', '')}" + ) + st.title("Channel Settings") + physical_channel = st.selectbox( + options=panel.get_value("available_channel_names", ["Mod2/ai0"]), + index=0, + label="Physical Channels", + disabled=panel.get_value("is_running", False), + ) + panel.set_value("physical_channel", physical_channel) + enum_selectbox( + panel, + label="Terminal Configuration", + value=TerminalConfiguration.DEFAULT, + disabled=panel.get_value("is_running", False), + key="terminal_configuration", + ) - st.title("Timing Settings") + st.title("Timing Settings") - source = st.selectbox( - "Sample Clock Source", - options=panel.get_value("available_trigger_sources", [""]), - index=0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("source", source) - st.number_input( - "Sample Rate", - value=1000.0, - min_value=1.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="rate", - ) - st.number_input( - "Number of Samples", - value=100, - min_value=1, - step=1, - disabled=panel.get_value("is_running", False), - key="total_samples", - ) - st.number_input( - "Actual Sample Rate", - value=panel.get_value("sample_rate", 1000.0), - key="actual_sample_rate", - step=1.0, - disabled=True, - ) - st.title("Filtering Settings") + source = st.selectbox( + "Sample Clock Source", + options=panel.get_value("available_trigger_sources", [""]), + index=0, + disabled=panel.get_value("is_running", False), + ) + panel.set_value("source", source) + st.number_input( + "Sample Rate", + value=1000.0, + min_value=1.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="rate", + ) + st.number_input( + "Number of Samples", + value=100, + min_value=1, + step=1, + disabled=panel.get_value("is_running", False), + key="total_samples", + ) + st.number_input( + "Actual Sample Rate", + value=panel.get_value("sample_rate", 1000.0), + key="actual_sample_rate", + step=1.0, + disabled=True, + ) + st.title("Filtering Settings") - filter = st.selectbox( - "Filter", - options=["No Filtering", "Filter"], - disabled=panel.get_value("is_running", False), - ) - panel.set_value("filter", filter) - enum_selectbox( - panel, - label="Filter Response", - value=FilterResponse.COMB, - disabled=panel.get_value("is_running", False), - key="filter_response", - ) + filter = st.selectbox( + "Filter", + options=["No Filtering", "Filter"], + disabled=panel.get_value("is_running", False), + ) + panel.set_value("filter", filter) + enum_selectbox( + panel, + label="Filter Response", + value=FilterResponse.COMB, + disabled=panel.get_value("is_running", False), + key="filter_response", + ) - filter_freq = st.number_input( - "Filtering Frequency", - value=1000.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) - filter_order = st.number_input( - "Filter Order", - min_value=0, - max_value=1, - value=1, - disabled=panel.get_value("is_running", False), - ) - st.selectbox( - "Actual Filter Frequency", - options=[panel.get_value("actual_filter_freq", 0.0)], - disabled=True, - ) - st.selectbox( - "Actual Filter Order", - options=[panel.get_value("actual_filter_order", 0)], - disabled=True, - ) + filter_freq = st.number_input( + "Filtering Frequency", + value=1000.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) + filter_order = st.number_input( + "Filter Order", + min_value=0, + max_value=1, + value=1, + disabled=panel.get_value("is_running", False), + ) + st.selectbox( + "Actual Filter Frequency", + options=[panel.get_value("actual_filter_freq", 0.0)], + disabled=True, + ) + st.selectbox( + "Actual Filter Order", + options=[panel.get_value("actual_filter_order", 0)], + disabled=True, + ) with right_col: st.title("Task Types") diff --git a/examples/nidaqmx/nidaqmx_analog_output_voltage/nidaqmx_analog_output_voltage_panel.py b/examples/nidaqmx/nidaqmx_analog_output_voltage/nidaqmx_analog_output_voltage_panel.py deleted file mode 100644 index 22fdd84..0000000 --- a/examples/nidaqmx/nidaqmx_analog_output_voltage/nidaqmx_analog_output_voltage_panel.py +++ /dev/null @@ -1,206 +0,0 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_analog_output_voltage.py.""" - -import extra_streamlit_components as stx # type: ignore[import-untyped] -import streamlit as st -from nidaqmx.constants import Edge -from streamlit_echarts import st_echarts - -import nipanel -from nipanel.controls import enum_selectbox - -st.set_page_config(page_title="Voltage - Continuous Output", page_icon="📈", layout="wide") -st.title("Voltage - Continuous Output") -panel = nipanel.get_streamlit_panel_accessor() - -left_col, right_col = st.columns(2) - -st.markdown( - """ - - - """, - unsafe_allow_html=True, -) - - -with left_col: - with st.container(border=True): - if panel.get_value("is_running", True): - st.button("Stop", key="stop_button") - elif not panel.get_value("is_running", True) and panel.get_value("daq_error", "") == "": - run_button = st.button("Run", key="run_button") - else: - st.markdown( - """ - - """, - unsafe_allow_html=True, - ) - st.error( - f"There was an error running the script. Fix the issue and re-run nidaqmx_analog_input_filtering.py \n\n {panel.get_value('daq_error', '')}" - ) - - st.title("Channel Settings") - physical_channel = st.selectbox( - options=panel.get_value("available_channel_names", ["Mod2/ai0"]), - index=0, - label="Physical Channels", - disabled=panel.get_value("is_running", False), - ) - panel.set_value("physical_channel", physical_channel) - - max_value_voltage = st.number_input( - "Max Value", - value=5.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="max_value_voltage", - ) - - min_value_voltage = st.number_input( - "Min Value", - value=-5.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="min_value_voltage", - ) - st.title("Timing and Buffer Settings") - - source = st.selectbox( - "Sample Clock Source", - options=panel.get_value("available_trigger_sources", [""]), - index=0, - disabled=panel.get_value("is_running", False), - ) - panel.set_value("source", source) - st.number_input( - "Sample Rate", - value=1000.0, - min_value=1.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="rate", - ) - st.number_input( - "Number of Samples", - value=1000, - min_value=1, - step=1, - disabled=panel.get_value("is_running", False), - key="total_samples", - ) - st.number_input( - "Actual Sample Rate", - value=panel.get_value("actual_sample_rate", 1000.0), - key="actual_sample_rate", - step=1.0, - disabled=True, - ) - st.title("Waveform Settings") - st.number_input( - "Frequency", - value=panel.get_value("frequency", 10.0), - key="frequency", - step=1.0, - disabled=panel.get_value("is_running", False), - ) - st.number_input( - "Amplitude", - value=panel.get_value("amplitude", 1.0), - key="amplitude", - step=1.0, - disabled=panel.get_value("is_running", False), - ) - st.selectbox( - label="Wave Type", - options=["Sine Wave", "Triangle Wave", "Square Wave"], - key="wave_type", - disabled=panel.get_value("is_running", False), - ) - -with right_col: - with st.container(border=True): - st.title("Trigger Settings") - trigger_type = stx.tab_bar( - data=[ - stx.TabBarItemData(id=1, title="No Trigger", description=""), - stx.TabBarItemData(id=2, title="Digital Start", description=""), - stx.TabBarItemData(id=3, title="Digital Pause", description=""), - stx.TabBarItemData(id=4, title="Digital Reference", description=""), - stx.TabBarItemData(id=5, title="Analog Start", description=""), - stx.TabBarItemData(id=6, title="Analog Pause", description=""), - stx.TabBarItemData(id=7, title="Analog Reference", description=""), - ], - default=1, - ) - panel.set_value("trigger_type", trigger_type) - - if trigger_type == "2": - with st.container(border=True): - source = st.selectbox( - "Source:", options=panel.get_value("available_trigger_sources", [""]) - ) - panel.set_value("digital_source", source) - enum_selectbox( - panel, - label="Edge", - value=Edge.FALLING, - disabled=panel.get_value("is_running", False), - key="edge", - ) - else: - with st.container(border=True): - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." - ) - - with st.container(border=True): - acquired_data = panel.get_value("data", [0.0]) - sample_rate = panel.get_value("sample_rate", 1000.0) - acquired_data_graph = { - "animation": False, - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["Voltage (V)"]}, - "xAxis": { - "type": "category", - "data": [x / sample_rate for x in range(len(acquired_data))], - "name": "Time", - "nameLocation": "center", - "nameGap": 40, - }, - "yAxis": { - "type": "value", - "name": "Amplitude", - "nameRotate": 90, - "nameLocation": "center", - "nameGap": 40, - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": acquired_data, - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - ], - } - st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") From 5401b66294ac48b9069e3aa76a1e3eb1bc38cb46 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 25 Jul 2025 11:55:14 -0500 Subject: [PATCH 50/50] renaming labels --- .../nidaqmx_analog_input_filtering_panel.py | 352 +++++++++--------- 1 file changed, 175 insertions(+), 177 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py index bfb5f46..fb16937 100644 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ b/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py @@ -145,7 +145,115 @@ ) with right_col: + + with st.container(border=True): + st.title("Acquired Data") + acquired_data = panel.get_value("acquired_data", [0.0]) + sample_rate = panel.get_value("sample_rate", 100.0) + acquired_data_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Voltage (V)"]}, + "xAxis": { + "type": "category", + "data": [x / sample_rate for x in range(len(acquired_data))], + "name": "Time", + "nameLocation": "center", + "nameGap": 40, + }, + "yAxis": { + "type": "value", + "name": "Volts", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "voltage_amplitude", + "type": "line", + "data": acquired_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%") + + st.title("Trigger Settings") + trigger_type = stx.tab_bar( + data=[ + stx.TabBarItemData(id=1, title="No Trigger", description=""), + stx.TabBarItemData(id=2, title="Digital Start", description=""), + stx.TabBarItemData(id=3, title="Digital Pause", description=""), + stx.TabBarItemData(id=4, title="Digital Reference", description=""), + stx.TabBarItemData(id=5, title="Analog Start", description=""), + stx.TabBarItemData(id=6, title="Analog Pause", description=""), + stx.TabBarItemData(id=7, title="Analog Reference", description=""), + ], + default=1, + ) + panel.set_value("trigger_type", trigger_type) + + if trigger_type == "1": + with st.container(border=True): + st.write( + "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." + ) + if trigger_type == "2": + with st.container(border=True): + source = st.selectbox( + "Source", options=panel.get_value("available_trigger_sources", [""]) + ) + panel.set_value("digital_source", source) + enum_selectbox( + panel, + label="Edge", + value=Edge.FALLING, + disabled=panel.get_value("is_running", False), + key="edge", + ) + if trigger_type == "3": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + if trigger_type == "4": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + if trigger_type == "5": + with st.container(border=True): + analog_source = st.text_input("Source", "APFI0", key="analog_source") + enum_selectbox( + panel, + label="Slope", + value=Slope.FALLING, + disabled=panel.get_value("is_running", False), + key="slope", + ) + + level = st.number_input("Level", key="level") + hysteriesis = st.number_input( + "Hysteriesis", + disabled=panel.get_value("is_running", False), + key="hysteriesis", + ) + + if trigger_type == "6": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + ) + if trigger_type == "7": + with st.container(border=True): + st.write( + "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + ) st.title("Task Types") + chan_type = stx.tab_bar( data=[ stx.TabBarItemData(id=1, title="Voltage", description=""), @@ -156,7 +264,6 @@ ) panel.set_value("chan_type", chan_type) - if chan_type == "1": with st.container(border=True): st.title("Voltage Data") @@ -197,26 +304,25 @@ disabled=panel.get_value("is_running", False), key="units", ) - with st.expander("More current info", expanded=False): - min_value_current = st.number_input( - "Min Value", - value=-0.01, - step=0.001, - disabled=panel.get_value("is_running", False), - ) - max_value_current = st.number_input( - "Max Value", - value=0.01, - step=1.0, - key="max_value_current", - disabled=panel.get_value("is_running", False), - ) - shunt_resistor_value = st.number_input( - "Shunt Resistor Value", - value=249.0, - step=1.0, - disabled=panel.get_value("is_running", False), - ) + min_value_current = st.number_input( + "Min Value", + value=-0.01, + step=0.001, + disabled=panel.get_value("is_running", False), + ) + max_value_current = st.number_input( + "Max Value", + value=0.01, + step=1.0, + key="max_value_current", + disabled=panel.get_value("is_running", False), + ) + shunt_resistor_value = st.number_input( + "Shunt Resistor Value", + value=249.0, + step=1.0, + disabled=panel.get_value("is_running", False), + ) if chan_type == "3": with st.container(border=True): st.title("Strain Gage Data") @@ -242,169 +348,61 @@ disabled=panel.get_value("is_running", False), key="strain_units", ) - with st.expander("Strain Gage Information", expanded=False): - st.title("Strain Gage Information") - gage_factor = st.number_input( - "Gage Factor", - value=2.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="gage_factor", - ) - nominal_gage = st.number_input( - "nominal gage resistance", - value=350.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="gage_resistance", - ) - poisson_ratio = st.number_input( - "poisson ratio", - value=0.3, - step=1.0, - disabled=panel.get_value("is_running", False), - key="poisson_ratio", - ) - with st.expander("Bridge Information", expanded=False): - st.title("Bridge Information") - enum_selectbox( - panel, - label="Strain Configuration", - value=StrainGageBridgeType.FULL_BRIDGE_I, - disabled=panel.get_value("is_running", False), - key="strain_configuration", - ) - wire_resistance = st.number_input( - "lead wire resistance", - value=0.0, - step=1.0, - key="wire_resistance", - ) - initial_voltage = st.number_input( - "initial bridge voltage", - value=0.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="initial_voltage", - ) - - st.selectbox( - label="voltage excitation source", - key="voltage_excit", - options=["External"], - disabled=True, - ) - panel.set_value("voltage_excitation_source", "voltage_excit") - voltage_excit = st.number_input( - "voltage excitation value", - value=2.5, - step=1.0, - key="voltage_excitation_value", - disabled=panel.get_value("is_running", False), - ) - - st.title("Trigger Settings") - trigger_type = stx.tab_bar( - data=[ - stx.TabBarItemData(id=1, title="No Trigger", description=""), - stx.TabBarItemData(id=2, title="Digital Start", description=""), - stx.TabBarItemData(id=3, title="Digital Pause", description=""), - stx.TabBarItemData(id=4, title="Digital Reference", description=""), - stx.TabBarItemData(id=5, title="Analog Start", description=""), - stx.TabBarItemData(id=6, title="Analog Pause", description=""), - stx.TabBarItemData(id=7, title="Analog Reference", description=""), - ], - default=1, - ) - panel.set_value("trigger_type", trigger_type) - - if trigger_type == "1": - with st.container(border=True): - st.write( - "To enable triggers, select a tab above, and configure the settings. \n Not all hardware supports all trigger types. Refer to your device documentation for more information." - ) - if trigger_type == "2": - with st.container(border=True): - source = st.selectbox( - "Source->", options=panel.get_value("available_trigger_sources", [""]) - ) - panel.set_value("digital_source", source) + st.title("Strain Gage Information") + gage_factor = st.number_input( + "Gage Factor", + value=2.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="gage_factor", + ) + nominal_gage = st.number_input( + "Nominal Gage Resistance", + value=350.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="gage_resistance", + ) + poisson_ratio = st.number_input( + "Poisson Ratio", + value=0.3, + step=1.0, + disabled=panel.get_value("is_running", False), + key="poisson_ratio", + ) + st.title("Bridge Information") enum_selectbox( panel, - label="Edge", - value=Edge.FALLING, + label="Strain Configuration", + value=StrainGageBridgeType.FULL_BRIDGE_I, disabled=panel.get_value("is_running", False), - key="edge", - ) - if trigger_type == "3": - with st.container(border=True): - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" - ) - if trigger_type == "4": - with st.container(border=True): - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + key="strain_configuration", ) - if trigger_type == "5": - with st.container(border=True): - analog_source = st.text_input("Source:", "APFI0", key="analog_source") - enum_selectbox( - panel, - label="Slope", - value=Slope.FALLING, - disabled=panel.get_value("is_running", False), - key="slope", + wire_resistance = st.number_input( + "Lead Wire Resistance", + value=0.0, + step=1.0, + key="wire_resistance", ) - - level = st.number_input("Level", key="level") - hysteriesis = st.number_input( - "Hysteriesis", + initial_voltage = st.number_input( + "Initial Bridge Voltage", + value=0.0, + step=1.0, disabled=panel.get_value("is_running", False), - key="hysteriesis", + key="initial_voltage", ) - if trigger_type == "6": - with st.container(border=True): - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported" + st.selectbox( + label="Voltage Excitation Source", + key="voltage_excit", + options=["External"], + disabled=True, ) - if trigger_type == "7": - with st.container(border=True): - st.write( - "This trigger type is not supported in continuous sample timing. Refer to your device documentation for more information on which triggers are supported." + panel.set_value("voltage_excitation_source", "voltage_excit") + voltage_excit = st.number_input( + "Voltage Excitation Value", + value=2.5, + step=1.0, + key="voltage_excitation_value", + disabled=panel.get_value("is_running", False), ) - - with st.container(border=True): - acquired_data = panel.get_value("acquired_data", [0.0]) - sample_rate = panel.get_value("sample_rate", 100.0) - acquired_data_graph = { - "animation": False, - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["Voltage (V)"]}, - "xAxis": { - "type": "category", - "data": [x / sample_rate for x in range(len(acquired_data))], - "name": "Time", - "nameLocation": "center", - "nameGap": 40, - }, - "yAxis": { - "type": "value", - "name": "Volts", - "nameRotate": 90, - "nameLocation": "center", - "nameGap": 40, - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": acquired_data, - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - ], - } - st_echarts(options=acquired_data_graph, height="400px", key="graph", width="100%")