Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AOI example #212

Merged
merged 11 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ STAC Versions
+---------------+-----------+-----------------------------+
| pystac-client | STAC spec | STAC API Spec |
+===============+===========+=============================+
| 0.4.x | 1.0.x | 1.0.0-beta.1 - 1.0.0-rc.1 |
+---------------+-----------+-----------------------------+
| 0.3.x | 1.0.x | 1.0.0-beta.1 - 1.0.0-beta.4 |
+---------------+-----------+-----------------------------+
| 0.2.x | 1.0.x | 1.0.0-beta.1 - 1.0.0-beta.2 |
Expand Down
13 changes: 12 additions & 1 deletion docs/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@ STAC Metadata Visualization
This tutorial gives an introduction to using Holeviews and hvplot to visualize
STAC metadata and Item geometries on a map.

CQL Filtering
CQL2 Filtering
---------------------------

- :tutorial:`GitHub version <cql2-filter.ipynb>`
- :ref:`Docs version </tutorials/cql2-filter.ipynb>`
philvarner marked this conversation as resolved.
Show resolved Hide resolved

This tutorial gives an introduction to using CQL-JSON filtering in searches to
search by arbitrary STAC Item properties.

Calculating Coverage Percentage of the AOI by an Item
-----------------------------------------------------

- :tutorial:`GitHub version <aoi-coverage.ipynb>`
philvarner marked this conversation as resolved.
Show resolved Hide resolved
- :ref:`Docs version </tutorials/aoi-coverage.ipynb>`

This tutorial demonstrates the use of pystac-client to calculate the
percentage an Item's geometry that intesects with the area of interest
(AOI) specified in the search by the `intersects` parameter.
150 changes: 150 additions & 0 deletions docs/tutorials/aoi-coverage.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e06a27bf",
"metadata": {},
"source": [
"# Calculating Coverage Percentage of the AOI by an Item\n",
"\n",
"This notebook demonstrates the use of pystac-client to calculate the percentage an Item's geometry that intesects with the area of interest (AOI) specified in the search by the `intersects` parameter."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b65de617",
"metadata": {},
"outputs": [],
"source": [
"from pystac_client import Client\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from shapely.geometry import shape\n",
"from pystac_client import Client\n",
"from pystac.item import Item\n",
"from typing import Dict, Any"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "98942e75",
"metadata": {},
"outputs": [],
"source": [
"def intersection_percent(item: Item, aoi: Dict[str, Any]) -> float:\n",
" '''The percentage that the Item's geometry intersects the AOI. An Item that\n",
" completely covers the AOI has a value of 100.\n",
" '''\n",
" geom_item = shape(item.geometry)\n",
" geom_aoi = shape(aoi)\n",
"\n",
" intersected_geom = geom_aoi.intersection(geom_item)\n",
"\n",
" intersection_percent = (intersected_geom.area * 100) / geom_aoi.area\n",
"\n",
" return intersection_percent\n",
"\n",
"\n",
"# STAC API root URL\n",
"URL = 'https://planetarycomputer.microsoft.com/api/stac/v1'\n",
"\n",
"# geometry of the AOI to search over\n",
"intersects_geometry = {\n",
" \"type\": \"Polygon\",\n",
" \"coordinates\": [\n",
" [\n",
" [-73.21, 43.99],\n",
" [-73.21, 47.05],\n",
" [-70.12, 47.05],\n",
" [-70.12, 43.99],\n",
" [-73.21, 43.99],\n",
" ]\n",
" ],\n",
"}\n",
"\n",
"# Create a Client and an ItemSearch representing our search\n",
"# No search operations will be performed until we call the items() method\n",
"client = Client.open(URL, ignore_conformance=False)\n",
"item_search = client.search(\n",
" collections=[\"sentinel-2-l2a\"], intersects=intersects_geometry, max_items=100\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0b0883fe",
"metadata": {},
"outputs": [],
"source": [
"print([f\"{intersection_percent(item, intersects_geometry):.2f}\" for item in item_search.items()])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "03254847",
"metadata": {},
"outputs": [],
"source": [
"# create a generator that filters to only those Items that intersect more than 5%\n",
"items_gt_5_percent = (\n",
" i for i in item_search.items() if intersection_percent(i, intersects_geometry) > 5\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1de7a09",
"metadata": {},
"outputs": [],
"source": [
"# Render the AOI and Item results\n",
"# The green shape is the AOI\n",
"# The blue shapes are the Item geometries\n",
"# If there are no blue shapes, adjust the intersection percent filter above until there are\n",
"\n",
"cm = plt.get_cmap('RdBu')\n",
"fig, axs = plt.subplots()\n",
"axs.set_aspect('equal', 'datalim')\n",
"\n",
"for item in items_gt_5_percent:\n",
" xs, ys = shape(item.geometry).exterior.xy\n",
" axs.fill(xs, ys, alpha=0.5, fc='b', ec='none')\n",
"\n",
"geom_intersects = shape(intersects_geometry)\n",
"xs, ys = geom_intersects.exterior.xy\n",
"axs.fill(xs, ys, alpha=0.5, fc='g', ec='none')\n",
"\n",
"plt.show()"
]
}
],
"metadata": {
"interpreter": {
"hash": "6b6313dbab648ff537330b996f33bf845c0da10ea77ae70864d6ca8e2699c7ea"
},
"kernelspec": {
"display_name": "Python 3.9.11 ('.venv': venv)",
"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.9.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
2 changes: 1 addition & 1 deletion docs/tutorials/cql2-filter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "e06a27bf",
"metadata": {},
"source": [
"# pystac-client CQL2 Filtering\n",
"# CQL2 Filtering\n",
"\n",
"This notebook demonstrates the use of pystac-client to use [CQL2 filtering](https://github.com/radiantearth/stac-api-spec/tree/master/fragments/filter). The server needs to support this and advertise conformance as the `https://api.stacspec.org/v1.0.0-rc.1/item-search#filter` class in the `conformsTo` attribute of the root API.\n",
"\n",
Expand Down
25 changes: 10 additions & 15 deletions docs/tutorials/pystac-client-introduction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "e06a27bf",
"metadata": {},
"source": [
"# pystac-client Introduction\n",
"# PySTAC-Client Introduction\n",
"\n",
"This notebook shows basic use of pystac-client to open an API, iterate through Collections and Items, and perform simple spatio-temporal searches."
]
Expand Down Expand Up @@ -175,8 +175,6 @@
"\n",
"items = list(search.items())\n",
"\n",
"item_json = items.to_dict()\n",
"\n",
"len(items)"
]
},
Expand All @@ -190,7 +188,9 @@
"# note that this will work in JupyterLab, but not in a Jupyter Notebook\n",
"\n",
"import IPython.display\n",
"IPython.display.JSON(item_json)"
"\n",
"\n",
"IPython.display.JSON([i.to_dict() for i in items])"
philvarner marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
Expand Down Expand Up @@ -224,21 +224,16 @@
" \"\"\" % (self.uuid, self.json_str), raw=True)\n",
"\n",
"\n",
"RenderJSON(item_json)"
"RenderJSON([i.to_dict() for i in items])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "93d65ed4",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"interpreter": {
"hash": "6b6313dbab648ff537330b996f33bf845c0da10ea77ae70864d6ca8e2699c7ea"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3.9.11 ('.venv': venv)",
"language": "python",
"name": "python3"
},
Expand All @@ -252,7 +247,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.4"
"version": "3.9.11"
}
},
"nbformat": 4,
Expand Down
12 changes: 8 additions & 4 deletions docs/tutorials/stac-metadata-viz.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@
" datetime = \"2000-01-01/2010-12-31\",\n",
")\n",
"\n",
"items = list(search.items())\n",
"# retrieve the items as dictionaries, rather than Item objects\n",
"items = list(search.items_as_dicts())\n",
"len(items)"
]
},
Expand Down Expand Up @@ -174,7 +175,7 @@
"outputs": [],
"source": [
"# convert found items to a GeoDataFrame\n",
"items_gdf = items_to_geodataframe(items.to_dict()['features'])\n",
"items_gdf = items_to_geodataframe(items)\n",
"items_gdf.head()"
]
},
Expand Down Expand Up @@ -273,8 +274,11 @@
}
],
"metadata": {
"interpreter": {
"hash": "6b6313dbab648ff537330b996f33bf845c0da10ea77ae70864d6ca8e2699c7ea"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3.9.11 ('.venv': venv)",
"language": "python",
"name": "python3"
},
Expand All @@ -288,7 +292,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.4"
"version": "3.9.11"
}
},
"nbformat": 4,
Expand Down
10 changes: 5 additions & 5 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ requests to a service's "search" endpoint. This method returns a
.. code-block:: python

