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/city_metrix/layers/__init__.py b/city_metrix/layers/__init__.py
index 1ca7443..4af37fb 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_height 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/environment.yml b/environment.yml
index 21b5e16..18f95f4 100644
--- a/environment.yml
+++ b/environment.yml
@@ -25,3 +25,4 @@ dependencies:
- pip:
- cartoframes==1.2.5
- git+https://github.com/isciences/exactextract
+ - overturemaps==0.6.0
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
+}
diff --git a/tests/layers.py b/tests/layers.py
index 417dd35..19c6936 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, SmartSurfaceLULC
+from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse, OpenBuildings, TreeCanopyHeight, AlosDSM, SmartSurfaceLULC, OvertureBuildings
from city_metrix.layers.layer import get_image_collection
from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer, MockGroupByLayer, \
MockLargeGroupByLayer
@@ -109,7 +109,10 @@ def test_alos_dsm():
mean = AlosDSM().get_data(SAMPLE_BBOX).mean()
assert mean
-
def test_smart_surface_lulc():
count = SmartSurfaceLULC().get_data(SAMPLE_BBOX).count()
assert count
+
+def test_overture_buildings():
+ count = OvertureBuildings().get_data(SAMPLE_BBOX).count().sum()
+ assert count