Update GPR and SAR3D processing
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""GPR object filtering, B-scan transforms and live-setting normalization."""
|
||||
"""GPR payload lookup, B-scan transforms and live-setting normalization."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -26,8 +26,6 @@ from python_app.models.dataset_model import (
|
||||
)
|
||||
from python_app.gui.result_payloads import (
|
||||
collection_payload_by_name,
|
||||
collection_payloads_by_prefix,
|
||||
filter_object_rows,
|
||||
gpr_object_rows,
|
||||
)
|
||||
from python_app.orchestration.live_processing_config import ProcessingLiveConfig
|
||||
@@ -43,32 +41,16 @@ def _collection(payloads: Iterable[ResultPayload]) -> ResultCollection:
|
||||
|
||||
class CollectionLookupTest(unittest.TestCase):
|
||||
def test_payload_by_name_matches_name_and_optional_kind(self) -> None:
|
||||
col = _collection([_table("gpr_points", [[0, 0, 1]]), _table("gpr_region_centers", [[1, 1, 2, 9]])])
|
||||
col = _collection([_table("gpr_points", [[0, 0, 1]])])
|
||||
self.assertIs(collection_payload_by_name(col, "gpr_points"), col.collection_payloads[0])
|
||||
self.assertIsNone(collection_payload_by_name(col, "missing"))
|
||||
self.assertIsNone(collection_payload_by_name(col, "gpr_points", kind=3)) # wrong kind
|
||||
|
||||
def test_payloads_by_prefix_returns_all_in_order(self) -> None:
|
||||
col = _collection([
|
||||
ResultPayload(processing_name="gpr_region_mask_0", kind=3, image=np.zeros((1, 1), dtype=np.float32)),
|
||||
ResultPayload(processing_name="gpr_region_mask_1", kind=3, image=np.zeros((1, 1), dtype=np.float32)),
|
||||
_table("gpr_points", [[0, 0, 1]]),
|
||||
])
|
||||
masks = collection_payloads_by_prefix(col, "gpr_region_mask_", kind=3)
|
||||
self.assertEqual([p.processing_name for p in masks], ["gpr_region_mask_0", "gpr_region_mask_1"])
|
||||
self.assertEqual(collection_payloads_by_prefix(col, "nope_"), [])
|
||||
|
||||
|
||||
class GprObjectRowsTest(unittest.TestCase):
|
||||
def test_extracts_first_three_columns_of_points(self) -> None:
|
||||
rows = gpr_object_rows(_collection([_table("gpr_points", [[1, 2, 3], [4, 5, 6]])]))
|
||||
self.assertTrue(np.array_equal(rows, np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)))
|
||||
|
||||
def test_falls_back_to_region_centers_and_drops_extra_columns(self) -> None:
|
||||
# region_centers is [x, z, score, pixel_count]; only the first 3 cols are used.
|
||||
rows = gpr_object_rows(_collection([_table("gpr_region_centers", [[1, 2, 3, 99]])]))
|
||||
self.assertTrue(np.array_equal(rows, np.array([[1, 2, 3]], dtype=np.float32)))
|
||||
|
||||
def test_empty_when_no_object_payloads(self) -> None:
|
||||
self.assertEqual(gpr_object_rows(_collection([_table("gpr_accumulator", [[1, 2, 3]])])).shape, (0, 3))
|
||||
|
||||
@@ -76,39 +58,6 @@ class GprObjectRowsTest(unittest.TestCase):
|
||||
self.assertEqual(gpr_object_rows(_collection([_table("gpr_points", [[1, 2]])])).shape, (0, 3))
|
||||
|
||||
|
||||
class FilterObjectRowsTest(unittest.TestCase):
|
||||
BOUNDS = {"x_bounds": (-2.0, 2.0), "z_bounds": (0.0, 10.0)}
|
||||
|
||||
def _filter(self, rows: Sequence[Sequence[float]], *, min_score: float) -> np.ndarray:
|
||||
return filter_object_rows(np.asarray(rows, dtype=np.float32), min_score=min_score,
|
||||
**self.BOUNDS)
|
||||
|
||||
def test_keeps_in_window_and_at_or_above_threshold(self) -> None:
|
||||
out = self._filter([[0.0, 5.0, 0.5], [1.0, 1.0, 0.9]], min_score=0.5) # score==threshold kept (inclusive)
|
||||
self.assertEqual(out.shape[0], 2)
|
||||
|
||||
def test_drops_below_threshold(self) -> None:
|
||||
out = self._filter([[0.0, 5.0, 0.4]], min_score=0.5)
|
||||
self.assertEqual(out.shape[0], 0)
|
||||
|
||||
def test_window_bounds_are_inclusive(self) -> None:
|
||||
out = self._filter([[2.0, 10.0, 1.0], [-2.0, 0.0, 1.0]], min_score=0.0) # exactly on each edge
|
||||
self.assertEqual(out.shape[0], 2)
|
||||
|
||||
def test_drops_outside_window(self) -> None:
|
||||
out = self._filter([[2.001, 5.0, 1.0], [0.0, 10.001, 1.0]], min_score=0.0)
|
||||
self.assertEqual(out.shape[0], 0)
|
||||
|
||||
def test_drops_non_finite_rows(self) -> None:
|
||||
out = self._filter([[np.nan, 5.0, 1.0], [0.0, np.inf, 1.0], [0.0, 5.0, 1.0]], min_score=0.0)
|
||||
self.assertEqual(out.shape[0], 1)
|
||||
|
||||
def test_legacy_pair_count_threshold_uses_same_compare(self) -> None:
|
||||
# legacy GPR passes an integer pair-count threshold; the >= compare is identical.
|
||||
out = self._filter([[0.0, 5.0, 3.0], [0.0, 5.0, 2.0]], min_score=3)
|
||||
self.assertTrue(np.array_equal(out, np.array([[0.0, 5.0, 3.0]], dtype=np.float32)))
|
||||
|
||||
|
||||
class BscanTransformTest(unittest.TestCase):
|
||||
def test_mean_ascan_subtraction(self) -> None:
|
||||
history = deque([np.array([1.0, 1.0], dtype=np.float32), np.array([3.0, 3.0], dtype=np.float32)])
|
||||
|
||||
Reference in New Issue
Block a user