Skip to content

Commit 48ba65b

Browse files
Merge pull request #102 from stac-utils/add_tutorials
Add notebook tutorials
2 parents 238b215 + 16fafce commit 48ba65b

File tree

4 files changed

+467
-39
lines changed

4 files changed

+467
-39
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9+
### Added
10+
- Jupyter Notebook tutorials
11+
912
### Changed
1013

1114
- Improved performance when constructing `pystac.ItemCollection` objects.

docs/tutorials.rst

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,13 @@ PySTAC-Client Introduction
99
- :tutorial:`GitHub version <pystac-client-introduction.ipynb>`
1010
- :ref:`Docs version </tutorials/pystac-client-introduction.ipynb>`
1111

12-
This tutorial gives an introduction to PySTAC-Client concepts through code examples.
12+
This tutorial gives an introduction to using pystac-client with a STAC API
13+
14+
STAC Metadata Visualization
15+
---------------------------
16+
17+
- :tutorial:`GitHub version <stac-metadata-viz.ipynb>`
18+
- :ref:`Docs version </tutorials/stac-metadata-viz.ipynb>`
19+
20+
This tutorial gives an introduction to using Holeviews and hvplot to visualize
21+
STAC metadata and Item geometries on a map.

docs/tutorials/pystac-client-introduction.ipynb

