{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualizing STAC Data Layers using stac_ipyleaflet (beta)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Authors: Emma Paz (Development Seed)\n", "\n", "Date: May 10, 2023\n", "\n", "Description: This project - **stac_ipyleafet** - leverages the [ipyleaflet](https://pypi.org/project/ipyleaflet/) mapping library and is intended to reduce the code needed to visualize data from the [MAAP STAC](../search/searching_the_stac_catalog.ipynb). The beta version supports Cloud-Optimized GeoTIFFs (COGs).\n", "\n", "Currently, this package works within [this Algorithm Development Environment](https://ade.maap-project.org/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Run This Notebook\n", "To access and run this tutorial within MAAP's Algorithm Development Environment (ADE), please refer to the [\"Getting started with the MAAP\"](https://docs.maap-project.org/en/latest/getting_started/getting_started.html) section of our documentation.\n", "\n", "Disclaimer: it is recommended to run this tutorial within MAAP's ADE **Pangeo workspace**, which already includes the stac_ipyleaflet package." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional Resources\n", "- stac_ipyleafet DOI: [10.5281/zenodo.10015863](https://doi.org/10.5281/zenodo.10015863)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Importing and Installing Packages\n", "\n", "Selecting a new **PANGEO workspace**\n", "\n", "![ade workspace](../../_static/stac_ipyleaflet_workspace.png)\n", "\n", "or alternatively, you may install stac_ipyleaflet into your environment by uncommenting the install in the following cell:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# NOTE: This has only been tested in the **MAAP Basic Stable (Vanilla)** environment.\n", "\n", "# %pip install git+https://github.com/MAAP-Project/stac_ipyleaflet.git#egg-info=stac_ipyleaflet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import stac_ipyleaflet\n", "m = stac_ipyleaflet.StacIpyleaflet()\n", "m" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![stac_ipyleaflet mapview](../../_static/stac_ipyleaflet_main.png)\n", "\n", "The **stac ipyleaflet** notebook's user interface consists of a map and a custom set of tools to aid in the discovery and visualization of STAC datasets, along with Biomass Layers and pre-determined Basemaps.\n", "\n", "***" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## Map Navigation\n", "\n", "### Move the Map\n", "- press and hold a mouse-click, then drag the map\n", "\n", "### Adjust the Map's Scale (Zoom Extent) - 1 of 4 Methods:\n", "- click the Zoom In / Out buttons in the top left-corner (this will maintain the center)\n", "- use your mouse's scroll-wheel - hovering over an area of interest\n", "- double-click within the map on an area of interest\n", "- while pressing the `shift` key on your keyboard, press and hold a mouse-click, then drag to draw a rectangle around the area of interest\n", "\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Layers Tool\n", "\n", "Pressing the Layers button at the top opens the **Layers widget** that consists of 2 tabs. This tool currently allows users to:\n", "- View one or more **[Biomass Layers](https://www.earthdata.nasa.gov/maap-biomass/)** at the same time to see different combinations.\n", "- Choose between common **Basemap Layers** that are known favorites.\n", "- Have full control over the **opacity** of any layer or basemap for fine-tuning how the map looks.\n", "\n", "### The Layers Tab\n", "- Toggle each layer's visibility by using its checkbox\n", "- Adjust each layer's opacity by moving its slider\n", "\n", "![stac_ipyleaflet layers widget](../../_static/stac_ipyleaflet_layers.png)\n", "\n", "### The Basemaps Tab\n", "- Select a basemap from the dropdown\n", "- Adjust the basemap's opacity by moving its slider\n", "\n", "![stac_ipyleaflet basemap widget](../../_static/stac_ipyleaflet_basemaps.png)\n", "\n", "***" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## STAC Discovery Tool\n", "Pressing the STAC Data button at the top opens the **STAC widget** that consists of 2 tabs. This tool currently allows users to:\n", "- **Connect** to the [MAAP STAC](https://stac-browser.maap-project.org) to access collections of mission data.\n", "- **Discover** items per the selected collection, including description, available dates, & direct URL.\n", "- **Identify** valid COG datasets.\n", "- **Add COG tiles** dynamically to the map.\n", "- **Customize** the tiles by changing the selected color palette for the selected item.\n", "\n", "\n", "### The Catalog Data Discovery Tab\n", "- Select a Collection within the default STAC library.\n", "\n", "![stac_ipyleaflet stac widget](../../_static/stac_ipyleaflet_stac.png)\n", "\n", "- Browse through the Collection's details.\n", "\n", "![stac_ipyleaflet details](../../_static/stac_ipyleaflet_details.png)\n", "\n", "- Select an item from the collection to check if it is a valid COG. If it is, the Display button will become active (available) to add the selected item to the map. The displayed STAC layer's opacity can be adjusted by moving its slider.\n", "\n", "![stac_ipyleaflet items](../../_static/stac_ipyleaflet_items.png)\n", "\n", "\n", "### The Visualization Tab\n", "- Select a category from the dropdown.\n", "- Select an item from the corresponding color palettes.\n", "- Press the Display button to update the data on the map.\n", "\n", "![stac_ipyleaflet color palettes](../../_static/stac_ipyleaflet_colors.png)\n", "\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interact with the Map\n", "\n", "1. **Activate the Interact Tools** (click on the top _Interact_ button)\n", "2. From within the `Point` tab: **Use your mouse** to activate the Point tool; then click on the map at a location of interest\n", " - **Coordinates** will be printed within the open tab\n", " - **Raster cell values** will be identified and printed, if raster layers are on\n", "3. From within the `Area` tab: **Use your mouse** to activate the Polygon tool; then click, hold and draw a polygon over the map - releasing to finish\n", " - The area of interest's **Coordinates & BBox** within the open tab\n", " - Alternatively **Print** the area of interest's bbox from within a cell: \n", " ![stac_ipyleaflet aoi bbox](../../_static/stac_ipyleaflet_bbox.png)\n", "4. **Clear** the point or polygon graphics as needed\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Add a Tile Layer" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import httpx\n", "import json\n", "titiler_url = \"https://titiler.maap-project.org\" # MAAP titiler endpoint\n", "titiler_tilejson_url = f\"{titiler_url}/cog/tilejson.json\"\n", "band_min = 0\n", "band_max = 400\n", "bidx = 1\n", "colormap_name = 'gist_earth_r'\n", "data_url = f\"s3://maap-ops-workspace/shared/alexdevseed/landsat8/viz/Copernicus_30439_covars_cog_topo_stack.tif\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create TileLayer" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TileLayer(options=['attribution', 'bounds', 'detect_retina', 'max_native_zoom', 'max_zoom', 'min_native_zoom', 'min_zoom', 'no_wrap', 'tile_size', 'tms', 'zoom_offset'], show_loading=True, url='https://titiler.maap-project.org/cog/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?url=s3%3A%2F%2Fmaap-ops-workspace%2Fshared%2Falexdevseed%2Flandsat8%2Fviz%2FCopernicus_30439_covars_cog_topo_stack.tif&bidx=1&rescale=0%2C+400&pixel_selection=first&resampling_method=nearest&colormap_name=gist_earth_r')\n" ] } ], "source": [ "from ipyleaflet import TileLayer\n", "\n", "params = {\n", " \"url\": data_url, \n", " \"bidx\": bidx,\n", " \"rescale\": f\"{band_min}, {band_max}\", \n", " \"pixel_selection\": \"first\",\n", " \"resampling_method\": \"nearest\",\n", " \"colormap_name\": colormap_name\n", "}\n", "r = httpx.get(titiler_tilejson_url, params = params).json()\n", "\n", "custom_layer = TileLayer(url=r[\"tiles\"][0], show_loading=True, visible=True)\n", "# print(custom_layer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Get Tile Layer info & calculate center" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bounds: [-163.51338693693168, 67.17121197506852, -162.6566451826878, 67.49580310072406]\n", "Zoom: 8\n", "Data type: float32\n", "Bands: [['b1', {}], ['b2', {}], ['b3', {}], ['b4', {}], ['b5', {}]]\n" ] } ], "source": [ "r = httpx.get(\n", " f\"{titiler_url}/cog/info\",\n", " params = {\n", " \"url\": data_url,\n", " }\n", ").json()\n", "\n", "# print(json.dumps(r, indent=4))\n", "\n", "bounds = r.get(\"bounds\")\n", "minzoom = r.get(\"minzoom\")\n", "zoom = minzoom + 1 if minzoom == 0 else minzoom\n", "bands = r.get(\"band_metadata\")\n", "\n", "print(\"Bounds:\", bounds)\n", "print(\"Zoom:\", zoom)\n", "print(\"Data type:\", r.get(\"dtype\"))\n", "print(\"Bands:\", bands)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Center: (67.33350753789628, -163.0850160598097)\n" ] } ], "source": [ "from shapely.geometry import box\n", "\n", "polygon = box(*bounds)\n", "center = (polygon.centroid.y, polygon.centroid.x)\n", "print(\"Center:\", center)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# import stac_ipyleaflet\n", "\n", "m = stac_ipyleaflet.StacIpyleaflet(zoom=zoom, center=center)\n", "m.add_layer(custom_layer)\n", "m" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![stac_ipyleaflet added layer](../../_static/stac_ipyleaflet_add_single_layer.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Option to remove custom layer\n", "`m.remove_layer(custom_layer)`" ] } ], "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.12" }, "vscode": { "interpreter": { "hash": "5c7b89af1651d0b8571dde13640ecdccf7d5a6204171d6ab33e7c296e100e08a" } } }, "nbformat": 4, "nbformat_minor": 4 }