Skip to content

gee module

Google Earth Engine utilities.

addNDVI_ee(image)

Add an NDVI band to a Sentinel-2 Earth Engine image.

Source code in pysatgeo/gee.py
def addNDVI_ee(image):
    """Add an NDVI band to a Sentinel-2 Earth Engine image."""
    ndvi = image.normalizedDifference(["B8", "B4"]).rename("ndvi")
    return image.addBands(ndvi)

apply_cloud_masks_ee(image)

Mask common cloudy Sentinel-2 scene classes using the SCL band.

Source code in pysatgeo/gee.py
def apply_cloud_masks_ee(image):
    """Mask common cloudy Sentinel-2 scene classes using the SCL band."""
    cloud_shadow = image.select("SCL").eq(3)
    cloud_low = image.select("SCL").eq(7)
    cloud_med = image.select("SCL").eq(8)
    cloud_high = image.select("SCL").eq(9)
    cloud_cirrus = image.select("SCL").eq(10)
    cloud_mask = (
        cloud_shadow.add(cloud_low)
        .add(cloud_med)
        .add(cloud_high)
        .add(cloud_cirrus)
    )
    return image.updateMask(cloud_mask.eq(0))

apply_scale_factor_ee(image)

Apply the common Sentinel reflectance scale factor.

Source code in pysatgeo/gee.py
def apply_scale_factor_ee(image):
    """Apply the common Sentinel reflectance scale factor."""
    return image.multiply(0.0001)

export_tiled_mosaic(image, aoi, out_file, scale=500, crs='EPSG:4326', n=2, tmp_dir='tiles_tmp', max_attempts=5)

Export an Earth Engine image in tiles and merge them into one raster.

Source code in pysatgeo/gee.py
def export_tiled_mosaic(
    image,
    aoi,
    out_file,
    scale=500,
    crs="EPSG:4326",
    n=2,
    tmp_dir="tiles_tmp",
    max_attempts=5,
):
    """Export an Earth Engine image in tiles and merge them into one raster."""
    import os

    import ee
    import geemap
    import rasterio
    from rasterio.merge import merge

    attempt = 0
    success = False

    while attempt < max_attempts and not success:
        try:
            os.makedirs(tmp_dir, exist_ok=True)

            bounds = aoi.bounds().coordinates().getInfo()[0]
            x_min, y_min = bounds[0]
            x_max, y_max = bounds[2]
            width = x_max - x_min
            height = y_max - y_min
            tile_width = width / n
            tile_height = height / n

            tile_files = []
            total_tiles = n * n

            for i in range(n):
                for j in range(n):
                    x1 = x_min + i * tile_width
                    y1 = y_min + j * tile_height
                    x2 = x1 + tile_width
                    y2 = y1 + tile_height
                    tile_geom = ee.Geometry.Rectangle([x1, y1, x2, y2])

                    tile_out = os.path.join(tmp_dir, f"tile_{i}_{j}.tif")
                    tile_number = i * n + j + 1
                    print(
                        f"Exporting tile {tile_number} of {total_tiles} "
                        f"(n={n}) -> {tile_out}"
                    )

                    geemap.ee_export_image(
                        image,
                        filename=tile_out,
                        scale=scale,
                        region=tile_geom,
                        crs=crs,
                        file_per_band=False,
                    )

                    with rasterio.open(tile_out, "r+") as dst:
                        dst.nodata = 0

                    tile_files.append(tile_out)

            print("Merging tiles into final mosaic...")
            src_files = [rasterio.open(path) for path in tile_files]
            mosaic, out_transform = merge(src_files, nodata=0)

            out_meta = src_files[0].meta.copy()
            out_meta.update(
                {
                    "driver": "GTiff",
                    "height": mosaic.shape[1],
                    "width": mosaic.shape[2],
                    "transform": out_transform,
                    "nodata": 0,
                }
            )

            with rasterio.open(out_file, "w", **out_meta) as dest:
                dest.write(mosaic)

            for src in src_files:
                src.close()

            print(f"Mosaic saved at: {out_file}")
            success = True

        except Exception as exc:
            attempt += 1
            print(f"Export failed at n={n} (attempt {attempt}/{max_attempts})")
            print(f"Error: {exc}")
            n += 1
            print(f"Retrying with n={n}...\n")

    if not success:
        raise RuntimeError("Export failed after maximum attempts.")

split_region(geometry, n)

Split an Earth Engine geometry into an n x n grid of rectangles.

Source code in pysatgeo/gee.py
def split_region(geometry, n):
    """Split an Earth Engine geometry into an `n x n` grid of rectangles."""
    import ee

    tiles = []
    bounds = geometry.bounds().getInfo()["coordinates"][0]
    x_min, y_min = bounds[0]
    x_max, y_max = bounds[2]
    width = x_max - x_min
    height = y_max - y_min
    tile_width = width / n
    tile_height = height / n

    for i in range(n):
        for j in range(n):
            x1 = x_min + i * tile_width
            y1 = y_min + j * tile_height
            x2 = x1 + tile_width
            y2 = y1 + tile_height
            tiles.append(ee.Geometry.Rectangle([x1, y1, x2, y2]))

    return tiles