gee_s2_funcs module¶
This module contains functions for working with satellite images and Google Earth Engine.
apply_scale_factorsL8(img)
¶
Applies scale factors to Landsat 8 imagery bands.
This function scales the optical and thermal bands of a Landsat 8 image. The optical bands are scaled by multiplying by 0.0000275 and adding -0.2. The thermal bands are scaled by multiplying by 0.00341802 and adding 149.0.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
img |
ee.Image |
The input Landsat 8 image to which the scale factors will be applied. |
required |
Returns:
Type | Description |
---|---|
ee.Image |
The image with scaled optical and thermal bands. |
Source code in gishndev/gee_s2_funcs.py
def apply_scale_factorsL8(img):
"""
Applies scale factors to Landsat 8 imagery bands.
This function scales the optical and thermal bands of a Landsat 8 image.
The optical bands are scaled by multiplying by 0.0000275 and adding -0.2.
The thermal bands are scaled by multiplying by 0.00341802 and adding 149.0.
Args:
img (ee.Image): The input Landsat 8 image to which the scale factors will be applied.
Returns:
ee.Image: The image with scaled optical and thermal bands.
"""
optical_bands = img.select("SR_B.").multiply(0.0000275).add(-0.2)
thermal_bands = img.select("ST_B.*").multiply(0.00341802).add(149.0)
return img.addBands(optical_bands, None, True).addBands(thermal_bands, None, True)
compute_index(img, index, params)
¶
Computes spectral indices for the given image and adds them as bands.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
img |
ee.Image |
The input image to which the spectral indices will be added. |
required |
index |
list or str |
A list of spectral indices to compute. If a single index is provided, it will be converted to a list. |
required |
params |
dict |
A dictionary of parameters required for computing the indices. |
required |
Returns:
Type | Description |
---|---|
ee.Image |
The input image with the computed spectral indices added as bands. |
Source code in gishndev/gee_s2_funcs.py
def compute_index(img, index, params):
"""
Computes spectral indices for the given image and adds them as bands.
Args:
img (ee.Image): The input image to which the spectral indices will be added.
index (list or str): A list of spectral indices to compute. If a single index is provided, it will be converted to a list.
params (dict): A dictionary of parameters required for computing the indices.
Returns:
ee.Image: The input image with the computed spectral indices added as bands.
"""
if not isinstance(index, list):
index = [index]
for idx in index:
formula = spectral_indices[idx]["formula"]
img = img.addBands(img.expression(formula, params).rename(idx))
return img
create_gdfbounds_from_tif(tif_path)
¶
Creates a GeoDataFrame from the bounds of a TIFF file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tif_path |
str |
Path to the TIFF file. |
required |
Returns:
Type | Description |
---|---|
gpd.GeoDataFrame |
GeoDataFrame with a polygon representing the bounds of the TIFF file. |
Source code in gishndev/gee_s2_funcs.py
def create_gdfbounds_from_tif(tif_path):
"""
Creates a GeoDataFrame from the bounds of a TIFF file.
Args:
tif_path (str): Path to the TIFF file.
Returns:
gpd.GeoDataFrame: GeoDataFrame with a polygon representing the bounds of the TIFF file.
"""
# Leer el archivo TIFF
with rasterio.open(tif_path) as src:
bounds = src.bounds
crs = src.crs
# Crear un polígono a partir de los límites
bbox = box(bounds.left, bounds.bottom, bounds.right, bounds.top)
# Crear un GeoDataFrame
gdf = gpd.GeoDataFrame({"geometry": [bbox]}, crs=crs)
return gdf
ee_to_df_sampled(samples, stack, n_samples)
¶
Subsets the given samples DataFrame, converts it to an Earth Engine FeatureCollection, samples the given stack Image using the subset, and returns the sampled data as a DataFrame.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
samples |
pd.DataFrame |
A DataFrame containing the sample points with their respective coordinates. |
required |
stack |
ee.Image |
An Earth Engine Image object from which to sample the data. |
required |
n_samples |
int |
The number of samples to subset from the samples DataFrame. |
required |
Returns:
Type | Description |
---|---|
pd.DataFrame |
A DataFrame containing the sampled data with properties from the Earth Engine Image. |
Source code in gishndev/gee_s2_funcs.py
def ee_to_df_sampled(samples, stack, n_samples):
"""
Subsets the given samples DataFrame, converts it to an Earth Engine FeatureCollection,
samples the given stack Image using the subset, and returns the sampled data as a DataFrame.
Args:
samples (pd.DataFrame): A DataFrame containing the sample points with their respective coordinates.
stack (ee.Image): An Earth Engine Image object from which to sample the data.
n_samples (int): The number of samples to subset from the samples DataFrame.
Returns:
pd.DataFrame: A DataFrame containing the sampled data with properties from the Earth Engine Image.
"""
subset = samples.iloc[0:n_samples]
subset_ee = geemap.geopandas_to_ee(subset)
sampled = stack.sampleRegions(collection=subset_ee, scale=10, geometries=True)
features = sampled.getInfo()["features"]
data = []
for feature in features:
properties = feature["properties"]
data.append(properties)
df = pd.DataFrame(data)
return df
extract_values_to_point_per_part(samples, stack, num_samples, out_dir, out_file_name)
¶
Extracts values to points for each part of the samples and saves the output to a specified directory.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
samples |
gpd.GeoDataFrame |
A GeoDataFrame containing the sample points. |
required |
stack |
ee.Image |
The image stack from which to extract values. |
required |
num_samples |
int |
The number of samples to process in each part. |
required |
out_dir |
str |
The output directory where the results will be saved. |
required |
out_file_name |
str |
The base name for the output files. |
required |
Source code in gishndev/gee_s2_funcs.py
def extract_values_to_point_per_part(
samples, stack, num_samples, out_dir, out_file_name
):
"""
Extracts values to points for each part of the samples and saves the output to a specified directory.
Args:
samples (gpd.GeoDataFrame): A GeoDataFrame containing the sample points.
stack (ee.Image): The image stack from which to extract values.
num_samples (int): The number of samples to process in each part.
out_dir (str): The output directory where the results will be saved.
out_file_name (str): The base name for the output files.
"""
# Extract the basename of the input samples
out_fc_base = f"{out_dir}/{out_file_name}"
num_parts = (samples.shape[0] // num_samples) + 1
for i in range(num_parts):
start_idx = i * num_samples
end_idx = start_idx + num_samples - 1
samples_part = samples.iloc[start_idx:end_idx]
samples_part_ee = geemap.geopandas_to_ee(samples_part)
geemap.extract_values_to_points(
samples_part_ee, stack, scale=10, out_fc=f"{out_fc_base}_{i}.csv"
)
get_sampled_size(samples, stack, n_samples)
¶
Get the size of the sampled regions from a stack based on a subset of samples.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
samples |
pd.DataFrame |
A pandas DataFrame containing the sample points. |
required |
stack |
ee.Image or ee.ImageCollection |
An Earth Engine Image or ImageCollection to sample from. |
required |
n_samples |
int |
The number of samples to take from the samples DataFrame. |
required |
Returns:
Type | Description |
---|---|
int |
The size of the sampled regions. |
Source code in gishndev/gee_s2_funcs.py
def get_sampled_size(samples, stack, n_samples):
"""
Get the size of the sampled regions from a stack based on a subset of samples.
Args:
samples (pd.DataFrame): A pandas DataFrame containing the sample points.
stack (ee.Image or ee.ImageCollection): An Earth Engine Image or ImageCollection to sample from.
n_samples (int): The number of samples to take from the samples DataFrame.
Returns:
int: The size of the sampled regions.
"""
subset = samples.iloc[0:n_samples]
subset_ee = geemap.geopandas_to_ee(subset)
sampled = stack.sampleRegions(collection=subset_ee, scale=10, geometries=True)
return sampled.size().getInfo()
index_info(index, properties=None)
¶
Retrieve and print information about specified spectral indices.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
index |
str or list of str |
A single index or a list of indices to retrieve information for. |
required |
properties |
list of str |
A list of properties to retrieve for each index. Default is ["formula"]. Possible properties include 'application_domain', 'bands', 'contributor', 'date_of_addition', 'formula', 'long_name', 'platforms', 'reference', 'short_name'. |
None |
Source code in gishndev/gee_s2_funcs.py
def index_info(index, properties=None):
"""
Retrieve and print information about specified spectral indices.
Args:
index (str or list of str): A single index or a list of indices to retrieve information for.
properties (list of str, optional): A list of properties to retrieve for each index. Default is ["formula"].
Possible properties include 'application_domain', 'bands', 'contributor',
'date_of_addition', 'formula', 'long_name', 'platforms',
'reference', 'short_name'.
"""
if properties is None:
properties = ["formula"]
if not isinstance(index, list):
index = [index]
if not isinstance(properties, list):
properties = [properties]
for idx in index:
properties_dic = {}
for prop in properties:
properties_dic[prop] = spectral_indices[idx][prop]
print(f"'{idx}' info:")
print(properties_dic)
mask_s2_clouds(img)
¶
Masks clouds and cloud shadows in Sentinel-2 images using the SCL band, QA60 band, and cloud probability.
This function applies a series of masks to a Sentinel-2 image to remove pixels that are likely to be affected by clouds, cloud shadows, cirrus, or snow. It uses the Scene Classification Layer (SCL) band, the QA60 band, and optionally the cloud probability band from the COPERNICUS/S2_CLOUD_PROBABILITY collection.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
img |
ee.Image |
The Sentinel-2 image to be masked. |
required |
Returns:
Type | Description |
---|---|
ee.Image |
The masked Sentinel-2 image with values scaled between 0 and 1. |
Source code in gishndev/gee_s2_funcs.py
def mask_s2_clouds(img):
"""
Masks clouds and cloud shadows in Sentinel-2 images using the SCL band, QA60 band, and cloud probability.
This function applies a series of masks to a Sentinel-2 image to remove pixels that are likely to be affected by clouds, cloud shadows, cirrus, or snow. It uses the Scene Classification Layer (SCL) band, the QA60 band, and optionally the cloud probability band from the COPERNICUS/S2_CLOUD_PROBABILITY collection.
Args:
img (ee.Image): The Sentinel-2 image to be masked.
Returns:
ee.Image: The masked Sentinel-2 image with values scaled between 0 and 1.
"""
# Load the cloud probability image collection
cloud_prob_collection = (
ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY")
.filterBounds(img.geometry())
.filterDate(img.date(), img.date().advance(1, "day"))
)
# Get the first cloud probability image if available
cloud_prob_img = ee.Algorithms.If(
cloud_prob_collection.size().gt(0),
cloud_prob_collection.first(), # Use cloud probability image if it exists
None, # Otherwise, return None to skip cloud probability masking
)
# Use the SCL band for scene classification
scl = img.select("SCL")
# Create masks based on the SCL band
scl_mask = (
scl.neq(3)
.And(scl.neq(8)) # 3 = Cloud shadow
.And(scl.neq(9)) # 8 = Clouds
.And(scl.neq(10)) # 9 = Cirrus
) # 10 = Snow
# QA60 mask for clouds and cirrus
qa = img.select("QA60")
cloud_bit_mask = ee.Number(1024) # 2^10 = 1024, 10th bit is clouds
cirrus_bit_mask = ee.Number(2048) # 2^11 = 2048, 11th bit is cirrus clouds
mask_qa60 = (
qa.bitwiseAnd(cloud_bit_mask).eq(0).And(qa.bitwiseAnd(cirrus_bit_mask).eq(0))
)
# Use cloud probability threshold (e.g., clouds if probability > 20%)
cloud_prob_mask = ee.Image(cloud_prob_img).select("probability").lt(20)
# Combine the SCL mask, QA60 mask, and cloud probability mask (if available)
combined_mask = ee.Algorithms.If(
cloud_prob_img, # If cloud_prob_image is not None
scl_mask.And(mask_qa60).And(cloud_prob_mask), # Combine all masks
scl_mask.And(
mask_qa60
), # Use only SCL and QA60 mask if cloud probability image is unavailable
)
# Return the masked image, scaled by 10,000 to get values between 0-1
return img.updateMask(combined_mask)
params_index_s2(index, img)
¶
Processes spectral indices and returns a dictionary of parameters with their corresponding values or bands.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
index |
list or str |
A list of spectral index names or a single spectral index name. |
required |
img |
ee.Image |
An image object from which bands are selected. |
required |
Returns:
Type | Description |
---|---|
dict |
A dictionary where keys are parameter names and values are either constants or selected bands from the image. |
Source code in gishndev/gee_s2_funcs.py
def params_index_s2(index, img):
"""
Processes spectral indices and returns a dictionary of parameters with their corresponding values or bands.
Args:
index (list or str): A list of spectral index names or a single spectral index name.
img (ee.Image): An image object from which bands are selected.
Returns:
dict: A dictionary where keys are parameter names and values are either constants or selected bands from the image.
"""
# Convertir a lista sino lo es``
if not isinstance(index, list):
index = [index]
# Obtener los parámetros de los índices
unique_params = []
for idx in index:
idx_params = spectral_indices[idx]["bands"]
total_params = unique_params + idx_params
unique_params = list(set(total_params))
## Crear las constantes
param_constants = [
param for param in unique_params if param in spectral_constants.keys()
]
constants_values = {}
for constant in param_constants:
value = spectral_constants[constant]["default"]
constants_values[constant] = value
## Asignar la banda de sentinel a cada params_bands
param_bands = [
param for param in unique_params if param not in spectral_constants.keys()
]
s2_param_bands = {}
for band in param_bands:
s2_band = spectral_bands[band]["platforms"]["sentinel2a"]["band"]
s2_param_bands[band] = s2_band
## Crear los parámetros
params = {}
for param in unique_params:
if param in constants_values.keys():
value = constants_values[param]
params[param] = value
elif param in s2_param_bands.keys():
band_name = s2_param_bands[param]
params[param] = img.select(band_name)
return params
tif_to_gdf(tif)
¶
Converts a TIFF raster file to a GeoDataFrame.
This function reads a TIFF file, processes its raster data, and converts it into a GeoDataFrame. The raster data is converted to float32 if it is not in a compatible data type. Only the pixels with values greater than 0 are considered for conversion to geometries.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tif |
str |
The file path to the TIFF raster file. |
required |
Returns:
Type | Description |
---|---|
gpd.GeoDataFrame |
A GeoDataFrame containing the geometries and their associated values extracted from the raster. |
Exceptions:
Type | Description |
---|---|
Exception |
If there is an error in reading the TIFF file or converting it to a GeoDataFrame. |
Source code in gishndev/gee_s2_funcs.py
def tif_to_gdf(tif):
"""
Converts a TIFF raster file to a GeoDataFrame.
This function reads a TIFF file, processes its raster data, and converts it into a GeoDataFrame.
The raster data is converted to float32 if it is not in a compatible data type. Only the pixels
with values greater than 0 are considered for conversion to geometries.
Args:
tif (str): The file path to the TIFF raster file.
Returns:
gpd.GeoDataFrame: A GeoDataFrame containing the geometries and their associated values extracted from the raster.
Raises:
Exception: If there is an error in reading the TIFF file or converting it to a GeoDataFrame.
"""
# Crear el nombre del archivo tif
try:
with rasterio.open(tif) as src:
image = src.read(1)
# Convertir el tipo de datos del raster a float32 si no es compatible
if image.dtype not in ["int16", "int32", "uint8", "uint16", "float32"]:
image = image.astype("float32")
mask = image > 0
results = (
{"properties": {"value": v}, "geometry": s}
for s, v in shapes(image, mask=mask, transform=src.transform)
)
geoms = list(results)
gdf = gpd.GeoDataFrame.from_features(geoms, crs=src.crs)
return gdf
except Exception as e:
print(f"Error al convertir el raster a GeoDataFrame: {e}")
raise