added GPR

This commit is contained in:
Ayzen
2026-03-19 19:29:08 +03:00
parent bdefe3f581
commit 9581730e41
39 changed files with 3830 additions and 201 deletions
@@ -14,27 +14,62 @@ class ProcessingLiveConfig:
processor_mode: str = "pass_through"
gain_db: float = 0.0
phase_deg: float = 0.0
pass_through_fixed_y_enabled: bool = False
pass_through_y_min_db: float = -100.0
pass_through_y_max_db: float = 0.0
bscan_axis: str = "abs"
bscan_cut_m: float = 0.824
bscan_max_depth_m: float = 1.0
bscan_gain: float = 1.0
bscan_start_freq_mhz: float = 100.0
bscan_stop_freq_mhz: float = 8800.0
gpr_input_positions: list[int] | None = None
gpr_output_positions: list[int] | None = None
gpr_min_depth_m: float = 2.0
gpr_max_depth_m: float = 14.0
gpr_comp_power: float = 0.2
gpr_start_freq_mhz: float = 3000.0
gpr_stop_freq_mhz: float = 6000.0
gpr_background_subtract_enabled: bool = True
gpr_background_mean_count: int = 10
history_command_seq: int = 0
history_command: str = "none"
def to_dict(self) -> dict[str, float | str | int]:
def __post_init__(self) -> None:
"""Normalize optional list fields to concrete integer lists."""
if self.gpr_input_positions is None:
self.gpr_input_positions = []
else:
self.gpr_input_positions = [int(value) for value in self.gpr_input_positions]
if self.gpr_output_positions is None:
self.gpr_output_positions = []
else:
self.gpr_output_positions = [int(value) for value in self.gpr_output_positions]
def to_dict(self) -> dict[str, object]:
"""Convert live config to JSON-serializable dictionary."""
return {
"processor_mode": str(self.processor_mode),
"gain_db": float(self.gain_db),
"phase_deg": float(self.phase_deg),
"pass_through_fixed_y_enabled": bool(self.pass_through_fixed_y_enabled),
"pass_through_y_min_db": float(self.pass_through_y_min_db),
"pass_through_y_max_db": float(self.pass_through_y_max_db),
"bscan_axis": str(self.bscan_axis),
"bscan_cut_m": float(self.bscan_cut_m),
"bscan_max_depth_m": float(self.bscan_max_depth_m),
"bscan_gain": float(self.bscan_gain),
"bscan_start_freq_mhz": float(self.bscan_start_freq_mhz),
"bscan_stop_freq_mhz": float(self.bscan_stop_freq_mhz),
"gpr_input_positions": [int(value) for value in self.gpr_input_positions],
"gpr_output_positions": [int(value) for value in self.gpr_output_positions],
"gpr_min_depth_m": float(self.gpr_min_depth_m),
"gpr_max_depth_m": float(self.gpr_max_depth_m),
"gpr_comp_power": float(self.gpr_comp_power),
"gpr_start_freq_mhz": float(self.gpr_start_freq_mhz),
"gpr_stop_freq_mhz": float(self.gpr_stop_freq_mhz),
"gpr_background_subtract_enabled": bool(self.gpr_background_subtract_enabled),
"gpr_background_mean_count": int(self.gpr_background_mean_count),
"history_command_seq": int(self.history_command_seq),
"history_command": str(self.history_command),
}
+68 -31
View File
@@ -56,6 +56,62 @@ def decode_trace_collection(payload: bytes, expected_magic: int) -> SweepCollect
def decode_result_collection(payload: bytes) -> ResultCollection:
"""Decode one processed result collection from binary payload."""
def read_payload(cursor: ByteCursor) -> ResultPayload:
"""Decode one result payload from stream."""
kind = cursor.read_u8()
name_size = cursor.read_u16()
name = cursor.read_bytes(name_size).decode("utf-8")
if kind == 1:
point_count = cursor.read_u32()
freq = np.frombuffer(cursor.read_bytes(point_count * 4), dtype="<f4").astype(np.float32, copy=False)
interleaved = np.frombuffer(cursor.read_bytes(point_count * 8), dtype="<f4")
trace = (interleaved[0::2] + 1j * interleaved[1::2]).astype(np.complex64, copy=False)
return ResultPayload(
processing_name=name,
kind=kind,
frequency_hz=freq,
trace=trace,
)
if kind == 2:
return ResultPayload(
processing_name=name,
kind=kind,
scalar_value=cursor.read_f32(),
)
if kind == 3:
x_count = cursor.read_u32()
y_count = cursor.read_u32()
image_x_axis = np.frombuffer(cursor.read_bytes(x_count * 4), dtype="<f4").astype(np.float32, copy=False)
image_y_axis = np.frombuffer(cursor.read_bytes(y_count * 4), dtype="<f4").astype(np.float32, copy=False)
value_count = x_count * y_count
image_values = np.frombuffer(cursor.read_bytes(value_count * 4), dtype="<f4").astype(np.float32, copy=False)
image = image_values.reshape((y_count, x_count)) if value_count > 0 else np.zeros((0, 0), dtype=np.float32)
return ResultPayload(
processing_name=name,
kind=kind,
image_x_axis=image_x_axis,
image_y_axis=image_y_axis,
image=image,
)
if kind == 4:
table_columns = cursor.read_u32()
table_rows = cursor.read_u32()
value_count = table_columns * table_rows
table_values = np.frombuffer(cursor.read_bytes(value_count * 4), dtype="<f4").astype(np.float32, copy=False)
table = (
table_values.reshape((table_rows, table_columns))
if value_count > 0 and table_columns > 0
else np.zeros((0, 0), dtype=np.float32)
)
return ResultPayload(
processing_name=name,
kind=kind,
table=table,
)
raise ValueError(f"Unsupported result payload kind: {kind}")
cursor = ByteCursor(payload)
magic = cursor.read_u32()
if magic != RESULT_MAGIC:
@@ -63,8 +119,13 @@ def decode_result_collection(payload: bytes) -> ResultCollection:
collection_id = cursor.read_u64()
monotonic_ns = cursor.read_u64()
collection_payload_count = cursor.read_u32()
block_count = cursor.read_u32()
collection_payloads: list[ResultPayload] = []
for _ in range(collection_payload_count):
collection_payloads.append(read_payload(cursor))
blocks: list[ResultBlock] = []
for _ in range(block_count):
input_pos = cursor.read_u32()
@@ -73,36 +134,7 @@ def decode_result_collection(payload: bytes) -> ResultCollection:
payloads: list[ResultPayload] = []
for _ in range(payload_count):
kind = cursor.read_u8()
name_size = cursor.read_u16()
name = cursor.read_bytes(name_size).decode("utf-8")
if kind == 1:
point_count = cursor.read_u32()
freq = np.frombuffer(cursor.read_bytes(point_count * 4), dtype="<f4").astype(np.float32, copy=False)
interleaved = np.frombuffer(cursor.read_bytes(point_count * 8), dtype="<f4")
trace = (interleaved[0::2] + 1j * interleaved[1::2]).astype(np.complex64, copy=False)
payloads.append(
ResultPayload(
processing_name=name,
kind=kind,
frequency_hz=freq,
trace=trace,
)
)
elif kind == 2:
scalar_value = cursor.read_f32()
payloads.append(
ResultPayload(
processing_name=name,
kind=kind,
frequency_hz=np.array([], dtype=np.float32),
trace=np.array([], dtype=np.complex64),
scalar_value=scalar_value,
)
)
else:
raise ValueError(f"Unsupported result payload kind: {kind}")
payloads.append(read_payload(cursor))
blocks.append(
ResultBlock(
@@ -111,4 +143,9 @@ def decode_result_collection(payload: bytes) -> ResultCollection:
)
)
return ResultCollection(collection_id=collection_id, monotonic_ns=monotonic_ns, blocks=blocks)
return ResultCollection(
collection_id=collection_id,
monotonic_ns=monotonic_ns,
collection_payloads=collection_payloads,
blocks=blocks,
)