From d2c1558b10eb51967f139f760f96c38c6afbf2ad Mon Sep 17 00:00:00 2001 From: mackdelany Date: Thu, 5 Aug 2021 10:32:08 +1200 Subject: [PATCH 01/10] mercantile --- src/titiler/mosaic/tests/test_factory.py | 29 +++++++++ src/titiler/mosaic/titiler/mosaic/factory.py | 63 ++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/src/titiler/mosaic/tests/test_factory.py b/src/titiler/mosaic/tests/test_factory.py index af2001b9b..ed083b1e5 100644 --- a/src/titiler/mosaic/tests/test_factory.py +++ b/src/titiler/mosaic/tests/test_factory.py @@ -142,3 +142,32 @@ def test_MosaicTilerFactory(): "/mosaic/validate", json=MosaicJSON.from_urls(assets).dict(), ) assert response.status_code == 200 + + response = client.get("/mosaic/0302320/assets", params={"url": mosaic_file},) + assert response.status_code == 200 + assert all( + filepath.split("/")[-1] in ["cog1.tif"] for filepath in response.json() + ) + + response = client.get("/mosaic/-71,46/assets", params={"url": mosaic_file},) + assert response.status_code == 200 + assert all( + filepath.split("/")[-1] in ["cog1.tif", "cog2.tif"] + for filepath in response.json() + ) + + response = client.get( + "/mosaic/-75.9375,43.06888777416962,-73.125,45.089035564831015/assets", + params={"url": mosaic_file}, + ) + assert response.status_code == 200 + assert all( + filepath.split("/")[-1] in ["cog1.tif", "cog2.tif"] + for filepath in response.json() + ) + + response = client.get( + "/mosaic/10,10,11,11/assets", params={"url": mosaic_file}, + ) + assert response.status_code == 200 + assert response.json() == [] diff --git a/src/titiler/mosaic/titiler/mosaic/factory.py b/src/titiler/mosaic/titiler/mosaic/factory.py index 536961782..d96e6056a 100644 --- a/src/titiler/mosaic/titiler/mosaic/factory.py +++ b/src/titiler/mosaic/titiler/mosaic/factory.py @@ -5,6 +5,7 @@ from typing import Callable, Dict, Optional, Type from urllib.parse import urlencode, urlparse +import mercantile import rasterio from cogeo_mosaic.backends import BaseBackend, MosaicBackend from cogeo_mosaic.models import Info as mosaicInfo @@ -484,3 +485,65 @@ def validate(self): def validate(body: MosaicJSON): """Validate a MosaicJSON""" return True + + def assets(self): + """Register /assets endpoint.""" + + @self.router.get( + r"/{minx},{miny},{maxx},{maxy}/assets", + responses={200: {"description": "Return list of COGs in bounding box"}}, + ) + def bbox( + src_path=Depends(self.path_dependency), + minx: float = Query(None, description="Left side of bounding box"), + miny: float = Query(None, description="Bottom of bounding box"), + maxx: float = Query(None, description="Right side of bounding box"), + maxy: float = Query(None, description="Top of bounding box"), + ): + """Return a list of assets which overlap a bounding box""" + with self.reader(src_path, **self.backend_options) as mosaic: + tl_tile = mercantile.tile(minx, maxy, mosaic.minzoom) + br_tile = mercantile.tile(maxx, miny, mosaic.minzoom) + tiles = [ + (x, y, mosaic.minzoom) + for x in range(tl_tile.x, br_tile.x + 1) + for y in range(tl_tile.y, br_tile.y + 1) + ] + assets = list( + { + asset + for asset_list in [mosaic.assets_for_tile(*t) for t in tiles] + for asset in asset_list + } + ) + + return assets + + @self.router.get( + r"/{lng},{lat}/assets", + responses={200: {"description": "Return list of COGs"}}, + ) + def lonlat( + src_path=Depends(self.path_dependency), + lng: float = Query(None, description="Longitude"), + lat: float = Query(None, description="Latitude"), + ): + """Return a list of assets which overlap a point""" + with self.reader(src_path, **self.backend_options) as mosaic: + assets = mosaic.assets_for_point(lng, lat) + + return assets + + @self.router.get( + r"/{quadkey}/assets", + responses={200: {"description": "Return list of COGs"}}, + ) + def quadkey( + src_path=Depends(self.path_dependency), + quadkey: str = Query(None, description="Quadkey to return COGS for."), + ): + """Return a list of assets which overlap a given quadkey""" + with self.reader(src_path, **self.backend_options) as mosaic: + assets = mosaic.assets_for_tile(*mercantile.quadkey_to_tile(quadkey)) + + return assets From 92207c27c543129a7875f3b4552198bd09cb542d Mon Sep 17 00:00:00 2001 From: mackdelany Date: Thu, 5 Aug 2021 10:55:16 +1200 Subject: [PATCH 02/10] test fixes --- src/titiler/mosaic/tests/test_factory.py | 4 ++-- src/titiler/mosaic/titiler/mosaic/factory.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/titiler/mosaic/tests/test_factory.py b/src/titiler/mosaic/tests/test_factory.py index ed083b1e5..ca5117007 100644 --- a/src/titiler/mosaic/tests/test_factory.py +++ b/src/titiler/mosaic/tests/test_factory.py @@ -41,7 +41,7 @@ def test_MosaicTilerFactory(): optional_headers=[OptionalHeader.server_timing, OptionalHeader.x_assets], router_prefix="mosaic", ) - assert len(mosaic.router.routes) == 19 + assert len(mosaic.router.routes) == 22 assert mosaic.tms_dependency == WebMercatorTMSParams app = FastAPI() @@ -143,7 +143,7 @@ def test_MosaicTilerFactory(): ) assert response.status_code == 200 - response = client.get("/mosaic/0302320/assets", params={"url": mosaic_file},) + response = client.get("/mosaic/0302302/assets", params={"url": mosaic_file},) assert response.status_code == 200 assert all( filepath.split("/")[-1] in ["cog1.tif"] for filepath in response.json() diff --git a/src/titiler/mosaic/titiler/mosaic/factory.py b/src/titiler/mosaic/titiler/mosaic/factory.py index d96e6056a..602e5a872 100644 --- a/src/titiler/mosaic/titiler/mosaic/factory.py +++ b/src/titiler/mosaic/titiler/mosaic/factory.py @@ -65,6 +65,7 @@ def register_routes(self): self.wmts() self.point() self.validate() + self.assets() ############################################################################ # /read From b5a09c4a7491584416e30f7025bcf2fe068c08e4 Mon Sep 17 00:00:00 2001 From: mackdelany Date: Fri, 6 Aug 2021 14:04:44 +1200 Subject: [PATCH 03/10] changelog, docs and mercantile req --- CHANGES.md | 601 ++++++++++++++++++------------------ docs/endpoints/mosaic.md | 24 +- src/titiler/mosaic/setup.py | 5 +- 3 files changed, 321 insertions(+), 309 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ef70aef32..40f30c0b9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,40 +1,45 @@ # Release Notes +## 0.3.5 (2021-08-05) + +### titiler.mosaic + +- add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return lists of assets that overlap a given geometry (https://github.com/developmentseed/titiler/pull/351) + ## 0.3.4 (2021-08-02) ### titiler.core -* add `/crop` POST endpoint to return an image from a GeoJSON feature (https://github.com/developmentseed/titiler/pull/339) -* add `/statistics` (GET and POST) endpoints to return advanced images statistics (https://github.com/developmentseed/titiler/pull/347) +- add `/crop` POST endpoint to return an image from a GeoJSON feature (https://github.com/developmentseed/titiler/pull/339) +- add `/statistics` (GET and POST) endpoints to return advanced images statistics (https://github.com/developmentseed/titiler/pull/347) ### titiler.application -* add optional `root_path` setting to specify a url path prefix to use when running the app behind a reverse proxy (https://github.com/developmentseed/titiler/pull/343) +- add optional `root_path` setting to specify a url path prefix to use when running the app behind a reverse proxy (https://github.com/developmentseed/titiler/pull/343) ## 0.3.3 (2021-06-29) ### titiler.core -* fix possible bug when querystring parameter are case insensitive (https://github.com/developmentseed/titiler/pull/323) +- fix possible bug when querystring parameter are case insensitive (https://github.com/developmentseed/titiler/pull/323) ### titiler.mosaic -* update `tilejson` and `WMTSCapabilities.xml` endpoints to allow list querystrings (as done previously in https://github.com/developmentseed/titiler/issues/319) +- update `tilejson` and `WMTSCapabilities.xml` endpoints to allow list querystrings (as done previously in https://github.com/developmentseed/titiler/issues/319) ### titiler.application -* add `titiler.application.middleware.LowerCaseQueryStringMiddleware` to cast all query string parameter to lowercase (author @lorenzori, https://github.com/developmentseed/titiler/pull/321) - +- add `titiler.application.middleware.LowerCaseQueryStringMiddleware` to cast all query string parameter to lowercase (author @lorenzori, https://github.com/developmentseed/titiler/pull/321) ### code and repo -* move `titiler` code to `src/titiler` +- move `titiler` code to `src/titiler` ## 0.3.2 (2021-05-26) ### titiler.core -* update rio-tiler dependency to `>=2.1` version and update `rescale` query-parameter (https://github.com/developmentseed/titiler/issues/319) +- update rio-tiler dependency to `>=2.1` version and update `rescale` query-parameter (https://github.com/developmentseed/titiler/issues/319) ``` # before @@ -48,138 +53,140 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ### titiler.mosaic -* update `cogeo-mosaic` version to `>=3.0,<3.1`. +- update `cogeo-mosaic` version to `>=3.0,<3.1`. ### titiler.application -* re-order middlewares (https://github.com/developmentseed/titiler/issues/311) -* update rio-cogeo version to `>=2.2` and use `rio_cogeo.models` instead of custom ones. - +- re-order middlewares (https://github.com/developmentseed/titiler/issues/311) +- update rio-cogeo version to `>=2.2` and use `rio_cogeo.models` instead of custom ones. ## 0.3.1 (2021-04-27) -* add `exclude_path` options in `titiler.application.middleware.CacheControlMiddleware` to avoid adding cache-control headers to specific paths. -* allow `histogram_bins` to be a single value or a `,` delimited scalar (https://github.com/developmentseed/titiler/pull/307) -* change error status from `404` to `500` for `RasterioIOError` exception (author @kylebarron, https://github.com/developmentseed/titiler/pull/300) +- add `exclude_path` options in `titiler.application.middleware.CacheControlMiddleware` to avoid adding cache-control headers to specific paths. +- allow `histogram_bins` to be a single value or a `,` delimited scalar (https://github.com/developmentseed/titiler/pull/307) +- change error status from `404` to `500` for `RasterioIOError` exception (author @kylebarron, https://github.com/developmentseed/titiler/pull/300) - Sometimes GDAL/Rasterio can lose track of the file handler (might be related to cache issue + threading) and raise `RasterioIOError: file not found`, while the file exists for real. To avoid caching this, we changed the error code to 500 (errors >= 500 do not get `cache-control` header on titiler.application). + Sometimes GDAL/Rasterio can lose track of the file handler (might be related to cache issue + threading) and raise `RasterioIOError: file not found`, while the file exists for real. To avoid caching this, we changed the error code to 500 (errors >= 500 do not get `cache-control` header on titiler.application). ## 0.3.0 (2021-04-19) -* add support for `.jpg` and `.jpeg` extensions (https://github.com/developmentseed/titiler/pull/271) -* better error message when parsing the colormap value fails (https://github.com/developmentseed/titiler/pull/279) +- add support for `.jpg` and `.jpeg` extensions (https://github.com/developmentseed/titiler/pull/271) +- better error message when parsing the colormap value fails (https://github.com/developmentseed/titiler/pull/279) **breaking change** -* split `titiler` into a set of namespaces packages (https://github.com/developmentseed/titiler/pull/284) +- split `titiler` into a set of namespaces packages (https://github.com/developmentseed/titiler/pull/284) + + **titiler.core** + + The `core` package host the low level tiler factories. - **titiler.core** + ```python + # before + from titiler.endpoints.factory import TilerFactory - The `core` package host the low level tiler factories. - ```python - # before - from titiler.endpoints.factory import TilerFactory + # now + from titiler.core.factory import TilerFactory + ``` - # now - from titiler.core.factory import TilerFactory - ``` + **titiler.mosaic** - **titiler.mosaic** + The `mosaic` package is a plugin to `titiler.core` which adds support for MosaicJSON - The `mosaic` package is a plugin to `titiler.core` which adds support for MosaicJSON - ```python - # before - from titiler.endpoints.factory import MosaicTilerFactory + ```python + # before + from titiler.endpoints.factory import MosaicTilerFactory - # now - from titiler.mosaic.factory import MosaicTilerFactory - ``` + # now + from titiler.mosaic.factory import MosaicTilerFactory + ``` - **titiler.application** + **titiler.application** - The `application` package is a full `ready to use` FastAPI application with support of STAC, COG and MosaicJSON. + The `application` package is a full `ready to use` FastAPI application with support of STAC, COG and MosaicJSON. - ```bash - # before - $ pip install titiler - $ uvicorn titiler.main:app --reload + ```bash + # before + $ pip install titiler + $ uvicorn titiler.main:app --reload - # now - $ pip install titiler.application uvicorn - $ uvicorn titiler.application.main:app --reload - ``` + # now + $ pip install titiler.application uvicorn + $ uvicorn titiler.application.main:app --reload + ``` ## 0.2.0 (2021-03-09) -* adapt for cogeo-mosaic `3.0.0rc2` and add `backend_options` attribute in MosaicTilerFactory (https://github.com/developmentseed/titiler/pull/247) -* update FastAPI requirements -* update minimal python version to 3.6 -* add `**render_params.kwargs` to pass custom render params in `image.render` method (https://github.com/developmentseed/titiler/pull/259) -* Changed probe url from `/ping` to `/healthz` in k8s deployment +- adapt for cogeo-mosaic `3.0.0rc2` and add `backend_options` attribute in MosaicTilerFactory (https://github.com/developmentseed/titiler/pull/247) +- update FastAPI requirements +- update minimal python version to 3.6 +- add `**render_params.kwargs` to pass custom render params in `image.render` method (https://github.com/developmentseed/titiler/pull/259) +- Changed probe url from `/ping` to `/healthz` in k8s deployment **breaking change** -* renamed `OptionalHeaders`, `MimeTypes` and `ImageDrivers` enums to the singular form (https://github.com/developmentseed/titiler/pull/258) -* renamed titiler.dependencies's Enums (`ColorMapName`, `ResamplingName` and `TileMatrixSetName`) to the singular form (https://github.com/developmentseed/titiler/pull/260) -* renamed `MimeType` to `MediaType` (https://github.com/developmentseed/titiler/pull/258) -* add `ColorMapParams` dependency to ease the creation of custom colormap dependency (https://github.com/developmentseed/titiler/pull/252) -* renamed `PathParams` to `DatasetPathParams` and also made it a simple callable (https://github.com/developmentseed/titiler/pull/260) -* renamed `colormap` query-parameter to `colormap_name` (https://github.com/developmentseed/titiler/pull/262) - ``` - # before - /cog/preview.png?colormap=viridis - - # now - /cog/preview.png?colormap_name=viridis - ``` - -* use `colormap` query-parameter to pass custom colormap (https://github.com/developmentseed/titiler/pull/262) - ``` - /cog/preview.png?colormap={"0": "#FFFF00FF", ...} - ``` +- renamed `OptionalHeaders`, `MimeTypes` and `ImageDrivers` enums to the singular form (https://github.com/developmentseed/titiler/pull/258) +- renamed titiler.dependencies's Enums (`ColorMapName`, `ResamplingName` and `TileMatrixSetName`) to the singular form (https://github.com/developmentseed/titiler/pull/260) +- renamed `MimeType` to `MediaType` (https://github.com/developmentseed/titiler/pull/258) +- add `ColorMapParams` dependency to ease the creation of custom colormap dependency (https://github.com/developmentseed/titiler/pull/252) +- renamed `PathParams` to `DatasetPathParams` and also made it a simple callable (https://github.com/developmentseed/titiler/pull/260) +- renamed `colormap` query-parameter to `colormap_name` (https://github.com/developmentseed/titiler/pull/262) + + ``` + # before + /cog/preview.png?colormap=viridis + + # now + /cog/preview.png?colormap_name=viridis + ``` + +- use `colormap` query-parameter to pass custom colormap (https://github.com/developmentseed/titiler/pull/262) + ``` + /cog/preview.png?colormap={"0": "#FFFF00FF", ...} + ``` ## 0.1.0 (2021-02-17) -* update FastAPI requirements -* add `validate` in `MosaicTilerFactory` (https://github.com/developmentseed/titiler/pull/206, author @drnextgis) -* rename `ressources` package to `resources` (https://github.com/developmentseed/titiler/pull/210, author @drnextgis) -* renamed environment variables prefixes for API and STACK configurations: `TITILER_STACK` as prefix to CDK and `TITILER_API` as prefix to API (https://github.com/developmentseed/titiler/pull/211, author @fredliporace) -* remove MosaicTilerFactory `create` and `update` endpoints (https://github.com/developmentseed/titiler/pull/218) -* deleted `titiler.models.mosaics` because the models are not used anymore (https://github.com/developmentseed/titiler/pull/221) -* update rio-tiler and cogeo-mosaic minimal versions (https://github.com/developmentseed/titiler/pull/220, https://github.com/developmentseed/titiler/pull/213) -* move STAC related dependencies to `titiler.dependencies (https://github.com/developmentseed/titiler/pull/225) -* add `rio_tiler.io.MultiBandReader` bands dependencies (https://github.com/developmentseed/titiler/pull/226) -* add `MultiBaseTilerFactory` and `MultiBandTilerFactory` custom tiler factories (https://github.com/developmentseed/titiler/pull/230) -* Update STAC tiler to use the new `MultiBaseTilerFactory` factory -* depreciate *empty* GET endpoint for MosaicTilerFactory read (https://github.com/developmentseed/titiler/pull/232) -* better `debug` configuration and make reponse headers metadata optional (https://github.com/developmentseed/titiler/pull/232) +- update FastAPI requirements +- add `validate` in `MosaicTilerFactory` (https://github.com/developmentseed/titiler/pull/206, author @drnextgis) +- rename `ressources` package to `resources` (https://github.com/developmentseed/titiler/pull/210, author @drnextgis) +- renamed environment variables prefixes for API and STACK configurations: `TITILER_STACK` as prefix to CDK and `TITILER_API` as prefix to API (https://github.com/developmentseed/titiler/pull/211, author @fredliporace) +- remove MosaicTilerFactory `create` and `update` endpoints (https://github.com/developmentseed/titiler/pull/218) +- deleted `titiler.models.mosaics` because the models are not used anymore (https://github.com/developmentseed/titiler/pull/221) +- update rio-tiler and cogeo-mosaic minimal versions (https://github.com/developmentseed/titiler/pull/220, https://github.com/developmentseed/titiler/pull/213) +- move STAC related dependencies to `titiler.dependencies (https://github.com/developmentseed/titiler/pull/225) +- add `rio_tiler.io.MultiBandReader` bands dependencies (https://github.com/developmentseed/titiler/pull/226) +- add `MultiBaseTilerFactory` and `MultiBandTilerFactory` custom tiler factories (https://github.com/developmentseed/titiler/pull/230) +- Update STAC tiler to use the new `MultiBaseTilerFactory` factory +- depreciate _empty_ GET endpoint for MosaicTilerFactory read (https://github.com/developmentseed/titiler/pull/232) +- better `debug` configuration and make reponse headers metadata optional (https://github.com/developmentseed/titiler/pull/232) **breaking change** -* update `titiler.dependencies.AssetsBidxParams` to make `asset` a required parameter (https://github.com/developmentseed/titiler/pull/230 -* the STAC `/info` endpoint now expect the `assets` parameter to be passed. To ge the list of available assets we added a new `/assets` endpoint within the tiler factory -* remove `COGReader` as default `reader` in `titiler.endpoints.factory.BaseTilerFactory` +- update `titiler.dependencies.AssetsBidxParams` to make `asset` a required parameter (https://github.com/developmentseed/titiler/pull/230 +- the STAC `/info` endpoint now expect the `assets` parameter to be passed. To ge the list of available assets we added a new `/assets` endpoint within the tiler factory +- remove `COGReader` as default `reader` in `titiler.endpoints.factory.BaseTilerFactory` ## 0.1.0a14 (2021-01-05) -* add `rio_tiler.errors.MissingBands` in known errors. -* add `titiler.endpoints.factory.TMSFactory` to enable custom TMS endpoints. -* **breaking** rename `BaseFactory` to `BaseTilerFactory` in `titiler.endpoints.factory` +- add `rio_tiler.errors.MissingBands` in known errors. +- add `titiler.endpoints.factory.TMSFactory` to enable custom TMS endpoints. +- **breaking** rename `BaseFactory` to `BaseTilerFactory` in `titiler.endpoints.factory` ## 0.1.0a13 (2020-12-20) -* allow `API_DISABLE_{COG/STAC/MOSAIC}` environment variables to control default endpoints in titiler main app (https://github.com/developmentseed/titiler/issues/156) -* add `overwriting=False/True` on MosaicJSON creation (https://github.com/developmentseed/titiler/issues/164) -* add `gdal_config` option to Tiler factories to replace custom `APIRoute` class (https://github.com/developmentseed/titiler/issues/168) -* add `info.geojson` endpoint to return dataset info as a GeoJSON feature (https://github.com/developmentseed/titiler/issues/166) -* update `rio-tiler`, `cogeo-mosaic` and optional dependencies +- allow `API_DISABLE_{COG/STAC/MOSAIC}` environment variables to control default endpoints in titiler main app (https://github.com/developmentseed/titiler/issues/156) +- add `overwriting=False/True` on MosaicJSON creation (https://github.com/developmentseed/titiler/issues/164) +- add `gdal_config` option to Tiler factories to replace custom `APIRoute` class (https://github.com/developmentseed/titiler/issues/168) +- add `info.geojson` endpoint to return dataset info as a GeoJSON feature (https://github.com/developmentseed/titiler/issues/166) +- update `rio-tiler`, `cogeo-mosaic` and optional dependencies ## 0.1.0a12 (2020-11-18) -* require `rio-tiler>=2.0.0rc2` -* update Enums for Image types. (**breaking**) -* Add more output datatype (jpeg2000, pngraw) -* add `width/height` in `/crop` endpoint path +- require `rio-tiler>=2.0.0rc2` +- update Enums for Image types. (**breaking**) +- Add more output datatype (jpeg2000, pngraw) +- add `width/height` in `/crop` endpoint path ``` /crop/{minx},{miny},{maxx},{maxy}.{format} @@ -188,7 +195,7 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ## 0.1.0a11.post1 (2020-11-12) -* relax version for rio-tiler and cogeo-mosaic +- relax version for rio-tiler and cogeo-mosaic ```python "rio-cogeo~=2.0" @@ -198,39 +205,39 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ## 0.1.0a11 (2020-11-12) -* split `tile()` for `MosaicTilerFactory` method (https://github.com/developmentseed/titiler/issues/147) +- split `tile()` for `MosaicTilerFactory` method (https://github.com/developmentseed/titiler/issues/147) ## 0.1.0a10 (2020-11-09) -* update for rio-tiler==2.0.0rc1, cogeo-mosaic==3.0.0a17 and morecantile==2.0 -* split `tile()` factory method (https://github.com/developmentseed/titiler/issues/141, author @fredliporace) +- update for rio-tiler==2.0.0rc1, cogeo-mosaic==3.0.0a17 and morecantile==2.0 +- split `tile()` factory method (https://github.com/developmentseed/titiler/issues/141, author @fredliporace) ## 0.1.0a9 (2020-10-26) -* avoid changing mutable TMS and Colormap list by using deepcopy. -* quiet/turn off logs -* add logger middleware (https://github.com/developmentseed/titiler/pull/139) +- avoid changing mutable TMS and Colormap list by using deepcopy. +- quiet/turn off logs +- add logger middleware (https://github.com/developmentseed/titiler/pull/139) ## 0.1.0a8 (2020-10-13) -* update for rio-tiler 2.0.0b17, which now support TMS (morecantile) by default. -* update fastapi minimum version to 0.61 +- update for rio-tiler 2.0.0b17, which now support TMS (morecantile) by default. +- update fastapi minimum version to 0.61 **breaking changes** -* removed TMSTilerFactory (because default reader built with rio_tiler BaseReader should support TMS). +- removed TMSTilerFactory (because default reader built with rio_tiler BaseReader should support TMS). Note: We changed the versioning scheme to `{major}.{minor}.{path}{pre}{prenum}` ## 0.1.0-alpha.7 (2020-10-13) -* remove `pkg_resources` (https://github.com/pypa/setuptools/issues/510) +- remove `pkg_resources` (https://github.com/pypa/setuptools/issues/510) ## 0.1.0-alpha.6 (2020-10-05) -* refactor CacheControl Middleware -* rename headers value `X-Server-Timings` to `Server-Timing`. -* add `total;dur={}` in response header `Server-Timing`, using new `titiler.middleware.TotalTimeMiddleware` middleware (113) +- refactor CacheControl Middleware +- rename headers value `X-Server-Timings` to `Server-Timing`. +- add `total;dur={}` in response header `Server-Timing`, using new `titiler.middleware.TotalTimeMiddleware` middleware (113) ```python from titiler.middleware import CacheControlMiddleware, TotalTimeMiddleware @@ -240,200 +247,204 @@ app.add_middleware(CacheControlMiddleware, cachecontrol="public, max-age=3600") app.add_middleware(TotalTimeMiddleware) ``` -* Add Brotli compression support (#126, author @kylebarron) -* Numerous fix to CDK app.py (co-author @kylebarron) +- Add Brotli compression support (#126, author @kylebarron) +- Numerous fix to CDK app.py (co-author @kylebarron) ## 0.1.0-alpha.5 (2020-09-22) -* exclude `tests/` an `stack/` in titiler python package. -* add `EPSG6933` in TMS +- exclude `tests/` an `stack/` in titiler python package. +- add `EPSG6933` in TMS **breaking changes** -* [FACTORY] the `additional_dependency` should be a Callable which return a dict. - - ```python - @dataclass # type: ignore - class BaseFactory(metaclass=abc.ABCMeta): - """BaseTiler Factory.""" - ... - # provide custom dependency - additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) - ``` - - ```python - def AssetsParams( - assets: Optional[str] = Query( - None, - title="Asset indexes", - description="comma (',') delimited asset names (might not be an available options of some readers)", - ) - ) -> Dict: - """Assets Dependency.""" - kwargs = {} - if assets: - kwargs["assets"] = assets.split(",") - return kwargs - ``` -* [FACTORY] remove `_` prefix in factory methods (e.g `_tile` -> `tile`) -* [FACTORY] refactor dependencies to better align with rio_tiler.io.BaseReader method definition. - - Example: - - In the `metadata`, the `MetadataParams` will be used to pass `pmin` and `pmax` because they are the only - required parameters for the metadata method. All other params will be passed to a `kwargs` dict. - - ```python - @dataclass - class MetadataParams(DefaultDependency): - """Common Metadada parameters.""" - # Required params - pmin: float = Query(2.0, description="Minimum percentile") - pmax: float = Query(98.0, description="Maximum percentile") - # Optional parameters - bidx: Optional[str] = Query( - None, title="Band indexes", description="comma (',') delimited band indexes", - ) - ... - def __post_init__(self): - """Post Init.""" - - if self.bidx is not None: - self.kwargs["indexes"] = tuple( - int(s) for s in re.findall(r"\d+", self.bidx) - ) - ... - - # metadata method in factory - def metadata( - src_path=Depends(self.path_dependency), - metadata_params=Depends(self.metadata_dependency), - kwargs: Dict = Depends(self.additional_dependency), - ): - """Return metadata.""" - reader = src_path.reader or self.reader - with reader(src_path.url, **self.reader_options) as src_dst: - info = src_dst.metadata( - metadata_params.pmin, - metadata_params.pmax, - **metadata_params.kwargs, - **kwargs, - ) - return info - ``` -* [FACTORY] refactor dependencies definition - ```python - @dataclass # type: ignore - class BaseFactory(metaclass=abc.ABCMeta): - """BaseTiler Factory.""" - - reader: default_readers_type = field(default=COGReader) - reader_options: Dict = field(default_factory=dict) - - # FastAPI router - router: APIRouter = field(default_factory=APIRouter) - - # Path Dependency - path_dependency: Type[PathParams] = field(default=PathParams) - - # Rasterio Dataset Options (nodata, unscale, resampling) - dataset_dependency: default_deps_type = field(default=DatasetParams) - - # Indexes/Expression Dependencies - layer_dependency: default_deps_type = field(default=BidxExprParams) - - # Image rendering Dependencies - render_dependency: default_deps_type = field(default=RenderParams) - - # TileMatrixSet dependency - tms_dependency: Callable[..., TileMatrixSet] = WebMercatorTMSParams - - # provide custom dependency - additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) - ``` - -* remove `PathParams.reader` attribute. This option was not used and would have been technically difficult to use. - ```python - @dataclass - class PathParams: - """Create dataset path from args""" - - url: str = Query(..., description="Dataset URL") - ``` +- [FACTORY] the `additional_dependency` should be a Callable which return a dict. + + ```python + @dataclass # type: ignore + class BaseFactory(metaclass=abc.ABCMeta): + """BaseTiler Factory.""" + ... + # provide custom dependency + additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) + ``` + + ```python + def AssetsParams( + assets: Optional[str] = Query( + None, + title="Asset indexes", + description="comma (',') delimited asset names (might not be an available options of some readers)", + ) + ) -> Dict: + """Assets Dependency.""" + kwargs = {} + if assets: + kwargs["assets"] = assets.split(",") + return kwargs + ``` + +- [FACTORY] remove `_` prefix in factory methods (e.g `_tile` -> `tile`) +- [FACTORY] refactor dependencies to better align with rio_tiler.io.BaseReader method definition. + + Example: + + In the `metadata`, the `MetadataParams` will be used to pass `pmin` and `pmax` because they are the only + required parameters for the metadata method. All other params will be passed to a `kwargs` dict. + + ```python + @dataclass + class MetadataParams(DefaultDependency): + """Common Metadada parameters.""" + # Required params + pmin: float = Query(2.0, description="Minimum percentile") + pmax: float = Query(98.0, description="Maximum percentile") + # Optional parameters + bidx: Optional[str] = Query( + None, title="Band indexes", description="comma (',') delimited band indexes", + ) + ... + def __post_init__(self): + """Post Init.""" + + if self.bidx is not None: + self.kwargs["indexes"] = tuple( + int(s) for s in re.findall(r"\d+", self.bidx) + ) + ... + + # metadata method in factory + def metadata( + src_path=Depends(self.path_dependency), + metadata_params=Depends(self.metadata_dependency), + kwargs: Dict = Depends(self.additional_dependency), + ): + """Return metadata.""" + reader = src_path.reader or self.reader + with reader(src_path.url, **self.reader_options) as src_dst: + info = src_dst.metadata( + metadata_params.pmin, + metadata_params.pmax, + **metadata_params.kwargs, + **kwargs, + ) + return info + ``` + +- [FACTORY] refactor dependencies definition + + ```python + @dataclass # type: ignore + class BaseFactory(metaclass=abc.ABCMeta): + """BaseTiler Factory.""" + + reader: default_readers_type = field(default=COGReader) + reader_options: Dict = field(default_factory=dict) + + # FastAPI router + router: APIRouter = field(default_factory=APIRouter) + + # Path Dependency + path_dependency: Type[PathParams] = field(default=PathParams) + + # Rasterio Dataset Options (nodata, unscale, resampling) + dataset_dependency: default_deps_type = field(default=DatasetParams) + + # Indexes/Expression Dependencies + layer_dependency: default_deps_type = field(default=BidxExprParams) + + # Image rendering Dependencies + render_dependency: default_deps_type = field(default=RenderParams) + + # TileMatrixSet dependency + tms_dependency: Callable[..., TileMatrixSet] = WebMercatorTMSParams + + # provide custom dependency + additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) + ``` + +- remove `PathParams.reader` attribute. This option was not used and would have been technically difficult to use. + + ```python + @dataclass + class PathParams: + """Create dataset path from args""" + + url: str = Query(..., description="Dataset URL") + ``` ## 0.1.0-alpha.4 (2020-09-14) -* Update `.npy` output format to follow the numpyTile format (#103) - - ```python - import numpy - import requests - from io import BytesIO +- Update `.npy` output format to follow the numpyTile format (#103) - endpoint = ... - url = "https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif" + ```python + import numpy + import requests + from io import BytesIO - r = requests.get(f"{endpoint}/cog/tiles/14/10818/9146.npy", - params = { - "url": url, - } - ) - data = numpy.load(BytesIO(r.content)) - print(data.shape) - > (4, 256, 256) - ``` + endpoint = ... + url = "https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif" -* Add `titiler.custom.routing.apiroute_factory`. This function enable the creation of custom fastapi.routing.APIRoute class with `rasterio.Env()` block. + r = requests.get(f"{endpoint}/cog/tiles/14/10818/9146.npy", + params = { + "url": url, + } + ) + data = numpy.load(BytesIO(r.content)) + print(data.shape) + > (4, 256, 256) + ``` - ```python - from fastapi import FastAPI, APIRouter - from rasterio._env import get_gdal_config - from titiler.custom.routing import apiroute_factory +- Add `titiler.custom.routing.apiroute_factory`. This function enable the creation of custom fastapi.routing.APIRoute class with `rasterio.Env()` block. - app = FastAPI() - route_class = apiroute_factory({"GDAL_DISABLE_READDIR_ON_OPEN": "FALSE"}) - router = APIRouter(route_class=route_class) + ```python + from fastapi import FastAPI, APIRouter + from rasterio._env import get_gdal_config + from titiler.custom.routing import apiroute_factory - @router.get("/simple") - def simple(): - """should return FALSE.""" - res = get_gdal_config("GDAL_DISABLE_READDIR_ON_OPEN") - return {"env": res} + app = FastAPI() + route_class = apiroute_factory({"GDAL_DISABLE_READDIR_ON_OPEN": "FALSE"}) + router = APIRouter(route_class=route_class) - app.include_router(router) - ``` + @router.get("/simple") + def simple(): + """should return FALSE.""" + res = get_gdal_config("GDAL_DISABLE_READDIR_ON_OPEN") + return {"env": res} - Note: This has only be tested for python 3.6 and 3.7. + app.include_router(router) + ``` + Note: This has only be tested for python 3.6 and 3.7. ## 0.1.0-alpha.3 (2020-09-03) -* add custom `url_for` method in TilerFactory to retrieve `prefixed` endpoint URL (#95) -* remove magic `titiler.dependencies.PathParams` mosaicid path translation, where a user could pass `url=mosaicid://` to the endpoint. -* switch to `pydantic.BaseSettings` for FastAPI application setting management. +- add custom `url_for` method in TilerFactory to retrieve `prefixed` endpoint URL (#95) +- remove magic `titiler.dependencies.PathParams` mosaicid path translation, where a user could pass `url=mosaicid://` to the endpoint. +- switch to `pydantic.BaseSettings` for FastAPI application setting management. - List of Settings: + List of Settings: - ```python - name: str = "titiler" - cors_origins: str = "*" - cachecontrol: str = "public, max-age=3600" - ``` + ```python + name: str = "titiler" + cors_origins: str = "*" + cachecontrol: str = "public, max-age=3600" + ``` API Settings can now be set by adding a `.env` file in your local project or by setting environment variables (e.g `API_CORS_ORIGIN="https://mywebsite.com/*"`) ## 0.1.0-alpha.2 (2020-09-01) -* add Transform and CRS information in `/part` GeoTIFF output -* pin **rio-tiler-crs** to `>=3.0b4,<3.1` and **cogeo-mosaic** to `>=3.0a10,<3.1` +- add Transform and CRS information in `/part` GeoTIFF output +- pin **rio-tiler-crs** to `>=3.0b4,<3.1` and **cogeo-mosaic** to `>=3.0a10,<3.1` ## 0.1.0-alpha.1 (2020-09-01) -* rename titiler.models.cog.py to titiler.models.dataset.py -* remove cog* prefix to Bounds, Info and Metadata models -* allow Union[str, int] for key in Metadata.statistics (as defined in rio-tiler-pds) +- rename titiler.models.cog.py to titiler.models.dataset.py +- remove cog\* prefix to Bounds, Info and Metadata models +- allow Union[str, int] for key in Metadata.statistics (as defined in rio-tiler-pds) e.g Create a Landsat 8 Tiler + ```python from titiler.endpoints.factory import TilerFactory, MosaicTilerFactory from titiler.dependencies import BandsParams @@ -484,6 +495,7 @@ The `titiler.endpoints.factory.TilerFactory` class will create a tiler with `Web For other TMS support, tiler needs to be created with `titiler.endpoints.factory.TMSTilerFactory` and with a TMS friendly reader (e.g `rio_tiler_crs.COGReader`). **Simple tiler with only Web Mercator support** + ```python from rio_tiler.io import COGReader @@ -495,6 +507,7 @@ assert app.tms_dependency == WebMercatorTMSParams ``` **Tiler with more TMS support (from morecantile)** + ```python from rio_tiler_crs import COGReader @@ -507,22 +520,22 @@ assert app.tms_dependency == TMSParams ### Other changes -* add mosaic support (#17 author @geospatial-jeff) -* update to rio-tiler-crs>=3.0b* and rio-tiler>=2.0b* -* Pin fastapi version to 0.60.1 -* Remove titiler.core in favor of starlette settings (#55, author @geospatial-jeff) -* Add fastapi exception handlers (#56, author @geospatial-jeff) -* Remove intermediary routers (#57, author @geospatial-jeff) -* Remove /titiler/api submodule (e.g titiler.api.utils -> titiler.utils) -* Add Cache-Control middleware. Endpoints do not define any cache-control headers. (part of #43, co-author with @geospatial-jeff) -* Add 'X-Assets' in response headers for mosaic tiles (#51) -* add cog validation via rio-cogeo (co-author with @geospatial-jeff, #37) +- add mosaic support (#17 author @geospatial-jeff) +- update to rio-tiler-crs>=3.0b* and rio-tiler>=2.0b* +- Pin fastapi version to 0.60.1 +- Remove titiler.core in favor of starlette settings (#55, author @geospatial-jeff) +- Add fastapi exception handlers (#56, author @geospatial-jeff) +- Remove intermediary routers (#57, author @geospatial-jeff) +- Remove /titiler/api submodule (e.g titiler.api.utils -> titiler.utils) +- Add Cache-Control middleware. Endpoints do not define any cache-control headers. (part of #43, co-author with @geospatial-jeff) +- Add 'X-Assets' in response headers for mosaic tiles (#51) +- add cog validation via rio-cogeo (co-author with @geospatial-jeff, #37) ### Breaking changes -* default tiler to Web Mercator only -* removed cache layer for tiles -* updated html templates +- default tiler to Web Mercator only +- removed cache layer for tiles +- updated html templates ```python template_dir = pkg_resources.resource_filename("titiler", "templates") @@ -553,30 +566,30 @@ stac_template = templates.TemplateResponse( ## 2.1.2 (2020-06-24) -* add `width` & `height` parameters in API docs to force output size for part/preview endpoints. -* add `resampling_method` in API docs. +- add `width` & `height` parameters in API docs to force output size for part/preview endpoints. +- add `resampling_method` in API docs. link: https://github.com/developmentseed/titiler/commit/725da5fa1bc56d8e192ae8ff0ad107493ca93378 ## 2.1.1 (2020-06-22) -* add minimum fastapi version (0.54.0) and update docker config +- add minimum fastapi version (0.54.0) and update docker config link: https://github.com/developmentseed/titiler/commit/95b98a32ffb3274d546dd52f99a3920091029b4c ## 2.1.0 (2020-06-11) -* add `/preview`, `/crop`, `/point` endpoints +- add `/preview`, `/crop`, `/point` endpoints link: https://github.com/developmentseed/titiler/commit/8b63fc6b6141b9c9361c95d80897d77b5e2d47c3 ## 2.0.0 (2020-06-09) -* support STAC items (#16) -* better API documentation via response models -* update UI (`/stac/viewer`, `/cog/viewer`) -* re-order OpenAPI route tags -* update documentation +- support STAC items (#16) +- better API documentation via response models +- update UI (`/stac/viewer`, `/cog/viewer`) +- re-order OpenAPI route tags +- update documentation link: https://github.com/developmentseed/titiler/commit/fa2cb78906b0fd88506b89bace8174969be8cd4f diff --git a/docs/endpoints/mosaic.md b/docs/endpoints/mosaic.md index a3fd145b5..b77cc53b3 100644 --- a/docs/endpoints/mosaic.md +++ b/docs/endpoints/mosaic.md @@ -1,4 +1,3 @@ - The `titiler.application` package comes with a full FastAPI application with COG, STAC and MosaicJSON supports. # MosaicJSON @@ -7,16 +6,19 @@ Read Mosaic Info/Metadata and create Web map Tiles from a multiple COG. The `mos ## API -| Method | URL | Output | Description -| ------ | --------------------------------------------------------------- |---------- |-------------- -| `GET` | `/mosaicjson/` | JSON | return a MosaicJSON document -| `GET` | `/mosaicjson/bounds` | JSON | return bounds info for a MosaicJSON -| `GET` | `/mosaicjson/info` | JSON | return basic info for a MosaicJSON -| `GET` | `/mosaicjson/info.geojson` | GeoJSON | return basic info for a MosaicJSON as a GeoJSON feature -| `GET` | `/mosaicjson/tiles/[{TileMatrixSetId}]/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | create a web map tile image from a MosaicJSON -| `GET` | `/mosaicjson/[{TileMatrixSetId}]/tilejson.json` | JSON | return a Mapbox TileJSON document -| `GET` | `/mosaicjson/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities -| `GET` | `/mosaicjson/point/{lon},{lat}` | JSON | return pixel value from a MosaicJSON dataset +| Method | URL | Output | Description | +| ------ | ------------------------------------------------------------------------- | --------- | ------------------------------------------------------- | +| `GET` | `/mosaicjson/` | JSON | return a MosaicJSON document | +| `GET` | `/mosaicjson/bounds` | JSON | return bounds info for a MosaicJSON | +| `GET` | `/mosaicjson/info` | JSON | return basic info for a MosaicJSON | +| `GET` | `/mosaicjson/info.geojson` | GeoJSON | return basic info for a MosaicJSON as a GeoJSON feature | +| `GET` | `/mosaicjson/tiles/[{TileMatrixSetId}]/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | create a web map tile image from a MosaicJSON | +| `GET` | `/mosaicjson/[{TileMatrixSetId}]/tilejson.json` | JSON | return a Mapbox TileJSON document | +| `GET` | `/mosaicjson/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities | +| `GET` | `/mosaicjson/point/{lon},{lat}` | JSON | return pixel value from a MosaicJSON dataset | +| `GET` | `/mosaicjson/{quadkey}/assets` | JSON | return list of assets overlapping a quadkey | +| `GET` | `/mosaicjson/{lon},{lat}/assets` | JSON | return list of assets overlapping a point | +| `GET` | `/mosaicjson/{minx},{miny},{maxx},{maxy}/assets` | JSON | return list of assets overlapping a bounding box | ## Description diff --git a/src/titiler/mosaic/setup.py b/src/titiler/mosaic/setup.py index 0f6cefab9..2098fe580 100644 --- a/src/titiler/mosaic/setup.py +++ b/src/titiler/mosaic/setup.py @@ -5,10 +5,7 @@ with open("README.md") as f: long_description = f.read() -inst_reqs = [ - "titiler.core", - "cogeo-mosaic>=3.0,<3.1", -] +inst_reqs = ["titiler.core", "cogeo-mosaic>=3.0,<3.1", "mercantile"] extra_reqs = { "test": ["pytest", "pytest-cov", "pytest-asyncio", "requests"], } From 7b12d566f14f59bb9ecc23bd5b7f4987e6ac8972 Mon Sep 17 00:00:00 2001 From: mackdelany Date: Fri, 6 Aug 2021 14:05:16 +1200 Subject: [PATCH 04/10] changelog, docs and mercantile req --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 40f30c0b9..466579466 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ### titiler.mosaic -- add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return lists of assets that overlap a given geometry (https://github.com/developmentseed/titiler/pull/351) +- add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return a list of assets that overlap the given geometry (https://github.com/developmentseed/titiler/pull/351) ## 0.3.4 (2021-08-02) From 8272f5ed82506a6277824c78734ce26cdc519492 Mon Sep 17 00:00:00 2001 From: mackdelany Date: Fri, 6 Aug 2021 14:08:41 +1200 Subject: [PATCH 05/10] remove autoformatted changes --- CHANGES.md | 597 ++++++++++++++++++++++++++--------------------------- 1 file changed, 295 insertions(+), 302 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 466579466..2d2cc36dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,42 +4,43 @@ ### titiler.mosaic -- add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return a list of assets that overlap the given geometry (https://github.com/developmentseed/titiler/pull/351) +* add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return a list of assets that intersect a given geometry (https://github.com/developmentseed/titiler/pull/351) ## 0.3.4 (2021-08-02) ### titiler.core -- add `/crop` POST endpoint to return an image from a GeoJSON feature (https://github.com/developmentseed/titiler/pull/339) -- add `/statistics` (GET and POST) endpoints to return advanced images statistics (https://github.com/developmentseed/titiler/pull/347) +* add `/crop` POST endpoint to return an image from a GeoJSON feature (https://github.com/developmentseed/titiler/pull/339) +* add `/statistics` (GET and POST) endpoints to return advanced images statistics (https://github.com/developmentseed/titiler/pull/347) ### titiler.application -- add optional `root_path` setting to specify a url path prefix to use when running the app behind a reverse proxy (https://github.com/developmentseed/titiler/pull/343) +* add optional `root_path` setting to specify a url path prefix to use when running the app behind a reverse proxy (https://github.com/developmentseed/titiler/pull/343) ## 0.3.3 (2021-06-29) ### titiler.core -- fix possible bug when querystring parameter are case insensitive (https://github.com/developmentseed/titiler/pull/323) +* fix possible bug when querystring parameter are case insensitive (https://github.com/developmentseed/titiler/pull/323) ### titiler.mosaic -- update `tilejson` and `WMTSCapabilities.xml` endpoints to allow list querystrings (as done previously in https://github.com/developmentseed/titiler/issues/319) +* update `tilejson` and `WMTSCapabilities.xml` endpoints to allow list querystrings (as done previously in https://github.com/developmentseed/titiler/issues/319) ### titiler.application -- add `titiler.application.middleware.LowerCaseQueryStringMiddleware` to cast all query string parameter to lowercase (author @lorenzori, https://github.com/developmentseed/titiler/pull/321) +* add `titiler.application.middleware.LowerCaseQueryStringMiddleware` to cast all query string parameter to lowercase (author @lorenzori, https://github.com/developmentseed/titiler/pull/321) + ### code and repo -- move `titiler` code to `src/titiler` +* move `titiler` code to `src/titiler` ## 0.3.2 (2021-05-26) ### titiler.core -- update rio-tiler dependency to `>=2.1` version and update `rescale` query-parameter (https://github.com/developmentseed/titiler/issues/319) +* update rio-tiler dependency to `>=2.1` version and update `rescale` query-parameter (https://github.com/developmentseed/titiler/issues/319) ``` # before @@ -53,140 +54,138 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ### titiler.mosaic -- update `cogeo-mosaic` version to `>=3.0,<3.1`. +* update `cogeo-mosaic` version to `>=3.0,<3.1`. ### titiler.application -- re-order middlewares (https://github.com/developmentseed/titiler/issues/311) -- update rio-cogeo version to `>=2.2` and use `rio_cogeo.models` instead of custom ones. +* re-order middlewares (https://github.com/developmentseed/titiler/issues/311) +* update rio-cogeo version to `>=2.2` and use `rio_cogeo.models` instead of custom ones. + ## 0.3.1 (2021-04-27) -- add `exclude_path` options in `titiler.application.middleware.CacheControlMiddleware` to avoid adding cache-control headers to specific paths. -- allow `histogram_bins` to be a single value or a `,` delimited scalar (https://github.com/developmentseed/titiler/pull/307) -- change error status from `404` to `500` for `RasterioIOError` exception (author @kylebarron, https://github.com/developmentseed/titiler/pull/300) +* add `exclude_path` options in `titiler.application.middleware.CacheControlMiddleware` to avoid adding cache-control headers to specific paths. +* allow `histogram_bins` to be a single value or a `,` delimited scalar (https://github.com/developmentseed/titiler/pull/307) +* change error status from `404` to `500` for `RasterioIOError` exception (author @kylebarron, https://github.com/developmentseed/titiler/pull/300) - Sometimes GDAL/Rasterio can lose track of the file handler (might be related to cache issue + threading) and raise `RasterioIOError: file not found`, while the file exists for real. To avoid caching this, we changed the error code to 500 (errors >= 500 do not get `cache-control` header on titiler.application). + Sometimes GDAL/Rasterio can lose track of the file handler (might be related to cache issue + threading) and raise `RasterioIOError: file not found`, while the file exists for real. To avoid caching this, we changed the error code to 500 (errors >= 500 do not get `cache-control` header on titiler.application). ## 0.3.0 (2021-04-19) -- add support for `.jpg` and `.jpeg` extensions (https://github.com/developmentseed/titiler/pull/271) -- better error message when parsing the colormap value fails (https://github.com/developmentseed/titiler/pull/279) +* add support for `.jpg` and `.jpeg` extensions (https://github.com/developmentseed/titiler/pull/271) +* better error message when parsing the colormap value fails (https://github.com/developmentseed/titiler/pull/279) **breaking change** -- split `titiler` into a set of namespaces packages (https://github.com/developmentseed/titiler/pull/284) - - **titiler.core** +* split `titiler` into a set of namespaces packages (https://github.com/developmentseed/titiler/pull/284) - The `core` package host the low level tiler factories. + **titiler.core** - ```python - # before - from titiler.endpoints.factory import TilerFactory + The `core` package host the low level tiler factories. + ```python + # before + from titiler.endpoints.factory import TilerFactory - # now - from titiler.core.factory import TilerFactory - ``` + # now + from titiler.core.factory import TilerFactory + ``` - **titiler.mosaic** + **titiler.mosaic** - The `mosaic` package is a plugin to `titiler.core` which adds support for MosaicJSON + The `mosaic` package is a plugin to `titiler.core` which adds support for MosaicJSON + ```python + # before + from titiler.endpoints.factory import MosaicTilerFactory - ```python - # before - from titiler.endpoints.factory import MosaicTilerFactory + # now + from titiler.mosaic.factory import MosaicTilerFactory + ``` - # now - from titiler.mosaic.factory import MosaicTilerFactory - ``` + **titiler.application** - **titiler.application** + The `application` package is a full `ready to use` FastAPI application with support of STAC, COG and MosaicJSON. - The `application` package is a full `ready to use` FastAPI application with support of STAC, COG and MosaicJSON. + ```bash + # before + $ pip install titiler + $ uvicorn titiler.main:app --reload - ```bash - # before - $ pip install titiler - $ uvicorn titiler.main:app --reload - - # now - $ pip install titiler.application uvicorn - $ uvicorn titiler.application.main:app --reload - ``` + # now + $ pip install titiler.application uvicorn + $ uvicorn titiler.application.main:app --reload + ``` ## 0.2.0 (2021-03-09) -- adapt for cogeo-mosaic `3.0.0rc2` and add `backend_options` attribute in MosaicTilerFactory (https://github.com/developmentseed/titiler/pull/247) -- update FastAPI requirements -- update minimal python version to 3.6 -- add `**render_params.kwargs` to pass custom render params in `image.render` method (https://github.com/developmentseed/titiler/pull/259) -- Changed probe url from `/ping` to `/healthz` in k8s deployment +* adapt for cogeo-mosaic `3.0.0rc2` and add `backend_options` attribute in MosaicTilerFactory (https://github.com/developmentseed/titiler/pull/247) +* update FastAPI requirements +* update minimal python version to 3.6 +* add `**render_params.kwargs` to pass custom render params in `image.render` method (https://github.com/developmentseed/titiler/pull/259) +* Changed probe url from `/ping` to `/healthz` in k8s deployment **breaking change** -- renamed `OptionalHeaders`, `MimeTypes` and `ImageDrivers` enums to the singular form (https://github.com/developmentseed/titiler/pull/258) -- renamed titiler.dependencies's Enums (`ColorMapName`, `ResamplingName` and `TileMatrixSetName`) to the singular form (https://github.com/developmentseed/titiler/pull/260) -- renamed `MimeType` to `MediaType` (https://github.com/developmentseed/titiler/pull/258) -- add `ColorMapParams` dependency to ease the creation of custom colormap dependency (https://github.com/developmentseed/titiler/pull/252) -- renamed `PathParams` to `DatasetPathParams` and also made it a simple callable (https://github.com/developmentseed/titiler/pull/260) -- renamed `colormap` query-parameter to `colormap_name` (https://github.com/developmentseed/titiler/pull/262) - - ``` - # before - /cog/preview.png?colormap=viridis - - # now - /cog/preview.png?colormap_name=viridis - ``` - -- use `colormap` query-parameter to pass custom colormap (https://github.com/developmentseed/titiler/pull/262) - ``` - /cog/preview.png?colormap={"0": "#FFFF00FF", ...} - ``` +* renamed `OptionalHeaders`, `MimeTypes` and `ImageDrivers` enums to the singular form (https://github.com/developmentseed/titiler/pull/258) +* renamed titiler.dependencies's Enums (`ColorMapName`, `ResamplingName` and `TileMatrixSetName`) to the singular form (https://github.com/developmentseed/titiler/pull/260) +* renamed `MimeType` to `MediaType` (https://github.com/developmentseed/titiler/pull/258) +* add `ColorMapParams` dependency to ease the creation of custom colormap dependency (https://github.com/developmentseed/titiler/pull/252) +* renamed `PathParams` to `DatasetPathParams` and also made it a simple callable (https://github.com/developmentseed/titiler/pull/260) +* renamed `colormap` query-parameter to `colormap_name` (https://github.com/developmentseed/titiler/pull/262) + ``` + # before + /cog/preview.png?colormap=viridis + + # now + /cog/preview.png?colormap_name=viridis + ``` + +* use `colormap` query-parameter to pass custom colormap (https://github.com/developmentseed/titiler/pull/262) + ``` + /cog/preview.png?colormap={"0": "#FFFF00FF", ...} + ``` ## 0.1.0 (2021-02-17) -- update FastAPI requirements -- add `validate` in `MosaicTilerFactory` (https://github.com/developmentseed/titiler/pull/206, author @drnextgis) -- rename `ressources` package to `resources` (https://github.com/developmentseed/titiler/pull/210, author @drnextgis) -- renamed environment variables prefixes for API and STACK configurations: `TITILER_STACK` as prefix to CDK and `TITILER_API` as prefix to API (https://github.com/developmentseed/titiler/pull/211, author @fredliporace) -- remove MosaicTilerFactory `create` and `update` endpoints (https://github.com/developmentseed/titiler/pull/218) -- deleted `titiler.models.mosaics` because the models are not used anymore (https://github.com/developmentseed/titiler/pull/221) -- update rio-tiler and cogeo-mosaic minimal versions (https://github.com/developmentseed/titiler/pull/220, https://github.com/developmentseed/titiler/pull/213) -- move STAC related dependencies to `titiler.dependencies (https://github.com/developmentseed/titiler/pull/225) -- add `rio_tiler.io.MultiBandReader` bands dependencies (https://github.com/developmentseed/titiler/pull/226) -- add `MultiBaseTilerFactory` and `MultiBandTilerFactory` custom tiler factories (https://github.com/developmentseed/titiler/pull/230) -- Update STAC tiler to use the new `MultiBaseTilerFactory` factory -- depreciate _empty_ GET endpoint for MosaicTilerFactory read (https://github.com/developmentseed/titiler/pull/232) -- better `debug` configuration and make reponse headers metadata optional (https://github.com/developmentseed/titiler/pull/232) +* update FastAPI requirements +* add `validate` in `MosaicTilerFactory` (https://github.com/developmentseed/titiler/pull/206, author @drnextgis) +* rename `ressources` package to `resources` (https://github.com/developmentseed/titiler/pull/210, author @drnextgis) +* renamed environment variables prefixes for API and STACK configurations: `TITILER_STACK` as prefix to CDK and `TITILER_API` as prefix to API (https://github.com/developmentseed/titiler/pull/211, author @fredliporace) +* remove MosaicTilerFactory `create` and `update` endpoints (https://github.com/developmentseed/titiler/pull/218) +* deleted `titiler.models.mosaics` because the models are not used anymore (https://github.com/developmentseed/titiler/pull/221) +* update rio-tiler and cogeo-mosaic minimal versions (https://github.com/developmentseed/titiler/pull/220, https://github.com/developmentseed/titiler/pull/213) +* move STAC related dependencies to `titiler.dependencies (https://github.com/developmentseed/titiler/pull/225) +* add `rio_tiler.io.MultiBandReader` bands dependencies (https://github.com/developmentseed/titiler/pull/226) +* add `MultiBaseTilerFactory` and `MultiBandTilerFactory` custom tiler factories (https://github.com/developmentseed/titiler/pull/230) +* Update STAC tiler to use the new `MultiBaseTilerFactory` factory +* depreciate *empty* GET endpoint for MosaicTilerFactory read (https://github.com/developmentseed/titiler/pull/232) +* better `debug` configuration and make reponse headers metadata optional (https://github.com/developmentseed/titiler/pull/232) **breaking change** -- update `titiler.dependencies.AssetsBidxParams` to make `asset` a required parameter (https://github.com/developmentseed/titiler/pull/230 -- the STAC `/info` endpoint now expect the `assets` parameter to be passed. To ge the list of available assets we added a new `/assets` endpoint within the tiler factory -- remove `COGReader` as default `reader` in `titiler.endpoints.factory.BaseTilerFactory` +* update `titiler.dependencies.AssetsBidxParams` to make `asset` a required parameter (https://github.com/developmentseed/titiler/pull/230 +* the STAC `/info` endpoint now expect the `assets` parameter to be passed. To ge the list of available assets we added a new `/assets` endpoint within the tiler factory +* remove `COGReader` as default `reader` in `titiler.endpoints.factory.BaseTilerFactory` ## 0.1.0a14 (2021-01-05) -- add `rio_tiler.errors.MissingBands` in known errors. -- add `titiler.endpoints.factory.TMSFactory` to enable custom TMS endpoints. -- **breaking** rename `BaseFactory` to `BaseTilerFactory` in `titiler.endpoints.factory` +* add `rio_tiler.errors.MissingBands` in known errors. +* add `titiler.endpoints.factory.TMSFactory` to enable custom TMS endpoints. +* **breaking** rename `BaseFactory` to `BaseTilerFactory` in `titiler.endpoints.factory` ## 0.1.0a13 (2020-12-20) -- allow `API_DISABLE_{COG/STAC/MOSAIC}` environment variables to control default endpoints in titiler main app (https://github.com/developmentseed/titiler/issues/156) -- add `overwriting=False/True` on MosaicJSON creation (https://github.com/developmentseed/titiler/issues/164) -- add `gdal_config` option to Tiler factories to replace custom `APIRoute` class (https://github.com/developmentseed/titiler/issues/168) -- add `info.geojson` endpoint to return dataset info as a GeoJSON feature (https://github.com/developmentseed/titiler/issues/166) -- update `rio-tiler`, `cogeo-mosaic` and optional dependencies +* allow `API_DISABLE_{COG/STAC/MOSAIC}` environment variables to control default endpoints in titiler main app (https://github.com/developmentseed/titiler/issues/156) +* add `overwriting=False/True` on MosaicJSON creation (https://github.com/developmentseed/titiler/issues/164) +* add `gdal_config` option to Tiler factories to replace custom `APIRoute` class (https://github.com/developmentseed/titiler/issues/168) +* add `info.geojson` endpoint to return dataset info as a GeoJSON feature (https://github.com/developmentseed/titiler/issues/166) +* update `rio-tiler`, `cogeo-mosaic` and optional dependencies ## 0.1.0a12 (2020-11-18) -- require `rio-tiler>=2.0.0rc2` -- update Enums for Image types. (**breaking**) -- Add more output datatype (jpeg2000, pngraw) -- add `width/height` in `/crop` endpoint path +* require `rio-tiler>=2.0.0rc2` +* update Enums for Image types. (**breaking**) +* Add more output datatype (jpeg2000, pngraw) +* add `width/height` in `/crop` endpoint path ``` /crop/{minx},{miny},{maxx},{maxy}.{format} @@ -195,7 +194,7 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ## 0.1.0a11.post1 (2020-11-12) -- relax version for rio-tiler and cogeo-mosaic +* relax version for rio-tiler and cogeo-mosaic ```python "rio-cogeo~=2.0" @@ -205,39 +204,39 @@ rescale=0,1000&rescale=0,1000&rescale=0,1000 ## 0.1.0a11 (2020-11-12) -- split `tile()` for `MosaicTilerFactory` method (https://github.com/developmentseed/titiler/issues/147) +* split `tile()` for `MosaicTilerFactory` method (https://github.com/developmentseed/titiler/issues/147) ## 0.1.0a10 (2020-11-09) -- update for rio-tiler==2.0.0rc1, cogeo-mosaic==3.0.0a17 and morecantile==2.0 -- split `tile()` factory method (https://github.com/developmentseed/titiler/issues/141, author @fredliporace) +* update for rio-tiler==2.0.0rc1, cogeo-mosaic==3.0.0a17 and morecantile==2.0 +* split `tile()` factory method (https://github.com/developmentseed/titiler/issues/141, author @fredliporace) ## 0.1.0a9 (2020-10-26) -- avoid changing mutable TMS and Colormap list by using deepcopy. -- quiet/turn off logs -- add logger middleware (https://github.com/developmentseed/titiler/pull/139) +* avoid changing mutable TMS and Colormap list by using deepcopy. +* quiet/turn off logs +* add logger middleware (https://github.com/developmentseed/titiler/pull/139) ## 0.1.0a8 (2020-10-13) -- update for rio-tiler 2.0.0b17, which now support TMS (morecantile) by default. -- update fastapi minimum version to 0.61 +* update for rio-tiler 2.0.0b17, which now support TMS (morecantile) by default. +* update fastapi minimum version to 0.61 **breaking changes** -- removed TMSTilerFactory (because default reader built with rio_tiler BaseReader should support TMS). +* removed TMSTilerFactory (because default reader built with rio_tiler BaseReader should support TMS). Note: We changed the versioning scheme to `{major}.{minor}.{path}{pre}{prenum}` ## 0.1.0-alpha.7 (2020-10-13) -- remove `pkg_resources` (https://github.com/pypa/setuptools/issues/510) +* remove `pkg_resources` (https://github.com/pypa/setuptools/issues/510) ## 0.1.0-alpha.6 (2020-10-05) -- refactor CacheControl Middleware -- rename headers value `X-Server-Timings` to `Server-Timing`. -- add `total;dur={}` in response header `Server-Timing`, using new `titiler.middleware.TotalTimeMiddleware` middleware (113) +* refactor CacheControl Middleware +* rename headers value `X-Server-Timings` to `Server-Timing`. +* add `total;dur={}` in response header `Server-Timing`, using new `titiler.middleware.TotalTimeMiddleware` middleware (113) ```python from titiler.middleware import CacheControlMiddleware, TotalTimeMiddleware @@ -247,204 +246,200 @@ app.add_middleware(CacheControlMiddleware, cachecontrol="public, max-age=3600") app.add_middleware(TotalTimeMiddleware) ``` -- Add Brotli compression support (#126, author @kylebarron) -- Numerous fix to CDK app.py (co-author @kylebarron) +* Add Brotli compression support (#126, author @kylebarron) +* Numerous fix to CDK app.py (co-author @kylebarron) ## 0.1.0-alpha.5 (2020-09-22) -- exclude `tests/` an `stack/` in titiler python package. -- add `EPSG6933` in TMS +* exclude `tests/` an `stack/` in titiler python package. +* add `EPSG6933` in TMS **breaking changes** +* [FACTORY] the `additional_dependency` should be a Callable which return a dict. + + ```python + @dataclass # type: ignore + class BaseFactory(metaclass=abc.ABCMeta): + """BaseTiler Factory.""" + ... + # provide custom dependency + additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) + ``` + + ```python + def AssetsParams( + assets: Optional[str] = Query( + None, + title="Asset indexes", + description="comma (',') delimited asset names (might not be an available options of some readers)", + ) + ) -> Dict: + """Assets Dependency.""" + kwargs = {} + if assets: + kwargs["assets"] = assets.split(",") + return kwargs + ``` +* [FACTORY] remove `_` prefix in factory methods (e.g `_tile` -> `tile`) +* [FACTORY] refactor dependencies to better align with rio_tiler.io.BaseReader method definition. + + Example: + + In the `metadata`, the `MetadataParams` will be used to pass `pmin` and `pmax` because they are the only + required parameters for the metadata method. All other params will be passed to a `kwargs` dict. + + ```python + @dataclass + class MetadataParams(DefaultDependency): + """Common Metadada parameters.""" + # Required params + pmin: float = Query(2.0, description="Minimum percentile") + pmax: float = Query(98.0, description="Maximum percentile") + # Optional parameters + bidx: Optional[str] = Query( + None, title="Band indexes", description="comma (',') delimited band indexes", + ) + ... + def __post_init__(self): + """Post Init.""" + + if self.bidx is not None: + self.kwargs["indexes"] = tuple( + int(s) for s in re.findall(r"\d+", self.bidx) + ) + ... + + # metadata method in factory + def metadata( + src_path=Depends(self.path_dependency), + metadata_params=Depends(self.metadata_dependency), + kwargs: Dict = Depends(self.additional_dependency), + ): + """Return metadata.""" + reader = src_path.reader or self.reader + with reader(src_path.url, **self.reader_options) as src_dst: + info = src_dst.metadata( + metadata_params.pmin, + metadata_params.pmax, + **metadata_params.kwargs, + **kwargs, + ) + return info + ``` +* [FACTORY] refactor dependencies definition + ```python + @dataclass # type: ignore + class BaseFactory(metaclass=abc.ABCMeta): + """BaseTiler Factory.""" + + reader: default_readers_type = field(default=COGReader) + reader_options: Dict = field(default_factory=dict) + + # FastAPI router + router: APIRouter = field(default_factory=APIRouter) + + # Path Dependency + path_dependency: Type[PathParams] = field(default=PathParams) + + # Rasterio Dataset Options (nodata, unscale, resampling) + dataset_dependency: default_deps_type = field(default=DatasetParams) + + # Indexes/Expression Dependencies + layer_dependency: default_deps_type = field(default=BidxExprParams) + + # Image rendering Dependencies + render_dependency: default_deps_type = field(default=RenderParams) + + # TileMatrixSet dependency + tms_dependency: Callable[..., TileMatrixSet] = WebMercatorTMSParams + + # provide custom dependency + additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) + ``` + +* remove `PathParams.reader` attribute. This option was not used and would have been technically difficult to use. + ```python + @dataclass + class PathParams: + """Create dataset path from args""" + + url: str = Query(..., description="Dataset URL") + ``` -- [FACTORY] the `additional_dependency` should be a Callable which return a dict. - - ```python - @dataclass # type: ignore - class BaseFactory(metaclass=abc.ABCMeta): - """BaseTiler Factory.""" - ... - # provide custom dependency - additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) - ``` - - ```python - def AssetsParams( - assets: Optional[str] = Query( - None, - title="Asset indexes", - description="comma (',') delimited asset names (might not be an available options of some readers)", - ) - ) -> Dict: - """Assets Dependency.""" - kwargs = {} - if assets: - kwargs["assets"] = assets.split(",") - return kwargs - ``` - -- [FACTORY] remove `_` prefix in factory methods (e.g `_tile` -> `tile`) -- [FACTORY] refactor dependencies to better align with rio_tiler.io.BaseReader method definition. - - Example: - - In the `metadata`, the `MetadataParams` will be used to pass `pmin` and `pmax` because they are the only - required parameters for the metadata method. All other params will be passed to a `kwargs` dict. - - ```python - @dataclass - class MetadataParams(DefaultDependency): - """Common Metadada parameters.""" - # Required params - pmin: float = Query(2.0, description="Minimum percentile") - pmax: float = Query(98.0, description="Maximum percentile") - # Optional parameters - bidx: Optional[str] = Query( - None, title="Band indexes", description="comma (',') delimited band indexes", - ) - ... - def __post_init__(self): - """Post Init.""" - - if self.bidx is not None: - self.kwargs["indexes"] = tuple( - int(s) for s in re.findall(r"\d+", self.bidx) - ) - ... - - # metadata method in factory - def metadata( - src_path=Depends(self.path_dependency), - metadata_params=Depends(self.metadata_dependency), - kwargs: Dict = Depends(self.additional_dependency), - ): - """Return metadata.""" - reader = src_path.reader or self.reader - with reader(src_path.url, **self.reader_options) as src_dst: - info = src_dst.metadata( - metadata_params.pmin, - metadata_params.pmax, - **metadata_params.kwargs, - **kwargs, - ) - return info - ``` - -- [FACTORY] refactor dependencies definition - - ```python - @dataclass # type: ignore - class BaseFactory(metaclass=abc.ABCMeta): - """BaseTiler Factory.""" - - reader: default_readers_type = field(default=COGReader) - reader_options: Dict = field(default_factory=dict) - - # FastAPI router - router: APIRouter = field(default_factory=APIRouter) - - # Path Dependency - path_dependency: Type[PathParams] = field(default=PathParams) - - # Rasterio Dataset Options (nodata, unscale, resampling) - dataset_dependency: default_deps_type = field(default=DatasetParams) - - # Indexes/Expression Dependencies - layer_dependency: default_deps_type = field(default=BidxExprParams) - - # Image rendering Dependencies - render_dependency: default_deps_type = field(default=RenderParams) - - # TileMatrixSet dependency - tms_dependency: Callable[..., TileMatrixSet] = WebMercatorTMSParams - - # provide custom dependency - additional_dependency: Callable[..., Dict] = field(default=lambda: dict()) - ``` - -- remove `PathParams.reader` attribute. This option was not used and would have been technically difficult to use. - - ```python - @dataclass - class PathParams: - """Create dataset path from args""" - - url: str = Query(..., description="Dataset URL") - ``` ## 0.1.0-alpha.4 (2020-09-14) -- Update `.npy` output format to follow the numpyTile format (#103) +* Update `.npy` output format to follow the numpyTile format (#103) + + ```python + import numpy + import requests + from io import BytesIO - ```python - import numpy - import requests - from io import BytesIO + endpoint = ... + url = "https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif" - endpoint = ... - url = "https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif" + r = requests.get(f"{endpoint}/cog/tiles/14/10818/9146.npy", + params = { + "url": url, + } + ) + data = numpy.load(BytesIO(r.content)) + print(data.shape) + > (4, 256, 256) + ``` - r = requests.get(f"{endpoint}/cog/tiles/14/10818/9146.npy", - params = { - "url": url, - } - ) - data = numpy.load(BytesIO(r.content)) - print(data.shape) - > (4, 256, 256) - ``` +* Add `titiler.custom.routing.apiroute_factory`. This function enable the creation of custom fastapi.routing.APIRoute class with `rasterio.Env()` block. -- Add `titiler.custom.routing.apiroute_factory`. This function enable the creation of custom fastapi.routing.APIRoute class with `rasterio.Env()` block. + ```python + from fastapi import FastAPI, APIRouter + from rasterio._env import get_gdal_config + from titiler.custom.routing import apiroute_factory - ```python - from fastapi import FastAPI, APIRouter - from rasterio._env import get_gdal_config - from titiler.custom.routing import apiroute_factory + app = FastAPI() + route_class = apiroute_factory({"GDAL_DISABLE_READDIR_ON_OPEN": "FALSE"}) + router = APIRouter(route_class=route_class) - app = FastAPI() - route_class = apiroute_factory({"GDAL_DISABLE_READDIR_ON_OPEN": "FALSE"}) - router = APIRouter(route_class=route_class) + @router.get("/simple") + def simple(): + """should return FALSE.""" + res = get_gdal_config("GDAL_DISABLE_READDIR_ON_OPEN") + return {"env": res} - @router.get("/simple") - def simple(): - """should return FALSE.""" - res = get_gdal_config("GDAL_DISABLE_READDIR_ON_OPEN") - return {"env": res} + app.include_router(router) + ``` - app.include_router(router) - ``` + Note: This has only be tested for python 3.6 and 3.7. - Note: This has only be tested for python 3.6 and 3.7. ## 0.1.0-alpha.3 (2020-09-03) -- add custom `url_for` method in TilerFactory to retrieve `prefixed` endpoint URL (#95) -- remove magic `titiler.dependencies.PathParams` mosaicid path translation, where a user could pass `url=mosaicid://` to the endpoint. -- switch to `pydantic.BaseSettings` for FastAPI application setting management. +* add custom `url_for` method in TilerFactory to retrieve `prefixed` endpoint URL (#95) +* remove magic `titiler.dependencies.PathParams` mosaicid path translation, where a user could pass `url=mosaicid://` to the endpoint. +* switch to `pydantic.BaseSettings` for FastAPI application setting management. - List of Settings: + List of Settings: - ```python - name: str = "titiler" - cors_origins: str = "*" - cachecontrol: str = "public, max-age=3600" - ``` + ```python + name: str = "titiler" + cors_origins: str = "*" + cachecontrol: str = "public, max-age=3600" + ``` API Settings can now be set by adding a `.env` file in your local project or by setting environment variables (e.g `API_CORS_ORIGIN="https://mywebsite.com/*"`) ## 0.1.0-alpha.2 (2020-09-01) -- add Transform and CRS information in `/part` GeoTIFF output -- pin **rio-tiler-crs** to `>=3.0b4,<3.1` and **cogeo-mosaic** to `>=3.0a10,<3.1` +* add Transform and CRS information in `/part` GeoTIFF output +* pin **rio-tiler-crs** to `>=3.0b4,<3.1` and **cogeo-mosaic** to `>=3.0a10,<3.1` ## 0.1.0-alpha.1 (2020-09-01) -- rename titiler.models.cog.py to titiler.models.dataset.py -- remove cog\* prefix to Bounds, Info and Metadata models -- allow Union[str, int] for key in Metadata.statistics (as defined in rio-tiler-pds) +* rename titiler.models.cog.py to titiler.models.dataset.py +* remove cog* prefix to Bounds, Info and Metadata models +* allow Union[str, int] for key in Metadata.statistics (as defined in rio-tiler-pds) e.g Create a Landsat 8 Tiler - ```python from titiler.endpoints.factory import TilerFactory, MosaicTilerFactory from titiler.dependencies import BandsParams @@ -495,7 +490,6 @@ The `titiler.endpoints.factory.TilerFactory` class will create a tiler with `Web For other TMS support, tiler needs to be created with `titiler.endpoints.factory.TMSTilerFactory` and with a TMS friendly reader (e.g `rio_tiler_crs.COGReader`). **Simple tiler with only Web Mercator support** - ```python from rio_tiler.io import COGReader @@ -507,7 +501,6 @@ assert app.tms_dependency == WebMercatorTMSParams ``` **Tiler with more TMS support (from morecantile)** - ```python from rio_tiler_crs import COGReader @@ -520,22 +513,22 @@ assert app.tms_dependency == TMSParams ### Other changes -- add mosaic support (#17 author @geospatial-jeff) -- update to rio-tiler-crs>=3.0b* and rio-tiler>=2.0b* -- Pin fastapi version to 0.60.1 -- Remove titiler.core in favor of starlette settings (#55, author @geospatial-jeff) -- Add fastapi exception handlers (#56, author @geospatial-jeff) -- Remove intermediary routers (#57, author @geospatial-jeff) -- Remove /titiler/api submodule (e.g titiler.api.utils -> titiler.utils) -- Add Cache-Control middleware. Endpoints do not define any cache-control headers. (part of #43, co-author with @geospatial-jeff) -- Add 'X-Assets' in response headers for mosaic tiles (#51) -- add cog validation via rio-cogeo (co-author with @geospatial-jeff, #37) +* add mosaic support (#17 author @geospatial-jeff) +* update to rio-tiler-crs>=3.0b* and rio-tiler>=2.0b* +* Pin fastapi version to 0.60.1 +* Remove titiler.core in favor of starlette settings (#55, author @geospatial-jeff) +* Add fastapi exception handlers (#56, author @geospatial-jeff) +* Remove intermediary routers (#57, author @geospatial-jeff) +* Remove /titiler/api submodule (e.g titiler.api.utils -> titiler.utils) +* Add Cache-Control middleware. Endpoints do not define any cache-control headers. (part of #43, co-author with @geospatial-jeff) +* Add 'X-Assets' in response headers for mosaic tiles (#51) +* add cog validation via rio-cogeo (co-author with @geospatial-jeff, #37) ### Breaking changes -- default tiler to Web Mercator only -- removed cache layer for tiles -- updated html templates +* default tiler to Web Mercator only +* removed cache layer for tiles +* updated html templates ```python template_dir = pkg_resources.resource_filename("titiler", "templates") @@ -566,30 +559,30 @@ stac_template = templates.TemplateResponse( ## 2.1.2 (2020-06-24) -- add `width` & `height` parameters in API docs to force output size for part/preview endpoints. -- add `resampling_method` in API docs. +* add `width` & `height` parameters in API docs to force output size for part/preview endpoints. +* add `resampling_method` in API docs. link: https://github.com/developmentseed/titiler/commit/725da5fa1bc56d8e192ae8ff0ad107493ca93378 ## 2.1.1 (2020-06-22) -- add minimum fastapi version (0.54.0) and update docker config +* add minimum fastapi version (0.54.0) and update docker config link: https://github.com/developmentseed/titiler/commit/95b98a32ffb3274d546dd52f99a3920091029b4c ## 2.1.0 (2020-06-11) -- add `/preview`, `/crop`, `/point` endpoints +* add `/preview`, `/crop`, `/point` endpoints link: https://github.com/developmentseed/titiler/commit/8b63fc6b6141b9c9361c95d80897d77b5e2d47c3 ## 2.0.0 (2020-06-09) -- support STAC items (#16) -- better API documentation via response models -- update UI (`/stac/viewer`, `/cog/viewer`) -- re-order OpenAPI route tags -- update documentation +* support STAC items (#16) +* better API documentation via response models +* update UI (`/stac/viewer`, `/cog/viewer`) +* re-order OpenAPI route tags +* update documentation link: https://github.com/developmentseed/titiler/commit/fa2cb78906b0fd88506b89bace8174969be8cd4f From f16f502f6745d6d14ad87cac5143811425d90df2 Mon Sep 17 00:00:00 2001 From: mackdelany Date: Fri, 6 Aug 2021 14:09:34 +1200 Subject: [PATCH 06/10] remove autoformatted changes --- docs/endpoints/mosaic.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/endpoints/mosaic.md b/docs/endpoints/mosaic.md index b77cc53b3..5167d1735 100644 --- a/docs/endpoints/mosaic.md +++ b/docs/endpoints/mosaic.md @@ -1,3 +1,4 @@ + The `titiler.application` package comes with a full FastAPI application with COG, STAC and MosaicJSON supports. # MosaicJSON @@ -6,19 +7,19 @@ Read Mosaic Info/Metadata and create Web map Tiles from a multiple COG. The `mos ## API -| Method | URL | Output | Description | -| ------ | ------------------------------------------------------------------------- | --------- | ------------------------------------------------------- | -| `GET` | `/mosaicjson/` | JSON | return a MosaicJSON document | -| `GET` | `/mosaicjson/bounds` | JSON | return bounds info for a MosaicJSON | -| `GET` | `/mosaicjson/info` | JSON | return basic info for a MosaicJSON | -| `GET` | `/mosaicjson/info.geojson` | GeoJSON | return basic info for a MosaicJSON as a GeoJSON feature | -| `GET` | `/mosaicjson/tiles/[{TileMatrixSetId}]/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | create a web map tile image from a MosaicJSON | -| `GET` | `/mosaicjson/[{TileMatrixSetId}]/tilejson.json` | JSON | return a Mapbox TileJSON document | -| `GET` | `/mosaicjson/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities | -| `GET` | `/mosaicjson/point/{lon},{lat}` | JSON | return pixel value from a MosaicJSON dataset | -| `GET` | `/mosaicjson/{quadkey}/assets` | JSON | return list of assets overlapping a quadkey | -| `GET` | `/mosaicjson/{lon},{lat}/assets` | JSON | return list of assets overlapping a point | -| `GET` | `/mosaicjson/{minx},{miny},{maxx},{maxy}/assets` | JSON | return list of assets overlapping a bounding box | +| Method | URL | Output | Description +| ------ | --------------------------------------------------------------- |---------- |-------------- +| `GET` | `/mosaicjson/` | JSON | return a MosaicJSON document +| `GET` | `/mosaicjson/bounds` | JSON | return bounds info for a MosaicJSON +| `GET` | `/mosaicjson/info` | JSON | return basic info for a MosaicJSON +| `GET` | `/mosaicjson/info.geojson` | GeoJSON | return basic info for a MosaicJSON as a GeoJSON feature +| `GET` | `/mosaicjson/tiles/[{TileMatrixSetId}]/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | create a web map tile image from a MosaicJSON +| `GET` | `/mosaicjson/[{TileMatrixSetId}]/tilejson.json` | JSON | return a Mapbox TileJSON document +| `GET` | `/mosaicjson/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities +| `GET` | `/mosaicjson/point/{lon},{lat}` | JSON | return pixel value from a MosaicJSON dataset +| `GET` | `/mosaicjson/{quadkey}/assets` | JSON | return list of assets overlapping a quadkey +| `GET` | `/mosaicjson/{lon},{lat}/assets` | JSON | return list of assets overlapping a point +| `GET` | `/mosaicjson/{minx},{miny},{maxx},{maxy}/assets` | JSON | return list of assets overlapping a bounding box ## Description From eff96bd2ad8614c10b5ea1cf7d3c646d2e2e19ea Mon Sep 17 00:00:00 2001 From: mackdelany Date: Fri, 6 Aug 2021 14:10:25 +1200 Subject: [PATCH 07/10] intersecting not overlapping --- docs/endpoints/mosaic.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/endpoints/mosaic.md b/docs/endpoints/mosaic.md index 5167d1735..fe8873a42 100644 --- a/docs/endpoints/mosaic.md +++ b/docs/endpoints/mosaic.md @@ -17,9 +17,9 @@ Read Mosaic Info/Metadata and create Web map Tiles from a multiple COG. The `mos | `GET` | `/mosaicjson/[{TileMatrixSetId}]/tilejson.json` | JSON | return a Mapbox TileJSON document | `GET` | `/mosaicjson/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities | `GET` | `/mosaicjson/point/{lon},{lat}` | JSON | return pixel value from a MosaicJSON dataset -| `GET` | `/mosaicjson/{quadkey}/assets` | JSON | return list of assets overlapping a quadkey -| `GET` | `/mosaicjson/{lon},{lat}/assets` | JSON | return list of assets overlapping a point -| `GET` | `/mosaicjson/{minx},{miny},{maxx},{maxy}/assets` | JSON | return list of assets overlapping a bounding box +| `GET` | `/mosaicjson/{quadkey}/assets` | JSON | return list of assets intersecting a quadkey +| `GET` | `/mosaicjson/{lon},{lat}/assets` | JSON | return list of assets intersecting a point +| `GET` | `/mosaicjson/{minx},{miny},{maxx},{maxy}/assets` | JSON | return list of assets intersecting a bounding box ## Description From f493bcd35953cc9bd6f67c422f9f57a4eec7be0d Mon Sep 17 00:00:00 2001 From: Vincent Sarago Date: Fri, 6 Aug 2021 10:50:44 +0200 Subject: [PATCH 08/10] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 2d2cc36dc..942bd6a54 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Release Notes -## 0.3.5 (2021-08-05) +## 0.3.5 (TBD) ### titiler.mosaic From 76ae04d260fb3646176afad48297630bb7c53229 Mon Sep 17 00:00:00 2001 From: Vincent Sarago Date: Fri, 6 Aug 2021 10:51:41 +0200 Subject: [PATCH 09/10] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 942bd6a54..1f5025891 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ### titiler.mosaic -* add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return a list of assets that intersect a given geometry (https://github.com/developmentseed/titiler/pull/351) +* add `/{quadkey}/assets`, `/{lon},{lat}/assets`, `/{minx},{miny},{maxx},{maxy}/assets` GET endpoints to return a list of assets that intersect a given geometry (author @mackdelany, https://github.com/developmentseed/titiler/pull/351) ## 0.3.4 (2021-08-02) From b2a76185d96af9aa8b653fd8134bbaa591d637a5 Mon Sep 17 00:00:00 2001 From: Vincent Sarago Date: Fri, 6 Aug 2021 10:52:44 +0200 Subject: [PATCH 10/10] Update src/titiler/mosaic/tests/test_factory.py --- src/titiler/mosaic/tests/test_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/titiler/mosaic/tests/test_factory.py b/src/titiler/mosaic/tests/test_factory.py index ca5117007..20c1f7342 100644 --- a/src/titiler/mosaic/tests/test_factory.py +++ b/src/titiler/mosaic/tests/test_factory.py @@ -149,7 +149,7 @@ def test_MosaicTilerFactory(): filepath.split("/")[-1] in ["cog1.tif"] for filepath in response.json() ) - response = client.get("/mosaic/-71,46/assets", params={"url": mosaic_file},) + response = client.get("/mosaic/-71,46/assets", params={"url": mosaic_file}) assert response.status_code == 200 assert all( filepath.split("/")[-1] in ["cog1.tif", "cog2.tif"]