API
Getting started
This section gives a quick overview of the API. You can also take a look at the tutorials.
Initialisation
Initialize()
provides a shortcut for initialising the Earth Engine API.
import geedim as gd
gd.Initialize()
Searching image collections
Any Earth Engine image collection can be searched with MaskedCollection
. Here, we search for Landsat-8 surface reflectance images over Stellenbosch, South Africa.
# geojson search polygon
region = {
'type': 'Polygon',
'coordinates': [[(19, -34), (19, -33.8), (18.8, -33.8), (18.8, -34), (19.0, -34)]],
}
# create & search a landsat-8 collection, reporting cloudless portions
coll = gd.MaskedCollection.from_name('LANDSAT/LC08/C02/T1_L2')
filt_coll = coll.search('2019-01-01', '2019-02-15', region, cloudless_portion=0)
# display the search results
print(filt_coll.schema_table)
print(filt_coll.properties_table)
The output:
ABBREV DESCRIPTION
--------- ---------------------------------------
ID Earth Engine image id
DATE Image capture date/time (UTC)
FILL Portion of region pixels that are valid (%)
CLOUDLESS Portion of filled pixels that are cloud/shadow free (%)
GRMSE Orthorectification RMSE (m)
SAA Solar azimuth angle (deg)
SEA Solar elevation angle (deg)
ID DATE FILL CLOUDLESS GRMSE SAA SEA
------------------------------------------- ---------------- ----- --------- ----- ----- -----
LANDSAT/LC08/C02/T1_L2/LC08_175083_20190101 2019-01-01 08:35 99.83 55.62 8.48 79.36 59.20
LANDSAT/LC08/C02/T1_L2/LC08_175084_20190101 2019-01-01 08:35 99.79 60.35 9.71 77.28 58.67
LANDSAT/LC08/C02/T1_L2/LC08_175083_20190117 2019-01-17 08:35 99.98 94.90 8.84 76.98 56.79
LANDSAT/LC08/C02/T1_L2/LC08_175084_20190117 2019-01-17 08:35 99.97 95.07 9.75 75.13 56.21
LANDSAT/LC08/C02/T1_L2/LC08_175083_20190202 2019-02-02 08:34 99.91 95.82 8.46 71.91 54.00
LANDSAT/LC08/C02/T1_L2/LC08_175084_20190202 2019-02-02 08:35 99.87 95.21 9.21 70.34 53.30
Image creation and download
Images can be created, masked and downloaded with the MaskedImage
class. Typically, one would pass the Earth Engine image ID to MaskedImage.from_id()
to create the image.
# create a landsat-8 image from its ID
im = gd.MaskedImage.from_id('LANDSAT/LC08/C02/T1_L2/LC08_175083_20190117', mask=False)
# download a region of the image with 'average' resampling to 60m pixels, and
# data type conversion to 16 bit unsigned int
im.download('landsat_8_image.tif', region=region, resampling='average', scale=60, dtype='uint16')
Compositing
Let’s form a cloud/shadow-free composite of the search result images, using the q-mosaic method, then download the result. By specifying the region
parameter to MaskedCollection.composite()
, we prioritise selection of pixels from the least cloudy images when forming the composite.
Note
When downloading composite images, the region
, crs
and scale
parameters must be specified, as the image has no fixed (known) projection.
# find a 'q-mosaic' composite image of the search result images, prioritising
# the least cloudy image by specifying `region`
comp_im = filt_coll.composite(method='q-mosaic', region=region)
# download the composite, specifying crs, region, and scale
comp_im.download('landsat_8_comp_image.tif', region=region, crs='EPSG:32634', scale=30)
Cloud/shadow masking
All MaskedImage
and MaskedCollection
methods that involve cloud/shadow
masking (MaskedImage.from_id()
, MaskedCollection.search()
, and MaskedCollection.composite()
)
take optional cloud/shadow masking **kwargs
. See MaskedImage.__init__()
for a description of these
parameters.
Here, we create and download a cloud/shadow masked Sentinel-2 image, specifying a cloud score threshold of 0.7.
# create a cloud/shadow masked Sentinel-2 image, specifying a cloud
# score threshold of 0.7
im = gd.MaskedImage.from_id(
'COPERNICUS/S2_SR_HARMONIZED/20190101T082331_20190101T084846_T34HCH', mask=True, score=0.7
)
# download a region of the masked image, downsampling to 20m pixels
im.download('s2_sr_hm_image.tif', region=region, scale=20, resampling='average')
Image metadata
geedim
populates downloaded files with metadata from the source Earth Engine image, and the associated STAC entry.
The next code snippet uses rasterio to read the metadata of the downloaded
Sentinel-2 image.
import rasterio as rio
with rio.open('s2_sr_image.tif', 'r') as ds:
print('Image properties:\n', ds.tags())
print('Band names:\n', ds.descriptions)
print('Band 1 properties:\n', ds.tags(1))
Output:
Image properties:
{'AOT_RETRIEVAL_ACCURACY': '0', 'AREA_OR_POINT': 'Area', 'CLOUDY_PIXEL_PERCENTAGE': '4.228252', 'CLOUD_COVERAGE_ASSESSMENT': '4.228252', 'CLOUD_SHADOW_PERCENTAGE': '0.353758', 'DARK_FEATURES_PERCENTAGE': '1.390344', 'DATASTRIP_ID': 'S2A_OPER_MSI_L2A_DS_MTI__20190101T112242_S20190101T084846_N02.11', 'DATATAKE_IDENTIFIER': 'GS2A_20190101T082331_018422_N02.11', 'DATATAKE_TYPE': 'INS-NOBS', 'DEGRADED_MSI_DATA_PERCENTAGE': '0', 'FORMAT_CORRECTNESS': 'PASSED', 'GENERAL_QUALITY': 'PASSED', 'GENERATION_TIME': '1546341762000', 'GEOMETRIC_QUALITY': 'PASSED', 'GRANULE_ID': 'L2A_T34HCH_A018422_20190101T084846', 'HIGH_PROBA_CLOUDS_PERCENTAGE': '1.860266', 'LICENSE': 'https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR#terms-of-use', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B1': '197.927117994', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B10': '200.473257333', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B11': '199.510962726', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B12': '198.925728126', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B2': '204.233801024', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B3': '201.623624653', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B4': '200.124411228', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B5': '199.531415295', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B6': '199.06932777', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B7': '198.686746475', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B8': '202.762429499', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B8A': '198.389627535', 'MEAN_INCIDENCE_AZIMUTH_ANGLE_B9': '197.722038042', 'MEAN_INCIDENCE_ZENITH_ANGLE_B1': '3.18832352559', 'MEAN_INCIDENCE_ZENITH_ANGLE_B10': '2.74480253282', 'MEAN_INCIDENCE_ZENITH_ANGLE_B11': '2.9240632909', 'MEAN_INCIDENCE_ZENITH_ANGLE_B12': '3.12457836272', 'MEAN_INCIDENCE_ZENITH_ANGLE_B2': '2.56258512587', 'MEAN_INCIDENCE_ZENITH_ANGLE_B3': '2.66821142821', 'MEAN_INCIDENCE_ZENITH_ANGLE_B4': '2.78791939543', 'MEAN_INCIDENCE_ZENITH_ANGLE_B5': '2.86049380258', 'MEAN_INCIDENCE_ZENITH_ANGLE_B6': '2.93757718579', 'MEAN_INCIDENCE_ZENITH_ANGLE_B7': '3.01912758709', 'MEAN_INCIDENCE_ZENITH_ANGLE_B8': '2.61179829178', 'MEAN_INCIDENCE_ZENITH_ANGLE_B8A': '3.10418395274', 'MEAN_INCIDENCE_ZENITH_ANGLE_B9': '3.28253454154', 'MEAN_SOLAR_AZIMUTH_ANGLE': '74.331216318', 'MEAN_SOLAR_ZENITH_ANGLE': '27.589988524', 'MEDIUM_PROBA_CLOUDS_PERCENTAGE': '0.774948', 'MGRS_TILE': '34HCH', 'NODATA_PIXEL_PERCENTAGE': '2.7e-05', 'NOT_VEGETATED_PERCENTAGE': '72.305781', 'PROCESSING_BASELINE': '02.11', 'PRODUCT_ID': 'S2A_MSIL2A_20190101T082331_N0211_R121_T34HCH_20190101T112242', 'RADIATIVE_TRANSFER_ACCURACY': '0', 'RADIOMETRIC_QUALITY': 'PASSED', 'REFLECTANCE_CONVERSION_CORRECTION': '1.03413456106', 'SATURATED_DEFECTIVE_PIXEL_PERCENTAGE': '0', 'SENSING_ORBIT_DIRECTION': 'DESCENDING', 'SENSING_ORBIT_NUMBER': '121', 'SENSOR_QUALITY': 'PASSED', 'SNOW_ICE_PERCENTAGE': '0.0156', 'SOLAR_IRRADIANCE_B1': '1884.69', 'SOLAR_IRRADIANCE_B10': '367.15', 'SOLAR_IRRADIANCE_B11': '245.59', 'SOLAR_IRRADIANCE_B12': '85.25', 'SOLAR_IRRADIANCE_B2': '1959.72', 'SOLAR_IRRADIANCE_B3': '1823.24', 'SOLAR_IRRADIANCE_B4': '1512.06', 'SOLAR_IRRADIANCE_B5': '1424.64', 'SOLAR_IRRADIANCE_B6': '1287.61', 'SOLAR_IRRADIANCE_B7': '1162.08', 'SOLAR_IRRADIANCE_B8': '1041.63', 'SOLAR_IRRADIANCE_B8A': '955.32', 'SOLAR_IRRADIANCE_B9': '812.92', 'SPACECRAFT_NAME': 'Sentinel-2A', 'system-asset_size': '1820790758', 'system-index': '20190101T082331_20190101T084846_T34HCH', 'system-time_end': '1546332584000', 'system-time_start': '1546332584000', 'THIN_CIRRUS_PERCENTAGE': '1.593038', 'UNCLASSIFIED_PERCENTAGE': '1.202621', 'VEGETATION_PERCENTAGE': '18.241563', 'WATER_PERCENTAGE': '2.262083', 'WATER_VAPOUR_RETRIEVAL_ACCURACY': '0'}
Band names:
('B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'B9', 'B11', 'B12', 'AOT', 'WVP', 'SCL', 'TCI_R', 'TCI_G', 'TCI_B', 'MSK_CLDPRB', 'MSK_SNWPRB', 'QA10', 'QA20', 'QA60', 'FILL_MASK', 'CLOUD_MASK', 'CLOUDLESS_MASK', 'SHADOW_MASK', 'CLOUD_PROB', 'CLOUD_DIST')
Band 1 properties:
{'center_wavelength': '0.4439', 'description': 'Aerosols', 'gsd': '60', 'name': 'B1', 'scale': '0.0001', 'wavelength': '443.9nm (S2A) / 442.3nm (S2B)'}
Computed images and user memory
Earth engine has a size limit of 32 MB on download requests. geedim
avoids exceeding this by tiling downloads. However, Earth engine also has a limit on user memory for image computations. This limit can be exceeded when downloading large computed images (such as custom user images or geedim
generated composites), raising a user memory limit exceeded error. Unfortunately, there is no way for geedim
to adjust tiles to avoid exceeding this limit, as the memory requirements of a computation are not known in advance. The user has two options for working around this error:
1) max_tile_size
Decreasing the max_tile_size
argument to geedim.mask.MaskedImage.download()
reduces the user memory required by computations. The user would need to experiment to find a reduced value that solves any memory limit problem. --max-tile-size
is the equivalent option on the command line.
import ee
# create a computed ee.Image
ee_im = ee.Image('COPERNICUS/S2_SR_HARMONIZED/20190101T082331_20190101T084846_T34HCH')
comp_im = ee_im.select('B3').entropy(ee.Kernel.square(5))
# encapsulate in MaskedImage, and download with max_tile_size=8
im = gd.MaskedImage(comp_im)
im.download('s2_entropy.tif', region=region, max_tile_size=8)
2) Exporting
Exporting the image to an Earth Engine asset, and then downloading. Exporting images is not subject to the user memory limit, and once exported, computation on the asset image is complete. The exported asset image can then be downloaded in the standard way.
# create EE asset ID & export computed image to asset
asset_id = f'projects/<your cloud project>/assets/s2_entropy'
_ = im.export(asset_id, type='asset', region=region, wait=True)
# create and download the asset image
im = gd.MaskedImage.from_id(asset_id)
im.download('s2_entropy.tif')
Reference
MaskedImage
- class geedim.mask.MaskedImage
- __init__(ee_image: Image, mask: bool = False, region: dict | Geometry = None, **kwargs)
A class for describing, masking and downloading an Earth Engine image.
- Parameters:
ee_image (ee.Image) – Earth Engine image to encapsulate.
mask (bool, optional) – Whether to mask the image.
region (dict, ee.Geometry, optional) – Region in which to find statistics for the image, as a GeoJSON dictionary or
ee.Geometry
. Statistics are stored in the image properties. If None, statistics are not found (the default).**kwargs – Cloud/shadow masking parameters - see below:
mask_cirrus (bool, optional) – Whether to mask cirrus clouds. Valid for Landsat 8-9 images, and for Sentinel-2 images with the qa
mask_method
.mask_shadows (bool, optional) – Whether to mask cloud shadows. Valid for Landsat images, and for Sentinel-2 images with the qa or cloud-prob
mask_method
.mask_method (CloudMaskMethod, str, optional) – Method used to mask clouds. Valid for Sentinel-2 images. See
CloudMaskMethod
for details.prob (float, optional) – Cloud probability threshold (%). Valid for Sentinel-2 images with the cloud-prob
mask_method
.dark (float, optional) – NIR threshold [0-1]. NIR values below this threshold are potential cloud shadows. Valid for Sentinel-2 images with the qa or cloud-prob
mask_method
.shadow_dist (int, optional) – Maximum distance (m) to look for cloud shadows from cloud edges. Valid for Sentinel-2 images with the qa or cloud-prob
mask_method
.buffer (int, optional) – Distance (m) to dilate cloud/shadow. Valid for Sentinel-2 images with the qa or cloud-prob
mask_method
.cdi_thresh (float, optional) – Cloud Displacement Index threshold. Values below this threshold are considered potential clouds. If this parameter is not specified (=None), the index is not used. Valid for Sentinel-2 images with the qa or cloud-prob
mask_method
. See https://developers.google.com/earth-engine/apidocs/ee-algorithms-sentinel2-cdi for details.max_cloud_dist (int, optional) – Maximum distance (m) to look for clouds when forming the ‘cloud distance’ band. Valid for Sentinel-2 images.
score (float, optional) – Cloud Score+ threshold. Valid for Sentinel-2 images with the cloud-score
mask_method
.cs_band (CloudScoreBand, str, optional) – Cloud Score+ band to threshold. Valid for Sentinel-2 images with the cloud-score
mask_method
.
- __new__(**kwargs)
Methods
|
Create a MaskedImage, or sub-class, instance from an Earth Engine image ID. |
Apply the cloud/shadow mask if supported, otherwise apply the fill mask. |
|
|
Download the encapsulated image to a GeoTiff file. |
|
Export the encapsulated image to Google Drive, Earth Engine asset or Google Cloud Storage. |
|
Monitor and display the progress of an export task. |
Attributes
Encapsulated Earth Engine image. |
|
Earth Engine image ID. |
|
Image capture date & time. |
|
CRS of the minimum scale band. |
|
Minimum scale of the image bands (meters). |
|
GeoJSON polygon of the image extent. |
|
Geo-transform of the minimum scale band. |
|
(row, column) pixel dimensions of the minimum scale band. |
|
Number of image bands. |
|
Minimum size data type able to represent the image values. |
|
Image size (bytes). |
|
True if the image has a fixed projection, otherwise False. |
|
Image name (the |
|
Earth Engine image properties. |
|
Merged STAC and Earth Engine band properties. |
MaskedCollection
- class geedim.collection.MaskedCollection
- __init__(ee_collection: ImageCollection, add_props: List[str] = None)
A class for describing, searching and compositing an Earth Engine image collection, with support for cloud/shadow masking.
- Parameters:
ee_collection (ee.ImageCollection) – Earth Engine image collection to encapsulate.
add_props (list of str, optional) – Additional Earth Engine image properties to include in
properties
.
- __new__(**kwargs)
Methods
|
Create a MaskedCollection instance from an Earth Engine image collection name. |
|
Create a MaskedCollection instance from a list of Earth Engine image ID strings, |
|
Search for images based on date, region, filled/cloudless portion, and custom criteria. |
|
Create a composite image from the encapsulated image collection. |
Attributes
Earth Engine image collection. |
|
Name of the encapsulated Earth Engine image collection. |
|
|
|
A dictionary of properties for each image in the collection. |
|
|
|
A dictionary of abbreviations and descriptions for |
|
|
|
List of spectral / reflectance band names, if any. |
enums
CompositeMethod
- class geedim.enums.CompositeMethod
Enumeration for the compositing method, i.e. the method for finding a composite pixel from the stack of corresponding input image pixels.
- q_mosaic = 'q-mosaic'
Use the unmasked pixel with the highest cloud distance (distance to nearest cloud). Where more than one pixel has the same cloud distance, the first one in the stack is selected.
- mosaic = 'mosaic'
Use the first unmasked pixel in the stack.
- medoid = 'medoid'
Use the medoid of the unmasked pixels. This is the pixel from the image having the minimum sum of spectral distances to the rest of the images. Maintains the original relationship between bands. See https://www.mdpi.com/2072-4292/5/12/6481 for detail.
- median = 'median'
Use the median of the unmasked pixels.
- mode = 'mode'
Use the mode of the unmasked pixels.
- mean = 'mean'
Use the mean of the unmasked pixels.
- __new__(value)
CloudMaskMethod
ResamplingMethod
ExportType
Initialize
- geedim.utils.Initialize(opt_url: str | None = 'https://earthengine-highvolume.googleapis.com', **kwargs)
Initialise Earth Engine.
Credentials will be read from the EE_SERVICE_ACC_PRIVATE_KEY environment variable if it exists (useful for integrating with e.g. GitHub actions).
Note
Earth Engine recommends using the high volume endpoint for applications like
geedim
. See the docs for more information.- Parameters:
opt_url (str) – The Earth Engine endpoint to use. If
None
, the default is used.kwargs – Optional arguments to pass to ee.Initialize.