Spaces:
Sleeping
Sleeping
Support downloading grid and its info
Browse files- app.py +35 -23
- geo_tools.py +15 -6
app.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
import gradio as gr
|
| 3 |
import plotly.graph_objects as go
|
| 4 |
|
| 5 |
from geo_tools import (
|
| 6 |
shapefile_to_latlong,
|
| 7 |
-
|
| 8 |
points_to_shapefile,
|
| 9 |
get_cached_grid_indices,
|
| 10 |
)
|
|
@@ -19,7 +20,6 @@ OUT_DIR = "out/"
|
|
| 19 |
def gr_generate_map(
|
| 20 |
token: str,
|
| 21 |
side_len: str,
|
| 22 |
-
show_grid: bool,
|
| 23 |
show_mask: bool,
|
| 24 |
show_hospitals: bool = True,
|
| 25 |
show_police: bool = True,
|
|
@@ -28,21 +28,33 @@ def gr_generate_map(
|
|
| 28 |
side_len = float(side_len)
|
| 29 |
|
| 30 |
scattermaps = []
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
if show_mask:
|
| 47 |
contours = shapefile_to_latlong(MASK_PATH)
|
| 48 |
for contour in contours:
|
|
@@ -129,7 +141,7 @@ def gr_generate_map(
|
|
| 129 |
),
|
| 130 |
)
|
| 131 |
|
| 132 |
-
return fig
|
| 133 |
|
| 134 |
|
| 135 |
with gr.Blocks() as demo:
|
|
@@ -141,7 +153,6 @@ with gr.Blocks() as demo:
|
|
| 141 |
)
|
| 142 |
grid_side_len = gr.Textbox(value="100", label="Sampling Gap (m)")
|
| 143 |
|
| 144 |
-
grid_show_grid = gr.Checkbox(True, label="Show Grid")
|
| 145 |
grid_show_mask = gr.Checkbox(False, label="Show Mask")
|
| 146 |
grid_show_hosp = gr.Checkbox(True, label="Show Hospitals")
|
| 147 |
grid_show_police = gr.Checkbox(True, label="Show Police Stations")
|
|
@@ -161,11 +172,13 @@ with gr.Blocks() as demo:
|
|
| 161 |
"Seruwila",
|
| 162 |
],
|
| 163 |
)
|
|
|
|
|
|
|
| 164 |
|
| 165 |
grid_button.click(
|
| 166 |
gr_generate_map,
|
| 167 |
-
inputs=[grid_token, grid_side_len,
|
| 168 |
-
outputs=grid_map,
|
| 169 |
)
|
| 170 |
|
| 171 |
grid_region.change(
|
|
@@ -173,13 +186,12 @@ with gr.Blocks() as demo:
|
|
| 173 |
inputs=[
|
| 174 |
grid_token,
|
| 175 |
grid_side_len,
|
| 176 |
-
grid_show_grid,
|
| 177 |
grid_show_mask,
|
| 178 |
grid_show_hosp,
|
| 179 |
grid_show_police,
|
| 180 |
grid_region,
|
| 181 |
],
|
| 182 |
-
outputs=grid_map,
|
| 183 |
)
|
| 184 |
|
| 185 |
demo.queue(concurrency_count=10).launch(debug=True)
|
|
|
|
| 1 |
import os
|
| 2 |
+
import zipfile
|
| 3 |
import gradio as gr
|
| 4 |
import plotly.graph_objects as go
|
| 5 |
|
| 6 |
from geo_tools import (
|
| 7 |
shapefile_to_latlong,
|
| 8 |
+
mask_shapefile_to_grid_indices,
|
| 9 |
points_to_shapefile,
|
| 10 |
get_cached_grid_indices,
|
| 11 |
)
|
|
|
|
| 20 |
def gr_generate_map(
|
| 21 |
token: str,
|
| 22 |
side_len: str,
|
|
|
|
| 23 |
show_mask: bool,
|
| 24 |
show_hospitals: bool = True,
|
| 25 |
show_police: bool = True,
|
|
|
|
| 28 |
side_len = float(side_len)
|
| 29 |
|
| 30 |
scattermaps = []
|
| 31 |
+
grid_path = MASK_PATH[: -len(".shp")] + f"-gap={side_len}.shp"
|
| 32 |
+
prefix = ".".join(grid_path.split(".")[:-1])
|
| 33 |
+
if not os.path.exists(grid_path):
|
| 34 |
+
indices, labels = mask_shapefile_to_grid_indices(MASK_PATH, side_len)
|
| 35 |
+
points_to_shapefile(indices, labels, grid_path)
|
| 36 |
+
|
| 37 |
+
file_list = [prefix + ext for ext in (".shp", ".shx", ".prj", ".dbf", ".cpg")]
|
| 38 |
+
with zipfile.ZipFile(prefix + ".zip", "w") as fp:
|
| 39 |
+
for file in file_list:
|
| 40 |
+
fp.write(file, compress_type=zipfile.ZIP_DEFLATED)
|
| 41 |
+
|
| 42 |
+
with open(prefix + ".csv", "w") as fp:
|
| 43 |
+
fp.write("Label, Latitude, Longitude\n")
|
| 44 |
+
for lbl, idx in zip(labels, indices):
|
| 45 |
+
fp.write(f"{lbl}, {idx[1]}, {idx[0]}\n")
|
| 46 |
+
else:
|
| 47 |
+
indices, labels = get_cached_grid_indices(grid_path)
|
| 48 |
+
box = go.Scattermapbox(
|
| 49 |
+
lat=indices[:, 1],
|
| 50 |
+
lon=indices[:, 0],
|
| 51 |
+
mode="markers+text",
|
| 52 |
+
text=labels,
|
| 53 |
+
marker=go.scattermapbox.Marker(size=6),
|
| 54 |
+
)
|
| 55 |
+
box.name = "Grids"
|
| 56 |
+
scattermaps.append(box)
|
| 57 |
+
|
| 58 |
if show_mask:
|
| 59 |
contours = shapefile_to_latlong(MASK_PATH)
|
| 60 |
for contour in contours:
|
|
|
|
| 141 |
),
|
| 142 |
)
|
| 143 |
|
| 144 |
+
return fig, prefix + ".zip", prefix + ".csv"
|
| 145 |
|
| 146 |
|
| 147 |
with gr.Blocks() as demo:
|
|
|
|
| 153 |
)
|
| 154 |
grid_side_len = gr.Textbox(value="100", label="Sampling Gap (m)")
|
| 155 |
|
|
|
|
| 156 |
grid_show_mask = gr.Checkbox(False, label="Show Mask")
|
| 157 |
grid_show_hosp = gr.Checkbox(True, label="Show Hospitals")
|
| 158 |
grid_show_police = gr.Checkbox(True, label="Show Police Stations")
|
|
|
|
| 172 |
"Seruwila",
|
| 173 |
],
|
| 174 |
)
|
| 175 |
+
grid_shapefile = gr.File(label="Grid Shapefile")
|
| 176 |
+
grid_point_info = gr.File(label="Sample Point Info")
|
| 177 |
|
| 178 |
grid_button.click(
|
| 179 |
gr_generate_map,
|
| 180 |
+
inputs=[grid_token, grid_side_len, grid_show_mask],
|
| 181 |
+
outputs=[grid_map, grid_shapefile, grid_point_info],
|
| 182 |
)
|
| 183 |
|
| 184 |
grid_region.change(
|
|
|
|
| 186 |
inputs=[
|
| 187 |
grid_token,
|
| 188 |
grid_side_len,
|
|
|
|
| 189 |
grid_show_mask,
|
| 190 |
grid_show_hosp,
|
| 191 |
grid_show_police,
|
| 192 |
grid_region,
|
| 193 |
],
|
| 194 |
+
outputs=[grid_map, grid_shapefile, grid_point_info],
|
| 195 |
)
|
| 196 |
|
| 197 |
demo.queue(concurrency_count=10).launch(debug=True)
|
geo_tools.py
CHANGED
|
@@ -30,15 +30,20 @@ def shapefile_to_latlong(file_path: str):
|
|
| 30 |
return contours
|
| 31 |
|
| 32 |
|
| 33 |
-
def
|
| 34 |
file_path: str, side_len_m: float = 100, meters_per_px: float = 10
|
| 35 |
):
|
| 36 |
c = fiona.open(file_path, "r")
|
| 37 |
all_indices = []
|
|
|
|
|
|
|
| 38 |
side_len = side_len_m / meters_per_px
|
| 39 |
|
| 40 |
for poly in c:
|
| 41 |
coords = poly["geometry"].coordinates
|
|
|
|
|
|
|
|
|
|
| 42 |
for coord_set in tqdm(coords):
|
| 43 |
contour = np.array(coord_set[0] if len(coord_set) == 1 else coord_set)
|
| 44 |
|
|
@@ -62,16 +67,20 @@ def shapefile_to_grid_indices(
|
|
| 62 |
indices = np.array(get_optimal_grid(mask, side_len=side_len)[0])
|
| 63 |
indices = indices * meters_per_px + cmin
|
| 64 |
|
| 65 |
-
all_indices += indices.tolist()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
|
| 68 |
all_indices = list(transformer.itransform(all_indices))
|
| 69 |
|
| 70 |
-
return np.array(all_indices)
|
| 71 |
|
| 72 |
|
| 73 |
-
def points_to_shapefile(points: np.ndarray, file_path: str):
|
| 74 |
-
schema = {"geometry": "Point", "properties": [("ID", "int")]}
|
| 75 |
|
| 76 |
# open a fiona object
|
| 77 |
pointShp = fiona.open(
|
|
@@ -85,7 +94,7 @@ def points_to_shapefile(points: np.ndarray, file_path: str):
|
|
| 85 |
for i, (x, y) in enumerate(points):
|
| 86 |
rowDict = {
|
| 87 |
"geometry": {"type": "Point", "coordinates": (x, y)},
|
| 88 |
-
"properties": {"ID": i},
|
| 89 |
}
|
| 90 |
pointShp.write(rowDict)
|
| 91 |
# close fiona object
|
|
|
|
| 30 |
return contours
|
| 31 |
|
| 32 |
|
| 33 |
+
def mask_shapefile_to_grid_indices(
|
| 34 |
file_path: str, side_len_m: float = 100, meters_per_px: float = 10
|
| 35 |
):
|
| 36 |
c = fiona.open(file_path, "r")
|
| 37 |
all_indices = []
|
| 38 |
+
all_labels = []
|
| 39 |
+
city_counts = {}
|
| 40 |
side_len = side_len_m / meters_per_px
|
| 41 |
|
| 42 |
for poly in c:
|
| 43 |
coords = poly["geometry"].coordinates
|
| 44 |
+
city = poly["properties"]["City"]
|
| 45 |
+
if city not in city_counts:
|
| 46 |
+
city_counts[city] = 0
|
| 47 |
for coord_set in tqdm(coords):
|
| 48 |
contour = np.array(coord_set[0] if len(coord_set) == 1 else coord_set)
|
| 49 |
|
|
|
|
| 67 |
indices = np.array(get_optimal_grid(mask, side_len=side_len)[0])
|
| 68 |
indices = indices * meters_per_px + cmin
|
| 69 |
|
| 70 |
+
all_indices += sorted(indices.tolist(), key=lambda x: x[1])
|
| 71 |
+
all_labels += [
|
| 72 |
+
f"{city}-{city_counts[city] + i}" for i in range(len(indices))
|
| 73 |
+
]
|
| 74 |
+
city_counts[city] += len(indices)
|
| 75 |
|
| 76 |
transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
|
| 77 |
all_indices = list(transformer.itransform(all_indices))
|
| 78 |
|
| 79 |
+
return np.array(all_indices), all_labels
|
| 80 |
|
| 81 |
|
| 82 |
+
def points_to_shapefile(points: np.ndarray, labels: list, file_path: str):
|
| 83 |
+
schema = {"geometry": "Point", "properties": [("ID", "int"), ("Name", "str")]}
|
| 84 |
|
| 85 |
# open a fiona object
|
| 86 |
pointShp = fiona.open(
|
|
|
|
| 94 |
for i, (x, y) in enumerate(points):
|
| 95 |
rowDict = {
|
| 96 |
"geometry": {"type": "Point", "coordinates": (x, y)},
|
| 97 |
+
"properties": {"ID": i, "Name": labels[i]},
|
| 98 |
}
|
| 99 |
pointShp.write(rowDict)
|
| 100 |
# close fiona object
|