Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ poetry run sphinx-build docs docs/_build --builder html --fail-on-warning
start docs\_build\index.html
```

## Running examples

1. First, run the PythonPanelService (not part of this repo, provided seperately)
2. Run the command `poetry run python examples/sample/sample.py`
3. Open http://localhost:42001/panel-service/panels/sample_panel/ in your browser
4. If there is an error about missing imports (especially nipanel), execute this
command to install the dependencies into the venv: `C:\Users\mprosser\AppData\Local\Temp\python_panel_service_venv\Scripts\python.exe
-m pip install C:\dev\fireserp\nipanel-python[examples,dev]`, then restart the PythonPanelService and re-run sample.py.

You can see all running panels (and stop them) at: http://localhost:42001/panel-service/

# Debugging on the streamlit side

Debugging the measurement script can be done using standard Python debugging
Expand Down
15 changes: 15 additions & 0 deletions examples/all_types/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## All Types Example

This is an example for `nipanel` that demonstrates all supported data types

### Feature

- Demonstrates support for all data types

### Required Software

- Python 3.9 or later

### Usage

Run `poetry run python examples/all_types/all_types.py`
23 changes: 23 additions & 0 deletions examples/all_types/all_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""An example that demonstrates the supported data types for nipanel scripts."""

from pathlib import Path

from define_types import all_types_with_values

import nipanel

panel_script_path = Path(__file__).with_name("all_types_panel.py")
panel = nipanel.create_panel(panel_script_path)

print("Setting values")
for name, value in all_types_with_values.items():
print(f"{name:>15} {value}")
panel.set_value(name, value)

print()
print("Getting values")
for name in all_types_with_values.keys():
the_value = panel.get_value(name)
print(f"{name:>20} {the_value}")

print(f"Panel URL: {panel.panel_url}")
20 changes: 20 additions & 0 deletions examples/all_types/all_types_panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""A Streamlit visualization panel for the all_types.py example script."""

import streamlit as st
from define_types import all_types_with_values

import nipanel

panel = nipanel.initialize_panel()

st.set_page_config(page_title="All Types Example", page_icon="📊", layout="wide")
st.title("All Types Example")

for name in all_types_with_values.keys():
col1, col2 = st.columns([0.4, 0.6])

with col1:
st.write(name)

with col2:
st.write(panel.get_value(name))
62 changes: 62 additions & 0 deletions examples/all_types/define_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Define types."""

import enum

import numpy as np
from nitypes.scalar import Scalar
from nitypes.waveform import AnalogWaveform


class MyIntFlags(enum.IntFlag):
"""Example of an IntFlag enum."""

VALUE1 = 1
VALUE2 = 2
VALUE4 = 4


class MyIntEnum(enum.IntEnum):
"""Example of an IntEnum enum."""

VALUE10 = 10
VALUE20 = 20
VALUE30 = 30


class MyStrEnum(str, enum.Enum):
"""Example of a mixin string enum."""

VALUE1 = "value1"
VALUE2 = "value2"
VALUE3 = "value3"


all_types_with_values = {
# supported scalar types
"bool": True,
"bytes": b"robotext",
"float": 13.12,
"int": 42,
"str": "sample string",
# supported collection types
"bool_collection": [True, False, True],
"bytes_collection": [b"one", b"two", b"three"],
"float_collection": [1.1, 2.2, 3.3],
"int_collection": [1, 2, 3],
"str_collection": ["one", "two", "three"],
# supported enum and flag types
"intflags": MyIntFlags.VALUE1 | MyIntFlags.VALUE4,
"intenum": MyIntEnum.VALUE20,
"strenum": MyStrEnum.VALUE3,
"intflags_collection": [MyIntFlags.VALUE1, MyIntFlags.VALUE2, MyIntFlags.VALUE4],
"intenum_collection": [MyIntEnum.VALUE10, MyIntEnum.VALUE20, MyIntEnum.VALUE30],
"strenum_collection": [MyStrEnum.VALUE1, MyStrEnum.VALUE2, MyStrEnum.VALUE3],
# supported collections
"list": [1, 2, 3],
"tuple": (4, 5, 6),
"set": {7, 8, 9},
"frozenset": frozenset([10, 11, 12]),
# NI types
"nitypes_Scalar": Scalar(42, "m"),
"nitypes_AnalogWaveform": AnalogWaveform.from_array_1d(np.array([1.0, 2.0, 3.0])),
}
58 changes: 0 additions & 58 deletions examples/placeholder.py

This file was deleted.

2 changes: 1 addition & 1 deletion examples/sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ This is a nipanel example that displays an interactive Streamlit app and updates

### Usage

Run `poetry run examples/sample/sample.py`
Run `poetry run python examples/sample/sample.py`
10 changes: 3 additions & 7 deletions examples/sample/sample.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
"""This example demonstrates how to open/update a Streamlit application using nipanel package."""

import pathlib
from pathlib import Path

import nipanel

script_path = pathlib.Path(__file__)
panel_script_path = str(script_path.with_name("sample_panel.py"))
panel_script_path = Path(__file__).with_name("sample_panel.py")
panel = nipanel.create_panel(panel_script_path)

panel = nipanel.StreamlitPanel(
panel_id="sample_panel",
streamlit_script_path=panel_script_path,
)
panel.set_value("sample_string", "Hello, World!")
panel.set_value("sample_int", 42)
panel.set_value("sample_float", 3.14)
Expand Down
4 changes: 3 additions & 1 deletion examples/sample/sample_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

panel = nipanel.initialize_panel()

st.title("Sample Panel")

st.set_page_config(page_title="Sample Panel Example", page_icon="📊", layout="wide")
st.title("Sample Panel Example")

col1, col2 = st.columns([0.4, 0.6])

Expand Down
18 changes: 18 additions & 0 deletions examples/simple_graph/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Simple Graph Example

This example demonstrates using nipanel with Streamlit to display a dynamic sine wave using the `streamlit-echarts` library.

## Features

- Generates sine wave data with varying frequency
- Displays the data in an interactive chart using ECharts
- Updates automatically every 1 second
- Shows statistics about the displayed data

### Required Software

- Python 3.9 or later

### Usage

Run `poetry run python examples/simple_graph/simple_graph.py`
38 changes: 38 additions & 0 deletions examples/simple_graph/simple_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""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

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:
time_points = np.linspace(0, num_points, num_points)
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(1)

except KeyboardInterrupt:
print("Exiting...")
60 changes: 60 additions & 0 deletions examples/simple_graph/simple_graph_panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Example of displaying a sine wave using streamlit-echarts in a nipanel."""

import streamlit as st
from streamlit_echarts import st_echarts # type: ignore

from nipanel import initialize_panel


panel = initialize_panel()

st.set_page_config(page_title="Simple Graph Example", page_icon="📈", layout="wide")
st.title("Simple Graph Example")

time_points = panel.get_value("time_points", [0.0])
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}")
with col2:
st.metric("Frequency", f"{frequency:.2f} Hz")
with col3:
st.metric("Min Value", f"{min(sine_values):.3f}")
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
"title": {"text": "Sine Wave"},
"tooltip": {"trigger": "axis"},
"xAxis": {"type": "value", "name": "Time (s)", "nameLocation": "middle", "nameGap": 30},
"yAxis": {
"type": "value",
"name": "Amplitude",
"nameLocation": "middle",
"nameGap": 30,
},
"series": [
{
"data": data,
"type": "line",
"showSymbol": True,
"smooth": True,
"lineStyle": {"width": 2, "color": "#1f77b4"},
"areaStyle": {"color": "#1f77b4", "opacity": 0.3},
"name": "Sine Wave",
}
],
}

# Display the chart
st_echarts(options=options, height="400px")
Loading