Public Access
Put sidebar controls in fragment to prevent page blanking
Both controls and display are now fragments, so slider changes don't trigger full page reruns.
This commit is contained in:
@@ -16,9 +16,6 @@ from py_dvt_ate.simulation.physics.engine import PhysicsEngine
|
||||
# History buffer size for charts
|
||||
HISTORY_SIZE = 500
|
||||
|
||||
# Simulation speed settings
|
||||
DEFAULT_TIME_MULTIPLIER = 10.0 # 10x faster than real-time
|
||||
|
||||
|
||||
@dataclass
|
||||
class SimulationHistory:
|
||||
@@ -48,17 +45,17 @@ def init_session_state() -> None:
|
||||
st.session_state.history = SimulationHistory()
|
||||
if "running" not in st.session_state:
|
||||
st.session_state.running = False
|
||||
if "time_multiplier" not in st.session_state:
|
||||
st.session_state.time_multiplier = DEFAULT_TIME_MULTIPLIER
|
||||
if "last_update" not in st.session_state:
|
||||
st.session_state.last_update = time.time()
|
||||
# Note: time_multiplier, temp_setpoint, input_voltage, output_enabled,
|
||||
# load_current are managed by their respective widgets via keys
|
||||
|
||||
|
||||
def step_simulation() -> None:
|
||||
"""Advance the simulation based on elapsed real time and multiplier."""
|
||||
engine: PhysicsEngine = st.session_state.engine
|
||||
history: SimulationHistory = st.session_state.history
|
||||
multiplier: float = st.session_state.time_multiplier
|
||||
multiplier: float = st.session_state.get("time_multiplier", 10)
|
||||
|
||||
# Calculate how much simulation time to advance
|
||||
current_time = time.time()
|
||||
@@ -87,10 +84,18 @@ def step_simulation() -> None:
|
||||
history.power_dissipation.append(electrical.power_dissipation)
|
||||
|
||||
|
||||
def display_controls() -> None:
|
||||
"""Display simulation control panel in sidebar."""
|
||||
def sync_engine_from_session_state() -> None:
|
||||
"""Sync engine parameters from session state (called by fragment)."""
|
||||
engine: PhysicsEngine = st.session_state.engine
|
||||
engine.set_chamber_setpoint(st.session_state.get("temp_setpoint", 25.0))
|
||||
engine.set_input_voltage(st.session_state.get("input_voltage", 5.0))
|
||||
engine.set_output_enabled(st.session_state.get("output_enabled", False))
|
||||
engine.set_load_current(st.session_state.get("load_current", 100.0) / 1000.0)
|
||||
|
||||
|
||||
@st.fragment
|
||||
def display_controls() -> None:
|
||||
"""Display simulation control panel in sidebar (as fragment to avoid full reruns)."""
|
||||
st.sidebar.header("Simulation Controls")
|
||||
|
||||
# Start/Stop button
|
||||
@@ -99,14 +104,12 @@ def display_controls() -> None:
|
||||
"Stop Simulation", type="primary", use_container_width=True
|
||||
):
|
||||
st.session_state.running = False
|
||||
st.rerun()
|
||||
else:
|
||||
if st.sidebar.button(
|
||||
"Start Simulation", type="primary", use_container_width=True
|
||||
):
|
||||
st.session_state.running = True
|
||||
st.session_state.last_update = time.time()
|
||||
st.rerun()
|
||||
|
||||
# Reset button
|
||||
if st.sidebar.button("Reset", use_container_width=True):
|
||||
@@ -114,27 +117,27 @@ def display_controls() -> None:
|
||||
st.session_state.history = SimulationHistory()
|
||||
st.session_state.running = False
|
||||
st.session_state.last_update = time.time()
|
||||
st.rerun()
|
||||
|
||||
st.sidebar.divider()
|
||||
|
||||
# Time multiplier
|
||||
st.sidebar.subheader("Simulation Speed")
|
||||
time_mult = st.sidebar.select_slider(
|
||||
st.sidebar.select_slider(
|
||||
"Time Multiplier",
|
||||
options=[1, 2, 5, 10, 20, 50, 100],
|
||||
value=int(st.session_state.time_multiplier),
|
||||
value=10,
|
||||
format_func=lambda x: f"{x}x",
|
||||
key="time_mult_slider",
|
||||
key="time_multiplier",
|
||||
)
|
||||
st.sidebar.caption(
|
||||
f"1 real second = {st.session_state.get('time_multiplier', 10)} simulation seconds"
|
||||
)
|
||||
st.session_state.time_multiplier = float(time_mult)
|
||||
st.sidebar.caption(f"1 real second = {time_mult} simulation seconds")
|
||||
|
||||
st.sidebar.divider()
|
||||
|
||||
# Temperature setpoint
|
||||
st.sidebar.subheader("Thermal Chamber")
|
||||
temp_setpoint = st.sidebar.slider(
|
||||
st.sidebar.slider(
|
||||
"Temperature Setpoint (C)",
|
||||
min_value=-40.0,
|
||||
max_value=125.0,
|
||||
@@ -142,13 +145,12 @@ def display_controls() -> None:
|
||||
step=5.0,
|
||||
key="temp_setpoint",
|
||||
)
|
||||
engine.set_chamber_setpoint(temp_setpoint)
|
||||
|
||||
st.sidebar.divider()
|
||||
|
||||
# Power supply controls
|
||||
st.sidebar.subheader("Power Supply")
|
||||
input_voltage = st.sidebar.slider(
|
||||
st.sidebar.slider(
|
||||
"Input Voltage (V)",
|
||||
min_value=0.0,
|
||||
max_value=12.0,
|
||||
@@ -156,20 +158,18 @@ def display_controls() -> None:
|
||||
step=0.1,
|
||||
key="input_voltage",
|
||||
)
|
||||
engine.set_input_voltage(input_voltage)
|
||||
|
||||
output_enabled = st.sidebar.toggle(
|
||||
st.sidebar.toggle(
|
||||
"Output Enabled",
|
||||
value=engine.is_output_enabled,
|
||||
value=False,
|
||||
key="output_enabled",
|
||||
)
|
||||
engine.set_output_enabled(output_enabled)
|
||||
|
||||
st.sidebar.divider()
|
||||
|
||||
# Load controls
|
||||
st.sidebar.subheader("Electronic Load")
|
||||
load_current_ma = st.sidebar.slider(
|
||||
st.sidebar.slider(
|
||||
"Load Current (mA)",
|
||||
min_value=0.0,
|
||||
max_value=500.0,
|
||||
@@ -177,7 +177,6 @@ def display_controls() -> None:
|
||||
step=10.0,
|
||||
key="load_current",
|
||||
)
|
||||
engine.set_load_current(load_current_ma / 1000.0)
|
||||
|
||||
|
||||
@st.fragment(run_every=0.1)
|
||||
@@ -186,6 +185,9 @@ def simulation_display() -> None:
|
||||
engine: PhysicsEngine = st.session_state.engine
|
||||
history: SimulationHistory = st.session_state.history
|
||||
|
||||
# Sync engine parameters from UI controls
|
||||
sync_engine_from_session_state()
|
||||
|
||||
# Step simulation if running
|
||||
if st.session_state.running:
|
||||
step_simulation()
|
||||
@@ -220,7 +222,7 @@ def simulation_display() -> None:
|
||||
st.metric(
|
||||
"Sim Time",
|
||||
f"{engine.simulation_time:.1f} s",
|
||||
delta=f"{status} @ {st.session_state.time_multiplier:.0f}x",
|
||||
delta=f"{status} @ {st.session_state.get('time_multiplier', 10):.0f}x",
|
||||
)
|
||||
|
||||
# Temperature chart
|
||||
|
||||
Reference in New Issue
Block a user