Skip to content
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
26 changes: 13 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
database:
image: ghcr.io/stac-utils/pgstac:v0.9.8
image: ghcr.io/stac-utils/pgstac:v0.9.10
environment:
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
Expand Down Expand Up @@ -56,11 +56,11 @@ services:
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
start_period: 120s


stac-fastapi:
image: ghcr.io/stac-utils/stac-fastapi-pgstac:6.0.2
image: ghcr.io/stac-utils/stac-fastapi-pgstac:6.2.2
ports:
- 8081:8081
environment:
Expand All @@ -80,21 +80,19 @@ services:
condition: service_healthy
command:
bash -c "uvicorn stac_fastapi.pgstac.app:app --host 0.0.0.0 --port 8081"
volumes:
- ./dockerfiles/scripts:/tmp/scripts

titiler-pgstac:
platform: linux/amd64
image: ghcr.io/stac-utils/titiler-pgstac:1.9.0
image: ghcr.io/stac-utils/titiler-pgstac:3.0.0
ports:
- 8082:8082
environment:
# Postgres connection
- POSTGRES_USER=username
- POSTGRES_PASS=password
- POSTGRES_DBNAME=postgis
- POSTGRES_HOST=database
- POSTGRES_PORT=5432
- PGUSER=username
- PGPASSWORD=password
- PGDATABASE=postgis
- PGHOST=database
- PGPORT=5432
- DB_MIN_CONN_SIZE=1
- DB_MAX_CONN_SIZE=10
# - DB_MAX_QUERIES=10
Expand All @@ -112,9 +110,11 @@ services:
# TiTiler Config
- MOSAIC_CONCURRENCY=1
- TITILER_PGSTAC_API_ENABLE_EXTERNAL_DATASET_ENDPOINTS=True
# AWS S3 endpoint config
# AWS S3 endpoint config — the workshop's s3:// assets (glad collection)
# are in public buckets; read unsigned unless real credentials are provided
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_NO_SIGN_REQUEST=${AWS_NO_SIGN_REQUEST:-YES}
depends_on:
database:
condition: service_started
Expand All @@ -124,7 +124,7 @@ services:
bash -c "uvicorn titiler.pgstac.main:app --host 0.0.0.0 --port 8082"

