Export and cloud mask Google Earth Engine imagery with automated composite creation and filtering capabilities.
—
Create temporal composites from image collections using various algorithms including median, medoid, q-mosaic, and statistical methods. Geedim provides sophisticated compositing capabilities that leverage cloud masking for optimal pixel selection.
Enumeration of available compositing algorithms.
class CompositeMethod(Enum):
"""Enumeration for compositing methods."""
q_mosaic = 'q-mosaic'
"""
Use the unmasked pixel with the highest cloud distance (distance to nearest
cloud). When more than one pixel has the same cloud distance, the first one
is used.
"""
mosaic = 'mosaic'
"""Use the first unmasked pixel."""
medoid = 'medoid'
"""
Medoid of the unmasked pixels - the pixel from the image with the minimum
sum of spectral distances to the rest of the images. Where more than one
pixel has the same summed distance, the first one is used.
"""
median = 'median'
"""Median of the unmasked pixels."""
mode = 'mode'
"""Mode of the unmasked pixels."""
mean = 'mean'
"""Mean of the unmasked pixels."""Metrics used for medoid compositing calculations.
class SpectralDistanceMetric(Enum):
"""Enumeration for spectral distance metrics."""
sam = 'sam'
"""Spectral angle mapper."""
sid = 'sid'
"""Spectral information divergence."""
sed = 'sed'
"""Squared euclidean distance."""
emd = 'emd'
"""Earth movers distance."""Create temporal composites from image collections with advanced parameter control.
def composite(
self,
method: CompositeMethod = CompositeMethod.median,
region: dict | ee.Geometry = None,
scale: float = None,
bands: list[str] = None,
date_range: tuple[str, str] = None,
cloud_filter: float = None,
**kwargs
) -> ee.Image:
"""
Create a temporal composite from the image collection.
Parameters:
- method (CompositeMethod): Compositing algorithm to use
- region (dict | ee.Geometry, optional): Composite region bounds
- scale (float, optional): Composite scale in meters
- bands (list[str], optional): Bands to include in composite
- date_range (tuple, optional): Date range as (start_date, end_date)
- cloud_filter (float, optional): Maximum cloud percentage (0-100)
- **kwargs: Additional compositing parameters
Returns:
ee.Image: Composite image with metadata properties
"""Specialized medoid compositing with configurable distance metrics.
def medoid_composite(
collection: ee.ImageCollection,
bands: list[str] = None,
metric: SpectralDistanceMetric = SpectralDistanceMetric.sed,
region: dict | ee.Geometry = None,
scale: float = None
) -> ee.Image:
"""
Create medoid composite using spectral distance calculations.
Parameters:
- collection (ee.ImageCollection): Input image collection
- bands (list[str], optional): Bands to use for distance calculations
- metric (SpectralDistanceMetric): Distance metric algorithm
- region (dict | ee.Geometry, optional): Analysis region
- scale (float, optional): Analysis scale in meters
Returns:
ee.Image: Medoid composite image
"""Create quality-based mosaics using cloud distance information.
def quality_mosaic(
collection: ee.ImageCollection,
region: dict | ee.Geometry = None,
scale: float = None,
max_cloud_dist: float = 5000
) -> ee.Image:
"""
Create quality mosaic based on cloud distance.
Parameters:
- collection (ee.ImageCollection): Input image collection
- region (dict | ee.Geometry, optional): Mosaic region
- scale (float, optional): Mosaic scale in meters
- max_cloud_dist (float): Maximum cloud distance in meters
Returns:
ee.Image: Quality mosaic image
"""import ee
import geedim
geedim.Initialize()
# Load image collection
collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
.filterDate('2020-06-01', '2020-09-30') \
.filterBounds(ee.Geometry.Point(-122.4194, 37.7749).buffer(50000))
# Add cloud masking to collection
masked_collection = collection.gd.addMaskBands(
mask_cirrus=True,
mask_shadows=True
).maskClouds()
# Define region of interest
region = ee.Geometry.Rectangle([-122.5, 37.7, -122.3, 37.8])
# Create median composite
median_composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=30
)
print("Median composite created")# Quality mosaic - selects best pixels based on cloud distance
quality_composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.q_mosaic,
region=region,
scale=30,
bands=['B2', 'B3', 'B4', 'B5', 'B6', 'B7'] # Specific bands
)
# Medoid composite - spectrally representative pixels
medoid_composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.medoid,
region=region,
scale=30,
bands=['B4', 'B5'], # Use NIR and Red for medoid calculation
metric=geedim.SpectralDistanceMetric.sam # Spectral angle mapper
)
# Statistical composites
mean_composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.mean,
region=region,
scale=30
)
mode_composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.mode,
region=region,
scale=30
)# Create seasonal composites
seasons = {
'spring': ('2020-03-01', '2020-05-31'),
'summer': ('2020-06-01', '2020-08-31'),
'fall': ('2020-09-01', '2020-11-30'),
'winter': ('2020-12-01', '2021-02-28')
}
seasonal_composites = {}
for season, (start_date, end_date) in seasons.items():
# Filter collection by season
seasonal_collection = collection \
.filterDate(start_date, end_date) \
.gd.addMaskBands().maskClouds()
# Create composite for season
composite = seasonal_collection.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=30,
cloud_filter=50 # Max 50% cloud cover
)
seasonal_composites[season] = composite
print(f"{season.capitalize()} composite created")
# Export seasonal composites
for season, composite in seasonal_composites.items():
task = composite.gd.export(
description=f'landsat_{season}_composite',
folder='seasonal_composites',
region=region,
scale=30
)
task.start()# Combine Landsat 8 and 9 collections
l8_collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
.filterDate('2020-01-01', '2020-12-31') \
.filterBounds(region)
l9_collection = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2') \
.filterDate('2020-01-01', '2020-12-31') \
.filterBounds(region)
# Merge collections (spectrally compatible)
combined_collection = l8_collection.merge(l9_collection)
# Add cloud masking
masked_combined = combined_collection.gd.addMaskBands(
mask_cirrus=True,
mask_shadows=True
).maskClouds()
# Create multi-sensor composite
multi_sensor_composite = masked_combined.gd.composite(
method=geedim.CompositeMethod.q_mosaic,
region=region,
scale=30
)# Create composite with metadata analysis
composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=30
)
# Get composite metadata
composite_info = composite.getInfo()
print(f"Composite bands: {[band['id'] for band in composite_info['bands']]}")
# Get image count used in composite
image_count = composite.get('COMPOSITE_COUNT').getInfo()
print(f"Images used in composite: {image_count}")
# Get date range of source images
date_range = composite.get('DATE_RANGE').getInfo()
print(f"Date range: {date_range}")
# Analyze composite quality
quality_bands = ['FILL_MASK', 'CLOUDLESS_MASK']
if any(band in [b['id'] for b in composite_info['bands']] for band in quality_bands):
# Calculate quality statistics
quality_stats = composite.select(quality_bands).gd.regionCoverage(
region=region,
scale=120 # Lower resolution for faster analysis
)
print(f"Composite quality: {quality_stats}")def create_best_pixel_composite(collection, region, scale=30):
"""Create composite using best available pixels."""
# Add mask bands to collection
masked_collection = collection.gd.addMaskBands().maskClouds()
# Filter for high-quality images
high_quality = masked_collection.gd.search(
cloudless_portion=80,
fill_portion=95
)
# Create quality mosaic if enough high-quality images
image_count = high_quality.size().getInfo()
if image_count >= 5:
# Use quality mosaic for best pixels
composite = high_quality.gd.composite(
method=geedim.CompositeMethod.q_mosaic,
region=region,
scale=scale
)
elif image_count >= 2:
# Use median for fewer images
composite = high_quality.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=scale
)
else:
# Use simple mosaic as fallback
composite = masked_collection.gd.composite(
method=geedim.CompositeMethod.mosaic,
region=region,
scale=scale
)
return composite.set('IMAGES_USED', image_count)
# Apply custom compositing
custom_composite = create_best_pixel_composite(collection, region)
images_used = custom_composite.get('IMAGES_USED').getInfo()
print(f"Custom composite used {images_used} images")# Create monthly composites for a year
import calendar
monthly_composites = {}
for month in range(1, 13):
# Get month date range
start_date = f'2020-{month:02d}-01'
if month == 12:
end_date = '2020-12-31'
else:
end_date = f'2020-{month+1:02d}-01'
# Filter collection by month
monthly_collection = collection \
.filterDate(start_date, end_date) \
.gd.addMaskBands().maskClouds()
# Create monthly composite
monthly_composite = monthly_collection.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=30
)
month_name = calendar.month_name[month].lower()
monthly_composites[month_name] = monthly_composite
print(f"{month_name.capitalize()} composite created")
# Create annual composite from monthly composites
annual_collection = ee.ImageCollection.fromImages(
list(monthly_composites.values())
)
annual_composite = annual_collection.gd.composite(
method=geedim.CompositeMethod.median,
region=region,
scale=30
)Install with Tessl CLI
npx tessl i tessl/pypi-geedim