Skip to content

Commit

Permalink
Renamed class property in compliance with stac standard. Implemented …
Browse files Browse the repository at this point in the history
…test_layer_parameters in a manner intended to improve ease of code maintenance.
  • Loading branch information
kcartier-wri committed Aug 29, 2024
1 parent 6c66430 commit 1648974
Show file tree
Hide file tree
Showing 14 changed files with 197 additions and 115 deletions.
16 changes: 12 additions & 4 deletions city_metrix/layers/albedo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@
from .layer import Layer, get_utm_zone_epsg, get_image_collection

class Albedo(Layer):
def __init__(self, start_date="2021-01-01", end_date="2022-01-01", scale_meters=10, threshold=None, **kwargs):
"""
Attributes:
start_date: starting date for data retrieval
end_date: ending date for data retrieval
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
threshold: threshold value for filtering the retrieval
"""

def __init__(self, start_date="2021-01-01", end_date="2022-01-01", spatial_resolution=10, threshold=None, **kwargs):
super().__init__(**kwargs)
self.start_date = start_date
self.end_date = end_date
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution
self.threshold = threshold

def get_data(self, bbox):
Expand All @@ -30,7 +38,7 @@ def mask_and_count_clouds(s2wc, geom):
nb_cloudy_pixels = is_cloud.reduceRegion(
reducer=ee.Reducer.sum().unweighted(),
geometry=geom,
scale=self.scale_meters,
scale=self.spatial_resolution,
maxPixels=1e9
)
return s2wc.updateMask(is_cloud.eq(0)).set('nb_cloudy_pixels',
Expand Down Expand Up @@ -89,7 +97,7 @@ def calc_s2_albedo(image):
albedo_mean = s2_albedo.reduce(ee.Reducer.mean())

data = (get_image_collection(
ee.ImageCollection(albedo_mean), bbox, self.scale_meters, "albedo")
ee.ImageCollection(albedo_mean), bbox, self.spatial_resolution, "albedo")
.albedo_mean)

if self.threshold is not None:
Expand Down
11 changes: 8 additions & 3 deletions city_metrix/layers/alos_dsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@


class AlosDSM(Layer):
def __init__(self, scale_meters=30, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=30, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
dataset = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2")
Expand All @@ -17,6 +22,6 @@ def get_data(self, bbox):
.select('DSM')
.mean()
)
data = get_image_collection(alos_dsm, bbox, self.scale_meters, "ALOS DSM").DSM
data = get_image_collection(alos_dsm, bbox, self.spatial_resolution, "ALOS DSM").DSM

return data
11 changes: 8 additions & 3 deletions city_metrix/layers/average_net_building_height.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
from .layer import Layer, get_utm_zone_epsg, get_image_collection

class AverageNetBuildingHeight(Layer):
def __init__(self, scale_meters=100, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=100, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
# https://ghsl.jrc.ec.europa.eu/ghs_buH2023.php
Expand All @@ -19,7 +24,7 @@ def get_data(self, bbox):

anbh = ee.Image("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_GLOBE_R2023A")
data = (get_image_collection(
ee.ImageCollection(anbh), bbox, self.scale_meters, "average net building height")
ee.ImageCollection(anbh), bbox, self.spatial_resolution, "average net building height")
.b1)

return data
11 changes: 8 additions & 3 deletions city_metrix/layers/built_up_height.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@


