From e33f68825184367e5279037a5135e11f124f2554 Mon Sep 17 00:00:00 2001 From: Chris Rowe Date: Tue, 28 May 2024 21:54:21 -0400 Subject: [PATCH 1/2] add TreeCanopyHeight function --- city_metrix/layers/__init__.py | 1 + city_metrix/layers/tree_canopy_hight.py | 29 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 city_metrix/layers/tree_canopy_hight.py diff --git a/city_metrix/layers/__init__.py b/city_metrix/layers/__init__.py index 1869e13..3ece2ef 100644 --- a/city_metrix/layers/__init__.py +++ b/city_metrix/layers/__init__.py @@ -14,3 +14,4 @@ from .built_up_height import BuiltUpHeight from .average_net_building_height import AverageNetBuildingHeight from .open_buildings import OpenBuildings +from .tree_canopy_hight import TreeCanopyHeight diff --git a/city_metrix/layers/tree_canopy_hight.py b/city_metrix/layers/tree_canopy_hight.py new file mode 100644 index 0000000..464c7cf --- /dev/null +++ b/city_metrix/layers/tree_canopy_hight.py @@ -0,0 +1,29 @@ +from .layer import Layer, get_utm_zone_epsg, get_image_collection + +from dask.diagnostics import ProgressBar +import xarray as xr +import xee +import ee + + +class TreeCanopyHeight(Layer): + + name = "tree_canopy_hight" + + NO_DATA_VALUE = 0 + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def get_data(self, bbox): + canopy_ht = ee.ImageCollection("projects/meta-forest-monitoring-okw37/assets/CanopyHeight") + # aggregate time series into a single image + canopy_ht = canopy_ht.reduce(ee.Reducer.mean()).rename("cover_code") + + + + + data = get_image_collection(ee.ImageCollection(canopy_ht), bbox, 1, "tree canopy hight") + + return data.cover_code + From 39a4d8bfbb4920127da22d3422715cdc35b4a51d Mon Sep 17 00:00:00 2001 From: Chris Rowe Date: Tue, 28 May 2024 22:31:24 -0400 Subject: [PATCH 2/2] add test and notebook section for tree canopy hight layer --- notebooks/tutorial/get layers.ipynb | 108 ++++++++++++++++++---------- tests/layers.py | 6 +- 2 files changed, 75 insertions(+), 39 deletions(-) diff --git a/notebooks/tutorial/get layers.ipynb b/notebooks/tutorial/get layers.ipynb index b426bdb..0a40bf9 100644 --- a/notebooks/tutorial/get layers.ipynb +++ b/notebooks/tutorial/get layers.ipynb @@ -32,7 +32,8 @@ "| Natural Areas | `NaturalAreas()` | `none` | |\n", "| Open Street Map | `OpenStreetMap()` | `osm_class=None`; `OpenStreetMapClass`: Groupings of OSM Tags for various land uses | |\n", "| Building Hight | `AverageNetBuildingHeight()` | `none` | |\n", - "| Building Footprints | `OpenBuildings()` | `country='USA'` | |" + "| Building Footprints | `OpenBuildings()` | `country='USA'` | |\n", + "| 1m Global Tree Canopy Height | `TreeCanopyHeight()` | | |" ] }, { @@ -47,43 +48,20 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 1, "id": "7ed2c665-e6d8-4e98-95ac-41aab749493f", "metadata": {}, "outputs": [ { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'rasterio'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mgeopandas\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mgpd\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mrasterio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mplot\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m show\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mrasterio\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m \n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'rasterio'" + ] } ], "source": [ @@ -96,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": null, "id": "602a6217-fd80-4cec-b40b-20de68b8f62b", "metadata": {}, "outputs": [ @@ -4641,13 +4619,67 @@ "Map\n" ] }, + { + "cell_type": "markdown", + "id": "a875211e", + "metadata": {}, + "source": [ + "# 1m Global Tree Canopy Height" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2417058", + "metadata": {}, + "outputs": [], + "source": [ + "from city_metrix.layers import TreeCanopyHeight" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80a05bdf", + "metadata": {}, + "outputs": [], + "source": [ + "# Load 1m Global Tree Canopy Hight layer\n", + "city_TreeCanopyHeight = TreeCanopyHeight().get_data(city_centroid_buffer.total_bounds)\n", + "city_TreeCanopyHeight" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aabb9dbe", + "metadata": {}, + "outputs": [], + "source": [ + "city_TreeCanopyHeight.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "1276883d", + "metadata": {}, + "source": [ + "# Development" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "95c9221e", + "id": "81786aad", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import sys\n", + "sys.dont_write_bytecode=True\n", + "\n", + "%load_ext autoreload\n", + "%autoreload" + ] } ], "metadata": { @@ -4666,7 +4698,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.14" } }, "nbformat": 4, diff --git a/tests/layers.py b/tests/layers.py index cb8af49..fb8aa50 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 +from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse, OpenBuildings, TreeCanopyHeight from city_metrix.layers.layer import get_image_collection from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer @@ -90,3 +90,7 @@ def test_urban_land_use(): def test_openbuildings(): count = OpenBuildings().get_data(SAMPLE_BBOX).count().sum() assert count + +def test_tree_canopy_hight(): + count = TreeCanopyHeight().get_data(SAMPLE_BBOX).count() + assert count \ No newline at end of file