Skip to content

Commit

Permalink
Merge pull request #23 from developmentseed/feature/add-tms-options
Browse files Browse the repository at this point in the history
add tms options
vincentsarago authored Jan 24, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 2a9b8a4 + ce9f545 commit 9e1e9ef
Showing 5 changed files with 102 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@

## 0.12.0 (2024-01-24)

* allow `tms` options in CLI (`profile`, `random` and `get-zooms`) to select TileMatrixSet

## 0.11.0 (2023-10-18)

* update requirements
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -40,17 +40,18 @@ Note: In GDAL 3.2, logging capabilities for /vsicurl, /vsis3 and the like was ad
You can install `tilebench` using pip

```bash
$ pip install -U pip
$ pip install -U tilebench
$ python -m pip install -U pip
$ python -m pip install -U tilebench
```

or install from source:

```bash
$ git clone https://github.com/developmentseed/tilebench.git
$ cd tilebench
$ pip install -U pip
$ pip install -e .
git clone https://github.com/developmentseed/tilebench.git
cd tilebench

python -m pip install -U pip
python -m pip install -e .
```

## API
1 change: 1 addition & 0 deletions tests/fixtures/WGS1984Quad.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"title":"EPSG:4326 for the World","id":"WorldCRS84Quad","uri":"http://www.opengis.net/def/tilematrixset/OGC/1.0/WorldCRS84Quad","orderedAxes":["Lat","Lon"],"crs":"http://www.opengis.net/def/crs/EPSG/0/4326","wellKnownScaleSet":"http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad","tileMatrices":[{"id":"0","scaleDenominator":279541132.014358,"cellSize":0.703125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":2,"matrixHeight":1},{"id":"1","scaleDenominator":139770566.007179,"cellSize":0.3515625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":4,"matrixHeight":2},{"id":"2","scaleDenominator":69885283.0035897,"cellSize":0.17578125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":8,"matrixHeight":4},{"id":"3","scaleDenominator":34942641.5017948,"cellSize":0.087890625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":16,"matrixHeight":8},{"id":"4","scaleDenominator":17471320.7508974,"cellSize":0.0439453125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":32,"matrixHeight":16},{"id":"5","scaleDenominator":8735660.37544871,"cellSize":0.02197265625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":64,"matrixHeight":32},{"id":"6","scaleDenominator":4367830.18772435,"cellSize":0.010986328125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":128,"matrixHeight":64},{"id":"7","scaleDenominator":2183915.09386217,"cellSize":0.0054931640625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":256,"matrixHeight":128},{"id":"8","scaleDenominator":1091957.54693108,"cellSize":0.00274658203125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":512,"matrixHeight":256},{"id":"9","scaleDenominator":545978.773465544,"cellSize":0.001373291015625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":1024,"matrixHeight":512},{"id":"10","scaleDenominator":272989.386732772,"cellSize":0.0006866455078125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":2048,"matrixHeight":1024},{"id":"11","scaleDenominator":136494.693366386,"cellSize":0.00034332275390625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":4096,"matrixHeight":2048},{"id":"12","scaleDenominator":68247.346683193,"cellSize":0.000171661376953125,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":8192,"matrixHeight":4096},{"id":"13","scaleDenominator":34123.6733415964,"cellSize":0.0000858306884765625,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":16384,"matrixHeight":8192},{"id":"14","scaleDenominator":17061.8366707982,"cellSize":0.0000429153442382812,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":32768,"matrixHeight":16384},{"id":"15","scaleDenominator":8530.91833539913,"cellSize":0.0000214576721191406,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":65536,"matrixHeight":32768},{"id":"16","scaleDenominator":4265.45916769956,"cellSize":0.0000107288360595703,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":131072,"matrixHeight":65536},{"id":"17","scaleDenominator":2132.72958384978,"cellSize":5.36441802978515e-6,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":262144,"matrixHeight":131072},{"id":"18","scaleDenominator":1066.36479192489,"cellSize":2.68220901489258e-6,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":524288,"matrixHeight":262144},{"id":"19","scaleDenominator":533.182395962445,"cellSize":1.34110450744629e-6,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":1048576,"matrixHeight":524288},{"id":"20","scaleDenominator":266.591197981222,"cellSize":6.7055225372314e-7,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":2097152,"matrixHeight":1048576},{"id":"21","scaleDenominator":133.295598990611,"cellSize":3.3527612686157e-7,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":4194304,"matrixHeight":2097152},{"id":"22","scaleDenominator":66.6477994953056,"cellSize":1.6763806343079e-7,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":8388608,"matrixHeight":4194304},{"id":"23","scaleDenominator":33.3238997476528,"cellSize":8.381903171539e-8,"cornerOfOrigin":"topLeft","pointOfOrigin":[90.0,-180.0],"tileWidth":256,"tileHeight":256,"matrixWidth":16777216,"matrixHeight":8388608}]}
31 changes: 31 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test CLI."""

import json
import os
from unittest.mock import patch

from click.testing import CliRunner
@@ -9,6 +10,8 @@

COG_PATH = "https://noaa-eri-pds.s3.amazonaws.com/2022_Hurricane_Ian/20221002a_RGB/20221002aC0795145w325100n.tif"

TMS = os.path.join(os.path.dirname(__file__), "fixtures", "WGS1984Quad.json")


def test_profile():
"""Should work as expected."""
@@ -73,6 +76,8 @@ def test_get_zoom():
assert result.exit_code == 0
log = json.loads(result.output)
assert ["minzoom", "maxzoom"] == list(log)
assert log["minzoom"] == 14
assert log["maxzoom"] == 19

result = runner.invoke(
cli, ["get-zooms", COG_PATH, "--reader", "rio_tiler.io.Reader"]
@@ -118,3 +123,29 @@ def test_viz(launch):
assert not result.exception
assert result.exit_code == 0
assert "14-" in result.output


def test_tms():
"""Should work as expected."""
runner = CliRunner()

result = runner.invoke(cli, ["profile", COG_PATH, "--tms", TMS])
assert not result.exception
assert result.exit_code == 0
log = json.loads(result.output)
assert ["HEAD", "GET", "Timing"] == list(log)
# Make sure we didn't cache any request when `--tile` is not provided
assert "0-" in log["GET"]["ranges"][0]

result = runner.invoke(cli, ["get-zooms", COG_PATH, "--tms", TMS])
assert not result.exception
assert result.exit_code == 0
log = json.loads(result.output)
assert ["minzoom", "maxzoom"] == list(log)
assert log["minzoom"] == 13
assert log["maxzoom"] == 18

result = runner.invoke(cli, ["random", COG_PATH, "--tms", TMS])
assert not result.exception
assert result.exit_code == 0
assert "-" in result.output
79 changes: 59 additions & 20 deletions tilebench/scripts/cli.py
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
from tilebench import profile as profiler
from tilebench.viz import TileDebug

tms = morecantile.tms.get("WebMercatorQuad")
default_tms = morecantile.tms.get("WebMercatorQuad")


# The CLI command group.
@@ -53,6 +53,11 @@ def cli():
type=str,
help="rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader`",
)
@click.option(
"--tms",
help="Path to TileMatrixSet JSON file.",
type=click.Path(),
)
@click.option(
"--config",
"config",
@@ -62,9 +67,23 @@ def cli():
help="GDAL configuration options.",
)
def profile(
input, tile, tilesize, zoom, add_kernels, add_stdout, add_cprofile, reader, config
input,
tile,
tilesize,
zoom,
add_kernels,
add_stdout,
add_cprofile,
reader,
tms,
config,
):
"""Profile COGReader Mercator Tile read."""
tilematrixset = default_tms
if tms:
with open(tms, "r") as f:
tilematrixset = morecantile.TileMatrixSet(**json.load(f))

if reader:
module, classname = reader.rsplit(".", 1)
reader = getattr(importlib.import_module(module), classname) # noqa
@@ -75,19 +94,19 @@ def profile(

if not tile:
with rasterio.Env(CPL_VSIL_CURL_NON_CACHED=parse_path(input).as_vsi()):
with Reader(input, tms=tms) as cog:
with Reader(input, tms=tilematrixset) as cog:
if zoom is None:
zoom = randint(cog.minzoom, cog.maxzoom)

w, s, e, n = cog.geographic_bounds
# Truncate BBox to the TMS bounds
w = max(tms.bbox.left, w)
s = max(tms.bbox.bottom, s)
e = min(tms.bbox.right, e)
n = min(tms.bbox.top, n)
w = max(tilematrixset.bbox.left, w)
s = max(tilematrixset.bbox.bottom, s)
e = min(tilematrixset.bbox.right, e)
n = min(tilematrixset.bbox.top, n)

ul_tile = tms.tile(w, n, zoom)
lr_tile = tms.tile(e, s, zoom)
ul_tile = tilematrixset.tile(w, n, zoom)
lr_tile = tilematrixset.tile(e, s, zoom)
extrema = {
"x": {"min": ul_tile.x, "max": lr_tile.x + 1},
"y": {"min": ul_tile.y, "max": lr_tile.y + 1},
@@ -109,7 +128,7 @@ def profile(
config=config,
)
def _read_tile(src_path: str, x: int, y: int, z: int, tilesize: int = 256):
with Reader(src_path) as cog:
with Reader(src_path, tms=tilematrixset) as cog:
return cog.tile(x, y, z, tilesize=tilesize)

(_, _), stats = _read_tile(input, tile_x, tile_y, tile_z, tilesize)
@@ -124,8 +143,18 @@ def _read_tile(src_path: str, x: int, y: int, z: int, tilesize: int = 256):
type=str,
help="rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader`",
)
def get_zooms(input, reader):
@click.option(
"--tms",
help="Path to TileMatrixSet JSON file.",
type=click.Path(),
)
def get_zooms(input, reader, tms):
"""Get Mercator Zoom levels."""
tilematrixset = default_tms
if tms:
with open(tms, "r") as f:
tilematrixset = morecantile.TileMatrixSet(**json.load(f))

if reader:
module, classname = reader.rsplit(".", 1)
reader = getattr(importlib.import_module(module), classname) # noqa
@@ -134,7 +163,7 @@ def get_zooms(input, reader):

Reader = reader or COGReader

with Reader(input, tms=tms) as cog:
with Reader(input, tms=tilematrixset) as cog:
click.echo(json.dumps({"minzoom": cog.minzoom, "maxzoom": cog.maxzoom}))


@@ -146,8 +175,18 @@ def get_zooms(input, reader):
type=str,
help="rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader`",
)
def random(input, zoom, reader):
@click.option(
"--tms",
help="Path to TileMatrixSet JSON file.",
type=click.Path(),
)
def random(input, zoom, reader, tms):
"""Get random tile."""
tilematrixset = default_tms
if tms:
with open(tms, "r") as f:
tilematrixset = morecantile.TileMatrixSet(**json.load(f))

if reader:
module, classname = reader.rsplit(".", 1)
reader = getattr(importlib.import_module(module), classname) # noqa
@@ -156,19 +195,19 @@ def random(input, zoom, reader):

Reader = reader or COGReader

with Reader(input, tms=tms) as cog:
with Reader(input, tms=tilematrixset) as cog:
if zoom is None:
zoom = randint(cog.minzoom, cog.maxzoom)
w, s, e, n = cog.geographic_bounds

# Truncate BBox to the TMS bounds
w = max(tms.bbox.left, w)
s = max(tms.bbox.bottom, s)
e = min(tms.bbox.right, e)
n = min(tms.bbox.top, n)
w = max(tilematrixset.bbox.left, w)
s = max(tilematrixset.bbox.bottom, s)
e = min(tilematrixset.bbox.right, e)
n = min(tilematrixset.bbox.top, n)

ul_tile = tms.tile(w, n, zoom)
lr_tile = tms.tile(e, s, zoom)
ul_tile = tilematrixset.tile(w, n, zoom)
lr_tile = tilematrixset.tile(e, s, zoom)
extrema = {
"x": {"min": ul_tile.x, "max": lr_tile.x + 1},
"y": {"min": ul_tile.y, "max": lr_tile.y + 1},

0 comments on commit 9e1e9ef

Please sign in to comment.