Image Collections & Useful Operations
Note: This example notebook covers the basics for how to define/initialize image collections and general data management operations using
RadGEEToolbox⚠⚠⚠ If you would like to learn how to visualize images processed with
RadGEEToolbox, please follow the ``Complete_ReadMe_Example.ipynb`,Palettes_and_Visualization.ipynb, orS1_SAR_Backscatter_Basic_Usage.ipynbexample notebooks on GitHub <https://github.com/radwinskis/RadGEEToolbox/tree/main/Example%20Notebooks>`__ ⚠⚠⚠
Initialization and Setup
[2]:
import ee
from RadGEEToolbox import LandsatCollection
from RadGEEToolbox import Sentinel2Collection
[ ]:
# Store name of Google Cloud Project assosiated with Earth Engine - replace with your project ID/name
PROJECT_ID = 'your-cloud-project-id'
# Attempt to initialize Earth Engine
try:
ee.Initialize(project=PROJECT_ID)
print("Earth Engine initialized successfully.")
except Exception as e:
print("Initialization failed, attempting authentication...")
try:
ee.Authenticate()
ee.Initialize(project=PROJECT_ID)
print("Authentication and initialization successful.")
except Exception as auth_error:
print("Authentication failed. Error details:", auth_error)
Earth Engine initialized successfully.
Defining collections - required arguments are ``start_date=`` and ``end_date=``.
Optional arguments are for specifying tile(s), boundary/geometry, or relative orbit(s) (orbits for Sentinel-2 only)
Below are multiple examples of how to define/initialize image collections for Sentinel-2 MSI data using the Sentinel2Collection class
specifying Military Grid Reference System (MGRS) tile(s) (see https://mappingsupport.com/p2/coordinates-mgrs-gissurfer-maps.html for more information and an interactive map illustrating the location(s) and size of MGRS tiles)
[4]:
#General way to define a Sentinel-2 image collection using start date, end date, and a single MGRS tile
S2_col = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-30', tile='12TUL')
specifying a list of MGRS tiles
[5]:
#General way to define a Sentinel-2 image collection using start date, end date, and multiple MGRS tiles
S2_col = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-30', tile=['12TUL', '12TUM', '12TUN'])
using relative orbit number instead of tile(s) to isolate an entire swath
[6]:
#Rather than using tiles, we can use a boundary (ee.Geometry) or if using Sentinel-2 we can use relative orbits - here we use a relative orbit number which provides a full swath of data
S2_col_orbit_filter = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-30', relative_orbit_number=127)
using a region of interest / boundary / geometry to filter to images overlapping the geometry
[7]:
#Here is an example of using a boundary to filter the collection - first defining a boundary, in this case the county of Salt Lake City
counties = ee.FeatureCollection('TIGER/2018/Counties')
salt_lake_county = counties.filter(ee.Filter.And(
ee.Filter.eq('NAME', 'Salt Lake'),
ee.Filter.eq('STATEFP', '49')))
salt_lake_geometry = salt_lake_county.geometry()
S2_col_boundary_filter = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-15', boundary=salt_lake_geometry)
using relative orbit numbers and cloud percentage threshold (no images with clouds greater than set aeral percentage)
[8]:
#You can filter for clouds by setting the cloud percentage threshold - here we set it to 15%
S2_col_low_clouds = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-30', relative_orbit_number=127, cloud_percentage_threshold=15)
using relative orbit numbers and NoData threshold (no images with more than the set threshold of percentage of NoData pixels in the image)
[9]:
#You can also filter for images with a lot of NoData - which happens more than you'd think - here we set the threshold to 15% as well
S2_col_no_blank_images = Sentinel2Collection(start_date='2023-06-01', end_date='2023-06-30', relative_orbit_number=127, nodata_threshold=15)
REMINDER:
If you would like to learn how to visualize images processed with
RadGEEToolbox, please follow the ``Complete_ReadMe_Example.ipynb`,Palettes_and_Visualization.ipynb, orS1_SAR_Backscatter_Basic_Usage.ipynbexample notebooks on GitHub <https://github.com/radwinskis/RadGEEToolbox/tree/main/Example%20Notebooks>`__ ⚠⚠⚠
As GEE uses deferred execution, GEE doesn’t immediately compute results when you define a collection. The processing is deferred until you explicitly ask for an output.
This can be done by printing the dates of a defined collection, to verify the collection is defined correctly and is not an empty collection.
Below is an example of how to quickly print the dates for any ``RadGEEToolbox`` collection object using ``.dates``
In this case, printing all of the dates from the Sentinel-2 collection defined above (S2_col)
[10]:
print(S2_col.dates)
['2023-06-01', '2023-06-01', '2023-06-02', '2023-06-02', '2023-06-04', '2023-06-04', '2023-06-04', '2023-06-06', '2023-06-06', '2023-06-07', '2023-06-07', '2023-06-09', '2023-06-09', '2023-06-09', '2023-06-11', '2023-06-11', '2023-06-12', '2023-06-12', '2023-06-12', '2023-06-14', '2023-06-14', '2023-06-14', '2023-06-16', '2023-06-16', '2023-06-17', '2023-06-17', '2023-06-19', '2023-06-19', '2023-06-19', '2023-06-21', '2023-06-21', '2023-06-22', '2023-06-22', '2023-06-22', '2023-06-24', '2023-06-24', '2023-06-24', '2023-06-26', '2023-06-26', '2023-06-27', '2023-06-27', '2023-06-29', '2023-06-29', '2023-06-29']
Defining a LandsatCollection object is very similar to Sentinel-2, however, Landsat tiles use a different grid system, the Worldwide Reference System (WRS-2), and thus the arguments for filtering by tile(s) are slightly different
See https://maps.eatlas.org.au/index.html?intro=false&z=7&ll=131.46626,-15.36800&l0=ea_ref%3AWorld_USGS_Landsat-WRS-2_Descending,ea_ea-be%3AWorld_Bright-Earth-e-Atlas-basemap,google_HYBRID,google_TERRAIN,google_SATELLITE,google_ROADMAP&o0=,0.3&v0=,,f,f,f,f for more information and an interactive map of WRS-2 tiles.
Below are some examples of how to define and filter a Landsat collection
[11]:
# Similar examples for Landsat collections - showing how to filter using tiles or boundaries
col = LandsatCollection(start_date='2023-06-01', end_date='2023-06-30', tile_row=32, tile_path=38)
tile_filtered_col = LandsatCollection(start_date='2023-06-01', end_date='2023-06-30', tile_row=32, tile_path=38, cloud_percentage_threshold=50)
SLC_filtered_col = LandsatCollection(start_date='2023-06-01', end_date='2023-06-30', boundary=salt_lake_geometry, cloud_percentage_threshold=15)
You may want to view the metadata of the defined collection to view band names and available properties - as shown below
The .collection attribute converts the RadGEEToolbox collection object to an ee.ImageCollection object to perform native GEE operations
Below we print the metadata of the image collection as a demo
[12]:
# Showing how to access the collection information by using the getInfo() method after converting the LandsatCollection object to an ee.ImageCollection object.
# This will return a dictionary with metadata about the collection.
print(SLC_filtered_col.collection.getInfo())
{'type': 'ImageCollection', 'bands': [], 'features': [{'type': 'Image', 'bands': [{'id': 'SR_B1', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B2', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B3', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B4', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B5', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B6', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_B7', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'SR_QA_AEROSOL', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 255}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_B10', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_ATRAN', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_CDIST', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_DRAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_EMIS', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_EMSD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_QA', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_TRAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'ST_URAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'QA_PIXEL', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}, {'id': 'QA_RADSAT', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7891, 8001], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 167985, 0, -30, 4587315]}], 'version': 1742938683640367, 'id': 'LANDSAT/LC09/C02/T1_L2/LC09_039032_20230620', 'properties': {'Date_Filter': '2023-06-20', 'system:index': '1_2_LC09_039032_20230620', 'DATA_SOURCE_ELEVATION': 'GLS2000', 'WRS_TYPE': 2, 'REFLECTANCE_ADD_BAND_1': -0.2, 'REFLECTANCE_ADD_BAND_2': -0.2, 'DATUM': 'WGS84', 'REFLECTANCE_ADD_BAND_3': -0.2, 'REFLECTANCE_ADD_BAND_4': -0.2, 'REFLECTANCE_ADD_BAND_5': -0.2, 'REFLECTANCE_ADD_BAND_6': -0.2, 'REFLECTANCE_ADD_BAND_7': -0.2, 'system:footprint': {'type': 'LinearRing', 'coordinates': [[-114.3199560530282, 41.38043783910363], [-114.32123392726943, 41.3768220430979], [-114.32371557834522, 41.36918162516504], [-114.33972875047438, 41.31765367718595], [-114.57864064161195, 40.53749352881813], [-114.81267806266982, 39.75699649972928], [-114.82653197680122, 39.71006593956936], [-114.8399712272878, 39.664159937190355], [-114.83369753399, 39.66299635243376], [-114.62102861518655, 39.62500432998853], [-112.98096141126392, 39.31726841838409], [-112.7320990579478, 39.2682837650888], [-112.73111206777264, 39.27074108839426], [-112.62527139854481, 39.59188036825782], [-112.25314511743413, 40.70195404795193], [-112.1574568798558, 40.98270964923042], [-112.15823134034592, 40.983281226743436], [-112.42898792679283, 41.03561258455256], [-114.31935483778066, 41.3809267846946], [-114.3199560530282, 41.38043783910363]]}, 'REFLECTIVE_SAMPLES': 7891, 'GROUND_CONTROL_POINTS_VERSION': 5, 'SUN_AZIMUTH': 128.23788739, 'UTM_ZONE': 12, 'DATE_ACQUIRED': '2023-06-20', 'ELLIPSOID': 'WGS84', 'system:time_end': 1687284822465, 'DATA_SOURCE_PRESSURE': 'Calculated', 'LANDSAT_PRODUCT_ID': 'LC09_L2SP_039032_20230620_20230622_02_T1', 'STATION_ID': 'LGN', 'TEMPERATURE_ADD_BAND_ST_B10': 149, 'DATA_SOURCE_REANALYSIS': 'GEOS-5 FP-IT', 'REFLECTANCE_MULT_BAND_7': 2.75e-05, 'system:time_start': 1687284822465, 'REFLECTANCE_MULT_BAND_6': 2.75e-05, 'L1_PROCESSING_LEVEL': 'L1TP', 'PROCESSING_SOFTWARE_VERSION': 'LPGS_16.3.0', 'L1_DATE_PRODUCT_GENERATED': '2023-06-20T22:25:38Z', 'ORIENTATION': 'NORTH_UP', 'REFLECTANCE_MULT_BAND_1': 2.75e-05, 'WRS_ROW': 32, 'REFLECTANCE_MULT_BAND_3': 2.75e-05, 'REFLECTANCE_MULT_BAND_2': 2.75e-05, 'TARGET_WRS_ROW': 32, 'REFLECTANCE_MULT_BAND_5': 2.75e-05, 'REFLECTANCE_MULT_BAND_4': 2.75e-05, 'THERMAL_LINES': 8001, 'GRID_CELL_SIZE_THERMAL': 30, 'IMAGE_QUALITY_TIRS': 9, 'NADIR_OFFNADIR': 'NADIR', 'CLOUD_COVER': 9.59, 'REQUEST_ID': '1749180_00042', 'EARTH_SUN_DISTANCE': 1.0161939, 'GEOMETRIC_RMSE_VERIFY': 1.676, 'COLLECTION_CATEGORY': 'T1', 'SCENE_CENTER_TIME': '18:13:42.4656960Z', 'GRID_CELL_SIZE_REFLECTIVE': 30, 'SUN_ELEVATION': 65.86332393, 'ALGORITHM_SOURCE_SURFACE_TEMPERATURE': 'st_1.5.0', 'TEMPERATURE_MAXIMUM_BAND_ST_B10': 372.999941, 'CLOUD_COVER_LAND': 9.59, 'GEOMETRIC_RMSE_MODEL': 5.145, 'ROLL_ANGLE': 0, 'COLLECTION_NUMBER': 2, 'DATE_PRODUCT_GENERATED': 1687414168000, 'L1_REQUEST_ID': '1748726_00042', 'DATA_SOURCE_OZONE': 'MODIS', 'SATURATION_BAND_1': 'N', 'DATA_SOURCE_WATER_VAPOR': 'MODIS', 'SATURATION_BAND_2': 'N', 'SATURATION_BAND_3': 'N', 'IMAGE_QUALITY_OLI': 9, 'SATURATION_BAND_4': 'N', 'LANDSAT_SCENE_ID': 'LC90390322023171LGN00', 'SATURATION_BAND_5': 'N', 'MAP_PROJECTION': 'UTM', 'SATURATION_BAND_6': 'Y', 'SENSOR_ID': 'OLI_TIRS', 'SATURATION_BAND_7': 'Y', 'SATURATION_BAND_8': 'N', 'WRS_PATH': 39, 'L1_PROCESSING_SOFTWARE_VERSION': 'LPGS_16.3.0', 'SATURATION_BAND_9': 'N', 'TARGET_WRS_PATH': 39, 'L1_LANDSAT_PRODUCT_ID': 'LC09_L1TP_039032_20230620_20230620_02_T1', 'TEMPERATURE_MULT_BAND_ST_B10': 0.00341802, 'PROCESSING_LEVEL': 'L2SP', 'ALGORITHM_SOURCE_SURFACE_REFLECTANCE': 'LaSRC_1.6.0', 'GROUND_CONTROL_POINTS_MODEL': 684, 'SPACECRAFT_ID': 'LANDSAT_9', 'TEMPERATURE_MINIMUM_BAND_ST_B10': 149.003418, 'GEOMETRIC_RMSE_MODEL_Y': 3.755, 'REFLECTIVE_LINES': 8001, 'GEOMETRIC_RMSE_MODEL_X': 3.517, 'THERMAL_SAMPLES': 7891, 'system:asset_size': 987150561, 'DATA_SOURCE_AIR_TEMPERATURE': 'MODIS', 'GROUND_CONTROL_POINTS_VERIFY': 161}}, {'type': 'Image', 'bands': [{'id': 'SR_B1', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B2', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B3', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B4', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B5', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B6', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_B7', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'SR_QA_AEROSOL', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 255}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_B10', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_ATRAN', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_CDIST', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_DRAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_EMIS', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_EMSD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_QA', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_TRAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'ST_URAD', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': -32768, 'max': 32767}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'QA_PIXEL', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}, {'id': 'QA_RADSAT', 'data_type': {'type': 'PixelType', 'precision': 'int', 'min': 0, 'max': 65535}, 'dimensions': [7791, 7921], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 302985, 0, -30, 4583415]}], 'version': 1688130359088278, 'id': 'LANDSAT/LC08/C02/T1_L2/LC08_038032_20230621', 'properties': {'Date_Filter': '2023-06-21', 'system:index': '1_1_LC08_038032_20230621', 'DATA_SOURCE_ELEVATION': 'GLS2000', 'WRS_TYPE': 2, 'REFLECTANCE_ADD_BAND_1': -0.2, 'REFLECTANCE_ADD_BAND_2': -0.2, 'DATUM': 'WGS84', 'REFLECTANCE_ADD_BAND_3': -0.2, 'REFLECTANCE_ADD_BAND_4': -0.2, 'REFLECTANCE_ADD_BAND_5': -0.2, 'REFLECTANCE_ADD_BAND_6': -0.2, 'REFLECTANCE_ADD_BAND_7': -0.2, 'system:footprint': {'type': 'LinearRing', 'coordinates': [[-112.75322341594308, 41.383271362121825], [-112.7538643317823, 41.38276864349693], [-113.01572520657774, 40.528203604162975], [-113.27021909552008, 39.677184288029366], [-113.27305552695559, 39.66736631270371], [-113.27301854511222, 39.666238263764285], [-113.23230468889169, 39.65894356408898], [-112.92866008563828, 39.60411211275331], [-111.99880693229721, 39.4306682665387], [-111.17451774947381, 39.26991947345506], [-111.17281794988826, 39.26992193883038], [-111.1711869220607, 39.27417723903013], [-110.88809495993736, 40.129238646243024], [-110.86719837755574, 40.19165284028886], [-110.79143492699511, 40.41749510985585], [-110.60028340148403, 40.983719632075825], [-110.60027767277539, 40.984672368452394], [-110.60945073796914, 40.98651933361583], [-111.73524356630396, 41.200487752804285], [-112.73428143483021, 41.38000825301653], [-112.75322341594308, 41.383271362121825]]}, 'REFLECTIVE_SAMPLES': 7791, 'GROUND_CONTROL_POINTS_VERSION': 5, 'SUN_AZIMUTH': 128.24625554, 'DATA_SOURCE_TIRS_STRAY_LIGHT_CORRECTION': 'TIRS', 'UTM_ZONE': 12, 'DATE_ACQUIRED': '2023-06-21', 'ELLIPSOID': 'WGS84', 'system:time_end': 1687370860034, 'DATA_SOURCE_PRESSURE': 'Calculated', 'LANDSAT_PRODUCT_ID': 'LC08_L2SP_038032_20230621_20230630_02_T1', 'STATION_ID': 'LGN', 'TEMPERATURE_ADD_BAND_ST_B10': 149, 'DATA_SOURCE_REANALYSIS': 'GEOS-5 FP-IT', 'REFLECTANCE_MULT_BAND_7': 2.75e-05, 'system:time_start': 1687370860034, 'REFLECTANCE_MULT_BAND_6': 2.75e-05, 'L1_PROCESSING_LEVEL': 'L1TP', 'PROCESSING_SOFTWARE_VERSION': 'LPGS_16.3.0', 'L1_DATE_PRODUCT_GENERATED': '2023-06-30T03:45:38Z', 'ORIENTATION': 'NORTH_UP', 'REFLECTANCE_MULT_BAND_1': 2.75e-05, 'WRS_ROW': 32, 'REFLECTANCE_MULT_BAND_3': 2.75e-05, 'REFLECTANCE_MULT_BAND_2': 2.75e-05, 'TARGET_WRS_ROW': 32, 'REFLECTANCE_MULT_BAND_5': 2.75e-05, 'REFLECTANCE_MULT_BAND_4': 2.75e-05, 'THERMAL_LINES': 7921, 'TIRS_SSM_POSITION_STATUS': 'ESTIMATED', 'GRID_CELL_SIZE_THERMAL': 30, 'IMAGE_QUALITY_TIRS': 9, 'TRUNCATION_OLI': 'UPPER', 'NADIR_OFFNADIR': 'NADIR', 'CLOUD_COVER': 2.99, 'REQUEST_ID': '1752742_00036', 'EARTH_SUN_DISTANCE': 1.016259, 'GEOMETRIC_RMSE_VERIFY': 2.682, 'TIRS_SSM_MODEL': 'FINAL', 'COLLECTION_CATEGORY': 'T1', 'SCENE_CENTER_TIME': '18:07:40.0342960Z', 'GRID_CELL_SIZE_REFLECTIVE': 30, 'SUN_ELEVATION': 65.86947224, 'ALGORITHM_SOURCE_SURFACE_TEMPERATURE': 'st_1.5.0', 'TEMPERATURE_MAXIMUM_BAND_ST_B10': 372.999941, 'CLOUD_COVER_LAND': 2.99, 'GEOMETRIC_RMSE_MODEL': 5.622, 'ROLL_ANGLE': -0.001, 'COLLECTION_NUMBER': 2, 'DATE_PRODUCT_GENERATED': 1688098109000, 'L1_REQUEST_ID': '1752742_00036', 'DATA_SOURCE_OZONE': 'MODIS', 'SATURATION_BAND_1': 'N', 'DATA_SOURCE_WATER_VAPOR': 'MODIS', 'SATURATION_BAND_2': 'N', 'SATURATION_BAND_3': 'Y', 'IMAGE_QUALITY_OLI': 9, 'SATURATION_BAND_4': 'Y', 'LANDSAT_SCENE_ID': 'LC80380322023172LGN00', 'SATURATION_BAND_5': 'Y', 'MAP_PROJECTION': 'UTM', 'SATURATION_BAND_6': 'Y', 'SENSOR_ID': 'OLI_TIRS', 'SATURATION_BAND_7': 'Y', 'SATURATION_BAND_8': 'N', 'WRS_PATH': 38, 'SATURATION_BAND_9': 'N', 'TARGET_WRS_PATH': 38, 'L1_PROCESSING_SOFTWARE_VERSION': 'LPGS_16.3.0', 'TEMPERATURE_MULT_BAND_ST_B10': 0.00341802, 'L1_LANDSAT_PRODUCT_ID': 'LC08_L1TP_038032_20230621_20230630_02_T1', 'PROCESSING_LEVEL': 'L2SP', 'ALGORITHM_SOURCE_SURFACE_REFLECTANCE': 'LaSRC_1.6.0', 'GROUND_CONTROL_POINTS_MODEL': 909, 'SPACECRAFT_ID': 'LANDSAT_8', 'TEMPERATURE_MINIMUM_BAND_ST_B10': 149.003418, 'GEOMETRIC_RMSE_MODEL_Y': 4.134, 'REFLECTIVE_LINES': 7921, 'GEOMETRIC_RMSE_MODEL_X': 3.81, 'THERMAL_SAMPLES': 7791, 'system:asset_size': 991995719, 'DATA_SOURCE_AIR_TEMPERATURE': 'MODIS', 'GROUND_CONTROL_POINTS_VERIFY': 236}}]}
Below we print the crs projection type of the image collection as a demo
[13]:
# Showing how to print properties of an image collection by turning the LandsatCollection object into an ee.ImageCollection object and using the .getInfo() parameter, then explore the python dictionary output
print(SLC_filtered_col.collection.getInfo()['features'][0]['bands'][0]['crs'])
EPSG:32612
After calling .getInfo(), the server-side ee.ImageCollection is converted into a native Python dictionary representing the object’s structure. This allows you to inspect metadata like projection, band names, image dimensions, and more.
Data management is an important aspect of remote sensing workflows and RadGEEToolbox provides flexibility to convert image collections back and forth from RadGEEToolbox and GEE image collection objects, which allows inclusion of custom GEE API functions and image processing workflows while retaining the ability to use RadGEEToolbox functionality at any time
If we print the variable of one of the collections we see it is a RadGEEToolbox object
[12]:
print(S2_col)
<RadGEEToolbox.Sentinel2Collection.Sentinel2Collection object at 0x000002253CEBF8F0>
Below is an example of how to convert back to a GEE collection then convert back to a RadGEEToolbox collection
First we convert a Sentinel2Collection object to a GEE object using .collection, as verified by the printout below
[13]:
# We can turn a Sentinel2Collection or LandsatCollection object into an Earth Engine image collection using the collection attribute
S2_gee_col = S2_col.collection
print('The collection is now a', type(S2_gee_col))
The collection is now a <class 'ee.imagecollection.ImageCollection'>
You may now perform native GEE operations on this collection.
Once you are ready to convert back, the following demonstrates the easy conversion from a GEE object to a Sentinel2Collection object - this is identical for the LandsatCollection and Sentinel1Collection classes.
When initializing the class object, just feed in the ee.ImageCollection using the argument ``collection=``
The printout below verifies the collection is once again a RadGEEToolbox object
[14]:
# Say you have an Earth Engine image collection object but you want to turn it into a Sentinel2Collection or LandsatCollection object,
# just feed it in as a collection!
S2_col = Sentinel2Collection(collection=S2_gee_col)
print('The collection is back to a', type(S2_col))
The collection is back to a <class 'RadGEEToolbox.Sentinel2Collection.Sentinel2Collection'>
Supplemental examples
Attributes
How to store and print the list of dates in the S2_col image collection using .dates
[15]:
# We can easily print the dates of all of the images in the collection using the dates attribute - this is a client-side operation
S2_dates = S2_col.dates
print('Readable list of image dates (client-side)', S2_dates)
Readable list of image dates (client-side) ['2023-06-01', '2023-06-01', '2023-06-02', '2023-06-02', '2023-06-04', '2023-06-04', '2023-06-04', '2023-06-06', '2023-06-06', '2023-06-07', '2023-06-07', '2023-06-09', '2023-06-09', '2023-06-09', '2023-06-11', '2023-06-11', '2023-06-12', '2023-06-12', '2023-06-12', '2023-06-14', '2023-06-14', '2023-06-14', '2023-06-16', '2023-06-16', '2023-06-17', '2023-06-17', '2023-06-19', '2023-06-19', '2023-06-19', '2023-06-21', '2023-06-21', '2023-06-22', '2023-06-22', '2023-06-22', '2023-06-24', '2023-06-24', '2023-06-24', '2023-06-26', '2023-06-26', '2023-06-27', '2023-06-27', '2023-06-29', '2023-06-29', '2023-06-29']
.dates makes a client-side request using .getInfo() to convert the server-side list of image dates into a native Python list. The result is cached, so printing or reusing the list does not repeatedly trigger new requests.
However, in some cases you may want to retain the list as a server-side ee.List—for example, when performing iterative operations inside native Earth Engine functions.
For this, use .dates_list.
Using .dates_list to retrieve a server-side list of dates from the S2_col image collection is useful for operations that must remain on the Earth Engine server.
The printout below shows the object is an ee.List, not a Python list.
[16]:
# Alternatively, we can make a list of server-side dates for iteration, if needed
S2_dates_server_side = S2_col.dates_list
print('Server side dates are of type:', type(S2_dates_server_side))
Server side dates are of type: <class 'ee.ee_list.List'>
How to mask clouds out of a multispectral image collection using .masked_clouds_collection
[17]:
# You can easily mask out clouds or water in the image collections
S2_masked_clouds = S2_col.masked_clouds_collection
How to mask to water with a multispectral image collection using .masked_to_water_collection
[18]:
S2_masked_to_water = S2_col.masked_to_water_collection
Utilizing methods for general data management
Masking to polygon using
.mask_to_polygon()
[19]:
# Mask entire collection based on geometry
masked_S2_col = S2_col_orbit_filter.mask_to_polygon(salt_lake_geometry)
Mosacing images with same date using
.mosaicByDate
[ ]:
# Mosaic images in collection that share an image date
mosaiced_S2_col = S2_col_boundary_filter.mosaicByDate
Masking water out of images automatically using
.masked_water_collection
[21]:
# Mask water pixels from each single image using quality bands
water_masked_S2_col = S2_col_boundary_filter.masked_water_collection
Masking images to water automatically using
.masked_water_collection_NDWI()
[22]:
# Mask water pixels from each single image using NDWI - where values less than the specified threshold are masked in each image
water_masked_S2_col = S2_col_boundary_filter.masked_water_collection_NDWI(threshold=0)
Example chaining of methods - where we first mosaic the collection using ``.mosaicByDate``, mask the collection to water pixels using ``.masked_to_water_collection``, then calculate relative turbidity for each image using ``.turbidity``
[ ]:
# Example chaining of methods - where we first mosaic the collection, mask the collection to water pixels, then calculate relative turbidity for each image
turbidity_chain_example = S2_col.mosaicByDate.masked_to_water_collection.turbidity
print(turbidity_chain_example.dates)
['2023-06-01', '2023-06-02', '2023-06-04', '2023-06-06', '2023-06-07', '2023-06-09', '2023-06-11', '2023-06-12', '2023-06-14', '2023-06-16', '2023-06-17', '2023-06-19', '2023-06-21', '2023-06-22', '2023-06-24', '2023-06-26', '2023-06-27', '2023-06-29']
Arguably, two of the most useful method functions when exploring an image collection are image_grab() or image_pick() - which allow you to iteratively select images from an image collection, which is helpful when visualizing the imagery
Example using
.image_grab(), grabbing the most recent image in the collection and printing the date
[24]:
# Select image from collection based on index
image_from_S2_collection = mosaiced_S2_col.image_grab(-1)
print('Image date: ', image_from_S2_collection.getInfo()['properties']['Date_Filter'])
Image date: 2023-06-14
Example using
.image_pick(), where you specify the date of the image you want to pick from the collection.
First let’s pick a date, date_of_interest and print the date to verify
[25]:
date_of_interest = mosaiced_S2_col.dates[-1]
print('Date of interest: ', date_of_interest)
Date of interest: 2023-06-14
Then use .image_pick() to select the image from the collection
We print the date of the selected image to verify it matches the date we want
[26]:
# Select image from collection based on date
image_from_S2_collection = mosaiced_S2_col.image_pick(date_of_interest)
#Verify the date of the image matches the date we selected
print('Date of selected image: ', image_from_S2_collection.getInfo()['properties']['Date_Filter'])
Date of selected image: 2023-06-14
Using static functions
The below examples show how you can use RadGEEToolbox functions on Earth Engine objects - where we define the Earth Engine object by converting a RadGEEToolbox collection to an Earth Engine object. Then, to apply the function we use .map() to iterate the function across the collection (for functions which require an ee.Image as the input)
Note: All functionality offered by static functions are built into the RadGEEToolbox functionality. These are only useful when wanting to work outside of RadGEEToolbox class objects and solely with Earth Engine objects
Using
.image_daterto add the RadGEEToolbox recognized date to the properties of each image in the collection.
This is mandatory if you anticipate using RadGEEToolbox functionality as static functions, as they will look for an image property called Date_Filter which is not present by default.
[27]:
# adding image date properties to images (very general example)
S2_col_date_props = S2_col.collection.map(Sentinel2Collection.image_dater)
Using
maskWaterto automatically mask water from Sentinel-2 imagery
[ ]:
# masking water from images
S2_water_masked_col = S2_col.collection.map(Sentinel2Collection.maskWater)
Using
pixelAreaSum()to calculate the area of a class from a classified image
[ ]:
# calculating the surface area of pixels of interest as square meters(water pixels from NDWI for example)
water_area = Sentinel2Collection.pixelAreaSum(image=mosaiced_S2_col.ndwi.image_grab(-1), band_name='ndwi', geometry=salt_lake_geometry, threshold=0, scale=10)
print('Square meters of water in image:', water_area.getInfo().get('properties')['ndwi'])
Square meters of water in image: 1647328630.1742606
Finally, a powerful example illustrating how simple it is to create a valuable time series dataset, in this case calculating the area of water within Salt Lake County over an entire collection.
We stack .ndwi and .pixelAreaSumCollection() to process the orginal collection to NDWI and create the time series in one line of code
Then show how to print the resulting area calculations using .aggregate_array(). This is necessary, as Earth Engine doesn’t allow outputs of different types from the input data - so a list can not be directly returned from an image collection. To work around this, the surface area of the class of interest is stored as a property for each image in the collection under the band name of the class of interest. In this case, the band name is ‘ndwi’, so we print out the list of image properties
with the name of ‘ndwi’ and use .getInfo() to convert the server-side list to a client-side list.
For best data management, it is suggested to store the list as a dataframe and export as a csv or table type of preference for further analyses - or else processing will be slowed by repetitive client-side requests.
[ ]:
# Showing how to make an image collection with pixel area calculated for all images in the collection (using ndwi images as example), and how to assess
# the area calculations using aggregate_array()
area_col = mosaiced_S2_col.ndwi.pixelAreaSumCollection(band_name='ndwi', geometry=salt_lake_geometry, threshold=0, scale=50)
print('Square meters of water in images are:', area_col.aggregate_array('ndwi').getInfo())
Square meters of water in images are: [1069594768.6520188, 251369607.87758926, 247235936.65393806, 496807659.3774899, 192290154.215422, 1646335856.4432714]
Dates of images corresponding to water area list
[31]:
print('Dates of images:', mosaiced_S2_col.dates)
Dates of images: ['2023-06-01', '2023-06-04', '2023-06-06', '2023-06-09', '2023-06-11', '2023-06-14']