Landscape Expansion Index#
More details on the wiki - worldbank/GOST_Urban
The Landscape Expansion Index measures the nature of urbanization, quantifying the new urban landscape as one of the following three categories. The process works by isolating the areas of new urban footprint in your study area, buffering those by a set amount (300 m) and intersecting the buffer donut with the original urban area. LEI is calculated as the ratio of the area of the buffer to the area of the old built area within the buffer (the threshold for each class is customizable).
Expansion Type |
Description |
---|---|
Infill |
> 80% of the donut is in the old urban area |
Expansion |
> 20% and < 80% of the donut is in the old urban area |
Leapfrog |
< 20% of the donut is in the old urban area |
import os
import rasterio
import rasterio.features
import geopandas as gpd
import pandas as pd
import GOSTRocks.rasterMisc as rMisc
import GOSTRocks.ghslMisc as ghslMisc
import GOSTurban.LEI as lei
import GOSTRocks.mapMisc as mapMisc
%load_ext autoreload
%autoreload 2
# Define input variables
tutorial_folder = "../../data/tutorial_data"
aoi_file = os.path.join(tutorial_folder, "AOI_GHSL.geojson")
input_ghsl = os.path.join(tutorial_folder, "GHSL.tif")
# This section will extract GHSL data from global data, if you have the GHSL for the AOI extracted
# define above as input_ghsl
if not os.path.exists(input_ghsl):
temp_folder = "C:/Temp"
# clip from global GHSL file
ghsl_folder = "J:/Data/GLOBAL/GHSL/built"
ghsl_files = [
os.path.join(ghsl_folder, x)
for x in os.listdir(ghsl_folder)
if x.endswith(".tif")
]
inA = gpd.read_file(aoi_file)
temp_ghsl_files = []
for ghsl_file in ghsl_files:
temp_file = os.path.join(temp_folder, os.path.basename(ghsl_file))
temp_ghsl_files.append(temp_file)
if not os.path.exists(temp_file):
rMisc.clipRaster(rasterio.open(ghsl_file), inA, temp_file)
ghsl_res, ghsl_profile = ghslMisc.combine_ghsl_annual(temp_ghsl_files)
with rasterio.open(input_ghsl, "w", **ghsl_profile) as outR:
outR.write_band(1, ghsl_res)
GHSL data#
This tutorial relies on the Global Human Settlement Layer (GHSL) produced by the European Commission ([download the data here])(https://ghsl.jrc.ec.europa.eu/download.php).
The current release of the data provides individual layers ber annum of fractional area built per 1 hectare cell. For the LEI examples, we need binary data of existing built and new built. We leverage a function from the GOSTrocks library to combine these multiple yearly layers into a single geotiff with each pixel labelled with the year it was built.
ghsl_r = rasterio.open(input_ghsl)
ghsl_d = ghsl_r.read()
ghsl_d[ghsl_d == ghsl_r.meta["nodata"]] = 0
thresh = list(range(1975, 2031, 5))
with rMisc.create_rasterio_inmemory(ghsl_r.profile, ghsl_d) as temp_ghsl:
mapMisc.static_map_raster(temp_ghsl, thresh=thresh)
Calculate LEI between 1990 and 2000#
# This calculates the change from 1990 and 2000
lei_raw = lei.calculate_LEI(
input_ghsl, old_list=list(range(1975, 1991, 5)), new_list=list(range(1995, 2001, 5))
)
lei_90_00 = gpd.GeoDataFrame(
pd.DataFrame(lei_raw, columns=["geometry", "old", "total"]),
geometry="geometry",
crs=ghsl_r.crs,
)
lei_90_00["LEI"] = lei_90_00["old"] / lei_90_00["total"]
lei_90_00.head()
# Map LEI results
leap_val = 0.30
exp_val = 0.70
lei_90_00["area"] = lei_90_00["geometry"].apply(lambda x: x.area)
def calculate_LEI(val, leap_val, exp_val):
if val <= leap_val:
return 3
elif val < exp_val:
return 2
else:
return 1
lei_90_00["class"] = lei_90_00["LEI"].apply(
lambda x: calculate_LEI(x, leap_val, exp_val)
)
mapMisc.static_map_vector(
lei_90_00, "class", edgecolor="match", colormap="Dark2"
) # , basemap=ctx.providers.CartoDB.Voyager)
# Calculate summaries of lei as area (km2) in each class
lei.summarize_LEI(lei_90_00, leap_val=0.05, exp_val=0.75) / 1000000
Calculate LEI between 2000 and 2030#
# This calculates the change from 2000 and 2014
lei_raw = lei.calculate_LEI(
input_ghsl, old_list=list(range(1975, 2011, 5)), new_list=list(range(2015, 2030, 5))
)
lei_00_14 = pd.DataFrame(lei_raw, columns=["geometry", "old", "total"])
lei_00_14["LEI"] = lei_00_14["old"] / lei_00_14["total"]
lei_00_14.head()
# Map LEI results
leap_val = 0.30
exp_val = 0.70
lei_90_00["area"] = lei_90_00["geometry"].apply(lambda x: x.area)
# def calculate_LEI(val, leap_val, exp_val):
# if val <= leap_val:
# return 3
# elif val < exp_val:
# return 2
# else:
# return 1
lei_90_00["class"] = lei_90_00["LEI"].apply(
lambda x: calculate_LEI(x, leap_val, exp_val)
)
mapMisc.static_map_vector(
lei_90_00, "class", edgecolor="match", colormap="Dark2"
) # , basemap=ctx.providers.CartoDB.Voyager)
# Calculate summaries of lei
lei.summarize_LEI(lei_00_14, leap_val=0.05, exp_val=0.75) / 1000000
# write raw LEI results to file
input_folder = "."
lei_90_00.to_csv(os.path.join(input_folder, "GHSL_LEI_90_00.csv"))
lei_00_14.to_csv(os.path.join(input_folder, "GHSL_LEI_00_14.csv"))