>>> from pystac_client import Client
>>> api = Client.from_file('https://planetarycomputer.microsoft.com/api/stac/v1')
>>> api = Client.open('https://planetarycomputer.microsoft.com/api/stac/v1')
>>> results = api.search(
... max_items=5
... bbox=[-73.21, 43.99, -73.12, 44.05],
Expand Down Expand Up @@ -272,16 +272,16 @@ descending sort and a ``+`` prefix or no prefix means an ascending sort.
.. code-block:: python

>>> from pystac_client import Client
>>> results = Client.from_file('https://planetarycomputer.microsoft.com/api/stac/v1').search(
>>> results = Client.open('https://planetarycomputer.microsoft.com/api/stac/v1').search(
... sortby="properties.datetime"
... )
>>> results = Client.from_file('https://planetarycomputer.microsoft.com/api/stac/v1').search(
>>> results = Client.open('https://planetarycomputer.microsoft.com/api/stac/v1').search(
... sortby="-properties.datetime,+id,+collection"
... )
>>> results = Client.from_file('https://planetarycomputer.microsoft.com/api/stac/v1').search(
>>> results = Client.open('https://planetarycomputer.microsoft.com/api/stac/v1').search(
... sortby=["-properties.datetime", "+id" , "+collection" ]
... )
>>> results = Client.from_file('https://planetarycomputer.microsoft.com/api/stac/v1').search(
>>> results = Client.open('https://planetarycomputer.microsoft.com/api/stac/v1').search(
... sortby=[
{"direction": "desc", "field": "properties.datetime"},
{"direction": "asc", "field": "id"},
Expand Down
3 changes: 2 additions & 1 deletion requirements-docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ myst-parser~=0.17.2
nbsphinx~=0.8
jinja2<4.0
geopandas~=0.10.2
hvplot~=0.8.0
hvplot~=0.8.0
matplotlib~=3.5.2