Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cif 234 veg water change #91

Merged
merged 11 commits into from
Jan 13, 2025
1 change: 1 addition & 0 deletions city_metrix/layers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
from .glad_lulc import LandCoverHabitatGlad
from .glad_lulc import LandCoverHabitatChangeGlad
from .cams import Cams
from .vegetation_water_map import VegetationWaterMap
140 changes: 67 additions & 73 deletions city_metrix/layers/albedo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Albedo(Layer):
resampling_method: interpolation method used by Google Earth Engine. Default is 'bilinear'. All options are: ('bilinear', 'bicubic', None).
threshold: threshold value for filtering the retrieval
"""
MAX_CLOUD_PROB = 30
S2_ALBEDO_EQN = '((B*Bw)+(G*Gw)+(R*Rw)+(NIR*NIRw)+(SWIR1*SWIR1w)+(SWIR2*SWIR2w))'

def __init__(self, start_date="2021-01-01", end_date="2022-01-01", spatial_resolution:int=10,
resampling_method:str='bilinear', threshold=None, **kwargs):
Expand All @@ -23,78 +25,70 @@ def __init__(self, start_date="2021-01-01", end_date="2022-01-01", spatial_resol
self.spatial_resolution = spatial_resolution
self.resampling_method = resampling_method
self.threshold = threshold

def get_data(self, bbox: tuple[float, float, float, float]):
S2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
S2C = ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY")

MAX_CLOUD_PROB = 30
S2_ALBEDO_EQN = '((B*Bw)+(G*Gw)+(R*Rw)+(NIR*NIRw)+(SWIR1*SWIR1w)+(SWIR2*SWIR2w))'

## METHODS

## get cloudmasked image collection

def mask_and_count_clouds(s2wc, geom):
s2wc = ee.Image(s2wc)
geom = ee.Geometry(geom.geometry())
is_cloud = (ee.Image(s2wc.get('cloud_mask'))
.gt(MAX_CLOUD_PROB)
.rename('is_cloud')
)

nb_cloudy_pixels = is_cloud.reduceRegion(
reducer=ee.Reducer.sum().unweighted(),
geometry=geom,
scale=self.spatial_resolution,
maxPixels=1e9
)
mask = (s2wc
.updateMask(is_cloud.eq(0))
.set('nb_cloudy_pixels',nb_cloudy_pixels.getNumber('is_cloud'))
.divide(10000)

## METHODS
## get cloudmasked image collection
def mask_and_count_clouds(self, s2wc, geom):
s2wc = ee.Image(s2wc)
geom = ee.Geometry(geom.geometry())
is_cloud = (ee.Image(s2wc.get('cloud_mask'))
.gt(self.MAX_CLOUD_PROB)
.rename('is_cloud')
)

return mask

def mask_clouds_and_rescale(im):
clouds = ee.Image(im.get('cloud_mask')
).select('probability')
mask = im.updateMask(clouds
.lt(MAX_CLOUD_PROB)
).divide(10000)

return mask

def get_masked_s2_collection(roi, start, end):
criteria = (ee.Filter.And(
ee.Filter.date(start, end),
ee.Filter.bounds(roi)
))
s2 = S2.filter(criteria) # .select('B2','B3','B4','B8','B11','B12')
s2c = S2C.filter(criteria)
s2_with_clouds = (
ee.Join.saveFirst('cloud_mask')
.apply(**{
'primary': ee.ImageCollection(s2),
'secondary': ee.ImageCollection(s2c),
'condition': ee.Filter.equals(**{'leftField': 'system:index', 'rightField': 'system:index'})
})
)

def _mcc(im):
return mask_and_count_clouds(im, roi)
# s2_with_clouds=ee.ImageCollection(s2_with_clouds).map(_mcc)

# s2_with_clouds=s2_with_clouds.limit(image_limit,'nb_cloudy_pixels')
s2_with_clouds = (ee.ImageCollection(s2_with_clouds)
.map(mask_clouds_and_rescale)
) # .limit(image_limit,'CLOUDY_PIXEL_PERCENTAGE')

s2_with_clouds_ic = ee.ImageCollection(s2_with_clouds)

return s2_with_clouds_ic

nb_cloudy_pixels = is_cloud.reduceRegion(
reducer=ee.Reducer.sum().unweighted(),
geometry=geom,
scale=self.spatial_resolution,
maxPixels=1e9
)
mask = (s2wc
.updateMask(is_cloud.eq(0))
.set('nb_cloudy_pixels',nb_cloudy_pixels.getNumber('is_cloud'))
.divide(10000)
)

return mask

def mask_clouds_and_rescale(self, im):
clouds = ee.Image(im.get('cloud_mask')
).select('probability')
mask = im.updateMask(clouds
.lt(self.MAX_CLOUD_PROB)
).divide(10000)

return mask

def get_masked_s2_collection(self, roi, start, end):
criteria = (ee.Filter.And(
ee.Filter.date(start, end),
ee.Filter.bounds(roi)
))
s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED").filter(criteria) # .select('B2','B3','B4','B8','B11','B12')
s2c = ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY").filter(criteria)
s2_with_clouds = (
ee.Join.saveFirst('cloud_mask')
.apply(**{
'primary': ee.ImageCollection(s2),
'secondary': ee.ImageCollection(s2c),
'condition': ee.Filter.equals(**{'leftField': 'system:index', 'rightField': 'system:index'})
})
)

def _mcc(im):
return self.mask_and_count_clouds(im, roi)
# s2_with_clouds=ee.ImageCollection(s2_with_clouds).map(_mcc)

# s2_with_clouds=s2_with_clouds.limit(image_limit,'nb_cloudy_pixels')
s2_with_clouds = (ee.ImageCollection(s2_with_clouds)
.map(self.mask_clouds_and_rescale)
) # .limit(image_limit,'CLOUDY_PIXEL_PERCENTAGE')

s2_with_clouds_ic = ee.ImageCollection(s2_with_clouds)

return s2_with_clouds_ic

def get_data(self, bbox):
# calculate albedo for images
# weights derived from
# S. Bonafoni and A. Sekertekin, "Albedo Retrieval From Sentinel-2 by New Narrow-to-Broadband Conversion Coefficients," in IEEE Geoscience and Remote Sensing Letters, vol. 17, no. 9, pp. 1618-1622, Sept. 2020, doi: 10.1109/LGRS.2020.2967085.
Expand All @@ -114,12 +108,12 @@ def calc_s2_albedo(image):
'SWIR2': image.select('B12')
}

albedo = image.expression(S2_ALBEDO_EQN, config).double().rename('albedo')
albedo = image.expression(self.S2_ALBEDO_EQN, config).double().rename('albedo')

return albedo

## S2 MOSAIC AND ALBEDO
dataset = get_masked_s2_collection(ee.Geometry.BBox(*bbox), self.start_date, self.end_date)
# S2 MOSAIC AND ALBEDO
dataset = self.get_masked_s2_collection(ee.Geometry.BBox(*bbox), self.start_date, self.end_date)
s2_albedo = dataset.map(calc_s2_albedo)

albedo_mean = (s2_albedo
Expand Down
Loading
Loading