jupyterlab-jstex — STAC explorer for JupyterLab
The package is jupyterlab-jstex; in Python you import jstex.
Find Earth-observation products on a map inside a notebook, then use them in
code. jstex is the light, notebook-native sibling of
STEX, the web EO Data Explorer. It offers collection search,
dates, one area of interest, attribute filters, a results table synchronised
with footprints on the map, and item details. Every result is also a pystac
object in Python.
On a JupyterHub, jstex searches with the signed-in user's own token, so restricted collections just work.
Features
- Search panel beside the map (STEX-like). Drag the divider to resize it,
fold it to an icon rail, or hide the map to work with just the panel and
the results:
- Collections: search by title or id, "only selected", ⓘ for the description, time extent and license.
- Dates and times (UTC): a calendar with a 24-hour time picker, as in
STEX, or type
YYYY-MM-DD [HH:MM]; either end may be left open, and From after To is flagged. - Area of interest: one area. Draw a polygon or a box, or upload GeoJSON; invalid geometries are repaired before searching.
- Attribute filters: built from the collections' queryables (
=,!=,<,<=,>,>=,IN), checked by field type before sending.
- Results ↔ map. Clicking a row highlights its footprint. Clicking a footprint opens that item; where footprints overlap, a popup lists them, as in STEX.
- Item details (sections folded by default) with Prev/Next and copy
buttons for:
- the self link and id;
- every property value;
- asset hrefs, including alternates such as S3;
- links;
- a ready-to-run Python snippet.
- Python access to results, selection and the current query (see below).
- Restricted collections via the user's JupyterHub OIDC token, with an anonymous fallback and a visible "Not signed in" hint.
- Light and dark mode follow JupyterLab (also VS Code and Colab), including the basemap.
- Links to the search:
ex.query_url()gives a clickable STACGET /searchURL;ex.stex_url()opens the same query in STEX. - Translatable following the JupyterLab i18n standard; English ships today.
Quick start
import jstex
ex = jstex.Explorer() # pick a collection, draw a box, click Search
ex
Then, in the next cell:
item = ex.selected_item # the item shown in Item details
item.assets["B04"].href # use it in your code
Using results in Python
| Member | What it gives |
|---|---|
jstex.Explorer(stac_url=None, height=600) |
The widget. stac_url overrides JSTEX_STAC_URL; height is the panel/map height in px. |
ex.results |
All loaded items as a pystac.ItemCollection |
ex.selected_items |
The checked result rows, as pystac.Items |
ex.selected_item |
The item shown in Item details (None if none) |
ex.query |
The current query as a dict. Assign to it to change the panel from Python. |
ex.search(wait=False) |
Run the current query. wait=True blocks until ex.results is filled. |
ex.cancel() |
Drop the running search; previous results stay |
ex.query_url() |
Clickable STAC GET /search URL for the query (returns the results as JSON; carries no token). A complex area is sent as its bbox, with a warning, to keep the URL under 2,000 characters. |
ex.stex_url() |
Clickable STEX link that opens the query (needs JSTEX_STEX_URL) |
jstex.item(href) |
Open any STAC item URL with the user's token (what "Copy Python" pastes) |
Search from code, and the widget shows the same results:
ex.query = {
**ex.query,
"collections": ["sentinel-2-l2a"],
"datetime": {"from": "2024-07-01T00:00:00Z", "to": "2024-07-31T23:59:59Z"},
"filters": [{"field": "eo:cloud_cover", "op": "<=", "value": 20}],
}
ex.search(wait=True)
for item in ex.results:
print(item.id, item.datetime, item.properties.get("eo:cloud_cover"))
Installation
pip install jupyterlab-jstex
In a JupyterHub single-user image:
FROM quay.io/jupyter/scipy-notebook:latest
RUN pip install --no-cache-dir jupyterlab-jstex
Wheels are also attached to each GitHub Release.
Requirements: JupyterLab 4, Python ≥ 3.10 with anywidget 0.11 (installed
as a dependency).
Configuration
Set these environment variables on the single-user server (e.g.
singleuser.extraEnv in Zero to JupyterHub):
| Env var | Default | Meaning |
|---|---|---|
JSTEX_STAC_URL |
https://stac.opensearch.dataspace.copernicus.eu/v1/ |
STAC API |
JSTEX_STEX_URL |
unset | STEX base URL for stex_url() links |
JSTEX_BASEMAP_LIGHT_URL / _KEY / _KEY_PARAM / _ATTRIBUTION |
OpenFreeMap Positron (no key needed) | Light-theme basemap |
JSTEX_BASEMAP_DARK_URL / _KEY / _KEY_PARAM / _ATTRIBUTION |
OpenFreeMap Positron (no key needed) | Dark-theme basemap |
JSTEX_ACCESS_TOKEN |
unset | Token for local development outside a hub |
The default basemap is OpenFreeMap Positron
(https://tiles.openfreemap.org/styles/positron) in both themes; it needs no
API key. Each theme can use another provider:
_URL: an XYZ raster tile template (contains{z}/{x}/{y};{r}becomes@2x), or any other URL is read as a MapLibre/Mapbox style JSON (vector)._KEY/_KEY_PARAM: an API key, added to the URL as?<KEY_PARAM>=<KEY>(default parameter namekey)._ATTRIBUTION: credits shown for raster tiles; a vector style brings its own credits from its sources.
JupyterHub prerequisites
jstex reads the user's access token from the hub's auth_state. The hub must:
- enable
auth_state; - grant
admin:auth_state!userso the user's server can read it.
See deploy/z2jh-values.example.yaml.
Without this, jstex searches anonymously and shows "Not signed in —
restricted collections are hidden." under the Search button.
Translations
The UI uses JupyterLab's translation system (gettext domain jstex). v0.1
ships English only. A translation is shown when the matching official
JupyterLab language pack (e.g. jupyterlab-language-pack-de-DE) is installed
and selected. To add a language, see
DEVELOPMENT.md → Translations.
Limitations (v0.1)
- While another cell is running, the widget waits for the kernel.
- There is one area of interest at a time.
- There is no "Load more" yet (planned for v0.2); a search loads one page (50 items).
- No downloads, visualisation or processing — use STEX for those.
Documentation
- Architecture — how the kernel, widget and JupyterLab extension fit together.
- DEVELOPMENT.md — setup, commands, gotchas.
- CONTRIBUTING.md — development install and releasing.
- CHANGELOG.md
License
GPL-3.0-or-later. The extension bundles third-party open-source libraries (e.g. OpenLayers, EOX Elements) under their own licenses.
Metadata
Release files for jupyterlab-jstex 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jupyterlab_jstex-0.1.0.tar.gz | 1.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jupyterlab_jstex-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.2 MB
Release files / jupyterlab_jstex-0.1.0.tar.gz
| Download URL | jupyterlab_jstex-0.1.0.tar.gz |
|---|---|
| Size | 1.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54626d76c6045ad5fd96a9634ccf46840f0caaf3888ca847f3eb711214a54c31
|
|
BLAKE2b-256 checksum How to use checksums |
58e5477f77dc2f9ff3895a39097d8e13eb79edd5d88bd071c25a60391608fb49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / jupyterlab_jstex-0.1.0-py3-none-any.whl
| Download URL | jupyterlab_jstex-0.1.0-py3-none-any.whl |
|---|---|
| Size | 1.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8316eb3f68260cabf5c7abfe1b85420058d7577be408ec62747fc625ffd9b0e4
|
|
BLAKE2b-256 checksum How to use checksums |
c0972aa661a37f48bb56a18345874e9b4022047ff6c0d018623a09ae3a550994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|