From b7abc39cf611a83a9a24e62ce33d434313889559 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Thu, 19 Jun 2025 06:53:29 -0500 Subject: [PATCH 01/76] 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 00000000..246e0537 --- /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 00000000..b83f09b5 --- /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 09977e43..188c1f24 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 2adc8d0e..deb57309 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 11ecccc0..0b8cfc70 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/76] 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 00000000..2f88b80c --- /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 00000000..7fae255c --- /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 0b8cfc70..15808cfe 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/76] 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 2f88b80c..00000000 --- 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 246e0537..00000000 --- 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 b83f09b5..00000000 --- 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 00000000..3429bd32 --- /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/76] 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 f3ab592d..6abbfdac 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 83f9d1c6..a55a0767 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 6c7c312a..eff6cd47 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 09f26305..a2f208f4 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 e7da4462..5f2a5ab8 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/76] 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 00000000..5bd4314b --- /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/76] 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 d15973a3..562b2efe 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 853890f0..28311aa3 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 a2f208f4..6a484b5d 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 4d242594..a3afd9ff 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/76] 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 d15973a3..562b2efe 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 853890f0..28311aa3 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 a2f208f4..6a484b5d 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 4d242594..a3afd9ff 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/76] 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 5bd4314b..6de44432 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 5f2a5ab8..68d73161 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 b1f12ca3..00000000 --- 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 73f78320..f5208c52 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 a3afd9ff..01e057c4 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/76] 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 f5208c52..324cf7cc 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 01e057c4..6550627a 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/76] 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 f5208c52..97a27b2e 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 01e057c4..6550627a 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/76] 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 324cf7cc..4b63530f 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/76] Poetry lock --- poetry.lock | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9f7e6d63..24c02a2c 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/76] 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 72f7e956..ec674483 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 dc389b3c..c2ef4eee 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/76] 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 72f7e956..ec674483 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 dc389b3c..c2ef4eee 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/76] changes to poetry lock file --- poetry.lock | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 1114bd82..fd847b27 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/76] 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 3bcae847..849a1846 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 3c5b8d43..1dc6c572 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 1114bd82..fd847b27 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/76] 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 849a1846..171ecd39 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/76] 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 171ecd39..c0783a4f 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/76] 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 c0783a4f..17f7643d 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/76] 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 6de44432..dcd518a0 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 17f7643d..98a0e2f0 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 1dc6c572..73f0034e 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 bed43eb7..5f2470a0 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 6a484b5d..00000000 --- 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/76] 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 6de44432..dcd518a0 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 17f7643d..a0f608b1 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 00000000..68116f05 --- /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 bed43eb7..5f2470a0 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 1dc6c572..00000000 --- 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 6a484b5d..00000000 --- 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/76] 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 a0f608b1..54308903 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/76] 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 68116f05..940d6057 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/76] 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 af485414..2a6bbe62 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/76] 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 2cd4041a..9c4bb21d 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 2a6bbe62..664fc766 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/76] 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 664fc766..59b01770 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/76] 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 9c4bb21d..7f86030a 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 59b01770..46bee1d0 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/76] 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 4fab4bd9..caf340ce 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/76] 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 7f86030a..73da6213 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 46bee1d0..0038d272 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/76] 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 73da6213..985b6839 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 0038d272..fd5c3b73 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/76] 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 985b6839..f3b262d3 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/76] 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 f3b262d3..23f99d7c 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 fd5c3b73..8e9ca7dc 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/76] 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 23f99d7c..8b289570 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/76] 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 8b289570..fbff346e 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/76] 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 fbff346e..a885e02e 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 8e9ca7dc..6adf1f0e 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/76] 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 a885e02e..c8e8dbb0 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 6adf1f0e..609f3ef6 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/76] 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 c8e8dbb0..62b6511d 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/76] 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 609f3ef6..5fa9d9e0 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/76] 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 f1cb03c9..bfb5f46e 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 22fdd843..00000000 --- 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/76] 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 bfb5f46e..fb169372 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%") From 733b95355336abd994ab4429aef4d803f3b5174f Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 08:51:57 -0500 Subject: [PATCH 51/76] update error message --- .../nidaqmx_continuous_analog_input.py | 17 ++++++++++++----- .../nidaqmx_continuous_analog_input_panel.py | 8 ++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index ec089ad5..53545a93 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -6,13 +6,14 @@ import nidaqmx from nidaqmx.constants import ( AcquisitionType, - TerminalConfiguration, CJCSource, - TemperatureUnits, - ThermocoupleType, LoggingMode, LoggingOperation, + TemperatureUnits, + TerminalConfiguration, + ThermocoupleType, ) +from nidaqmx.errors import DaqError import nipanel @@ -20,6 +21,8 @@ panel = nipanel.create_streamlit_panel(panel_script_path) 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)") @@ -31,7 +34,7 @@ # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: task.ai_channels.add_ai_voltage_chan( - physical_channel="Dev1/ai0", + physical_channel="Dev4/ai0", min_val=panel.get_value("voltage_min_value", -5.0), max_val=panel.get_value("voltage_max_value", 5.0), terminal_config=panel.get_value( @@ -39,7 +42,7 @@ ), ) task.ai_channels.add_ai_thrmcpl_chan( - "Dev1/ai1", + "Dev4/ai1", min_val=panel.get_value("thermocouple_min_value", 0.0), max_val=panel.get_value("thermocouple_max_value", 100.0), units=panel.get_value("thermocouple_units", TemperatureUnits.DEG_C), @@ -79,5 +82,9 @@ task.stop() panel.set_value("is_running", False) +except DaqError as e: + daq_error = str(e) + print(daq_error) + panel.set_value("daq_error", daq_error) except KeyboardInterrupt: pass diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py index 89a22316..7dda6a14 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py @@ -38,9 +38,13 @@ is_running = panel.get_value("is_running", False) if is_running: - st.button(r"âšī¸ Stop", key="stop_button") + st.button("Stop", key="stop_button") +elif not is_running and panel.get_value("daq_error", "") == "": + run_button = st.button("Run", key="run_button") else: - st.button(r"â–ļī¸ Run", key="run_button") + st.error( + f"There was an error running the script. Fix the issue and re-run nidaqmx_continuous_analog_input.py \n\n {panel.get_value('daq_error', '')}" + ) thermocouple_data = panel.get_value("thermocouple_data", [0.0]) voltage_data = panel.get_value("voltage_data", [0.0]) From b0a4fdfa8199d8372a931cdc0b3564445fcf3130 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 09:00:01 -0500 Subject: [PATCH 52/76] update README.md --- examples/nidaqmx/nidaqmx_continuous_analog_input/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md index fb9adfa9..e387eabc 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md @@ -18,5 +18,5 @@ This is a nipanel example that displays an interactive Streamlit app and updates ```pwsh poetry install --with examples -poetry run examples/nidaqmx/nidaqmx_continuous_analog_input.py +poetry run examples\nidaqmx\nidaqmx_continuous_analog_input\nidaqmx_continuous_analog_input.py ``` From 3ea497be6c1ef88f0b389f3bc1175331c10d0ef2 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 09:11:12 -0500 Subject: [PATCH 53/76] remove changes --- .../nidaqmx_analog_input_filtering/README.md | 23 - .../nidaqmx_analog_input_filtering.py | 154 ------- .../nidaqmx_analog_input_filtering_panel.py | 408 ------------------ 3 files changed, 585 deletions(-) delete mode 100644 examples/nidaqmx/nidaqmx_analog_input_filtering/README.md delete mode 100644 examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py delete mode 100644 examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py diff --git a/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md b/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md deleted file mode 100644 index caf340ce..00000000 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/README.md +++ /dev/null @@ -1,23 +0,0 @@ -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 an 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 - -```pwsh -poetry install --with examples -poetry run python examples\nidaqmx\nidaqmx_analog_input_filtering\nidaqmx_analog_input_filtering.py -``` - 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 deleted file mode 100644 index 62b6511d..00000000 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering.py +++ /dev/null @@ -1,154 +0,0 @@ -"""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, - CurrentUnits, - Edge, - ExcitationSource, - FilterResponse, - Slope, - StrainGageBridgeType, - TerminalConfiguration, -) -from nidaqmx.errors import DaqError - -import nipanel - -panel_script_path = Path(__file__).with_name("nidaqmx_analog_input_filtering_panel.py") -panel = nipanel.create_streamlit_panel(panel_script_path) -panel.set_value("is_running", False) - -system = nidaqmx.system.System.local() - -available_channel_names = [] -for dev in system.devices: - for chan in dev.ai_physical_chans: - available_channel_names.append(chan.name) -panel.set_value("available_channel_names", available_channel_names) - -available_trigger_sources = [""] -for dev in system.devices: - if hasattr(dev, "terminals"): - for term in dev.terminals: - 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)") - while True: - panel.set_value("run_button", False) - while not panel.get_value("run_button", False): - time.sleep(0.1) - # 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( - 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), - shunt_resistor_loc=panel.get_value( - "shunt_location", CurrentShuntResistorLocation.EXTERNAL - ), - units=panel.get_value("units", CurrentUnits.AMPS), - ) - - elif chan_type == "3": - chan = task.ai_channels.add_ai_strain_gage_chan( - 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), - min_val=panel.get_value("min_value_strain", -0.001), - poisson_ratio=panel.get_value("poisson_ratio", 0.3), - lead_wire_resistance=panel.get_value("wire_resistance", 0.0), - initial_bridge_voltage=panel.get_value("initial_voltage", 0.0), - gage_factor=panel.get_value("gage_factor", 2.0), - voltage_excit_val=panel.get_value("voltage_excitation_value", 0.0), - strain_config=panel.get_value( - "strain_configuration", StrainGageBridgeType.FULL_BRIDGE_I - ), - ) - else: - chan = task.ai_channels.add_ai_voltage_chan( - 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( - 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), - ) - 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) - 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) - else: - 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( - trigger_source=panel.get_value("analog_source", ""), - 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=panel.get_value("digital_source", ""), - trigger_edge=panel.get_value("edge", Edge.FALLING), - ) - task.triggers.start_trigger.anlg_edge_hyst = hysteresis = panel.get_value( - "hysteresis", 0.0 - ) - - 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] - ) - panel.set_value("acquired_data", data) - except KeyboardInterrupt: - pass - finally: - task.stop() - panel.set_value("is_running", False) - -except DaqError as e: - 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 deleted file mode 100644 index fb169372..00000000 --- a/examples/nidaqmx/nidaqmx_analog_input_filtering/nidaqmx_analog_input_filtering_panel.py +++ /dev/null @@ -1,408 +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, - 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_streamlit_panel_accessor() - -left_col, right_col = st.columns(2) - - -st.markdown( - """ - - - """, - unsafe_allow_html=True, -) - - -with left_col: - with st.container(border=True): - 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") - - 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_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: - - 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=""), - stx.TabBarItemData(id=2, title="Current", description=""), - stx.TabBarItemData(id=3, title="Strain Gage", description=""), - ], - default=1, - ) - - panel.set_value("chan_type", chan_type) - if chan_type == "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), - key="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", - ) - - if chan_type == "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", - ) - 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") - channel_left, channel_right = st.columns(2) - with channel_left: - min_value_strain = st.number_input( - "Min Value", - value=-0.01, - step=0.01, - key="min_value_strain", - ) - max_value_strain = st.number_input( - "Max Value", - value=0.01, - step=0.01, - max_value=2.0, - key="max_value_strain", - ) - enum_selectbox( - panel, - label="Strain Units", - value=CurrentUnits.AMPS, - disabled=panel.get_value("is_running", False), - key="strain_units", - ) - 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="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), - ) From 457020a2845e252cf880133665e1e517fb925e9f Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 09:13:50 -0500 Subject: [PATCH 54/76] removing changes --- poetry.lock | 16 +--------------- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 74a657d8..71434090 100644 --- a/poetry.lock +++ b/poetry.lock @@ -502,20 +502,6 @@ 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" @@ -3277,4 +3263,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0,!=3.9.7" -content-hash = "1b4c4105e78ce7eca099f1a45a130c93565d568f2263e70d6389ab59ed3bbe27" +content-hash = "45dc36d0ef51734fbde48be7f49ed705209f3b0d46c827cd0de4115fbf15ce62" diff --git a/pyproject.toml b/pyproject.toml index 41393ee2..199b079b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,6 @@ optional = true [tool.poetry.group.examples.dependencies] streamlit-echarts = ">=0.4.0" -extra-streamlit-components = "^0.1.80" nidaqmx = { version = ">=0.8.0", allow-prereleases = true } niscope = "^1.4.9" From b9b85ef67312cf9fcddca5c0a9b15fb1a7f3f8bd Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 10:06:02 -0500 Subject: [PATCH 55/76] resolve changes --- .../nidaqmx_continuous_analog_input_panel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py index 7dda6a14..2dee0bad 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py @@ -38,9 +38,9 @@ is_running = panel.get_value("is_running", False) if is_running: - st.button("Stop", key="stop_button") + st.button(r"âšī¸ Stop", key="stop_button") elif not is_running and panel.get_value("daq_error", "") == "": - run_button = st.button("Run", key="run_button") + run_button = st.button(r"â–ļī¸ Run", key="run_button") else: st.error( f"There was an error running the script. Fix the issue and re-run nidaqmx_continuous_analog_input.py \n\n {panel.get_value('daq_error', '')}" From ae409d558ff40a0f7a3f0136c0a7d30bb7c7612b Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 28 Jul 2025 10:12:09 -0500 Subject: [PATCH 56/76] Dev4 -> Dev1 --- .../nidaqmx_continuous_analog_input.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index 53545a93..697d6cde 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -34,7 +34,7 @@ # How to use nidaqmx: https://nidaqmx-python.readthedocs.io/en/stable/ with nidaqmx.Task() as task: task.ai_channels.add_ai_voltage_chan( - physical_channel="Dev4/ai0", + physical_channel="Dev1/ai0", min_val=panel.get_value("voltage_min_value", -5.0), max_val=panel.get_value("voltage_max_value", 5.0), terminal_config=panel.get_value( @@ -42,7 +42,7 @@ ), ) task.ai_channels.add_ai_thrmcpl_chan( - "Dev4/ai1", + "Dev1/ai1", min_val=panel.get_value("thermocouple_min_value", 0.0), max_val=panel.get_value("thermocouple_max_value", 100.0), units=panel.get_value("thermocouple_units", TemperatureUnits.DEG_C), From 0bb90e555eaba0dc0565715eecefb2737fec703a Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 29 Jul 2025 09:06:52 -0500 Subject: [PATCH 57/76] readme --- examples/nidaqmx/nidaqmx_continuous_analog_input/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md index e387eabc..fb9adfa9 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md @@ -18,5 +18,5 @@ This is a nipanel example that displays an interactive Streamlit app and updates ```pwsh poetry install --with examples -poetry run examples\nidaqmx\nidaqmx_continuous_analog_input\nidaqmx_continuous_analog_input.py +poetry run examples/nidaqmx/nidaqmx_continuous_analog_input.py ``` From 498bd7b276243a2bfd33fcd128b9f420ff1d1b4f Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 29 Jul 2025 09:25:03 -0500 Subject: [PATCH 58/76] readme --- examples/nidaqmx/nidaqmx_continuous_analog_input/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md index fb9adfa9..e387eabc 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md @@ -18,5 +18,5 @@ This is a nipanel example that displays an interactive Streamlit app and updates ```pwsh poetry install --with examples -poetry run examples/nidaqmx/nidaqmx_continuous_analog_input.py +poetry run examples\nidaqmx\nidaqmx_continuous_analog_input\nidaqmx_continuous_analog_input.py ``` From a415fe7f820e94b55e38c09d117f075e44fa988e Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 29 Jul 2025 09:46:16 -0500 Subject: [PATCH 59/76] run_button = deleted --- .../nidaqmx_continuous_analog_input_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py index 2dee0bad..942fe3d3 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py @@ -40,7 +40,7 @@ if is_running: st.button(r"âšī¸ Stop", key="stop_button") elif not is_running and panel.get_value("daq_error", "") == "": - run_button = st.button(r"â–ļī¸ Run", key="run_button") + st.button(r"â–ļī¸ Run", key="run_button") else: st.error( f"There was an error running the script. Fix the issue and re-run nidaqmx_continuous_analog_input.py \n\n {panel.get_value('daq_error', '')}" From 869a13bd6184519052895fcd8c053d8cd230236c Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 07:52:23 -0500 Subject: [PATCH 60/76] adding niscope binary example --- .../niscope_binary_acquisition/README.md | 23 +++ .../niscope_binary_acquisition.py | 114 +++++++++++ .../niscope_binary_acquisition_panel.py | 188 ++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 examples/niscope/niscope_binary_acquisition/README.md create mode 100644 examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py create mode 100644 examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py diff --git a/examples/niscope/niscope_binary_acquisition/README.md b/examples/niscope/niscope_binary_acquisition/README.md new file mode 100644 index 00000000..a3518b2c --- /dev/null +++ b/examples/niscope/niscope_binary_acquisition/README.md @@ -0,0 +1,23 @@ +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. This example uses NI oscilloscopes/digitizers, which have the module numbering pattern _51xx_. One example is NI PXIe-5114. + +## Sample + +This is a nipanel example that displays an interactive Streamlit app and updates and fetches data from device. + +### Feature + +Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary. +- Supports various data types + +### Required Software + +- Python 3.9 or later + +### Usage + +```pwsh +poetry install --with examples +poetry run examples\niscope\niscope_binary_acquisition\niscope_binary_acquisition.py +``` diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py new file mode 100644 index 00000000..1883113c --- /dev/null +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -0,0 +1,114 @@ +"""Continuously acquires waveforms from NI-SCOPE, processes/scales them.""" + +import time +from pathlib import Path +from typing import Any + +import hightime +import niscope +import numpy as np +from niscope.enums import ArrayMeasurement +from niscope.errors import Error + +import nipanel + +panel_script_path = Path(__file__).with_name("niscope_binary_acquisition_panel.py") +panel = nipanel.create_streamlit_panel(panel_script_path) + + +"""Example fetch data from device (Dev1).""" +panel.set_value("is_running", False) + +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)") + while True: + panel.set_value("run_button", False) + while not panel.get_value("run_button", False): + time.sleep(0.1) + with niscope.Session(resource_name=panel.get_value("resource_name", "Dev1")) as session: + session.configure_vertical( + range=panel.get_value("vertical_range", 5.0), + coupling=niscope.VerticalCoupling.DC, + offset=panel.get_value("vertical_offset", 0.0), + ) + session.configure_horizontal_timing( + min_sample_rate=panel.get_value("min_sample_rate", 200000000.0), + min_num_pts=1000, + ref_position=50.0, + num_records=1000, + enforce_realtime=True, + ) + + session.configure_trigger_immediate() + + with session.initiate(): + data_size = panel.get_value("data_size", 8) + if data_size == 8: + wfm: np.ndarray[Any, np.dtype[np.int8]] = np.ndarray( # type: ignore + 1000 * 1000, dtype=np.int8 + ) + elif data_size == 16: + wfm: np.ndarray[Any, np.dtype[np.int16]] = np.ndarray( # type: ignore + 1000 * 1000, dtype=np.int16 + ) + else: + wfm: np.ndarray[Any, np.dtype[np.int32]] = np.ndarray( + 1000 * 1000, dtype=np.int32 + ) + + waveforms = session.channels[panel.get_value("channel", 0)].fetch_into( + relative_to=niscope.FetchRelativeTo.READ_POINTER, + offset=0, + timeout=hightime.timedelta(seconds=5.0), + waveform=wfm, + ) + + try: + panel.set_value("is_running", True) + + panel.set_value("stop_button", False) + while not panel.get_value("stop_button", False): + wfm_info = session.channels[0].fetch_array_measurement( + array_meas_function=ArrayMeasurement.ADD_CHANNELS, + num_records=1000, + meas_num_samples=1000, + ) + gain = 0 + offset = 0 + for waveform in waveforms: + gain = waveform.gain + offset = waveform.offset + panel.set_value("gain_factor", gain) + panel.set_value("offset", offset) + + for i in range(len(waveforms)): + if panel.get_value("stop_button", True): + break + else: + time.sleep(0.1) + binary_data = waveforms[i].samples.tolist() + panel.set_value("binary_data", waveforms[i].samples.tolist()) + + samples_array = np.array(binary_data) + + # Apply scaling + voltage_values = samples_array * gain + offset + panel.set_value("scaled_voltage_data", voltage_values.tolist()) + + actual_binary_data_size = session.binary_sample_width + panel.set_value("actual_binary_data_size", actual_binary_data_size) + except KeyboardInterrupt: + pass + finally: + panel.set_value("is_running", False) + +except Error as e: + daq_error = str(e) + print(daq_error) + panel.set_value("daq_error", daq_error) + +except KeyboardInterrupt: + pass diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py new file mode 100644 index 00000000..b8a8302d --- /dev/null +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py @@ -0,0 +1,188 @@ +"""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 nipanel + +st.set_page_config(page_title="NiSCOPE Binary", page_icon="📈", layout="wide") +st.title("NiScope Binary Acquisition") +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", False): + st.button("Stop", key="stop_button") + elif not panel.get_value("is_running", False) 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 niscope_binary_acquisition.py \n\n {panel.get_value('daq_error', '')}" + ) + + resource_name = st.text_input(label="Resource Name", value="Dev1") + st.number_input( + "Channel", + value=0, + step=1, + disabled=panel.get_value("is_running", False), + key="channel", + ) + + st.title("Vertical") + st.number_input( + "Vertical Range(V)", + value=5.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="vertical_range", + ) + st.number_input( + "Vertical Offset", + value=0.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="vertical_offset", + ) + st.title("Horizontal") + st.number_input( + "Min Sample Rate", + value=20000000.0, + step=1.0, + disabled=panel.get_value("is_running", False), + key="min_sample_rate", + ) + st.number_input( + "Min Record Length", + value=1000, + step=1, + disabled=panel.get_value("is_running", False), + key="min_record_length", + ) + data_size = st.selectbox( + "Binary Data Size", + options=[8, 16, 32], + disabled=panel.get_value("is_running", False), + ) + panel.set_value("data_size", data_size) + st.number_input( + "Actual Binary Data Size", + value=panel.get_value("actual_binary_data_size", 16), + step=1, + disabled=True, + key="actual_binary_data_size", + ) + st.title("Scaling Calculation") + st.number_input( + "Gain Factor", + value=panel.get_value("gain_factor", 0.0000), + step=0.0001, + disabled=True, + format="%.10f", + key="gain_factor", + ) + st.number_input( + "Offset", + value=panel.get_value("offset", 0.0000), + step=0.0001, + disabled=True, + key="offset", + ) + + +with right_col: + with st.container(border=True): + st.title("Binary Waveform Graph") + binary_data = panel.get_value("binary_data", [0]) + + binary_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Amplitude (ADC Codes)"]}, + "xAxis": { + "type": "category", + "data": list(range(len(binary_data))), + "name": "Samples", + "nameLocation": "center", + "nameGap": 40, + }, + "yAxis": { + "type": "value", + "name": "Amplitude(ADC Codes)", + "nameRotate": 90, + "nameLocation": "center", + "nameGap": 40, + }, + "series": [ + { + "name": "niscope data", + "type": "line", + "data": binary_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts(options=binary_graph, height="400px", width="75%", key="binary_graph") + with st.container(border=True): + st.title("Scaled Voltage Graph") + scaled_voltage_data = panel.get_value("scaled_voltage_data", [0]) + scaled_voltage_graph = { + "animation": False, + "tooltip": {"trigger": "axis"}, + "legend": {"data": ["Amplitude (V)"]}, + "xAxis": { + "type": "category", + "data": list(range(len(scaled_voltage_data))), + "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": scaled_voltage_data, + "emphasis": {"focus": "series"}, + "smooth": True, + "seriesLayoutBy": "row", + }, + ], + } + st_echarts( + options=scaled_voltage_graph, height="400px", width="75%", key="scaled_voltage_graph" + ) From d45e9c70d6f8d7d7812d60cb65f35e901aea63d5 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 07:59:40 -0500 Subject: [PATCH 61/76] reset run button --- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index 1883113c..b0223c5e 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -18,6 +18,7 @@ """Example fetch data from device (Dev1).""" panel.set_value("is_running", False) +panel.set_value("run_button", False) try: panel.set_value("daq_error", "") From 09be84f4f0d65f46c779622030ce7ece0a9ab638 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 13:28:07 -0500 Subject: [PATCH 62/76] moving ex fetch forever files to folder --- examples/niscope/{ => nicope_ex_fetch_forever}/README.md | 2 +- .../{ => nicope_ex_fetch_forever}/niscope_ex_fetch_forever.py | 0 .../niscope_ex_fetch_forever_panel.py | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename examples/niscope/{ => nicope_ex_fetch_forever}/README.md (89%) rename examples/niscope/{ => nicope_ex_fetch_forever}/niscope_ex_fetch_forever.py (100%) rename examples/niscope/{ => nicope_ex_fetch_forever}/niscope_ex_fetch_forever_panel.py (100%) diff --git a/examples/niscope/README.md b/examples/niscope/nicope_ex_fetch_forever/README.md similarity index 89% rename from examples/niscope/README.md rename to examples/niscope/nicope_ex_fetch_forever/README.md index 35b1e47d..88063569 100644 --- a/examples/niscope/README.md +++ b/examples/niscope/nicope_ex_fetch_forever/README.md @@ -19,5 +19,5 @@ Script demonstrates NIScope waveform data getting continuously acquired. ```pwsh poetry install --with examples -poetry run examples/niscope/niscope_ex_fetch_forever.py +poetry run examples\niscope\niscope_ex_fetch_forever\niscope_ex_fetch_forever.py ``` diff --git a/examples/niscope/niscope_ex_fetch_forever.py b/examples/niscope/nicope_ex_fetch_forever/niscope_ex_fetch_forever.py similarity index 100% rename from examples/niscope/niscope_ex_fetch_forever.py rename to examples/niscope/nicope_ex_fetch_forever/niscope_ex_fetch_forever.py diff --git a/examples/niscope/niscope_ex_fetch_forever_panel.py b/examples/niscope/nicope_ex_fetch_forever/niscope_ex_fetch_forever_panel.py similarity index 100% rename from examples/niscope/niscope_ex_fetch_forever_panel.py rename to examples/niscope/nicope_ex_fetch_forever/niscope_ex_fetch_forever_panel.py From fcd72153dfe9e33520569ee906560dc3c110cdf5 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 13:40:39 -0500 Subject: [PATCH 63/76] changes to panel --- .../niscope_binary_acquisition_panel.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py index b8a8302d..5b854d99 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py @@ -38,15 +38,15 @@ with left_col: with st.container(border=True): if panel.get_value("is_running", False): - st.button("Stop", key="stop_button") + st.button(r"âšī¸ Stop", key="stop_button") elif not panel.get_value("is_running", False) and panel.get_value("daq_error", "") == "": - run_button = st.button("Run", key="run_button") + run_button = st.button(r"â–ļī¸ Run", key="run_button") else: st.error( f"There was an error running the script. Fix the issue and re-run niscope_binary_acquisition.py \n\n {panel.get_value('daq_error', '')}" ) - resource_name = st.text_input(label="Resource Name", value="Dev1") + st.text_input(label="Resource Name", value="Dev1", key="resource_name", disabled=panel.get_value("is_running", False)) st.number_input( "Channel", value=0, @@ -89,8 +89,8 @@ "Binary Data Size", options=[8, 16, 32], disabled=panel.get_value("is_running", False), + key = "data_size" ) - panel.set_value("data_size", data_size) st.number_input( "Actual Binary Data Size", value=panel.get_value("actual_binary_data_size", 16), From 33e74a94b16aefeb5247a1d084ed3cf05243c629 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 13:58:58 -0500 Subject: [PATCH 64/76] updating branch --- .github/renovate.json | 6 + .github/renovate.json5 | 41 -- examples/all_types/all_types.py | 7 + examples/all_types/all_types_panel.py | 93 ++- examples/all_types/define_types.py | 2 + .../nidaqmx_analog_input_filtering_panel.py | 19 +- poetry.lock | 581 ++++++++++-------- src/nipanel/_convert.py | 2 + src/nipanel/converters/builtin.py | 27 +- src/nipanel/converters/protobuf_types.py | 2 +- tests/unit/test_convert.py | 26 +- tests/unit/test_streamlit_panel.py | 4 +- 12 files changed, 486 insertions(+), 324 deletions(-) create mode 100644 .github/renovate.json delete mode 100644 .github/renovate.json5 diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..aba7334b --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "local>ni/python-renovate-config:recommended" + ] +} \ No newline at end of file diff --git a/.github/renovate.json5 b/.github/renovate.json5 deleted file mode 100644 index c8f90e53..00000000 --- a/.github/renovate.json5 +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "branchPrefix": "users/renovate/", - "timezone": "US/Central", - "extends": [ - "config:recommended", - "helpers:pinGitHubActionDigestsToSemver", - ":enableVulnerabilityAlerts" - ], - "packageRules": [ - { - // Update GitHub Actions on weekends. - "matchManagers": ["github-actions"], - "groupName": "GitHub Actions", - "groupSlug": "github", - "schedule": [ - "* * * * 0,6" - ] - }, - { - // Update Python packages on weekends, separate from lockFileMaintenance. - "matchCategories": ["python"], - "matchUpdateTypes": ["major", "minor", "patch", "rollback", "replacement"], - "groupName": "Python packages", - "groupSlug": "python", - "schedule": [ - "* * * * 0,6" - ] - } - ], - "lockFileMaintenance": { - // Maintain lock files on early Tuesday mornings. This is primarily to - // update indirect dependencies that aren't handled by the Python packages - // group. - "enabled": true, - "schedule": [ - "* 0-3 * * 2" - ] - }, - "osvVulnerabilityAlerts": true -} diff --git a/examples/all_types/all_types.py b/examples/all_types/all_types.py index 3a73c743..94538c88 100644 --- a/examples/all_types/all_types.py +++ b/examples/all_types/all_types.py @@ -9,6 +9,12 @@ panel_script_path = Path(__file__).with_name("all_types_panel.py") panel = nipanel.create_streamlit_panel(panel_script_path) +panel.set_value("example_selectbox", "Option 1") +panel.set_value("example_slider", 50) +panel.set_value("example_color_picker", "#000000") +panel.set_value("example_multiselect", ["Option 1"]) +panel.set_value("example_radio", "Option 1") + print("Setting values") for name, value in all_types_with_values.items(): print(f"{name:>15} {value}") @@ -20,4 +26,5 @@ the_value = panel.get_value(name) print(f"{name:>20} {the_value}") + print(f"Panel URL: {panel.panel_url}") diff --git a/examples/all_types/all_types_panel.py b/examples/all_types/all_types_panel.py index 529d39b2..bf2a26e8 100644 --- a/examples/all_types/all_types_panel.py +++ b/examples/all_types/all_types_panel.py @@ -1,5 +1,6 @@ """A Streamlit visualization panel for the all_types.py example script.""" +import datetime as dt from enum import Enum, Flag import streamlit as st @@ -13,12 +14,97 @@ st.title("All Types Example") panel = nipanel.get_streamlit_panel_accessor() + +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.header("Control or Type") +with col2: + st.header("Input") +with col3: + st.header("Output") + +st.markdown("---") +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.write("st.selectbox") +with col2: + st.selectbox( + label="string", + options=["Option 1", "Option 2", "Option 3", "Option 4"], + key="example_selectbox", + ) +with col3: + st.write(panel.get_value("example_selectbox", "")) + +st.markdown("---") +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.write("st.slider & st.progress") +with col2: + st.slider( + label="int", + min_value=0, + max_value=100, + value=50, + key="example_slider", + ) +with col3: + progress = panel.get_value("example_slider", 50) + st.progress(progress / 100, text=f"{progress}%") + + +st.markdown("---") +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.write("st.color_picker") +with col2: + st.color_picker( + label="color", + value="#000000", + key="example_color_picker", + ) +with col3: + color = panel.get_value("example_color_picker", "#000000") + st.write(color) + st.markdown( + f"
", + unsafe_allow_html=True, + ) + +st.markdown("---") +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.write("st.multiselect") +with col2: + st.multiselect( + label="list of strings", + options=["Option A", "Option B", "Option C", "Option D"], + default=["Option A"], + key="example_multiselect", + ) +with col3: + st.write(panel.get_value("example_multiselect", ["Option A"])) + +st.markdown("---") +col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) +with col1: + st.write("st.radio") +with col2: + st.radio( + label="string", + options=["Choice 1", "Choice 2", "Choice 3"], + index=0, + key="example_radio", + ) +with col3: + st.write(panel.get_value("example_radio", "Choice 1")) + for name in all_types_with_values.keys(): st.markdown("---") default_value = all_types_with_values[name] - col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) + col1, col2, col3 = st.columns([0.2, 0.2, 0.6]) with col1: st.write(name) @@ -35,6 +121,11 @@ st.number_input(label=name, value=default_value, key=name, format="%.2f") elif isinstance(default_value, str): st.text_input(label=name, value=default_value, key=name) + elif isinstance(default_value, dt.datetime): + date = st.date_input(label="date", value=default_value) + time = st.time_input(label="time", value=default_value) + datetime = dt.datetime.combine(date, time) + panel.set_value(name, datetime) with col3: st.write(panel.get_value(name, default_value=default_value)) diff --git a/examples/all_types/define_types.py b/examples/all_types/define_types.py index 33c8c47c..937abc4d 100644 --- a/examples/all_types/define_types.py +++ b/examples/all_types/define_types.py @@ -1,5 +1,6 @@ """Define types.""" +import datetime as dt import enum import numpy as np @@ -70,6 +71,7 @@ class MyMixedEnum(enum.Enum): "float": 13.12, "int": 42, "str": "sample string", + "dt_datetime": dt.datetime.now(), # supported enum and flag types "intflags": MyIntFlags.VALUE1 | MyIntFlags.VALUE4, "intenum": MyIntEnum.VALUE20, 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 fb169372..0828b022 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 @@ -57,13 +57,13 @@ 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( + st.selectbox( options=panel.get_value("available_channel_names", ["Mod2/ai0"]), index=0, label="Physical Channels", disabled=panel.get_value("is_running", False), + key="physical_channel", ) - panel.set_value("physical_channel", physical_channel) enum_selectbox( panel, label="Terminal Configuration", @@ -74,13 +74,13 @@ st.title("Timing Settings") - source = st.selectbox( + st.selectbox( "Sample Clock Source", options=panel.get_value("available_trigger_sources", [""]), index=0, disabled=panel.get_value("is_running", False), + key="source", ) - panel.set_value("source", source) st.number_input( "Sample Rate", value=1000.0, @@ -106,12 +106,12 @@ ) st.title("Filtering Settings") - filter = st.selectbox( + st.selectbox( "Filter", options=["No Filtering", "Filter"], disabled=panel.get_value("is_running", False), + key="filter", ) - panel.set_value("filter", filter) enum_selectbox( panel, label="Filter Response", @@ -203,10 +203,11 @@ ) if trigger_type == "2": with st.container(border=True): - source = st.selectbox( - "Source", options=panel.get_value("available_trigger_sources", [""]) + st.selectbox( + "Source", + options=panel.get_value("available_trigger_sources", [""]), + key="digital_source", ) - panel.set_value("digital_source", source) enum_selectbox( panel, label="Edge", diff --git a/poetry.lock b/poetry.lock index d022094a..92d4561c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -37,13 +37,13 @@ save = ["vl-convert-python (>=1.7.0)"] [[package]] name = "astroid" -version = "3.3.10" +version = "3.3.11" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.9.0" files = [ - {file = "astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb"}, - {file = "astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce"}, + {file = "astroid-3.3.11-py3-none-any.whl", hash = "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec"}, + {file = "astroid-3.3.11.tar.gz", hash = "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce"}, ] [package.dependencies] @@ -177,13 +177,13 @@ files = [ [[package]] name = "certifi" -version = "2025.6.15" +version = "2025.7.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"}, - {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"}, + {file = "certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2"}, + {file = "certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995"}, ] [[package]] @@ -334,78 +334,99 @@ files = [ [[package]] name = "coverage" -version = "7.9.2" +version = "7.10.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912"}, - {file = "coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f"}, - {file = "coverage-7.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f22627c1fe2745ee98d3ab87679ca73a97e75ca75eb5faee48660d060875465f"}, - {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b1c2d8363247b46bd51f393f86c94096e64a1cf6906803fa8d5a9d03784bdbf"}, - {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10c882b114faf82dbd33e876d0cbd5e1d1ebc0d2a74ceef642c6152f3f4d547"}, - {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de3c0378bdf7066c3988d66cd5232d161e933b87103b014ab1b0b4676098fa45"}, - {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1e2f097eae0e5991e7623958a24ced3282676c93c013dde41399ff63e230fcf2"}, - {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28dc1f67e83a14e7079b6cea4d314bc8b24d1aed42d3582ff89c0295f09b181e"}, - {file = "coverage-7.9.2-cp310-cp310-win32.whl", hash = "sha256:bf7d773da6af9e10dbddacbf4e5cab13d06d0ed93561d44dae0188a42c65be7e"}, - {file = "coverage-7.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:0c0378ba787681ab1897f7c89b415bd56b0b2d9a47e5a3d8dc0ea55aac118d6c"}, - {file = "coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba"}, - {file = "coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa"}, - {file = "coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a"}, - {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc"}, - {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2"}, - {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c"}, - {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd"}, - {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74"}, - {file = "coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6"}, - {file = "coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7"}, - {file = "coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62"}, - {file = "coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0"}, - {file = "coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3"}, - {file = "coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1"}, - {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615"}, - {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b"}, - {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9"}, - {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f"}, - {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d"}, - {file = "coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355"}, - {file = "coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0"}, - {file = "coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b"}, - {file = "coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038"}, - {file = "coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d"}, - {file = "coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3"}, - {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14"}, - {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6"}, - {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b"}, - {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d"}, - {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868"}, - {file = "coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a"}, - {file = "coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b"}, - {file = "coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694"}, - {file = "coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5"}, - {file = "coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b"}, - {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3"}, - {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8"}, - {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46"}, - {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584"}, - {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e"}, - {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac"}, - {file = "coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926"}, - {file = "coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd"}, - {file = "coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb"}, - {file = "coverage-7.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddc39510ac922a5c4c27849b739f875d3e1d9e590d1e7b64c98dadf037a16cce"}, - {file = "coverage-7.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a535c0c7364acd55229749c2b3e5eebf141865de3a8f697076a3291985f02d30"}, - {file = "coverage-7.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df0f9ef28e0f20c767ccdccfc5ae5f83a6f4a2fbdfbcbcc8487a8a78771168c8"}, - {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f3da12e0ccbcb348969221d29441ac714bbddc4d74e13923d3d5a7a0bebef7a"}, - {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a17eaf46f56ae0f870f14a3cbc2e4632fe3771eab7f687eda1ee59b73d09fe4"}, - {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:669135a9d25df55d1ed56a11bf555f37c922cf08d80799d4f65d77d7d6123fcf"}, - {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d3a700304d01a627df9db4322dc082a0ce1e8fc74ac238e2af39ced4c083193"}, - {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:71ae8b53855644a0b1579d4041304ddc9995c7b21c8a1f16753c4d8903b4dfed"}, - {file = "coverage-7.9.2-cp39-cp39-win32.whl", hash = "sha256:dd7a57b33b5cf27acb491e890720af45db05589a80c1ffc798462a765be6d4d7"}, - {file = "coverage-7.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f65bb452e579d5540c8b37ec105dd54d8b9307b07bcaa186818c104ffda22441"}, - {file = "coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050"}, - {file = "coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4"}, - {file = "coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b"}, + {file = "coverage-7.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1c86eb388bbd609d15560e7cc0eb936c102b6f43f31cf3e58b4fd9afe28e1372"}, + {file = "coverage-7.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b4ba0f488c1bdb6bd9ba81da50715a372119785458831c73428a8566253b86b"}, + {file = "coverage-7.10.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:083442ecf97d434f0cb3b3e3676584443182653da08b42e965326ba12d6b5f2a"}, + {file = "coverage-7.10.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c1a40c486041006b135759f59189385da7c66d239bad897c994e18fd1d0c128f"}, + {file = "coverage-7.10.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3beb76e20b28046989300c4ea81bf690df84ee98ade4dc0bbbf774a28eb98440"}, + {file = "coverage-7.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bc265a7945e8d08da28999ad02b544963f813a00f3ed0a7a0ce4165fd77629f8"}, + {file = "coverage-7.10.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:47c91f32ba4ac46f1e224a7ebf3f98b4b24335bad16137737fe71a5961a0665c"}, + {file = "coverage-7.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1a108dd78ed185020f66f131c60078f3fae3f61646c28c8bb4edd3fa121fc7fc"}, + {file = "coverage-7.10.1-cp310-cp310-win32.whl", hash = "sha256:7092cc82382e634075cc0255b0b69cb7cada7c1f249070ace6a95cb0f13548ef"}, + {file = "coverage-7.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:ac0c5bba938879c2fc0bc6c1b47311b5ad1212a9dcb8b40fe2c8110239b7faed"}, + {file = "coverage-7.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45e2f9d5b0b5c1977cb4feb5f594be60eb121106f8900348e29331f553a726f"}, + {file = "coverage-7.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a7a4d74cb0f5e3334f9aa26af7016ddb94fb4bfa11b4a573d8e98ecba8c34f1"}, + {file = "coverage-7.10.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d4b0aab55ad60ead26159ff12b538c85fbab731a5e3411c642b46c3525863437"}, + {file = "coverage-7.10.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dcc93488c9ebd229be6ee1f0d9aad90da97b33ad7e2912f5495804d78a3cd6b7"}, + {file = "coverage-7.10.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa309df995d020f3438407081b51ff527171cca6772b33cf8f85344b8b4b8770"}, + {file = "coverage-7.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfb8b9d8855c8608f9747602a48ab525b1d320ecf0113994f6df23160af68262"}, + {file = "coverage-7.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:320d86da829b012982b414c7cdda65f5d358d63f764e0e4e54b33097646f39a3"}, + {file = "coverage-7.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dc60ddd483c556590da1d9482a4518292eec36dd0e1e8496966759a1f282bcd0"}, + {file = "coverage-7.10.1-cp311-cp311-win32.whl", hash = "sha256:4fcfe294f95b44e4754da5b58be750396f2b1caca8f9a0e78588e3ef85f8b8be"}, + {file = "coverage-7.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:efa23166da3fe2915f8ab452dde40319ac84dc357f635737174a08dbd912980c"}, + {file = "coverage-7.10.1-cp311-cp311-win_arm64.whl", hash = "sha256:d12b15a8c3759e2bb580ffa423ae54be4f184cf23beffcbd641f4fe6e1584293"}, + {file = "coverage-7.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6b7dc7f0a75a7eaa4584e5843c873c561b12602439d2351ee28c7478186c4da4"}, + {file = "coverage-7.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:607f82389f0ecafc565813aa201a5cade04f897603750028dd660fb01797265e"}, + {file = "coverage-7.10.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f7da31a1ba31f1c1d4d5044b7c5813878adae1f3af8f4052d679cc493c7328f4"}, + {file = "coverage-7.10.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51fe93f3fe4f5d8483d51072fddc65e717a175490804e1942c975a68e04bf97a"}, + {file = "coverage-7.10.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e59d00830da411a1feef6ac828b90bbf74c9b6a8e87b8ca37964925bba76dbe"}, + {file = "coverage-7.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:924563481c27941229cb4e16eefacc35da28563e80791b3ddc5597b062a5c386"}, + {file = "coverage-7.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ca79146ee421b259f8131f153102220b84d1a5e6fb9c8aed13b3badfd1796de6"}, + {file = "coverage-7.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2b225a06d227f23f386fdc0eab471506d9e644be699424814acc7d114595495f"}, + {file = "coverage-7.10.1-cp312-cp312-win32.whl", hash = "sha256:5ba9a8770effec5baaaab1567be916c87d8eea0c9ad11253722d86874d885eca"}, + {file = "coverage-7.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:9eb245a8d8dd0ad73b4062135a251ec55086fbc2c42e0eb9725a9b553fba18a3"}, + {file = "coverage-7.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:7718060dd4434cc719803a5e526838a5d66e4efa5dc46d2b25c21965a9c6fcc4"}, + {file = "coverage-7.10.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ebb08d0867c5a25dffa4823377292a0ffd7aaafb218b5d4e2e106378b1061e39"}, + {file = "coverage-7.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f32a95a83c2e17422f67af922a89422cd24c6fa94041f083dd0bb4f6057d0bc7"}, + {file = "coverage-7.10.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c4c746d11c8aba4b9f58ca8bfc6fbfd0da4efe7960ae5540d1a1b13655ee8892"}, + {file = "coverage-7.10.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7f39edd52c23e5c7ed94e0e4bf088928029edf86ef10b95413e5ea670c5e92d7"}, + {file = "coverage-7.10.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab6e19b684981d0cd968906e293d5628e89faacb27977c92f3600b201926b994"}, + {file = "coverage-7.10.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5121d8cf0eacb16133501455d216bb5f99899ae2f52d394fe45d59229e6611d0"}, + {file = "coverage-7.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:df1c742ca6f46a6f6cbcaef9ac694dc2cb1260d30a6a2f5c68c5f5bcfee1cfd7"}, + {file = "coverage-7.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:40f9a38676f9c073bf4b9194707aa1eb97dca0e22cc3766d83879d72500132c7"}, + {file = "coverage-7.10.1-cp313-cp313-win32.whl", hash = "sha256:2348631f049e884839553b9974f0821d39241c6ffb01a418efce434f7eba0fe7"}, + {file = "coverage-7.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:4072b31361b0d6d23f750c524f694e1a417c1220a30d3ef02741eed28520c48e"}, + {file = "coverage-7.10.1-cp313-cp313-win_arm64.whl", hash = "sha256:3e31dfb8271937cab9425f19259b1b1d1f556790e98eb266009e7a61d337b6d4"}, + {file = "coverage-7.10.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1c4f679c6b573a5257af6012f167a45be4c749c9925fd44d5178fd641ad8bf72"}, + {file = "coverage-7.10.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:871ebe8143da284bd77b84a9136200bd638be253618765d21a1fce71006d94af"}, + {file = "coverage-7.10.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:998c4751dabf7d29b30594af416e4bf5091f11f92a8d88eb1512c7ba136d1ed7"}, + {file = "coverage-7.10.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:780f750a25e7749d0af6b3631759c2c14f45de209f3faaa2398312d1c7a22759"}, + {file = "coverage-7.10.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:590bdba9445df4763bdbebc928d8182f094c1f3947a8dc0fc82ef014dbdd8324"}, + {file = "coverage-7.10.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b2df80cb6a2af86d300e70acb82e9b79dab2c1e6971e44b78dbfc1a1e736b53"}, + {file = "coverage-7.10.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d6a558c2725bfb6337bf57c1cd366c13798bfd3bfc9e3dd1f4a6f6fc95a4605f"}, + {file = "coverage-7.10.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e6150d167f32f2a54690e572e0a4c90296fb000a18e9b26ab81a6489e24e78dd"}, + {file = "coverage-7.10.1-cp313-cp313t-win32.whl", hash = "sha256:d946a0c067aa88be4a593aad1236493313bafaa27e2a2080bfe88db827972f3c"}, + {file = "coverage-7.10.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e37c72eaccdd5ed1130c67a92ad38f5b2af66eeff7b0abe29534225db2ef7b18"}, + {file = "coverage-7.10.1-cp313-cp313t-win_arm64.whl", hash = "sha256:89ec0ffc215c590c732918c95cd02b55c7d0f569d76b90bb1a5e78aa340618e4"}, + {file = "coverage-7.10.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:166d89c57e877e93d8827dac32cedae6b0277ca684c6511497311249f35a280c"}, + {file = "coverage-7.10.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bed4a2341b33cd1a7d9ffc47df4a78ee61d3416d43b4adc9e18b7d266650b83e"}, + {file = "coverage-7.10.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ddca1e4f5f4c67980533df01430184c19b5359900e080248bbf4ed6789584d8b"}, + {file = "coverage-7.10.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:37b69226001d8b7de7126cad7366b0778d36777e4d788c66991455ba817c5b41"}, + {file = "coverage-7.10.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2f22102197bcb1722691296f9e589f02b616f874e54a209284dd7b9294b0b7f"}, + {file = "coverage-7.10.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1e0c768b0f9ac5839dac5cf88992a4bb459e488ee8a1f8489af4cb33b1af00f1"}, + {file = "coverage-7.10.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:991196702d5e0b120a8fef2664e1b9c333a81d36d5f6bcf6b225c0cf8b0451a2"}, + {file = "coverage-7.10.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae8e59e5f4fd85d6ad34c2bb9d74037b5b11be072b8b7e9986beb11f957573d4"}, + {file = "coverage-7.10.1-cp314-cp314-win32.whl", hash = "sha256:042125c89cf74a074984002e165d61fe0e31c7bd40ebb4bbebf07939b5924613"}, + {file = "coverage-7.10.1-cp314-cp314-win_amd64.whl", hash = "sha256:a22c3bfe09f7a530e2c94c87ff7af867259c91bef87ed2089cd69b783af7b84e"}, + {file = "coverage-7.10.1-cp314-cp314-win_arm64.whl", hash = "sha256:ee6be07af68d9c4fca4027c70cea0c31a0f1bc9cb464ff3c84a1f916bf82e652"}, + {file = "coverage-7.10.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d24fb3c0c8ff0d517c5ca5de7cf3994a4cd559cde0315201511dbfa7ab528894"}, + {file = "coverage-7.10.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1217a54cfd79be20512a67ca81c7da3f2163f51bbfd188aab91054df012154f5"}, + {file = "coverage-7.10.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:51f30da7a52c009667e02f125737229d7d8044ad84b79db454308033a7808ab2"}, + {file = "coverage-7.10.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ed3718c757c82d920f1c94089066225ca2ad7f00bb904cb72b1c39ebdd906ccb"}, + {file = "coverage-7.10.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc452481e124a819ced0c25412ea2e144269ef2f2534b862d9f6a9dae4bda17b"}, + {file = "coverage-7.10.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9d6f494c307e5cb9b1e052ec1a471060f1dea092c8116e642e7a23e79d9388ea"}, + {file = "coverage-7.10.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fc0e46d86905ddd16b85991f1f4919028092b4e511689bbdaff0876bd8aab3dd"}, + {file = "coverage-7.10.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80b9ccd82e30038b61fc9a692a8dc4801504689651b281ed9109f10cc9fe8b4d"}, + {file = "coverage-7.10.1-cp314-cp314t-win32.whl", hash = "sha256:e58991a2b213417285ec866d3cd32db17a6a88061a985dbb7e8e8f13af429c47"}, + {file = "coverage-7.10.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e88dd71e4ecbc49d9d57d064117462c43f40a21a1383507811cf834a4a620651"}, + {file = "coverage-7.10.1-cp314-cp314t-win_arm64.whl", hash = "sha256:1aadfb06a30c62c2eb82322171fe1f7c288c80ca4156d46af0ca039052814bab"}, + {file = "coverage-7.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:57b6e8789cbefdef0667e4a94f8ffa40f9402cee5fc3b8e4274c894737890145"}, + {file = "coverage-7.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:85b22a9cce00cb03156334da67eb86e29f22b5e93876d0dd6a98646bb8a74e53"}, + {file = "coverage-7.10.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:97b6983a2f9c76d345ca395e843a049390b39652984e4a3b45b2442fa733992d"}, + {file = "coverage-7.10.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ddf2a63b91399a1c2f88f40bc1705d5a7777e31c7e9eb27c602280f477b582ba"}, + {file = "coverage-7.10.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47ab6dbbc31a14c5486420c2c1077fcae692097f673cf5be9ddbec8cdaa4cdbc"}, + {file = "coverage-7.10.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:21eb7d8b45d3700e7c2936a736f732794c47615a20f739f4133d5230a6512a88"}, + {file = "coverage-7.10.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:283005bb4d98ae33e45f2861cd2cde6a21878661c9ad49697f6951b358a0379b"}, + {file = "coverage-7.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:fefe31d61d02a8b2c419700b1fade9784a43d726de26495f243b663cd9fe1513"}, + {file = "coverage-7.10.1-cp39-cp39-win32.whl", hash = "sha256:e8ab8e4c7ec7f8a55ac05b5b715a051d74eac62511c6d96d5bb79aaafa3b04cf"}, + {file = "coverage-7.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:c36baa0ecde742784aa76c2b816466d3ea888d5297fda0edbac1bf48fa94688a"}, + {file = "coverage-7.10.1-py3-none-any.whl", hash = "sha256:fa2a258aa6bf188eb9a8948f7102a83da7c430a0dce918dbd8b60ef8fcb772d7"}, + {file = "coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57"}, ] [package.dependencies] @@ -613,17 +634,18 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.44" +version = "3.1.45" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, + {file = "gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"}, + {file = "gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" +typing-extensions = {version = ">=3.10.0.2", markers = "python_version < \"3.10\""} [package.extras] doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] @@ -890,13 +912,13 @@ setuptools = "*" [[package]] name = "hightime" -version = "0.3.0.dev0" +version = "0.3.0.dev1" description = "Hightime Python API" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "hightime-0.3.0.dev0-py3-none-any.whl", hash = "sha256:777dd17ce9a6da40b650565992bf05f7016888076e1465740eae192a056ab292"}, - {file = "hightime-0.3.0.dev0.tar.gz", hash = "sha256:a89308b5effa746995de29182eb6bb8bdb0293c39b3d99bb46b05a38615c2104"}, + {file = "hightime-0.3.0.dev1-py3-none-any.whl", hash = "sha256:33b05864264655929f6ecaade8a1f27070f1e3a2028e304e051825cbe6a505c9"}, + {file = "hightime-0.3.0.dev1.tar.gz", hash = "sha256:e1ad569c034b61be5b906a5dc4b226af6b6fe4985f2550edc8b575a4df5fdaf0"}, ] [[package]] @@ -969,13 +991,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.24.0" +version = "4.25.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" files = [ - {file = "jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d"}, - {file = "jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196"}, + {file = "jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716"}, + {file = "jsonschema-4.25.0.tar.gz", hash = "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f"}, ] [package.dependencies] @@ -986,7 +1008,7 @@ rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] name = "jsonschema-specifications" @@ -1165,43 +1187,49 @@ files = [ [[package]] name = "mypy" -version = "1.17.0" +version = "1.17.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" files = [ - {file = "mypy-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8e08de6138043108b3b18f09d3f817a4783912e48828ab397ecf183135d84d6"}, - {file = "mypy-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce4a17920ec144647d448fc43725b5873548b1aae6c603225626747ededf582d"}, - {file = "mypy-1.17.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ff25d151cc057fdddb1cb1881ef36e9c41fa2a5e78d8dd71bee6e4dcd2bc05b"}, - {file = "mypy-1.17.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93468cf29aa9a132bceb103bd8475f78cacde2b1b9a94fd978d50d4bdf616c9a"}, - {file = "mypy-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:98189382b310f16343151f65dd7e6867386d3e35f7878c45cfa11383d175d91f"}, - {file = "mypy-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:c004135a300ab06a045c1c0d8e3f10215e71d7b4f5bb9a42ab80236364429937"}, - {file = "mypy-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be"}, - {file = "mypy-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61"}, - {file = "mypy-1.17.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f"}, - {file = "mypy-1.17.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d"}, - {file = "mypy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3"}, - {file = "mypy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70"}, - {file = "mypy-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb"}, - {file = "mypy-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d"}, - {file = "mypy-1.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8"}, - {file = "mypy-1.17.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e"}, - {file = "mypy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8"}, - {file = "mypy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d"}, - {file = "mypy-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06"}, - {file = "mypy-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a"}, - {file = "mypy-1.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889"}, - {file = "mypy-1.17.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba"}, - {file = "mypy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658"}, - {file = "mypy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c"}, - {file = "mypy-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:63e751f1b5ab51d6f3d219fe3a2fe4523eaa387d854ad06906c63883fde5b1ab"}, - {file = "mypy-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fb09d05e0f1c329a36dcd30e27564a3555717cde87301fae4fb542402ddfad"}, - {file = "mypy-1.17.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b72c34ce05ac3a1361ae2ebb50757fb6e3624032d91488d93544e9f82db0ed6c"}, - {file = "mypy-1.17.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:434ad499ad8dde8b2f6391ddfa982f41cb07ccda8e3c67781b1bfd4e5f9450a8"}, - {file = "mypy-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f105f61a5eff52e137fd73bee32958b2add9d9f0a856f17314018646af838e97"}, - {file = "mypy-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:ba06254a5a22729853209550d80f94e28690d5530c661f9416a68ac097b13fc4"}, - {file = "mypy-1.17.0-py3-none-any.whl", hash = "sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496"}, - {file = "mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03"}, + {file = "mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972"}, + {file = "mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7"}, + {file = "mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df"}, + {file = "mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390"}, + {file = "mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94"}, + {file = "mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b"}, + {file = "mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58"}, + {file = "mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5"}, + {file = "mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd"}, + {file = "mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b"}, + {file = "mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5"}, + {file = "mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b"}, + {file = "mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb"}, + {file = "mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403"}, + {file = "mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056"}, + {file = "mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341"}, + {file = "mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb"}, + {file = "mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19"}, + {file = "mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7"}, + {file = "mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81"}, + {file = "mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6"}, + {file = "mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849"}, + {file = "mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14"}, + {file = "mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a"}, + {file = "mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733"}, + {file = "mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd"}, + {file = "mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0"}, + {file = "mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a"}, + {file = "mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91"}, + {file = "mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed"}, + {file = "mypy-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9"}, + {file = "mypy-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99"}, + {file = "mypy-1.17.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8"}, + {file = "mypy-1.17.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8"}, + {file = "mypy-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259"}, + {file = "mypy-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d"}, + {file = "mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9"}, + {file = "mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01"}, ] [package.dependencies] @@ -1245,13 +1273,13 @@ types-protobuf = ">=4.24" [[package]] name = "narwhals" -version = "1.46.0" +version = "2.0.1" description = "Extremely lightweight compatibility layer between dataframe libraries" optional = false python-versions = ">=3.9" files = [ - {file = "narwhals-1.46.0-py3-none-any.whl", hash = "sha256:f15d2255695d7e99f624f76aa5b765eb3fff8a509d3215049707af3a3feebc90"}, - {file = "narwhals-1.46.0.tar.gz", hash = "sha256:fd7e53860b233c2b5566d8b4e1b3e8e9c01b5a87649a9f9a322742000f207a60"}, + {file = "narwhals-2.0.1-py3-none-any.whl", hash = "sha256:837457e36a2ba1710c881fb69e1f79ce44fb81728c92ac378f70892a53af8ddb"}, + {file = "narwhals-2.0.1.tar.gz", hash = "sha256:235e61ca807bc21110ca36a4d53888ecc22c42dcdf50a7c886e10dde3fd7f38c"}, ] [package.extras] @@ -1262,7 +1290,7 @@ ibis = ["ibis-framework (>=6.0.0)", "packaging", "pyarrow-hotfix", "rich"] modin = ["modin"] pandas = ["pandas (>=1.1.3)"] polars = ["polars (>=0.20.4)"] -pyarrow = ["pyarrow (>=11.0.0)"] +pyarrow = ["pyarrow (>=13.0.0)"] pyspark = ["pyspark (>=3.5.0)"] pyspark-connect = ["pyspark[connect] (>=3.5.0)"] sqlframe = ["sqlframe (>=3.22.0)"] @@ -1363,23 +1391,26 @@ toml = ">=0.10.1" [[package]] name = "nidaqmx" -version = "1.2.0.dev1" +version = "1.2.0" description = "NI-DAQmx Python API" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "nidaqmx-1.2.0.dev1-py3-none-any.whl", hash = "sha256:4141f844a4b6b9f5f979e3b6437c87899319b1a2dc6acaa938489ffa31d05bd6"}, - {file = "nidaqmx-1.2.0.dev1.tar.gz", hash = "sha256:9241a429c41f35d40ad02d099e3063b377bc62f377fcd0444ab1933800a5fb29"}, + {file = "nidaqmx-1.2.0-py3-none-any.whl", hash = "sha256:c2b8d6d39556a7920d966bf4aff6f5229e8df3bdf3b49c24dc68a2d42dfd5d30"}, + {file = "nidaqmx-1.2.0.tar.gz", hash = "sha256:faeea9889a2dae03b7e23f525a44889264a5cfbf5590558e3792c28871620c87"}, ] [package.dependencies] -click = ">=8.0.0" +click = [ + {version = ">=8.0.0,<8.2.0", markers = "python_version == \"3.9\""}, + {version = ">=8.0.0", markers = "python_version >= \"3.10\" and python_version < \"4.0\""}, +] deprecation = ">=2.1" distro = {version = ">=1.9.0", markers = "sys_platform == \"linux\""} hightime = ">=0.2.2" numpy = [ {version = ">=1.22", markers = "python_version >= \"3.9\" and python_version < \"3.12\""}, - {version = ">=1.26", markers = "python_version >= \"3.12\" and python_version < \"3.13\""}, + {version = ">=1.26", markers = "python_version == \"3.12\""}, {version = ">=2.1", markers = "python_version >= \"3.13\" and python_version < \"4.0\""}, ] python-decouple = ">=3.8" @@ -1423,13 +1454,13 @@ hightime = ">=0.2.0" [[package]] name = "nitypes" -version = "0.1.0.dev5" +version = "0.1.0.dev6" description = "Data types for NI Python APIs" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "nitypes-0.1.0.dev5-py3-none-any.whl", hash = "sha256:4f0e7ce6332b0911c3bd38083993ff2fb5a7cacf2a7c08397782e11fc106c50f"}, - {file = "nitypes-0.1.0.dev5.tar.gz", hash = "sha256:cf5adce1acc0f74ce7f3d6e7d3aadecfd93b53ea6795850444e356adf3765004"}, + {file = "nitypes-0.1.0.dev6-py3-none-any.whl", hash = "sha256:44ecc849d4a26137919a5406cbb103281d965102d0061682a939d58668de44ea"}, + {file = "nitypes-0.1.0.dev6.tar.gz", hash = "sha256:37ae3494ecaa98d866ebe3c27898c21961c4f47082cfb7a921dc842debd74526"}, ] [package.dependencies] @@ -1455,20 +1486,20 @@ files = [ [[package]] name = "nodejs-wheel-binaries" -version = "22.17.0" +version = "22.17.1" description = "unoffical Node.js package" optional = false python-versions = ">=3.7" files = [ - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:6545a6f6d2f736d9c9e2eaad7e599b6b5b2d8fd4cbd2a1df0807cbcf51b9d39b"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:4bea5b994dd87c20f8260031ea69a97c3d282e2d4472cc8908636a313a830d00"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:885508615274a22499dd5314759c1cf96ba72de03e6485d73b3e5475e7f12662"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90f38ce034a602bcab534d55cbe0390521e73e5dcffdd1c4b34354b932172af2"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5eed087855b644c87001fe04036213193963ccd65e7f89949e9dbe28e7743d9b"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:715f413c81500f0770ea8936ef1fc2529b900da8054cbf6da67cec3ee308dc76"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-win_amd64.whl", hash = "sha256:51165630493c8dd4acfe1cae1684b76940c9b03f7f355597d55e2d056a572ddd"}, - {file = "nodejs_wheel_binaries-22.17.0-py2.py3-none-win_arm64.whl", hash = "sha256:fae56d172227671fccb04461d3cd2b26a945c6c7c7fc29edb8618876a39d8b4a"}, - {file = "nodejs_wheel_binaries-22.17.0.tar.gz", hash = "sha256:529142012fb8fd20817ef70e2ef456274df4f49933292e312c8bbc7285af6408"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:1f4d208c0c087a2909b6e9e6e0735da083dc997aa74e9b302703b0798b2faa4c"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:457ada98c6e3e03c7fd3f7d6a55572b70af7155c8dd908246373c63697226db6"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79a87aeb2f1dfc3d36cd595921f7671a7342467f8b224b56e9049771e5ec20b"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05c4eafec348e439d069cd5a114f893c5f7ea898752e34a8aa43aacd39fcf9a3"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fc9690ed95b186ef4bb8dd316e83878d016a0b6072454f8f68fa843c1016f85b"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8200379c4c5ec957230285d2e7844f94de87ec0e8316b72b7a5f923cf19e88f2"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-win_amd64.whl", hash = "sha256:dadc1cf0d5dfacb4dbf2f339d8c070c58e48b37328a44f845de1d27fbbf2381f"}, + {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-win_arm64.whl", hash = "sha256:fde8e767272620c58cb882df104462d8f62859223dbf9ab50678d9f0c09dbbf5"}, + {file = "nodejs_wheel_binaries-22.17.1.tar.gz", hash = "sha256:0a8bf2a9d319988b8fa8b8b7bb5a7d986527672e6d6352735714f768af9828d0"}, ] [[package]] @@ -1591,62 +1622,85 @@ files = [ [[package]] name = "numpy" -version = "2.3.1" +version = "2.3.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" files = [ - {file = "numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070"}, - {file = "numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae"}, - {file = "numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a"}, - {file = "numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e"}, - {file = "numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db"}, - {file = "numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb"}, - {file = "numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93"}, - {file = "numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115"}, - {file = "numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369"}, - {file = "numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff"}, - {file = "numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a"}, - {file = "numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d"}, - {file = "numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29"}, - {file = "numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc"}, - {file = "numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943"}, - {file = "numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25"}, - {file = "numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660"}, - {file = "numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952"}, - {file = "numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77"}, - {file = "numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab"}, - {file = "numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76"}, - {file = "numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30"}, - {file = "numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8"}, - {file = "numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e"}, - {file = "numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0"}, - {file = "numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d"}, - {file = "numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1"}, - {file = "numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1"}, - {file = "numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0"}, - {file = "numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8"}, - {file = "numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8"}, - {file = "numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42"}, - {file = "numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e"}, - {file = "numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8"}, - {file = "numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb"}, - {file = "numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee"}, - {file = "numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992"}, - {file = "numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c"}, - {file = "numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48"}, - {file = "numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee"}, - {file = "numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280"}, - {file = "numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e"}, - {file = "numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc"}, - {file = "numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68"}, - {file = "numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb"}, - {file = "numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097"}, + {file = "numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220"}, + {file = "numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170"}, + {file = "numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be"}, + {file = "numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036"}, + {file = "numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f"}, + {file = "numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6"}, + {file = "numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b"}, + {file = "numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56"}, + {file = "numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5"}, + {file = "numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5"}, + {file = "numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450"}, + {file = "numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0"}, + {file = "numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2"}, + {file = "numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b"}, + {file = "numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf"}, + {file = "numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1"}, + {file = "numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b"}, + {file = "numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619"}, + {file = "numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48"}, ] [[package]] @@ -1999,66 +2053,54 @@ files = [ [[package]] name = "pyarrow" -version = "20.0.0" +version = "21.0.0" description = "Python library for Apache Arrow" optional = false python-versions = ">=3.9" files = [ - {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7"}, - {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4"}, - {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae"}, - {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee"}, - {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20"}, - {file = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9"}, - {file = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75"}, - {file = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8"}, - {file = "pyarrow-20.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191"}, - {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0"}, - {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62"}, - {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c"}, - {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3"}, - {file = "pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc"}, - {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba"}, - {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8"}, - {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e"}, - {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a"}, - {file = "pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b"}, - {file = "pyarrow-20.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:a15532e77b94c61efadde86d10957950392999503b3616b2ffcef7621a002893"}, - {file = "pyarrow-20.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:dd43f58037443af715f34f1322c782ec463a3c8a94a85fdb2d987ceb5658e061"}, - {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0d288143a8585806e3cc7c39566407aab646fb9ece164609dac1cfff45f6ae"}, - {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6953f0114f8d6f3d905d98e987d0924dabce59c3cda380bdfaa25a6201563b4"}, - {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:991f85b48a8a5e839b2128590ce07611fae48a904cae6cab1f089c5955b57eb5"}, - {file = "pyarrow-20.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:97c8dc984ed09cb07d618d57d8d4b67a5100a30c3818c2fb0b04599f0da2de7b"}, - {file = "pyarrow-20.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9b71daf534f4745818f96c214dbc1e6124d7daf059167330b610fc69b6f3d3e3"}, - {file = "pyarrow-20.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8b88758f9303fa5a83d6c90e176714b2fd3852e776fc2d7e42a22dd6c2fb368"}, - {file = "pyarrow-20.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:30b3051b7975801c1e1d387e17c588d8ab05ced9b1e14eec57915f79869b5031"}, - {file = "pyarrow-20.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ca151afa4f9b7bc45bcc791eb9a89e90a9eb2772767d0b1e5389609c7d03db63"}, - {file = "pyarrow-20.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:4680f01ecd86e0dd63e39eb5cd59ef9ff24a9d166db328679e36c108dc993d4c"}, - {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f4c8534e2ff059765647aa69b75d6543f9fef59e2cd4c6d18015192565d2b70"}, - {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e1f8a47f4b4ae4c69c4d702cfbdfe4d41e18e5c7ef6f1bb1c50918c1e81c57b"}, - {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a1f60dc14658efaa927f8214734f6a01a806d7690be4b3232ba526836d216122"}, - {file = "pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:204a846dca751428991346976b914d6d2a82ae5b8316a6ed99789ebf976551e6"}, - {file = "pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f3b117b922af5e4c6b9a9115825726cac7d8b1421c37c2b5e24fbacc8930612c"}, - {file = "pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e724a3fd23ae5b9c010e7be857f4405ed5e679db5c93e66204db1a69f733936a"}, - {file = "pyarrow-20.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:82f1ee5133bd8f49d31be1299dc07f585136679666b502540db854968576faf9"}, - {file = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:1bcbe471ef3349be7714261dea28fe280db574f9d0f77eeccc195a2d161fd861"}, - {file = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:a18a14baef7d7ae49247e75641fd8bcbb39f44ed49a9fc4ec2f65d5031aa3b96"}, - {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb497649e505dc36542d0e68eca1a3c94ecbe9799cb67b578b55f2441a247fbc"}, - {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11529a2283cb1f6271d7c23e4a8f9f8b7fd173f7360776b668e509d712a02eec"}, - {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fc1499ed3b4b57ee4e090e1cea6eb3584793fe3d1b4297bbf53f09b434991a5"}, - {file = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:db53390eaf8a4dab4dbd6d93c85c5cf002db24902dbff0ca7d988beb5c9dd15b"}, - {file = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:851c6a8260ad387caf82d2bbf54759130534723e37083111d4ed481cb253cc0d"}, - {file = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e22f80b97a271f0a7d9cd07394a7d348f80d3ac63ed7cc38b6d1b696ab3b2619"}, - {file = "pyarrow-20.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:9965a050048ab02409fb7cbbefeedba04d3d67f2cc899eff505cc084345959ca"}, - {file = "pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1"}, + {file = "pyarrow-21.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e563271e2c5ff4d4a4cbeb2c83d5cf0d4938b891518e676025f7268c6fe5fe26"}, + {file = "pyarrow-21.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:fee33b0ca46f4c85443d6c450357101e47d53e6c3f008d658c27a2d020d44c79"}, + {file = "pyarrow-21.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:7be45519b830f7c24b21d630a31d48bcebfd5d4d7f9d3bdb49da9cdf6d764edb"}, + {file = "pyarrow-21.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:26bfd95f6bff443ceae63c65dc7e048670b7e98bc892210acba7e4995d3d4b51"}, + {file = "pyarrow-21.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd04ec08f7f8bd113c55868bd3fc442a9db67c27af098c5f814a3091e71cc61a"}, + {file = "pyarrow-21.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9b0b14b49ac10654332a805aedfc0147fb3469cbf8ea951b3d040dab12372594"}, + {file = "pyarrow-21.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:9d9f8bcb4c3be7738add259738abdeddc363de1b80e3310e04067aa1ca596634"}, + {file = "pyarrow-21.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c077f48aab61738c237802836fc3844f85409a46015635198761b0d6a688f87b"}, + {file = "pyarrow-21.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:689f448066781856237eca8d1975b98cace19b8dd2ab6145bf49475478bcaa10"}, + {file = "pyarrow-21.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:479ee41399fcddc46159a551705b89c05f11e8b8cb8e968f7fec64f62d91985e"}, + {file = "pyarrow-21.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:40ebfcb54a4f11bcde86bc586cbd0272bac0d516cfa539c799c2453768477569"}, + {file = "pyarrow-21.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8d58d8497814274d3d20214fbb24abcad2f7e351474357d552a8d53bce70c70e"}, + {file = "pyarrow-21.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:585e7224f21124dd57836b1530ac8f2df2afc43c861d7bf3d58a4870c42ae36c"}, + {file = "pyarrow-21.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:555ca6935b2cbca2c0e932bedd853e9bc523098c39636de9ad4693b5b1df86d6"}, + {file = "pyarrow-21.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:3a302f0e0963db37e0a24a70c56cf91a4faa0bca51c23812279ca2e23481fccd"}, + {file = "pyarrow-21.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:b6b27cf01e243871390474a211a7922bfbe3bda21e39bc9160daf0da3fe48876"}, + {file = "pyarrow-21.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:e72a8ec6b868e258a2cd2672d91f2860ad532d590ce94cdf7d5e7ec674ccf03d"}, + {file = "pyarrow-21.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b7ae0bbdc8c6674259b25bef5d2a1d6af5d39d7200c819cf99e07f7dfef1c51e"}, + {file = "pyarrow-21.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:58c30a1729f82d201627c173d91bd431db88ea74dcaa3885855bc6203e433b82"}, + {file = "pyarrow-21.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:072116f65604b822a7f22945a7a6e581cfa28e3454fdcc6939d4ff6090126623"}, + {file = "pyarrow-21.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf56ec8b0a5c8c9d7021d6fd754e688104f9ebebf1bf4449613c9531f5346a18"}, + {file = "pyarrow-21.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e99310a4ebd4479bcd1964dff9e14af33746300cb014aa4a3781738ac63baf4a"}, + {file = "pyarrow-21.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:d2fe8e7f3ce329a71b7ddd7498b3cfac0eeb200c2789bd840234f0dc271a8efe"}, + {file = "pyarrow-21.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:f522e5709379d72fb3da7785aa489ff0bb87448a9dc5a75f45763a795a089ebd"}, + {file = "pyarrow-21.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:69cbbdf0631396e9925e048cfa5bce4e8c3d3b41562bbd70c685a8eb53a91e61"}, + {file = "pyarrow-21.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:731c7022587006b755d0bdb27626a1a3bb004bb56b11fb30d98b6c1b4718579d"}, + {file = "pyarrow-21.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc56bc708f2d8ac71bd1dcb927e458c93cec10b98eb4120206a4091db7b67b99"}, + {file = "pyarrow-21.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:186aa00bca62139f75b7de8420f745f2af12941595bbbfa7ed3870ff63e25636"}, + {file = "pyarrow-21.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:a7a102574faa3f421141a64c10216e078df467ab9576684d5cd696952546e2da"}, + {file = "pyarrow-21.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:1e005378c4a2c6db3ada3ad4c217b381f6c886f0a80d6a316fe586b90f77efd7"}, + {file = "pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:65f8e85f79031449ec8706b74504a316805217b35b6099155dd7e227eef0d4b6"}, + {file = "pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:3a81486adc665c7eb1a2bde0224cfca6ceaba344a82a971ef059678417880eb8"}, + {file = "pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fc0d2f88b81dcf3ccf9a6ae17f89183762c8a94a5bdcfa09e05cfe413acf0503"}, + {file = "pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6299449adf89df38537837487a4f8d3bd91ec94354fdd2a7d30bc11c48ef6e79"}, + {file = "pyarrow-21.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:222c39e2c70113543982c6b34f3077962b44fca38c0bd9e68bb6781534425c10"}, + {file = "pyarrow-21.0.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:a7f6524e3747e35f80744537c78e7302cd41deee8baa668d56d55f77d9c464b3"}, + {file = "pyarrow-21.0.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:203003786c9fd253ebcafa44b03c06983c9c8d06c3145e37f1b76a1f317aeae1"}, + {file = "pyarrow-21.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3b4d97e297741796fead24867a8dabf86c87e4584ccc03167e4a811f50fdf74d"}, + {file = "pyarrow-21.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:898afce396b80fdda05e3086b4256f8677c671f7b1d27a6976fa011d3fd0a86e"}, + {file = "pyarrow-21.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:067c66ca29aaedae08218569a114e413b26e742171f526e828e1064fcdec13f4"}, + {file = "pyarrow-21.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0c4e75d13eb76295a49e0ea056eb18dbd87d81450bfeb8afa19a7e5a75ae2ad7"}, + {file = "pyarrow-21.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdc4c17afda4dab2a9c0b79148a43a7f4e1094916b3e18d8975bfd6d6d52241f"}, + {file = "pyarrow-21.0.0.tar.gz", hash = "sha256:5051f2dccf0e283ff56335760cbc8622cf52264d67e359d5569541ac11b6d5bc"}, ] [package.extras] @@ -2298,27 +2340,31 @@ files = [ [[package]] name = "pywin32" -version = "310" +version = "311" description = "Python for Window Extensions" optional = false python-versions = "*" files = [ - {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, - {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, - {file = "pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213"}, - {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, - {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, - {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, - {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, - {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, - {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, - {file = "pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab"}, - {file = "pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e"}, - {file = "pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33"}, - {file = "pywin32-310-cp38-cp38-win32.whl", hash = "sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c"}, - {file = "pywin32-310-cp38-cp38-win_amd64.whl", hash = "sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36"}, - {file = "pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a"}, - {file = "pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475"}, + {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, + {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, + {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, + {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, + {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, + {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, + {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, + {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, + {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, + {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, + {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, + {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, + {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, + {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, + {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, + {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, + {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, + {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, + {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, + {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, ] [[package]] @@ -2422,19 +2468,18 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "14.0.0" +version = "14.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" files = [ - {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, - {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, + {file = "rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f"}, + {file = "rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8"}, ] [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] diff --git a/src/nipanel/_convert.py b/src/nipanel/_convert.py index 61a48587..6de5eff7 100644 --- a/src/nipanel/_convert.py +++ b/src/nipanel/_convert.py @@ -12,6 +12,7 @@ from nipanel.converters.builtin import ( BoolConverter, BytesConverter, + DTDateTimeConverter, FloatConverter, IntConverter, StrConverter, @@ -37,6 +38,7 @@ FloatConverter(), IntConverter(), StrConverter(), + DTDateTimeConverter(), # Containers next BoolCollectionConverter(), BytesCollectionConverter(), diff --git a/src/nipanel/converters/builtin.py b/src/nipanel/converters/builtin.py index c004315c..50c9b932 100644 --- a/src/nipanel/converters/builtin.py +++ b/src/nipanel/converters/builtin.py @@ -1,9 +1,10 @@ """Classes to convert between builtin Python scalars and containers.""" +import datetime as dt from collections.abc import Collection from typing import Type -from google.protobuf import wrappers_pb2 +from google.protobuf import timestamp_pb2, wrappers_pb2 from ni.panels.v1 import panel_types_pb2 from nipanel.converters import Converter @@ -119,6 +120,30 @@ def to_python_value(self, protobuf_message: wrappers_pb2.StringValue) -> str: return protobuf_message.value +class DTDateTimeConverter(Converter[dt.datetime, timestamp_pb2.Timestamp]): + """A converter for datetime.datetime types.""" + + @property + def python_typename(self) -> str: + """The Python type that this converter handles.""" + return dt.datetime.__name__ + + @property + def protobuf_message(self) -> Type[timestamp_pb2.Timestamp]: + """The type-specific protobuf message for the Python type.""" + return timestamp_pb2.Timestamp + + def to_protobuf_message(self, python_value: dt.datetime) -> timestamp_pb2.Timestamp: + """Convert the Python dt.datetime to a protobuf timestamp_pb2.Timestamp.""" + ts = self.protobuf_message() + ts.FromDatetime(python_value) + return ts + + def to_python_value(self, protobuf_message: timestamp_pb2.Timestamp) -> dt.datetime: + """Convert the protobuf timestamp_pb2.Timestamp to a Python dt.datetime.""" + return protobuf_message.ToDatetime() + + class BoolCollectionConverter(Converter[Collection[bool], panel_types_pb2.BoolCollection]): """A converter for a Collection of bools.""" diff --git a/src/nipanel/converters/protobuf_types.py b/src/nipanel/converters/protobuf_types.py index c05e905a..2cef62f2 100644 --- a/src/nipanel/converters/protobuf_types.py +++ b/src/nipanel/converters/protobuf_types.py @@ -25,10 +25,10 @@ from nitypes.waveform import ( AnalogWaveform, ExtendedPropertyDictionary, - ExtendedPropertyValue, NoneScaleMode, Timing, ) +from nitypes.waveform.typing import ExtendedPropertyValue from typing_extensions import TypeAlias from nipanel.converters import Converter diff --git a/tests/unit/test_convert.py b/tests/unit/test_convert.py index a68131c0..ea20befc 100644 --- a/tests/unit/test_convert.py +++ b/tests/unit/test_convert.py @@ -1,8 +1,9 @@ +import datetime as dt from typing import Any, Collection, Union import numpy as np import pytest -from google.protobuf import any_pb2, wrappers_pb2 +from google.protobuf import any_pb2, timestamp_pb2, wrappers_pb2 from google.protobuf.message import Message from ni.panels.v1 import panel_types_pb2 from ni.protobuf.types.scalar_pb2 import ScalarData @@ -53,6 +54,7 @@ (tests.types.MixinIntEnum.VALUE11, "int"), (tests.types.MyStrEnum.VALUE1, "str"), (tests.types.MixinStrEnum.VALUE11, "str"), + (dt.datetime.now(), "datetime"), ([False, False], "Collection.bool"), ([b"mystr", b"mystr"], "Collection.bytes"), ([456.2, 1.0], "Collection.float"), @@ -123,6 +125,16 @@ def test___python_builtin_scalar___to_any___valid_wrapperpb2_value( assert unpack_dest.value == expected_value +def test___python_datetime_datetime___to_any___valid_timestamppb2_value() -> None: + expected_value = dt.datetime.now() + result = nipanel._convert.to_any(expected_value) + unpack_dest = timestamp_pb2.Timestamp() + _assert_any_and_unpack(result, unpack_dest) + + assert isinstance(unpack_dest, timestamp_pb2.Timestamp) + assert unpack_dest.ToDatetime() == expected_value + + @pytest.mark.parametrize( "proto_type, default_value, expected_value", [ @@ -175,6 +187,18 @@ def test___wrapperpb2_value___from_any___valid_python_value( assert result == expected_value +def test___timestamppb2_timestamp___from_any___valid_python_value() -> None: + expected_value = dt.datetime.now() + pb_value = timestamp_pb2.Timestamp() + pb_value.FromDatetime(expected_value) + packed_any = _pack_into_any(pb_value) + + result = nipanel._convert.from_any(packed_any) + + assert isinstance(result, dt.datetime) + assert result == expected_value + + @pytest.mark.parametrize( "proto_type, expected_value", [ diff --git a/tests/unit/test_streamlit_panel.py b/tests/unit/test_streamlit_panel.py index 027a7c40..860bacf8 100644 --- a/tests/unit/test_streamlit_panel.py +++ b/tests/unit/test_streamlit_panel.py @@ -1,5 +1,5 @@ +import datetime as dt import enum -from datetime import datetime import grpc import pytest @@ -266,6 +266,7 @@ def test___set_string_enum_type___get_value_with_int_enum_default___raises_excep 3.14, True, b"robotext", + dt.datetime.now(), ], ) def test___builtin_scalar_type___set_value___gets_same_value( @@ -312,7 +313,6 @@ def test___enum_type___set_value___gets_same_value( @pytest.mark.parametrize( "value_payload", [ - datetime.now(), lambda x: x + 1, [1, "string"], ["string", []], From 7e85c8988b7484847a13004eab454a538120000f Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 14:04:29 -0500 Subject: [PATCH 65/76] removed comment & fixed wording --- examples/niscope/niscope_binary_acquisition/README.md | 2 +- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/README.md b/examples/niscope/niscope_binary_acquisition/README.md index a3518b2c..475b1531 100644 --- a/examples/niscope/niscope_binary_acquisition/README.md +++ b/examples/niscope/niscope_binary_acquisition/README.md @@ -8,7 +8,7 @@ This is a nipanel example that displays an interactive Streamlit app and updates ### Feature -Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary. +Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary data. - Supports various data types ### Required Software diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index b0223c5e..161d780d 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -95,7 +95,6 @@ samples_array = np.array(binary_data) - # Apply scaling voltage_values = samples_array * gain + offset panel.set_value("scaled_voltage_data", voltage_values.tolist()) From d56a09692e59eec840d81c8c9c6998dd4b045ff8 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 14:07:03 -0500 Subject: [PATCH 66/76] changes to wording --- examples/niscope/niscope_binary_acquisition/README.md | 2 +- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/README.md b/examples/niscope/niscope_binary_acquisition/README.md index a3518b2c..475b1531 100644 --- a/examples/niscope/niscope_binary_acquisition/README.md +++ b/examples/niscope/niscope_binary_acquisition/README.md @@ -8,7 +8,7 @@ This is a nipanel example that displays an interactive Streamlit app and updates ### Feature -Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary. +Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary data. - Supports various data types ### Required Software diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index b0223c5e..161d780d 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -95,7 +95,6 @@ samples_array = np.array(binary_data) - # Apply scaling voltage_values = samples_array * gain + offset panel.set_value("scaled_voltage_data", voltage_values.tolist()) From 577a11689f4a4329ad17662b9d7efb8ed7ef98af Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 14:11:16 -0500 Subject: [PATCH 67/76] delete space --- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index 161d780d..115a0c20 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -94,7 +94,6 @@ panel.set_value("binary_data", waveforms[i].samples.tolist()) samples_array = np.array(binary_data) - voltage_values = samples_array * gain + offset panel.set_value("scaled_voltage_data", voltage_values.tolist()) From a3e70f76432d1d5ddc888b2725f956cab67b9a35 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 14:23:09 -0500 Subject: [PATCH 68/76] revert changes --- .../nidaqmx_continuous_analog_input/README.md | 2 +- .../nidaqmx_continuous_analog_input.py | 2 +- .../nidaqmx_continuous_analog_input_panel.py | 6 +- .../nidaqmx_continuous_analog_input_panel.py | 939 ------------------ 4 files changed, 3 insertions(+), 946 deletions(-) delete mode 100644 examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md index e387eabc..fb9adfa9 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/README.md @@ -18,5 +18,5 @@ This is a nipanel example that displays an interactive Streamlit app and updates ```pwsh poetry install --with examples -poetry run examples\nidaqmx\nidaqmx_continuous_analog_input\nidaqmx_continuous_analog_input.py +poetry run examples/nidaqmx/nidaqmx_continuous_analog_input.py ``` diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index 697d6cde..94432d8e 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -87,4 +87,4 @@ print(daq_error) panel.set_value("daq_error", daq_error) except KeyboardInterrupt: - pass + pass \ No newline at end of file diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py index 942fe3d3..89a22316 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input_panel.py @@ -39,12 +39,8 @@ if is_running: st.button(r"âšī¸ Stop", key="stop_button") -elif not is_running and panel.get_value("daq_error", "") == "": - st.button(r"â–ļī¸ Run", key="run_button") else: - st.error( - f"There was an error running the script. Fix the issue and re-run nidaqmx_continuous_analog_input.py \n\n {panel.get_value('daq_error', '')}" - ) + st.button(r"â–ļī¸ Run", key="run_button") thermocouple_data = panel.get_value("thermocouple_data", [0.0]) voltage_data = panel.get_value("voltage_data", [0.0]) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py b/examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py deleted file mode 100644 index 14e9c53d..00000000 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py +++ /dev/null @@ -1,939 +0,0 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_continuous_analog_input.py.""" - -import streamlit as st -from nidaqmx.constants import ( - TerminalConfiguration, - CJCSource, - TemperatureUnits, - ThermocoupleType, - LoggingMode, -) -from streamlit_echarts import st_echarts - -import nipanel -from nipanel.controls import enum_selectbox - - -st.set_page_config(page_title="NI-DAQmx Example", page_icon="📈", layout="wide") -st.title("Analog Input - Voltage and Thermocouple in a Single Task") - -st.markdown( - """ - - """, - unsafe_allow_html=True, -) - -panel = nipanel.get_streamlit_panel_accessor() -is_running = panel.get_value("is_running", False) - -if is_running: - st.button(r"âšī¸ Stop", key="stop_button") -else: - st.button(r"â–ļī¸ Run", key="run_button") - -thermocouple_data = panel.get_value("thermocouple_data", [0.0]) -voltage_data = panel.get_value("voltage_data", [0.0]) -sample_rate = panel.get_value("sample_rate", 0.0) - -# Create two-column layout for the entire interface -left_column, right_column = st.columns([1, 1]) - -# Left column - Channel tabs and Timing Settings -with left_column: - # Channel Settings tabs - with st.container(border=True): - st.header("Channel Settings") - voltage_tab, thermocouple_tab = st.tabs(["Voltage", "Thermocouple"]) - - voltage_tab.header("Voltage") - with voltage_tab: - channel_left_column, channel_right_column = st.columns(2) - with channel_left_column: - st.selectbox(options=["Dev1/ai0"], label="Physical Channels", disabled=True) - st.number_input( - "Min Value", - value=-5.0, - step=0.1, - disabled=panel.get_value("is_running", False), - key="voltage_min_value", - ) - st.number_input( - "Max Value", - value=5.0, - step=0.1, - disabled=panel.get_value("is_running", False), - key="voltage_max_value", - ) - with channel_right_column: - enum_selectbox( - panel, - label="Terminal Configuration", - value=TerminalConfiguration.DEFAULT, - disabled=panel.get_value("is_running", False), - key="terminal_configuration", - ) - - thermocouple_tab.header("Thermocouple") - with thermocouple_tab: - channel_left_column, channel_middle_column, channel_right_column = st.columns(3) - with channel_left_column: - st.selectbox(options=["Dev1/ai1"], label="Physical Channel", disabled=True) - st.number_input( - "Min Value", - value=0.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="thermocouple_min_value", - ) - st.number_input( - "Max Value", - value=100.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="thermocouple_max_value", - ) - with channel_middle_column: - enum_selectbox( - panel, - label="Units", - value=TemperatureUnits.DEG_C, - disabled=panel.get_value("is_running", False), - key="thermocouple_units", - ) - enum_selectbox( - panel, - label="Thermocouple Type", - value=ThermocoupleType.K, - disabled=panel.get_value("is_running", False), - key="thermocouple_type", - ) - with channel_right_column: - enum_selectbox( - panel, - label="CJC Source", - value=CJCSource.CONSTANT_USER_VALUE, - disabled=panel.get_value("is_running", False), - key="thermocouple_cjc_source", - ) - st.number_input( - "CJC Value", - value=25.0, - step=1.0, - disabled=panel.get_value("is_running", False), - key="thermocouple_cjc_val", - ) - - # Timing Settings section in left column - with st.container(border=True): - st.header("Timing Settings") - timing_left_column, timing_right_column = st.columns(2) - with timing_left_column: - st.selectbox( - options=["OnboardClock"], - label="Sample Clock Source", - disabled=True, - ) - st.number_input( - "Sample Rate", - value=1000.0, - step=100.0, - min_value=1.0, - disabled=panel.get_value("is_running", False), - key="sample_rate_input", - ) - with timing_right_column: - st.number_input( - "Samples per Loop", - value=3000, - step=100, - min_value=10, - disabled=panel.get_value("is_running", False), - key="samples_per_channel", - ) - st.text_input( - label="Actual Sample Rate", - value=str(sample_rate) if sample_rate else "", - key="actual_sample_rate_display", - ) - -# Right column - Graph and Logging Settings -with right_column: - with st.container(border=True): - # Graph section - st.header("Voltage & Thermocouple") - voltage_therm_graph = { - "animation": False, - "tooltip": {"trigger": "axis"}, - "legend": {"data": ["Voltage (V)", "Temperature (C)"]}, - "xAxis": { - "type": "category", - "data": [ - x / sample_rate if sample_rate > 0.001 else x for x in range(len(voltage_data)) - ], - "name": "Time", - "nameLocation": "center", - "nameGap": 40, - }, - "yAxis": { - "type": "value", - "name": "Measurement", - "nameRotate": 90, - "nameLocation": "center", - "nameGap": 40, - }, - "series": [ - { - "name": "voltage_amplitude", - "type": "line", - "data": voltage_data, - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - { - "name": "thermocouple_amplitude", - "type": "line", - "data": thermocouple_data, - "color": "red", - "emphasis": {"focus": "series"}, - "smooth": True, - "seriesLayoutBy": "row", - }, - ], - } - st_echarts(options=voltage_therm_graph, height="446px", key="voltage_therm_graph") - # st_echarts(options=voltage_therm_graph, height="446px", key="1") - # st_echarts(options=voltage_therm_graph, height="446px", key="2") - # st_echarts(options=voltage_therm_graph, height="446px", key="3") - # st_echarts(options=voltage_therm_graph, height="446px", key="4") - # st_echarts(options=voltage_therm_graph, height="446px", key="5") - # st_echarts(options=voltage_therm_graph, height="446px", key="6") - # st_echarts(options=voltage_therm_graph, height="446px", key="7") - # st_echarts(options=voltage_therm_graph, height="446px", key="8") - # st_echarts(options=voltage_therm_graph, height="446px", key="9") - # st_echarts(options=voltage_therm_graph, height="446px", key="10") - # st_echarts(options=voltage_therm_graph, height="446px", key="11") - # st_echarts(options=voltage_therm_graph, height="446px", key="12") - # st_echarts(options=voltage_therm_graph, height="446px", key="13") - # st_echarts(options=voltage_therm_graph, height="446px", key="14") - # st_echarts(options=voltage_therm_graph, height="446px", key="15") - # st_echarts(options=voltage_therm_graph, height="446px", key="16") - # st_echarts(options=voltage_therm_graph, height="446px", key="17") - # st_echarts(options=voltage_therm_graph, height="446px", key="18") - # st_echarts(options=voltage_therm_graph, height="446px", key="19") - # st_echarts(options=voltage_therm_graph, height="446px", key="20") - # st_echarts(options=voltage_therm_graph, height="446px", key="21") - # st_echarts(options=voltage_therm_graph, height="446px", key="22") - # st_echarts(options=voltage_therm_graph, height="446px", key="23") - # st_echarts(options=voltage_therm_graph, height="446px", key="24") - # st_echarts(options=voltage_therm_graph, height="446px", key="25") - # st_echarts(options=voltage_therm_graph, height="446px", key="26") - # st_echarts(options=voltage_therm_graph, height="446px", key="27") - # st_echarts(options=voltage_therm_graph, height="446px", key="28") - # st_echarts(options=voltage_therm_graph, height="446px", key="29") - # st_echarts(options=voltage_therm_graph, height="446px", key="30") - # st_echarts(options=voltage_therm_graph, height="446px", key="41") - # st_echarts(options=voltage_therm_graph, height="446px", key="42") - # st_echarts(options=voltage_therm_graph, height="446px", key="43") - # st_echarts(options=voltage_therm_graph, height="446px", key="44") - # st_echarts(options=voltage_therm_graph, height="446px", key="45") - # st_echarts(options=voltage_therm_graph, height="446px", key="46") - # st_echarts(options=voltage_therm_graph, height="446px", key="47") - # st_echarts(options=voltage_therm_graph, height="446px", key="48") - # st_echarts(options=voltage_therm_graph, height="446px", key="49") - # st_echarts(options=voltage_therm_graph, height="446px", key="50") - # st_echarts(options=voltage_therm_graph, height="446px", key="61") - # st_echarts(options=voltage_therm_graph, height="446px", key="62") - # st_echarts(options=voltage_therm_graph, height="446px", key="63") - # st_echarts(options=voltage_therm_graph, height="446px", key="64") - # st_echarts(options=voltage_therm_graph, height="446px", key="65") - # st_echarts(options=voltage_therm_graph, height="446px", key="66") - # st_echarts(options=voltage_therm_graph, height="446px", key="67") - # st_echarts(options=voltage_therm_graph, height="446px", key="68") - # st_echarts(options=voltage_therm_graph, height="446px", key="69") - # st_echarts(options=voltage_therm_graph, height="446px", key="70") - # st_echarts(options=voltage_therm_graph, height="446px", key="81") - # st_echarts(options=voltage_therm_graph, height="446px", key="82") - # st_echarts(options=voltage_therm_graph, height="446px", key="83") - # st_echarts(options=voltage_therm_graph, height="446px", key="84") - # st_echarts(options=voltage_therm_graph, height="446px", key="85") - # st_echarts(options=voltage_therm_graph, height="446px", key="86") - # st_echarts(options=voltage_therm_graph, height="446px", key="87") - # st_echarts(options=voltage_therm_graph, height="446px", key="88") - # st_echarts(options=voltage_therm_graph, height="446px", key="89") - # st_echarts(options=voltage_therm_graph, height="446px", key="90") - # st_echarts(options=voltage_therm_graph, height="446px", key="91") - # st_echarts(options=voltage_therm_graph, height="446px", key="92") - # st_echarts(options=voltage_therm_graph, height="446px", key="93") - # st_echarts(options=voltage_therm_graph, height="446px", key="94") - # st_echarts(options=voltage_therm_graph, height="446px", key="95") - # st_echarts(options=voltage_therm_graph, height="446px", key="96") - # st_echarts(options=voltage_therm_graph, height="446px", key="97") - # st_echarts(options=voltage_therm_graph, height="446px", key="98") - # st_echarts(options=voltage_therm_graph, height="446px", key="99") - # st_echarts(options=voltage_therm_graph, height="446px", key="100") - # st_echarts(options=voltage_therm_graph, height="446px", key="101") - # st_echarts(options=voltage_therm_graph, height="446px", key="102") - # st_echarts(options=voltage_therm_graph, height="446px", key="103") - # st_echarts(options=voltage_therm_graph, height="446px", key="104") - # st_echarts(options=voltage_therm_graph, height="446px", key="105") - # st_echarts(options=voltage_therm_graph, height="446px", key="106") - # st_echarts(options=voltage_therm_graph, height="446px", key="107") - # st_echarts(options=voltage_therm_graph, height="446px", key="108") - # st_echarts(options=voltage_therm_graph, height="446px", key="109") - # st_echarts(options=voltage_therm_graph, height="446px", key="110") - # st_echarts(options=voltage_therm_graph, height="446px", key="111") - # st_echarts(options=voltage_therm_graph, height="446px", key="112") - # st_echarts(options=voltage_therm_graph, height="446px", key="113") - # st_echarts(options=voltage_therm_graph, height="446px", key="114") - # st_echarts(options=voltage_therm_graph, height="446px", key="115") - # st_echarts(options=voltage_therm_graph, height="446px", key="116") - # st_echarts(options=voltage_therm_graph, height="446px", key="117") - # st_echarts(options=voltage_therm_graph, height="446px", key="118") - # st_echarts(options=voltage_therm_graph, height="446px", key="119") - # st_echarts(options=voltage_therm_graph, height="446px", key="120") - # st_echarts(options=voltage_therm_graph, height="446px", key="121") - # st_echarts(options=voltage_therm_graph, height="446px", key="122") - # st_echarts(options=voltage_therm_graph, height="446px", key="123") - # st_echarts(options=voltage_therm_graph, height="446px", key="124") - # st_echarts(options=voltage_therm_graph, height="446px", key="125") - # st_echarts(options=voltage_therm_graph, height="446px", key="126") - # st_echarts(options=voltage_therm_graph, height="446px", key="127") - # st_echarts(options=voltage_therm_graph, height="446px", key="128") - # st_echarts(options=voltage_therm_graph, height="446px", key="129") - # st_echarts(options=voltage_therm_graph, height="446px", key="130") - # st_echarts(options=voltage_therm_graph, height="446px", key="141") - # st_echarts(options=voltage_therm_graph, height="446px", key="142") - # st_echarts(options=voltage_therm_graph, height="446px", key="143") - # st_echarts(options=voltage_therm_graph, height="446px", key="144") - # st_echarts(options=voltage_therm_graph, height="446px", key="145") - # st_echarts(options=voltage_therm_graph, height="446px", key="146") - # st_echarts(options=voltage_therm_graph, height="446px", key="147") - # st_echarts(options=voltage_therm_graph, height="446px", key="148") - # st_echarts(options=voltage_therm_graph, height="446px", key="149") - # st_echarts(options=voltage_therm_graph, height="446px", key="150") - # st_echarts(options=voltage_therm_graph, height="446px", key="161") - # st_echarts(options=voltage_therm_graph, height="446px", key="162") - # st_echarts(options=voltage_therm_graph, height="446px", key="163") - # st_echarts(options=voltage_therm_graph, height="446px", key="164") - # st_echarts(options=voltage_therm_graph, height="446px", key="165") - # st_echarts(options=voltage_therm_graph, height="446px", key="166") - # st_echarts(options=voltage_therm_graph, height="446px", key="167") - # st_echarts(options=voltage_therm_graph, height="446px", key="168") - # st_echarts(options=voltage_therm_graph, height="446px", key="169") - # st_echarts(options=voltage_therm_graph, height="446px", key="170") - # st_echarts(options=voltage_therm_graph, height="446px", key="181") - # st_echarts(options=voltage_therm_graph, height="446px", key="182") - # st_echarts(options=voltage_therm_graph, height="446px", key="183") - # st_echarts(options=voltage_therm_graph, height="446px", key="184") - # st_echarts(options=voltage_therm_graph, height="446px", key="185") - # st_echarts(options=voltage_therm_graph, height="446px", key="186") - # st_echarts(options=voltage_therm_graph, height="446px", key="187") - # st_echarts(options=voltage_therm_graph, height="446px", key="188") - # st_echarts(options=voltage_therm_graph, height="446px", key="189") - # st_echarts(options=voltage_therm_graph, height="446px", key="190") - # st_echarts(options=voltage_therm_graph, height="446px", key="191") - # st_echarts(options=voltage_therm_graph, height="446px", key="192") - # st_echarts(options=voltage_therm_graph, height="446px", key="193") - # st_echarts(options=voltage_therm_graph, height="446px", key="194") - # st_echarts(options=voltage_therm_graph, height="446px", key="195") - # st_echarts(options=voltage_therm_graph, height="446px", key="196") - # st_echarts(options=voltage_therm_graph, height="446px", key="197") - # st_echarts(options=voltage_therm_graph, height="446px", key="198") - # st_echarts(options=voltage_therm_graph, height="446px", key="199") - # st_echarts(options=voltage_therm_graph, height="446px", key="200") - # st_echarts(options=voltage_therm_graph, height="446px", key="301") - # st_echarts(options=voltage_therm_graph, height="446px", key="302") - # st_echarts(options=voltage_therm_graph, height="446px", key="303") - # st_echarts(options=voltage_therm_graph, height="446px", key="304") - # st_echarts(options=voltage_therm_graph, height="446px", key="305") - # st_echarts(options=voltage_therm_graph, height="446px", key="306") - # st_echarts(options=voltage_therm_graph, height="446px", key="307") - # st_echarts(options=voltage_therm_graph, height="446px", key="308") - # st_echarts(options=voltage_therm_graph, height="446px", key="309") - # st_echarts(options=voltage_therm_graph, height="446px", key="310") - # st_echarts(options=voltage_therm_graph, height="446px", key="311") - # st_echarts(options=voltage_therm_graph, height="446px", key="312") - # st_echarts(options=voltage_therm_graph, height="446px", key="313") - # st_echarts(options=voltage_therm_graph, height="446px", key="314") - # st_echarts(options=voltage_therm_graph, height="446px", key="315") - # st_echarts(options=voltage_therm_graph, height="446px", key="316") - # st_echarts(options=voltage_therm_graph, height="446px", key="317") - # st_echarts(options=voltage_therm_graph, height="446px", key="318") - # st_echarts(options=voltage_therm_graph, height="446px", key="319") - # st_echarts(options=voltage_therm_graph, height="446px", key="320") - # st_echarts(options=voltage_therm_graph, height="446px", key="321") - # st_echarts(options=voltage_therm_graph, height="446px", key="322") - # st_echarts(options=voltage_therm_graph, height="446px", key="323") - # st_echarts(options=voltage_therm_graph, height="446px", key="324") - # st_echarts(options=voltage_therm_graph, height="446px", key="325") - # st_echarts(options=voltage_therm_graph, height="446px", key="326") - # st_echarts(options=voltage_therm_graph, height="446px", key="327") - # st_echarts(options=voltage_therm_graph, height="446px", key="328") - # st_echarts(options=voltage_therm_graph, height="446px", key="329") - # st_echarts(options=voltage_therm_graph, height="446px", key="330") - # st_echarts(options=voltage_therm_graph, height="446px", key="341") - # st_echarts(options=voltage_therm_graph, height="446px", key="342") - # st_echarts(options=voltage_therm_graph, height="446px", key="343") - # st_echarts(options=voltage_therm_graph, height="446px", key="344") - # st_echarts(options=voltage_therm_graph, height="446px", key="345") - # st_echarts(options=voltage_therm_graph, height="446px", key="346") - # st_echarts(options=voltage_therm_graph, height="446px", key="347") - # st_echarts(options=voltage_therm_graph, height="446px", key="348") - # st_echarts(options=voltage_therm_graph, height="446px", key="349") - # st_echarts(options=voltage_therm_graph, height="446px", key="350") - # st_echarts(options=voltage_therm_graph, height="446px", key="361") - # st_echarts(options=voltage_therm_graph, height="446px", key="362") - # st_echarts(options=voltage_therm_graph, height="446px", key="363") - # st_echarts(options=voltage_therm_graph, height="446px", key="364") - # st_echarts(options=voltage_therm_graph, height="446px", key="365") - # st_echarts(options=voltage_therm_graph, height="446px", key="366") - # st_echarts(options=voltage_therm_graph, height="446px", key="367") - # st_echarts(options=voltage_therm_graph, height="446px", key="368") - # st_echarts(options=voltage_therm_graph, height="446px", key="369") - # st_echarts(options=voltage_therm_graph, height="446px", key="370") - # st_echarts(options=voltage_therm_graph, height="446px", key="381") - # st_echarts(options=voltage_therm_graph, height="446px", key="382") - # st_echarts(options=voltage_therm_graph, height="446px", key="383") - # st_echarts(options=voltage_therm_graph, height="446px", key="384") - # st_echarts(options=voltage_therm_graph, height="446px", key="385") - # st_echarts(options=voltage_therm_graph, height="446px", key="386") - # st_echarts(options=voltage_therm_graph, height="446px", key="387") - # st_echarts(options=voltage_therm_graph, height="446px", key="388") - # st_echarts(options=voltage_therm_graph, height="446px", key="389") - # st_echarts(options=voltage_therm_graph, height="446px", key="390") - # st_echarts(options=voltage_therm_graph, height="446px", key="391") - # st_echarts(options=voltage_therm_graph, height="446px", key="392") - # st_echarts(options=voltage_therm_graph, height="446px", key="393") - # st_echarts(options=voltage_therm_graph, height="446px", key="394") - # st_echarts(options=voltage_therm_graph, height="446px", key="395") - # st_echarts(options=voltage_therm_graph, height="446px", key="396") - # st_echarts(options=voltage_therm_graph, height="446px", key="397") - # st_echarts(options=voltage_therm_graph, height="446px", key="398") - # st_echarts(options=voltage_therm_graph, height="446px", key="399") - # st_echarts(options=voltage_therm_graph, height="446px", key="400") - # st_echarts(options=voltage_therm_graph, height="446px", key="401") - # st_echarts(options=voltage_therm_graph, height="446px", key="402") - # st_echarts(options=voltage_therm_graph, height="446px", key="403") - # st_echarts(options=voltage_therm_graph, height="446px", key="404") - # st_echarts(options=voltage_therm_graph, height="446px", key="405") - # st_echarts(options=voltage_therm_graph, height="446px", key="406") - # st_echarts(options=voltage_therm_graph, height="446px", key="407") - # st_echarts(options=voltage_therm_graph, height="446px", key="408") - # st_echarts(options=voltage_therm_graph, height="446px", key="409") - # st_echarts(options=voltage_therm_graph, height="446px", key="410") - # st_echarts(options=voltage_therm_graph, height="446px", key="411") - # st_echarts(options=voltage_therm_graph, height="446px", key="412") - # st_echarts(options=voltage_therm_graph, height="446px", key="413") - # st_echarts(options=voltage_therm_graph, height="446px", key="414") - # st_echarts(options=voltage_therm_graph, height="446px", key="415") - # st_echarts(options=voltage_therm_graph, height="446px", key="416") - # st_echarts(options=voltage_therm_graph, height="446px", key="417") - # st_echarts(options=voltage_therm_graph, height="446px", key="418") - # st_echarts(options=voltage_therm_graph, height="446px", key="419") - # st_echarts(options=voltage_therm_graph, height="446px", key="420") - # st_echarts(options=voltage_therm_graph, height="446px", key="421") - # st_echarts(options=voltage_therm_graph, height="446px", key="422") - # st_echarts(options=voltage_therm_graph, height="446px", key="423") - # st_echarts(options=voltage_therm_graph, height="446px", key="424") - # st_echarts(options=voltage_therm_graph, height="446px", key="425") - # st_echarts(options=voltage_therm_graph, height="446px", key="426") - # st_echarts(options=voltage_therm_graph, height="446px", key="427") - # st_echarts(options=voltage_therm_graph, height="446px", key="428") - # st_echarts(options=voltage_therm_graph, height="446px", key="429") - # st_echarts(options=voltage_therm_graph, height="446px", key="430") - # st_echarts(options=voltage_therm_graph, height="446px", key="441") - # st_echarts(options=voltage_therm_graph, height="446px", key="442") - # st_echarts(options=voltage_therm_graph, height="446px", key="443") - # st_echarts(options=voltage_therm_graph, height="446px", key="444") - # st_echarts(options=voltage_therm_graph, height="446px", key="445") - # st_echarts(options=voltage_therm_graph, height="446px", key="446") - # st_echarts(options=voltage_therm_graph, height="446px", key="447") - # st_echarts(options=voltage_therm_graph, height="446px", key="448") - # st_echarts(options=voltage_therm_graph, height="446px", key="449") - # st_echarts(options=voltage_therm_graph, height="446px", key="450") - # st_echarts(options=voltage_therm_graph, height="446px", key="461") - # st_echarts(options=voltage_therm_graph, height="446px", key="462") - # st_echarts(options=voltage_therm_graph, height="446px", key="463") - # st_echarts(options=voltage_therm_graph, height="446px", key="464") - # st_echarts(options=voltage_therm_graph, height="446px", key="465") - # st_echarts(options=voltage_therm_graph, height="446px", key="466") - # st_echarts(options=voltage_therm_graph, height="446px", key="467") - # st_echarts(options=voltage_therm_graph, height="446px", key="468") - # st_echarts(options=voltage_therm_graph, height="446px", key="469") - # st_echarts(options=voltage_therm_graph, height="446px", key="470") - # st_echarts(options=voltage_therm_graph, height="446px", key="481") - # st_echarts(options=voltage_therm_graph, height="446px", key="482") - # st_echarts(options=voltage_therm_graph, height="446px", key="483") - # st_echarts(options=voltage_therm_graph, height="446px", key="484") - # st_echarts(options=voltage_therm_graph, height="446px", key="485") - # st_echarts(options=voltage_therm_graph, height="446px", key="486") - # st_echarts(options=voltage_therm_graph, height="446px", key="487") - # st_echarts(options=voltage_therm_graph, height="446px", key="488") - # st_echarts(options=voltage_therm_graph, height="446px", key="489") - # st_echarts(options=voltage_therm_graph, height="446px", key="490") - # st_echarts(options=voltage_therm_graph, height="446px", key="491") - # st_echarts(options=voltage_therm_graph, height="446px", key="492") - # st_echarts(options=voltage_therm_graph, height="446px", key="493") - # st_echarts(options=voltage_therm_graph, height="446px", key="494") - # st_echarts(options=voltage_therm_graph, height="446px", key="495") - # st_echarts(options=voltage_therm_graph, height="446px", key="496") - # st_echarts(options=voltage_therm_graph, height="446px", key="497") - # st_echarts(options=voltage_therm_graph, height="446px", key="498") - # st_echarts(options=voltage_therm_graph, height="446px", key="499") - # st_echarts(options=voltage_therm_graph, height="446px", key="500") - # st_echarts(options=voltage_therm_graph, height="446px", key="501") - # st_echarts(options=voltage_therm_graph, height="446px", key="502") - # st_echarts(options=voltage_therm_graph, height="446px", key="503") - # st_echarts(options=voltage_therm_graph, height="446px", key="504") - # st_echarts(options=voltage_therm_graph, height="446px", key="505") - # st_echarts(options=voltage_therm_graph, height="446px", key="506") - # st_echarts(options=voltage_therm_graph, height="446px", key="507") - # st_echarts(options=voltage_therm_graph, height="446px", key="508") - # st_echarts(options=voltage_therm_graph, height="446px", key="509") - # st_echarts(options=voltage_therm_graph, height="446px", key="510") - # st_echarts(options=voltage_therm_graph, height="446px", key="511") - # st_echarts(options=voltage_therm_graph, height="446px", key="512") - # st_echarts(options=voltage_therm_graph, height="446px", key="513") - # st_echarts(options=voltage_therm_graph, height="446px", key="514") - # st_echarts(options=voltage_therm_graph, height="446px", key="515") - # st_echarts(options=voltage_therm_graph, height="446px", key="516") - # st_echarts(options=voltage_therm_graph, height="446px", key="517") - # st_echarts(options=voltage_therm_graph, height="446px", key="518") - # st_echarts(options=voltage_therm_graph, height="446px", key="519") - # st_echarts(options=voltage_therm_graph, height="446px", key="520") - # st_echarts(options=voltage_therm_graph, height="446px", key="521") - # st_echarts(options=voltage_therm_graph, height="446px", key="522") - # st_echarts(options=voltage_therm_graph, height="446px", key="523") - # st_echarts(options=voltage_therm_graph, height="446px", key="524") - # st_echarts(options=voltage_therm_graph, height="446px", key="525") - # st_echarts(options=voltage_therm_graph, height="446px", key="526") - # st_echarts(options=voltage_therm_graph, height="446px", key="527") - # st_echarts(options=voltage_therm_graph, height="446px", key="528") - # st_echarts(options=voltage_therm_graph, height="446px", key="529") - # st_echarts(options=voltage_therm_graph, height="446px", key="530") - # st_echarts(options=voltage_therm_graph, height="446px", key="541") - # st_echarts(options=voltage_therm_graph, height="446px", key="542") - # st_echarts(options=voltage_therm_graph, height="446px", key="543") - # st_echarts(options=voltage_therm_graph, height="446px", key="544") - # st_echarts(options=voltage_therm_graph, height="446px", key="545") - # st_echarts(options=voltage_therm_graph, height="446px", key="546") - # st_echarts(options=voltage_therm_graph, height="446px", key="547") - # st_echarts(options=voltage_therm_graph, height="446px", key="548") - # st_echarts(options=voltage_therm_graph, height="446px", key="549") - # st_echarts(options=voltage_therm_graph, height="446px", key="550") - # st_echarts(options=voltage_therm_graph, height="446px", key="561") - # st_echarts(options=voltage_therm_graph, height="446px", key="562") - # st_echarts(options=voltage_therm_graph, height="446px", key="563") - # st_echarts(options=voltage_therm_graph, height="446px", key="564") - # st_echarts(options=voltage_therm_graph, height="446px", key="565") - # st_echarts(options=voltage_therm_graph, height="446px", key="566") - # st_echarts(options=voltage_therm_graph, height="446px", key="567") - # st_echarts(options=voltage_therm_graph, height="446px", key="568") - # st_echarts(options=voltage_therm_graph, height="446px", key="569") - # st_echarts(options=voltage_therm_graph, height="446px", key="570") - # st_echarts(options=voltage_therm_graph, height="446px", key="581") - # st_echarts(options=voltage_therm_graph, height="446px", key="582") - # st_echarts(options=voltage_therm_graph, height="446px", key="583") - # st_echarts(options=voltage_therm_graph, height="446px", key="584") - # st_echarts(options=voltage_therm_graph, height="446px", key="585") - # st_echarts(options=voltage_therm_graph, height="446px", key="586") - # st_echarts(options=voltage_therm_graph, height="446px", key="587") - # st_echarts(options=voltage_therm_graph, height="446px", key="588") - # st_echarts(options=voltage_therm_graph, height="446px", key="589") - # st_echarts(options=voltage_therm_graph, height="446px", key="590") - # st_echarts(options=voltage_therm_graph, height="446px", key="591") - # st_echarts(options=voltage_therm_graph, height="446px", key="592") - # st_echarts(options=voltage_therm_graph, height="446px", key="593") - # st_echarts(options=voltage_therm_graph, height="446px", key="594") - # st_echarts(options=voltage_therm_graph, height="446px", key="595") - # st_echarts(options=voltage_therm_graph, height="446px", key="596") - # st_echarts(options=voltage_therm_graph, height="446px", key="597") - # st_echarts(options=voltage_therm_graph, height="446px", key="598") - # st_echarts(options=voltage_therm_graph, height="446px", key="599") - # st_echarts(options=voltage_therm_graph, height="446px", key="600") - # st_echarts(options=voltage_therm_graph, height="446px", key="601") - # st_echarts(options=voltage_therm_graph, height="446px", key="602") - # st_echarts(options=voltage_therm_graph, height="446px", key="603") - # st_echarts(options=voltage_therm_graph, height="446px", key="604") - # st_echarts(options=voltage_therm_graph, height="446px", key="605") - # st_echarts(options=voltage_therm_graph, height="446px", key="606") - # st_echarts(options=voltage_therm_graph, height="446px", key="607") - # st_echarts(options=voltage_therm_graph, height="446px", key="608") - # st_echarts(options=voltage_therm_graph, height="446px", key="609") - # st_echarts(options=voltage_therm_graph, height="446px", key="610") - # st_echarts(options=voltage_therm_graph, height="446px", key="611") - # st_echarts(options=voltage_therm_graph, height="446px", key="612") - # st_echarts(options=voltage_therm_graph, height="446px", key="613") - # st_echarts(options=voltage_therm_graph, height="446px", key="614") - # st_echarts(options=voltage_therm_graph, height="446px", key="615") - # st_echarts(options=voltage_therm_graph, height="446px", key="616") - # st_echarts(options=voltage_therm_graph, height="446px", key="617") - # st_echarts(options=voltage_therm_graph, height="446px", key="618") - # st_echarts(options=voltage_therm_graph, height="446px", key="619") - # st_echarts(options=voltage_therm_graph, height="446px", key="620") - # st_echarts(options=voltage_therm_graph, height="446px", key="621") - # st_echarts(options=voltage_therm_graph, height="446px", key="622") - # st_echarts(options=voltage_therm_graph, height="446px", key="623") - # st_echarts(options=voltage_therm_graph, height="446px", key="624") - # st_echarts(options=voltage_therm_graph, height="446px", key="625") - # st_echarts(options=voltage_therm_graph, height="446px", key="626") - # st_echarts(options=voltage_therm_graph, height="446px", key="627") - # st_echarts(options=voltage_therm_graph, height="446px", key="628") - # st_echarts(options=voltage_therm_graph, height="446px", key="629") - # st_echarts(options=voltage_therm_graph, height="446px", key="630") - # st_echarts(options=voltage_therm_graph, height="446px", key="641") - # st_echarts(options=voltage_therm_graph, height="446px", key="642") - # st_echarts(options=voltage_therm_graph, height="446px", key="643") - # st_echarts(options=voltage_therm_graph, height="446px", key="644") - # st_echarts(options=voltage_therm_graph, height="446px", key="645") - # st_echarts(options=voltage_therm_graph, height="446px", key="646") - # st_echarts(options=voltage_therm_graph, height="446px", key="647") - # st_echarts(options=voltage_therm_graph, height="446px", key="648") - # st_echarts(options=voltage_therm_graph, height="446px", key="649") - # st_echarts(options=voltage_therm_graph, height="446px", key="650") - # st_echarts(options=voltage_therm_graph, height="446px", key="661") - # st_echarts(options=voltage_therm_graph, height="446px", key="662") - # st_echarts(options=voltage_therm_graph, height="446px", key="663") - # st_echarts(options=voltage_therm_graph, height="446px", key="664") - # st_echarts(options=voltage_therm_graph, height="446px", key="665") - # st_echarts(options=voltage_therm_graph, height="446px", key="666") - # st_echarts(options=voltage_therm_graph, height="446px", key="667") - # st_echarts(options=voltage_therm_graph, height="446px", key="668") - # st_echarts(options=voltage_therm_graph, height="446px", key="669") - # st_echarts(options=voltage_therm_graph, height="446px", key="670") - # st_echarts(options=voltage_therm_graph, height="446px", key="681") - # st_echarts(options=voltage_therm_graph, height="446px", key="682") - # st_echarts(options=voltage_therm_graph, height="446px", key="683") - # st_echarts(options=voltage_therm_graph, height="446px", key="684") - # st_echarts(options=voltage_therm_graph, height="446px", key="685") - # st_echarts(options=voltage_therm_graph, height="446px", key="686") - # st_echarts(options=voltage_therm_graph, height="446px", key="687") - # st_echarts(options=voltage_therm_graph, height="446px", key="688") - # st_echarts(options=voltage_therm_graph, height="446px", key="689") - # st_echarts(options=voltage_therm_graph, height="446px", key="690") - # st_echarts(options=voltage_therm_graph, height="446px", key="691") - # st_echarts(options=voltage_therm_graph, height="446px", key="692") - # st_echarts(options=voltage_therm_graph, height="446px", key="693") - # st_echarts(options=voltage_therm_graph, height="446px", key="694") - # st_echarts(options=voltage_therm_graph, height="446px", key="695") - # st_echarts(options=voltage_therm_graph, height="446px", key="696") - # st_echarts(options=voltage_therm_graph, height="446px", key="697") - # st_echarts(options=voltage_therm_graph, height="446px", key="698") - # st_echarts(options=voltage_therm_graph, height="446px", key="699") - # st_echarts(options=voltage_therm_graph, height="446px", key="700") - # st_echarts(options=voltage_therm_graph, height="446px", key="701") - # st_echarts(options=voltage_therm_graph, height="446px", key="702") - # st_echarts(options=voltage_therm_graph, height="446px", key="703") - # st_echarts(options=voltage_therm_graph, height="446px", key="704") - # st_echarts(options=voltage_therm_graph, height="446px", key="705") - # st_echarts(options=voltage_therm_graph, height="446px", key="706") - # st_echarts(options=voltage_therm_graph, height="446px", key="707") - # st_echarts(options=voltage_therm_graph, height="446px", key="708") - # st_echarts(options=voltage_therm_graph, height="446px", key="709") - # st_echarts(options=voltage_therm_graph, height="446px", key="710") - # st_echarts(options=voltage_therm_graph, height="446px", key="711") - # st_echarts(options=voltage_therm_graph, height="446px", key="712") - # st_echarts(options=voltage_therm_graph, height="446px", key="713") - # st_echarts(options=voltage_therm_graph, height="446px", key="714") - # st_echarts(options=voltage_therm_graph, height="446px", key="715") - # st_echarts(options=voltage_therm_graph, height="446px", key="716") - # st_echarts(options=voltage_therm_graph, height="446px", key="717") - # st_echarts(options=voltage_therm_graph, height="446px", key="718") - # st_echarts(options=voltage_therm_graph, height="446px", key="719") - # st_echarts(options=voltage_therm_graph, height="446px", key="720") - # st_echarts(options=voltage_therm_graph, height="446px", key="721") - # st_echarts(options=voltage_therm_graph, height="446px", key="722") - # st_echarts(options=voltage_therm_graph, height="446px", key="723") - # st_echarts(options=voltage_therm_graph, height="446px", key="724") - # st_echarts(options=voltage_therm_graph, height="446px", key="725") - # st_echarts(options=voltage_therm_graph, height="446px", key="726") - # st_echarts(options=voltage_therm_graph, height="446px", key="727") - # st_echarts(options=voltage_therm_graph, height="446px", key="728") - # st_echarts(options=voltage_therm_graph, height="446px", key="729") - # st_echarts(options=voltage_therm_graph, height="446px", key="730") - # st_echarts(options=voltage_therm_graph, height="446px", key="741") - # st_echarts(options=voltage_therm_graph, height="446px", key="742") - # st_echarts(options=voltage_therm_graph, height="446px", key="743") - # st_echarts(options=voltage_therm_graph, height="446px", key="744") - # st_echarts(options=voltage_therm_graph, height="446px", key="745") - # st_echarts(options=voltage_therm_graph, height="446px", key="746") - # st_echarts(options=voltage_therm_graph, height="446px", key="747") - # st_echarts(options=voltage_therm_graph, height="446px", key="748") - # st_echarts(options=voltage_therm_graph, height="446px", key="749") - # st_echarts(options=voltage_therm_graph, height="446px", key="750") - # st_echarts(options=voltage_therm_graph, height="446px", key="761") - # st_echarts(options=voltage_therm_graph, height="446px", key="762") - # st_echarts(options=voltage_therm_graph, height="446px", key="763") - # st_echarts(options=voltage_therm_graph, height="446px", key="764") - # st_echarts(options=voltage_therm_graph, height="446px", key="765") - # st_echarts(options=voltage_therm_graph, height="446px", key="766") - # st_echarts(options=voltage_therm_graph, height="446px", key="767") - # st_echarts(options=voltage_therm_graph, height="446px", key="768") - # st_echarts(options=voltage_therm_graph, height="446px", key="769") - # st_echarts(options=voltage_therm_graph, height="446px", key="770") - # st_echarts(options=voltage_therm_graph, height="446px", key="781") - # st_echarts(options=voltage_therm_graph, height="446px", key="782") - # st_echarts(options=voltage_therm_graph, height="446px", key="783") - # st_echarts(options=voltage_therm_graph, height="446px", key="784") - # st_echarts(options=voltage_therm_graph, height="446px", key="785") - # st_echarts(options=voltage_therm_graph, height="446px", key="786") - # st_echarts(options=voltage_therm_graph, height="446px", key="787") - # st_echarts(options=voltage_therm_graph, height="446px", key="788") - # st_echarts(options=voltage_therm_graph, height="446px", key="789") - # st_echarts(options=voltage_therm_graph, height="446px", key="790") - # st_echarts(options=voltage_therm_graph, height="446px", key="791") - # st_echarts(options=voltage_therm_graph, height="446px", key="792") - # st_echarts(options=voltage_therm_graph, height="446px", key="793") - # st_echarts(options=voltage_therm_graph, height="446px", key="794") - # st_echarts(options=voltage_therm_graph, height="446px", key="795") - # st_echarts(options=voltage_therm_graph, height="446px", key="796") - # st_echarts(options=voltage_therm_graph, height="446px", key="797") - # st_echarts(options=voltage_therm_graph, height="446px", key="798") - # st_echarts(options=voltage_therm_graph, height="446px", key="799") - # st_echarts(options=voltage_therm_graph, height="446px", key="800") - # st_echarts(options=voltage_therm_graph, height="446px", key="801") - # st_echarts(options=voltage_therm_graph, height="446px", key="802") - # st_echarts(options=voltage_therm_graph, height="446px", key="803") - # st_echarts(options=voltage_therm_graph, height="446px", key="804") - # st_echarts(options=voltage_therm_graph, height="446px", key="805") - # st_echarts(options=voltage_therm_graph, height="446px", key="806") - # st_echarts(options=voltage_therm_graph, height="446px", key="807") - # st_echarts(options=voltage_therm_graph, height="446px", key="808") - # st_echarts(options=voltage_therm_graph, height="446px", key="809") - # st_echarts(options=voltage_therm_graph, height="446px", key="810") - # st_echarts(options=voltage_therm_graph, height="446px", key="811") - # st_echarts(options=voltage_therm_graph, height="446px", key="812") - # st_echarts(options=voltage_therm_graph, height="446px", key="813") - # st_echarts(options=voltage_therm_graph, height="446px", key="814") - # st_echarts(options=voltage_therm_graph, height="446px", key="815") - # st_echarts(options=voltage_therm_graph, height="446px", key="816") - # st_echarts(options=voltage_therm_graph, height="446px", key="817") - # st_echarts(options=voltage_therm_graph, height="446px", key="818") - # st_echarts(options=voltage_therm_graph, height="446px", key="819") - # st_echarts(options=voltage_therm_graph, height="446px", key="820") - # st_echarts(options=voltage_therm_graph, height="446px", key="821") - # st_echarts(options=voltage_therm_graph, height="446px", key="822") - # st_echarts(options=voltage_therm_graph, height="446px", key="823") - # st_echarts(options=voltage_therm_graph, height="446px", key="824") - # st_echarts(options=voltage_therm_graph, height="446px", key="825") - # st_echarts(options=voltage_therm_graph, height="446px", key="826") - # st_echarts(options=voltage_therm_graph, height="446px", key="827") - # st_echarts(options=voltage_therm_graph, height="446px", key="828") - # st_echarts(options=voltage_therm_graph, height="446px", key="829") - # st_echarts(options=voltage_therm_graph, height="446px", key="830") - # st_echarts(options=voltage_therm_graph, height="446px", key="841") - # st_echarts(options=voltage_therm_graph, height="446px", key="842") - # st_echarts(options=voltage_therm_graph, height="446px", key="843") - # st_echarts(options=voltage_therm_graph, height="446px", key="844") - # st_echarts(options=voltage_therm_graph, height="446px", key="845") - # st_echarts(options=voltage_therm_graph, height="446px", key="846") - # st_echarts(options=voltage_therm_graph, height="446px", key="847") - # st_echarts(options=voltage_therm_graph, height="446px", key="848") - # st_echarts(options=voltage_therm_graph, height="446px", key="849") - # st_echarts(options=voltage_therm_graph, height="446px", key="850") - # st_echarts(options=voltage_therm_graph, height="446px", key="861") - # st_echarts(options=voltage_therm_graph, height="446px", key="862") - # st_echarts(options=voltage_therm_graph, height="446px", key="863") - # st_echarts(options=voltage_therm_graph, height="446px", key="864") - # st_echarts(options=voltage_therm_graph, height="446px", key="865") - # st_echarts(options=voltage_therm_graph, height="446px", key="866") - # st_echarts(options=voltage_therm_graph, height="446px", key="867") - # st_echarts(options=voltage_therm_graph, height="446px", key="868") - # st_echarts(options=voltage_therm_graph, height="446px", key="869") - # st_echarts(options=voltage_therm_graph, height="446px", key="870") - # st_echarts(options=voltage_therm_graph, height="446px", key="881") - # st_echarts(options=voltage_therm_graph, height="446px", key="882") - # st_echarts(options=voltage_therm_graph, height="446px", key="883") - # st_echarts(options=voltage_therm_graph, height="446px", key="884") - # st_echarts(options=voltage_therm_graph, height="446px", key="885") - # st_echarts(options=voltage_therm_graph, height="446px", key="886") - # st_echarts(options=voltage_therm_graph, height="446px", key="887") - # st_echarts(options=voltage_therm_graph, height="446px", key="888") - # st_echarts(options=voltage_therm_graph, height="446px", key="889") - # st_echarts(options=voltage_therm_graph, height="446px", key="890") - # st_echarts(options=voltage_therm_graph, height="446px", key="891") - # st_echarts(options=voltage_therm_graph, height="446px", key="892") - # st_echarts(options=voltage_therm_graph, height="446px", key="893") - # st_echarts(options=voltage_therm_graph, height="446px", key="894") - # st_echarts(options=voltage_therm_graph, height="446px", key="895") - # st_echarts(options=voltage_therm_graph, height="446px", key="896") - # st_echarts(options=voltage_therm_graph, height="446px", key="897") - # st_echarts(options=voltage_therm_graph, height="446px", key="898") - # st_echarts(options=voltage_therm_graph, height="446px", key="899") - # st_echarts(options=voltage_therm_graph, height="446px", key="900") - # st_echarts(options=voltage_therm_graph, height="446px", key="901") - # st_echarts(options=voltage_therm_graph, height="446px", key="902") - # st_echarts(options=voltage_therm_graph, height="446px", key="903") - # st_echarts(options=voltage_therm_graph, height="446px", key="904") - # st_echarts(options=voltage_therm_graph, height="446px", key="905") - # st_echarts(options=voltage_therm_graph, height="446px", key="906") - # st_echarts(options=voltage_therm_graph, height="446px", key="907") - # st_echarts(options=voltage_therm_graph, height="446px", key="908") - # st_echarts(options=voltage_therm_graph, height="446px", key="909") - # st_echarts(options=voltage_therm_graph, height="446px", key="910") - # st_echarts(options=voltage_therm_graph, height="446px", key="911") - # st_echarts(options=voltage_therm_graph, height="446px", key="912") - # st_echarts(options=voltage_therm_graph, height="446px", key="913") - # st_echarts(options=voltage_therm_graph, height="446px", key="914") - # st_echarts(options=voltage_therm_graph, height="446px", key="915") - # st_echarts(options=voltage_therm_graph, height="446px", key="916") - # st_echarts(options=voltage_therm_graph, height="446px", key="917") - # st_echarts(options=voltage_therm_graph, height="446px", key="918") - # st_echarts(options=voltage_therm_graph, height="446px", key="919") - # st_echarts(options=voltage_therm_graph, height="446px", key="920") - # st_echarts(options=voltage_therm_graph, height="446px", key="921") - # st_echarts(options=voltage_therm_graph, height="446px", key="922") - # st_echarts(options=voltage_therm_graph, height="446px", key="923") - # st_echarts(options=voltage_therm_graph, height="446px", key="924") - # st_echarts(options=voltage_therm_graph, height="446px", key="925") - # st_echarts(options=voltage_therm_graph, height="446px", key="926") - # st_echarts(options=voltage_therm_graph, height="446px", key="927") - # st_echarts(options=voltage_therm_graph, height="446px", key="928") - # st_echarts(options=voltage_therm_graph, height="446px", key="929") - # st_echarts(options=voltage_therm_graph, height="446px", key="930") - # st_echarts(options=voltage_therm_graph, height="446px", key="941") - # st_echarts(options=voltage_therm_graph, height="446px", key="942") - # st_echarts(options=voltage_therm_graph, height="446px", key="943") - # st_echarts(options=voltage_therm_graph, height="446px", key="944") - # st_echarts(options=voltage_therm_graph, height="446px", key="945") - # st_echarts(options=voltage_therm_graph, height="446px", key="946") - # st_echarts(options=voltage_therm_graph, height="446px", key="947") - # st_echarts(options=voltage_therm_graph, height="446px", key="948") - # st_echarts(options=voltage_therm_graph, height="446px", key="949") - # st_echarts(options=voltage_therm_graph, height="446px", key="950") - # st_echarts(options=voltage_therm_graph, height="446px", key="961") - # st_echarts(options=voltage_therm_graph, height="446px", key="962") - # st_echarts(options=voltage_therm_graph, height="446px", key="963") - # st_echarts(options=voltage_therm_graph, height="446px", key="964") - # st_echarts(options=voltage_therm_graph, height="446px", key="965") - # st_echarts(options=voltage_therm_graph, height="446px", key="966") - # st_echarts(options=voltage_therm_graph, height="446px", key="967") - # st_echarts(options=voltage_therm_graph, height="446px", key="968") - # st_echarts(options=voltage_therm_graph, height="446px", key="969") - # st_echarts(options=voltage_therm_graph, height="446px", key="970") - # st_echarts(options=voltage_therm_graph, height="446px", key="981") - # st_echarts(options=voltage_therm_graph, height="446px", key="982") - # st_echarts(options=voltage_therm_graph, height="446px", key="983") - # st_echarts(options=voltage_therm_graph, height="446px", key="984") - # st_echarts(options=voltage_therm_graph, height="446px", key="985") - # st_echarts(options=voltage_therm_graph, height="446px", key="986") - # st_echarts(options=voltage_therm_graph, height="446px", key="987") - # st_echarts(options=voltage_therm_graph, height="446px", key="988") - # st_echarts(options=voltage_therm_graph, height="446px", key="989") - # st_echarts(options=voltage_therm_graph, height="446px", key="990") - # st_echarts(options=voltage_therm_graph, height="446px", key="991") - # st_echarts(options=voltage_therm_graph, height="446px", key="992") - # st_echarts(options=voltage_therm_graph, height="446px", key="993") - # st_echarts(options=voltage_therm_graph, height="446px", key="994") - # st_echarts(options=voltage_therm_graph, height="446px", key="995") - # st_echarts(options=voltage_therm_graph, height="446px", key="996") - # st_echarts(options=voltage_therm_graph, height="446px", key="997") - # st_echarts(options=voltage_therm_graph, height="446px", key="998") - # st_echarts(options=voltage_therm_graph, height="446px", key="999") - # st_echarts(options=voltage_therm_graph, height="446px", key="1000") - # st_echarts(options=voltage_therm_graph, height="446px", key="1001") - # st_echarts(options=voltage_therm_graph, height="446px", key="1002") - # st_echarts(options=voltage_therm_graph, height="446px", key="1003") - # st_echarts(options=voltage_therm_graph, height="446px", key="1004") - # st_echarts(options=voltage_therm_graph, height="446px", key="1005") - # st_echarts(options=voltage_therm_graph, height="446px", key="1006") - # st_echarts(options=voltage_therm_graph, height="446px", key="1007") - # st_echarts(options=voltage_therm_graph, height="446px", key="1008") - # st_echarts(options=voltage_therm_graph, height="446px", key="1009") - # st_echarts(options=voltage_therm_graph, height="446px", key="1010") - # st_echarts(options=voltage_therm_graph, height="446px", key="1011") - # st_echarts(options=voltage_therm_graph, height="446px", key="1012") - # st_echarts(options=voltage_therm_graph, height="446px", key="1013") - # st_echarts(options=voltage_therm_graph, height="446px", key="1014") - # st_echarts(options=voltage_therm_graph, height="446px", key="1015") - # st_echarts(options=voltage_therm_graph, height="446px", key="1016") - # st_echarts(options=voltage_therm_graph, height="446px", key="1017") - # st_echarts(options=voltage_therm_graph, height="446px", key="1018") - # st_echarts(options=voltage_therm_graph, height="446px", key="1019") - # st_echarts(options=voltage_therm_graph, height="446px", key="1020") - # st_echarts(options=voltage_therm_graph, height="446px", key="1021") - # st_echarts(options=voltage_therm_graph, height="446px", key="1022") - # st_echarts(options=voltage_therm_graph, height="446px", key="1023") - # st_echarts(options=voltage_therm_graph, height="446px", key="1024") - # st_echarts(options=voltage_therm_graph, height="446px", key="1025") - # st_echarts(options=voltage_therm_graph, height="446px", key="1026") - # st_echarts(options=voltage_therm_graph, height="446px", key="1027") - # st_echarts(options=voltage_therm_graph, height="446px", key="1028") - # st_echarts(options=voltage_therm_graph, height="446px", key="1029") - # st_echarts(options=voltage_therm_graph, height="446px", key="1030") - # st_echarts(options=voltage_therm_graph, height="446px", key="1041") - # st_echarts(options=voltage_therm_graph, height="446px", key="1042") - # st_echarts(options=voltage_therm_graph, height="446px", key="1043") - # st_echarts(options=voltage_therm_graph, height="446px", key="1044") - # st_echarts(options=voltage_therm_graph, height="446px", key="1045") - # st_echarts(options=voltage_therm_graph, height="446px", key="1046") - # st_echarts(options=voltage_therm_graph, height="446px", key="1047") - # st_echarts(options=voltage_therm_graph, height="446px", key="1048") - # st_echarts(options=voltage_therm_graph, height="446px", key="1049") - # st_echarts(options=voltage_therm_graph, height="446px", key="1050") - # st_echarts(options=voltage_therm_graph, height="446px", key="1061") - # st_echarts(options=voltage_therm_graph, height="446px", key="1062") - # st_echarts(options=voltage_therm_graph, height="446px", key="1063") - # st_echarts(options=voltage_therm_graph, height="446px", key="1064") - # st_echarts(options=voltage_therm_graph, height="446px", key="1065") - # st_echarts(options=voltage_therm_graph, height="446px", key="1066") - # st_echarts(options=voltage_therm_graph, height="446px", key="1067") - # st_echarts(options=voltage_therm_graph, height="446px", key="1068") - # st_echarts(options=voltage_therm_graph, height="446px", key="1069") - # st_echarts(options=voltage_therm_graph, height="446px", key="1070") - # st_echarts(options=voltage_therm_graph, height="446px", key="1081") - # st_echarts(options=voltage_therm_graph, height="446px", key="1082") - # st_echarts(options=voltage_therm_graph, height="446px", key="1083") - # st_echarts(options=voltage_therm_graph, height="446px", key="1084") - # st_echarts(options=voltage_therm_graph, height="446px", key="1085") - # st_echarts(options=voltage_therm_graph, height="446px", key="1086") - # st_echarts(options=voltage_therm_graph, height="446px", key="1087") - # st_echarts(options=voltage_therm_graph, height="446px", key="1088") - # st_echarts(options=voltage_therm_graph, height="446px", key="1089") - # st_echarts(options=voltage_therm_graph, height="446px", key="1090") - # st_echarts(options=voltage_therm_graph, height="446px", key="1091") - # st_echarts(options=voltage_therm_graph, height="446px", key="1092") - # st_echarts(options=voltage_therm_graph, height="446px", key="1093") - # st_echarts(options=voltage_therm_graph, height="446px", key="1094") - # st_echarts(options=voltage_therm_graph, height="446px", key="1095") - # st_echarts(options=voltage_therm_graph, height="446px", key="1096") - # st_echarts(options=voltage_therm_graph, height="446px", key="1097") - # st_echarts(options=voltage_therm_graph, height="446px", key="1098") - # st_echarts(options=voltage_therm_graph, height="446px", key="1099") - # st_echarts(options=voltage_therm_graph, height="446px", key="1100") - - - - # Logging Settings section in right column - with st.container(border=True): - st.header("Logging Settings") - logging_left_column, logging_right_column = st.columns(2) - with logging_left_column: - enum_selectbox( - panel, - label="Logging Mode", - value=LoggingMode.OFF, - disabled=panel.get_value("is_running", False), - key="logging_mode", - ) - with logging_right_column: - left_sub_column, right_sub_column = st.columns([3, 1]) - with left_sub_column: - tdms_file_path = st.text_input( - label="TDMS File Path", - disabled=panel.get_value("is_running", False), - value="data.tdms", - key="tdms_file_path", - ) From 771fad5ce94eb66805eb23cf73f6df14ce26fa6a Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Fri, 1 Aug 2025 14:25:43 -0500 Subject: [PATCH 69/76] revert changes --- .../nidaqmx_continuous_analog_input.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index 94432d8e..db4abb04 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -6,14 +6,13 @@ import nidaqmx from nidaqmx.constants import ( AcquisitionType, + TerminalConfiguration, CJCSource, - LoggingMode, - LoggingOperation, TemperatureUnits, - TerminalConfiguration, ThermocoupleType, + LoggingMode, + LoggingOperation, ) -from nidaqmx.errors import DaqError import nipanel @@ -21,8 +20,6 @@ panel = nipanel.create_streamlit_panel(panel_script_path) 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)") @@ -82,9 +79,5 @@ task.stop() panel.set_value("is_running", False) -except DaqError as e: - daq_error = str(e) - print(daq_error) - panel.set_value("daq_error", daq_error) except KeyboardInterrupt: pass \ No newline at end of file From f0b3056074e124b05ed76849f0520b8cb2d9276e Mon Sep 17 00:00:00 2001 From: DilmiWickramanayake <155610400+DilmiWickramanayake@users.noreply.github.com> Date: Fri, 1 Aug 2025 14:26:12 -0500 Subject: [PATCH 70/76] Update nidaqmx_continuous_analog_input.py --- .../nidaqmx_continuous_analog_input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py index db4abb04..ec089ad5 100644 --- a/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py +++ b/examples/nidaqmx/nidaqmx_continuous_analog_input/nidaqmx_continuous_analog_input.py @@ -80,4 +80,4 @@ panel.set_value("is_running", False) except KeyboardInterrupt: - pass \ No newline at end of file + pass From 2e25548ca2eea88077ff9b77803b6ba5a4cbe5fa Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 4 Aug 2025 07:33:04 -0500 Subject: [PATCH 71/76] fix lint error --- .../niscope_binary_acquisition_panel.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py index 5b854d99..51f0f725 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py @@ -1,6 +1,5 @@ """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 @@ -46,7 +45,12 @@ f"There was an error running the script. Fix the issue and re-run niscope_binary_acquisition.py \n\n {panel.get_value('daq_error', '')}" ) - st.text_input(label="Resource Name", value="Dev1", key="resource_name", disabled=panel.get_value("is_running", False)) + st.text_input( + label="Resource Name", + value="Dev1", + key="resource_name", + disabled=panel.get_value("is_running", False), + ) st.number_input( "Channel", value=0, @@ -89,7 +93,7 @@ "Binary Data Size", options=[8, 16, 32], disabled=panel.get_value("is_running", False), - key = "data_size" + key="data_size", ) st.number_input( "Actual Binary Data Size", From 789c1b9e0aa5708de640d7fecbaca86ff1dbfbb1 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 4 Aug 2025 07:45:09 -0500 Subject: [PATCH 72/76] fix mypy errors --- .../niscope_binary_acquisition.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index 115a0c20..ae8ac85b 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -47,18 +47,15 @@ with session.initiate(): data_size = panel.get_value("data_size", 8) + wfm: np.ndarray[Any, Any] + if data_size == 8: - wfm: np.ndarray[Any, np.dtype[np.int8]] = np.ndarray( # type: ignore - 1000 * 1000, dtype=np.int8 - ) + wfm = np.ndarray(1000 * 1000, dtype=np.int8) + elif data_size == 16: - wfm: np.ndarray[Any, np.dtype[np.int16]] = np.ndarray( # type: ignore - 1000 * 1000, dtype=np.int16 - ) + wfm = np.ndarray(1000 * 1000, dtype=np.int16) else: - wfm: np.ndarray[Any, np.dtype[np.int32]] = np.ndarray( - 1000 * 1000, dtype=np.int32 - ) + wfm = np.ndarray(1000 * 1000, dtype=np.int32) waveforms = session.channels[panel.get_value("channel", 0)].fetch_into( relative_to=niscope.FetchRelativeTo.READ_POINTER, From 34bc778760db6f7a2d02451c01fcc336f6817a0b Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 4 Aug 2025 09:01:04 -0500 Subject: [PATCH 73/76] resolved changes --- .../niscope_binary_acquisition.py | 2 +- .../niscope_binary_acquisition_panel.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index ae8ac85b..1b73abf0 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -57,7 +57,7 @@ else: wfm = np.ndarray(1000 * 1000, dtype=np.int32) - waveforms = session.channels[panel.get_value("channel", 0)].fetch_into( + waveforms = session.channels[panel.get_value("channel_number", 0)].fetch_into( relative_to=niscope.FetchRelativeTo.READ_POINTER, offset=0, timeout=hightime.timedelta(seconds=5.0), diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py index 51f0f725..bcfed62b 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py @@ -1,12 +1,12 @@ -"""Streamlit visualization script to display data acquired by nidaqmx_analog_input_filtering.py.""" +"""Streamlit dashboard for visualizing NI-SCOPE waveform data in real time.""" import streamlit as st from streamlit_echarts import st_echarts import nipanel -st.set_page_config(page_title="NiSCOPE Binary", page_icon="📈", layout="wide") -st.title("NiScope Binary Acquisition") +st.set_page_config(page_title="NI-SCOPE Binary Acquisition", page_icon="📈", layout="wide") +st.title("NI-SCOPE Binary Acquisition") panel = nipanel.get_streamlit_panel_accessor() left_col, right_col = st.columns(2) @@ -48,15 +48,15 @@ st.text_input( label="Resource Name", value="Dev1", - key="resource_name", disabled=panel.get_value("is_running", False), + key="resource_name", ) st.number_input( "Channel", value=0, step=1, disabled=panel.get_value("is_running", False), - key="channel", + key="channel_number", ) st.title("Vertical") From a71204879095bb9d988880f410f4e1363e7384fd Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Mon, 4 Aug 2025 10:20:46 -0500 Subject: [PATCH 74/76] changes to README.md --- examples/niscope/niscope_binary_acquisition/README.md | 6 +++--- .../niscope_binary_acquisition.py | 8 ++++---- .../niscope_binary_acquisition_panel.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/README.md b/examples/niscope/niscope_binary_acquisition/README.md index 475b1531..d704b9c9 100644 --- a/examples/niscope/niscope_binary_acquisition/README.md +++ b/examples/niscope/niscope_binary_acquisition/README.md @@ -1,14 +1,14 @@ 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. This example uses NI oscilloscopes/digitizers, which have the module numbering pattern _51xx_. One example is NI PXIe-5114. +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. This example uses NI oscilloscopes and digitizers like the NI PXIe-5114 ## Sample -This is a nipanel example that displays an interactive Streamlit app and updates and fetches data from device. +This is an nipanel example that displays an interactive Streamlit app and updates and fetches data from an NI device. ### Feature -Script demonstrates NIScope waveform data getting continuously acquired and being converted to binary data. +Script demonstrates waveform data getting continuously acquired and being converted to binary data. - Supports various data types ### Required Software diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index 1b73abf0..75897e83 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -21,7 +21,7 @@ panel.set_value("run_button", False) try: - panel.set_value("daq_error", "") + panel.set_value("scope_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)") @@ -102,9 +102,9 @@ panel.set_value("is_running", False) except Error as e: - daq_error = str(e) - print(daq_error) - panel.set_value("daq_error", daq_error) + scope_error = str(e) + print(scope_error) + panel.set_value("scope_error", scope_error) except KeyboardInterrupt: pass diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py index bcfed62b..fa9157f3 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition_panel.py @@ -38,11 +38,11 @@ with st.container(border=True): if panel.get_value("is_running", False): st.button(r"âšī¸ Stop", key="stop_button") - elif not panel.get_value("is_running", False) and panel.get_value("daq_error", "") == "": + elif not panel.get_value("is_running", False) and panel.get_value("scope_error", "") == "": run_button = st.button(r"â–ļī¸ Run", key="run_button") else: st.error( - f"There was an error running the script. Fix the issue and re-run niscope_binary_acquisition.py \n\n {panel.get_value('daq_error', '')}" + f"There was an error running the script. Fix the issue and re-run niscope_binary_acquisition.py \n\n {panel.get_value('scope_error', '')}" ) st.text_input( From 2b30a8f9bc45f973eda53d70460bfcf432fc7a91 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 5 Aug 2025 08:08:51 -0500 Subject: [PATCH 75/76] removed .fetch_array_measurement --- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index 75897e83..d1a01df4 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -69,11 +69,6 @@ panel.set_value("stop_button", False) while not panel.get_value("stop_button", False): - wfm_info = session.channels[0].fetch_array_measurement( - array_meas_function=ArrayMeasurement.ADD_CHANNELS, - num_records=1000, - meas_num_samples=1000, - ) gain = 0 offset = 0 for waveform in waveforms: From ce35c3449ea72859f297fa0f8b8b0f9561a7d553 Mon Sep 17 00:00:00 2001 From: Dilmi Wickramanayake Date: Tue, 5 Aug 2025 09:57:50 -0500 Subject: [PATCH 76/76] fixing lint errors --- .../niscope_binary_acquisition/niscope_binary_acquisition.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py index d1a01df4..afe93686 100644 --- a/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py +++ b/examples/niscope/niscope_binary_acquisition/niscope_binary_acquisition.py @@ -7,7 +7,6 @@ import hightime import niscope import numpy as np -from niscope.enums import ArrayMeasurement from niscope.errors import Error import nipanel