Spaces:
Sleeping
Sleeping
alessandro trinca tornidor
commited on
Commit
•
9881eef
1
Parent(s):
d801599
refactor: complete refactor because of samgis-lisa
Browse files- dockerfiles/dockerfile-lisa-predictions +0 -1
- scripts/create_folders_and_variables_if_not_exists.py +0 -51
- scripts/extract-openapi-fastapi.py +2 -1
- scripts/extract-openapi-lambda.py +0 -13
- tests/__init__.py +2 -1
- tests/io_package/__init__.py +0 -0
- tests/io_package/test_coordinates_pixel_conversion.py +0 -27
- tests/io_package/test_geo_helpers.py +0 -103
- tests/io_package/test_raster_helpers.py +0 -255
- tests/io_package/test_tms2geotiff.py +0 -138
- tests/io_package/test_wrappers_helpers.py +0 -78
- tests/local_tiles_http_server.py +0 -46
- tests/prediction_api/__init__.py +0 -0
- tests/prediction_api/test_predictors.py +0 -64
- tests/{test_fastapi_app.py → test_app.py} +20 -23
- tests/test_lambda_app.py +0 -232
dockerfiles/dockerfile-lisa-predictions
CHANGED
@@ -23,7 +23,6 @@ RUN ls -l ${LAMBDA_TASK_ROOT}
|
|
23 |
RUN ls -ld ${LAMBDA_TASK_ROOT}
|
24 |
RUN ls -l ${LAMBDA_TASK_ROOT}/machine_learning_models
|
25 |
RUN python -c "import sys; print(sys.path)"
|
26 |
-
RUN python -c "import cv2"
|
27 |
RUN python -c "import fastapi"
|
28 |
RUN python -c "import geopandas"
|
29 |
RUN python -c "import loguru"
|
|
|
23 |
RUN ls -ld ${LAMBDA_TASK_ROOT}
|
24 |
RUN ls -l ${LAMBDA_TASK_ROOT}/machine_learning_models
|
25 |
RUN python -c "import sys; print(sys.path)"
|
|
|
26 |
RUN python -c "import fastapi"
|
27 |
RUN python -c "import geopandas"
|
28 |
RUN python -c "import loguru"
|
scripts/create_folders_and_variables_if_not_exists.py
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
import logging
|
3 |
-
import os
|
4 |
-
from pathlib import Path
|
5 |
-
|
6 |
-
|
7 |
-
def stats_pathname(pathname: Path | str):
|
8 |
-
current_pathname = Path(pathname)
|
9 |
-
return current_pathname.is_dir()
|
10 |
-
|
11 |
-
|
12 |
-
def create_folder_if_not_exists(pathname: Path | str):
|
13 |
-
current_pathname = Path(pathname)
|
14 |
-
try:
|
15 |
-
print(f"Pathname exists? {current_pathname.exists()}, That's a folder? {current_pathname.is_dir()}...")
|
16 |
-
logging.info(f"Pathname exists? {current_pathname.exists()}, That's a folder? {current_pathname.is_dir()}...")
|
17 |
-
current_pathname.unlink(missing_ok=True)
|
18 |
-
except PermissionError as pe:
|
19 |
-
print(f"permission denied on removing pathname before folder creation:{pe}.")
|
20 |
-
logging.error(f"permission denied on removing pathname before folder creation:{pe}.")
|
21 |
-
except IsADirectoryError as errdir:
|
22 |
-
print(f"that's a directory:{errdir}.")
|
23 |
-
logging.error(f"that's a directory:{errdir}.")
|
24 |
-
|
25 |
-
print(f"Creating pathname: {current_pathname} ...")
|
26 |
-
logging.info(f"Creating pathname: {current_pathname} ...")
|
27 |
-
current_pathname.mkdir(mode=0o770, parents=True, exist_ok=True)
|
28 |
-
|
29 |
-
print(f"assertion: pathname exists and is a folder: {current_pathname} ...")
|
30 |
-
logging.info(f"assertion: pathname exists and is a folder: {current_pathname} ...")
|
31 |
-
assert current_pathname.is_dir()
|
32 |
-
|
33 |
-
|
34 |
-
if __name__ == '__main__':
|
35 |
-
folders_string = os.getenv("FOLDERS_MAP")
|
36 |
-
try:
|
37 |
-
folders_dict = json.loads(folders_string)
|
38 |
-
for folder_env_ref, folder_env_path in folders_dict.items():
|
39 |
-
print(f"folder_env_ref:{folder_env_ref}, folder_env_path:{folder_env_path}.")
|
40 |
-
logging.info(f"folder_env_ref:{folder_env_ref}, folder_env_path:{folder_env_path}.")
|
41 |
-
create_folder_if_not_exists(folder_env_path)
|
42 |
-
print("========")
|
43 |
-
assert os.getenv(folder_env_ref) == folder_env_path
|
44 |
-
except (json.JSONDecodeError, TypeError) as jde:
|
45 |
-
print(f"jde:{jde}.")
|
46 |
-
logging.error(f"jde:{jde}.")
|
47 |
-
print("double check your variables, e.g. for mispelling like 'FOLDER_MAP'...")
|
48 |
-
logging.info("double check your variables, e.g. for mispelling like 'FOLDER_MAP' instead than 'FOLDERS_MAP'...")
|
49 |
-
for k_env, v_env in dict(os.environ).items():
|
50 |
-
print(f"{k_env}, v_env:{v_env}.")
|
51 |
-
logging.info(f"{k_env}, v_env:{v_env}.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scripts/extract-openapi-fastapi.py
CHANGED
@@ -3,12 +3,13 @@ import argparse
|
|
3 |
import json
|
4 |
import logging
|
5 |
import sys
|
|
|
6 |
|
7 |
import yaml
|
8 |
from uvicorn.importer import import_from_string
|
9 |
|
10 |
-
from samgis_lisa_on_zero import PROJECT_ROOT_FOLDER
|
11 |
|
|
|
12 |
parser = argparse.ArgumentParser(prog="extract-openapi-fastapi.py")
|
13 |
parser.add_argument("app", help='App import string. Eg. "main:app"', default="main:app")
|
14 |
parser.add_argument("--app-dir", help="Directory containing the app", default=None)
|
|
|
3 |
import json
|
4 |
import logging
|
5 |
import sys
|
6 |
+
from pathlib import Path
|
7 |
|
8 |
import yaml
|
9 |
from uvicorn.importer import import_from_string
|
10 |
|
|
|
11 |
|
12 |
+
PROJECT_ROOT_FOLDER = Path(globals().get("__file__", "./_")).absolute().parent.parent
|
13 |
parser = argparse.ArgumentParser(prog="extract-openapi-fastapi.py")
|
14 |
parser.add_argument("app", help='App import string. Eg. "main:app"', default="main:app")
|
15 |
parser.add_argument("--app-dir", help="Directory containing the app", default=None)
|
scripts/extract-openapi-lambda.py
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
|
3 |
-
from samgis_lisa_on_zero import PROJECT_ROOT_FOLDER
|
4 |
-
|
5 |
-
if __name__ == '__main__':
|
6 |
-
from samgis_lisa_on_zero.utilities.type_hints import ApiRequestBody, ApiResponseBodyFailure, ApiResponseBodySuccess
|
7 |
-
|
8 |
-
with open(PROJECT_ROOT_FOLDER / "docs" / "specs" / "openapi_lambda_wip.json", "w") as output_json:
|
9 |
-
json.dump({
|
10 |
-
"ApiRequestBody": ApiRequestBody.model_json_schema(),
|
11 |
-
"ApiResponseBodyFailure": ApiResponseBodyFailure.model_json_schema(),
|
12 |
-
"ApiResponseBodySuccess": ApiResponseBodySuccess.model_json_schema()
|
13 |
-
}, output_json)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/__init__.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
-
from
|
2 |
|
3 |
|
|
|
4 |
TEST_ROOT_FOLDER = PROJECT_ROOT_FOLDER / "tests"
|
5 |
TEST_EVENTS_FOLDER = TEST_ROOT_FOLDER / "events"
|
6 |
LOCAL_URL_TILE = "http://localhost:8000/lambda_handler/{z}/{x}/{y}.png"
|
|
|
1 |
+
from pathlib import Path
|
2 |
|
3 |
|
4 |
+
PROJECT_ROOT_FOLDER = Path(globals().get("__file__", "./_")).absolute().parent.parent
|
5 |
TEST_ROOT_FOLDER = PROJECT_ROOT_FOLDER / "tests"
|
6 |
TEST_EVENTS_FOLDER = TEST_ROOT_FOLDER / "events"
|
7 |
LOCAL_URL_TILE = "http://localhost:8000/lambda_handler/{z}/{x}/{y}.png"
|
tests/io_package/__init__.py
DELETED
File without changes
|
tests/io_package/test_coordinates_pixel_conversion.py
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
|
3 |
-
from samgis_lisa_on_zero.io_package.coordinates_pixel_conversion import get_latlng_to_pixel_coordinates
|
4 |
-
from samgis_lisa_on_zero.utilities.type_hints import LatLngDict
|
5 |
-
from tests import TEST_EVENTS_FOLDER
|
6 |
-
|
7 |
-
|
8 |
-
def test_get_latlng_to_pixel_coordinates():
|
9 |
-
name_fn = "get_latlng_to_pixel_coordinates"
|
10 |
-
|
11 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
12 |
-
inputs_outputs = json.load(tst_json)
|
13 |
-
for k, input_output in inputs_outputs.items():
|
14 |
-
print(f"k:{k}")
|
15 |
-
current_input = input_output["input"]
|
16 |
-
zoom = current_input["zoom"]
|
17 |
-
latlng_origin_ne = LatLngDict.model_validate(current_input["latlng_origin_ne"])
|
18 |
-
latlng_origin_sw = LatLngDict.model_validate(current_input["latlng_origin_sw"])
|
19 |
-
latlng_current_point = LatLngDict.model_validate(current_input["latlng_current_point"])
|
20 |
-
output = get_latlng_to_pixel_coordinates(
|
21 |
-
latlng_origin_ne=latlng_origin_ne,
|
22 |
-
latlng_origin_sw=latlng_origin_sw,
|
23 |
-
latlng_current_point=latlng_current_point,
|
24 |
-
zoom=zoom,
|
25 |
-
k=k
|
26 |
-
)
|
27 |
-
assert output == input_output["output"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/io_package/test_geo_helpers.py
DELETED
@@ -1,103 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
import unittest
|
3 |
-
import numpy as np
|
4 |
-
import shapely
|
5 |
-
|
6 |
-
from samgis_lisa_on_zero.io_package.geo_helpers import load_affine_transformation_from_matrix
|
7 |
-
from tests import TEST_EVENTS_FOLDER
|
8 |
-
|
9 |
-
|
10 |
-
class TestGeoHelpers(unittest.TestCase):
|
11 |
-
def test_load_affine_transformation_from_matrix(self):
|
12 |
-
name_fn = "samexporter_predict"
|
13 |
-
|
14 |
-
expected_output = {
|
15 |
-
'europe': (
|
16 |
-
1524458.6551710723, 0.0, 152.87405657035242, 4713262.318571913, -762229.3275855362, -2356860.470370812
|
17 |
-
),
|
18 |
-
'north_america': (
|
19 |
-
-13855281.495084189, 0.0, 1222.9924525628194, 6732573.451358326, 6927640.747542094, -3368121.214358007
|
20 |
-
),
|
21 |
-
'oceania': (
|
22 |
-
7269467.138033403, 0.0, 9783.93962050256, -166326.9735485418, -3634733.5690167015, 68487.57734351706
|
23 |
-
),
|
24 |
-
'south_america': (
|
25 |
-
-7922544.351904369, 0.0, 305.74811314070394, -5432228.234830927, 3961272.1759521845, 2715655.4952457524
|
26 |
-
)}
|
27 |
-
|
28 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
29 |
-
inputs_outputs = json.load(tst_json)
|
30 |
-
for k, input_output in inputs_outputs.items():
|
31 |
-
print(f"k:{k}.")
|
32 |
-
|
33 |
-
output = load_affine_transformation_from_matrix(input_output["input"]["matrix"])
|
34 |
-
assert output.to_shapely() == expected_output[k]
|
35 |
-
|
36 |
-
def test_load_affine_transformation_from_matrix_value_error(self):
|
37 |
-
name_fn = "samexporter_predict"
|
38 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
39 |
-
inputs_outputs = json.load(tst_json)
|
40 |
-
with self.assertRaises(ValueError):
|
41 |
-
try:
|
42 |
-
io_value_error = inputs_outputs["europe"]["input"]["matrix"][:5]
|
43 |
-
load_affine_transformation_from_matrix(io_value_error)
|
44 |
-
except ValueError as ve:
|
45 |
-
print(f"ve:{ve}.")
|
46 |
-
self.assertEqual(str(ve), "Expected 6 coefficients, found 5; argument type: <class 'list'>.")
|
47 |
-
raise ve
|
48 |
-
|
49 |
-
def test_load_affine_transformation_from_matrix_exception(self):
|
50 |
-
name_fn = "samexporter_predict"
|
51 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
52 |
-
inputs_outputs = json.load(tst_json)
|
53 |
-
with self.assertRaises(Exception):
|
54 |
-
try:
|
55 |
-
io_exception = inputs_outputs["europe"]["input"]["matrix"]
|
56 |
-
io_exception[0] = "ciao"
|
57 |
-
load_affine_transformation_from_matrix(io_exception)
|
58 |
-
except Exception as e:
|
59 |
-
print(f"e:{e}.")
|
60 |
-
self.assertEqual(str(e), "exception:could not convert string to float: 'ciao', "
|
61 |
-
"check https://github.com/rasterio/affine project for updates")
|
62 |
-
raise e
|
63 |
-
|
64 |
-
def test_get_vectorized_raster_as_geojson_ok(self):
|
65 |
-
from rasterio.transform import Affine
|
66 |
-
from samgis_lisa_on_zero.io_package.geo_helpers import get_vectorized_raster_as_geojson
|
67 |
-
|
68 |
-
name_fn = "samexporter_predict"
|
69 |
-
|
70 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
71 |
-
inputs_outputs = json.load(tst_json)
|
72 |
-
for k, input_output in inputs_outputs.items():
|
73 |
-
print(f"k:{k}.")
|
74 |
-
mask = np.load(TEST_EVENTS_FOLDER / name_fn / k / "mask.npy")
|
75 |
-
|
76 |
-
transform = Affine.from_gdal(*input_output["input"]["matrix"])
|
77 |
-
output = get_vectorized_raster_as_geojson(mask=mask, transform=transform)
|
78 |
-
assert output["n_shapes_geojson"] == input_output["output"]["n_shapes_geojson"]
|
79 |
-
output_geojson = shapely.from_geojson(output["geojson"])
|
80 |
-
expected_output_geojson = shapely.from_geojson(input_output["output"]["geojson"])
|
81 |
-
assert shapely.equals_exact(output_geojson, expected_output_geojson, tolerance=0.000006)
|
82 |
-
|
83 |
-
def test_get_vectorized_raster_as_geojson_fail(self):
|
84 |
-
from samgis_lisa_on_zero.io_package.geo_helpers import get_vectorized_raster_as_geojson
|
85 |
-
|
86 |
-
name_fn = "samexporter_predict"
|
87 |
-
|
88 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
89 |
-
inputs_outputs = json.load(tst_json)
|
90 |
-
for k, input_output in inputs_outputs.items():
|
91 |
-
print(f"k:{k}.")
|
92 |
-
mask = np.load(TEST_EVENTS_FOLDER / name_fn / k / "mask.npy")
|
93 |
-
|
94 |
-
# Could be also another generic Exception, here we intercept TypeError caused by wrong matrix input on
|
95 |
-
# rasterio.Affine.from_gdal() wrapped by get_affine_transform_from_gdal()
|
96 |
-
with self.assertRaises(IndexError):
|
97 |
-
try:
|
98 |
-
wrong_matrix = 1.0,
|
99 |
-
get_vectorized_raster_as_geojson(mask=mask, transform=wrong_matrix)
|
100 |
-
except IndexError as te:
|
101 |
-
print(f"te:{te}.")
|
102 |
-
self.assertEqual(str(te), 'tuple index out of range')
|
103 |
-
raise te
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/io_package/test_raster_helpers.py
DELETED
@@ -1,255 +0,0 @@
|
|
1 |
-
import unittest
|
2 |
-
from unittest.mock import patch
|
3 |
-
import numpy as np
|
4 |
-
|
5 |
-
from samgis_core.utilities.utilities import hash_calculate
|
6 |
-
from samgis_lisa_on_zero.io_package import raster_helpers
|
7 |
-
|
8 |
-
|
9 |
-
def get_three_channels(size=5, param1=1000, param2=3, param3=-88):
|
10 |
-
arr_base = np.arange(size*size).reshape(size, size) / size**2
|
11 |
-
channel_0 = arr_base * param1
|
12 |
-
channel_1 = arr_base * param2
|
13 |
-
channel_2 = arr_base * param3
|
14 |
-
return channel_0, channel_1, channel_2
|
15 |
-
|
16 |
-
|
17 |
-
def helper_bell(size=10, param1=0.1, param2=2):
|
18 |
-
x = np.linspace(-size, size, num=size**2)
|
19 |
-
y = np.linspace(-size, size, num=size**2)
|
20 |
-
x, y = np.meshgrid(x, y)
|
21 |
-
return np.exp(-param1 * x ** param2 - param1 * y ** param2)
|
22 |
-
|
23 |
-
|
24 |
-
arr_5x5x5 = np.arange(125).reshape((5, 5, 5)) / 25
|
25 |
-
arr = np.arange(25).resize((5, 5))
|
26 |
-
channel0, channel1, channel2 = get_three_channels()
|
27 |
-
z = helper_bell()
|
28 |
-
slope_z_cellsize3, curvature_z_cellsize3 = raster_helpers.get_slope_curvature(z, slope_cellsize=3)
|
29 |
-
|
30 |
-
|
31 |
-
class Test(unittest.TestCase):
|
32 |
-
|
33 |
-
def test_get_rgb_prediction_image_real(self):
|
34 |
-
output = raster_helpers.get_rgb_prediction_image(z, slope_cellsize=61, invert_image=True)
|
35 |
-
hash_output = hash_calculate(output)
|
36 |
-
assert hash_output == b'QpQ9yxgCLw9cf3klNFKNFXIDHaSkuiZxkbpeQApR8pA='
|
37 |
-
output = raster_helpers.get_rgb_prediction_image(z, slope_cellsize=61, invert_image=False)
|
38 |
-
hash_output = hash_calculate(output)
|
39 |
-
assert hash_output == b'Y+iXO9w/sKzNVOw2rBh2JrVGJUFRqaa8/0F9hpevmLs='
|
40 |
-
|
41 |
-
@patch.object(raster_helpers, "get_slope_curvature")
|
42 |
-
@patch.object(raster_helpers, "normalize_array_list")
|
43 |
-
@patch.object(raster_helpers, "get_rgb_image")
|
44 |
-
def test_get_rgb_prediction_image_mocked(self, get_rgb_image_mocked, normalize_array_list, get_slope_curvature):
|
45 |
-
local_arr = np.array(z * 100, dtype=np.uint8)
|
46 |
-
|
47 |
-
get_slope_curvature.return_value = slope_z_cellsize3, curvature_z_cellsize3
|
48 |
-
normalize_array_list.side_effect = None
|
49 |
-
get_rgb_image_mocked.return_value = np.bitwise_not(local_arr)
|
50 |
-
output = raster_helpers.get_rgb_prediction_image(local_arr, slope_cellsize=61, invert_image=True)
|
51 |
-
hash_output = hash_calculate(output)
|
52 |
-
assert hash_output == b'BPIyVH64RgVunj42EuQAx4/v59Va8ZAjcMnuiGNqTT0='
|
53 |
-
get_rgb_image_mocked.return_value = local_arr
|
54 |
-
output = raster_helpers.get_rgb_prediction_image(local_arr, slope_cellsize=61, invert_image=False)
|
55 |
-
hash_output = hash_calculate(output)
|
56 |
-
assert hash_output == b'XX54sdLQQUrhkUHT6ikQZYSloMYDSfh/AGITDq6jnRM='
|
57 |
-
|
58 |
-
@patch.object(raster_helpers, "get_slope_curvature")
|
59 |
-
def test_get_rgb_prediction_image_value_error(self, get_slope_curvature):
|
60 |
-
msg = "this is a value error"
|
61 |
-
get_slope_curvature.side_effect = ValueError(msg)
|
62 |
-
|
63 |
-
with self.assertRaises(ValueError):
|
64 |
-
try:
|
65 |
-
raster_helpers.get_rgb_prediction_image(arr, slope_cellsize=3)
|
66 |
-
except ValueError as ve:
|
67 |
-
self.assertEqual(str(ve), msg)
|
68 |
-
raise ve
|
69 |
-
|
70 |
-
def test_get_rgb_image(self):
|
71 |
-
output = raster_helpers.get_rgb_image(channel0, channel1, channel2, invert_image=True)
|
72 |
-
hash_output = hash_calculate(output)
|
73 |
-
assert hash_output == b'YVnRWla5Ptfet6reSfM+OEIsGytLkeso6X+CRs34YHk='
|
74 |
-
output = raster_helpers.get_rgb_image(channel0, channel1, channel2, invert_image=False)
|
75 |
-
hash_output = hash_calculate(output)
|
76 |
-
assert hash_output == b'LC/kIZGUZULSrwwSXCeP1My2spTZdW9D7LH+tltwERs='
|
77 |
-
|
78 |
-
def test_get_rgb_image_value_error_1(self):
|
79 |
-
with self.assertRaises(ValueError):
|
80 |
-
try:
|
81 |
-
raster_helpers.get_rgb_image(arr_5x5x5, arr_5x5x5, arr_5x5x5, invert_image=True)
|
82 |
-
except ValueError as ve:
|
83 |
-
self.assertEqual(f"arr_size, wrong type:{type(arr_5x5x5)} or arr_size:{arr_5x5x5.shape}.", str(ve))
|
84 |
-
raise ve
|
85 |
-
|
86 |
-
def test_get_rgb_image_value_error2(self):
|
87 |
-
arr_0 = np.arange(25).reshape((5, 5))
|
88 |
-
arr_1 = np.arange(4).reshape((2, 2))
|
89 |
-
with self.assertRaises(ValueError):
|
90 |
-
try:
|
91 |
-
raster_helpers.get_rgb_image(arr_0, arr_1, channel2, invert_image=True)
|
92 |
-
except ValueError as ve:
|
93 |
-
self.assertEqual('could not broadcast input array from shape (2,2) into shape (5,5)', str(ve))
|
94 |
-
raise ve
|
95 |
-
|
96 |
-
def test_get_slope_curvature(self):
|
97 |
-
slope_output, curvature_output = raster_helpers.get_slope_curvature(z, slope_cellsize=3)
|
98 |
-
hash_curvature = hash_calculate(curvature_output)
|
99 |
-
hash_slope = hash_calculate(slope_output)
|
100 |
-
assert hash_curvature == b'LAL9JFOjJP9D6X4X3fVCpnitx9VPM9drS5YMHwMZ3iE='
|
101 |
-
assert hash_slope == b'IYf6x4G0lmR47j6HRS5kUYWdtmimhLz2nak8py75nwc='
|
102 |
-
|
103 |
-
def test_get_slope_curvature_value_error(self):
|
104 |
-
from samgis_lisa_on_zero.io_package import raster_helpers
|
105 |
-
|
106 |
-
with self.assertRaises(ValueError):
|
107 |
-
try:
|
108 |
-
raster_helpers.get_slope_curvature(np.array(1), slope_cellsize=3)
|
109 |
-
except ValueError as ve:
|
110 |
-
self.assertEqual('not enough values to unpack (expected 2, got 0)', str(ve))
|
111 |
-
raise ve
|
112 |
-
|
113 |
-
def test_calculate_slope(self):
|
114 |
-
slope_output = raster_helpers.calculate_slope(z, cell_size=3)
|
115 |
-
hash_output = hash_calculate(slope_output)
|
116 |
-
assert hash_output == b'IYf6x4G0lmR47j6HRS5kUYWdtmimhLz2nak8py75nwc='
|
117 |
-
|
118 |
-
def test_calculate_slope_value_error(self):
|
119 |
-
with self.assertRaises(ValueError):
|
120 |
-
try:
|
121 |
-
raster_helpers.calculate_slope(np.array(1), cell_size=3)
|
122 |
-
except ValueError as ve:
|
123 |
-
self.assertEqual('not enough values to unpack (expected 2, got 0)', str(ve))
|
124 |
-
raise ve
|
125 |
-
|
126 |
-
def test_normalize_array(self):
|
127 |
-
def check_ndarrays_almost_equal(cls, arr1, arr2, places, check_type="float", check_ndiff=1):
|
128 |
-
count_abs_diff = 0
|
129 |
-
for list00, list01 in zip(arr1.tolist(), arr2.tolist()):
|
130 |
-
for el00, el01 in zip(list00, list01):
|
131 |
-
ndiff = abs(el00 - el01)
|
132 |
-
if el00 != el01:
|
133 |
-
count_abs_diff += 1
|
134 |
-
if check_type == "float":
|
135 |
-
cls.assertAlmostEqual(el00, el01, places=places)
|
136 |
-
cls.assertLess(ndiff, check_ndiff) # cls.assertTrue(ndiff < check_ndiff)
|
137 |
-
print("count_abs_diff:", count_abs_diff)
|
138 |
-
|
139 |
-
normalized_array = raster_helpers.normalize_array(z)
|
140 |
-
hash_output = hash_calculate(normalized_array)
|
141 |
-
assert hash_output == b'MPkQwiiQa5NxL7LDvCS9V143YUEJT/Qh1aNEKc/Ehvo='
|
142 |
-
|
143 |
-
mult_variable = 3.423
|
144 |
-
test_array_input = np.arange(256).reshape((16, 16))
|
145 |
-
test_array_output = raster_helpers.normalize_array(test_array_input * mult_variable)
|
146 |
-
check_ndarrays_almost_equal(self, test_array_output, test_array_input, places=8)
|
147 |
-
|
148 |
-
test_array_output1 = raster_helpers.normalize_array(test_array_input * mult_variable, high=128, norm_type="int")
|
149 |
-
o = np.arange(256).reshape((16, 16)) / 2
|
150 |
-
expected_array_output1 = o.astype(int)
|
151 |
-
check_ndarrays_almost_equal(
|
152 |
-
self, test_array_output1, expected_array_output1, places=2, check_type="int", check_ndiff=2)
|
153 |
-
|
154 |
-
@patch.object(np, "nanmin")
|
155 |
-
@patch.object(np, "nanmax")
|
156 |
-
def test_normalize_array_floating_point_error_mocked(self, nanmax_mocked, nanmin_mocked):
|
157 |
-
nanmax_mocked.return_value = 100
|
158 |
-
nanmin_mocked.return_value = 100
|
159 |
-
|
160 |
-
with self.assertRaises(ValueError):
|
161 |
-
try:
|
162 |
-
raster_helpers.normalize_array(
|
163 |
-
np.arange(25).reshape((5, 5))
|
164 |
-
)
|
165 |
-
except ValueError as ve:
|
166 |
-
self.assertEqual(
|
167 |
-
"normalize_array:::h_arr_max:100,h_min_arr:100,fe:divide by zero encountered in divide.",
|
168 |
-
str(ve)
|
169 |
-
)
|
170 |
-
raise ve
|
171 |
-
|
172 |
-
@patch.object(np, "nanmin")
|
173 |
-
@patch.object(np, "nanmax")
|
174 |
-
def test_normalize_array_exception_error_mocked(self, nanmax_mocked, nanmin_mocked):
|
175 |
-
nanmax_mocked.return_value = 100
|
176 |
-
nanmin_mocked.return_value = np.NaN
|
177 |
-
|
178 |
-
with self.assertRaises(ValueError):
|
179 |
-
try:
|
180 |
-
raster_helpers.normalize_array(
|
181 |
-
np.arange(25).reshape((5, 5))
|
182 |
-
)
|
183 |
-
except ValueError as ve:
|
184 |
-
self.assertEqual("cannot convert float NaN to integer", str(ve))
|
185 |
-
raise ve
|
186 |
-
|
187 |
-
def test_normalize_array_value_error(self):
|
188 |
-
with self.assertRaises(ValueError):
|
189 |
-
try:
|
190 |
-
raster_helpers.normalize_array(
|
191 |
-
np.zeros((5, 5))
|
192 |
-
)
|
193 |
-
except ValueError as ve:
|
194 |
-
self.assertEqual(
|
195 |
-
"normalize_array::empty array '',h_min_arr:0.0,h_arr_max:0.0,h_diff:0.0, " 'dtype:float64.',
|
196 |
-
str(ve)
|
197 |
-
)
|
198 |
-
raise ve
|
199 |
-
|
200 |
-
def test_normalize_array_list(self):
|
201 |
-
normalized_array = raster_helpers.normalize_array_list([channel0, channel1, channel2])
|
202 |
-
hash_output = hash_calculate(normalized_array)
|
203 |
-
assert hash_output == b'+6IbhIpyb3vPElTgqqPkQdIR0umf4uFP2c7t5IaBVvI='
|
204 |
-
|
205 |
-
test_norm_list_output2 = raster_helpers.normalize_array_list(
|
206 |
-
[channel0, channel1, channel2], exaggerations_list=[2.0, 3.0, 5.0])
|
207 |
-
hash_variable2 = hash_calculate(test_norm_list_output2)
|
208 |
-
assert hash_variable2 == b'yYCYWCKO3i8NYsWk/wgYOzSRRLSLUprEs7mChJkdL+A='
|
209 |
-
|
210 |
-
def test_normalize_array_list_value_error(self):
|
211 |
-
with self.assertRaises(ValueError):
|
212 |
-
try:
|
213 |
-
raster_helpers.normalize_array_list([])
|
214 |
-
except ValueError as ve:
|
215 |
-
self.assertEqual("input list can't be empty:[].", str(ve))
|
216 |
-
raise ve
|
217 |
-
|
218 |
-
def test_check_empty_array(self):
|
219 |
-
a = np.zeros((10, 10))
|
220 |
-
b = np.ones((10, 10))
|
221 |
-
c = np.ones((10, 10)) * 2
|
222 |
-
d = np.zeros((10, 10))
|
223 |
-
d[1, 1] = np.nan
|
224 |
-
e = np.ones((10, 10)) * 3
|
225 |
-
e[1, 1] = np.nan
|
226 |
-
|
227 |
-
self.assertTrue(raster_helpers.check_empty_array(a, 999))
|
228 |
-
self.assertTrue(raster_helpers.check_empty_array(b, 0))
|
229 |
-
self.assertTrue(raster_helpers.check_empty_array(c, 2))
|
230 |
-
self.assertTrue(raster_helpers.check_empty_array(d, 0))
|
231 |
-
self.assertTrue(raster_helpers.check_empty_array(e, 3))
|
232 |
-
self.assertFalse(raster_helpers.check_empty_array(z, 3))
|
233 |
-
|
234 |
-
def test_get_nextzen_terrain_rgb_formula(self):
|
235 |
-
output = raster_helpers.get_nextzen_terrain_rgb_formula(channel0, channel1, channel2)
|
236 |
-
hash_output = hash_calculate(output)
|
237 |
-
assert hash_output == b'3KJ81YKmQRdccRZARbByfwo1iMVLj8xxz9mfsWki/qA='
|
238 |
-
|
239 |
-
def test_get_mapbox__terrain_rgb_formula(self):
|
240 |
-
output = raster_helpers.get_mapbox__terrain_rgb_formula(channel0, channel1, channel2)
|
241 |
-
hash_output = hash_calculate(output)
|
242 |
-
assert hash_output == b'RU7CcoKoR3Fkh5LE+m48DHRVUy/vGq6UgfOFUMXx07M='
|
243 |
-
|
244 |
-
def test_get_raster_terrain_rgb_like(self):
|
245 |
-
from samgis_lisa_on_zero.utilities.type_hints import XYZTerrainProvidersNames
|
246 |
-
|
247 |
-
arr_input = raster_helpers.get_rgb_image(channel0, channel1, channel2, invert_image=True)
|
248 |
-
output_nextzen = raster_helpers.get_raster_terrain_rgb_like(
|
249 |
-
arr_input, XYZTerrainProvidersNames.NEXTZEN_TERRAIN_TILES_NAME)
|
250 |
-
hash_nextzen = hash_calculate(output_nextzen)
|
251 |
-
assert hash_nextzen == b'+o2OTJliJkkBoqiAIGnhJ4s0xoLQ4MxHOvevLhNxysE='
|
252 |
-
output_mapbox = raster_helpers.get_raster_terrain_rgb_like(
|
253 |
-
arr_input, XYZTerrainProvidersNames.MAPBOX_TERRAIN_TILES_NAME)
|
254 |
-
hash_mapbox = hash_calculate(output_mapbox)
|
255 |
-
assert hash_mapbox == b'zWmekyKrpnmHnuDACnveCJl+o4GuhtHJmGlRDVwsce4='
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/io_package/test_tms2geotiff.py
DELETED
@@ -1,138 +0,0 @@
|
|
1 |
-
import unittest
|
2 |
-
|
3 |
-
import numpy as np
|
4 |
-
from samgis_core.utilities.utilities import hash_calculate
|
5 |
-
|
6 |
-
from samgis_lisa_on_zero import app_logger
|
7 |
-
from samgis_lisa_on_zero.io_package.tms2geotiff import download_extent
|
8 |
-
from tests import LOCAL_URL_TILE, TEST_EVENTS_FOLDER
|
9 |
-
|
10 |
-
|
11 |
-
input_bbox = [[39.036252959636606, 15.040283203125002], [38.302869955150044, 13.634033203125002]]
|
12 |
-
|
13 |
-
|
14 |
-
class TestTms2geotiff(unittest.TestCase):
|
15 |
-
# def test_download_extent_simple_source(self):
|
16 |
-
# from rasterio import Affine
|
17 |
-
# from xyzservices import TileProvider
|
18 |
-
# from tests.local_tiles_http_server import LocalTilesHttpServer
|
19 |
-
#
|
20 |
-
# listen_port = 8000
|
21 |
-
#
|
22 |
-
# with LocalTilesHttpServer.http_server("localhost", listen_port, directory=TEST_EVENTS_FOLDER):
|
23 |
-
# pt0, pt1 = input_bbox
|
24 |
-
# zoom = 10
|
25 |
-
#
|
26 |
-
# n_lat = pt0[0]
|
27 |
-
# e_lng = pt0[1]
|
28 |
-
# s_lat = pt1[0]
|
29 |
-
# w_lng = pt1[1]
|
30 |
-
#
|
31 |
-
# source = TileProvider(name="local_tile_provider", url=LOCAL_URL_TILE, attribution="")
|
32 |
-
# img, matrix = download_extent(w=w_lng, s=s_lat, e=e_lng, n=n_lat, zoom=zoom, source=source)
|
33 |
-
# app_logger.info(f"# DOWNLOAD ENDED, shape: {img.shape} #")
|
34 |
-
# np_img = np.ascontiguousarray(img)
|
35 |
-
# output_hash = hash_calculate(np_img)
|
36 |
-
# assert output_hash == b'UmbkwbPJpRT1XXcLnLUapUDP320w7YhS/AmT3H7u+b4='
|
37 |
-
# assert Affine.to_gdal(matrix) == (
|
38 |
-
# 1517657.1966021745, 152.8740565703525, 0.0, 4726942.266183584, 0.0, -152.87405657034955)
|
39 |
-
|
40 |
-
def test_download_extent_source_with_parameter(self):
|
41 |
-
from rasterio import Affine
|
42 |
-
from xyzservices import TileProvider
|
43 |
-
from tests.local_tiles_http_server import LocalTilesHttpServer
|
44 |
-
|
45 |
-
listen_port = 8000
|
46 |
-
|
47 |
-
with LocalTilesHttpServer.http_server("localhost", listen_port, directory=TEST_EVENTS_FOLDER):
|
48 |
-
pt0, pt1 = input_bbox
|
49 |
-
zoom = 10
|
50 |
-
|
51 |
-
n_lat = pt0[0]
|
52 |
-
e_lng = pt0[1]
|
53 |
-
s_lat = pt1[0]
|
54 |
-
w_lng = pt1[1]
|
55 |
-
|
56 |
-
local_url = "http://localhost:8000/{parameter}/{z}/{x}/{y}.png"
|
57 |
-
download_extent_args_no_parameter = {"name": "local_tile_provider", "url": LOCAL_URL_TILE, "attribution": ""}
|
58 |
-
download_extent_args = {
|
59 |
-
"no_parameter": download_extent_args_no_parameter,
|
60 |
-
"with_parameter": {"url": local_url, "parameter": "lambda_handler", **download_extent_args_no_parameter}
|
61 |
-
}
|
62 |
-
for _args_names, _args in download_extent_args.items():
|
63 |
-
app_logger.info(f"args_names:{_args_names}.")
|
64 |
-
source = TileProvider(**_args)
|
65 |
-
img, matrix = download_extent(w=w_lng, s=s_lat, e=e_lng, n=n_lat, zoom=zoom, source=source)
|
66 |
-
app_logger.info(f"# DOWNLOAD ENDED, shape: {img.shape} #")
|
67 |
-
np_img = np.ascontiguousarray(img)
|
68 |
-
output_hash = hash_calculate(np_img)
|
69 |
-
assert output_hash == b'UmbkwbPJpRT1XXcLnLUapUDP320w7YhS/AmT3H7u+b4='
|
70 |
-
assert Affine.to_gdal(matrix) == (
|
71 |
-
1517657.1966021745, 152.8740565703525, 0.0, 4726942.266183584, 0.0, -152.87405657034955)
|
72 |
-
|
73 |
-
def test_download_extent_source_with_parameter_key_error(self):
|
74 |
-
from xyzservices import TileProvider
|
75 |
-
|
76 |
-
with self.assertRaises(KeyError):
|
77 |
-
try:
|
78 |
-
pt0, pt1 = input_bbox
|
79 |
-
zoom = 10
|
80 |
-
|
81 |
-
n_lat = pt0[0]
|
82 |
-
e_lng = pt0[1]
|
83 |
-
s_lat = pt1[0]
|
84 |
-
w_lng = pt1[1]
|
85 |
-
|
86 |
-
local_url_tile2 = "http://localhost:8000/{parameter}/{z}/{x}/{y}.png"
|
87 |
-
source = TileProvider(name="local_tile_provider", url=local_url_tile2, attribution="")
|
88 |
-
download_extent(w=w_lng, s=s_lat, e=e_lng, n=n_lat, zoom=zoom, source=source)
|
89 |
-
except KeyError as ke:
|
90 |
-
assert str(ke) == "'parameter'"
|
91 |
-
raise ke
|
92 |
-
|
93 |
-
def test_download_extent_io_error1(self):
|
94 |
-
|
95 |
-
with self.assertRaises(Exception):
|
96 |
-
try:
|
97 |
-
pt0, pt1 = input_bbox
|
98 |
-
zoom = 10
|
99 |
-
|
100 |
-
n_lat = pt0[0]
|
101 |
-
e_lng = pt0[1]
|
102 |
-
s_lat = pt1[0]
|
103 |
-
w_lng = pt1[1]
|
104 |
-
|
105 |
-
download_extent(w=w_lng, s=s_lat, e=e_lng, n=n_lat, zoom=zoom, source=f"http://{LOCAL_URL_TILE}")
|
106 |
-
print("exception not raised")
|
107 |
-
except ConnectionError as ioe1:
|
108 |
-
app_logger.error(f"ioe1:{ioe1}.")
|
109 |
-
msg0 = "HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: /lambda_handler"
|
110 |
-
msg1 = "Caused by NewConnectionError"
|
111 |
-
msg2 = ": Failed to establish a new connection: [Errno 61] Connection refused'))"
|
112 |
-
assert msg0 in str(ioe1)
|
113 |
-
assert msg1 in str(ioe1)
|
114 |
-
assert msg2 in str(ioe1)
|
115 |
-
raise ioe1
|
116 |
-
|
117 |
-
def test_download_extent_io_error2(self):
|
118 |
-
from requests import HTTPError
|
119 |
-
from tests.local_tiles_http_server import LocalTilesHttpServer
|
120 |
-
|
121 |
-
listen_port = 8000
|
122 |
-
with LocalTilesHttpServer.http_server("localhost", listen_port, directory=TEST_EVENTS_FOLDER):
|
123 |
-
pt0, pt1 = input_bbox
|
124 |
-
zoom = 10
|
125 |
-
|
126 |
-
with self.assertRaises(HTTPError):
|
127 |
-
try:
|
128 |
-
n_lat = pt0[0]
|
129 |
-
e_lng = pt0[1]
|
130 |
-
s_lat = pt1[0]
|
131 |
-
w_lng = pt1[1]
|
132 |
-
|
133 |
-
download_extent(w=w_lng, s=s_lat, e=e_lng, n=n_lat, zoom=zoom,
|
134 |
-
source=LOCAL_URL_TILE + "_not_found_raster!")
|
135 |
-
except HTTPError as http_e:
|
136 |
-
app_logger.error(f"ae:{http_e}.")
|
137 |
-
assert "Tile URL resulted in a 404 error. Double-check your tile url:" in str(http_e)
|
138 |
-
raise http_e
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/io_package/test_wrappers_helpers.py
DELETED
@@ -1,78 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
import unittest
|
3 |
-
from unittest.mock import patch
|
4 |
-
|
5 |
-
from samgis_lisa_on_zero.io_package import wrappers_helpers
|
6 |
-
from samgis_lisa_on_zero.io_package.wrappers_helpers import get_parsed_bbox_points_with_dictlist_prompt
|
7 |
-
from samgis_lisa_on_zero.utilities.type_hints import ApiRequestBody
|
8 |
-
from tests import TEST_EVENTS_FOLDER
|
9 |
-
|
10 |
-
|
11 |
-
class WrappersHelpersTest(unittest.TestCase):
|
12 |
-
@staticmethod
|
13 |
-
def test_get_parsed_bbox_other_inputs():
|
14 |
-
for json_filename in ["single_rectangle", "multi_prompt"]:
|
15 |
-
with open(TEST_EVENTS_FOLDER / f"get_parsed_bbox_prompts_{json_filename}.json") as tst_json:
|
16 |
-
inputs_outputs = json.load(tst_json)
|
17 |
-
parsed_input = ApiRequestBody.model_validate(inputs_outputs["input"])
|
18 |
-
output = get_parsed_bbox_points_with_dictlist_prompt(parsed_input)
|
19 |
-
assert output == inputs_outputs["output"]
|
20 |
-
|
21 |
-
def test_get_parsed_bbox_points_with_string_prompt(self):
|
22 |
-
from samgis_lisa_on_zero.io_package.wrappers_helpers import get_parsed_bbox_points_with_string_prompt
|
23 |
-
req = {
|
24 |
-
"bbox":{
|
25 |
-
"ne":{"lat":46.17271333276639,"lng":10.079505443573},"sw":{"lat":46.1677724417049,"lng":10.068830251693727}
|
26 |
-
},
|
27 |
-
"string_prompt":"You are a ...",
|
28 |
-
"zoom":17,
|
29 |
-
"source_type":"Esri.WorldImagery"
|
30 |
-
}
|
31 |
-
print(req)
|
32 |
-
out = get_parsed_bbox_points_with_string_prompt(json.dumps(req))
|
33 |
-
assert isinstance(out, dict)
|
34 |
-
for out_k, req_k in zip(out.keys(), req.keys()):
|
35 |
-
assert isinstance(out_k, str)
|
36 |
-
assert isinstance(req_k, str)
|
37 |
-
|
38 |
-
@patch.object(wrappers_helpers, "providers")
|
39 |
-
def test_get_url_tile(self, providers_mocked):
|
40 |
-
import xyzservices
|
41 |
-
from samgis_lisa_on_zero.io_package.wrappers_helpers import get_url_tile
|
42 |
-
|
43 |
-
from tests import LOCAL_URL_TILE
|
44 |
-
|
45 |
-
local_tile_provider = xyzservices.TileProvider(name="local_tile_provider", url=LOCAL_URL_TILE, attribution="")
|
46 |
-
expected_output = {'name': 'local_tile_provider', 'url': LOCAL_URL_TILE, 'attribution': ''}
|
47 |
-
providers_mocked.query_name.return_value = local_tile_provider
|
48 |
-
assert get_url_tile("OpenStreetMap") == expected_output
|
49 |
-
|
50 |
-
local_url = 'http://localhost:8000/{parameter}/{z}/{x}/{y}.png'
|
51 |
-
local_tile_provider = xyzservices.TileProvider(
|
52 |
-
name="local_tile_provider_param", url=local_url, attribution="", parameter="lamda_handler"
|
53 |
-
)
|
54 |
-
providers_mocked.query_name.return_value = local_tile_provider
|
55 |
-
assert get_url_tile("OpenStreetMap.HOT") == {
|
56 |
-
"parameter": "lamda_handler", 'name': 'local_tile_provider_param', 'url': local_url, 'attribution': ''
|
57 |
-
}
|
58 |
-
|
59 |
-
@staticmethod
|
60 |
-
def test_get_url_tile_real():
|
61 |
-
from samgis_lisa_on_zero.io_package.wrappers_helpers import get_url_tile
|
62 |
-
|
63 |
-
assert get_url_tile("OpenStreetMap") == {
|
64 |
-
'url': 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'max_zoom': 19,
|
65 |
-
'html_attribution': '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
66 |
-
'attribution': '(C) OpenStreetMap contributors',
|
67 |
-
'name': 'OpenStreetMap.Mapnik'}
|
68 |
-
|
69 |
-
html_attribution_hot = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, '
|
70 |
-
html_attribution_hot += 'Tiles style by <a href="https://www.hotosm.org/" target="_blank">Humanitarian '
|
71 |
-
html_attribution_hot += 'OpenStreetMap Team</a> hosted by <a href="https://openstreetmap.fr/" target="_blank">'
|
72 |
-
html_attribution_hot += 'OpenStreetMap France</a>'
|
73 |
-
attribution_hot = '(C) OpenStreetMap contributors, Tiles style by Humanitarian OpenStreetMap Team hosted by '
|
74 |
-
attribution_hot += 'OpenStreetMap France'
|
75 |
-
assert get_url_tile("OpenStreetMap.HOT") == {
|
76 |
-
'url': 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', 'max_zoom': 19,
|
77 |
-
'html_attribution': html_attribution_hot, 'attribution': attribution_hot, 'name': 'OpenStreetMap.HOT'
|
78 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/local_tiles_http_server.py
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
import logging
|
2 |
-
import time
|
3 |
-
import unittest
|
4 |
-
|
5 |
-
|
6 |
-
class LocalTilesHttpServer(unittest.TestCase):
|
7 |
-
from contextlib import contextmanager
|
8 |
-
|
9 |
-
@staticmethod
|
10 |
-
@contextmanager
|
11 |
-
def http_server(host: str, port: int, directory: str):
|
12 |
-
"""Function http_server defined within this test class to avoid pytest error "fixture 'host' not found"."""
|
13 |
-
from functools import partial
|
14 |
-
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
15 |
-
from threading import Thread
|
16 |
-
|
17 |
-
server = ThreadingHTTPServer(
|
18 |
-
(host, port), partial(SimpleHTTPRequestHandler, directory=directory)
|
19 |
-
)
|
20 |
-
print("dir:", directory, "#")
|
21 |
-
server_thread = Thread(target=server.serve_forever, name="http_server")
|
22 |
-
server_thread.start()
|
23 |
-
logging.info(f"listen:: host {host}, port {port}.")
|
24 |
-
|
25 |
-
try:
|
26 |
-
yield
|
27 |
-
finally:
|
28 |
-
server.shutdown()
|
29 |
-
server_thread.join()
|
30 |
-
|
31 |
-
|
32 |
-
if __name__ == '__main__':
|
33 |
-
# from tests import TEST_ROOT_FOLDER
|
34 |
-
from pathlib import Path
|
35 |
-
|
36 |
-
PROJECT_ROOT_FOLDER = Path(globals().get("__file__", "./_")).absolute().parent.parent
|
37 |
-
|
38 |
-
TEST_ROOT_FOLDER = PROJECT_ROOT_FOLDER / "tests"
|
39 |
-
TEST_EVENTS_FOLDER = TEST_ROOT_FOLDER / "events"
|
40 |
-
|
41 |
-
main_listen_port = 8000
|
42 |
-
logging.info(f"http_basedir_serve: {TEST_ROOT_FOLDER}.")
|
43 |
-
with LocalTilesHttpServer.http_server("localhost", main_listen_port, directory=str(TEST_ROOT_FOLDER)):
|
44 |
-
time.sleep(1000)
|
45 |
-
logging.info("""import time; time.sleep(10)""")
|
46 |
-
# logging.info("Http server stopped.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/prediction_api/__init__.py
DELETED
File without changes
|
tests/prediction_api/test_predictors.py
DELETED
@@ -1,64 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
from unittest.mock import patch
|
3 |
-
|
4 |
-
import numpy as np
|
5 |
-
|
6 |
-
from samgis_lisa_on_zero.prediction_api import predictors
|
7 |
-
from samgis_lisa_on_zero.prediction_api.predictors import get_raster_inference, samexporter_predict
|
8 |
-
from tests import TEST_EVENTS_FOLDER
|
9 |
-
|
10 |
-
|
11 |
-
@patch.object(predictors, "SegmentAnythingONNX")
|
12 |
-
def test_get_raster_inference(segment_anything_onnx_mocked):
|
13 |
-
name_fn = "samexporter_predict"
|
14 |
-
|
15 |
-
with open(TEST_EVENTS_FOLDER / f"{name_fn}.json") as tst_json:
|
16 |
-
inputs_outputs = json.load(tst_json)
|
17 |
-
for k, input_output in inputs_outputs.items():
|
18 |
-
model_mocked = segment_anything_onnx_mocked()
|
19 |
-
|
20 |
-
img = np.load(TEST_EVENTS_FOLDER / f"{name_fn}" / k / "img.npy")
|
21 |
-
inference_out = np.load(TEST_EVENTS_FOLDER / f"{name_fn}" / k / "inference_out.npy")
|
22 |
-
mask = np.load(TEST_EVENTS_FOLDER / f"{name_fn}" / k / "mask.npy")
|
23 |
-
prompt = input_output["input"]["prompt"]
|
24 |
-
model_name = input_output["input"]["model_name"]
|
25 |
-
|
26 |
-
model_mocked.embed.return_value = np.array(img)
|
27 |
-
model_mocked.embed.side_effect = None
|
28 |
-
model_mocked.predict_masks.return_value = inference_out
|
29 |
-
model_mocked.predict_masks.side_effect = None
|
30 |
-
print(f"k:{k}.")
|
31 |
-
output_mask, len_inference_out = get_raster_inference(
|
32 |
-
img=img,
|
33 |
-
prompt=prompt,
|
34 |
-
models_instance=model_mocked,
|
35 |
-
model_name=model_name
|
36 |
-
)
|
37 |
-
assert np.array_equal(output_mask, mask)
|
38 |
-
assert len_inference_out == input_output["output"]["n_predictions"]
|
39 |
-
|
40 |
-
|
41 |
-
@patch.object(predictors, "get_raster_inference")
|
42 |
-
@patch.object(predictors, "SegmentAnythingONNX")
|
43 |
-
@patch.object(predictors, "download_extent")
|
44 |
-
@patch.object(predictors, "get_vectorized_raster_as_geojson")
|
45 |
-
def test_samexporter_predict(
|
46 |
-
get_vectorized_raster_as_geojson_mocked,
|
47 |
-
download_extent_mocked,
|
48 |
-
segment_anything_onnx_mocked,
|
49 |
-
get_raster_inference_mocked
|
50 |
-
):
|
51 |
-
"""
|
52 |
-
model_instance = SegmentAnythingONNX()
|
53 |
-
img, matrix = download_extent(DEFAULT_TMS, pt0[0], pt0[1], pt1[0], pt1[1], zoom)
|
54 |
-
transform = get_affine_transform_from_gdal(matrix)
|
55 |
-
mask, n_predictions = get_raster_inference(img, prompt, models_instance, model_name)
|
56 |
-
get_vectorized_raster_as_geojson(mask, matrix)
|
57 |
-
"""
|
58 |
-
aff = 1, 2, 3, 4, 5, 6
|
59 |
-
segment_anything_onnx_mocked.return_value = "SegmentAnythingONNX_instance"
|
60 |
-
download_extent_mocked.return_value = np.zeros((10, 10)), aff
|
61 |
-
get_raster_inference_mocked.return_value = np.ones((10, 10)), 1
|
62 |
-
get_vectorized_raster_as_geojson_mocked.return_value = {"geojson": "{}", "n_shapes_geojson": 2}
|
63 |
-
output = samexporter_predict(bbox=[[1, 2], [3, 4]], prompt=[{}], zoom=10, model_name_key="fastsam")
|
64 |
-
assert output == {"n_predictions": 1, "geojson": "{}", "n_shapes_geojson": 2}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/{test_fastapi_app.py → test_app.py}
RENAMED
@@ -4,19 +4,15 @@ import unittest
|
|
4 |
from unittest.mock import patch
|
5 |
|
6 |
from fastapi.testclient import TestClient
|
7 |
-
|
8 |
-
from samgis_lisa_on_zero import PROJECT_ROOT_FOLDER
|
9 |
-
from samgis_lisa_on_zero.io_package import wrappers_helpers
|
10 |
-
from tests import TEST_EVENTS_FOLDER
|
11 |
-
from tests.local_tiles_http_server import LocalTilesHttpServer
|
12 |
import app
|
13 |
-
from
|
14 |
-
|
15 |
|
16 |
infer_samgis = "/infer_samgis"
|
17 |
response_status_code = "response.status_code:{}."
|
18 |
response_body_loaded = "response.body_loaded:{}."
|
19 |
-
client = TestClient(app)
|
20 |
source = {
|
21 |
'url': 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'max_zoom': 19,
|
22 |
'html_attribution': '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
@@ -81,18 +77,18 @@ class TestFastapiApp(unittest.TestCase):
|
|
81 |
body = response.json()
|
82 |
assert body == {'msg': 'Error - Unprocessable Entity'}
|
83 |
|
84 |
-
def test_index(self):
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
|
97 |
def test_404(self):
|
98 |
response = client.get("/404")
|
@@ -119,7 +115,7 @@ class TestFastapiApp(unittest.TestCase):
|
|
119 |
assert body_loaded == {'success': False}
|
120 |
|
121 |
@patch.object(time, "time")
|
122 |
-
@patch.object(
|
123 |
def test_infer_samgis_500(self, samexporter_predict_mocked, time_mocked):
|
124 |
time_mocked.return_value = 0
|
125 |
samexporter_predict_mocked.side_effect = ValueError("I raise a value error!")
|
@@ -131,11 +127,12 @@ class TestFastapiApp(unittest.TestCase):
|
|
131 |
print(response_body_loaded.format(body))
|
132 |
assert body == {'msg': 'Error - Internal Server Error'}
|
133 |
|
134 |
-
@patch.object(
|
135 |
@patch.object(time, "time")
|
136 |
def test_infer_samgis_real_200(self, time_mocked, get_url_tile_mocked):
|
137 |
import shapely
|
138 |
import xyzservices
|
|
|
139 |
from tests import LOCAL_URL_TILE, TEST_EVENTS_FOLDER
|
140 |
|
141 |
time_mocked.return_value = 0
|
@@ -162,7 +159,7 @@ class TestFastapiApp(unittest.TestCase):
|
|
162 |
assert len(output_geojson.geoms) == 3
|
163 |
|
164 |
@patch.object(time, "time")
|
165 |
-
@patch.object(
|
166 |
def test_infer_samgis_mocked_200(self, samexporter_predict_mocked, time_mocked):
|
167 |
self.maxDiff = None
|
168 |
|
|
|
4 |
from unittest.mock import patch
|
5 |
|
6 |
from fastapi.testclient import TestClient
|
7 |
+
from samgis_web.web import web_helpers
|
|
|
|
|
|
|
|
|
8 |
import app
|
9 |
+
from tests import TEST_EVENTS_FOLDER
|
10 |
+
from samgis_core.utilities import frontend_builder
|
11 |
|
12 |
infer_samgis = "/infer_samgis"
|
13 |
response_status_code = "response.status_code:{}."
|
14 |
response_body_loaded = "response.body_loaded:{}."
|
15 |
+
client = TestClient(app.app)
|
16 |
source = {
|
17 |
'url': 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'max_zoom': 19,
|
18 |
'html_attribution': '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
|
77 |
body = response.json()
|
78 |
assert body == {'msg': 'Error - Unprocessable Entity'}
|
79 |
|
80 |
+
# def test_index(self):
|
81 |
+
# import subprocess
|
82 |
+
#
|
83 |
+
# subprocess.run(["pnpm", "build"], cwd=PROJECT_ROOT_FOLDER / "static")
|
84 |
+
# subprocess.run(["pnpm", "tailwindcss", "-i", "./src/input.css", "-o", "./dist/output.css"],
|
85 |
+
# cwd=PROJECT_ROOT_FOLDER / "static")
|
86 |
+
# response = client.get("/")
|
87 |
+
# assert response.status_code == 200
|
88 |
+
# html_body = response.read().decode("utf-8")
|
89 |
+
# assert "html" in html_body
|
90 |
+
# assert "head" in html_body
|
91 |
+
# assert "body" in html_body
|
92 |
|
93 |
def test_404(self):
|
94 |
response = client.get("/404")
|
|
|
115 |
assert body_loaded == {'success': False}
|
116 |
|
117 |
@patch.object(time, "time")
|
118 |
+
@patch.object(app, "samexporter_predict")
|
119 |
def test_infer_samgis_500(self, samexporter_predict_mocked, time_mocked):
|
120 |
time_mocked.return_value = 0
|
121 |
samexporter_predict_mocked.side_effect = ValueError("I raise a value error!")
|
|
|
127 |
print(response_body_loaded.format(body))
|
128 |
assert body == {'msg': 'Error - Internal Server Error'}
|
129 |
|
130 |
+
@patch.object(web_helpers, "get_url_tile")
|
131 |
@patch.object(time, "time")
|
132 |
def test_infer_samgis_real_200(self, time_mocked, get_url_tile_mocked):
|
133 |
import shapely
|
134 |
import xyzservices
|
135 |
+
from samgis_web.utilities.local_tiles_http_server import LocalTilesHttpServer
|
136 |
from tests import LOCAL_URL_TILE, TEST_EVENTS_FOLDER
|
137 |
|
138 |
time_mocked.return_value = 0
|
|
|
159 |
assert len(output_geojson.geoms) == 3
|
160 |
|
161 |
@patch.object(time, "time")
|
162 |
+
@patch.object(app, "samexporter_predict")
|
163 |
def test_infer_samgis_mocked_200(self, samexporter_predict_mocked, time_mocked):
|
164 |
self.maxDiff = None
|
165 |
|
tests/test_lambda_app.py
DELETED
@@ -1,232 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
import time
|
3 |
-
import unittest
|
4 |
-
from unittest.mock import patch
|
5 |
-
|
6 |
-
from samgis_lisa_on_zero import IS_AWS_LAMBDA
|
7 |
-
|
8 |
-
if IS_AWS_LAMBDA:
|
9 |
-
try:
|
10 |
-
from awslambdaric.lambda_context import LambdaContext
|
11 |
-
|
12 |
-
from samgis_lisa_on_zero.io_package import wrappers_helpers
|
13 |
-
from wrappers import lambda_wrapper
|
14 |
-
from tests.local_tiles_http_server import LocalTilesHttpServer
|
15 |
-
|
16 |
-
|
17 |
-
class TestLambdaApp(unittest.TestCase):
|
18 |
-
@patch.object(time, "time")
|
19 |
-
@patch.object(lambda_wrapper, "samexporter_predict")
|
20 |
-
@patch.object(lambda_wrapper, "get_parsed_bbox_points")
|
21 |
-
@patch.object(lambda_wrapper, "get_parsed_request_body")
|
22 |
-
def test_lambda_handler_500(
|
23 |
-
self,
|
24 |
-
get_parsed_request_body_mocked,
|
25 |
-
get_parsed_bbox_points_mocked,
|
26 |
-
samexporter_predict_mocked,
|
27 |
-
time_mocked
|
28 |
-
):
|
29 |
-
from wrappers.lambda_wrapper import lambda_handler
|
30 |
-
|
31 |
-
time_mocked.return_value = 0
|
32 |
-
get_parsed_request_body_mocked.value = {}
|
33 |
-
get_parsed_bbox_points_mocked.return_value = {"bbox": "bbox_object", "prompt": "prompt_object",
|
34 |
-
"zoom": 1}
|
35 |
-
samexporter_predict_mocked.side_effect = ValueError("I raise a value error!")
|
36 |
-
|
37 |
-
event = {"body": {}, "version": 1.0}
|
38 |
-
lambda_context = LambdaContext(
|
39 |
-
invoke_id="test_invoke_id",
|
40 |
-
client_context=None,
|
41 |
-
cognito_identity=None,
|
42 |
-
epoch_deadline_time_in_ms=time.time()
|
43 |
-
)
|
44 |
-
expected_response_500 = '{"statusCode": 500, "header": {"Content-Type": "application/json"}, '
|
45 |
-
expected_response_500 += '"body": "{\\"duration_run\\": 0, \\"message\\": \\"Internal server error\\", '
|
46 |
-
expected_response_500 += '\\"request_id\\": \\"test_invoke_id\\"}", "isBase64Encoded": false}'
|
47 |
-
|
48 |
-
assert lambda_handler(event, lambda_context) == expected_response_500
|
49 |
-
|
50 |
-
|
51 |
-
@patch.object(time, "time")
|
52 |
-
@patch.object(lambda_wrapper, "get_parsed_request_body")
|
53 |
-
def test_lambda_handler_400(self, get_parsed_request_body_mocked, time_mocked):
|
54 |
-
from wrappers.lambda_wrapper import lambda_handler
|
55 |
-
|
56 |
-
time_mocked.return_value = 0
|
57 |
-
get_parsed_request_body_mocked.return_value = {}
|
58 |
-
|
59 |
-
event = {"body": {}, "version": 1.0}
|
60 |
-
lambda_context = LambdaContext(
|
61 |
-
invoke_id="test_invoke_id",
|
62 |
-
client_context=None,
|
63 |
-
cognito_identity=None,
|
64 |
-
epoch_deadline_time_in_ms=time.time()
|
65 |
-
)
|
66 |
-
|
67 |
-
assert lambda_handler(event, lambda_context) == (
|
68 |
-
'{"statusCode": 400, "header": {"Content-Type": "application/json"}, '
|
69 |
-
'"body": "{\\"duration_run\\": 0, \\"message\\": \\"Bad Request\\", '
|
70 |
-
'\\"request_id\\": \\"test_invoke_id\\"}", "isBase64Encoded": false}')
|
71 |
-
|
72 |
-
|
73 |
-
@patch.object(time, "time")
|
74 |
-
def test_lambda_handler_422(self, time_mocked):
|
75 |
-
from wrappers.lambda_wrapper import lambda_handler
|
76 |
-
|
77 |
-
time_mocked.return_value = 0
|
78 |
-
event = {"body": {}, "version": 1.0}
|
79 |
-
lambda_context = LambdaContext(
|
80 |
-
invoke_id="test_invoke_id",
|
81 |
-
client_context=None,
|
82 |
-
cognito_identity=None,
|
83 |
-
epoch_deadline_time_in_ms=time.time()
|
84 |
-
)
|
85 |
-
|
86 |
-
response_422 = lambda_handler(event, lambda_context)
|
87 |
-
expected_response_422 = '{"statusCode": 422, "header": {"Content-Type": "application/json"}, '
|
88 |
-
expected_response_422 += '"body": "{\\"duration_run\\": 0, \\"message\\": \\"Missing required parameter\\", '
|
89 |
-
expected_response_422 += '\\"request_id\\": \\"test_invoke_id\\"}", "isBase64Encoded": false}'
|
90 |
-
|
91 |
-
assert response_422 == expected_response_422
|
92 |
-
|
93 |
-
|
94 |
-
@patch.object(time, "time")
|
95 |
-
@patch.object(lambda_wrapper, "samexporter_predict")
|
96 |
-
@patch.object(lambda_wrapper, "get_response")
|
97 |
-
@patch.object(lambda_wrapper, "get_parsed_bbox_points")
|
98 |
-
@patch.object(lambda_wrapper, "get_parsed_request_body")
|
99 |
-
def test_lambda_handler_200_mocked(
|
100 |
-
self,
|
101 |
-
get_parsed_request_body_mocked,
|
102 |
-
get_parsed_bbox_points_mocked,
|
103 |
-
get_response_mocked,
|
104 |
-
samexporter_predict_mocked,
|
105 |
-
time_mocked
|
106 |
-
):
|
107 |
-
from wrappers.lambda_wrapper import lambda_handler
|
108 |
-
from tests import TEST_EVENTS_FOLDER
|
109 |
-
|
110 |
-
time_mocked.return_value = 0
|
111 |
-
get_parsed_request_body_mocked.value = {}
|
112 |
-
get_parsed_bbox_points_mocked.return_value = {"bbox": "bbox_object", "prompt": "prompt_object", "zoom": 1}
|
113 |
-
|
114 |
-
response_type = "200"
|
115 |
-
with open(TEST_EVENTS_FOLDER / "get_response.json") as tst_json_get_response:
|
116 |
-
get_response_io = json.load(tst_json_get_response)
|
117 |
-
|
118 |
-
input_200 = {
|
119 |
-
"bbox": {
|
120 |
-
"ne": {"lat": 38.03932961278458, "lng": 15.36808069832851},
|
121 |
-
"sw": {"lat": 37.455509218936974, "lng": 14.632807441554068}
|
122 |
-
},
|
123 |
-
"prompt": [{
|
124 |
-
"type": "point",
|
125 |
-
"data": {"lat": 37.0, "lng": 15.0},
|
126 |
-
"label": 0
|
127 |
-
}],
|
128 |
-
"zoom": 10,
|
129 |
-
"source_type": "OpenStreetMap.Mapnik",
|
130 |
-
"debug": True
|
131 |
-
}
|
132 |
-
|
133 |
-
samexporter_predict_output = get_response_io[response_type]["input"]
|
134 |
-
samexporter_predict_mocked.return_value = samexporter_predict_output
|
135 |
-
samexporter_predict_mocked.side_effect = None
|
136 |
-
get_response_mocked.return_value = get_response_io[response_type]["output"]
|
137 |
-
|
138 |
-
event = {"body": input_200, "version": 1.0}
|
139 |
-
|
140 |
-
lambda_context = LambdaContext(
|
141 |
-
invoke_id="test_invoke_id",
|
142 |
-
client_context=None,
|
143 |
-
cognito_identity=None,
|
144 |
-
epoch_deadline_time_in_ms=time.time()
|
145 |
-
)
|
146 |
-
|
147 |
-
response_200 = lambda_handler(event, lambda_context)
|
148 |
-
expected_response_200 = get_response_io[response_type]["output"]
|
149 |
-
print(f"types: response_200:{type(response_200)}, expected:{type(expected_response_200)}.")
|
150 |
-
assert response_200 == expected_response_200
|
151 |
-
|
152 |
-
|
153 |
-
@patch.object(wrappers_helpers, "get_url_tile")
|
154 |
-
def test_lambda_handler_200_real_single_multi_point(self, get_url_tile_mocked):
|
155 |
-
import xyzservices
|
156 |
-
import shapely
|
157 |
-
|
158 |
-
from wrappers.lambda_wrapper import lambda_handler
|
159 |
-
from tests import LOCAL_URL_TILE, TEST_EVENTS_FOLDER
|
160 |
-
|
161 |
-
local_tile_provider = xyzservices.TileProvider(name="local_tile_provider", url=LOCAL_URL_TILE,
|
162 |
-
attribution="")
|
163 |
-
get_url_tile_mocked.return_value = local_tile_provider
|
164 |
-
fn_name = "lambda_handler"
|
165 |
-
invoke_id = "test_invoke_id"
|
166 |
-
|
167 |
-
for json_filename in [
|
168 |
-
"single_point",
|
169 |
-
"multi_prompt",
|
170 |
-
"single_rectangle"
|
171 |
-
]:
|
172 |
-
with open(TEST_EVENTS_FOLDER / f"{fn_name}_{json_filename}.json") as tst_json:
|
173 |
-
inputs_outputs = json.load(tst_json)
|
174 |
-
lambda_context = LambdaContext(
|
175 |
-
invoke_id=invoke_id,
|
176 |
-
client_context=None,
|
177 |
-
cognito_identity=None,
|
178 |
-
epoch_deadline_time_in_ms=time.time()
|
179 |
-
)
|
180 |
-
expected_response_dict = inputs_outputs["output"]
|
181 |
-
listen_port = 8000
|
182 |
-
expected_response_body = json.loads(expected_response_dict["body"])
|
183 |
-
|
184 |
-
with LocalTilesHttpServer.http_server("localhost", listen_port, directory=TEST_EVENTS_FOLDER):
|
185 |
-
input_event = inputs_outputs["input"]
|
186 |
-
input_event_body = json.loads(input_event["body"])
|
187 |
-
input_event["body"] = json.dumps(input_event_body)
|
188 |
-
response = lambda_handler(event=input_event, context=lambda_context)
|
189 |
-
|
190 |
-
response_dict = json.loads(response)
|
191 |
-
assert response_dict["statusCode"] == 200
|
192 |
-
body_dict = json.loads(response_dict["body"])
|
193 |
-
assert body_dict["n_predictions"] == 1
|
194 |
-
assert body_dict["request_id"] == invoke_id
|
195 |
-
assert body_dict["message"] == "ok"
|
196 |
-
assert body_dict["n_shapes_geojson"] == expected_response_body["n_shapes_geojson"]
|
197 |
-
|
198 |
-
output_geojson = shapely.from_geojson(body_dict["geojson"])
|
199 |
-
print("output_geojson::", type(output_geojson))
|
200 |
-
assert isinstance(output_geojson, shapely.GeometryCollection)
|
201 |
-
assert len(output_geojson.geoms) == expected_response_body["n_shapes_geojson"]
|
202 |
-
|
203 |
-
|
204 |
-
def test_debug(self):
|
205 |
-
from wrappers.lambda_wrapper import lambda_handler
|
206 |
-
|
207 |
-
input_event = {
|
208 |
-
'bbox': {
|
209 |
-
'ne': {'lat': 46.302592089330524, 'lng': 9.49493408203125},
|
210 |
-
'sw': {'lat': 46.14011755129237, 'lng': 9.143371582031252}},
|
211 |
-
'prompt': [
|
212 |
-
{'id': 166, 'type': 'point', 'data': {'lat': 46.18244521829928, 'lng': 9.418544769287111},
|
213 |
-
'label': 1}
|
214 |
-
],
|
215 |
-
'zoom': 12, 'source_type': 'OpenStreetMap'
|
216 |
-
}
|
217 |
-
lambda_context = LambdaContext(
|
218 |
-
invoke_id="test_invoke_id",
|
219 |
-
client_context=None,
|
220 |
-
cognito_identity=None,
|
221 |
-
epoch_deadline_time_in_ms=time.time()
|
222 |
-
)
|
223 |
-
response = lambda_handler(event=input_event, context=lambda_context)
|
224 |
-
print(response)
|
225 |
-
except ModuleNotFoundError as mnfe:
|
226 |
-
print("missing awslambdaric...")
|
227 |
-
raise mnfe
|
228 |
-
|
229 |
-
|
230 |
-
if __name__ == '__main__':
|
231 |
-
if IS_AWS_LAMBDA:
|
232 |
-
unittest.main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|