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
  • Loading branch information
vincentsarago authored Jan 24, 2024
2 parents 2a9b8a4 + ce9f545 commit 9e1e9ef
Show file tree
Hide file tree
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
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

0 comments on commit 9e1e9ef

Please sign in to comment.