Skip to content

Commit

Permalink
restructure
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsmrynk committed Nov 12, 2023
1 parent 53a7e99 commit 998ba41
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 255 deletions.
17 changes: 8 additions & 9 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,23 @@ 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:
boundary_gdf = boundary_gdf.set_crs(f'EPSG:{config.data.epsg_code}')
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:
Expand Down
91 changes: 37 additions & 54 deletions src/utils/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,80 @@
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):
"""
| 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+)$')

for path in cached_tiles_dir_path.iterdir():
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]
28 changes: 7 additions & 21 deletions src/utils/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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')
Expand Down
1 change: 0 additions & 1 deletion src/utils/tests/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
83 changes: 43 additions & 40 deletions src/utils/tests/data/data_test_filter_cached_coordinates.py
Original file line number Diff line number Diff line change
@@ -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))]
Loading

0 comments on commit 998ba41

Please sign in to comment.