{
"cells": [
{
"cell_type": "markdown",
"id": "4a99071f-ea18-4b19-9b62-de8be5c03d72",
"metadata": {},
"source": [
"## Interactively browse STAC footprints\n",
"\n",
"STAC items contain information about the spatio-temporal footprint of the data they catalog. Using [Jupyter Widgets](https://ipywidgets.readthedocs.io/en/latest/#), in particular [`ipywidgets.interact`](https://ipywidgets.readthedocs.io/en/latest/examples/Using%20Interact.html) and [`ipyleaflet`](https://ipyleaflet.readthedocs.io/en/latest/index.html), we can quickly build an interactive tool for visualizing item footprints. This can be helpful for understanding the path a satellite takes over earth or debugging strange looking item footprints.\n",
"\n",
"We'll start by grabbing some Sentinel-2 L2A items from the Planetary Computer's STAC API."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "242551be-9f6d-4cb6-8f55-9dcd2fe77eb3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import pystac_client\n",
"\n",
"catalog = pystac_client.Client.open(\n",
" \"https://planetarycomputer.microsoft.com/api/stac/v1\"\n",
")\n",
"\n",
"search = catalog.search(\n",
" collections=[\"sentinel-2-l2a\"],\n",
" datetime=\"2023-04-01\",\n",
" query={\"platform\": {\"eq\": \"Sentinel-2B\"}},\n",
" sortby=\"datetime\",\n",
" max_items=200,\n",
")\n",
"\n",
"items = search.item_collection()"
]
},
{
"cell_type": "markdown",
"id": "d13aea35-99d2-4445-8f44-9d257374abaa",
"metadata": {},
"source": [
"Next, we'll build up our tool. We start with our placeholders:\n",
"\n",
"1. An `ipyleaflet.Map` object\n",
"2. An empty `ipyleaflet.GeoJSON` layer, which we add to the map\n",
"\n",
"Then we use `ipywidgets.interact` to browse the list of items. This gives us a dropdown with the list of items, which we can scroll through to select a single item for display.\n",
"The body of the function updates the state of our map to set\n",
"\n",
"1. The center of the map to the center of the selected item\n",
"2. The `data` for the GeoJSON layer, to display the selected item's footprint\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cde2a30a-38ae-4b1b-9a4a-cffaa22b486b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import ipywidgets\n",
"import ipyleaflet\n",
"import shapely.geometry\n",
"\n",
"m = ipyleaflet.Map(zoom=3)\n",
"m.layout.width = \"600px\"\n",
"layer = ipyleaflet.GeoJSON()\n",
"m.add(layer)\n",
"\n",
"\n",
"@ipywidgets.interact(item=items)\n",
"def browse(item):\n",
" shape = shapely.geometry.shape(item.geometry)\n",
" m.center = tuple(shape.centroid.coords[0])[::-1]\n",
"\n",
" layer.data = item.geometry\n",
" print(item.id, item.datetime.isoformat())\n",
"\n",
"\n",
"m"
]
},