class BuiltUpHeight(Layer):
def __init__(self, scale_meters=100, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=100, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
# Notes for Heat project:
Expand All @@ -19,6 +24,6 @@ def get_data(self, bbox):
# ee.ImageCollection("projects/wri-datalab/GHSL/GHS-BUILT-H-ANBH_R2023A")

built_height = ee.Image("JRC/GHSL/P2023A/GHS_BUILT_H/2018")
data = get_image_collection(ee.ImageCollection(built_height), bbox, self.scale_meters, "built up height")
data = get_image_collection(ee.ImageCollection(built_height), bbox, self.spatial_resolution, "built up height")
return data.built_height

15 changes: 11 additions & 4 deletions city_metrix/layers/esa_world_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,36 @@ class EsaWorldCoverClass(Enum):
MOSS_AND_LICHEN = 100

class EsaWorldCover(Layer):
"""
Attributes:
land_cover_class: Enum value from EsaWorldCoverClass
year: year used for data retrieval
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

STAC_CATALOG_URI = "https://services.terrascope.be/stac/"
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, year=2020, scale_meters=10, **kwargs):
def __init__(self, land_cover_class=None, year=2020, spatial_resolution=10, **kwargs):
super().__init__(**kwargs)
self.land_cover_class = land_cover_class
self.year = year
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
if self.year == 2020:
data = get_image_collection(
ee.ImageCollection("ESA/WorldCover/v100"),
bbox,
self.scale_meters,
self.spatial_resolution,
"ESA world cover"
).Map
elif self.year == 2021:
data = get_image_collection(
ee.ImageCollection("ESA/WorldCover/v200"),
bbox,
self.scale_meters,
self.spatial_resolution,
"ESA world cover"
).Map

Expand Down
13 changes: 10 additions & 3 deletions city_metrix/layers/land_surface_temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@
import xarray

class LandSurfaceTemperature(Layer):
def __init__(self, start_date="2013-01-01", end_date="2023-01-01", scale_meters=30, **kwargs):
"""
Attributes:
start_date: starting date for data retrieval
end_date: ending date for data retrieval
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, start_date="2013-01-01", end_date="2023-01-01", spatial_resolution=30, **kwargs):
super().__init__(**kwargs)
self.start_date = start_date
self.end_date = end_date
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
def cloud_mask(image):
Expand All @@ -31,5 +38,5 @@ def apply_scale_factors(image):
.map(apply_scale_factors) \
.reduce(ee.Reducer.mean())

data = get_image_collection(ee.ImageCollection(l8_st), bbox, self.scale_meters, "LST").ST_B10_mean
data = get_image_collection(ee.ImageCollection(l8_st), bbox, self.spatial_resolution, "LST").ST_B10_mean
return data
11 changes: 8 additions & 3 deletions city_metrix/layers/nasa_dem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@


class NasaDEM(Layer):
def __init__(self, scale_meters=30, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=30, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
dataset = ee.Image("NASA/NASADEM_HGT/001")
Expand All @@ -17,6 +22,6 @@ def get_data(self, bbox):
.select('elevation')
.mean()
)
data = get_image_collection(nasa_dem, bbox, self.scale_meters, "NASA DEM").elevation
data = get_image_collection(nasa_dem, bbox, self.spatial_resolution, "NASA DEM").elevation

return data
11 changes: 8 additions & 3 deletions city_metrix/layers/natural_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
from .esa_world_cover import EsaWorldCover, EsaWorldCoverClass

