From 630a516587286f777ba7567c26eef52f419000b2 Mon Sep 17 00:00:00 2001 From: weiqi-tori Date: Wed, 28 Feb 2024 19:20:03 +0800 Subject: [PATCH 1/3] update osm and ulu --- city_metrix/layers/open_street_map.py | 6 +++--- city_metrix/layers/urban_land_use.py | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/city_metrix/layers/open_street_map.py b/city_metrix/layers/open_street_map.py index ad23ce3..a56ff6b 100644 --- a/city_metrix/layers/open_street_map.py +++ b/city_metrix/layers/open_street_map.py @@ -9,7 +9,7 @@ class OpenStreetMapClass(Enum): OPEN_SPACE = {'leisure': ['park', 'nature_reserve', 'common', 'playground', 'pitch', 'track'], 'boundary': ['protected_area', 'national_park']} - OPEN_SPACE_HEAT = {'leisure': ['park', 'nature_reserve', 'common', 'playground', 'pitch', 'track', 'garden', 'golf_course', 'dog_park', 'recreation_ground', 'disc_golf_course'], + OPEN_SPACE_HEAT = {'leisure': ['park', 'nature_reserve', 'common', 'playground', 'pitch', 'garden', 'golf_course', 'dog_park', 'recreation_ground', 'disc_golf_course'], 'boundary': ['protected_area', 'national_park', 'forest_compartment', 'forest']} WATER = {'water': True, 'natural': ['water'], @@ -27,11 +27,11 @@ def __init__(self, osm_class=None, **kwargs): self.osm_class = osm_class def get_data(self, bbox): - north, south, east, west = bbox[3], bbox[1], bbox[0], bbox[2] + north, south, east, west = bbox[3], bbox[1], bbox[0], bbox[2] # Set the OSMnx configuration to disable caching ox.settings.use_cache = False try: - osm_feature = ox.features_from_bbox(north, south, east, west, self.osm_class.value) + osm_feature = ox.features_from_bbox(bbox=(north, south, east, west), tags=self.osm_class.value) # When no feature in bbox, return an empty gdf except ox._errors.InsufficientResponseError as e: osm_feature = gpd.GeoDataFrame(pd.DataFrame(columns=['osmid', 'geometry']+list(self.osm_class.value.keys())), geometry='geometry') diff --git a/city_metrix/layers/urban_land_use.py b/city_metrix/layers/urban_land_use.py index 3cd1483..f34408a 100644 --- a/city_metrix/layers/urban_land_use.py +++ b/city_metrix/layers/urban_land_use.py @@ -13,12 +13,20 @@ def __init__(self, band='lulc', **kwargs): def get_data(self, bbox): dataset = ee.ImageCollection("projects/wri-datalab/cities/urban_land_use/V1") - ulu = ee.ImageCollection(dataset - .filterBounds(ee.Geometry.BBox(*bbox)) - .select(self.band) - .reduce(ee.Reducer.firstNonNull()) - .rename('lulc') - ) + # ImageCollection didn't cover the globe + if dataset.filterBounds(ee.Geometry.BBox(*bbox)).size().getInfo() == 0: + ulu = ee.ImageCollection(ee.Image.constant(0) + .clip(ee.Geometry.BBox(*bbox)) + .rename('lulc') + ) + else: + ulu = ee.ImageCollection(dataset + .filterBounds(ee.Geometry.BBox(*bbox)) + .select(self.band) + .reduce(ee.Reducer.firstNonNull()) + .rename('lulc') + ) data = get_image_collection(ulu, bbox, 5, "urban land use").lulc + return data From 937e17ef14b2ee4163a3c43e47cf51262cd8a942 Mon Sep 17 00:00:00 2001 From: weiqi-tori Date: Mon, 4 Mar 2024 17:53:50 +0800 Subject: [PATCH 2/3] update anbh and esa --- .../layers/average_net_building_height.py | 22 +++--------------- city_metrix/layers/esa_world_cover.py | 23 +++++++++++++------ 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/city_metrix/layers/average_net_building_height.py b/city_metrix/layers/average_net_building_height.py index 80ea6ab..a5b26f0 100644 --- a/city_metrix/layers/average_net_building_height.py +++ b/city_metrix/layers/average_net_building_height.py @@ -3,7 +3,7 @@ import xee import ee -from .layer import Layer, get_utm_zone_epsg +from .layer import Layer, get_utm_zone_epsg, get_image_collection class AverageNetBuildingHeight(Layer): @@ -11,29 +11,13 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def get_data(self, bbox): - crs = get_utm_zone_epsg(bbox) # https://ghsl.jrc.ec.europa.eu/ghs_buH2023.php # ANBH is the average height of the built surfaces, USE THIS # AGBH is the amount of built cubic meters per surface unit in the cell # US - ee.ImageCollection("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_R2023A") # GLOBE - ee.Image("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_GLOBE_R2023A") - - anbh = ee.Image("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_GLOBE_R2023A") - - ds = xr.open_dataset( - ee.ImageCollection(anbh), - engine='ee', - scale=100, - crs=crs, - geometry=ee.Geometry.Rectangle(*bbox), - chunks={'X': 512, 'Y': 512} - ) - with ProgressBar(): - print("Extracting ANBH layer:") - data = ds.b1.compute() + anbh = ee.Image("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_GLOBE_R2023A") + data = get_image_collection(ee.ImageCollection(anbh), bbox, 100, "average net building height").b1 - # get in rioxarray format - data = data.squeeze("time").transpose("Y", "X").rename({'X': 'x', 'Y': 'y'}) - return data diff --git a/city_metrix/layers/esa_world_cover.py b/city_metrix/layers/esa_world_cover.py index 7682b31..ed5f823 100644 --- a/city_metrix/layers/esa_world_cover.py +++ b/city_metrix/layers/esa_world_cover.py @@ -25,17 +25,26 @@ class EsaWorldCover(Layer): STAC_COLLECTION_ID = "urn:eop:VITO:ESA_WorldCover_10m_2020_AWS_V1" STAC_ASSET_ID = "ESA_WORLDCOVER_10M_MAP" - def __init__(self, land_cover_class=None, **kwargs): + def __init__(self, land_cover_class=None, year=2020, **kwargs): super().__init__(**kwargs) self.land_cover_class = land_cover_class + self.year = year def get_data(self, bbox): - data = get_image_collection( - ee.ImageCollection("ESA/WorldCover/v100"), - bbox, - 10, - "ESA world cover" - ).Map + if self.year == 2020: + data = get_image_collection( + ee.ImageCollection("ESA/WorldCover/v100"), + bbox, + 10, + "ESA world cover" + ).Map + elif self.year == 2021: + data = get_image_collection( + ee.ImageCollection("ESA/WorldCover/v200"), + bbox, + 10, + "ESA world cover" + ).Map if self.land_cover_class: data = data.where(data == self.land_cover_class.value) From 481508877688affffaab7bf8eac3aba2d8b56461 Mon Sep 17 00:00:00 2001 From: Chris Rowe Date: Thu, 23 May 2024 18:45:45 -0400 Subject: [PATCH 3/3] Add tests --- tests/layers.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/layers.py b/tests/layers.py index 9318518..79e9481 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 +from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse from city_metrix.layers.layer import get_image_collection from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer @@ -76,3 +76,14 @@ def test_lst(): def test_esa(): count = EsaWorldCover(land_cover_class=EsaWorldCoverClass.BUILT_UP).get_data(SAMPLE_BBOX).count() assert count + +def test_average_net_building_height(): + assert AverageNetBuildingHeight().get_data(SAMPLE_BBOX).mean() + +def test_open_street_map(): + count = OpenStreetMap(osm_class=OpenStreetMapClass.ROAD).get_data(SAMPLE_BBOX).count().sum() + assert count + +def test_urban_land_use(): + assert UrbanLandUse().get_data(SAMPLE_BBOX).count() +