Rework radar system
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""Qt-free defaults derived from a radar profile and GUI history capacities."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from python_app.models.run_config_schema import RunConfigModel, ComboModel
|
||||
from python_app.models.gui_profile_schema import (
|
||||
GuiStateModel, GuiSwitchStateModel, GuiProcessingStateModel, GuiGprStateModel,
|
||||
GuiLegacyGprStateModel, GuiSar3dStateModel, GuiDataActionsStateModel,
|
||||
)
|
||||
|
||||
GUI_SAVE_HISTORY_LIMIT = 1000
|
||||
# Mirrors data_processor replay_history_limit, bounded further by SHM capacities.
|
||||
CPP_BSCAN_REPLAY_WINDOW = 50
|
||||
|
||||
|
||||
def format_combos_text_from_config(config: RunConfigModel) -> str:
|
||||
"""Render configured combos for UI text editor, keeping full matrix as empty."""
|
||||
if config.is_multi_device:
|
||||
return ",".join(
|
||||
f"{int(combo.input)}:{int(combo.output)}"
|
||||
for combo in config.build_runtime_combos()
|
||||
)
|
||||
combos = list(config.combos)
|
||||
full_combos = config.build_full_combos(config.input_switch.positions, config.output_switch.positions)
|
||||
if len(combos) == len(full_combos) and all(
|
||||
int(left.input) == int(right.input) and int(left.output) == int(right.output)
|
||||
for left, right in zip(combos, full_combos, strict=True)
|
||||
):
|
||||
return ""
|
||||
return ",".join(f"{int(combo.input)}:{int(combo.output)}" for combo in combos)
|
||||
|
||||
|
||||
def env_enabled(name: str) -> bool:
|
||||
return os.environ.get(name, "").strip().lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
def _positions(geometry: set[int], combos: set[int]) -> str:
|
||||
return ",".join(map(str, sorted(geometry & combos or geometry)))
|
||||
|
||||
|
||||
def default_gpr_visible_x_bounds_from_config(config: RunConfigModel) -> tuple[float, float]:
|
||||
"""Build default visible X-range for GPR object-only rendering."""
|
||||
x_values = [float(entry.x_m) for entry in config.gpr.tx_geometry]
|
||||
x_values.extend(float(entry.x_m) for entry in config.gpr.rx_geometry)
|
||||
if not x_values:
|
||||
return (-2.0, 2.0)
|
||||
margin_m = 2.0
|
||||
return (min(x_values) - margin_m, max(x_values) + margin_m)
|
||||
|
||||
|
||||
def cpp_bscan_replay_window_for_config(config: RunConfigModel) -> int:
|
||||
"""Return how many newest collections the C++ processor re-processes on a
|
||||
live B-scan settings change.
|
||||
|
||||
Deliberately reproduces `replay_history_limit()` in `data_processor.cpp`
|
||||
formula-for-formula. The ring capacities matter because `ShmRing` overwrites
|
||||
the oldest unread slot on overflow, so a replay burst must fit in the results
|
||||
ring for the GUI to receive all of it.
|
||||
|
||||
This is the single place to change if the replay window ever becomes
|
||||
configurable on the C++ side.
|
||||
"""
|
||||
return max(
|
||||
1,
|
||||
min(
|
||||
int(config.rings.preprocessed.capacity),
|
||||
int(config.rings.results.capacity),
|
||||
CPP_BSCAN_REPLAY_WINDOW,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def default_gui_state_for_config(config: RunConfigModel, project_root: Path) -> GuiStateModel:
|
||||
"""Build fallback GUI-only defaults for a stable run config."""
|
||||
default_combo = config.combos[0] if config.combos else ComboModel(input=0, output=0)
|
||||
default_mode = "single" if len(config.combos) == 1 else "text"
|
||||
inputs = _positions({entry.input_pos for entry in config.gpr.rx_geometry}, {combo.input for combo in config.combos})
|
||||
outputs = _positions({entry.output_pos for entry in config.gpr.tx_geometry}, {combo.output for combo in config.combos})
|
||||
default_gpr_x_min_m, default_gpr_x_max_m = default_gpr_visible_x_bounds_from_config(config)
|
||||
return GuiStateModel(
|
||||
switches=GuiSwitchStateModel(
|
||||
combo_mode=default_mode,
|
||||
combos_text=format_combos_text_from_config(config),
|
||||
single_input=str(int(default_combo.input)),
|
||||
single_output=str(int(default_combo.output)),
|
||||
),
|
||||
processing=GuiProcessingStateModel(
|
||||
gpr=GuiGprStateModel(
|
||||
input_positions=inputs,
|
||||
output_positions=outputs,
|
||||
visible_x_min_m=default_gpr_x_min_m,
|
||||
visible_x_max_m=default_gpr_x_max_m,
|
||||
),
|
||||
legacy_gpr=GuiLegacyGprStateModel(
|
||||
input_positions=inputs,
|
||||
output_positions=outputs,
|
||||
visible_x_min_m=default_gpr_x_min_m,
|
||||
visible_x_max_m=default_gpr_x_max_m,
|
||||
),
|
||||
sar3d=GuiSar3dStateModel(
|
||||
input_positions=inputs,
|
||||
output_positions=outputs,
|
||||
),
|
||||
),
|
||||
data_actions=GuiDataActionsStateModel(
|
||||
save_path=str(project_root / "python_app/data/snapshots"),
|
||||
),
|
||||
)
|
||||
Reference in New Issue
Block a user