diff --git a/vna_system/core/processors/implementations/bscan_processor.py b/vna_system/core/processors/implementations/bscan_processor.py index d737513..349557d 100644 --- a/vna_system/core/processors/implementations/bscan_processor.py +++ b/vna_system/core/processors/implementations/bscan_processor.py @@ -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}
" - "Depth: %{y:.3f} m
" - "Amplitude: %{z:.3f}
" + "Развертка: %{x}
" + "Глубина: %{y:.3f} м
" + "Амплитуда: %{z:.3f}
" "" ), **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 } diff --git a/vna_system/core/processors/implementations/magnitude_processor.py b/vna_system/core/processors/implementations/magnitude_processor.py index 25f035b..3be9637 100644 --- a/vna_system/core/processors/implementations/magnitude_processor.py +++ b/vna_system/core/processors/implementations/magnitude_processor.py @@ -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"}, diff --git a/vna_system/core/processors/websocket_handler.py b/vna_system/core/processors/websocket_handler.py index aa03c7f..f3afc4e 100644 --- a/vna_system/core/processors/websocket_handler.py +++ b/vna_system/core/processors/websocket_handler.py @@ -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]: """