Note
Go to the end to download the full example code.
PlanetScope beside Sentinel-2, and the UDM2 snow band#
Output from the last scheduled build
This example needs planet credentials. The figures and printed output
below come from the most recent scheduled build, which has them; this build
reused that output instead of re-running the example.
PlanetScope is 3 m and near-daily, which is what makes it useful for catching a melt event between Sentinel-2 overpasses. It is also commercial: an order spends the account’s quota, so the ordering cell below is manual and does not run when the gallery is built.
Searching is free, so that part runs anywhere Planet credentials exist.
Search: free, and it only returns scenes the account may download.
scenes = esd.optical.planetscope.search(
aoi, when, cloud_cover=20, asset_types=["ortho_analytic_4b_sr", "ortho_udm2"]
)
print(scenes[["acquired", "cloud_percent", "clear_percent", "snow_ice_percent"]])
acquired ... snow_ice_percent
20230703_180548_93_2455 2023-07-03 18:05:48.931508+00:00 ... 21
20230703_180551_04_2455 2023-07-03 18:05:51.045197+00:00 ... 11
20230703_184655_52_2473 2023-07-03 18:46:55.521337+00:00 ... 5
20230703_184657_65_2473 2023-07-03 18:46:57.652433+00:00 ... 22
20230701_180931_56_24b0 2023-07-01 18:09:31.566153+00:00 ... 14
20230701_180933_91_24b0 2023-07-01 18:09:33.917506+00:00 ... 12
20230701_184407_40_2477 2023-07-01 18:44:07.403272+00:00 ... 11
20230701_184405_26_2477 2023-07-01 18:44:05.266513+00:00 ... 22
20230701_180512_23_241f 2023-07-01 18:05:12.238603+00:00 ... 8
[9 rows x 4 columns]
Warning
This cell spends Planet quota. It is the only step that does, and it
is why load never orders by itself. Uncomment it to run it by hand.
The clip tool means Planet charges for the AOI, not for the whole
600 MB strip; harmonize puts the radiometry on Sentinel-2’s scale.
With a delivery in hand, the bands are named, the UDM2 mask is decoded into its layers, and the snow band is directly usable:
ndsi_like = esd.processing.normalized_difference(ps["green"], ps["nir"])
snow = ps["snow"] # UDM2 snow mask, 0/1
print(float(esd.optical.planetscope.snow_fraction(ps).isel(time=0)))
fig, axes = plt.subplots(1, 3, figsize=(14, 4.5))
esd.plotting.rgb(
esd.processing.stretch_percentile(
esd.processing.rgb(ps.isel(time=0), ("red", "green", "blue"))
),
ax=axes[0],
title="PlanetScope 3 m",
)
ndsi_like.isel(time=0).plot.imshow(ax=axes[1], cmap="Blues")
esd.plotting.categorical(snow.isel(time=0), ax=axes[2], title="UDM2 snow")
The free comparison: the same box from Sentinel-2, which needs no account and no quota. Run the Planet cells above to put the 3 m and 10 m views side by side.
s2 = esd.optical.sentinel2.load(
aoi, when, bands=["green", "swir16", "red", "blue", "scl"], mask="scl-default"
)
ndsi = esd.processing.ndsi(s2)
if ndsi.sizes["time"]:
fig, ax = plt.subplots(figsize=(6, 5))
ndsi.isel(time=0).plot.imshow(ax=ax, cmap="Blues", vmin=-0.5, vmax=1.0)
ax.set_title("Sentinel-2 NDSI, same box")
ax.set_aspect("equal")
fig.tight_layout()

Total running time of the script: (0 minutes 8.335 seconds)