Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate country extract #23

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,872 changes: 2,872 additions & 0 deletions AOIs/belgium(fast).geojson

Large diffs are not rendered by default.

2,411 changes: 2,411 additions & 0 deletions AOIs/belgium.geojson

Large diffs are not rendered by default.

406 changes: 406 additions & 0 deletions AOIs/singapore(fast).geojson

Large diffs are not rendered by default.

289 changes: 289 additions & 0 deletions AOIs/singapore.geojson

Large diffs are not rendered by default.

2,972 changes: 2,972 additions & 0 deletions AOIs/switzerland(fast).geojson

Large diffs are not rendered by default.

2,245 changes: 2,245 additions & 0 deletions AOIs/switzerland_aois.geojson

Large diffs are not rendered by default.

12,479 changes: 12,479 additions & 0 deletions AOIs/united_kingdom(fast).geojson

Large diffs are not rendered by default.

10,405 changes: 10,405 additions & 0 deletions AOIs/united_kingdom.geojson

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ services:
volumes:
- ./webapp:/webapp/
- ./data/:/data/
- ./AOIs/:/AOIs/
ports:
- "5000:5000"
depends_on:
Expand Down
14 changes: 10 additions & 4 deletions webapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,27 @@ Now one can access the web interface at http://localhost:5000.

When the container is prepared for the webapp, the AOIs can be exported using the script `create_aois.py`

The AOIs extract is created and will be found in the [../AOIs](../AOIs) directory with file name of `switzerland_aois.geojson`
Note that the script is ran inside the webapp container so the path can be different.
This will be creating an AOI based on what you have imported in the
[import_osm.sh](./import_osm.sh)

```bash
docker-compose run --rm webapp python create_aois.py tmp/aois.geojson
docker-compose run --rm webapp python create_aois.py ../AOIs/switzerland_aois.geojson
```
The AOIs extract is created and will be found in the `./tmp` directory with file name of `aois.geojson`

`--clip-boundary-path` argument clips the exported AOIs to those that intersects the boundary specified by
Rapperswil-Jona_AL8.GeoJSON (GeoJSON file can be downloaded at https://wambachers-osm.website/boundaries/
and the file must contain only one geometry).
).

Generate AOIs of only Rapperswil-Jona:
```bash
docker-compose run --rm webapp python create_aois.py tmp/clipped_aois.geojson --clip-boundary-path ../../data/Rapperswil-Jona_AL8.GeoJson
docker-compose run --rm webapp python create_aois.py ../AOIs/clipped_aois.geojson --clip-boundary-path ../../data/clip/Rapperswil-Jona_AL8.GeoJson
```

The `--with-network-centrality` argument will provide a better AOIs by taking into account the network centrality using
the closeness centrality algorithm. The resulting AOIs extract will thus include the important roads.
Note that this can take some time if enabled

## Configure PostgreSQL

Expand Down
23 changes: 15 additions & 8 deletions webapp/app/aoi_query_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from tqdm import tqdm
from app.database import query_geometries
import logging
import json
from app import settings
import json

# hides Fiona libraries logs
logging.getLogger("Fiona").setLevel(logging.INFO)
Expand All @@ -35,10 +35,13 @@ def bbox_query(self):


def boundary_query(self):
boundary_4326 = self.boundary
return f"""
(SELECT * FROM ST_Transform(ST_SetSRid(ST_GeomFromGeoJSON('{json.dumps(
boundary_4326.loc[0]['geometry'].__geo_interface__)}'), 4326), 3857) AS boundarybox)
(WITH feature_collection AS (SELECT '{self.boundary}'::json AS features)
SELECT ST_Transform(ST_SetSRid(ST_GeomFromGeoJSON(feature_col->>'geometry'), 4326), 3857) AS geometry
FROM (
SELECT json_array_elements(features->'features') AS feature_col
FROM feature_collection
) AS subquery)
"""


Expand All @@ -58,7 +61,11 @@ def preclusters_subset_query(self):
if self.boundary is None:
return "SELECT * FROM preclusters"
else:
return f"SELECT * FROM preclusters WHERE ST_Intersects(hull, {self.boundary_query()})"
return f"""
SELECT *
FROM preclusters
INNER JOIN {self.boundary_query()} AS boundary ON ST_Intersects(preclusters.hull, boundary.geometry)
"""
else:
return f"""
SELECT * FROM preclusters WHERE ST_Intersects(hull, {self.bbox_query()})
Expand All @@ -68,10 +75,10 @@ def clusters_query(self):
return f"""
WITH preclusters_subset AS ({self.preclusters_subset_query()})
SELECT preclusters_subset.id AS precluster_id,
geometry,
ST_ClusterDBSCAN(geometry, eps := 35, minpoints := preclusters_subset.dbscan_minpts) over () AS cid
pois.geometry,
ST_ClusterDBSCAN(pois.geometry, eps := 35, minpoints := preclusters_subset.dbscan_minpts) over () AS cid
FROM pois, preclusters_subset
WHERE ST_Within(geometry, preclusters_subset.hull)
WHERE ST_Within(pois.geometry, preclusters_subset.hull)
"""

def hulls_query(self):
Expand Down
27 changes: 12 additions & 15 deletions webapp/create_aois.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import time
from app.aoi_query_generator import AoiQueryGenerator
import geopandas as gpd

import os
import json

def exec_sql(sql):
with psycopg2.connect("") as connection:
Expand All @@ -13,26 +14,17 @@ def exec_sql(sql):
with connection.cursor() as cursor:
cursor.execute(sql)


def is_valid_file(parser, arg):
try:
boundary_4326 = gpd.read_file(arg)
boundary_4326 = boundary_4326.to_crs({'init': 'epsg:4326'})
if boundary_4326.size > 1:
raise ValueError(f"multiple geometry not allowed: '{arg}'")
return boundary_4326

except (Exception) as e:
raise argparse.ArgumentTypeError(e) from e

def geojson(parser, arg):
boundary_geodataframe = gpd.read_file(arg)
return json.dumps(boundary_geodataframe.__geo_interface__)


parser = argparse.ArgumentParser(description='Used to export the AOIs extract`')
parser.add_argument('dest', help='file path for the exported AOIs', metavar='DEST')
parser.add_argument('--clip-boundary-path', default=None,
help='clips the exported AOIs to those that intersects the boundary specified in this '
'GeoJSON file (The file must contain only one geometry).',
type=lambda x: is_valid_file(parser, x), metavar='PATH')
'GeoJSON file.', type=lambda x: geojson(parser, x),
metavar='PATH')
parser.add_argument('--hull-algorithm', choices=['concave', 'convex'], default='convex',
help='algorthim used to create the hull (cluster)')
parser.add_argument('--with-network-centrality', action='store_true', default=False)
Expand All @@ -41,6 +33,10 @@ def is_valid_file(parser, arg):
start = time.time()
aois_query_generator = AoiQueryGenerator(hull_algorithm=args.hull_algorithm, boundary=args.clip_boundary_path)

# create directory if directory dont exist
if not os.path.exists(os.path.dirname(args.dest)):
os.makedirs(os.path.dirname(args.dest))

if args.with_network_centrality:
aois_query = aois_query_generator.extended_hulls_query()
aois_query = aois_query_generator.without_water_query(aois_query)
Expand Down Expand Up @@ -81,4 +77,5 @@ def is_valid_file(parser, arg):
"-sql", "select st_transform(hull, 4326) from aois_without_network_centrality"])



print("Creating aois took {}s".format(time.time() - start))