diff --git a/vna_system/core/processors/base_processor.py b/vna_system/core/processors/base_processor.py index 6baa78d..d35c5a1 100644 --- a/vna_system/core/processors/base_processor.py +++ b/vna_system/core/processors/base_processor.py @@ -598,7 +598,7 @@ class BaseProcessor: calibrated_data = entry["calibrated_data"] reference_data = entry.get("reference_data") - # Convert vna_config to fully serializable format + # Convert vna_config to fully serializable format (handles Enums) vna_config = self._make_json_serializable(entry.get("vna_config", {})) exported.append({ @@ -622,6 +622,7 @@ class BaseProcessor: History records in the format exported by export_history_data. """ from vna_system.core.acquisition.sweep_buffer import SweepData + from vna_system.core.settings.preset_manager import VNAMode with self._lock: self._sweep_history.clear() @@ -635,26 +636,37 @@ class BaseProcessor: sweep_data = SweepData( sweep_number=entry.get("sweep_number", 0), timestamp=entry.get("timestamp", 0.0), - points=sweep_points + points=sweep_points, + total_points=len(sweep_points) ) if sweep_points else None calibrated_data = SweepData( sweep_number=entry.get("sweep_number", 0), timestamp=entry.get("timestamp", 0.0), - points=calibrated_points + points=calibrated_points, + total_points=len(calibrated_points) ) if calibrated_points else None reference_data = SweepData( sweep_number=entry.get("sweep_number", 0), timestamp=entry.get("timestamp", 0.0), - points=reference_points + points=reference_points, + total_points=len(reference_points) ) if reference_points else None + # Restore VNAMode enum from string if needed + vna_config = entry.get("vna_config", {}) + if isinstance(vna_config.get("mode"), str): + try: + vna_config["mode"] = VNAMode(vna_config["mode"]) + except (ValueError, KeyError): + pass # Keep as string if conversion fails + self._sweep_history.append({ "sweep_data": sweep_data, "calibrated_data": calibrated_data, "reference_data": reference_data, - "vna_config": entry.get("vna_config", {}), + "vna_config": vna_config, "timestamp": entry.get("timestamp"), }) diff --git a/vna_system/core/processors/configs/bscan_config.json b/vna_system/core/processors/configs/bscan_config.json index a783cb8..fd4a9f7 100644 --- a/vna_system/core/processors/configs/bscan_config.json +++ b/vna_system/core/processors/configs/bscan_config.json @@ -1,9 +1,9 @@ { "open_air": false, "axis": "real", - "cut": 0.0, - "max": 1.4, - "gain": 1.0, + "cut": 0.292, + "max": 2.3, + "gain": 0.3, "start_freq": 100.0, "stop_freq": 8800.0, "clear_history": false, diff --git a/vna_system/core/processors/configs/magnitude_config.json b/vna_system/core/processors/configs/magnitude_config.json index 18abff2..1514069 100644 --- a/vna_system/core/processors/configs/magnitude_config.json +++ b/vna_system/core/processors/configs/magnitude_config.json @@ -1,5 +1,7 @@ { - "y_min": -30, - "y_max": 10, - "show_phase": true + "y_min": -80, + "y_max": 40, + "autoscale": true, + "show_magnitude": true, + "show_phase": false } \ No newline at end of file diff --git a/vna_system/core/processors/websocket_handler.py b/vna_system/core/processors/websocket_handler.py index af40cff..5f3aa32 100644 --- a/vna_system/core/processors/websocket_handler.py +++ b/vna_system/core/processors/websocket_handler.py @@ -200,16 +200,39 @@ class ProcessorWebSocketHandler: # --------------------------------------------------------------------- # # Outbound helpers # --------------------------------------------------------------------- # + def _make_json_serializable(self, obj: Any) -> Any: + """ + Recursively convert non-serializable objects to JSON-compatible types. + Handles numpy types, Enums, custom objects, etc. + """ + import numpy as np + from enum import Enum + + if isinstance(obj, (np.integer, np.floating)): + return obj.item() # Convert numpy scalar to Python type + elif isinstance(obj, np.ndarray): + return obj.tolist() # Convert numpy array to list + elif isinstance(obj, Enum): + return obj.value + elif isinstance(obj, dict): + return {key: self._make_json_serializable(value) for key, value in obj.items()} + elif isinstance(obj, (list, tuple)): + return [self._make_json_serializable(item) for item in obj] + elif hasattr(obj, '__dict__'): + return self._make_json_serializable(obj.__dict__) + else: + return obj + def _result_to_message(self, processor_id: str, result: ProcessedResult) -> dict[str, Any]: """Convert a `ProcessedResult` into a JSON-serializable message.""" return { "type": "processor_result", "processor_id": processor_id, "timestamp": result.timestamp, - "data": result.data, - "plotly_config": result.plotly_config, + "data": self._make_json_serializable(result.data), + "plotly_config": self._make_json_serializable(result.plotly_config), "ui_parameters": [asdict(param) for param in result.ui_parameters], - "metadata": result.metadata, + "metadata": self._make_json_serializable(result.metadata), } async def _send_error(