From 64966b367eba857e57a1e128c2e1c126171cd57e Mon Sep 17 00:00:00 2001 From: weiqi-tori Date: Mon, 17 Jun 2024 15:35:02 +0800 Subject: [PATCH 1/3] add overture buildings layer --- city_metrix/layers/__init__.py | 1 + city_metrix/layers/overture_buildings.py | 30 ++++++++++++++++++++++++ tests/layers.py | 6 ++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 city_metrix/layers/overture_buildings.py diff --git a/city_metrix/layers/__init__.py b/city_metrix/layers/__init__.py index bef56c3..aa56297 100644 --- a/city_metrix/layers/__init__.py +++ b/city_metrix/layers/__init__.py @@ -16,3 +16,4 @@ from .open_buildings import OpenBuildings from .tree_canopy_hight import TreeCanopyHeight from .alos_dsm import AlosDSM +from .overture_buildings import OvertureBuildings diff --git a/city_metrix/layers/overture_buildings.py b/city_metrix/layers/overture_buildings.py new file mode 100644 index 0000000..f8b2e24 --- /dev/null +++ b/city_metrix/layers/overture_buildings.py @@ -0,0 +1,30 @@ +import geopandas as gpd +import subprocess +from io import StringIO + +from .layer import Layer + + +class OvertureBuildings(Layer): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def get_data(self, bbox): + bbox_str = ','.join(map(str, bbox)) + + command = [ + "overturemaps", "download", + "--bbox="+bbox_str, + "-f", "geojson", + "--type=building" + ] + + result = subprocess.run(command, capture_output=True, text=True) + + if result.returncode == 0: + geojson_data = result.stdout + overture_buildings = gpd.read_file(StringIO(geojson_data)) + else: + print("Error occurred:", result.stderr) + + return overture_buildings diff --git a/tests/layers.py b/tests/layers.py index adf01ea..e85b9b6 100644 --- a/tests/layers.py +++ b/tests/layers.py @@ -1,6 +1,6 @@ import ee -from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse, OpenBuildings, TreeCanopyHeight, AlosDSM +from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse, OpenBuildings, TreeCanopyHeight, AlosDSM, OvertureBuildings from city_metrix.layers.layer import get_image_collection from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer, MockGroupByLayer, \ MockLargeGroupByLayer @@ -108,3 +108,7 @@ def test_tree_canopy_hight(): def test_AlosDSM(): mean = AlosDSM().get_data(SAMPLE_BBOX).mean() assert mean + +def test_overture_buildings(): + count = OvertureBuildings().get_data(SAMPLE_BBOX).count().sum() + assert count From 82db262f9fb66218c1ed3b3459e2633b152ca0db Mon Sep 17 00:00:00 2001 From: weiqi-tori Date: Mon, 17 Jun 2024 15:50:20 +0800 Subject: [PATCH 2/3] add install overturemaps --- environment.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/environment.yml b/environment.yml index 436dbbc..0855163 100644 --- a/environment.yml +++ b/environment.yml @@ -22,3 +22,4 @@ dependencies: - pip=23.3.1 - pip: - cartoframes==1.2.5 + - overturemaps==0.6.0 From b0a2332501562f520c3dbfabefa65437c1616d50 Mon Sep 17 00:00:00 2001 From: Chris Rowe Date: Tue, 2 Jul 2024 08:20:32 -0400 Subject: [PATCH 3/3] add example overture_buildings layer notebook --- .gitignore | 3 + notebooks/layers/overture_buildings.ipynb | 183 ++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 notebooks/layers/overture_buildings.ipynb diff --git a/.gitignore b/.gitignore index 01b3808..5d919a7 100644 --- a/.gitignore +++ b/.gitignore @@ -163,3 +163,6 @@ cython_debug/ /keys keys/ wri-gee-358d958ce7c6.json + +# data +/data diff --git a/notebooks/layers/overture_buildings.ipynb b/notebooks/layers/overture_buildings.ipynb new file mode 100644 index 0000000..865a113 --- /dev/null +++ b/notebooks/layers/overture_buildings.ipynb @@ -0,0 +1,183 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import geopandas as gpd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# # update the wd path to be able to laod the module\n", + "os.chdir('../..')\n", + "os.getcwd()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get Area of Interest" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load boundary from s3\n", + "boundary_path = 'https://cities-indicators.s3.eu-west-3.amazonaws.com/data/boundaries/boundary-BRA-Salvador-ADM4union.geojson'\n", + "city_gdf = gpd.read_file(boundary_path, driver='GeoJSON')\n", + "city_gdf.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Get area in sqare km\n", + "city_gdf.to_crs(epsg=3857).area / 10**6" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Get Layer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from city_metrix.layers import OvertureBuildings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "overture_buildings = OvertureBuildings().get_data(city_gdf.total_bounds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Save to file" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create a data folder if it does not exist\n", + "if not os.path.exists('data'):\n", + " os.makedirs('data')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Save the overture_buildings to a geoparquet file\n", + "# This is much quicker and creates a significantly smaller file compared to geojson\n", + "overture_buildings.to_parquet('data/overture_buildings.geoparquet')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Save the overture_buildings to a geojson file\n", + "overture_buildings.to_file('data/overture_buildings.geojson', driver='GeoJSON')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cities-cif", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}