Skip to content
Open
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
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

### titiler.xarray

* use `sel={dim}={method}::{value}` notation to specify selector method instead of `sel-method` query-parameter **breaking change**

```python
# before
.../info?tore.zarr?sel=time=2023-01-01&sel_method=nearest`

# now
.../info?tore.zarr?sel=time=nearest::2023-01-01`
```

* add `/validate` endpoint via `ValidateExtension` extension
* add `Latitude` and `Longitude` as compatible spatial dimensions (@abarciauskas-bgse, https://github.com/developmentseed/titiler/pull/1268)

Expand Down
236 changes: 236 additions & 0 deletions dev_notebooks/rendering.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ nav:
- NumpyTile: "examples/notebooks/Working_with_NumpyTile.ipynb"
- Algorithm: "examples/notebooks/Working_with_Algorithm.ipynb"
- Statistics: "examples/notebooks/Working_with_Statistics.ipynb"
- Xarray: "examples/notebooks/Working_with_Zarr.ipynb"

- API:
- titiler.core:
Expand Down
13 changes: 1 addition & 12 deletions docs/src/advanced/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,6 @@ Define options to select a **variable** within a Xarray Dataset.
| ------ | ---------- |----------|--------------
| **variable** | Query (str) | Yes | None
| **sel** | Query (list of str) | No | None
| **method** | Query (str)| No | None

<details>

Expand All @@ -1033,15 +1032,7 @@ class XarrayDsParams(DefaultDependency):
sel: Annotated[
Optional[List[SelDimStr]],
Query(
description="Xarray Indexing using dimension names `{dimension}={value}`.",
),
] = None

method: Annotated[
Optional[Literal["nearest", "pad", "ffill", "backfill", "bfill"]],
Query(
alias="sel_method",
description="Xarray indexing method to use for inexact matches.",
description="Xarray Indexing using dimension names `{dimension}={value}` or `{dimension}={method}::{value}`.",
),
] = None
```
Expand All @@ -1059,7 +1050,6 @@ Combination of `XarrayIOParams` and `XarrayDsParams`
| **decode_times** | Query (bool)| No | None
| **variable** | Query (str) | Yes | None
| **sel** | Query (list of str) | No | None
| **method** | Query (str)| No | None

<details>

Expand All @@ -1083,7 +1073,6 @@ same as `XarrayParams` but with optional `variable` option.
| **decode_times** | Query (bool)| No | None
| **variable** | Query (str) | No | None
| **sel** | Query (list of str) | No | None
| **method** | Query (str)| No | None

<details>

Expand Down
279 changes: 279 additions & 0 deletions docs/src/examples/notebooks/Working_with_Zarr.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# Working with Zarr"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Intro\n",
"\n",
"`titiler.xarray` is a submodule designed specifically for working with multidimensional dataset. With version `0.25.0`, we've introduced a default application with only support for Zarr dataset."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2023-04-06T14:25:40.161502Z",
"start_time": "2023-04-06T14:25:40.153667Z"
},
"collapsed": false
},
"outputs": [],
"source": [
"# setup\n",
"import httpx\n",
"import json\n",
"from IPython.display import Image\n",
"\n",
"# Developmentseed Demo endpoint. Please be kind. Ref: https://github.com/developmentseed/titiler/discussions/1223\n",
"# titiler_endpoint = \"https://xarray.titiler.xyz\"\n",
"\n",
"# Or launch your own local instance with:\n",
"# uv run --group server uvicorn titiler.xarray.main:app --host 127.0.0.1 --port 8080 --reload\n",
"titiler_endpoint = \"http://127.0.0.1:8080\"\n",
"\n",
"zarr_url = \"https://nasa-power.s3.us-west-2.amazonaws.com/syn1deg/temporal/power_syn1deg_monthly_temporal_lst.zarr\""
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Dataset Metadata\n",
"\n",
"The `/dataset/dict` endpoint returns general metadata about the Zarr Dataset\n",
"\n",
"Endpoint: `/dataset/dict`\n",
"\n",
"QueryParams:\n",
"- **url**: Zarr store URL"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2023-04-06T14:25:42.410135Z",
"start_time": "2023-04-06T14:25:42.355858Z"
},
"collapsed": false
},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/dataset/dict\",\n",
" params={\n",
" \"url\": zarr_url,\n",
" },\n",
").json()\n",
"\n",
"print(json.dumps(r, indent=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### List of available variables\n",
"\n",
"Endpoint: `/dataset/keys`\n",
"\n",
"QueryParams:\n",
"- **url**: Zarr store URL"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/dataset/keys\",\n",
" params={\n",
" \"url\": zarr_url,\n",
" },\n",
").json()\n",
"\n",
"print(json.dumps(r, indent=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Variable Info\n",
"\n",
"We can use `/info` endpoint to get more `Geo` information about a specific variable.\n",
"\n",
"QueryParams:\n",
"- **url**: Zarr store URL\n",
"- **variable**: Variable's name (e.g `AIRMASS`, found in `/dataset/keys` response)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/info\",\n",
" params={\"url\": zarr_url, \"variable\": \"AIRMASS\"},\n",
").json()\n",
"\n",
"print(json.dumps(r, indent=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Or as a GeoJSON feature"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/info.geojson\",\n",
" params={\"url\": zarr_url, \"variable\": \"AIRMASS\"},\n",
").json()\n",
"\n",
"print(json.dumps(r, indent=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Knowledge\n",
"\n",
"Looking at the `info` response we can see that the `AIRMASS` variable has `348` (count) bands, each one corresponding to as specific `TIME` (day).\n",
"\n",
"We can also see that the data is stored as `float32` which mean that we will have to apply linear rescaling in order to get output image as PNG/JPEG.\n",
"\n",
"The `min/max` values are also indicated with `valid_max=31.73` and `valid_min=1.0`.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Dimension Reduction\n",
"\n",
"We cannot visualize all the `bands` at once, so we need to perform dimension reduction to go from array in shape (348, 360, 180) to a 1b (1, 360, 180) or 3b (3, 360, 180) image. \n",
"\n",
"To do it, we have two methods whitin `titiler.xarray`:\n",
"- using `bidx=`: same as for COG we can select a band index\n",
"- using `sel={dimension}=value`: which will be using xarray `.sel` method"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/bbox/-180,-90,180,90.png\",\n",
" params=(\n",
" (\"url\", zarr_url),\n",
" (\"variable\", \"AIRMASS\"),\n",
" # Select 1 specific band\n",
" (\"bidx\", 50),\n",
" (\"rescale\", \"1,20\"),\n",
" (\"colormap_name\", \"viridis\"),\n",
" ),\n",
" timeout=10,\n",
")\n",
"\n",
"Image(r.content)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/bbox/-180,-90,180,90.png\",\n",
" params=(\n",
" (\"url\", zarr_url),\n",
" (\"variable\", \"AIRMASS\"),\n",
" # Select 1 specific time slices\n",
" (\"sel\", \"time=2003-06-30\"),\n",
" (\"rescale\", \"1,20\"),\n",
" (\"colormap_name\", \"viridis\"),\n",
" ),\n",
" timeout=10,\n",
")\n",
"\n",
"Image(r.content)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/bbox/-180,-90,180,90.png\",\n",
" params=(\n",
" (\"url\", zarr_url),\n",
" (\"variable\", \"AIRMASS\"),\n",
" # Select 3 specific time slices to create a 3 band image\n",
" (\"sel\", \"time=2003-06-30\"),\n",
" (\"sel\", \"time=2004-06-30\"),\n",
" (\"sel\", \"time=2005-06-30\"),\n",
" (\"rescale\", \"1,10\"),\n",
" ),\n",
" timeout=10,\n",
")\n",
"\n",
"Image(r.content)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "python3.13 (3.13.7)",
"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.13.7"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Loading