
{
"cell_type": "markdown",
"id": "75d54acb-8c91-4f05-9d9c-eb0dfa68c0af",
"metadata": {},
"source": [
"Here's an example of using the browser:\n",
"\n",
""
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {
"0759a11604384cbe81def1c99907a8d3": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "VBoxModel",
"state": {
"_dom_classes": [
"widget-interact"
],
"children": [
"IPY_MODEL_fa9756485234429c89e4e7f7d53d4c87",
"IPY_MODEL_910a2aa7c10746099b4cd2950d81ec40"
],
"layout": "IPY_MODEL_c33a8b99028b44548f1320b9706a4a38"
}
},
"1f045f9850a54de5bfc8844d7a0af224": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletMapStyleModel",
"state": {
"_model_module_version": "^0.17"
}
},
"357155de691f46c0b3b0ecc9f72fc737": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {}
},
"44f7b0f17450444abb2c337d9f55b6a3": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletGeoJSONModel",
"state": {
"_model_module_version": "^0.17",
"_view_module_version": "^0.17",
"data": {
"coordinates": [
[
[
-120.014725,
81.9309989
],
[
-119.98935,
81.8970757
],
[
-119.98349,
81.897147
],
[
-119.98326,
81.8968378
],
[
-119.97307,
81.8969618
],
[
-119.907745,
81.7904203
],
[
-119.87456,
81.7360749
],
[
-119.83392,
81.6689169
],
[
-119.8512,
81.6687068
],
[
-119.85118,
81.6686775
],
[
-119.85184,
81.6686696
],
[
-119.74194,
81.4666119
],
[
-119.73891,
81.4666488
],
[
-119.73883,
81.4665012
],
[
-119.72595,
81.4666571
],
[
-119.62312,
81.2390104
],
[
-119.638275,
81.2388263
],
[
-119.638275,
81.2388144
],
[
-119.63887,
81.2388072
],
[
-119.56386,
81.0356683
],
[
-119.561966,
81.0356914
],
[
-119.561966,
81.0356836
],
[
-119.560486,
81.0357015
],
[
-119.560486,
81.0356855
],
[
-119.55936,
81.0356991
],
[
-119.55928,
81.0354903
],
[
-119.557236,
81.0355152
],
[
-119.55719,
81.0354205
],
[
-119.54927,
81.0355168
],
[
-119.52269,
80.9513654
],
[
-122.69284,
80.9292576
],
[
-123.37811,
81.907481
],
[
-120.014725,
81.9309989
]
]
],
"type": "Polygon"
}
}
},
"5f7efb5c05954e61a1adbceb55630b08": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletMapStyleModel",
"state": {
"_model_module_version": "^0.17",
"cursor": "move"
}
},
"6643fd404b8249a0b9007152874878b2": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletAttributionControlModel",
"state": {
"_model_module_version": "^0.17",
"_view_module_version": "^0.17",
"options": [
"position",
"prefix"
],
"position": "bottomright",
"prefix": "ipyleaflet"
}
},
"910a2aa7c10746099b4cd2950d81ec40": {
"model_module": "@jupyter-widgets/output",
"model_module_version": "1.0.0",
"model_name": "OutputModel",
"state": {
"layout": "IPY_MODEL_357155de691f46c0b3b0ecc9f72fc737",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "S2B_MSIL2A_20230401T001159_R059_T11XML_20230401T021155 2023-04-01T00:11:59.024000+00:00\n"
}
]
}
},
"9a4f8c3b1f5e45b4accdcb9cb878c804": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletZoomControlModel",
"state": {
"_model_module_version": "^0.17",
"_view_module_version": "^0.17",
"options": [
"position",
"zoom_in_text",
"zoom_in_title",
"zoom_out_text",
"zoom_out_title"
]
}
},
"ad9d4313936341518379e3cfd35669de": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {
"width": "600px"
}
},
"b059336a79ba4feebe8fb5998c1d9964": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {}
},
"c33a8b99028b44548f1320b9706a4a38": {
"model_module": "@jupyter-widgets/base",
"model_module_version": "2.0.0",
"model_name": "LayoutModel",
"state": {}
},
"c6a3ba0a758c447e869f32911c82499a": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "DescriptionStyleModel",
"state": {
"description_width": ""
}
},
"c842ff06f33b4f3b974414cc1b560139": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletTileLayerModel",
"state": {
"_model_module_version": "^0.17",
"_view_module_version": "^0.17",
"attribution": "© OpenStreetMap contributors",
"base": true,
"max_zoom": 19,
"min_zoom": 1,
"name": "OpenStreetMap.Mapnik",
"options": [
"attribution",
"bounds",
"detect_retina",
"max_native_zoom",
"max_zoom",
"min_native_zoom",
"min_zoom",
"no_wrap",
"tile_size",
"tms",
"zoom_offset"
],
"url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
}
},
"f49b471ca604492c89276c024afef378": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletMapStyleModel",
"state": {
"_model_module_version": "^0.17"
}
},
"f6a553236d5b4dfe91733eb58e6a2171": {
"model_module": "jupyter-leaflet",
"model_module_version": "^0.17",
"model_name": "LeafletMapModel",
"state": {
"_model_module_version": "^0.17",
"_view_module_version": "^0.17",
"bottom": 379,
"center": [
81.43518005032495,
-121.3895405831003
],
"controls": [
"IPY_MODEL_9a4f8c3b1f5e45b4accdcb9cb878c804",
"IPY_MODEL_6643fd404b8249a0b9007152874878b2"
],
"default_style": "IPY_MODEL_1f045f9850a54de5bfc8844d7a0af224",
"dragging_style": "IPY_MODEL_5f7efb5c05954e61a1adbceb55630b08",
"east": -68.73046875000001,
"fullscreen": false,
"interpolation": "bilinear",
"layers": [
"IPY_MODEL_c842ff06f33b4f3b974414cc1b560139",
"IPY_MODEL_44f7b0f17450444abb2c337d9f55b6a3"
],
"layout": "IPY_MODEL_ad9d4313936341518379e3cfd35669de",
"left": 33,
"modisdate": "2023-05-03",
"north": 85.35956800800716,
"options": [
"bounce_at_zoom_limits",
"box_zoom",
"center",
"close_popup_on_click",
"double_click_zoom",
"dragging",
"fullscreen",
"inertia",
"inertia_deceleration",
"inertia_max_speed",
"interpolation",
"keyboard",
"keyboard_pan_offset",
"keyboard_zoom_offset",
"max_zoom",
"min_zoom",
"prefer_canvas",
"scroll_wheel_zoom",
"tap",
"tap_tolerance",
"touch_zoom",
"world_copy_jump",
"zoom",
"zoom_animation_threshold",
"zoom_delta",
"zoom_snap"
],
"prefer_canvas": false,
"right": 633,
"south": 74.25973837093132,
"style": "IPY_MODEL_f49b471ca604492c89276c024afef378",
"top": -21,
"west": -174.19921875000003,
"window_url": "https://pcc-staging.westeurope.cloudapp.azure.com/compute/user/taugspurger@microsoft.com/lab/tree/PlanetaryComputerExamples/tutorials/interactive-browser.ipynb",
"zoom": 3
}
},
"fa9756485234429c89e4e7f7d53d4c87": {
"model_module": "@jupyter-widgets/controls",
"model_module_version": "2.0.0",
"model_name": "DropdownModel",
"state": {
"_options_labels": [
"- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- ",
"
- "
],
"description": "item",
"index": 0,
"layout": "IPY_MODEL_b059336a79ba4feebe8fb5998c1d9964",
"style": "IPY_MODEL_c6a3ba0a758c447e869f32911c82499a"
}
}
},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}