translated to russian
This commit is contained in:
@ -65,13 +65,13 @@ class BScanProcessor(BaseProcessor):
|
||||
return [
|
||||
UIParameter(
|
||||
name="open_air",
|
||||
label="Open Air Reference",
|
||||
label="Референс открытого воздуха",
|
||||
type="toggle",
|
||||
value=cfg["open_air"],
|
||||
),
|
||||
UIParameter(
|
||||
name="axis",
|
||||
label="Axis",
|
||||
label="Ось",
|
||||
type="select",
|
||||
value=cfg["axis"],
|
||||
options={"choices": ["real", "abs", "phase"]},
|
||||
@ -85,45 +85,45 @@ class BScanProcessor(BaseProcessor):
|
||||
# ),
|
||||
UIParameter(
|
||||
name="cut",
|
||||
label="Cut (m)",
|
||||
label="Отсечка (м)",
|
||||
type="slider",
|
||||
value=cfg["cut"],
|
||||
options={"min": 0.0, "max": 2.0, "step": 0.001, "dtype": "float"},
|
||||
),
|
||||
UIParameter(
|
||||
name="max",
|
||||
label="Max Depth (m)",
|
||||
label="Макс. глубина (м)",
|
||||
type="slider",
|
||||
value=cfg["max"],
|
||||
options={"min": 0.1, "max": 5.0, "step": 0.1, "dtype": "float"},
|
||||
),
|
||||
UIParameter(
|
||||
name="gain",
|
||||
label="Gain Factor",
|
||||
label="Коэф. усиления",
|
||||
type="slider",
|
||||
value=cfg["gain"],
|
||||
options={"min": 0.0, "max": 3.0, "step": 0.1, "dtype": "float"},
|
||||
),
|
||||
UIParameter(
|
||||
name="start_freq",
|
||||
label="Start Frequency (MHz)",
|
||||
label="Нач. частота (МГц)",
|
||||
type="slider",
|
||||
value=cfg["start_freq"],
|
||||
options={"min": 100.0, "max": 8800.0, "step": 10.0, "dtype": "float"},
|
||||
),
|
||||
UIParameter(
|
||||
name="stop_freq",
|
||||
label="Stop Frequency (MHz)",
|
||||
label="Кон. частота (МГц)",
|
||||
type="slider",
|
||||
value=cfg["stop_freq"],
|
||||
options={"min": 100.0, "max": 8800.0, "step": 10.0, "dtype": "float"},
|
||||
),
|
||||
UIParameter(
|
||||
name="clear_history",
|
||||
label="Clear Plot History",
|
||||
label="Очистить историю",
|
||||
type="button",
|
||||
value=False,
|
||||
options={"action": "Clear accumulated plot history"},
|
||||
options={"action": "Очистить накопленную историю графика"},
|
||||
),
|
||||
]
|
||||
|
||||
@ -258,10 +258,10 @@ class BScanProcessor(BaseProcessor):
|
||||
return {
|
||||
"data": [],
|
||||
"layout": {
|
||||
"title": "B-Scan Analysis - Error",
|
||||
"title": "B-Scan анализ - Ошибка",
|
||||
"annotations": [
|
||||
{
|
||||
"text": f"Error: {processed_data['error']}",
|
||||
"text": f"Ошибка: {processed_data['error']}",
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"xref": "paper",
|
||||
@ -280,9 +280,9 @@ class BScanProcessor(BaseProcessor):
|
||||
return {
|
||||
"data": [],
|
||||
"layout": {
|
||||
"title": "B-Scan Analysis - No Data",
|
||||
"xaxis": {"title": "Sweep Number"},
|
||||
"yaxis": {"title": "Depth (m)"},
|
||||
"title": "B-Scan анализ - Нет данных",
|
||||
"xaxis": {"title": "Номер развертки"},
|
||||
"yaxis": {"title": "Глубина (м)"},
|
||||
"template": "plotly_dark",
|
||||
},
|
||||
}
|
||||
@ -316,11 +316,11 @@ class BScanProcessor(BaseProcessor):
|
||||
"y": y_coords,
|
||||
"z": z_values,
|
||||
"colorscale": colorscale,
|
||||
"colorbar": {"title": "Amplitude"},
|
||||
"colorbar": {"title": "Амплитуда"},
|
||||
"hovertemplate": (
|
||||
"Sweep: %{x}<br>"
|
||||
"Depth: %{y:.3f} m<br>"
|
||||
"Amplitude: %{z:.3f}<br>"
|
||||
"Развертка: %{x}<br>"
|
||||
"Глубина: %{y:.3f} м<br>"
|
||||
"Амплитуда: %{z:.3f}<br>"
|
||||
"<extra></extra>"
|
||||
),
|
||||
**heatmap_kwargs,
|
||||
@ -328,28 +328,28 @@ class BScanProcessor(BaseProcessor):
|
||||
|
||||
freq_start, freq_stop = processed_data.get("frequency_range", [0.0, 0.0])
|
||||
config_info = (
|
||||
f"Freq: {freq_start/1e6:.1f}-{freq_stop/1e6:.1f} MHz | "
|
||||
f"Gain: {self._config['gain']:.1f} | "
|
||||
f"Cut: {self._config['cut']:.3f} m | "
|
||||
f"Max: {self._config['max']:.1f} m | "
|
||||
f"Axis: {self._config['axis']} | "
|
||||
f"Sweeps: {len(history)}"
|
||||
f"Частота: {freq_start/1e6:.1f}-{freq_stop/1e6:.1f} МГц | "
|
||||
f"Усиление: {self._config['gain']:.1f} | "
|
||||
f"Отсечка: {self._config['cut']:.3f} м | "
|
||||
f"Макс глубина: {self._config['max']:.1f} м | "
|
||||
f"Ось: {self._config['axis']} | "
|
||||
f"Разверток: {len(history)}"
|
||||
)
|
||||
|
||||
if processed_data.get("reference_used", False):
|
||||
config_info += " | Open Air: ON"
|
||||
config_info += " | Открытый воздух: ВКЛ"
|
||||
|
||||
# if self._config["data_limitation"]:
|
||||
# config_info += f" | Limit: {self._config['data_limitation']}"
|
||||
|
||||
layout = {
|
||||
"title": f"B-Scan Heatmap - {config_info}",
|
||||
"xaxis": {"title": "Sweep Number", "side": "bottom"},
|
||||
"yaxis": {"title": "Depth (m)", "autorange": "reversed"},
|
||||
"title": f"B-Scan тепловая карта - {config_info}",
|
||||
"xaxis": {"title": "Номер развертки", "side": "bottom"},
|
||||
"yaxis": {"title": "Глубина (м)", "autorange": "reversed"},
|
||||
"hovermode": "closest",
|
||||
"height": 546,
|
||||
"template": "plotly_dark",
|
||||
"margin": {"t": 40, "r": 50, "b": 110, "l": 50},
|
||||
"margin": {"t": 40, "r": 50, "b": 110, "l": 50},
|
||||
"autosize": True
|
||||
}
|
||||
|
||||
|
||||
@ -137,7 +137,7 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
"y": mags_db,
|
||||
"type": "scatter",
|
||||
"mode": "lines",
|
||||
"name": f"|{parameter_type}| Magnitude",
|
||||
"name": f"|{parameter_type}| Амплитуда",
|
||||
"line": {"color": magnitude_color, "width": 2},
|
||||
"yaxis": "y",
|
||||
})
|
||||
@ -149,15 +149,15 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
"y": phases_deg,
|
||||
"type": "scatter",
|
||||
"mode": "lines",
|
||||
"name": f"∠{parameter_type} Phase",
|
||||
"name": f"∠{parameter_type} Фаза",
|
||||
"line": {"color": phase_color, "width": 2},
|
||||
"yaxis": "y2" if show_magnitude else "y",
|
||||
})
|
||||
|
||||
# Layout configuration
|
||||
layout = {
|
||||
"title": f"{parameter_type} Response",
|
||||
"xaxis": {"title": "Frequency (GHz)", "showgrid": True},
|
||||
"title": f"Отклик {parameter_type}",
|
||||
"xaxis": {"title": "Частота (ГГц)", "showgrid": True},
|
||||
"hovermode": "x unified",
|
||||
"showlegend": True,
|
||||
}
|
||||
@ -165,7 +165,7 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
# Configure y-axis based on what's shown
|
||||
if show_magnitude:
|
||||
y_axis_config = {
|
||||
"title": "Magnitude (dB)",
|
||||
"title": "Амплитуда (дБ)",
|
||||
"showgrid": True,
|
||||
"side": "left",
|
||||
"titlefont": {"color": magnitude_color},
|
||||
@ -183,7 +183,7 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
if show_magnitude:
|
||||
# Phase on second axis (radians converted to degrees, but displayed as -π to π)
|
||||
layout["yaxis2"] = {
|
||||
"title": "Phase (rad)",
|
||||
"title": "Фаза (рад)",
|
||||
"overlaying": "y",
|
||||
"side": "right",
|
||||
"showgrid": False,
|
||||
@ -194,7 +194,7 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
else:
|
||||
# Phase on primary axis if magnitude is hidden
|
||||
layout["yaxis"] = {
|
||||
"title": "Phase (rad)",
|
||||
"title": "Фаза (рад)",
|
||||
"showgrid": True,
|
||||
"side": "left",
|
||||
"range": [-180, 180], # -π to π in degrees
|
||||
@ -218,32 +218,32 @@ class MagnitudeProcessor(BaseProcessor):
|
||||
return [
|
||||
UIParameter(
|
||||
name="show_magnitude",
|
||||
label="Show Magnitude",
|
||||
label="Показать амплитуду",
|
||||
type="toggle",
|
||||
value=self._config.get("show_magnitude", True),
|
||||
),
|
||||
UIParameter(
|
||||
name="show_phase",
|
||||
label="Show Phase",
|
||||
label="Показать фазу",
|
||||
type="toggle",
|
||||
value=self._config.get("show_phase", False),
|
||||
),
|
||||
UIParameter(
|
||||
name="autoscale",
|
||||
label="Autoscale Y Axis",
|
||||
label="Автомасштаб оси Y",
|
||||
type="toggle",
|
||||
value=self._config.get("autoscale", False),
|
||||
),
|
||||
UIParameter(
|
||||
name="y_min",
|
||||
label="Y Axis Min (dB)",
|
||||
label="Мин. ось Y (дБ)",
|
||||
type="slider",
|
||||
value=self._config.get("y_min", -80),
|
||||
options={"min": -80, "max": 20, "step": 5, "dtype": "int"},
|
||||
),
|
||||
UIParameter(
|
||||
name="y_max",
|
||||
label="Y Axis Max (dB)",
|
||||
label="Макс. ось Y (дБ)",
|
||||
type="slider",
|
||||
value=self._config.get("y_max", 10),
|
||||
options={"min": -20, "max": 40, "step": 5, "dtype": "int"},
|
||||
|
||||
@ -105,19 +105,19 @@ class ProcessorWebSocketHandler:
|
||||
elif mtype == "get_processor_state":
|
||||
await self._handle_get_processor_state(websocket, message)
|
||||
else:
|
||||
await self._send_error(websocket, f"Unknown message type: {mtype!r}")
|
||||
await self._send_error(websocket, f"Неизвестный тип сообщения: {mtype!r}")
|
||||
except json.JSONDecodeError as json_error:
|
||||
logger.error("JSON decode error", raw_data=data[:200], error=str(json_error))
|
||||
await self._send_error(
|
||||
websocket,
|
||||
"Invalid JSON format",
|
||||
details=f"JSON parse error: {json_error}",
|
||||
"Неверный формат JSON",
|
||||
details=f"Ошибка парсинга JSON: {json_error}",
|
||||
source="websocket_handler",
|
||||
raw_data=data[:200] if len(data) <= 200 else f"{data[:200]}..."
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("Error handling websocket message")
|
||||
await self._send_error(websocket, f"Internal error: {exc}")
|
||||
await self._send_error(websocket, f"Внутренняя ошибка: {exc}")
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# Client commands
|
||||
@ -130,7 +130,7 @@ class ProcessorWebSocketHandler:
|
||||
config_updates = message.get("config_updates")
|
||||
|
||||
if not processor_id:
|
||||
await self._send_error(websocket, "processor_id is required")
|
||||
await self._send_error(websocket, "Требуется processor_id")
|
||||
return
|
||||
|
||||
try:
|
||||
@ -138,10 +138,10 @@ class ProcessorWebSocketHandler:
|
||||
if result:
|
||||
await websocket.send_text(json.dumps(self._result_to_message(processor_id, result)))
|
||||
else:
|
||||
await self._send_error(websocket, f"No result from processor {processor_id}")
|
||||
await self._send_error(websocket, f"Нет результата от процессора {processor_id}")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("Recalculation failed")
|
||||
await self._send_error(websocket, f"Recalculation failed: {exc}")
|
||||
await self._send_error(websocket, f"Пересчёт не удался: {exc}")
|
||||
|
||||
async def _handle_get_history(self, websocket: WebSocket, message: dict[str, Any]) -> None:
|
||||
"""
|
||||
@ -151,7 +151,7 @@ class ProcessorWebSocketHandler:
|
||||
limit = int(message.get("limit", 10))
|
||||
|
||||
if not processor_id:
|
||||
await self._send_error(websocket, "processor_id is required")
|
||||
await self._send_error(websocket, "Требуется processor_id")
|
||||
return
|
||||
|
||||
try:
|
||||
@ -172,7 +172,7 @@ class ProcessorWebSocketHandler:
|
||||
await websocket.send_text(json.dumps(response))
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("Error getting history")
|
||||
await self._send_error(websocket, f"Error getting history: {exc}")
|
||||
await self._send_error(websocket, f"Ошибка получения истории: {exc}")
|
||||
|
||||
async def _handle_load_history(self, websocket: WebSocket, message: dict[str, Any]) -> None:
|
||||
"""
|
||||
@ -182,11 +182,11 @@ class ProcessorWebSocketHandler:
|
||||
history_data = message.get("history_data")
|
||||
|
||||
if not processor_id:
|
||||
await self._send_error(websocket, "processor_id is required")
|
||||
await self._send_error(websocket, "Требуется processor_id")
|
||||
return
|
||||
|
||||
if not history_data or not isinstance(history_data, list):
|
||||
await self._send_error(websocket, "history_data (list) is required")
|
||||
await self._send_error(websocket, "Требуется history_data (список)")
|
||||
return
|
||||
|
||||
try:
|
||||
@ -194,10 +194,10 @@ class ProcessorWebSocketHandler:
|
||||
if result:
|
||||
await websocket.send_text(json.dumps(self._result_to_message(processor_id, result)))
|
||||
else:
|
||||
await self._send_error(websocket, f"No result from processor {processor_id} after loading history")
|
||||
await self._send_error(websocket, f"Нет результата от процессора {processor_id} после загрузки истории")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("History load failed", processor_id=processor_id, error=repr(exc))
|
||||
await self._send_error(websocket, f"History load failed: {exc}")
|
||||
await self._send_error(websocket, f"Загрузка истории не удалась: {exc}")
|
||||
|
||||
async def _handle_get_processor_state(self, websocket: WebSocket, message: dict[str, Any]) -> None:
|
||||
"""
|
||||
@ -209,7 +209,7 @@ class ProcessorWebSocketHandler:
|
||||
processor_id = message.get("processor_id")
|
||||
|
||||
if not processor_id:
|
||||
await self._send_error(websocket, "processor_id is required")
|
||||
await self._send_error(websocket, "Требуется processor_id")
|
||||
return
|
||||
|
||||
try:
|
||||
@ -217,7 +217,7 @@ class ProcessorWebSocketHandler:
|
||||
await websocket.send_text(json.dumps(response))
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("Error getting processor state", processor_id=processor_id, error=repr(exc))
|
||||
await self._send_error(websocket, f"Error getting processor state: {exc}")
|
||||
await self._send_error(websocket, f"Ошибка получения состояния процессора: {exc}")
|
||||
|
||||
def _result_to_message(self, processor_id: str, result: ProcessedResult) -> dict[str, Any]:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user