Skip to content

Commit 5c1e492

Browse files
Mike ProsserMike Prosser
authored andcommitted
nipanel.enum_selectbox
1 parent acc1e9b commit 5c1e492

File tree

6 files changed

+83
-27
lines changed

6 files changed

+83
-27
lines changed

examples/all_types/all_types_panel.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""A Streamlit visualization panel for the all_types.py example script."""
22

3+
from enum import Enum
4+
35
import streamlit as st
46
from define_types import all_types_with_values
57

@@ -11,10 +13,25 @@
1113

1214
panel = nipanel.get_panel_accessor()
1315
for name in all_types_with_values.keys():
14-
col1, col2 = st.columns([0.4, 0.6])
16+
st.markdown("---")
17+
18+
default_value = all_types_with_values[name]
19+
col1, col2, col3 = st.columns([0.2, 0.2, 0.6])
1520

1621
with col1:
1722
st.write(name)
1823

1924
with col2:
25+
if isinstance(all_types_with_values[name], Enum):
26+
nipanel.enum_selectbox(panel, label=name, value=default_value, key=name)
27+
elif isinstance(all_types_with_values[name], bool):
28+
st.checkbox(label=name, value=default_value, key=name)
29+
elif isinstance(all_types_with_values[name], int):
30+
st.number_input(label=name, value=default_value, key=name)
31+
elif isinstance(all_types_with_values[name], float):
32+
st.number_input(label=name, value=default_value, key=name, format="%.2f")
33+
elif isinstance(all_types_with_values[name], str):
34+
st.text_input(label=name, value=default_value, key=name)
35+
36+
with col3:
2037
st.write(panel.get_value(name))

examples/all_types/define_types.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@ class MyStrEnum(str, enum.Enum):
3838
"float": 13.12,
3939
"int": 42,
4040
"str": "sample string",
41+
# supported enum and flag types
42+
"intflags": MyIntFlags.VALUE1 | MyIntFlags.VALUE4,
43+
"intenum": MyIntEnum.VALUE20,
44+
"strenum": MyStrEnum.VALUE3,
45+
# NI types
46+
"nitypes_Scalar": Scalar(42, "m"),
47+
"nitypes_AnalogWaveform": AnalogWaveform.from_array_1d(np.array([1.0, 2.0, 3.0])),
4148
# supported collection types
4249
"bool_collection": [True, False, True],
4350
"bytes_collection": [b"one", b"two", b"three"],
4451
"float_collection": [1.1, 2.2, 3.3],
4552
"int_collection": [1, 2, 3],
4653
"str_collection": ["one", "two", "three"],
47-
# supported enum and flag types
48-
"intflags": MyIntFlags.VALUE1 | MyIntFlags.VALUE4,
49-
"intenum": MyIntEnum.VALUE20,
50-
"strenum": MyStrEnum.VALUE3,
5154
"intflags_collection": [MyIntFlags.VALUE1, MyIntFlags.VALUE2, MyIntFlags.VALUE4],
5255
"intenum_collection": [MyIntEnum.VALUE10, MyIntEnum.VALUE20, MyIntEnum.VALUE30],
5356
"strenum_collection": [MyStrEnum.VALUE1, MyStrEnum.VALUE2, MyStrEnum.VALUE3],
@@ -56,9 +59,6 @@ class MyStrEnum(str, enum.Enum):
5659
"tuple": (4, 5, 6),
5760
"set": {7, 8, 9},
5861
"frozenset": frozenset([10, 11, 12]),
59-
# NI types
60-
"nitypes_Scalar": Scalar(42, "m"),
61-
"nitypes_AnalogWaveform": AnalogWaveform.from_array_1d(np.array([1.0, 2.0, 3.0])),
6262
# supported 2D collections
6363
"list_list_float": [[1.0, 2.0], [3.0, 4.0]],
6464
"tuple_tuple_float": ((1.0, 2.0), (3.0, 4.0)),

examples/simple_graph/simple_graph.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,14 @@
2121

2222
# Generate and update the sine wave data periodically
2323
while True:
24-
# not-found values need to be performant
25-
not_found = panel.get_value("no_such_value", "Hello, World!")
26-
27-
amplitude_enum = panel.get_value("amplitude_enum", AmplitudeEnum.SMALL)
24+
amplitude = panel.get_value("amplitude", AmplitudeEnum.SMALL)
2825
base_frequency = panel.get_value("base_frequency", 1.0)
2926

3027
# Slowly vary the total frequency for a more dynamic visualization
3128
frequency = base_frequency + 0.5 * math.sin(time.time() / 5.0)
3229

3330
time_points = np.linspace(0, num_points, num_points)
34-
sine_values = amplitude_enum.value * np.sin(frequency * time_points)
31+
sine_values = amplitude.value * np.sin(frequency * time_points)
3532

3633
panel.set_value("frequency", frequency)
3734
panel.set_value("time_points", time_points.tolist())

examples/simple_graph/simple_graph_panel.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,16 @@
1212
col1, col2, col3, col4, col5, col6 = st.columns(6)
1313

1414
panel = nipanel.get_panel_accessor()
15+
frequency = panel.get_value("frequency", 0.0)
16+
time_points = panel.get_value("time_points", [0.0])
17+
sine_values = panel.get_value("sine_values", [0.0])
1518

1619
with col1:
17-
amplitude_tuple = st.selectbox(
18-
"Amplitude",
19-
options=[(e.name, e.value) for e in AmplitudeEnum],
20-
format_func=lambda x: x[0],
21-
index=0,
22-
)
23-
amplitude_enum = AmplitudeEnum[amplitude_tuple[0]]
24-
panel.set_value("amplitude_enum", amplitude_enum)
20+
nipanel.enum_selectbox(panel, label="Amplitude", value=AmplitudeEnum.MEDIUM, key="amplitude")
2521
with col2:
26-
base_frequency = st.number_input("Base Frequency", value=1.0, step=0.1, key="base_frequency")
27-
22+
st.number_input("Base Frequency", value=1.0, step=0.5, key="base_frequency")
2823
with col3:
29-
frequency = panel.get_value("frequency", 0.0)
3024
st.metric("Frequency", f"{frequency:.2f} Hz")
31-
32-
time_points = panel.get_value("time_points", [0.0])
33-
sine_values = panel.get_value("sine_values", [0.0])
3425
with col4:
3526
st.metric("Min Value", f"{min(sine_values):.3f}")
3627
with col5:

src/nipanel/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from importlib.metadata import version
44

55
from nipanel._panel import Panel
6+
from nipanel._streamlit_components import enum_selectbox
67
from nipanel._streamlit_panel import StreamlitPanel
78
from nipanel._streamlit_panel_initializer import create_panel, get_panel_accessor
89
from nipanel._streamlit_panel_value_accessor import StreamlitPanelValueAccessor
910

1011
__all__ = [
1112
"create_panel",
13+
"enum_selectbox",
1214
"get_panel_accessor",
1315
"Panel",
1416
"StreamlitPanel",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Streamlit UI components for NI Panel."""
2+
3+
from enum import Enum
4+
from typing import TypeVar
5+
6+
import streamlit as st
7+
8+
from nipanel._panel_value_accessor import PanelValueAccessor
9+
10+
T = TypeVar("T", bound=Enum)
11+
12+
13+
def enum_selectbox(panel: PanelValueAccessor, label: str, value: T, key: str) -> T:
14+
"""Create a selectbox for an Enum.
15+
16+
The selectbox will display the names of all the enum values, and when a value is selected,
17+
that value will be stored in the panel under the specified key.
18+
19+
Args:
20+
panel: The panel
21+
label: Label to display for the selectbox
22+
value: The default enum value to select (also determines the specific enum type)
23+
key: Key to use for storing the enum value in the panel
24+
25+
Returns:
26+
The selected enum value of the same specific enum subclass as the input value
27+
"""
28+
enum_class = type(value)
29+
if not issubclass(enum_class, Enum):
30+
raise TypeError(f"Expected an Enum type, got {type(value)}")
31+
32+
options = [(e.name, e.value) for e in enum_class]
33+
34+
default_index = 0
35+
if value is not None:
36+
for i, (name, _) in enumerate(options):
37+
if name == value.name:
38+
default_index = i
39+
break
40+
41+
box_tuple = st.selectbox(
42+
label,
43+
options=options,
44+
format_func=lambda x: x[0],
45+
index=default_index,
46+
)
47+
enum_value = enum_class[box_tuple[0]]
48+
panel.set_value(key, enum_value)
49+
return enum_value

0 commit comments

Comments
 (0)