SerpentineZoneSampling / geo_tools.py
dilithjay's picture
Set label format to use starting letters of sites
c424639
import cv2
import fiona
from pyproj import Transformer
import numpy as np
from tqdm import tqdm
from grid_optim import get_optimal_grid
def shapefile_to_latlong(file_path: str):
c = fiona.open(file_path)
contours = []
transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
for poly in c:
coords = poly["geometry"].coordinates
for coord_set in coords:
contours.append(
np.array(
list(
transformer.itransform(
coord_set[0] if len(coord_set) == 1 else coord_set
)
)
)
)
return contours
def mask_shapefile_to_grid_indices(
file_path: str, side_len_m: float = 100, meters_per_px: float = 10
):
c = fiona.open(file_path, "r")
all_indices = []
all_labels = []
city_counts = {}
side_len = side_len_m / meters_per_px
for poly in c:
coords = poly["geometry"].coordinates
city = poly["properties"]["City"]
if city not in city_counts:
city_counts[city] = 0
for coord_set in tqdm(coords):
contour = np.array(coord_set[0] if len(coord_set) == 1 else coord_set)
cmin = contour.min(axis=0)
contour -= cmin
cmax = int(contour.max() / meters_per_px)
contour = contour // meters_per_px
if cmax < side_len:
continue
mask = np.zeros((cmax, cmax), dtype="uint8")
mask = cv2.drawContours(
mask,
[contour.reshape((-1, 1, 2)).astype(np.int32)],
-1,
(255),
thickness=cv2.FILLED,
)
indices = np.array(get_optimal_grid(mask, side_len=side_len)[0])
indices = indices * meters_per_px + cmin
all_indices += sorted(indices.tolist(), key=lambda x: x[1])
all_labels += [
f"{city[0]}-{city_counts[city] + i}" for i in range(len(indices))
]
city_counts[city] += len(indices)
transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
all_indices = list(transformer.itransform(all_indices))
return np.array(all_indices), all_labels
def points_to_shapefile(points: np.ndarray, labels: list, file_path: str):
schema = {"geometry": "Point", "properties": [("ID", "int"), ("Name", "str")]}
# open a fiona object
pointShp = fiona.open(
file_path,
mode="w",
driver="ESRI Shapefile",
schema=schema,
crs="EPSG:4326",
)
# iterate over each row in the dataframe and save record
for i, (x, y) in enumerate(points):
rowDict = {
"geometry": {"type": "Point", "coordinates": (x, y)},
"properties": {"ID": i, "Name": labels[i]},
}
pointShp.write(rowDict)
# close fiona object
pointShp.close()
def get_cached_grid_indices(file_path: str):
c = fiona.open(file_path, "r")
all_indices = []
all_labels = []
for poly in c:
all_indices.append(poly["geometry"].coordinates)
if "Name" in poly["properties"]:
all_labels.append(poly["properties"]["Name"])
return np.array(all_indices), all_labels