Skip to content

Commit

Permalink
Update Landsat C1 to C2 for misc Guide pages
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 605129643
  • Loading branch information
jdbcode authored and copybara-github committed Feb 8, 2024
1 parent ba9b81f commit be1fef7
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 145 deletions.
1 change: 1 addition & 0 deletions samples/javascript/guides/landsat01.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var surfaceReflectanceL4 = ee.ImageCollection('LANDSAT/LT04/C02/T1_L2');
var surfaceReflectanceL5 = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2');
var surfaceReflectanceL7 = ee.ImageCollection('LANDSAT/LE07/C02/T1_L2');
var surfaceReflectanceL8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2');
var surfaceReflectanceL9 = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2');
// [END earthengine__landsat01__sr_collections]


Expand Down
2 changes: 1 addition & 1 deletion tutorials/beginners-cookbook/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ var geometry = ee.Geometry.Rectangle([55.1, 25, 55.4, 25.4]);
// Add layer to map.
Map.addLayer(geometry);
// Load Landsat image collection.
var allImages = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
var allImages = ee.ImageCollection('LANDSAT/LT05/C02/T1_TOA')
// Filter row and path such that they cover Dubai.
.filter(ee.Filter.eq('WRS_PATH', 160))
.filter(ee.Filter.eq('WRS_ROW', 43))
Expand Down
218 changes: 94 additions & 124 deletions tutorials/histogram-matching/index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
},
"source": [
"import ee\n",
"import geemap\n",
"\n",
"ee.Authenticate()\n",
"ee.Initialize(project='my-project')"
],
Expand Down Expand Up @@ -161,36 +163,36 @@
"id": "l-ofElnberw1"
},
"source": [
"def histogram_match(source_img, target_img, geometry):\r\n",
" \"\"\"Performs histogram matching for 3-band RGB images by forcing the histogram CDF of source_img to match target_img.\r\n",
"\r\n",
" Args:\r\n",
" source_img: A 3-band ee.Image to be color matched. Must have bands named 'R', 'G', and 'B'.\r\n",
" target_img: A 3-band ee.Image for color reference. Must have bands named 'R', 'G', and 'B'.\r\n",
" geometry: An ee.Geometry that defines the region to generate RGB histograms for.\r\n",
" It should intersect both source_img and target_img inputs.\r\n",
"\r\n",
" Returns:\r\n",
" A copy of src_img color-matched to target_img.\r\n",
" \"\"\"\r\n",
"\r\n",
" args = {\r\n",
" 'reducer': ee.Reducer.autoHistogram(**{'maxBuckets': 256, 'cumulative': True}),\r\n",
" 'geometry': geometry,\r\n",
" 'scale': 1, # Need to specify a scale, but it doesn't matter what it is because bestEffort is true.\r\n",
" 'maxPixels': 65536 * 4 - 1,\r\n",
" 'bestEffort': True\r\n",
" }\r\n",
"\r\n",
" # Only use pixels in target that have a value in source (inside the footprint and unmasked).\r\n",
" source = source_img.reduceRegion(**args)\r\n",
" target = target_img.updateMask(source_img.mask()).reduceRegion(**args)\r\n",
"\r\n",
" return ee.Image.cat(\r\n",
" source_img.select(['R']).interpolate(**lookup(source.getArray('R'), target.getArray('R'))),\r\n",
" source_img.select(['G']).interpolate(**lookup(source.getArray('G'), target.getArray('G'))),\r\n",
" source_img.select(['B']).interpolate(**lookup(source.getArray('B'), target.getArray('B')))\r\n",
" ).copyProperties(source_img, ['system:time_start'])"
"def histogram_match(source_img, target_img, geometry):\n",
" \"\"\"Performs histogram matching for 3-band RGB images by forcing the histogram CDF of source_img to match target_img.\n",
"\n",
" Args:\n",
" source_img: A 3-band ee.Image to be color matched. Must have bands named 'R', 'G', and 'B'.\n",
" target_img: A 3-band ee.Image for color reference. Must have bands named 'R', 'G', and 'B'.\n",
" geometry: An ee.Geometry that defines the region to generate RGB histograms for.\n",
" It should intersect both source_img and target_img inputs.\n",
"\n",
" Returns:\n",
" A copy of src_img color-matched to target_img.\n",
" \"\"\"\n",
"\n",
" args = {\n",
" 'reducer': ee.Reducer.autoHistogram(maxBuckets=256, cumulative=True),\n",
" 'geometry': geometry,\n",
" 'scale': 1, # Need to specify a scale, but it doesn't matter what it is because bestEffort is true.\n",
" 'maxPixels': 65536 * 4 - 1,\n",
" 'bestEffort': True\n",
" }\n",
"\n",
" # Only use pixels in target that have a value in source (inside the footprint and unmasked).\n",
" source = source_img.reduceRegion(**args)\n",
" target = target_img.updateMask(source_img.mask()).reduceRegion(**args)\n",
"\n",
" return ee.Image(ee.Image.cat(\n",
" source_img.select(['R']).interpolate(**lookup(source.getArray('R'), target.getArray('R'))),\n",
" source_img.select(['G']).interpolate(**lookup(source.getArray('G'), target.getArray('G'))),\n",
" source_img.select(['B']).interpolate(**lookup(source.getArray('B'), target.getArray('B')))\n",
" ).copyProperties(source_img, ['system:time_start']))"
],
"execution_count": null,
"outputs": []
Expand All @@ -214,33 +216,33 @@
"id": "_EmxcWn_gOE_"
},
"source": [
"def find_closest(target_image, image_col, days):\r\n",
" \"\"\"Filter images in a collection by date proximity and spatial intersection to a target image.\r\n",
"\r\n",
" Args:\r\n",
" target_image: An ee.Image whose observation date is used to find near-date images in\r\n",
" the provided image_col image collection. It must have a 'system:time_start' property.\r\n",
" image_col: An ee.ImageCollection to filter by date proximity and spatial intersection\r\n",
" to the target_image. Each image in the collection must have a 'system:time_start'\r\n",
" property.\r\n",
" days: A number that defines the maximum number of days difference allowed between\r\n",
" the target_image and images in the image_col.\r\n",
"\r\n",
" Returns:\r\n",
" An ee.ImageCollection that has been filtered to include those images that are within the\r\n",
" given date proximity to target_image and intersect it spatially.\r\n",
" \"\"\"\r\n",
"\r\n",
" # Compute the timespan for N days (in milliseconds).\r\n",
" range = ee.Number(days).multiply(1000 * 60 * 60 * 24)\r\n",
"\r\n",
" filter = ee.Filter.And(\r\n",
" ee.Filter.maxDifference(range, 'system:time_start', None, 'system:time_start'),\r\n",
" ee.Filter.intersects('.geo', None, '.geo'))\r\n",
"\r\n",
" closest = (ee.Join.saveAll('matches', 'measure')\r\n",
" .apply(ee.ImageCollection([target_image]), image_col, filter))\r\n",
"\r\n",
"def find_closest(target_image, image_col, days):\n",
" \"\"\"Filter images in a collection by date proximity and spatial intersection to a target image.\n",
"\n",
" Args:\n",
" target_image: An ee.Image whose observation date is used to find near-date images in\n",
" the provided image_col image collection. It must have a 'system:time_start' property.\n",
" image_col: An ee.ImageCollection to filter by date proximity and spatial intersection\n",
" to the target_image. Each image in the collection must have a 'system:time_start'\n",
" property.\n",
" days: A number that defines the maximum number of days difference allowed between\n",
" the target_image and images in the image_col.\n",
"\n",
" Returns:\n",
" An ee.ImageCollection that has been filtered to include those images that are within the\n",
" given date proximity to target_image and intersect it spatially.\n",
" \"\"\"\n",
"\n",
" # Compute the timespan for N days (in milliseconds).\n",
" range = ee.Number(days).multiply(1000 * 60 * 60 * 24)\n",
"\n",
" filter = ee.Filter.And(\n",
" ee.Filter.maxDifference(range, 'system:time_start', None, 'system:time_start'),\n",
" ee.Filter.intersects('.geo', None, '.geo'))\n",
"\n",
" closest = (ee.Join.saveAll('matches', 'measure')\n",
" .apply(ee.ImageCollection([target_image]), image_col, filter))\n",
"\n",
" return ee.ImageCollection(ee.List(closest.first().get('matches')))"
],
"execution_count": null,
Expand Down Expand Up @@ -274,13 +276,9 @@
"id": "OPBddAaYNMIz"
},
"source": [
"geometry = ee.Geometry.Polygon(\r\n",
" [[[-155.97117211519446, 20.09006980142336],\r\n",
" [-155.97117211519446, 19.7821681268256],\r\n",
" [-155.73256280122962, 19.7821681268256],\r\n",
" [-155.73256280122962, 20.09006980142336]]], None, False)\r\n",
"\r\n",
"skysat = (ee.Image('SKYSAT/GEN-A/PUBLIC/ORTHO/RGB/s01_20161020T214047Z')\r\n",
"geometry = ee.Geometry.BBox(-155.971, 19.782, -155.733, 20.09)\n",
"\n",
"skysat = (ee.Image('SKYSAT/GEN-A/PUBLIC/ORTHO/RGB/s01_20161020T214047Z')\n",
" .clip(geometry))"
],
"execution_count": null,
Expand All @@ -301,20 +299,24 @@
"id": "5sZYiLMAo6M1"
},
"source": [
"def prep_landsat(image):\r\n",
" \"\"\"Apply cloud/shadow mask and select/rename Landsat 8 bands.\"\"\"\r\n",
"\r\n",
" qa = image.select('pixel_qa')\r\n",
" return (image.updateMask(\r\n",
" qa.bitwiseAnd(1 \u003c\u003c 3).eq(0).And(qa.bitwiseAnd(1 \u003c\u003c 5).eq(0)))\r\n",
" .divide(10000)\r\n",
" .select(['B4', 'B3', 'B2'], ['R', 'G', 'B'])\r\n",
" .copyProperties(image, ['system:time_start']))\r\n",
"\r\n",
"# Get the landsat collection, cloud masked and scaled to surface reflectance.\r\n",
"landsat_col = (ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')\r\n",
"\t.filterBounds(geometry)\r\n",
"\t.map(prep_landsat))"
"def prep_landsat(image):\n",
" \"\"\"Scale, apply cloud/shadow mask, and select/rename Landsat 8 bands.\"\"\"\n",
" qa_mask = image.select('QA_PIXEL').bitwiseAnd(int('11111', 2)).eq(0)\n",
"\n",
" def get_factor_img(factor_names):\n",
" factor_list = image.toDictionary().select(factor_names).values()\n",
" return ee.Image.constant(factor_list)\n",
"\n",
" scale_img = get_factor_img(['REFLECTANCE_MULT_BAND_.'])\n",
" offset_img = get_factor_img(['REFLECTANCE_ADD_BAND_.'])\n",
" scaled = image.select('SR_B.').multiply(scale_img).add(offset_img)\n",
"\n",
" return image.addBands(scaled, None, True).select(\n",
" ['SR_B4', 'SR_B3', 'SR_B2'], ['R', 'G', 'B']).updateMask(qa_mask)\n",
"\n",
"# Get the landsat collection, cloud masked and scaled to surface reflectance.\n",
"landsat_col = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2').filterBounds(\n",
" geometry).map(prep_landsat)"
],
"execution_count": null,
"outputs": []
Expand All @@ -334,7 +336,7 @@
"id": "vxxWeyPVo16v"
},
"source": [
"reference = find_closest(skysat, landsat_col, 32).sort('CLOUD_COVER').mosaic()\r\n",
"reference = find_closest(skysat, landsat_col, 32).sort('CLOUD_COVER').mosaic()\n",
"result = histogram_match(skysat, reference, geometry)"
],
"execution_count": null,
Expand All @@ -346,41 +348,9 @@
"id": "s2YImlVmcEA3"
},
"source": [
"## Results\r\n",
"\r\n",
"Setup folium for interactive map viewing."
]
},
{
"cell_type": "code",
"metadata": {
"id": "2K0O6bv0cGf-"
},
"source": [
"import folium\r\n",
"\r\n",
"def add_ee_layer(self, ee_image_object, vis_params, name):\r\n",
" map_id_dict = ee.Image(ee_image_object).getMapId(vis_params)\r\n",
" folium.raster_layers.TileLayer(\r\n",
" tiles=map_id_dict['tile_fetcher'].url_format,\r\n",
" attr='Map Data \u0026copy; \u003ca href=\"https://earthengine.google.com/\"\u003eGoogle Earth Engine\u003c/a\u003e',\r\n",
" name=name,\r\n",
" overlay=True,\r\n",
" control=True\r\n",
" ).add_to(self)\r\n",
"\r\n",
"folium.Map.add_ee_layer = add_ee_layer"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "HQgGj9HJrPKa"
},
"source": [
"Define a folium map object, add layers, and display it. Until you zoom in really far, it's nearly impossible to tell where the Landsat image ends and the SkySat image begins."
"## Results\n",
"\n",
"Define a `geemap.Map` object, add layers, and display it. Until you zoom in really far, it's nearly impossible to tell where the Landsat image ends and the SkySat image begins."
]
},
{
Expand All @@ -389,16 +359,16 @@
"id": "QJDqpNtDpUKO"
},
"source": [
"lon, lat, zoom = -155.79584, 19.99866, 13\r\n",
"map_matched = folium.Map(location=[lat, lon], zoom_start=zoom)\r\n",
"\r\n",
"vis_params_refl = {'min': 0, 'max': 0.25}\r\n",
"vis_params_dn = {'min': 0, 'max': 255}\r\n",
"\r\n",
"map_matched.add_ee_layer(reference, vis_params_refl, 'Landsat-8 reference')\r\n",
"map_matched.add_ee_layer(skysat, vis_params_dn, 'SkySat source')\r\n",
"map_matched.add_ee_layer(result, vis_params_refl, 'SkySat matched')\r\n",
"display(map_matched.add_child(folium.LayerControl()))"
"lon, lat, zoom = -155.79584, 19.99866, 13\n",
"m = geemap.Map(center=[lat, lon], zoom=zoom)\n",
"\n",
"vis_params_refl = {'min': 0, 'max': 0.25}\n",
"vis_params_dn = {'min': 0, 'max': 255}\n",
"\n",
"m.add_layer(reference, vis_params_refl, 'Landsat-8 reference')\n",
"m.add_layer(skysat, vis_params_dn, 'SkySat source')\n",
"m.add_layer(result, vis_params_refl, 'SkySat matched')\n",
"m"
],
"execution_count": null,
"outputs": []
Expand Down
37 changes: 17 additions & 20 deletions tutorials/time-series-visualization-with-altair/index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1059,7 +1059,7 @@
"ndvi_df_sub = ndvi_df[(ndvi_df['DOY'] \u003e= ndvi_doy_range[0])\n",
" \u0026 (ndvi_df['DOY'] \u003c= ndvi_doy_range[1])]\n",
"\n",
"ndvi_df_sub = ndvi_df_sub.groupby('Year').agg('min')"
"ndvi_df_sub = ndvi_df_sub.groupby('Year').min(numeric_only=True)"
],
"execution_count": null,
"outputs": []
Expand Down Expand Up @@ -1094,7 +1094,7 @@
"pdsi_df_sub = pdsi_df[(pdsi_df['DOY'] \u003e= pdsi_doy_range[0])\n",
" \u0026 (pdsi_df['DOY'] \u003c= pdsi_doy_range[1])]\n",
"\n",
"pdsi_df_sub = pdsi_df_sub.groupby('Year').agg('mean')"
"pdsi_df_sub = pdsi_df_sub.groupby('Year').mean(numeric_only=True)"
],
"execution_count": null,
"outputs": []
Expand Down Expand Up @@ -1360,23 +1360,20 @@
"# Define a function to get and rename bands of interest from OLI.\n",
"def rename_oli(img):\n",
" return (img.select(\n",
" ee.List(['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'pixel_qa']),\n",
" ee.List(['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2', 'pixel_qa'])))\n",
" ee.List(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7']),\n",
" ee.List(['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2'])))\n",
"\n",
"# Define a function to get and rename bands of interest from ETM+.\n",
"def rename_etm(img):\n",
" return (img.select(\n",
" ee.List(['B1', 'B2', 'B3', 'B4', 'B5', 'B7', 'pixel_qa']),\n",
" ee.List(['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2', 'pixel_qa'])))\n",
"\n",
"# Define a function to mask out clouds and cloud shadows.\n",
"def cfmask(img):\n",
" cloud_shadow_bi_mask = 1 \u003c\u003c 3\n",
" cloud_bit_mask = 1 \u003c\u003c 5\n",
" qa = img.select('pixel_qa')\n",
" mask = qa.bitwiseAnd(cloud_shadow_bi_mask).eq(0).And(\n",
" qa.bitwiseAnd(cloud_bit_mask).eq(0))\n",
" return img.updateMask(mask)\n",
" ee.List(['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B7']),\n",
" ee.List(['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2'])))\n",
"\n",
"# Define a function to scale images and mask out clouds and cloud shadows.\n",
"def scale_and_mask(img):\n",
" qa_mask = img.select('QA_PIXEL').bitwiseAnd(int('11111', 2)).eq(0)\n",
" scaled = img.select('SR_B.').multiply(0.0000275).add(-0.2)\n",
" return scaled.updateMask(qa_mask)\n",
"\n",
"# Define a function to add year as an image property.\n",
"def set_year(img):\n",
Expand All @@ -1390,25 +1387,25 @@
"# Define a function to prepare OLI images.\n",
"def prep_oli(img):\n",
" orig = img\n",
" img = scale_and_mask(img)\n",
" img = rename_oli(img)\n",
" img = cfmask(img)\n",
" img = calc_nbr(img)\n",
" img = img.copyProperties(orig, orig.propertyNames())\n",
" return set_year(img)\n",
"\n",
"# Define a function to prepare TM/ETM+ images.\n",
"def prep_etm(img):\n",
" orig = img\n",
" img = scale_and_mask(img)\n",
" img = rename_etm(img)\n",
" img = cfmask(img)\n",
" img = calc_nbr(img)\n",
" img = img.copyProperties(orig, orig.propertyNames())\n",
" return set_year(img)\n",
"\n",
"# Import image collections for each Landsat sensor (surface reflectance).\n",
"tm_col = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')\n",
"etm_col = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')\n",
"oli_col = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')\n",
"tm_col = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2')\n",
"etm_col = ee.ImageCollection('LANDSAT/LE07/C02/T1_L2')\n",
"oli_col = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')\n",
"\n",
"# Filter collections and prepare them for merging.\n",
"oli_col = oli_col.filterBounds(point).filter(\n",
Expand Down

0 comments on commit be1fef7

Please sign in to comment.