diff --git a/src/main.py b/src/main.py index c19bb32..e2c76fa 100644 --- a/src/main.py +++ b/src/main.py @@ -62,9 +62,6 @@ def main(): # endregion # region Initializing - coordinator = Coordinator() - logger.debug('Coordinator initialized') - if config.data.boundary_shape_file_path: boundary_gdf = gpd.read_file(config.data.boundary_shape_file_path) if boundary_gdf.crs is None: @@ -72,14 +69,16 @@ def main(): else: boundary_gdf = boundary_gdf.to_crs(f'EPSG:{config.data.epsg_code}') boundary_gdf = boundary_gdf[['geometry']] - # noinspection PyTypeChecker - coordinates = coordinator.get_valid_coordinates(bounding_box=config.data.bounding_box, - epsg_code=config.data.epsg_code, - boundary_gdf=boundary_gdf) else: boundary_gdf = None - # noinspection PyTypeChecker - coordinates = coordinator.get_coordinates(bounding_box=config.data.bounding_box) + + # noinspection PyTypeChecker + coordinator = Coordinator(bounding_box=config.data.bounding_box, + epsg_code=config.data.epsg_code, + gdf_boundary=boundary_gdf) + logger.debug('Coordinator initialized') + + coordinates = coordinator.get_coordinates() logger.debug('Coordinates calculated') if not config.data.ignore_cached_tiles: diff --git a/src/utils/coordinator.py b/src/utils/coordinator.py index 80d38aa..c237b9c 100644 --- a/src/utils/coordinator.py +++ b/src/utils/coordinator.py @@ -2,69 +2,54 @@ from pathlib import Path import geopandas as gpd +import numpy as np import src.utils.settings as settings from src.utils.grid_generator import GridGenerator class Coordinator: - @staticmethod - def get_coordinates(bounding_box): + def __init__(self, + bounding_box, + epsg_code, + gdf_boundary): """ - | Returns the coordinates of the top left corner of each tile in the area of the bounding box. - The bounding box is quantized to the image size in meters. + | Constructor method - :param (int, int, int, int) bounding_box: bounding box (x_1, y_1, x_2, y_2) - :returns: coordinates (x, y) of each tile - :rtype: list[(int, int)] + :param (int, int, int, int) bounding_box: bounding box (x_min, y_min, x_max, y_max) + :param int epsg_code: epsg code of the coordinate reference system + :param gpd.GeoDataFrame or None gdf_boundary: boundary geodataframe + :returns: None + :rtype: None """ - coordinates = [] - - bounding_box = (bounding_box[0] - (bounding_box[0] % settings.IMAGE_SIZE_METERS), - bounding_box[1] - (bounding_box[1] % settings.IMAGE_SIZE_METERS), - bounding_box[2], - bounding_box[3]) + self.bounding_box = bounding_box + self.epsg_code = epsg_code + self.gdf_boundary = gdf_boundary - columns = (bounding_box[2] - bounding_box[0]) // settings.IMAGE_SIZE_METERS - if (bounding_box[2] - bounding_box[0]) % settings.IMAGE_SIZE_METERS: - columns += 1 + def get_coordinates(self): + """ + | Returns the coordinates of the top left corner of each tile. - rows = (bounding_box[3] - bounding_box[1]) // settings.IMAGE_SIZE_METERS - if (bounding_box[3] - bounding_box[1]) % settings.IMAGE_SIZE_METERS: - rows += 1 + :returns: coordinates (x_min, y_max) of each tile + :rtype: np.ndarray[np.int32] + """ + grid_generator = GridGenerator(bounding_box=self.bounding_box, + epsg_code=self.epsg_code) - for row in range(rows): - for column in range(columns): - coordinates.append((bounding_box[0] + column * settings.IMAGE_SIZE_METERS, - bounding_box[1] + (row + 1) * settings.IMAGE_SIZE_METERS)) + coordinates = grid_generator.get_coordinates(tile_size=settings.IMAGE_SIZE_METERS, + quantize=True) - return coordinates + coordinates[:, 1] += settings.IMAGE_SIZE_METERS - def get_valid_coordinates(self, - bounding_box, - epsg_code, - boundary_gdf): - """ - | Returns the coordinates of the top left corner of each tile in the area of the boundary geodataframe. - - :param (int, int, int, int) bounding_box: bounding box (x_1, y_1, x_2, y_2) - :param int epsg_code: epsg code of the coordinate reference system - :param gpd.GeoDataFrame boundary_gdf: boundary geodataframe - :returns: valid coordinates (x, y) of each tile - :rtype: list[(int, int)] - """ - coordinates = self.get_coordinates(bounding_box) + if self.gdf_boundary is None: + return coordinates - grid_generator = GridGenerator(bounding_box=bounding_box, - epsg_code=epsg_code) - grid_gdf = grid_generator.get_grid(tile_size=settings.IMAGE_SIZE_METERS, + gdf_grid = grid_generator.get_grid(tile_size=settings.IMAGE_SIZE_METERS, quantize=True) - intersections = list(grid_gdf['geometry'].intersects(boundary_gdf['geometry'][0])) - valid_coordinates = [coordinates_element for (coordinates_element, valid) in zip(coordinates, intersections) - if valid] + mask = np.array(gdf_grid['geometry'].intersects(self.gdf_boundary['geometry'][0]), dtype=bool) - return valid_coordinates + return coordinates[mask] @staticmethod def filter_cached_coordinates(coordinates, output_dir_path): @@ -72,17 +57,17 @@ def filter_cached_coordinates(coordinates, output_dir_path): | Returns the filtered coordinates. If a tile has already been processed (its shape file directory exists in the cached_tiles directory), its coordinates are removed. - :param list[(int, int)] coordinates: coordinates (x, y) of each tile + :param np.ndarray[np.int32] coordinates: coordinates (x_min, y_max) of each tile :param str or Path output_dir_path: path to the output directory - :returns: filtered coordinates (x, y) of each tile - :rtype: list[(int, int)] + :returns: filtered coordinates (x_min, y_max) of each tile + :rtype: np.ndarray[np.int32] """ cached_tiles_dir_path = Path(output_dir_path) / 'cached_tiles' if not cached_tiles_dir_path.is_dir(): return coordinates - filtered_coordinates = coordinates[:] + mask = np.ones(coordinates.shape[0], dtype=bool) pattern = re.compile(r'^(-?\d+)_(-?\d+)$') @@ -90,9 +75,7 @@ def filter_cached_coordinates(coordinates, output_dir_path): match = pattern.search(path.name) if match: - cached_coordinates = (int(match.group(1)), int(match.group(2))) - - if cached_coordinates in coordinates: - filtered_coordinates.remove(cached_coordinates) + coordinates_cached = np.array([int(match.group(1)), int(match.group(2))], dtype=np.int32) + mask &= np.any(coordinates != coordinates_cached, axis=1) - return filtered_coordinates + return coordinates[mask] diff --git a/src/utils/tests/conftest.py b/src/utils/tests/conftest.py index 8b7bccb..edb2357 100644 --- a/src/utils/tests/conftest.py +++ b/src/utils/tests/conftest.py @@ -3,9 +3,6 @@ import geopandas as gpd import pytest from shapely.geometry import box as Box # PEP8 compliant -from shapely.geometry import Polygon - -from src.utils.coordinator import Coordinator @pytest.fixture(scope='session') @@ -27,17 +24,6 @@ def shape_file_dir_path(tmp_path_factory): return shape_file_dir_path -@pytest.fixture(scope='session') -def coordinator(): - """ - | Returns a coordinator instance. - - :returns: coordinator - :rtype: Coordinator - """ - return Coordinator() - - @pytest.fixture(scope='session') def output_dir_path_no_cached_tiles_dir(tmp_path_factory): """ @@ -92,19 +78,19 @@ def output_dir_path_not_empty_cached_tiles_dir(tmp_path_factory): @pytest.fixture(scope='session') -def boundary_gdf(): +def gdf_boundary(): """ | Returns a boundary geodataframe. :returns: boundary geodataframe :rtype: gpd.GeoDataFrame """ - polygon = Polygon([[-512, -512], - [512, -512], - [512, 512], - [-512, 512]]) - boundary_gdf = gpd.GeoDataFrame(geometry=[polygon], crs='EPSG:25832') - return boundary_gdf + polygon = Box(-512, -512, 512, 512) + + gdf_boundary = gpd.GeoDataFrame(geometry=[polygon], + crs='EPSG:25832') + + return gdf_boundary @pytest.fixture(scope='session') diff --git a/src/utils/tests/data/__init__.py b/src/utils/tests/data/__init__.py index 5e0f6c3..309759a 100644 --- a/src/utils/tests/data/__init__.py +++ b/src/utils/tests/data/__init__.py @@ -3,6 +3,5 @@ from .data_test_filter_cached_coordinates import * from .data_test_get_argument_parser import * from .data_test_get_coordinates import * -from .data_test_get_valid_coordinates import * from .data_test_Postprocessing import * from .data_test_WMSLayerError import * diff --git a/src/utils/tests/data/data_test_filter_cached_coordinates.py b/src/utils/tests/data/data_test_filter_cached_coordinates.py index 611bdc1..a89437d 100644 --- a/src/utils/tests/data/data_test_filter_cached_coordinates.py +++ b/src/utils/tests/data/data_test_filter_cached_coordinates.py @@ -1,46 +1,49 @@ +import numpy as np + + parameters_filter_cached_coordinates_no_cached_tiles_dir = \ - [([(512, 768), (768, 768), (512, 1024), (768, 1024)], - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ([(512, -768), (768, -768), (512, -512), (768, -512)], - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ([(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)], - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ([(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)], - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ([(-256, 0), (0, 0), (-256, 256), (0, 256)], - [(-256, 0), (0, 0), (-256, 256), (0, 256)])] + [(np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + (np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + (np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + (np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + (np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32))] parameters_filter_cached_coordinates_empty_cached_tiles_dir = \ - [([(512, 768), (768, 768), (512, 1024), (768, 1024)], - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ([(512, -768), (768, -768), (512, -512), (768, -512)], - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ([(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)], - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ([(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)], - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ([(-256, 0), (0, 0), (-256, 256), (0, 256)], - [(-256, 0), (0, 0), (-256, 256), (0, 256)])] + [(np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + (np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + (np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + (np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + (np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32))] parameters_filter_cached_coordinates_not_empty_cached_tiles_dir = \ - [([(512, 768), (768, 768), (512, 1024), (768, 1024)], - [(512, 768), (768, 768)]), - ([(512, -768), (768, -768), (512, -512), (768, -512)], - [(512, -768), (768, -768)]), - ([(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)], - [(-1024, -768), (-768, -768)]), - ([(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)], - [(-1024, 768), (-768, 768)]), - ([(-256, 0), (0, 0), (-256, 256), (0, 256)], - [(-256, 0), (0, 0)]), + [(np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32), + np.array([[512, 768], [768, 768]], dtype=np.int32)), + (np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32), + np.array([[512, -768], [768, -768]], dtype=np.int32)), + (np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32), + np.array([[-1024, -768], [-768, -768]], dtype=np.int32)), + (np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32), + np.array([[-1024, 768], [-768, 768]], dtype=np.int32)), + (np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32), + np.array([[-256, 0], [0, 0]], dtype=np.int32)), - ([(512, 1024), (768, 1024)], - []), - ([(512, -512), (768, -512)], - []), - ([(-1024, -512), (-768, -512)], - []), - ([(-1024, 1024), (-768, 1024)], - []), - ([(-256, 256), (0, 256)], - [])] + (np.array([[512, 1024], [768, 1024]], dtype=np.int32), + np.empty(shape=(0, 2), dtype=np.int32)), + (np.array([[512, -512], [768, -512]], dtype=np.int32), + np.empty(shape=(0, 2), dtype=np.int32)), + (np.array([[-1024, -512], [-768, -512]], dtype=np.int32), + np.empty(shape=(0, 2), dtype=np.int32)), + (np.array([[-1024, 1024], [-768, 1024]], dtype=np.int32), + np.empty(shape=(0, 2), dtype=np.int32)), + (np.array([[-256, 256], [0, 256]], dtype=np.int32), + np.empty(shape=(0, 2), dtype=np.int32))] diff --git a/src/utils/tests/data/data_test_get_coordinates.py b/src/utils/tests/data/data_test_get_coordinates.py index 6310e5f..e5f4812 100644 --- a/src/utils/tests/data/data_test_get_coordinates.py +++ b/src/utils/tests/data/data_test_get_coordinates.py @@ -1,43 +1,81 @@ -parameters_get_coordinates = [((512, 512, 1024, 1024), - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ((512, -1024, 1024, -512), - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ((-1024, -1024, -512, -512), - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ((-1024, 512, -512, 1024), - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ((-256, -256, 256, 256), - [(-256, 0), (0, 0), (-256, 256), (0, 256)]), - - ((640, 640, 1024, 1024), - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ((640, -896, 1024, -512), - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ((-896, -896, -512, -512), - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ((-896, 640, -512, 1024), - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ((-128, -128, 256, 256), - [(-256, 0), (0, 0), (-256, 256), (0, 256)]), - - ((512, 512, 896, 896), - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ((512, -1024, 896, -640), - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ((-1024, -1024, -640, -640), - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ((-1024, 512, -640, 896), - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ((-256, -256, 128, 128), - [(-256, 0), (0, 0), (-256, 256), (0, 256)]), - - ((640, 640, 896, 896), - [(512, 768), (768, 768), (512, 1024), (768, 1024)]), - ((640, -896, 896, -640), - [(512, -768), (768, -768), (512, -512), (768, -512)]), - ((-896, -896, -640, -640), - [(-1024, -768), (-768, -768), (-1024, -512), (-768, -512)]), - ((-896, 640, -640, 896), - [(-1024, 768), (-768, 768), (-1024, 1024), (-768, 1024)]), - ((-128, -128, 128, 128), - [(-256, 0), (0, 0), (-256, 256), (0, 256)])] +import numpy as np + + +parameters_get_coordinates_no_gdf_boundary = \ + [((512, 512, 1024, 1024), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + ((512, -1024, 1024, -512), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + ((-1024, -1024, -512, -512), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + ((-1024, 512, -512, 1024), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + ((-256, -256, 256, 256), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32)), + + ((640, 640, 1024, 1024), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + ((640, -896, 1024, -512), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + ((-896, -896, -512, -512), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + ((-896, 640, -512, 1024), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + ((-128, -128, 256, 256), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32)), + + ((512, 512, 896, 896), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + ((512, -1024, 896, -640), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + ((-1024, -1024, -640, -640), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + ((-1024, 512, -640, 896), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + ((-256, -256, 128, 128), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32)), + + ((640, 640, 896, 896), + np.array([[512, 768], [768, 768], [512, 1024], [768, 1024]], dtype=np.int32)), + ((640, -896, 896, -640), + np.array([[512, -768], [768, -768], [512, -512], [768, -512]], dtype=np.int32)), + ((-896, -896, -640, -640), + np.array([[-1024, -768], [-768, -768], [-1024, -512], [-768, -512]], dtype=np.int32)), + ((-896, 640, -640, 896), + np.array([[-1024, 768], [-768, 768], [-1024, 1024], [-768, 1024]], dtype=np.int32)), + ((-128, -128, 128, 128), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32))] + +parameters_get_coordinates = \ + [((-256, -256, 256, 256), + np.array([[-256, 0], [0, 0], [-256, 256], [0, 256]], dtype=np.int32)), + + ((-512, -512, 512, 512), + np.array([[-512, -256], [-256, -256], [0, -256], [256, -256], + [-512, 0], [-256, 0], [0, 0], [256, 0], + [-512, 256], [-256, 256], [0, 256], [256, 256], + [-512, 512], [-256, 512], [0, 512], [256, 512]], dtype=np.int32)), + + ((-768, -768, 768, 768), + np.array([[-768, -512], [-512, -512], [-256, -512], [0, -512], [256, -512], [512, -512], + [-768, -256], [-512, -256], [-256, -256], [0, -256], [256, -256], [512, -256], + [-768, 0], [-512, 0], [-256, 0], [0, 0], [256, 0], [512, 0], + [-768, 256], [-512, 256], [-256, 256], [0, 256], [256, 256], [512, 256], + [-768, 512], [-512, 512], [-256, 512], [0, 512], [256, 512], [512, 512], + [-768, 768], [-512, 768], [-256, 768], [0, 768], [256, 768], [512, 768]], dtype=np.int32)), + ((-1024, -1024, 1024, 1024), + np.array([[-768, -512], [-512, -512], [-256, -512], [0, -512], [256, -512], [512, -512], + [-768, -256], [-512, -256], [-256, -256], [0, -256], [256, -256], [512, -256], + [-768, 0], [-512, 0], [-256, 0], [0, 0], [256, 0], [512, 0], + [-768, 256], [-512, 256], [-256, 256], [0, 256], [256, 256], [512, 256], + [-768, 512], [-512, 512], [-256, 512], [0, 512], [256, 512], [512, 512], + [-768, 768], [-512, 768], [-256, 768], [0, 768], [256, 768], [512, 768]], dtype=np.int32)), + + ((768, 768, 1024, 1024), + np.empty(shape=(0, 2), dtype=np.int32)), + ((768, -768, 1024, -1024), + np.empty(shape=(0, 2), dtype=np.int32)), + ((-768, -768, -1024, -1024), + np.empty(shape=(0, 2), dtype=np.int32)), + ((-768, 768, -1024, 1024), + np.empty(shape=(0, 2), dtype=np.int32))] diff --git a/src/utils/tests/data/data_test_get_valid_coordinates.py b/src/utils/tests/data/data_test_get_valid_coordinates.py deleted file mode 100644 index 482fc55..0000000 --- a/src/utils/tests/data/data_test_get_valid_coordinates.py +++ /dev/null @@ -1,32 +0,0 @@ -parameters_get_valid_coordinates = [((-256, -256, 256, 256), - [(-256, 0), (0, 0), (-256, 256), (0, 256)]), - - ((-512, -512, 512, 512), - [(-512, -256), (-256, -256), (0, -256), (256, -256), - (-512, 0), (-256, 0), (0, 0), (256, 0), - (-512, 256), (-256, 256), (0, 256), (256, 256), - (-512, 512), (-256, 512), (0, 512), (256, 512)]), - - ((-768, -768, 768, 768), - [(-768, -512), (-512, -512), (-256, -512), (0, -512), (256, -512), (512, -512), - (-768, -256), (-512, -256), (-256, -256), (0, -256), (256, -256), (512, -256), - (-768, 0), (-512, 0), (-256, 0), (0, 0), (256, 0), (512, 0), - (-768, 256), (-512, 256), (-256, 256), (0, 256), (256, 256), (512, 256), - (-768, 512), (-512, 512), (-256, 512), (0, 512), (256, 512), (512, 512), - (-768, 768), (-512, 768), (-256, 768), (0, 768), (256, 768), (512, 768)]), - ((-1024, -1024, 1024, 1024), - [(-768, -512), (-512, -512), (-256, -512), (0, -512), (256, -512), (512, -512), - (-768, -256), (-512, -256), (-256, -256), (0, -256), (256, -256), (512, -256), - (-768, 0), (-512, 0), (-256, 0), (0, 0), (256, 0), (512, 0), - (-768, 256), (-512, 256), (-256, 256), (0, 256), (256, 256), (512, 256), - (-768, 512), (-512, 512), (-256, 512), (0, 512), (256, 512), (512, 512), - (-768, 768), (-512, 768), (-256, 768), (0, 768), (256, 768), (512, 768)]), - - ((768, 768, 1024, 1024), - []), - ((768, -768, 1024, -1024), - []), - ((-768, -768, -1024, -1024), - []), - ((-768, 768, -1024, 1024), - [])] diff --git a/src/utils/tests/test_coordinator.py b/src/utils/tests/test_coordinator.py index 7f99dc6..833d655 100644 --- a/src/utils/tests/test_coordinator.py +++ b/src/utils/tests/test_coordinator.py @@ -1,70 +1,86 @@ from pathlib import Path import geopandas as gpd +import geopandas.testing import pytest from src.utils.coordinator import Coordinator from src.utils.tests.data import * -def test_init(): +def test_init(gdf_boundary): """ | Tests __init__(). + :param gpd.GeoDataFrame gdf_boundary: boundary geodataframe :returns: None :rtype: None """ - coordinator = Coordinator() + coordinator = Coordinator(bounding_box=(-512, -512, 512, 512), + epsg_code=25832, + gdf_boundary=gdf_boundary) assert isinstance(coordinator, Coordinator) - assert list(coordinator.__dict__.keys()) == [] + assert list(coordinator.__dict__.keys()) == ['bounding_box', 'epsg_code', 'gdf_boundary'] + assert isinstance(coordinator.bounding_box, tuple) + for coordinate in coordinator.bounding_box: + assert isinstance(coordinate, int) + assert coordinator.bounding_box == (-512, -512, 512, 512) -@pytest.mark.parametrize('test_input, expected', parameters_get_coordinates) -def test_get_coordinates(test_input, expected): + assert isinstance(coordinator.epsg_code, int) + assert coordinator.epsg_code == 25832 + + assert isinstance(coordinator.gdf_boundary, gpd.GeoDataFrame) + gpd.testing.assert_geodataframe_equal(coordinator.gdf_boundary, + gdf_boundary, + check_index_type=False) + + +@pytest.mark.parametrize('test_input, expected', parameters_get_coordinates_no_gdf_boundary) +def test_get_coordinates_no_gdf_boundary(test_input, + expected): """ | Tests get_coordinates() with different bounding boxes. + | The boundary geodataframe is not used. - :param (int, int, int, int) test_input: bounding box (x_1, y_1, x_2, y_2) of the area from - the bottom left corner to the top right corner - :param list[(int, int)] expected: coordinates (x, y) of each tile + :param (int, int, int, int) test_input: bounding box (x_min, y_min, x_max, y_max) + :param np.ndarray[np.int32] expected: coordinates (x_min, y_max) of each tile :returns: None :rtype: None """ - coordinates = Coordinator.get_coordinates(bounding_box=test_input) + coordinator = Coordinator(bounding_box=test_input, + epsg_code=25832, + gdf_boundary=None) - for coordinates_element in coordinates: - assert isinstance(coordinates_element[0], int) - assert isinstance(coordinates_element[1], int) + coordinates = coordinator.get_coordinates() - assert coordinates == expected + assert coordinates.dtype == expected.dtype + np.testing.assert_array_equal(coordinates, expected) -@pytest.mark.parametrize('test_input, expected', parameters_get_valid_coordinates) -def test_get_valid_coordinates(test_input, - expected, - coordinator, - boundary_gdf): +@pytest.mark.parametrize('test_input, expected', parameters_get_coordinates) +def test_get_coordinates(test_input, + expected, + gdf_boundary): """ - | Tests get_valid_coordinates() with different bounding boxes. + | Tests get_coordinates() with different bounding boxes. + | The boundary geodataframe is used. - :param (int, int, int, int) test_input: bounding box (x_1, y_1, x_2, y_2) of the area from - the bottom left corner to the top right corner - :param list[(int, int)] expected: valid coordinates (x, y) of each tile - :param Coordinator coordinator: coordinator - :param gpd.GeoDataFrame boundary_gdf: boundary geodataframe + :param (int, int, int, int) test_input: bounding box (x_min, y_min, x_max, y_max) + :param np.ndarray[np.int32] expected: coordinates (x_min, y_max) of each tile + :param gpd.GeoDataFrame gdf_boundary: boundary geodataframe :returns: None :rtype: None """ - valid_coordinates = coordinator.get_valid_coordinates(bounding_box=test_input, - epsg_code=25832, - boundary_gdf=boundary_gdf) + coordinator = Coordinator(bounding_box=test_input, + epsg_code=25832, + gdf_boundary=gdf_boundary) - for valid_coordinates_element in valid_coordinates: - assert isinstance(valid_coordinates_element[0], int) - assert isinstance(valid_coordinates_element[1], int) + coordinates = coordinator.get_coordinates() - assert valid_coordinates == expected + assert coordinates.dtype == expected.dtype + np.testing.assert_array_equal(coordinates, expected) @pytest.mark.parametrize('test_input, expected', parameters_filter_cached_coordinates_no_cached_tiles_dir) @@ -75,20 +91,17 @@ def test_filter_cached_coordinates_no_cached_tiles_dir(test_input, | Tests filter_cached_coordinates() with different coordinates. | The cached_tiles directory does not exist. - :param list[(int, int)] test_input: coordinates (x, y) of each tile - :param list[(int, int)] expected: filtered coordinates (x, y) of each tile + :param np.ndarray[np.int32] test_input: coordinates (x_min, y_max) of each tile + :param np.ndarray[np.int32] expected: filtered coordinates (x_min, y_max) of each tile :param Path output_dir_path_no_cached_tiles_dir: path to the output directory :returns: None :rtype: None """ - filtered_coordinates = Coordinator.filter_cached_coordinates(coordinates=test_input, + coordinates_filtered = Coordinator.filter_cached_coordinates(coordinates=test_input, output_dir_path=output_dir_path_no_cached_tiles_dir) - for filtered_coordinates_element in filtered_coordinates: - assert isinstance(filtered_coordinates_element[0], int) - assert isinstance(filtered_coordinates_element[1], int) - - assert filtered_coordinates == expected + assert coordinates_filtered.dtype == expected.dtype + np.testing.assert_array_equal(coordinates_filtered, expected) @pytest.mark.parametrize('test_input, expected', parameters_filter_cached_coordinates_empty_cached_tiles_dir) @@ -99,20 +112,17 @@ def test_filter_cached_coordinates_empty_cached_tiles_dir(test_input, | Tests filter_cached_coordinates() with different coordinates. | The cached_tiles directory is empty. - :param list[(int, int)] test_input: coordinates (x, y) of each tile - :param list[(int, int)] expected: filtered coordinates (x, y) of each tile + :param np.ndarray[np.int32] test_input: coordinates (x_min, y_max) of each tile + :param np.ndarray[np.int32] expected: filtered coordinates (x_min, y_max) of each tile :param Path output_dir_path_empty_cached_tiles_dir: path to the output directory :returns: None :rtype: None """ - filtered_coordinates = Coordinator.filter_cached_coordinates(coordinates=test_input, + coordinates_filtered = Coordinator.filter_cached_coordinates(coordinates=test_input, output_dir_path=output_dir_path_empty_cached_tiles_dir) - for filtered_coordinates_element in filtered_coordinates: - assert isinstance(filtered_coordinates_element[0], int) - assert isinstance(filtered_coordinates_element[1], int) - - assert filtered_coordinates == expected + assert coordinates_filtered.dtype == expected.dtype + np.testing.assert_array_equal(coordinates_filtered, expected) @pytest.mark.parametrize('test_input, expected', parameters_filter_cached_coordinates_not_empty_cached_tiles_dir) @@ -123,18 +133,15 @@ def test_filter_cached_coordinates_not_empty_cached_tiles_dir(test_input, | Tests filter_cached_coordinates() with different coordinates. | The cached_tiles directory is not empty. - :param list[(int, int)] test_input: coordinates (x, y) of each tile - :param list[(int, int)] expected: filtered coordinates (x, y) of each tile + :param np.ndarray[np.int32] test_input: coordinates (x_min, y_max) of each tile + :param np.ndarray[np.int32] expected: filtered coordinates (x_min, y_max) of each tile :param Path output_dir_path_not_empty_cached_tiles_dir: path to the output directory :returns: None :rtype: None """ - filtered_coordinates = \ + coordinates_filtered = \ Coordinator.filter_cached_coordinates(coordinates=test_input, output_dir_path=output_dir_path_not_empty_cached_tiles_dir) - for filtered_coordinates_element in filtered_coordinates: - assert isinstance(filtered_coordinates_element[0], int) - assert isinstance(filtered_coordinates_element[1], int) - - assert filtered_coordinates == expected + assert coordinates_filtered.dtype == expected.dtype + np.testing.assert_array_equal(coordinates_filtered, expected)