some refactoring and socket server added

This commit is contained in:
Ayzen
2026-04-08 18:43:29 +03:00
parent 202993325d
commit 1d7d0a756e
25 changed files with 3093 additions and 2527 deletions
+120
View File
@@ -0,0 +1,120 @@
"""Helpers for extracting GPR objects and locator observations from results."""
from __future__ import annotations
from datetime import datetime
from typing import Any
import numpy as np
from python_app.models.dataset_model import ResultCollection, ResultPayload
def collection_payload_by_name(
collection: ResultCollection,
name: str,
kind: int | None = None,
) -> ResultPayload | None:
"""Return the first collection payload matching name and optional kind."""
for payload in collection.collection_payloads:
if payload.processing_name != name:
continue
if kind is not None and int(payload.kind) != int(kind):
continue
return payload
return None
def collection_payloads_by_prefix(
collection: ResultCollection,
prefix: str,
kind: int | None = None,
) -> list[ResultPayload]:
"""Return collection payloads matching a processing-name prefix."""
payloads: list[ResultPayload] = []
for payload in collection.collection_payloads:
if not str(payload.processing_name).startswith(prefix):
continue
if kind is not None and int(payload.kind) != int(kind):
continue
payloads.append(payload)
return payloads
def collection_has_gpr_payloads(collection: ResultCollection) -> bool:
"""Return whether collection carries GPR-specific collection payloads."""
return any(
str(payload.processing_name).startswith("gpr_")
for payload in collection.collection_payloads
)
def gpr_object_rows(collection: ResultCollection) -> np.ndarray:
"""Return object rows as `[x_m, z_m, pair_count]` from a GPR collection."""
points_payload = collection_payload_by_name(collection, "gpr_points", kind=4)
if points_payload is not None:
points = np.asarray(points_payload.table, dtype=np.float32)
if points.ndim == 2 and points.shape[1] >= 3:
return points[:, :3]
centers_payload = collection_payload_by_name(collection, "gpr_region_centers", kind=4)
if centers_payload is not None:
centers = np.asarray(centers_payload.table, dtype=np.float32)
if centers.ndim == 2 and centers.shape[1] >= 3:
return centers[:, :3]
return np.zeros((0, 3), dtype=np.float32)
def locator_observations_from_collection(
collection: ResultCollection,
min_pair_count: float,
*,
visible_bounds: tuple[float, float, float, float] | None = None,
) -> list[dict[str, float]]:
"""Build locator observations from GPR rows using pair threshold and optional X/Z bounds."""
rows = gpr_object_rows(collection)
if rows.size == 0:
return []
finite_mask = np.all(np.isfinite(rows[:, :3]), axis=1)
visible_mask = finite_mask & (rows[:, 2] >= float(min_pair_count))
if visible_bounds is not None:
x_min, x_max, z_min, z_max = (float(value) for value in visible_bounds)
visible_mask &= (
(rows[:, 0] >= x_min)
& (rows[:, 0] <= x_max)
& (rows[:, 1] >= z_min)
& (rows[:, 1] <= z_max)
)
filtered = rows[visible_mask]
observations: list[dict[str, float]] = []
for x_m, z_m, _pair_count in filtered:
observations.append(
{
"dst": round(float(z_m), 2),
"crs": round(float(x_m), 2),
}
)
return observations
def build_locator_payload(
observations: list[dict[str, float]],
*,
protocol_version: int,
status: int = 1,
) -> dict[str, Any]:
"""Assemble one outbound locator payload from precomputed observations."""
return {
"ver": int(protocol_version),
"tim": _format_timestamp(),
"sts": int(status),
"obs": observations,
}
def _format_timestamp() -> str:
"""Return wall-clock timestamp with millisecond precision."""
return datetime.now().strftime("%H:%M:%S.%f")[:-3]