Skip to content

Commit

Permalink
add /statistics endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
hrodmn committed Oct 14, 2024
1 parent e9a14c6 commit 6fed76e
Show file tree
Hide file tree
Showing 6 changed files with 913 additions and 303 deletions.
226 changes: 195 additions & 31 deletions docs/src/examples/HLS_Example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,33 @@
"source": [
"# TiTiler-CMR: HLS Data Demo\n",
"\n",
"The Harmonized Landsat Sentinel-2 dataset is available in two collections in CMR. This example will use data from the `HLSL30.002` (Landsat) dataset.\n",
"\n",
"#### Requirements\n",
"- folium\n",
"- httpx\n",
"To run some of the chunks in this notebook you will need to install a few packages:\n",
"\n",
"- `earthaccess`\n",
"- `folium`\n",
"- `httpx`\n",
"\n",
"`!pip install folium httpx earthaccess`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import json\n",
"import httpx\n",
"import earthaccess\n",
"import geojson_pydantic\n",
"import httpx\n",
"import json\n",
"\n",
"\n",
"from folium import Map, TileLayer"
"from folium import GeoJson, Map, TileLayer"
]
},
{
Expand All @@ -32,17 +41,15 @@
"metadata": {},
"outputs": [],
"source": [
"titiler_endpoint = \"http://localhost:8000\""
"titiler_endpoint = \"http://localhost:8081\""
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"datasets = earthaccess.search_datasets(doi=\"10.5067/HLS/HLSL30.002\")\n",
"ds = datasets[0]"
"## Identify the dataset\n",
"You can find the `HLSL30.002` dataset using the earthaccess.search_datasets function."
]
},
{
Expand All @@ -51,8 +58,21 @@
"metadata": {},
"outputs": [],
"source": [
"datasets = earthaccess.search_datasets(doi=\"10.5067/HLS/HLSL30.002\")\n",
"ds = datasets[0]\n",
"\n",
"concept_id = ds[\"meta\"][\"concept-id\"]\n",
"print(\"Concept-Id: \", concept_id)"
"print(\"Concept-Id: \", concept_id)\n",
"print(\"Abstract: \", ds[\"umm\"][\"Abstract\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Examine a granule\n",
"\n",
"Each granule contains the data for a single point in time for an MGRS tile. "
]
},
{
Expand Down Expand Up @@ -84,12 +104,12 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"print(results[0])"
"## Demonstrate `assets_for_tile` method\n",
"\n",
"While rendering `xyz` tile images, `titiler-cmr` searches for assets using the `assets_for_tile` method which converts the `xyz` tile extent into a bounding box."
]
},
{
Expand All @@ -115,20 +135,10 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"with CMRBackend() as backend:\n",
" assets = backend.assets_for_tile(\n",
" x=62,\n",
" y=44,\n",
" z=7,\n",
" bands_regex=\"B[0-9][0-9]\",\n",
" concept_id=\"C2021957657-LPCLOUD\",\n",
" temporal=(\"2024-02-11\", \"2024-02-13\")\n",
" )\n"
"## `titiler.cmr` API documentation"
]
},
{
Expand All @@ -141,6 +151,15 @@
"IFrame(f\"{titiler_endpoint}/api.html\", 900,500)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Display tiles in an interactive map\n",
"\n",
"The `/tilejson.json` endpoint will provide a parameterized `xyz` tile URL that can be added to an interactive map."
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -166,7 +185,6 @@
" (\"bands\", \"B02\"),\n",
" # The data is in type of Uint16 so we need to apply some\n",
" # rescaling/color_formula in order to create PNGs\n",
" # (\"rescale\", \"0,1000\"),\n",
" (\"color_formula\", \"Gamma RGB 3.5 Saturation 1.7 Sigmoidal RGB 15 0.35\"),\n",
" # We need to set min/max zoom because we don't want to use lowerzoom level (e.g 0)\n",
" # which will results in useless large scale query\n",
Expand All @@ -187,7 +205,7 @@
"bounds = r[\"bounds\"]\n",
"m = Map(\n",
" location=(47.590266824611675, -91.03729840730689),\n",
" zoom_start=r[\"maxzoom\"] - 3\n",
" zoom_start=r[\"maxzoom\"] - 2\n",
")\n",
"\n",
"TileLayer(\n",
Expand All @@ -198,6 +216,152 @@
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Render NDVI using the `expression` parameter\n",
"The `expression` parameter can be used to render images from an expression of a combination of the individual `bands`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = httpx.get(\n",
" f\"{titiler_endpoint}/WebMercatorQuad/tilejson.json\",\n",
" params = (\n",
" (\"concept_id\", concept_id),\n",
" # Datetime in form of `start_date/end_date`\n",
" (\"datetime\", \"2024-06-20T00:00:00Z/2024-06-27T23:59:59Z\"),\n",
" # We know that the HLS collection dataset is stored as File per Band\n",
" # so we need to pass a `band_regex` option to assign `bands` to each URL\n",
" (\"bands_regex\", \"B[0-9][0-9]\"),\n",
" # titiler-cmr can work with both Zarr and COG dataset\n",
" # but we need to tell the endpoints in advance which backend\n",
" # to use\n",
" (\"backend\", \"rasterio\"),\n",
" # NDVI\n",
" (\"expression\", \"(B05-B04)/(B05+B04)\"),\n",
" # Need red (B04) and nir (B05) for NDVI\n",
" (\"bands\", \"B05\"),\n",
" (\"bands\", \"B04\"),\n",
" # The data is in type of Uint16 so we need to apply some\n",
" # rescaling/color_formula in order to create PNGs\n",
" (\"colormap_name\", \"viridis\"),\n",
" (\"rescale\", \"-1,1\"),\n",
" # We need to set min/max zoom because we don't want to use lowerzoom level (e.g 0)\n",
" # which will results in useless large scale query\n",
" (\"minzoom\", 8),\n",
" (\"maxzoom\", 13),\n",
" )\n",
").json()\n",
"\n",
"m = Map(\n",
" location=(47.9221313337365, -91.65432884883238),\n",
" zoom_start=r[\"maxzoom\"] - 1\n",
")\n",
"\n",
"\n",
"TileLayer(\n",
" tiles=r[\"tiles\"][0],\n",
" opacity=1,\n",
" attr=\"NASA\",\n",
").add_to(m)\n",
"\n",
"GeoJson(geojson).add_to(m)\n",
"\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## GeoJSON Statistics\n",
"The `/statistics` endpoint can be used to get summary statistics for a geojson `Feature` or `FeatureCollection`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"geojson = {\n",
" \"type\": \"FeatureCollection\",\n",
" \"features\": [\n",
" {\n",
" \"type\": \"Feature\",\n",
" \"properties\": {},\n",
" \"geometry\": {\n",
" \"coordinates\": [\n",
" [\n",
" [\n",
" -91.65432884883238,\n",
" 47.9221313337365\n",
" ],\n",
" [\n",
" -91.65432884883238,\n",
" 47.86503396133904\n",
" ],\n",
" [\n",
" -91.53842043960762,\n",
" 47.86503396133904\n",
" ],\n",
" [\n",
" -91.53842043960762,\n",
" 47.9221313337365\n",
" ],\n",
" [\n",
" -91.65432884883238,\n",
" 47.9221313337365\n",
" ]\n",
" ]\n",
" ],\n",
" \"type\": \"Polygon\"\n",
" }\n",
" }\n",
" ]\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"r = httpx.post(\n",
" f\"{titiler_endpoint}/statistics\",\n",
" params=(\n",
" (\"concept_id\", concept_id),\n",
" # Datetime in form of `start_date/end_date`\n",
" (\"datetime\", \"2024-07-01T00:00:00Z/2024-07-10T23:59:59Z\"),\n",
" # We know that the HLS collection dataset is stored as File per Band\n",
" # so we need to pass a `band_regex` option to assign `bands` to each URL\n",
" (\"bands_regex\", \"B[0-9][0-9]\"),\n",
" # titiler-cmr can work with both Zarr and COG dataset\n",
" # but we need to tell the endpoints in advance which backend\n",
" # to use\n",
" (\"backend\", \"rasterio\"),\n",
" # NDVI\n",
" (\"expression\", \"(B05-B04)/(B05+B04)\"),\n",
" # Need red (B04) and nir (B05) for NDVI\n",
" (\"bands\", \"B05\"),\n",
" (\"bands\", \"B04\"),\n",
" ),\n",
" json=geojson,\n",
" timeout=30,\n",
").json()\n",
"\n",
"print(json.dumps(r, indent=2))"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
Loading

0 comments on commit 6fed76e

Please sign in to comment.