Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tms options #23

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
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
Expand All @@ -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."""
Expand Down Expand Up @@ -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"]
Expand Down Expand Up @@ -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
Expand Up @@ -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.
Expand Down Expand Up @@ -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",
Expand All @@ -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
Expand All @@ -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},
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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}))


Expand All @@ -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
Expand All @@ -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},
Expand Down
Loading