tipg:
image: ghcr.io/developmentseed/tipg:1.1.2
image: ghcr.io/developmentseed/tipg:1.4.0
ports:
- 8083:8083
environment:
Expand Down
16 changes: 13 additions & 3 deletions docs/02-database.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,20 @@
"source": [
"from IPython.display import IFrame\n",
"\n",
"stac_api_endpoint = os.getenv(\"STAC_API_ENDPOINT\").replace(\"stac-fastapi\", \"localhost\")\n",
"# Use the stack's own STAC Browser when deployed (its catalog is already this\n",
"# STAC API); otherwise fall back to the public STAC Browser in external mode.\n",
"stac_browser_endpoint = os.getenv(\"STAC_BROWSER_ENDPOINT\")\n",
"\n",
"if stac_browser_endpoint:\n",
" browser_url = f\"{stac_browser_endpoint}/#/collections/{my_collection.id}\"\n",
"else:\n",
" browser_stac_url = os.getenv(\"STAC_API_ENDPOINT\").replace(\n",
" \"stac-auth-proxy:8000\", \"localhost:8084\"\n",
" )\n",
" browser_url = f\"https://radiantearth.github.io/stac-browser/#/external/{browser_stac_url}/collections/{my_collection.id}\"\n",
"\n",
"IFrame(\n",
" f\"https://radiantearth.github.io/stac-browser/#/external/{stac_api_endpoint}/collections/{my_collection.id}\",\n",
" browser_url,\n",
" 1200,\n",
" 800,\n",
")"
Expand Down Expand Up @@ -467,7 +477,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.12.13"
}
},
"nbformat": 4,
Expand Down
9 changes: 5 additions & 4 deletions docs/03-stac_fastapi_pgstac.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "c8ec4c5b-1156-4608-8ab9-b2cdcbcc47e1",
"metadata": {},
Expand Down Expand Up @@ -49,7 +48,7 @@
"### 3.1.2 Authentication\n",
"stac-fastapi-pgstac does not contain any authentication mechanism out-of-the-box, meaning your STAC API will be accessible to anyone if it is deployed to a public web address. If you want to make your STAC API accessible only with a username/password or token, check out the [FastAPI docs](https://fastapi.tiangolo.com/tutorial/security) for examples of how to add them to the application in a custom runtime.\n",
"\n",
"There is a new project called [stac-auth-proxy](https://github.com/developmentseed/stac-auth-proxy) that can provide fine-grained access controls to a STAC API by adding a proxy layer between users and the actual STAC API.\n",
"There is a new project called [stac-auth-proxy](https://github.com/developmentseed/stac-auth-proxy) that can provide fine-grained access controls to a STAC API by adding a proxy layer between users and the actual STAC API. In this workshop stack, the STAC API is exposed through stac-auth-proxy at `http://localhost:8084`.\n",
"\n",
"### 3.1.3 STAC API interface\n",
"Once your STAC API is up and running, its capabilities will be described in the `/conformance` endpoint response:"
Expand Down Expand Up @@ -196,7 +195,9 @@
"source": [
"from IPython.display import IFrame\n",
"\n",
"local_stac_api_endpoint = stac_api_endpoint.replace(\"stac-fastapi\", \"localhost\")\n",
"local_stac_api_endpoint = os.getenv(\n",
" \"STAC_API_BROWSER_URL\"\n",
") or stac_api_endpoint.replace(\"stac-auth-proxy:8000\", \"localhost:8084\")\n",
"api_docs = (\n",
" f\"{local_stac_api_endpoint}/api.html#/default/Get_Collections_collections_get\"\n",
")\n",
Expand Down Expand Up @@ -544,7 +545,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.12.13"
}
},
"nbformat": 4,
Expand Down
37 changes: 22 additions & 15 deletions docs/04-titiler_pgstac.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,13 @@
"\n",
"from IPython.display import IFrame, Image\n",
"\n",
"titiler_pgstac_endpoint = os.getenv(\"TITILER_PGSTAC_API_ENDPOINT\").replace(\n",
" \"titiler-pgstac\", \"localhost\"\n",
")\n",
"api_docs = f\"{titiler_pgstac_endpoint}/api.html\"\n",
"titiler_pgstac_endpoint = os.getenv(\"TITILER_PGSTAC_API_ENDPOINT\")\n",
"# browser-facing URL for the IFrame/map cells (the user's browser can't reach\n",
"# the server-side endpoint above when running on Kubernetes or docker-compose)\n",
"titiler_browser_endpoint = os.getenv(\n",
" \"TITILER_BROWSER_URL\"\n",
") or titiler_pgstac_endpoint.replace(\"titiler-pgstac\", \"localhost\")\n",
"api_docs = f\"{titiler_browser_endpoint}/api.html\"\n",
"print(api_docs)\n",
"\n",
"IFrame(\n",
Expand Down Expand Up @@ -152,7 +155,7 @@
" - Leaflet\n",
" - Mapbox\n",
"\n",
"For now you can take a shortcut to view the map directly in this notebook using the `/map` endpoint which will generate an HTML file with a Leaflet map that can be rendered directly in the notebook.\n",
"For now you can take a shortcut to view the map directly in this notebook using the `/map.html` endpoint which will generate an HTML file with a Leaflet map that can be rendered directly in the notebook.\n",
"\n",
"<div class=\"alert alert-block alert-warning\">\n",
"It may take a while to render tiles for the full view because the titiler-pgstac container is downloading data from S3 in order to render the images - zoom in to have a better browsing experience. This performance can be improved when deploying your own eoAPI through careful preparation of data and sourcing of hardware resources, the demo runs on a very small server.\n",
Expand All @@ -167,7 +170,7 @@
"outputs": [],
"source": [
"IFrame(\n",
" f\"{titiler_pgstac_endpoint}/collections/{collection_id}/WebMercatorQuad/map?{urlencode(params, doseq=True)}\",\n",
" f\"{titiler_browser_endpoint}/collections/{collection_id}/WebMercatorQuad/map.html?{urlencode(params, doseq=True)}\",\n",
" 1200,\n",
" 800,\n",
")"
Expand All @@ -180,8 +183,8 @@
"source": [
"### How does it work?\n",
"\n",
"- titiler-pgstac is running as a Lambda (serverless) function in AWS that started up when you made the request for the `/map` endpoint.\n",
"- The `/map` endpoint returns an HTML file that is pre-populated with some map code that includes the layer that you specified with the request parameters\n",
"- titiler-pgstac is running as a Lambda (serverless) function in AWS that started up when you made the request for the `/map.html` endpoint.\n",
"- The `/map.html` endpoint returns an HTML file that is pre-populated with some map code that includes the layer that you specified with the request parameters\n",
"- As you browse the map, the map is sending XYZ tile requests to titiler-pgstac function in AWS\n",
"- Each request contains the information titiler-pgstac needs to search for items in the pgstac database and how to construct an image from the items' assets\n",
" - `collection_id`: by specifying the collection ID in the request path you are instructing titiler-pgstac to search for items from a specific STAC collection. Unless otherwise specified, pgstac will retrieve the STAC items in descending order by datetime and it will stop returning results when a tile's geometry is completely covered.\n",
Expand Down Expand Up @@ -247,7 +250,7 @@
"source": [
"The response comes back with an `id` which uniquely identifies this search and a handful of useful links associated with our newly registered search.\n",
"\n",
"Now you can browse the results of this search with the `/map` endpoint like you did earlier."
"Now you can browse the results of this search with the `/map.html` endpoint like you did earlier."
]
},
{
Expand All @@ -267,7 +270,7 @@
")\n",
"\n",
"IFrame(\n",
" f\"{titiler_pgstac_endpoint}/searches/{search_id}/WebMercatorQuad/map?{urlencode(params, doseq=True)}\",\n",
" f\"{titiler_browser_endpoint}/searches/{search_id}/WebMercatorQuad/map.html?{urlencode(params, doseq=True)}\",\n",
" 1200,\n",
" 800,\n",
")"
Expand Down Expand Up @@ -303,14 +306,16 @@
"outputs": [],
"source": [
"params = (\n",
" (\"assets\", \"nir\"),\n",
" (\"assets\", \"red\"),\n",
" (\"asset_as_band\", \"True\"),\n",
" (\"expression\", \"(nir - red) / (nir + red)\"),\n",
" (\"colormap_name\", \"viridis\"),\n",
" (\"rescale\", \"-0.5,1\"),\n",
")\n",
"\n",
"IFrame(\n",
" f\"{titiler_pgstac_endpoint}/searches/{search_id}/WebMercatorQuad/map?{urlencode(params, doseq=True)}\",\n",
" f\"{titiler_browser_endpoint}/searches/{search_id}/WebMercatorQuad/map.html?{urlencode(params, doseq=True)}\",\n",
" 1200,\n",
" 800,\n",
")"
Expand Down Expand Up @@ -366,6 +371,7 @@
" params={\n",
" \"url\": cog_href,\n",
" },\n",
" timeout=None,\n",
")\n",
"\n",
"print(json.dumps(cog_info_request.json(), indent=2))"
Expand Down Expand Up @@ -394,6 +400,7 @@
" \"url\": cog_href,\n",
" \"maxsize\": 2048,\n",
" },\n",
" timeout=None,\n",
")\n",
"\n",
"Image(preview_request.content)"
Expand Down Expand Up @@ -506,7 +513,7 @@
"outputs": [],
"source": [
"map_request = httpx.get(\n",
" f\"{titiler_pgstac_endpoint}/external/WebMercatorQuad/map\",\n",
" f\"{titiler_pgstac_endpoint}/external/WebMercatorQuad/map.html\",\n",
" params={\n",
" \"url\": cog_href,\n",
" \"maxsize\": 2048,\n",
Expand All @@ -517,7 +524,7 @@
"\n",
"\n",
"IFrame(\n",
" map_request.url,\n",
" str(map_request.url).replace(titiler_pgstac_endpoint, titiler_browser_endpoint),\n",
" 1200,\n",
" 800,\n",
")"
Expand All @@ -541,7 +548,7 @@
"outputs": [],
"source": [
"map_request = httpx.get(\n",
" f\"{titiler_pgstac_endpoint}/collections/glad-global-forest-change-1.11/WebMercatorQuad/map\",\n",
" f\"{titiler_pgstac_endpoint}/collections/glad-global-forest-change-1.11/WebMercatorQuad/map.html\",\n",
" params={\n",
" \"assets\": \"lossyear\",\n",
" \"colormap\": json.dumps({i: rgb for i, rgb in colormap.items()}),\n",
Expand All @@ -551,7 +558,7 @@
"\n",
"\n",
"IFrame(\n",
" map_request.url,\n",
" str(map_request.url).replace(titiler_pgstac_endpoint, titiler_browser_endpoint),\n",
" 1200,\n",
" 800,\n",
")"
Expand Down
21 changes: 13 additions & 8 deletions docs/05-tipg.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
"import httpx\n",
"\n",
"tipg_endpoint = os.getenv(\"TIPG_API_ENDPOINT\")\n",
"# browser-facing URL for the IFrame/viewer cells (the user's browser can't\n",
"# reach the server-side endpoint above when running on Kubernetes)\n",
"tipg_browser_endpoint = os.getenv(\"TIPG_BROWSER_URL\") or tipg_endpoint.replace(\n",
" \"tipg\", \"localhost\"\n",
")\n",
"\n",
"collections_request = httpx.get(f\"{tipg_endpoint}/collections\")\n",
"\n",
Expand All @@ -76,9 +81,9 @@
"- `/collections/{collection_id}/items`: where features can be accessed\n",
"- `/collections/{collection_id}/tiles`: list of tile matrix set IDs that are available for tile requests\n",
"- `/collections/{collection_id}/tiles/{tileMatrixSetId}`: returns a tilejson for a vector tile layer\n",
"- `/collections/{collection_id}/tiles/{tileMatrixSetId}/viewer`: interactive map of the collection\n",
"- `/collections/{collection_id}/tiles/{tileMatrixSetId}/map.html`: interactive map of the collection\n",
"\n",
"The `/items`, `/tiles/{tileMatrixSetId}`, and `/tiles/{tileMatrixSetId}/viewer` endpoints will all accept field filters in the form of `{queryable}={value}` where `queryable` is one of the fields listed in the `/queryables` response for that collection."
"The `/items`, `/tiles/{tileMatrixSetId}`, and `/tiles/{tileMatrixSetId}/map.html` endpoints will all accept field filters in the form of `{queryable}={value}` where `queryable` is one of the fields listed in the `/queryables` response for that collection."
]
},
{
Expand Down Expand Up @@ -261,7 +266,7 @@
" },\n",
")\n",
"\n",
"local_url = str(bbox_filtered_request.url).replace(\"tipg\", \"localhost\")\n",
"local_url = str(bbox_filtered_request.url).replace(tipg_endpoint, tipg_browser_endpoint)\n",
"\n",
"IFrame(\n",
" local_url,\n",
Expand All @@ -285,7 +290,7 @@
"metadata": {},
"outputs": [],
"source": [
"local_tipg_endpoint = tipg_endpoint.replace(\"tipg\", \"localhost\")\n",
"local_tipg_endpoint = tipg_browser_endpoint\n",
"IFrame(\n",
" f\"{local_tipg_endpoint}/api.html#OGC Features API/items_collections__collectionId__items_get\",\n",
" width=1200,\n",
Expand Down Expand Up @@ -374,11 +379,11 @@
"outputs": [],
"source": [
"viewer_request = httpx.get(\n",
" f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/viewer\",\n",
" f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/map.html\",\n",
")\n",
"\n",
"IFrame(\n",
" str(viewer_request.url).replace(\"tipg\", \"localhost\"),\n",
" str(viewer_request.url).replace(tipg_endpoint, tipg_browser_endpoint),\n",
" width=1200,\n",
" height=800,\n",
")"
Expand All @@ -400,14 +405,14 @@
"outputs": [],
"source": [
"filtered_viewer_request = httpx.get(\n",
" f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/viewer\",\n",
" f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/map.html\",\n",
" params={\n",
" \"na_l2name\": \"MEDITERRANEAN CALIFORNIA\",\n",
" },\n",
")\n",
"\n",
"IFrame(\n",
" str(filtered_viewer_request.url).replace(\"tipg\", \"localhost\"),\n",
" str(filtered_viewer_request.url).replace(tipg_endpoint, tipg_browser_endpoint),\n",
" width=1200,\n",
" height=800,\n",
")"
Expand Down