diff --git a/docs/05-tipg.ipynb b/docs/05-tipg.ipynb new file mode 100644 index 0000000..8170d15 --- /dev/null +++ b/docs/05-tipg.ipynb @@ -0,0 +1,1204 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "416f1814-d6af-4a4e-8217-33fddc226f95", + "metadata": {}, + "source": [ + "# 5. The Vector API: tipg\n", + "\n", + "\n", + "\n", + "No geospatial data stack is complete without a mechanism for serving vector features as GeoJSON or for consumption in web maps as vector tiles. **tipg** is the component that fills that niche in eoAPI.\n", + "\n", + "From the tipg README:\n", + "> `tipg`, pronounced *T[ee]pg*, is a **Python** package that helps create lightweight OGC **Features** and **Tiles** API with a PostGIS Database backend. The API has been designed for [OGC Features](https://ogcapi.ogc.org/features) and [OGC Tiles](https://ogcapi.ogc.org/tiles/) specifications.\n", + "\n", + "In addition to serving existing features from a pre-defined set of tables in a PostGIS-enabled PostgreSQL database, it can serve features from custom views defined in user-defined PostgreSQL functions." + ] + }, + { + "cell_type": "markdown", + "id": "c3506c50-f4bd-45c4-bce7-b9336f3a41e7", + "metadata": {}, + "source": [ + "## 5.1 Configuration\n", + "\n", + "In an eoAPI stack, tipg can be connected to any PostgreSQL database including the existing pgstac database. This is controlled by the `POSTGRES_*` environment variables in the application runtime.\n", + "\n", + "When deploying tipg, you can specify which schemas in your database will be exposed to the tipg API. This is controlled by the `TIPG_DB_SCHEMAS` environment variable.\n", + "\n", + "For the workshop we have created a schema in the pgstac database called `features` that you will be working with. To expose this schema to tipg we set `TIPG_DB_SCHEMAS=[\"features\"]` in the application runtime (see line 178 in [infrastructure/app.py](../infrastructure/app.py)). There is one table that has been pre-loaded (`features.terrestrial_ecoregions`) for the examples in this notebook.\n", + "\n", + "### Additional resources:\n", + "- tipg configuration docs: " + ] + }, + { + "cell_type": "markdown", + "id": "45ac9635-b646-44f7-89c7-d6e3c20c5264", + "metadata": {}, + "source": [ + "## 5.2 OGC API - Features\n", + "tipg contains an OGC Features API that is interoperable with many existing applications.\n", + "\n", + "\n", + "\n", + "Each table in the PostgreSQL schema represents a single collection. The list of collections available to tipg can be obtained with a GET request to the `/collections` endpoint" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "25e1b941-7abd-43c5-a8fc-5a298a3edb4c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"links\": [\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections\",\n", + " \"rel\": \"self\",\n", + " \"type\": \"application/json\"\n", + " }\n", + " ],\n", + " \"numberMatched\": 1,\n", + " \"numberReturned\": 1,\n", + " \"collections\": [\n", + " {\n", + " \"id\": \"features.terrestrial_ecoregions\",\n", + " \"title\": \"features.terrestrial_ecoregions\",\n", + " \"links\": [\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\n", + " \"rel\": \"collection\",\n", + " \"type\": \"application/json\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items\",\n", + " \"rel\": \"items\",\n", + " \"type\": \"application/geo+json\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/queryables\",\n", + " \"rel\": \"queryables\",\n", + " \"type\": \"application/schema+json\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/tiles\",\n", + " \"rel\": \"data\",\n", + " \"type\": \"application/json\",\n", + " \"title\": \"Collection TileSets\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/tiles/{tileMatrixSetId}\",\n", + " \"rel\": \"data\",\n", + " \"type\": \"application/json\",\n", + " \"templated\": true,\n", + " \"title\": \"Collection TileSet (Template URL)\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/tiles/{tileMatrixSetId}/viewer\",\n", + " \"rel\": \"data\",\n", + " \"type\": \"text/html\",\n", + " \"templated\": true,\n", + " \"title\": \"Collection Map viewer (Template URL)\"\n", + " }\n", + " ],\n", + " \"extent\": {\n", + " \"spatial\": {\n", + " \"bbox\": [\n", + " [\n", + " -180.0,\n", + " -89.89197540283203,\n", + " 180.0,\n", + " 83.62313079833984\n", + " ]\n", + " ],\n", + " \"crs\": \"http://www.opengis.net/def/crs/OGC/1.3/CRS84\"\n", + " }\n", + " },\n", + " \"itemType\": \"feature\",\n", + " \"crs\": [\n", + " \"http://www.opengis.net/def/crs/OGC/1.3/CRS84\"\n", + " ]\n", + " }\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "import json\n", + "import os\n", + "\n", + "import httpx\n", + "\n", + "tipg_endpoint = os.getenv(\"TIPG_API_ENDPOINT\")\n", + "\n", + "collections_request = httpx.get(f\"{tipg_endpoint}/collections\")\n", + "\n", + "print(json.dumps(collections_request.json(), indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "c867ca53-2cf2-4584-a6bc-28930c1be953", + "metadata": {}, + "source": [ + "Each collection has a set of links associated with it including:\n", + "- `/collections/{collection_id}/queryables`: describes the fields that can be used for filtering features\n", + "- `/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", + "\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." + ] + }, + { + "cell_type": "markdown", + "id": "1961c2fd-9e02-47ef-a63e-1832b9ce0546", + "metadata": {}, + "source": [ + "### 5.2.2 /collections/{collection_id/queryables\n", + "\n", + "The `/queryables` endpoint returns a list of fields that can be used to filter features in requests for a collection:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "bcf33106-51c5-49b2-9324-743362ec3af2", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"title\": \"features.terrestrial_ecoregions\",\n", + " \"properties\": {\n", + " \"geom\": {\n", + " \"$ref\": \"https://geojson.org/schema/MultiPolygon.json\"\n", + " },\n", + " \"area\": {\n", + " \"name\": \"area\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"area_km2\": {\n", + " \"name\": \"area_km2\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"biome\": {\n", + " \"name\": \"biome\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"eco_code\": {\n", + " \"name\": \"eco_code\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"eco_id\": {\n", + " \"name\": \"eco_id\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"eco_name\": {\n", + " \"name\": \"eco_name\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"eco_num\": {\n", + " \"name\": \"eco_num\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"eco_sym\": {\n", + " \"name\": \"eco_sym\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"g200_biome\": {\n", + " \"name\": \"g200_biome\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"g200_num\": {\n", + " \"name\": \"g200_num\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"g200_regio\": {\n", + " \"name\": \"g200_regio\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"g200_stat\": {\n", + " \"name\": \"g200_stat\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"gbl_stat\": {\n", + " \"name\": \"gbl_stat\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"id\": {\n", + " \"name\": \"id\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"objectid\": {\n", + " \"name\": \"objectid\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"per_area\": {\n", + " \"name\": \"per_area\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"per_area_1\": {\n", + " \"name\": \"per_area_1\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"per_area_2\": {\n", + " \"name\": \"per_area_2\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"perimeter\": {\n", + " \"name\": \"perimeter\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"realm\": {\n", + " \"name\": \"realm\",\n", + " \"type\": \"string\"\n", + " },\n", + " \"shape_area\": {\n", + " \"name\": \"shape_area\",\n", + " \"type\": \"number\"\n", + " },\n", + " \"shape_leng\": {\n", + " \"name\": \"shape_leng\",\n", + " \"type\": \"number\"\n", + " }\n", + " },\n", + " \"type\": \"object\",\n", + " \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\n", + " \"$id\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/queryables\"\n", + "}\n" + ] + } + ], + "source": [ + "collection_id = \"features.terrestrial_ecoregions\"\n", + "\n", + "queryables_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/queryables\"\n", + ")\n", + "\n", + "print(json.dumps(queryables_request.json(), indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "ae165899-69b5-403f-b15f-116e42bd1cd1", + "metadata": {}, + "source": [ + "### 5.2.2 /collections/{collection_id}/items\n", + "\n", + "The `/items` endpoint for a collection can be used to retrieve paginated lists of features in a number of formats:\n", + " - GeoJSON\n", + " - CSV\n", + " - JSON\n", + " - GeoJSON Sequence\n", + " - NDJSON (new-line-delimited JSON)\n", + " - HTML (for viewing in a browser)\n", + "\n", + "[source](https://github.com/developmentseed/tipg/blob/1a2e5eb6816d51f97ae1d5bbc1d1e952d996987b/tipg/factory.py#L757-L762)\n", + "\n", + "Try retrieving a page of results from the `features.terrestrial_ecoregions` collection. This will return a GeoJSON FeatureCollection with two features (`limit=2`):" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0be96e36-956a-4486-aea1-d09314b2b49b", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"type\": \"FeatureCollection\",\n", + " \"id\": \"features.terrestrial_ecoregions\",\n", + " \"title\": \"features.terrestrial_ecoregions\",\n", + " \"description\": \"features.terrestrial_ecoregions\",\n", + " \"numberMatched\": 14458,\n", + " \"numberReturned\": 2,\n", + " \"links\": [\n", + " {\n", + " \"title\": \"Collection\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\n", + " \"rel\": \"collection\",\n", + " \"type\": \"application/json\"\n", + " },\n", + " {\n", + " \"title\": \"Items\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items?f=geojson&limit=2\",\n", + " \"rel\": \"self\",\n", + " \"type\": \"application/geo+json\"\n", + " },\n", + " {\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items?f=geojson&limit=2&offset=2\",\n", + " \"rel\": \"next\",\n", + " \"type\": \"application/geo+json\",\n", + " \"title\": \"Next page\"\n", + " }\n", + " ],\n", + " \"features\": [\n", + " {\n", + " \"type\": \"Feature\",\n", + " \"geometry\": {\n", + " \"type\": \"MultiPolygon\",\n", + " \"coordinates\": [\n", + " [\n", + " [\n", + " [\n", + " -112.269721533,\n", + " 29.326477674\n", + " ],\n", + " [\n", + " -112.288085612,\n", + " 29.326271814\n", + " ],\n", + " [\n", + " -112.30207065,\n", + " 29.321869806\n", + " ],\n", + " [\n", + " -112.313644549,\n", + " 29.320189905\n", + " ],\n", + " [\n", + " -112.320777549,\n", + " 29.316841167\n", + " ],\n", + " [\n", + " -112.324989623,\n", + " 29.315979172\n", + " ],\n", + " [\n", + " -112.329490537,\n", + " 29.317375095\n", + " ],\n", + " [\n", + " -112.33276367,\n", + " 29.320391909\n", + " ],\n", + " [\n", + " -112.336730658,\n", + " 29.320041043\n", + " ],\n", + " [\n", + " -112.343643548,\n", + " 29.314392143\n", + " ],\n", + " [\n", + " -112.347297555,\n", + " 29.315589079\n", + " ],\n", + " [\n", + " -112.349532674,\n", + " 29.318044138\n", + " ],\n", + " [\n", + " -112.350349574,\n", + " 29.320272048\n", + " ],\n", + " [\n", + " -112.350341527,\n", + " 29.322913856\n", + " ],\n", + " [\n", + " -112.348998579,\n", + " 29.328520511\n", + " ],\n", + " [\n", + " -112.346343527,\n", + " 29.333462314\n", + " ],\n", + " [\n", + " -112.343353535,\n", + " 29.34005401\n", + " ],\n", + " [\n", + " -112.337051685,\n", + " 29.34927578\n", + " ],\n", + " [\n", + " -112.334724533,\n", + " 29.353559603\n", + " ],\n", + " [\n", + " -112.332076522,\n", + " 29.357179579\n", + " ],\n", + " [\n", + " -112.32678268,\n", + " 29.362443415\n", + " ],\n", + " [\n", + " -112.323142587,\n", + " 29.365402226\n", + " ],\n", + " [\n", + " -112.318191564,\n", + " 29.367363927\n", + " ],\n", + " [\n", + " -112.310600577,\n", + " 29.367335931\n", + " ],\n", + " [\n", + " -112.305328528,\n", + " 29.366327086\n", + " ],\n", + " [\n", + " -112.30072066,\n", + " 29.364000269\n", + " ],\n", + " [\n", + " -112.288543599,\n", + " 29.356033438\n", + " ],\n", + " [\n", + " -112.281631546,\n", + " 29.352044658\n", + " ],\n", + " [\n", + " -112.276695611,\n", + " 29.347406951\n", + " ],\n", + " [\n", + " -112.274070567,\n", + " 29.344095931\n", + " ],\n", + " [\n", + " -112.270789555,\n", + " 29.338803095\n", + " ],\n", + " [\n", + " -112.268165684,\n", + " 29.335492243\n", + " ],\n", + " [\n", + " -112.267471662,\n", + " 29.331038435\n", + " ],\n", + " [\n", + " -112.269721533,\n", + " 29.326477674\n", + " ]\n", + " ]\n", + " ]\n", + " ]\n", + " },\n", + " \"id\": 1,\n", + " \"properties\": {\n", + " \"area\": 29.8029417004,\n", + " \"area_km2\": 8174,\n", + " \"biome\": 14.0,\n", + " \"eco_code\": \"NT1404\",\n", + " \"eco_id\": 61404.0,\n", + " \"eco_name\": \"Northern Mesoamerican Pacific mangroves\",\n", + " \"eco_num\": 4.0,\n", + " \"eco_sym\": 119.0,\n", + " \"g200_biome\": 0.0,\n", + " \"g200_num\": 0.0,\n", + " \"g200_regio\": null,\n", + " \"g200_stat\": 0.0,\n", + " \"gbl_stat\": 1.0,\n", + " \"id\": 1,\n", + " \"objectid\": 1,\n", + " \"per_area\": 0.0,\n", + " \"per_area_1\": 0.0,\n", + " \"per_area_2\": 0.0,\n", + " \"perimeter\": 0.219,\n", + " \"realm\": \"NT\",\n", + " \"shape_area\": 0.00276856457,\n", + " \"shape_leng\": 0.21947541388\n", + " },\n", + " \"links\": [\n", + " {\n", + " \"title\": \"Collection\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\n", + " \"rel\": \"collection\",\n", + " \"type\": \"application/json\"\n", + " },\n", + " {\n", + " \"title\": \"Item\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items/1\",\n", + " \"rel\": \"item\",\n", + " \"type\": \"application/geo+json\"\n", + " }\n", + " ]\n", + " },\n", + " {\n", + " \"type\": \"Feature\",\n", + " \"geometry\": {\n", + " \"type\": \"MultiPolygon\",\n", + " \"coordinates\": [\n", + " [\n", + " [\n", + " [\n", + " -112.199066615,\n", + " 29.175277696\n", + " ],\n", + " [\n", + " -112.207397556,\n", + " 29.177438383\n", + " ],\n", + " [\n", + " -112.213943655,\n", + " 29.177302596\n", + " ],\n", + " [\n", + " -112.218963577,\n", + " 29.175076698\n", + " ],\n", + " [\n", + " -112.222885637,\n", + " 29.175593694\n", + " ],\n", + " [\n", + " -112.224418687,\n", + " 29.177682464\n", + " ],\n", + " [\n", + " -112.21676668,\n", + " 29.195259818\n", + " ],\n", + " [\n", + " -112.203399556,\n", + " 29.238253114\n", + " ],\n", + " [\n", + " -112.20394153,\n", + " 29.255748325\n", + " ],\n", + " [\n", + " -112.198890595,\n", + " 29.24412581\n", + " ],\n", + " [\n", + " -112.195609583,\n", + " 29.238833141\n", + " ],\n", + " [\n", + " -112.198615669,\n", + " 29.229600475\n", + " ],\n", + " [\n", + " -112.198974582,\n", + " 29.22200865\n", + " ],\n", + " [\n", + " -112.197013552,\n", + " 29.215727922\n", + " ],\n", + " [\n", + " -112.19638055,\n", + " 29.208463327\n", + " ],\n", + " [\n", + " -112.194427567,\n", + " 29.200533544\n", + " ],\n", + " [\n", + " -112.194122633,\n", + " 29.194259689\n", + " ],\n", + " [\n", + " -112.19581561,\n", + " 29.181721368\n", + " ],\n", + " [\n", + " -112.199066615,\n", + " 29.175277696\n", + " ]\n", + " ]\n", + " ]\n", + " ]\n", + " },\n", + " \"id\": 2,\n", + " \"properties\": {\n", + " \"area\": 11.977823573,\n", + " \"area_km2\": 8174,\n", + " \"biome\": 14.0,\n", + " \"eco_code\": \"NT1404\",\n", + " \"eco_id\": 61404.0,\n", + " \"eco_name\": \"Northern Mesoamerican Pacific mangroves\",\n", + " \"eco_num\": 4.0,\n", + " \"eco_sym\": 119.0,\n", + " \"g200_biome\": 0.0,\n", + " \"g200_num\": 0.0,\n", + " \"g200_regio\": null,\n", + " \"g200_stat\": 0.0,\n", + " \"gbl_stat\": 1.0,\n", + " \"id\": 2,\n", + " \"objectid\": 2,\n", + " \"per_area\": 0.0,\n", + " \"per_area_1\": 0.0,\n", + " \"per_area_2\": 0.0,\n", + " \"perimeter\": 0.193,\n", + " \"realm\": \"NT\",\n", + " \"shape_area\": 0.00111124492,\n", + " \"shape_leng\": 0.19328912274\n", + " },\n", + " \"links\": [\n", + " {\n", + " \"title\": \"Collection\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\n", + " \"rel\": \"collection\",\n", + " \"type\": \"application/json\"\n", + " },\n", + " {\n", + " \"title\": \"Item\",\n", + " \"href\": \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items/2\",\n", + " \"rel\": \"item\",\n", + " \"type\": \"application/geo+json\"\n", + " }\n", + " ]\n", + " }\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "geojson_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/items\",\n", + " params={\"f\": \"geojson\", \"limit\": 2},\n", + ")\n", + "geojson_response = geojson_request.json()\n", + "print(json.dumps(geojson_response, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "fb774d33-1fe4-47be-93f4-1a794a2e2f7a", + "metadata": {}, + "source": [ + "You can request a sequence of GeoJSON features separated by new lines with `f=geojsonseq`" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fe8eb885-daf7-4d70-bc3d-579cc544c399", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"type\":\"Feature\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-112.269721533,29.326477674],[-112.288085612,29.326271814],[-112.30207065,29.321869806],[-112.313644549,29.320189905],[-112.320777549,29.316841167],[-112.324989623,29.315979172],[-112.329490537,29.317375095],[-112.33276367,29.320391909],[-112.336730658,29.320041043],[-112.343643548,29.314392143],[-112.347297555,29.315589079],[-112.349532674,29.318044138],[-112.350349574,29.320272048],[-112.350341527,29.322913856],[-112.348998579,29.328520511],[-112.346343527,29.333462314],[-112.343353535,29.34005401],[-112.337051685,29.34927578],[-112.334724533,29.353559603],[-112.332076522,29.357179579],[-112.32678268,29.362443415],[-112.323142587,29.365402226],[-112.318191564,29.367363927],[-112.310600577,29.367335931],[-112.305328528,29.366327086],[-112.30072066,29.364000269],[-112.288543599,29.356033438],[-112.281631546,29.352044658],[-112.276695611,29.347406951],[-112.274070567,29.344095931],[-112.270789555,29.338803095],[-112.268165684,29.335492243],[-112.267471662,29.331038435],[-112.269721533,29.326477674]]]]},\"id\":1,\"properties\":{\"area\":29.8029417004,\"area_km2\":8174,\"biome\":14.0,\"eco_code\":\"NT1404\",\"eco_id\":61404.0,\"eco_name\":\"Northern Mesoamerican Pacific mangroves\",\"eco_num\":4.0,\"eco_sym\":119.0,\"g200_biome\":0.0,\"g200_num\":0.0,\"g200_regio\":null,\"g200_stat\":0.0,\"gbl_stat\":1.0,\"id\":1,\"objectid\":1,\"per_area\":0.0,\"per_area_1\":0.0,\"per_area_2\":0.0,\"perimeter\":0.219,\"realm\":\"NT\",\"shape_area\":0.00276856457,\"shape_leng\":0.21947541388},\"links\":[{\"title\":\"Collection\",\"href\":\"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\"rel\":\"collection\",\"type\":\"application/json\"},{\"title\":\"Item\",\"href\":\"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items/1\",\"rel\":\"item\",\"type\":\"application/geo+json\"}]}\n", + "{\"type\":\"Feature\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-112.199066615,29.175277696],[-112.207397556,29.177438383],[-112.213943655,29.177302596],[-112.218963577,29.175076698],[-112.222885637,29.175593694],[-112.224418687,29.177682464],[-112.21676668,29.195259818],[-112.203399556,29.238253114],[-112.20394153,29.255748325],[-112.198890595,29.24412581],[-112.195609583,29.238833141],[-112.198615669,29.229600475],[-112.198974582,29.22200865],[-112.197013552,29.215727922],[-112.19638055,29.208463327],[-112.194427567,29.200533544],[-112.194122633,29.194259689],[-112.19581561,29.181721368],[-112.199066615,29.175277696]]]]},\"id\":2,\"properties\":{\"area\":11.977823573,\"area_km2\":8174,\"biome\":14.0,\"eco_code\":\"NT1404\",\"eco_id\":61404.0,\"eco_name\":\"Northern Mesoamerican Pacific mangroves\",\"eco_num\":4.0,\"eco_sym\":119.0,\"g200_biome\":0.0,\"g200_num\":0.0,\"g200_regio\":null,\"g200_stat\":0.0,\"gbl_stat\":1.0,\"id\":2,\"objectid\":2,\"per_area\":0.0,\"per_area_1\":0.0,\"per_area_2\":0.0,\"perimeter\":0.193,\"realm\":\"NT\",\"shape_area\":0.00111124492,\"shape_leng\":0.19328912274},\"links\":[{\"title\":\"Collection\",\"href\":\"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions\",\"rel\":\"collection\",\"type\":\"application/json\"},{\"title\":\"Item\",\"href\":\"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/items/2\",\"rel\":\"item\",\"type\":\"application/geo+json\"}]}\n", + "\n" + ] + } + ], + "source": [ + "geojsonseq_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/items\",\n", + " params={\"f\": \"geojsonseq\", \"limit\": 2},\n", + ")\n", + "\n", + "print(geojsonseq_request.text)" + ] + }, + { + "cell_type": "markdown", + "id": "a17c0497-511a-4b7e-9b92-84b0e23dd24b", + "metadata": {}, + "source": [ + "You can apply a filter using the fields returned in the `/queryables` endpoint for a collection:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9b1271eb-d653-4452-a4f1-c0f178305c9d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "77 features match this filtered request out of 14458 features in the entire collection\n" + ] + } + ], + "source": [ + "filtered_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/items\",\n", + " params={\n", + " \"eco_name\": \"Northern Mesoamerican Pacific mangroves\",\n", + " \"f\": \"geojson\",\n", + " \"limit\": 2,\n", + " },\n", + ")\n", + "\n", + "filtered_response = filtered_request.json()\n", + "print(\n", + " f\"{filtered_response['numberMatched']} features match this filtered request\",\n", + " f\"out of {geojson_response['numberMatched']} features in the entire collection\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "25f60170-0b5d-4835-a81c-4459feee212a", + "metadata": {}, + "source": [ + "In addition to field-based filters, you can use other standard filter mechanisms:\n", + "- `ids`: limit to a comma-separated list of feature ids\n", + "- `bbox`: filter by bounding box\n", + "- `datetime`: filter by datetime (use with `datetime-column` parameter)\n", + "- `filter`: apply a CQL2 filter (use with `filter-lang` parameter set to cql2-text or cql2-json) for more complex filter operations" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2aafc321-ae06-469e-91ea-63c53ebb0733", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5 features match this filtered request out of 14458 features in the entire collection\n" + ] + } + ], + "source": [ + "# filter by bounding box\n", + "bbox_filtered_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/items\",\n", + " params={\"bbox\": \"-77,39,-76,40\", \"f\": \"geojson\", \"limit\": 2},\n", + ")\n", + "\n", + "bbox_filtered_response = bbox_filtered_request.json()\n", + "print(\n", + " f\"{bbox_filtered_response['numberMatched']} features match this filtered request\",\n", + " f\"out of {geojson_response['numberMatched']} features in the entire collection\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "bdb2a8c2-94f4-4064-9cc9-1275fe22c053", + "metadata": {}, + "source": [ + "tipg also comes with a convenient HTML response type which makes it possible to interact with the endpoints in your browser. The returned geojson features from a `/items` request will be displayed in a map!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7be40619-e4e4-4211-ad5b-303a82834a70", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import IFrame\n", + "\n", + "bbox_filtered_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/items\",\n", + " params={\n", + " \"bbox\": \"-77,39,-76,40\",\n", + " \"f\": \"html\",\n", + " },\n", + ")\n", + "\n", + "IFrame(\n", + " bbox_filtered_request.url,\n", + " width=1200,\n", + " height=800,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8a13692f-e964-4f14-b206-d4ff8da5035d", + "metadata": {}, + "source": [ + "Here is a view of the full API docs for the `/collections/{collection_id}/items` endpoint:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "9eb89183-7cf6-482d-aabf-8066a141928f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IFrame(\n", + " f\"{tipg_endpoint}/api.html#OGC Features API/items_collections__collectionId__items_get\",\n", + " width=1200,\n", + " height=800,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "fa9c7359-4502-4c4a-95ab-96e1e4c77e46", + "metadata": {}, + "source": [ + "## 5.3 OGC API - Tiles\n", + "\n", + "tipg also serves an OGC Tiles API for vector tiles.\n", + "\n", + "\n", + "\n", + "The Tiles API works exactly like the Features API but instead of taking requests for entire features it accepts requests for XYZ vector tiles that are very useful for streaming vector data into map client applications. This is useful because it will becomes impracticalimpossible to stream all of a collection's features into a map application as a geojson - tipg moves the simplification and filtering operations up to the PostGIS database and returns the minimum required data to the map client." + ] + }, + { + "cell_type": "markdown", + "id": "5c1595fd-48db-4bc3-bfb5-774025e001bf", + "metadata": {}, + "source": [ + "### 5.3.1 /collections/{collection_id/tiles/{tileMatrixSetId}/tilejson.json\n", + "\n", + "The `tilejson` endpoint is the most useful for adding vector tile layers to a map application. The response contains information about the available fields (which can be used for styling the vector tiles), the full collection extent, and the XYZ tile url that can be loaded as a layer in a map." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "962d67f3-95cd-410f-92a4-df6c343a26eb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"tilejson\": \"3.0.0\",\n", + " \"name\": \"features.terrestrial_ecoregions\",\n", + " \"version\": \"1.0.0\",\n", + " \"scheme\": \"xyz\",\n", + " \"tiles\": [\n", + " \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/tiles/WebMercatorQuad/{z}/{x}/{y}\"\n", + " ],\n", + " \"vector_layers\": [\n", + " {\n", + " \"id\": \"default\",\n", + " \"fields\": {\n", + " \"area\": \"number\",\n", + " \"area_km2\": \"number\",\n", + " \"biome\": \"number\",\n", + " \"eco_code\": \"string\",\n", + " \"eco_id\": \"number\",\n", + " \"eco_name\": \"string\",\n", + " \"eco_num\": \"number\",\n", + " \"eco_sym\": \"number\",\n", + " \"g200_biome\": \"number\",\n", + " \"g200_num\": \"number\",\n", + " \"g200_regio\": \"string\",\n", + " \"g200_stat\": \"number\",\n", + " \"gbl_stat\": \"number\",\n", + " \"id\": \"number\",\n", + " \"objectid\": \"number\",\n", + " \"per_area\": \"number\",\n", + " \"per_area_1\": \"number\",\n", + " \"per_area_2\": \"number\",\n", + " \"perimeter\": \"number\",\n", + " \"realm\": \"string\",\n", + " \"shape_area\": \"number\",\n", + " \"shape_leng\": \"number\"\n", + " },\n", + " \"minzoom\": 0,\n", + " \"maxzoom\": 22\n", + " }\n", + " ],\n", + " \"minzoom\": 0,\n", + " \"maxzoom\": 22,\n", + " \"bounds\": [\n", + " -180.0,\n", + " -89.89197540283203,\n", + " 180.0,\n", + " 83.62313079833984\n", + " ],\n", + " \"center\": [\n", + " 0.0,\n", + " -3.1344223022460938,\n", + " 0\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "tilejson_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/tilejson.json\",\n", + ")\n", + "tilejson_response = tilejson_request.json()\n", + "print(json.dumps(tilejson_response, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "f77155de-5c6f-470d-b2cc-293023d24f28", + "metadata": {}, + "source": [ + "All of the same rules for queryables and query parameters from the `/items` endpoint apply to the `/tiles` endpoints, too. The query parameters will be tacked onto the end of the XYZ tile URL:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "628777c3-b633-45ec-b0f5-9d07f59cbe28", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"tilejson\": \"3.0.0\",\n", + " \"name\": \"features.terrestrial_ecoregions\",\n", + " \"version\": \"1.0.0\",\n", + " \"scheme\": \"xyz\",\n", + " \"tiles\": [\n", + " \"https://ea1xibo0hd.execute-api.us-west-2.amazonaws.com/collections/features.terrestrial_ecoregions/tiles/WebMercatorQuad/{z}/{x}/{y}?eco_name=Northern+Mesoamerican+Pacific+mangroves\"\n", + " ],\n", + " \"vector_layers\": [\n", + " {\n", + " \"id\": \"default\",\n", + " \"fields\": {\n", + " \"area\": \"number\",\n", + " \"area_km2\": \"number\",\n", + " \"biome\": \"number\",\n", + " \"eco_code\": \"string\",\n", + " \"eco_id\": \"number\",\n", + " \"eco_name\": \"string\",\n", + " \"eco_num\": \"number\",\n", + " \"eco_sym\": \"number\",\n", + " \"g200_biome\": \"number\",\n", + " \"g200_num\": \"number\",\n", + " \"g200_regio\": \"string\",\n", + " \"g200_stat\": \"number\",\n", + " \"gbl_stat\": \"number\",\n", + " \"id\": \"number\",\n", + " \"objectid\": \"number\",\n", + " \"per_area\": \"number\",\n", + " \"per_area_1\": \"number\",\n", + " \"per_area_2\": \"number\",\n", + " \"perimeter\": \"number\",\n", + " \"realm\": \"string\",\n", + " \"shape_area\": \"number\",\n", + " \"shape_leng\": \"number\"\n", + " },\n", + " \"minzoom\": 0,\n", + " \"maxzoom\": 22\n", + " }\n", + " ],\n", + " \"minzoom\": 0,\n", + " \"maxzoom\": 22,\n", + " \"bounds\": [\n", + " -180.0,\n", + " -89.89197540283203,\n", + " 180.0,\n", + " 83.62313079833984\n", + " ],\n", + " \"center\": [\n", + " 0.0,\n", + " -3.1344223022460938,\n", + " 0\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "filtered_tilejson_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/tilejson.json\",\n", + " params={\n", + " \"eco_name\": \"Northern Mesoamerican Pacific mangroves\",\n", + " },\n", + ")\n", + "filtered_tilejson_response = filtered_tilejson_request.json()\n", + "print(json.dumps(filtered_tilejson_response, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "8aa43dd5-0e0b-4154-85b8-c582eea80678", + "metadata": {}, + "source": [ + "### 5.3.1 /collections/{collection_id/tiles/{tileMatrixSetId}/viewer\n", + "\n", + "For a quick demonstration of how vector tiles enable visualization of massive feature collections, check out this map of the `terrestrial_ecoregions` table that lives in our database. It has 14,000+ features which we would never dream of downloading to view in a web map. Instead, we let our map client make requests for simplified features for each XYZ tile as we explore the map." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "857f7870-4311-404b-8c88-640e89891e83", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viewer_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/viewer\",\n", + ")\n", + "\n", + "IFrame(\n", + " viewer_request.url,\n", + " width=1200,\n", + " height=800,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "7f80150b-c92c-40dc-b83a-e90b13a25012", + "metadata": {}, + "source": [ + "You can apply a field-based filter to limit the features to a subset of the full collection:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "d12d12ef-8b12-4c7a-b681-4aea02c44df5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "filtered_viewer_request = httpx.get(\n", + " f\"{tipg_endpoint}/collections/{collection_id}/tiles/WebMercatorQuad/viewer\",\n", + " params={\n", + " \"eco_name\": \"Northern Mesoamerican Pacific mangroves\",\n", + " },\n", + ")\n", + "\n", + "IFrame(\n", + " filtered_viewer_request.url,\n", + " width=1200,\n", + " height=800,\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}