+195-38
Original file line numberDiff line numberDiff line change
@@ -2,83 +2,240 @@
22
"cells": [
33
{
44
"cell_type": "markdown",
5+
"id": "e06a27bf",
6+
"metadata": {},
57
"source": [
6-
"# pystac-client Tutorial\n",
7-
"\n"
8-
],
9-
"metadata": {}
8+
"# pystac-client Introduction\n",
9+
"\n",
10+
"This notebook shows basic use of pystac-client to open an API, iterate through Collections and Items, and perform simple spatio-temporal searches."
11+
]
1012
},
1113
{
1214
"cell_type": "code",
1315
"execution_count": null,
14-
"source": [
15-
"import pystac\n",
16-
"from pystac_client import Client"
17-
],
16+
"id": "b65de617",
17+
"metadata": {},
1818
"outputs": [],
19-
"metadata": {}
19+
"source": [
20+
"from pystac_client import Client\n",
21+
"\n",
22+
"# set pystac_client logger to DEBUG to see API calls\n",
23+
"import logging\n",
24+
"logging.basicConfig()\n",
25+
"logger = logging.getLogger('pystac_client')\n",
26+
"logger.setLevel(logging.DEBUG)"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"id": "1e16077c",
32+
"metadata": {},
33+
"source": [
34+
"# Client\n",
35+
"\n",
36+
"We first connect to an API by retrieving the root catalog, or landing page, of the API with the `Client.open` function."
37+
]
2038
},
2139
{
2240
"cell_type": "code",
2341
"execution_count": null,
42+
"id": "98942e75",
43+
"metadata": {},
44+
"outputs": [],
2445
"source": [
25-
"# public STAC URLs\n",
26-
"\n",
27-
"PC_URL = 'https://planetarycomputer.microsoft.com/api/stac/v1'\n",
28-
"CMR_URL = 'https://cmr.earthdata.nasa.gov/stac'\n",
46+
"# STAC API root URL\n",
47+
"URL = 'https://planetarycomputer.microsoft.com/api/stac/v1'\n",
2948
"\n",
3049
"# custom headers\n",
31-
"headers = []"
32-
],
33-
"outputs": [],
34-
"metadata": {}
50+
"headers = []\n",
51+
"\n",
52+
"cat = Client.open(URL, headers=headers)\n",
53+
"cat"
54+
]
55+
},
56+
{
57+
"cell_type": "markdown",
58+
"id": "f6efbb86",
59+
"metadata": {},
60+
"source": [
61+
"# CollectionClient\n",
62+
"\n",
63+
"As with a static catalog the `get_collections` function will iterate through the Collections in the Catalog. Notice that because this is an API it can get all the Collections through a single call, rather than having to fetch each one individually."
64+
]
3565
},
3666
{
3767
"cell_type": "code",
3868
"execution_count": null,
39-
"source": [
40-
"cat = Client.open(CMR_URL, headers=headers)"
41-
],
69+
"id": "bb7693fb",
70+
"metadata": {},
4271
"outputs": [],
43-
"metadata": {}
72+
"source": [
73+
"for collection in cat.get_collections():\n",
74+
" print(collection)"
75+
]
4476
},
4577
{
4678
"cell_type": "code",
4779
"execution_count": null,
48-
"source": [
49-
"print(cat)"
50-
],
80+
"id": "fef20a46",
81+
"metadata": {},
5182
"outputs": [],
52-
"metadata": {}
83+
"source": [
84+
"collection = cat.get_collection('aster-l1t')\n",
85+
"collection"
86+
]
87+
},
88+
{
89+
"cell_type": "markdown",
90+
"id": "47a540fe",
91+
"metadata": {},
92+
"source": [
93+
"# Items\n",
94+
"\n",
95+
"The main functions for getting items return iterators, where pystac-client will handle retrieval of additional pages when needed. Note that one request is made for the first ten items, then a second request for the next ten."
96+
]
5397
},
5498
{
5599
"cell_type": "code",
56100
"execution_count": null,
57-
"source": [
58-
"for kitten in cat.get_children():\n",
59-
" print(kitten)"
60-
],
101+
"id": "17d6de4b",
102+
"metadata": {},
61103
"outputs": [],
62-
"metadata": {}
104+
"source": [
105+
"items = collection.get_items()\n",
106+
"\n",
107+
"# flush stdout so we can see the exact order that things happen\n",
108+
"def get_ten_items(items):\n",
109+
" for i, item in enumerate(items):\n",
110+
" print(f\"{i}: {item}\", flush=True)\n",
111+
" if i == 9:\n",
112+
" return\n",
113+
"\n",
114+
"print('First page', flush=True)\n",
115+
"get_ten_items(items)\n",
116+
"\n",
117+
"print('Second page', flush=True)\n",
118+
"get_ten_items(items)"
119+
]
120+
},
121+
{
122+
"cell_type": "markdown",
123+
"id": "62e26114",
124+
"metadata": {},
125+
"source": [
126+
"# API Search\n",
127+
"\n",
128+
"If the Catalog is an API, we have the ability to search for items based on spatio-temporal properties."
129+
]
63130
},
64131
{
65132
"cell_type": "code",
66133
"execution_count": null,
134+
"id": "d8af6334",
135+
"metadata": {},
136+
"outputs": [],
67137
"source": [
68-
"cat = Client.open('https://cmr.earthdata.nasa.gov/stac/ASF')"
69-
],
138+
"# AOI around Delfzijl, in northern Netherlands\n",
139+
"geom = {\n",
140+
" \"type\": \"Polygon\",\n",
141+
" \"coordinates\": [\n",
142+
" [\n",
143+
" [\n",
144+
" 6.42425537109375,\n",
145+
" 53.174765470134616\n",
146+
" ],\n",
147+
" [\n",
148+
" 7.344360351562499,\n",
149+
" 53.174765470134616\n",
150+
" ],\n",
151+
" [\n",
152+
" 7.344360351562499,\n",
153+
" 53.67393435835391\n",
154+
" ],\n",
155+
" [\n",
156+
" 6.42425537109375,\n",
157+
" 53.67393435835391\n",
158+
" ],\n",
159+
" [\n",
160+
" 6.42425537109375,\n",
161+
" 53.174765470134616\n",
162+
" ]\n",
163+
" ]\n",
164+
" ]\n",
165+
"}\n",
166+
"\n",
167+
"# limit sets the # of items per page so we can see multiple pages getting fetched\n",
168+
"search = cat.search(\n",
169+
" collections = \"aster-l1t\",\n",
170+
" intersects = geom,\n",
171+
" datetime = \"2000-01-01/2010-12-31\",\n",
172+
" max_items = 15,\n",
173+
" limit = 5\n",
174+
")\n",
175+
"\n",
176+
"# PySTAC ItemCollection\n",
177+
"items = search.get_all_items()\n",
178+
"\n",
179+
"# Dictionary (GeoJSON FeatureCollection)\n",
180+
"item_json = items.to_dict()\n",
181+
"\n",
182+
"len(items)"
183+
]
184+
},
185+
{
186+
"cell_type": "code",
187+
"execution_count": null,
188+
"id": "275f316f",
189+
"metadata": {},
70190
"outputs": [],
71-
"metadata": {}
191+
"source": [
192+
"# note that this will work in JupyterLab, but not in a Jupyter Notebook\n",
193+
"\n",
194+
"import IPython.display\n",
195+
"IPython.display.JSON(item_json)"
196+
]
72197
},
73198
{
74199
"cell_type": "code",
75200
"execution_count": null,
201+
"id": "68bf65f2",
202+
"metadata": {},
203+
"outputs": [],
76204
"source": [
77-
"for col in cat.get_collections():\n",
78-
" print(col)"
79-
],
205+
"# this cell can be used in Jupyter Notebook. Use above if using JupyterLab\n",
206+
"\n",
207+
"import json\n",
208+
"import uuid\n",
209+
"from IPython.display import display_javascript, display_html, display\n",
210+
"\n",
211+
"class RenderJSON(object):\n",
212+
" def __init__(self, json_data):\n",
213+
" if isinstance(json_data, dict) or isinstance(json_data, list):\n",
214+
" self.json_str = json.dumps(json_data)\n",
215+
" else:\n",
216+
" self.json_str = json_data\n",
217+
" self.uuid = str(uuid.uuid4())\n",
218+
"\n",
219+
" def _ipython_display_(self):\n",
220+
" display_html('<div id=\"{}\" style=\"height: 600px; width:100%;font: 12px/18px monospace !important;\"></div>'.format(self.uuid), raw=True)\n",
221+
" display_javascript(\"\"\"\n",
222+
" require([\"https://rawgit.com/caldwell/renderjson/master/renderjson.js\"], function() {\n",
223+
" renderjson.set_show_to_level(2);\n",
224+
" document.getElementById('%s').appendChild(renderjson(%s))\n",
225+
" });\n",
226+
" \"\"\" % (self.uuid, self.json_str), raw=True)\n",
227+
"\n",
228+
"\n",
229+
"RenderJSON(item_json)"
230+
]
231+
},
232+
{
233+
"cell_type": "code",
234+
"execution_count": null,
235+
"id": "93d65ed4",
236+
"metadata": {},
80237
"outputs": [],
81-
"metadata": {}
238+
"source": []
82239
}
83240
],
84241
"metadata": {
@@ -102,4 +259,4 @@
102259
},
103260
"nbformat": 4,
104261
"nbformat_minor": 5
105-
}
262+
}

0 commit comments

Comments
 (0)