diff --git a/city_metrix/layers/layer.py b/city_metrix/layers/layer.py index 0b2da49..732992f 100644 --- a/city_metrix/layers/layer.py +++ b/city_metrix/layers/layer.py @@ -68,9 +68,26 @@ def count(self): def _zonal_stats(self, stats_func): if box(*self.zones.total_bounds).area <= MAX_TILE_SIZE**2: - return self._zonal_stats_tile(self.zones, [stats_func])[stats_func] + stats = self._zonal_stats_tile(self.zones, [stats_func]) else: - return self._zonal_stats_fishnet(stats_func) + stats = self._zonal_stats_fishnet(stats_func) + + if self.layer is not None: + # decode zone and layer value using bit operations + stats["layer"] = stats["zone"].astype("uint32").values >> 16 + stats["zone"] = stats["zone"].astype("uint32").values & 65535 + + # group layer values together into a dictionary per zone + def group_layer_values(df): + layer_values = df.drop(columns="zone").groupby("layer").sum() + layer_dicts = layer_values.to_dict() + return layer_dicts[stats_func] + + stats = stats.groupby("zone").apply(group_layer_values) + + return stats + + return stats[stats_func] def _zonal_stats_fishnet(self, stats_func): # fishnet GeoDataFrame into smaller tiles @@ -91,31 +108,42 @@ def _zonal_stats_fishnet(self, stats_func): tile_funcs = get_stats_funcs(stats_func) # run zonal stats per data frame + print(f"Input covers too much area, splitting into {len(tile_gdfs)} tiles") tile_stats = pd.concat([ self._zonal_stats_tile(tile_gdf, tile_funcs) for tile_gdf in tile_gdfs ]) aggregated = tile_stats.groupby("zone").apply(_aggregate_stats, stats_func) + aggregated.name = stats_func - return aggregated + return aggregated.reset_index() def _zonal_stats_tile(self, tile_gdf, stats_func): bbox = tile_gdf.total_bounds aggregate_data = self.aggregate.get_data(bbox) mask_datum = [mask.get_data(bbox) for mask in self.masks] + layer_data = self.layer.get_data(bbox) if self.layer is not None else None # align to highest resolution raster, which should be the largest raster # since all are clipped to the extent - raster_data = [data for data in mask_datum + [aggregate_data] if isinstance(data, xr.DataArray)] + raster_data = [data for data in mask_datum + [aggregate_data] + [layer_data] if isinstance(data, xr.DataArray)] align_to = sorted(raster_data, key=lambda data: data.size, reverse=True).pop() aggregate_data = self._align(aggregate_data, align_to) mask_datum = [self._align(data, align_to) for data in mask_datum] + if self.layer is not None: + layer_data = self._align(layer_data, align_to) + for mask in mask_datum: aggregate_data = aggregate_data.where(~np.isnan(mask)) zones = self._rasterize(tile_gdf, align_to) + + if self.layer is not None: + # encode layer into zones by bitshifting + zones = zones + (layer_data.astype("uint32") << 16) + stats = zonal_stats(zones, aggregate_data, stats_funcs=stats_func) return stats @@ -228,7 +256,7 @@ def get_image_collection( ) with ProgressBar(): - print(f"Extracting layer {name} from Google Earth Engine:") + print(f"Extracting layer {name} from Google Earth Engine for bbox {bbox}:") data = ds.compute() # get in rioxarray format diff --git a/notebooks/tutorial/compute indicators.ipynb b/notebooks/tutorial/compute indicators.ipynb index 99f03fd..6fe09bf 100644 --- a/notebooks/tutorial/compute indicators.ipynb +++ b/notebooks/tutorial/compute indicators.ipynb @@ -1224,8 +1224,1249 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "source": [ + "{\n", + " \"cells\": [\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"cdd83ce4-8281-496b-a27e-c17527387fec\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"# Introduction\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"9e3282ba-378a-4272-b6ca-dedf965e4172\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"This tutorial provides instructions on nhow to use `city_metrix` to calcaulte indicators based on user-specific geometry.\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"6f77de84-d7a9-4377-afd5-9cb265112718\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"Every 'indicator' is defined as separate python function:\\n\",\n", + " \"\\n\",\n", + " \"| Indicator name | function name | Parameters | Method |\\n\",\n", + " \"| ---- | ---- | ---- | ---- |\\n\",\n", + " \"| Average tree cover | `mean_tree_cover()` | | |\\n\",\n", + " \"| Percent of built land without tree cover | `built_land_without_tree_cover()` | | |\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"48a31f86-c031-4347-be1d-e631ea0f636e\",\n", + " \"metadata\": {\n", + " \"tags\": []\n", + " },\n", + " \"source\": [\n", + " \"# Setting\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 1,\n", + " \"id\": \"dcc7a7b9-cf15-442c-acfd-fef1806ad05e\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"import os\\n\",\n", + " \"import geopandas as gpd\\n\",\n", + " \"from rasterio.plot import show\\n\",\n", + " \"import rasterio\\n\",\n", + " \"import pandas as pd\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 2,\n", + " \"id\": \"6bcc8215-0c19-45bd-8265-2be0c2a83c6b\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"data\": {\n", + " \"text/plain\": [\n", + " \"'/Users/jt/dev/cities-cif'\"\n", + " ]\n", + " },\n", + " \"execution_count\": 2,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"# update the wd path to be able to laod the module\\n\",\n", + " \"os.chdir('../..') \\n\",\n", + " \"os.getcwd()\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 3,\n", + " \"id\": \"4ce04cdf-634c-4c9c-8d20-1e2a3caffac2\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"os.environ['GCS_BUCKET']='gee-exports'\\n\",\n", + " \"os.environ['GOOGLE_APPLICATION_USER']='developers@citiesindicators.iam.gserviceaccount.com'\\n\",\n", + " \"os.environ['GOOGLE_APPLICATION_CREDENTIALS']='C:\\\\\\\\Users\\\\Saif.Shabou\\\\OneDrive - World Resources Institute\\\\Documents\\\\cities-indicators-framework\\\\citymetrix\\\\credentials-citiesindicators.json'\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"67f86f26-b888-4cc2-b500-47ebe9458609\",\n", + " \"metadata\": {\n", + " \"tags\": []\n", + " },\n", + " \"source\": [\n", + " \"# Get boundaries\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 3,\n", + " \"id\": \"acbc5aaa-5f47-44ff-b9ab-b885c06d7424\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometry
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \"\n", + " ]\n", + " },\n", + " \"execution_count\": 3,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"# load boundary of a region of interest\\n\",\n", + " \"boundary_path = 'https://cities-indicators.s3.eu-west-3.amazonaws.com/data/boundaries/boundary-BRA-Salvador-ADM4union.geojson'\\n\",\n", + " \"city_gdf_aoi = gpd.read_file(boundary_path, driver='GeoJSON')\\n\",\n", + " \"city_gdf_aoi.head()\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 4,\n", + " \"id\": \"7af8657e-feed-42b8-b32a-d4ee5754cd4c\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometry
0BRA-Salvador_ADM4_1ADM4PituaçuBRA-Salvador2022-08-03MULTIPOLYGON (((-38.40125 -12.96457, -38.40126...
1BRA-Salvador_ADM4_2ADM4PatamaresBRA-Salvador2022-08-03MULTIPOLYGON (((-38.39898 -12.96269, -38.39898...
2BRA-Salvador_ADM4_3ADM4PiatãBRA-Salvador2022-08-03MULTIPOLYGON (((-38.37346 -12.93345, -38.37386...
3BRA-Salvador_ADM4_4ADM4Boca do RioBRA-Salvador2022-08-03MULTIPOLYGON (((-38.41741 -12.97578, -38.41746...
4BRA-Salvador_ADM4_5ADM4Jardim ArmaçãoBRA-Salvador2022-08-03MULTIPOLYGON (((-38.43383 -12.98742, -38.43386...
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4_1 ADM4 Pituaçu BRA-Salvador \\n\",\n", + " \"1 BRA-Salvador_ADM4_2 ADM4 Patamares BRA-Salvador \\n\",\n", + " \"2 BRA-Salvador_ADM4_3 ADM4 Piatã BRA-Salvador \\n\",\n", + " \"3 BRA-Salvador_ADM4_4 ADM4 Boca do Rio BRA-Salvador \\n\",\n", + " \"4 BRA-Salvador_ADM4_5 ADM4 Jardim Armação BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.40125 -12.96457, -38.40126... \\n\",\n", + " \"1 2022-08-03 MULTIPOLYGON (((-38.39898 -12.96269, -38.39898... \\n\",\n", + " \"2 2022-08-03 MULTIPOLYGON (((-38.37346 -12.93345, -38.37386... \\n\",\n", + " \"3 2022-08-03 MULTIPOLYGON (((-38.41741 -12.97578, -38.41746... \\n\",\n", + " \"4 2022-08-03 MULTIPOLYGON (((-38.43383 -12.98742, -38.43386... \"\n", + " ]\n", + " },\n", + " \"execution_count\": 4,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"# load boundary of sub-georgaphy\\n\",\n", + " \"boundary_path = 'https://cities-indicators.s3.eu-west-3.amazonaws.com/data/boundaries/boundary-BRA-Salvador-ADM4.geojson'\\n\",\n", + " \"city_gdf_sub = gpd.read_file(boundary_path, driver='GeoJSON')\\n\",\n", + " \"city_gdf_sub.head()\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"788d5679-2fc5-4025-996c-25af1d35b900\",\n", + " \"metadata\": {\n", + " \"tags\": []\n", + " },\n", + " \"source\": [\n", + " \"# LND-2 Average Tree Cover\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 5,\n", + " \"id\": \"8bdaa746-b071-4e9f-8959-c8c57921c73c\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Authenticating to GEE with configured credentials file.\\n\"\n", + " ]\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import mean_tree_cover\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 6,\n", + " \"id\": \"e69f2674-dc78-4098-b423-0686944eabe8\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix import mean_tree_cover\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"7b71f6e7-9e83-4c88-8a98-9d30958a8dc4\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"## City level - one city\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 9,\n", + " \"id\": \"8b85131c\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting layer tree cover from Google Earth Engine:\\n\",\n", + " \"CPU times: user 6.65 s, sys: 1.12 s, total: 7.77 s\\n\",\n", + " \"Wall time: 12.5 s\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_cover
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...0.283668
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover \\n\",\n", + " \"0 0.283668 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 9,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"# for one geography\\n\",\n", + " \"city_gdf_aoi[\\\"mean_tree_cover\\\"] = mean_tree_cover(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"ee63ca6a-a5c5-4ce7-82cd-3a35e52d3cd6\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"## Sub-city level\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 8,\n", + " \"id\": \"71349065-4726-4a12-bbb8-1f998562c338\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting tree cover layer in bbox [-38.6469891 -13.0171475 -38.30455157 -12.75628844]:\\n\",\n", + " \"[########################################] | 100% Completed | 14.55 s\\n\",\n", + " \"CPU times: total: 17.1 s\\n\",\n", + " \"Wall time: 17.8 s\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_cover
0BRA-Salvador_ADM4_1ADM4PituaçuBRA-Salvador2022-08-03MULTIPOLYGON (((-38.40125 -12.96457, -38.40126...0.523927
1BRA-Salvador_ADM4_2ADM4PatamaresBRA-Salvador2022-08-03MULTIPOLYGON (((-38.39898 -12.96269, -38.39898...0.433088
2BRA-Salvador_ADM4_3ADM4PiatãBRA-Salvador2022-08-03MULTIPOLYGON (((-38.37346 -12.93345, -38.37386...0.274104
3BRA-Salvador_ADM4_4ADM4Boca do RioBRA-Salvador2022-08-03MULTIPOLYGON (((-38.41741 -12.97578, -38.41746...0.157694
4BRA-Salvador_ADM4_5ADM4Jardim ArmaçãoBRA-Salvador2022-08-03MULTIPOLYGON (((-38.43383 -12.98742, -38.43386...0.210874
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4_1 ADM4 Pituaçu BRA-Salvador \\n\",\n", + " \"1 BRA-Salvador_ADM4_2 ADM4 Patamares BRA-Salvador \\n\",\n", + " \"2 BRA-Salvador_ADM4_3 ADM4 Piatã BRA-Salvador \\n\",\n", + " \"3 BRA-Salvador_ADM4_4 ADM4 Boca do Rio BRA-Salvador \\n\",\n", + " \"4 BRA-Salvador_ADM4_5 ADM4 Jardim Armação BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.40125 -12.96457, -38.40126... \\n\",\n", + " \"1 2022-08-03 MULTIPOLYGON (((-38.39898 -12.96269, -38.39898... \\n\",\n", + " \"2 2022-08-03 MULTIPOLYGON (((-38.37346 -12.93345, -38.37386... \\n\",\n", + " \"3 2022-08-03 MULTIPOLYGON (((-38.41741 -12.97578, -38.41746... \\n\",\n", + " \"4 2022-08-03 MULTIPOLYGON (((-38.43383 -12.98742, -38.43386... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover \\n\",\n", + " \"0 0.523927 \\n\",\n", + " \"1 0.433088 \\n\",\n", + " \"2 0.274104 \\n\",\n", + " \"3 0.157694 \\n\",\n", + " \"4 0.210874 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 8,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"# for sub geographies\\n\",\n", + " \"city_gdf_sub[\\\"mean_tree_cover\\\"] = mean_tree_cover(city_gdf_sub) \\n\",\n", + " \"city_gdf_sub.head()\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"6580e18f-50b1-499c-adb7-9ed604c33e81\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"## Multiple cities\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 9,\n", + " \"id\": \"5006d2d3-6ef0-4460-b127-f72522e94585\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometry
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...
1IDN-Jakarta_ADM-4-union_1ADM-4-unionIDN-JakartaIDN-Jakarta2022-06-27MULTIPOLYGON (((106.78141 -6.31616, 106.78124 ...
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"1 IDN-Jakarta_ADM-4-union_1 ADM-4-union IDN-Jakarta IDN-Jakarta \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"1 2022-06-27 MULTIPOLYGON (((106.78141 -6.31616, 106.78124 ... \"\n", + " ]\n", + " },\n", + " \"execution_count\": 9,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"# Calculate indicator for multiple regions of interest\\n\",\n", + " \"\\n\",\n", + " \"boundary_path = 'https://cities-indicators.s3.eu-west-3.amazonaws.com/data/boundaries/boundary-BRA-Salvador-ADM4union.geojson'\\n\",\n", + " \"city_Salvador = gpd.read_file(boundary_path, driver='GeoJSON')\\n\",\n", + " \"\\n\",\n", + " \"boundary_path = 'https://cities-indicators.s3.eu-west-3.amazonaws.com/data/boundaries/boundary-IDN-Jakarta-ADM4union.geojson'\\n\",\n", + " \"city_Jakarta = gpd.read_file(boundary_path, driver='GeoJSON')\\n\",\n", + " \"\\n\",\n", + " \"cities = pd.concat([city_Salvador, city_Jakarta])\\n\",\n", + " \"cities = cities.reset_index(drop=True)\\n\",\n", + " \"cities\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 10,\n", + " \"id\": \"47791e3e-3761-404e-96a5-26493cc8ef54\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting tree cover layer in bbox [-38.6469891 -13.0171475 -38.30455157 -12.75628844]:\\n\",\n", + " \"[########################################] | 100% Completed | 16.77 s\\n\",\n", + " \"Extracting tree cover layer in bbox [106.685589 -6.3650478 106.8530109 -6.0891749]:\\n\",\n", + " \"[########################################] | 100% Completed | 9.38 ss\\n\",\n", + " \"Extracting tree cover layer in bbox [106.8530109 -6.3744575 106.973975 -6.0895823]:\\n\",\n", + " \"[########################################] | 100% Completed | 8.75 ss\\n\"\n", + " ]\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"cities[\\\"mean_tree_cover\\\"] = mean_tree_cover(cities)\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 11,\n", + " \"id\": \"d58a38fd-adea-4961-b0f8-abac0d0943cf\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_cover
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...0.283667
1IDN-Jakarta_ADM-4-union_1ADM-4-unionIDN-JakartaIDN-Jakarta2022-06-27MULTIPOLYGON (((106.78141 -6.31616, 106.78124 ...0.159044
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"1 IDN-Jakarta_ADM-4-union_1 ADM-4-union IDN-Jakarta IDN-Jakarta \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"1 2022-06-27 MULTIPOLYGON (((106.78141 -6.31616, 106.78124 ... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover \\n\",\n", + " \"0 0.283667 \\n\",\n", + " \"1 0.159044 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 11,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"cities\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"8aa3590f-b78e-4c57-872b-c5056266ff1a\",\n", + " \"metadata\": {\n", + " \"tags\": []\n", + " },\n", + " \"source\": [\n", + " \"# HEA-4 Percent of built land without tree cover\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 14,\n", + " \"id\": \"e5948b81-cb27-4c97-9567-a297e078cdb5\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import built_land_without_tree_cover\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 15,\n", + " \"id\": \"10e89534-19d7-4dba-bc98-d4f3dd8b95f4\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting ESA world cover layer in bbox [-38.6469891 -13.0171475 -38.30455157 -12.75628844]:\\n\",\n", + " \"[########################################] | 100% Completed | 9.68 ss\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"ename\": \"UnboundLocalError\",\n", + " \"evalue\": \"local variable 'stats_funcs_dict' referenced before assignment\",\n", + " \"output_type\": \"error\",\n", + " \"traceback\": [\n", + " \"\\u001b[1;31m---------------------------------------------------------------------------\\u001b[0m\",\n", + " \"\\u001b[1;31mUnboundLocalError\\u001b[0m Traceback (most recent call last)\",\n", + " \"File \\u001b[1;32m:2\\u001b[0m\\n\",\n", + " \"File \\u001b[1;32m~\\\\OneDrive - World Resources Institute\\\\Documents\\\\cities-indicators-framework\\\\citymetrix\\\\cities-cif\\\\city_metrix\\\\metrics\\\\built_land_without_tree_cover.py:16\\u001b[0m, in \\u001b[0;36mbuilt_land_without_tree_cover\\u001b[1;34m(zones)\\u001b[0m\\n\\u001b[0;32m 13\\u001b[0m built_up_land \\u001b[38;5;241m=\\u001b[39m EsaWorldCover(land_cover_class\\u001b[38;5;241m=\\u001b[39mEsaWorldCoverClass\\u001b[38;5;241m.\\u001b[39mBUILT_UP)\\n\\u001b[0;32m 14\\u001b[0m tree_cover \\u001b[38;5;241m=\\u001b[39m TreeCover(min_tree_cover\\u001b[38;5;241m=\\u001b[39m\\u001b[38;5;241m1\\u001b[39m)\\n\\u001b[1;32m---> 16\\u001b[0m built_land \\u001b[38;5;241m=\\u001b[39m \\u001b[43mbuilt_up_land\\u001b[49m\\u001b[38;5;241;43m.\\u001b[39;49m\\u001b[43mgroupby\\u001b[49m\\u001b[43m(\\u001b[49m\\u001b[43mzones\\u001b[49m\\u001b[43m)\\u001b[49m\\u001b[38;5;241;43m.\\u001b[39;49m\\u001b[43mcount\\u001b[49m\\u001b[43m(\\u001b[49m\\u001b[43m)\\u001b[49m\\n\\u001b[0;32m 17\\u001b[0m tree_cover_in_built_land \\u001b[38;5;241m=\\u001b[39m tree_cover\\u001b[38;5;241m.\\u001b[39mmask(built_up_land)\\u001b[38;5;241m.\\u001b[39mgroupby(zones)\\u001b[38;5;241m.\\u001b[39mcount()\\n\\u001b[0;32m 19\\u001b[0m percent_tree_cover_in_built_up_land \\u001b[38;5;241m=\\u001b[39m \\u001b[38;5;241m1\\u001b[39m \\u001b[38;5;241m-\\u001b[39m (tree_cover_in_built_land\\u001b[38;5;241m.\\u001b[39mfillna(\\u001b[38;5;241m0\\u001b[39m) \\u001b[38;5;241m/\\u001b[39m built_land)\\n\",\n", + " \"File \\u001b[1;32m~\\\\OneDrive - World Resources Institute\\\\Documents\\\\cities-indicators-framework\\\\citymetrix\\\\cities-cif\\\\city_metrix\\\\layers\\\\layer.py:64\\u001b[0m, in \\u001b[0;36mLayerGroupBy.count\\u001b[1;34m(self)\\u001b[0m\\n\\u001b[0;32m 63\\u001b[0m \\u001b[38;5;28;01mdef\\u001b[39;00m \\u001b[38;5;21mcount\\u001b[39m(\\u001b[38;5;28mself\\u001b[39m):\\n\\u001b[1;32m---> 64\\u001b[0m \\u001b[38;5;28;01mreturn\\u001b[39;00m \\u001b[38;5;28;43mself\\u001b[39;49m\\u001b[38;5;241;43m.\\u001b[39;49m\\u001b[43m_zonal_stats\\u001b[49m\\u001b[43m(\\u001b[49m\\u001b[38;5;124;43m\\\"\\u001b[39;49m\\u001b[38;5;124;43mcount\\u001b[39;49m\\u001b[38;5;124;43m\\\"\\u001b[39;49m\\u001b[43m)\\u001b[49m\\n\",\n", + " \"File \\u001b[1;32m~\\\\OneDrive - World Resources Institute\\\\Documents\\\\cities-indicators-framework\\\\citymetrix\\\\cities-cif\\\\city_metrix\\\\layers\\\\layer.py:68\\u001b[0m, in \\u001b[0;36mLayerGroupBy._zonal_stats\\u001b[1;34m(self, stats_func)\\u001b[0m\\n\\u001b[0;32m 66\\u001b[0m \\u001b[38;5;28;01mdef\\u001b[39;00m \\u001b[38;5;21m_zonal_stats\\u001b[39m(\\u001b[38;5;28mself\\u001b[39m, stats_func):\\n\\u001b[0;32m 67\\u001b[0m \\u001b[38;5;28;01mif\\u001b[39;00m box(\\u001b[38;5;241m*\\u001b[39m\\u001b[38;5;28mself\\u001b[39m\\u001b[38;5;241m.\\u001b[39mzones\\u001b[38;5;241m.\\u001b[39mtotal_bounds)\\u001b[38;5;241m.\\u001b[39marea \\u001b[38;5;241m<\\u001b[39m\\u001b[38;5;241m=\\u001b[39m MAX_TILE_SIZE\\u001b[38;5;241m*\\u001b[39m\\u001b[38;5;241m*\\u001b[39m\\u001b[38;5;241m2\\u001b[39m:\\n\\u001b[1;32m---> 68\\u001b[0m \\u001b[38;5;28;01mreturn\\u001b[39;00m \\u001b[38;5;28;43mself\\u001b[39;49m\\u001b[38;5;241;43m.\\u001b[39;49m\\u001b[43m_zonal_stats_tile\\u001b[49m\\u001b[43m(\\u001b[49m\\u001b[38;5;28;43mself\\u001b[39;49m\\u001b[38;5;241;43m.\\u001b[39;49m\\u001b[43mzones\\u001b[49m\\u001b[43m,\\u001b[49m\\u001b[43m \\u001b[49m\\u001b[43mstats_func\\u001b[49m\\u001b[43m)\\u001b[49m[stats_func]\\n\\u001b[0;32m 69\\u001b[0m \\u001b[38;5;28;01melse\\u001b[39;00m:\\n\\u001b[0;32m 70\\u001b[0m \\u001b[38;5;28;01mreturn\\u001b[39;00m \\u001b[38;5;28mself\\u001b[39m\\u001b[38;5;241m.\\u001b[39m_zonal_stats_fishnet(stats_func)\\n\",\n", + " \"File \\u001b[1;32m~\\\\OneDrive - World Resources Institute\\\\Documents\\\\cities-indicators-framework\\\\citymetrix\\\\cities-cif\\\\city_metrix\\\\layers\\\\layer.py:116\\u001b[0m, in \\u001b[0;36mLayerGroupBy._zonal_stats_tile\\u001b[1;34m(self, tile_gdf, stats_func)\\u001b[0m\\n\\u001b[0;32m 113\\u001b[0m aggregate_data \\u001b[38;5;241m=\\u001b[39m aggregate_data\\u001b[38;5;241m.\\u001b[39mwhere(\\u001b[38;5;241m~\\u001b[39mnp\\u001b[38;5;241m.\\u001b[39misnan(mask))\\n\\u001b[0;32m 115\\u001b[0m zones \\u001b[38;5;241m=\\u001b[39m \\u001b[38;5;28mself\\u001b[39m\\u001b[38;5;241m.\\u001b[39m_rasterize(tile_gdf, align_to)\\n\\u001b[1;32m--> 116\\u001b[0m stats \\u001b[38;5;241m=\\u001b[39m \\u001b[43mzonal_stats\\u001b[49m\\u001b[43m(\\u001b[49m\\u001b[43mzones\\u001b[49m\\u001b[43m,\\u001b[49m\\u001b[43m \\u001b[49m\\u001b[43maggregate_data\\u001b[49m\\u001b[43m,\\u001b[49m\\u001b[43m \\u001b[49m\\u001b[43mstats_funcs\\u001b[49m\\u001b[38;5;241;43m=\\u001b[39;49m\\u001b[43mstats_func\\u001b[49m\\u001b[43m)\\u001b[49m\\n\\u001b[0;32m 118\\u001b[0m \\u001b[38;5;28;01mreturn\\u001b[39;00m stats\\n\",\n", + " \"File \\u001b[1;32m~\\\\anaconda3\\\\envs\\\\citymetrix_env\\\\lib\\\\site-packages\\\\xrspatial\\\\zonal.py:579\\u001b[0m, in \\u001b[0;36mstats\\u001b[1;34m(zones, values, zone_ids, stats_funcs, nodata_values, return_type)\\u001b[0m\\n\\u001b[0;32m 568\\u001b[0m stats_funcs_dict \\u001b[38;5;241m=\\u001b[39m stats_funcs\\u001b[38;5;241m.\\u001b[39mcopy()\\n\\u001b[0;32m 570\\u001b[0m mapper \\u001b[38;5;241m=\\u001b[39m ArrayTypeFunctionMapping(\\n\\u001b[0;32m 571\\u001b[0m numpy_func\\u001b[38;5;241m=\\u001b[39m\\u001b[38;5;28;01mlambda\\u001b[39;00m \\u001b[38;5;241m*\\u001b[39margs: _stats_numpy(\\u001b[38;5;241m*\\u001b[39margs, return_type\\u001b[38;5;241m=\\u001b[39mreturn_type),\\n\\u001b[0;32m 572\\u001b[0m dask_func\\u001b[38;5;241m=\\u001b[39m_stats_dask_numpy,\\n\\u001b[1;32m (...)\\u001b[0m\\n\\u001b[0;32m 576\\u001b[0m ),\\n\\u001b[0;32m 577\\u001b[0m )\\n\\u001b[0;32m 578\\u001b[0m result \\u001b[38;5;241m=\\u001b[39m mapper(values)(\\n\\u001b[1;32m--> 579\\u001b[0m zones\\u001b[38;5;241m.\\u001b[39mdata, values\\u001b[38;5;241m.\\u001b[39mdata, zone_ids, \\u001b[43mstats_funcs_dict\\u001b[49m, nodata_values,\\n\\u001b[0;32m 580\\u001b[0m )\\n\\u001b[0;32m 582\\u001b[0m \\u001b[38;5;28;01mif\\u001b[39;00m return_type \\u001b[38;5;241m==\\u001b[39m \\u001b[38;5;124m'\\u001b[39m\\u001b[38;5;124mxarray.DataArray\\u001b[39m\\u001b[38;5;124m'\\u001b[39m:\\n\\u001b[0;32m 583\\u001b[0m \\u001b[38;5;28;01mreturn\\u001b[39;00m xr\\u001b[38;5;241m.\\u001b[39mDataArray(\\n\\u001b[0;32m 584\\u001b[0m result,\\n\\u001b[0;32m 585\\u001b[0m coords\\u001b[38;5;241m=\\u001b[39m{\\u001b[38;5;124m'\\u001b[39m\\u001b[38;5;124mstats\\u001b[39m\\u001b[38;5;124m'\\u001b[39m: \\u001b[38;5;28mlist\\u001b[39m(stats_funcs_dict\\u001b[38;5;241m.\\u001b[39mkeys()), \\u001b[38;5;241m*\\u001b[39m\\u001b[38;5;241m*\\u001b[39mvalues\\u001b[38;5;241m.\\u001b[39mcoords},\\n\\u001b[0;32m 586\\u001b[0m dims\\u001b[38;5;241m=\\u001b[39m(\\u001b[38;5;124m'\\u001b[39m\\u001b[38;5;124mstats\\u001b[39m\\u001b[38;5;124m'\\u001b[39m, \\u001b[38;5;241m*\\u001b[39mvalues\\u001b[38;5;241m.\\u001b[39mdims),\\n\\u001b[0;32m 587\\u001b[0m attrs\\u001b[38;5;241m=\\u001b[39mvalues\\u001b[38;5;241m.\\u001b[39mattrs\\n\\u001b[0;32m 588\\u001b[0m )\\n\",\n", + " \"\\u001b[1;31mUnboundLocalError\\u001b[0m: local variable 'stats_funcs_dict' referenced before assignment\"\n", + " ]\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"# for one geography\\n\",\n", + " \"city_gdf_aoi[\\\"built_land_without_tree_cover\\\"] = built_land_without_tree_cover(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"afbb60b1-437f-4af5-99fe-9679559b250b\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"# HEA-3 Built land with Low Surface reflectivity\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 12,\n", + " \"id\": \"3c61a81e-f575-4d24-863d-ca9b7be34ad5\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import built_land_with_low_surface_reflectivity\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 13,\n", + " \"id\": \"748d1d72-c4fe-4c6c-91f6-99dac052bdd8\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 8.21 ss\\n\",\n", + " \"Calculating albedo layer:\\n\",\n", + " \"[########################################] | 100% Completed | 84.36 s\\n\",\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 8.32 ss\\n\",\n", + " \"CPU times: total: 30.5 s\\n\",\n", + " \"Wall time: 1min 49s\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_coverbuilt_land_without_tree_coverbuilt_land_with_low_surface_reflectivity
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...28.3667340.9073820.786552
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover built_land_without_tree_cover \\\\\\n\",\n", + " \"0 28.366734 0.907382 \\n\",\n", + " \"\\n\",\n", + " \" built_land_with_low_surface_reflectivity \\n\",\n", + " \"0 0.786552 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 13,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"city_gdf_aoi[\\\"built_land_with_low_surface_reflectivity\\\"] = built_land_with_low_surface_reflectivity(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"bbfcabaa-2acc-4b9b-bdce-27b415e04354\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"# HEA-2 Built Land With High LST\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 14,\n", + " \"id\": \"6df5d7a3-1c25-49ac-ab33-9081722168c9\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import built_land_with_high_land_surface_temperature\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 15,\n", + " \"id\": \"5288d4e6-e35d-48f4-9ff7-2d84c857b21a\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 8.65 ss\\n\",\n", + " \"Calculating land surface temperature layer:\\n\",\n", + " \"[########################################] | 100% Completed | 2.73 ss\\n\",\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 9.16 ss\\n\",\n", + " \"CPU times: total: 14.8 s\\n\",\n", + " \"Wall time: 37.7 s\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_coverbuilt_land_without_tree_coverbuilt_land_with_low_surface_reflectivitybuilt_land_with_high_land_surface_temperature
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...28.3667340.9073820.7865520.0961
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover built_land_without_tree_cover \\\\\\n\",\n", + " \"0 28.366734 0.907382 \\n\",\n", + " \"\\n\",\n", + " \" built_land_with_low_surface_reflectivity \\\\\\n\",\n", + " \"0 0.786552 \\n\",\n", + " \"\\n\",\n", + " \" built_land_with_high_land_surface_temperature \\n\",\n", + " \"0 0.0961 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 15,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"city_gdf_aoi[\\\"built_land_with_high_land_surface_temperature\\\"] = built_land_with_high_land_surface_temperature(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"feb93688-9435-47a5-be31-0a806dd48fe1\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"# Percent of Natural areas\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 18,\n", + " \"id\": \"aee87e06-d16d-4017-a5e1-7fd8cef906d4\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import natural_areas\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": null,\n", + " \"id\": \"026261af-a18d-4c0c-bdb8-b11a3c192ddc\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"# for one geography\\n\",\n", + " \"city_gdf_aoi[\\\"natural_areas\\\"] = natural_areas(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"markdown\",\n", + " \"id\": \"b05cef42-67cd-4cdc-a7db-5f34ddd7837b\",\n", + " \"metadata\": {},\n", + " \"source\": [\n", + " \"# Open Space in built up land\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 21,\n", + " \"id\": \"b4281469-9ca5-4b2c-a308-32f2e2fd5404\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": [\n", + " \"from city_metrix.metrics import urban_open_space\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": 22,\n", + " \"id\": \"db612f31-eb82-4a10-9433-0907f0a64a0e\",\n", + " \"metadata\": {},\n", + " \"outputs\": [\n", + " {\n", + " \"name\": \"stdout\",\n", + " \"output_type\": \"stream\",\n", + " \"text\": [\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 12.48 s\\n\",\n", + " \"Extracting ESA world cover layer:\\n\",\n", + " \"[########################################] | 100% Completed | 9.08 ss\\n\",\n", + " \"CPU times: total: 24 s\\n\",\n", + " \"Wall time: 31.1 s\\n\"\n", + " ]\n", + " },\n", + " {\n", + " \"data\": {\n", + " \"text/html\": [\n", + " \"
\\n\",\n", + " \"\\n\",\n", + " \"\\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \" \\n\",\n", + " \"
geo_idgeo_levelgeo_namegeo_parent_namecreation_dategeometrymean_tree_coverbuilt_land_without_tree_coverbuilt_land_with_low_surface_reflectivitybuilt_land_with_high_land_surface_temperatureurban_open_space
0BRA-Salvador_ADM4-union_1ADM4-unionBRA-SalvadorBRA-Salvador2022-08-03MULTIPOLYGON (((-38.50135 -13.01134, -38.50140...28.3667340.9073820.7865520.09610.028378
\\n\",\n", + " \"
\"\n", + " ],\n", + " \"text/plain\": [\n", + " \" geo_id geo_level geo_name geo_parent_name \\\\\\n\",\n", + " \"0 BRA-Salvador_ADM4-union_1 ADM4-union BRA-Salvador BRA-Salvador \\n\",\n", + " \"\\n\",\n", + " \" creation_date geometry \\\\\\n\",\n", + " \"0 2022-08-03 MULTIPOLYGON (((-38.50135 -13.01134, -38.50140... \\n\",\n", + " \"\\n\",\n", + " \" mean_tree_cover built_land_without_tree_cover \\\\\\n\",\n", + " \"0 28.366734 0.907382 \\n\",\n", + " \"\\n\",\n", + " \" built_land_with_low_surface_reflectivity \\\\\\n\",\n", + " \"0 0.786552 \\n\",\n", + " \"\\n\",\n", + " \" built_land_with_high_land_surface_temperature urban_open_space \\n\",\n", + " \"0 0.0961 0.028378 \"\n", + " ]\n", + " },\n", + " \"execution_count\": 22,\n", + " \"metadata\": {},\n", + " \"output_type\": \"execute_result\"\n", + " }\n", + " ],\n", + " \"source\": [\n", + " \"%%time\\n\",\n", + " \"\\n\",\n", + " \"# for one geography\\n\",\n", + " \"city_gdf_aoi[\\\"urban_open_space\\\"] = urban_open_space(city_gdf_aoi) \\n\",\n", + " \"city_gdf_aoi\"\n", + " ]\n", + " },\n", + " {\n", + " \"cell_type\": \"code\",\n", + " \"execution_count\": null,\n", + " \"id\": \"951151f1-e0f5-4a8a-99a7-19a6f7c84591\",\n", + " \"metadata\": {},\n", + " \"outputs\": [],\n", + " \"source\": []\n", + " }\n", + " ],\n", + " \"metadata\": {\n", + " \"kernelspec\": {\n", + " \"display_name\": \"Python 3 (ipykernel)\",\n", + " \"language\": \"python\",\n", + " \"name\": \"python3\"\n", + " },\n", + " \"language_info\": {\n", + " \"codemirror_mode\": {\n", + " \"name\": \"ipython\",\n", + " \"version\": 3\n", + " },\n", + " \"file_extension\": \".py\",\n", + " \"mimetype\": \"text/x-python\",\n", + " \"name\": \"python\",\n", + " \"nbconvert_exporter\": \"python\",\n", + " \"pygments_lexer\": \"ipython3\",\n", + " \"version\": \"3.10.13\"\n", + " }\n", + " },\n", + " \"nbformat\": 4,\n", + " \"nbformat_minor\": 5\n", + "}" + ], + "metadata": { + "collapsed": false + } + } } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/notebooks/tutorial/get layers.ipynb b/notebooks/tutorial/get layers.ipynb index 195deae..883d107 100644 --- a/notebooks/tutorial/get layers.ipynb +++ b/notebooks/tutorial/get layers.ipynb @@ -4693,10 +4693,10 @@ "evalue": "name 'TreeCanopyHeight' is not defined", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[5], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Load 1m Global Tree Canopy Hight layer\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m city_TreeCanopyHeight \u001b[38;5;241m=\u001b[39m \u001b[43mTreeCanopyHeight\u001b[49m()\u001b[38;5;241m.\u001b[39mget_data(city_gdf\u001b[38;5;241m.\u001b[39mtotal_bounds)\n\u001b[1;32m 3\u001b[0m city_TreeCanopyHeight\n", - "\u001b[0;31mNameError\u001b[0m: name 'TreeCanopyHeight' is not defined" + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mNameError\u001B[0m Traceback (most recent call last)", + "Cell \u001B[0;32mIn[5], line 2\u001B[0m\n\u001B[1;32m 1\u001B[0m \u001B[38;5;66;03m# Load 1m Global Tree Canopy Hight layer\u001B[39;00m\n\u001B[0;32m----> 2\u001B[0m city_TreeCanopyHeight \u001B[38;5;241m=\u001B[39m \u001B[43mTreeCanopyHeight\u001B[49m()\u001B[38;5;241m.\u001B[39mget_data(city_gdf\u001B[38;5;241m.\u001B[39mtotal_bounds)\n\u001B[1;32m 3\u001B[0m city_TreeCanopyHeight\n", + "\u001B[0;31mNameError\u001B[0m: name 'TreeCanopyHeight' is not defined" ] } ], @@ -5373,4 +5373,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 7e935f8..b56318c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,6 +34,7 @@ def create_fishnet_grid(min_x, min_y, max_x, max_y, cell_size): ZONES = create_fishnet_grid(106.7, -6.3, 106.8, -6.2, 0.01).reset_index() LARGE_ZONES = create_fishnet_grid(106, -7, 107, -6, 0.1).reset_index() + class MockLayer(Layer): """ Simple mock layer that just rasterizes the zones @@ -66,6 +67,23 @@ def get_data(self, bbox): return mask +class MockGroupByLayer(Layer): + """ + Simple categorical layer with alternating 1s and 2s + """ + def get_data(self, bbox): + group_by_gdf = create_fishnet_grid(*bbox, 0.001).reset_index() + group_by_gdf['index'] = (group_by_gdf['index'] % 2) + 1 + group_by = make_geocube( + vector_data=group_by_gdf, + measurements=['index'], + resolution=(0.001, 0.001), + output_crs=4326, + ).index + + return group_by + + class MockLargeLayer(Layer): """ Simple mock layer that just rasterizes the zones @@ -77,4 +95,22 @@ def get_data(self, bbox): resolution=(0.01, 0.01), output_crs=4326, ).index - return arr \ No newline at end of file + return arr + + +class MockLargeGroupByLayer(Layer): + """ + Large categorical layer with alternating 1s and 2s + """ + + def get_data(self, bbox): + group_by_gdf = create_fishnet_grid(*bbox, 0.01).reset_index() + group_by_gdf['index'] = (group_by_gdf['index'] % 2) + 1 + group_by = make_geocube( + vector_data=group_by_gdf, + measurements=['index'], + resolution=(0.01, 0.01), + output_crs=4326, + ).index + + return group_by \ No newline at end of file diff --git a/tests/layers.py b/tests/layers.py index ce9fc3f..adf01ea 100644 --- a/tests/layers.py +++ b/tests/layers.py @@ -2,8 +2,8 @@ from city_metrix.layers import LandsatCollection2, Albedo, LandSurfaceTemperature, EsaWorldCover, EsaWorldCoverClass, TreeCover, AverageNetBuildingHeight, OpenStreetMap, OpenStreetMapClass, UrbanLandUse, OpenBuildings, TreeCanopyHeight, AlosDSM from city_metrix.layers.layer import get_image_collection -from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer - +from .conftest import MockLayer, MockMaskLayer, ZONES, LARGE_ZONES, MockLargeLayer, MockGroupByLayer, \ + MockLargeGroupByLayer import pytest import numpy as np @@ -43,6 +43,16 @@ def test_masks(): assert count == 100 +def test_group_by_layer(): + counts = MockLayer().groupby(ZONES, layer=MockGroupByLayer()).count() + assert all([count == {1: 50.0, 2: 50.0} for count in counts]) + + +def test_group_by_large_layer(): + counts = MockLargeLayer().groupby(LARGE_ZONES, layer=MockLargeGroupByLayer()).count() + assert all([count == {1: 50.0, 2: 50.0} for count in counts]) + + SAMPLE_BBOX = (-38.35530428121955, -12.821710300686393, -38.33813814352424, -12.80363249765361)