class NaturalAreas(Layer):
def __init__(self, scale_meters=10, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=10, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
esa_world_cover = EsaWorldCover(scale_meters=self.scale_meters).get_data(bbox)
esa_world_cover = EsaWorldCover(spatial_resolution=self.spatial_resolution).get_data(bbox)
reclass_map = {
EsaWorldCoverClass.TREE_COVER.value: 1,
EsaWorldCoverClass.SHRUBLAND.value: 1,
Expand Down
10 changes: 6 additions & 4 deletions city_metrix/layers/ndvi_sentinel2_gee.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
class NdviSentinel2(Layer):
""""
NDVI = Sentinel-2 Normalized Difference Vegetation Index
param: year: The satellite imaging year.
Attributes:
year: The satellite imaging year.
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
return: a rioxarray-format DataArray
Author of associated Jupyter notebook: [email protected]
Notebook: https://github.com/wri/cities-cities4forests-indicators/blob/dev-eric/scripts/extract-VegetationCover.ipynb
Reference: https://en.wikipedia.org/wiki/Normalized_difference_vegetation_index
"""
def __init__(self, year=None, scale_meters=10, **kwargs):
def __init__(self, year=None, spatial_resolution=10, **kwargs):
super().__init__(**kwargs)
self.year = year
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
if self.year is None:
Expand All @@ -40,7 +42,7 @@ def calculate_ndvi(image):
ndvi_mosaic = ndvi.qualityMosaic('NDVI')

ic = ee.ImageCollection(ndvi_mosaic)
ndvi_data = get_image_collection(ic, bbox, self.scale_meters, "NDVI")
ndvi_data = get_image_collection(ic, bbox, self.spatial_resolution, "NDVI")

xdata = ndvi_data.to_dataarray()

Expand Down
11 changes: 8 additions & 3 deletions city_metrix/layers/tree_canopy_height.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@
import ee

class TreeCanopyHeight(Layer):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

name = "tree_canopy_height"
NO_DATA_VALUE = 0

def __init__(self, scale_meters=1, **kwargs):
def __init__(self, spatial_resolution=1, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

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,
self.scale_meters, "tree canopy height")
self.spatial_resolution, "tree canopy height")

return data.cover_code
12 changes: 8 additions & 4 deletions city_metrix/layers/tree_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,27 @@
class TreeCover(Layer):
"""
Merged tropical and nontropical tree cover from WRI
Attributes:
min_tree_cover: minimum tree-cover values used for filtering results
max_tree_cover: maximum tree-cover values used for filtering results
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

NO_DATA_VALUE = 255

def __init__(self, min_tree_cover=None, max_tree_cover=None, scale_meters=10, **kwargs):
def __init__(self, min_tree_cover=None, max_tree_cover=None, spatial_resolution=10, **kwargs):
super().__init__(**kwargs)
self.min_tree_cover = min_tree_cover
self.max_tree_cover = max_tree_cover
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
tropics = ee.ImageCollection('projects/wri-datalab/TropicalTreeCover')
nontropics = ee.ImageCollection('projects/wri-datalab/TTC-nontropics')
merged_ttc = tropics.merge(nontropics)
ttc_image = merged_ttc.reduce(ee.Reducer.mean()).rename('ttc')

data = get_image_collection(ee.ImageCollection(ttc_image), bbox, self.scale_meters, "tree cover").ttc
data = get_image_collection(ee.ImageCollection(ttc_image), bbox, self.spatial_resolution, "tree cover").ttc

if self.min_tree_cover is not None:
data = data.where(data >= self.min_tree_cover)
Expand Down
12 changes: 9 additions & 3 deletions city_metrix/layers/urban_land_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@


class UrbanLandUse(Layer):
def __init__(self, band='lulc', scale_meters=5, **kwargs):
"""
Attributes:
band: raster band used for data retrieval
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, band='lulc', spatial_resolution=5, **kwargs):
super().__init__(**kwargs)
self.band = band
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
dataset = ee.ImageCollection("projects/wri-datalab/cities/urban_land_use/V1")
Expand All @@ -28,6 +34,6 @@ def get_data(self, bbox):
.rename('lulc')
)

data = get_image_collection(ulu, bbox, self.scale_meters, "urban land use").lulc
data = get_image_collection(ulu, bbox, self.spatial_resolution, "urban land use").lulc

return data
11 changes: 8 additions & 3 deletions city_metrix/layers/world_pop.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
from .layer import Layer, get_utm_zone_epsg, get_image_collection

class WorldPop(Layer):
def __init__(self, scale_meters=100, **kwargs):
"""
Attributes:
spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster)
"""

def __init__(self, spatial_resolution=100, **kwargs):
super().__init__(**kwargs)
self.scale_meters = scale_meters
self.spatial_resolution = spatial_resolution

def get_data(self, bbox):
# load population
Expand All @@ -20,5 +25,5 @@ def get_data(self, bbox):
.mean()
)

data = get_image_collection(world_pop, bbox, self.scale_meters, "world pop")
data = get_image_collection(world_pop, bbox, self.spatial_resolution, "world pop")
return data.population
Loading

0 comments on commit 1648974

Please sign in to comment.