From 9c825c12ec0d0ed3be4e2b9140f21e3bc6514e1e Mon Sep 17 00:00:00 2001 From: Favyen Bastani Date: Thu, 19 Dec 2024 15:22:01 -0800 Subject: [PATCH 1/3] Make unit test create its own infrastructure map --- tests/unit/test_filter.py | 51 ++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/tests/unit/test_filter.py b/tests/unit/test_filter.py index 8f9fe0f1..811ac5fc 100644 --- a/tests/unit/test_filter.py +++ b/tests/unit/test_filter.py @@ -1,25 +1,52 @@ +import json +import pathlib + +import pytest + from rslp.utils.filter import NearInfraFilter +TEST_INFRA_LON = 1.234 +TEST_INFRA_LAT = 5.678 -def test_near_infra_filter() -> None: - # Test case 1: Detection is exactly on infrastructure. - # The coordinates are directly extracted from the geojson file. - infra_lat = 16.613 - infra_lon = 103.381 - filter = NearInfraFilter() +@pytest.fixture +def single_point_infra_filter(tmp_path: pathlib.Path) -> NearInfraFilter: + geojson_data = { + "type": "FeatureCollection", + "properties": {}, + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [TEST_INFRA_LON, TEST_INFRA_LAT], + }, + } + ], + } + fname = tmp_path / "data.geojson" + with fname.open("w") as f: + json.dump(geojson_data, f) + return NearInfraFilter(infra_url=str(fname)) + + +def test_near_infra_filter(single_point_infra_filter: NearInfraFilter) -> None: + # Test case 1: Detection is exactly on infrastructure. + # The coordinates are directly extracted from the geojson file. # Since this point is exactly an infrastructure point, the filter should discard it (return True) - assert filter.should_filter( - infra_lat, infra_lon + assert single_point_infra_filter.should_filter( + TEST_INFRA_LAT, + TEST_INFRA_LON, ), "Detection should be filtered out as it is located on infrastructure." # Test case 2: Detection is close to infrastructure. - assert filter.should_filter( - infra_lat + 0.0001, infra_lon + 0.0001 + assert single_point_infra_filter.should_filter( + TEST_INFRA_LAT + 0.0001, TEST_INFRA_LON + 0.0001 ), "Detection should be filtered out as it is too close to infrastructure." # Test case 3: Detection is far from infrastructure. - assert not filter.should_filter( - infra_lat + 0.5, infra_lon + 0.5 + assert not single_point_infra_filter.should_filter( + TEST_INFRA_LAT + 0.5, TEST_INFRA_LON + 0.5 ), "Detection should be kept as it is far from infrastructure." From 3c0fb7fd70ddf2f33c5ebc4b144db92e204b4d80 Mon Sep 17 00:00:00 2001 From: Favyen Bastani Date: Thu, 19 Dec 2024 16:16:33 -0800 Subject: [PATCH 2/3] fix --- rslp/utils/filter.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/rslp/utils/filter.py b/rslp/utils/filter.py index c729351c..f283cb35 100644 --- a/rslp/utils/filter.py +++ b/rslp/utils/filter.py @@ -1,9 +1,10 @@ """Filters for vessel detection projects.""" import functools +import json import numpy as np -import requests +from upath import UPath class Filter: @@ -30,22 +31,17 @@ def should_filter(self, lat: float, lon: float) -> bool: @functools.cache -def get_infra_latlons(infra_url: str) -> tuple[np.ndarray, np.ndarray]: +def get_infra_latlons(infra_path: UPath) -> tuple[np.ndarray, np.ndarray]: """Fetch and cache the infrastructure latitudes and longitudes. Args: - infra_url: URL to the marine infrastructure GeoJSON file. + infra_path: path to the marine infrastructure GeoJSON file. Returns: A tuple of arrays: (latitudes, longitudes). """ - try: - # Read the geojson data from the URL. - response = requests.get(infra_url, timeout=10) - response.raise_for_status() # Raise an error for bad responses - geojson_data = response.json() - except requests.RequestException as e: - raise RuntimeError(f"Failed to fetch infrastructure data: {e}") + with infra_path.open("r") as f: + geojson_data = json.load(f) lats = np.array( [feature["geometry"]["coordinates"][1] for feature in geojson_data["features"]] @@ -72,7 +68,7 @@ def __init__( infra_distance_threshold: distance threshold for marine infrastructure. """ self.infra_url = infra_url - self.infra_latlons = get_infra_latlons(self.infra_url) + self.infra_latlons = get_infra_latlons(UPath(self.infra_url)) self.infra_distance_threshold = infra_distance_threshold def _get_haversine_distances( From ab1b146edd044df9a7a46d9c08a99d8bab510c26 Mon Sep 17 00:00:00 2001 From: Favyen Bastani Date: Fri, 20 Dec 2024 14:47:37 -0800 Subject: [PATCH 3/3] split up tests --- tests/unit/test_filter.py | 84 ++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/tests/unit/test_filter.py b/tests/unit/test_filter.py index 811ac5fc..a3c5085c 100644 --- a/tests/unit/test_filter.py +++ b/tests/unit/test_filter.py @@ -9,44 +9,46 @@ TEST_INFRA_LAT = 5.678 -@pytest.fixture -def single_point_infra_filter(tmp_path: pathlib.Path) -> NearInfraFilter: - geojson_data = { - "type": "FeatureCollection", - "properties": {}, - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Point", - "coordinates": [TEST_INFRA_LON, TEST_INFRA_LAT], - }, - } - ], - } - fname = tmp_path / "data.geojson" - with fname.open("w") as f: - json.dump(geojson_data, f) - - return NearInfraFilter(infra_url=str(fname)) - - -def test_near_infra_filter(single_point_infra_filter: NearInfraFilter) -> None: - # Test case 1: Detection is exactly on infrastructure. - # The coordinates are directly extracted from the geojson file. - # Since this point is exactly an infrastructure point, the filter should discard it (return True) - assert single_point_infra_filter.should_filter( - TEST_INFRA_LAT, - TEST_INFRA_LON, - ), "Detection should be filtered out as it is located on infrastructure." - - # Test case 2: Detection is close to infrastructure. - assert single_point_infra_filter.should_filter( - TEST_INFRA_LAT + 0.0001, TEST_INFRA_LON + 0.0001 - ), "Detection should be filtered out as it is too close to infrastructure." - - # Test case 3: Detection is far from infrastructure. - assert not single_point_infra_filter.should_filter( - TEST_INFRA_LAT + 0.5, TEST_INFRA_LON + 0.5 - ), "Detection should be kept as it is far from infrastructure." +class TestNearInfraFilter: + @pytest.fixture + def single_point_infra_filter(self, tmp_path: pathlib.Path) -> NearInfraFilter: + geojson_data = { + "type": "FeatureCollection", + "properties": {}, + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [TEST_INFRA_LON, TEST_INFRA_LAT], + }, + } + ], + } + fname = tmp_path / "data.geojson" + with fname.open("w") as f: + json.dump(geojson_data, f) + + return NearInfraFilter(infra_url=str(fname)) + + def test_exactly_on_infra(self, single_point_infra_filter: NearInfraFilter) -> None: + # Test when detection is exactly on infrastructure. + # The coordinates are directly extracted from the geojson file. + # Since this point is exactly an infrastructure point, the filter should discard it (return True) + assert single_point_infra_filter.should_filter( + TEST_INFRA_LAT, + TEST_INFRA_LON, + ), "Detection should be filtered out as it is located on infrastructure." + + def test_close_to_infra(self, single_point_infra_filter: NearInfraFilter) -> None: + # Test when detection is close to infrastructure. + assert single_point_infra_filter.should_filter( + TEST_INFRA_LAT + 0.0001, TEST_INFRA_LON + 0.0001 + ), "Detection should be filtered out as it is too close to infrastructure." + + def test_far_from_infra(self, single_point_infra_filter: NearInfraFilter) -> None: + # Test when detection is far from infrastructure. + assert not single_point_infra_filter.should_filter( + TEST_INFRA_LAT + 0.5, TEST_INFRA_LON + 0.5 + ), "Detection should be kept as it is far from infrastructure."