{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# SlideRule API: Interactive Widget\n", "\n", "SlideRule is an on-demand science data processing service that runs in on Amazon Web Services and responds to REST API calls to process and return science results. SlideRule was designed to enable researchers and other data systems to have low-latency access to custom-generated, high-level, analysis-ready data products using processing parameters supplied at the time of the request. \n", "\n", "The SlideRule ICESat-2 plug-in is a cloud-optimized version of the [ATL06 algorithm](https://nsidc.org/sites/nsidc.org/files/technical-references/ICESat2_ATL06_ATBD_r005.pdf) that can process the lower-level [ATL03 geolocated photon height data products](https://nsidc.org/data/atl03) hosted on AWS by the NSIDC DAAC. \n", "\n", "[Documentation for using SlideRule](https://slideruleearth.io/rtd) is available from the [project website](https://slideruleearth.io) \n", "\n", "### Background\n", "SlideRule creates a simplified version of the [ICESat-2 ATL06 land ice height product](https://nsidc.org/data/atl06) that can be adjusted to suit different needs. SlideRule let's you create customized ICESat-2 segment heights _directly_ from the photon height data anywhere on the globe, _on-demand_ and quickly.\n", "\n", "### Jupyter and SlideRule\n", "[Jupyter widgets](https://ipywidgets.readthedocs.io) are used to set parameters for the SlideRule API. \n", "\n", "Regions of interest for submitting to SlideRule are drawn on a [ipyleaflet](https://ipyleaflet.readthedocs.io) map. \n", "The results from SlideRule can be displayed on the interactive [ipyleaflet](https://ipyleaflet.readthedocs.io) map along with additional contextual layers." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Load necessary packages" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sliderule import icesat2, ipysliderule, io\n", "import ipywidgets as widgets\n", "import logging\n", "import warnings\n", "# autoreload\n", "%load_ext autoreload\n", "%autoreload 2\n", "# turn off warnings for demo\n", "warnings.filterwarnings('ignore')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Initiate SlideRule API\n", "- Sets the URL for accessing the SlideRule service\n", "- Builds a table of servers available for processing data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# set the url for the sliderule service\n", "# set the logging level\n", "icesat2.init(\"slideruleearth.io\", loglevel=logging.WARNING)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Set options for making science data processing requests to SlideRule\n", "\n", "SlideRule follows a streamlined version of the [ATL06 land ice height algorithm](https://nsidc.org/sites/nsidc.org/files/technical-references/ICESat2_ATL06_ATBD_r005.pdf).\n", "\n", "SlideRule also can use different sources for photon classification before calculating the average segment height. \n", "This is useful for example, in cases where there may be a vegetated canopy affecting the spread of the photon returns.\n", "- ATL03 photon confidence values, based on algorithm-specific classification types for land, ocean, sea-ice, land-ice, or inland water\n", "- [ATL08 Land and Vegetation Height product](https://nsidc.org/data/atl08) photon classification\n", "- Experimental YAPC (Yet Another Photon Classification) photon-density-based classification" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# display widgets for setting SlideRule parameters\n", "SRwidgets = ipysliderule.widgets()\n", "widgets.VBox([\n", " SRwidgets.asset,\n", " SRwidgets.release,\n", " SRwidgets.classification,\n", " SRwidgets.surface_type,\n", " SRwidgets.confidence,\n", " SRwidgets.quality,\n", " SRwidgets.land_class,\n", " SRwidgets.yapc_knn,\n", " SRwidgets.yapc_win_h,\n", " SRwidgets.yapc_win_x,\n", " SRwidgets.yapc_min_ph,\n", " SRwidgets.yapc_weight,\n", " SRwidgets.length,\n", " SRwidgets.step,\n", " SRwidgets.iteration,\n", " SRwidgets.spread,\n", " SRwidgets.count,\n", " SRwidgets.window,\n", " SRwidgets.sigma,\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Interactive Mapping with Leaflet\n", "\n", "Interactive maps within the SlideRule python API are built upon [ipyleaflet](https://ipyleaflet.readthedocs.io).\n", "\n", "#### Leaflet Basemaps and Layers\n", "\n", "There are 3 projections available within SlideRule for mapping ([Global](https://epsg.io/3857), [North](https://epsg.io/5936) and [South](https://epsg.io/3031)). There are also contextual layers available for each projection.\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Global (Web Mercator, EPSG:3857)North (Alaska Polar Stereographic, EPSG:5936)South (Antarctic Polar Stereographic, EPSG:3031)
\n", " \n", " \n", " \n", " \n", " \n", "
\n", "\n", "In addition, most [xyzservice providers](https://xyzservices.readthedocs.io/en/stable/introduction.html) can be added as contextual layers to the global Web Mercator maps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "widgets.VBox([\n", " SRwidgets.projection,\n", " SRwidgets.layers,\n", " SRwidgets.raster_functions\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Select regions of interest for submitting to SlideRule\n", "\n", "Here, we create polygons or bounding boxes for our regions of interest. \n", "This map is also our viewer for inspecting our SlideRule ICESat-2 data returns." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# create ipyleaflet map in specified projection\n", "m = ipysliderule.leaflet(SRwidgets.projection.value)\n", "# install click handler callback\n", "m.add_selected_callback(SRwidgets.atl06_click_handler)\n", "m.map" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m.add_layer(\n", " layers=SRwidgets.layers.value,\n", " rendering_rule=SRwidgets.rendering_rule\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Build and transmit requests to SlideRule\n", "\n", "- SlideRule will query the [NASA Common Metadata Repository (CMR)](https://cmr.earthdata.nasa.gov/) for ATL03 data within our region of interest\n", "- When using the `nsidc-s3` asset, the ICESat-2 ATL03 data are then accessed from the NSIDC AWS s3 bucket in `us-west-2`\n", "- The ATL03 granules is spatially subset within SlideRule to our exact region of interest\n", "- SlideRule then uses our specified parameters to calculate average height segments from the ATL03 data in parallel\n", "- The completed data is streamed concurrently back and combined into a geopandas GeoDataFrame within the Python client" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "# sliderule asset and data release\n", "asset = SRwidgets.asset.value\n", "release = SRwidgets.release.value\n", "# build sliderule parameters using latest values from widget\n", "parms = SRwidgets.build_atl06()\n", "\n", "# create an empty geodataframe\n", "gdf = icesat2.__emptyframe()\n", "\n", "# for each region of interest\n", "for poly in m.regions:\n", " # add polygon from map to sliderule parameters\n", " parms[\"poly\"] = poly \n", " # make the request to the SlideRule (ATL06-SR) endpoint\n", " # and pass it the request parameters to request ATL06 Data\n", " gdf = gdf.append(icesat2.atl06p(parms, asset, version=release))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Review GeoDataFrame output\n", "Can inspect the columns, number of returns and returns at the top of the GeoDataFrame.\n", "\n", "See the [ICESat-2 documentation](https://slideruleearth.io/rtd/user_guide/ICESat-2.html#elevations) for descriptions of each column" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f'Returned {gdf.shape[0]} records')\n", "gdf.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Add GeoDataFrame to map\n", "\n", "For stability of the leaflet map, SlideRule will as a default limit the plot to have up to 10000 points from the GeoDataFrame\n", "\n", "GeoDataFrames can be plotted in any available [matplotlib colormap](https://matplotlib.org/stable/tutorials/colors/colormaps.html)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "widgets.VBox([\n", " SRwidgets.variable,\n", " SRwidgets.cmap,\n", " SRwidgets.reverse,\n", "])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "# ATL06-SR fields for hover tooltip\n", "fields = m.default_atl06_fields()\n", "m.GeoData(gdf, column_name=SRwidgets.variable.value, cmap=SRwidgets.colormap,\n", " max_plot_points=10000, tooltip=True, colorbar=True, fields=fields)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create plots for a single track\n", "- cycles: Will plot all available cycles of data returned by SlideRule for a single RGT and ground track\n", "- scatter: Will plot data returned by SlideRule for a single RGT, ground track and cycle\n", "- (to select a track from the leaflet plot above, click on one of the plotted elevations and the RGT and Cycle will automatically get populated below)\n", "\n", "The cycles plots should only be used in regions with [repeat Reference Ground Track (RGT) pointing](https://icesat-2.gsfc.nasa.gov/science/specs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "widgets.VBox([\n", " SRwidgets.plot_kind,\n", " SRwidgets.rgt,\n", " SRwidgets.ground_track,\n", " SRwidgets.cycle,\n", "])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "# default is to skip cycles with significant off-pointing\n", "SRwidgets.plot(gdf, kind=SRwidgets.plot_kind.value, cycle_start=3,\n", " legend=True, legend_frameon=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Save GeoDataFrame to output file\n", "- [pytables HDF5](https://www.pytables.org/): easily read back as a Geopandas GeoDataFrame\n", "- [netCDF](https://www.unidata.ucar.edu/software/netcdf): interoperable with other programs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display(SRwidgets.filesaver)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# append sliderule api version to attributes\n", "version = icesat2.get_version()\n", "parms['version'] = version['icesat2']['version']\n", "parms['commit'] = version['icesat2']['commit']\n", "# save to file in format (HDF5 or netCDF)\n", "io.to_file(gdf, SRwidgets.file,\n", " format=SRwidgets.format,\n", " driver='pytables',\n", " parameters=parms,\n", " regions=m.regions,\n", " verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Read GeoDataFrame from input file\n", "- [pytables HDF5](https://www.pytables.org/)\n", "- [netCDF](https://www.unidata.ucar.edu/software/netcdf)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display(SRwidgets.fileloader)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# read from file in format (HDF5 or netCDF)\n", "gdf,parms,regions = io.from_file(SRwidgets.file,\n", " format=SRwidgets.format,\n", " driver='pytables',\n", " return_parameters=True,\n", " return_regions=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Review GeoDataFrame input from file" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gdf.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Set parameters and add saved regions to map" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SRwidgets.set_values(parms)\n", "m.add_region(regions)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" }, "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.8.13" } }, "nbformat": 4, "nbformat_minor": 4 }