1111from loguru import logger as log
1212from rasterio ._path import _parse_path as parse_path
1313from rasterio .rio import options
14- from rio_tiler .io import BaseReader , COGReader , MultiBandReader , MultiBaseReader
14+ from rio_tiler .io import BaseReader , MultiBandReader , MultiBaseReader , Reader
1515
1616from tilebench import profile as profiler
1717from tilebench .viz import TileDebug
1818
1919default_tms = morecantile .tms .get ("WebMercatorQuad" )
2020
2121
22+ def options_to_dict (ctx , param , value ):
23+ """
24+ click callback to validate `--opt KEY1=VAL1 --opt KEY2=VAL2` and collect
25+ in a dictionary like the one below, which is what the CLI function receives.
26+ If no value or `None` is received then an empty dictionary is returned.
27+
28+ {
29+ 'KEY1': 'VAL1',
30+ 'KEY2': 'VAL2'
31+ }
32+
33+ Note: `==VAL` breaks this as `str.split('=', 1)` is used.
34+ """
35+
36+ if not value :
37+ return {}
38+ else :
39+ out = {}
40+ for pair in value :
41+ if "=" not in pair :
42+ raise click .BadParameter (f"Invalid syntax for KEY=VAL arg: { pair } " )
43+ else :
44+ k , v = pair .split ("=" , 1 )
45+ out [k ] = v
46+
47+ return out
48+
49+
2250# The CLI command group.
2351@click .group (help = "Command line interface for the tilebench Python package." )
2452def cli ():
@@ -51,7 +79,7 @@ def cli():
5179@click .option (
5280 "--reader" ,
5381 type = str ,
54- help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader `" ,
82+ help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.Reader `" ,
5583)
5684@click .option (
5785 "--tms" ,
@@ -66,6 +94,15 @@ def cli():
6694 callback = options ._cb_key_val ,
6795 help = "GDAL configuration options." ,
6896)
97+ @click .option (
98+ "--reader-params" ,
99+ "-p" ,
100+ "reader_params" ,
101+ metavar = "NAME=VALUE" ,
102+ multiple = True ,
103+ callback = options_to_dict ,
104+ help = "Reader Options." ,
105+ )
69106def profile (
70107 input ,
71108 tile ,
@@ -77,8 +114,9 @@ def profile(
77114 reader ,
78115 tms ,
79116 config ,
117+ reader_params ,
80118):
81- """Profile COGReader Mercator Tile read."""
119+ """Profile Reader Tile read."""
82120 tilematrixset = default_tms
83121 if tms :
84122 with open (tms , "r" ) as f :
@@ -90,15 +128,17 @@ def profile(
90128 if not issubclass (reader , (BaseReader , MultiBandReader , MultiBaseReader )):
91129 warnings .warn (f"Invalid reader type: { type (reader )} " , stacklevel = 1 )
92130
93- Reader = reader or COGReader
131+ DstReader = reader or Reader
94132
95133 if not tile :
96134 with rasterio .Env (CPL_VSIL_CURL_NON_CACHED = parse_path (input ).as_vsi ()):
97- with Reader (input , tms = tilematrixset ) as cog :
135+ with Reader (input , tms = tilematrixset , ** reader_params ) as cog :
98136 if zoom is None :
99137 zoom = randint (cog .minzoom , cog .maxzoom )
100138
101- w , s , e , n = cog .geographic_bounds
139+ w , s , e , n = cog .get_geographic_bounds (
140+ tilematrixset .rasterio_geographic_crs
141+ )
102142 # Truncate BBox to the TMS bounds
103143 w = max (tilematrixset .bbox .left , w )
104144 s = max (tilematrixset .bbox .bottom , s )
@@ -128,7 +168,7 @@ def profile(
128168 config = config ,
129169 )
130170 def _read_tile (src_path : str , x : int , y : int , z : int , tilesize : int = 256 ):
131- with Reader (src_path , tms = tilematrixset ) as cog :
171+ with DstReader (src_path , tms = tilematrixset , ** reader_params ) as cog :
132172 return cog .tile (x , y , z , tilesize = tilesize )
133173
134174 (_ , _ ), stats = _read_tile (input , tile_x , tile_y , tile_z , tilesize )
@@ -141,14 +181,23 @@ def _read_tile(src_path: str, x: int, y: int, z: int, tilesize: int = 256):
141181@click .option (
142182 "--reader" ,
143183 type = str ,
144- help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader `" ,
184+ help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.Reader `" ,
145185)
146186@click .option (
147187 "--tms" ,
148188 help = "Path to TileMatrixSet JSON file." ,
149189 type = click .Path (),
150190)
151- def get_zooms (input , reader , tms ):
191+ @click .option (
192+ "--reader-params" ,
193+ "-p" ,
194+ "reader_params" ,
195+ metavar = "NAME=VALUE" ,
196+ multiple = True ,
197+ callback = options_to_dict ,
198+ help = "Reader Options." ,
199+ )
200+ def get_zooms (input , reader , tms , reader_params ):
152201 """Get Mercator Zoom levels."""
153202 tilematrixset = default_tms
154203 if tms :
@@ -161,9 +210,9 @@ def get_zooms(input, reader, tms):
161210 if not issubclass (reader , (BaseReader , MultiBandReader , MultiBaseReader )):
162211 warnings .warn (f"Invalid reader type: { type (reader )} " , stacklevel = 1 )
163212
164- Reader = reader or COGReader
213+ DstReader = reader or Reader
165214
166- with Reader (input , tms = tilematrixset ) as cog :
215+ with DstReader (input , tms = tilematrixset , ** reader_params ) as cog :
167216 click .echo (json .dumps ({"minzoom" : cog .minzoom , "maxzoom" : cog .maxzoom }))
168217
169218
@@ -173,14 +222,23 @@ def get_zooms(input, reader, tms):
173222@click .option (
174223 "--reader" ,
175224 type = str ,
176- help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader `" ,
225+ help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.Reader `" ,
177226)
178227@click .option (
179228 "--tms" ,
180229 help = "Path to TileMatrixSet JSON file." ,
181230 type = click .Path (),
182231)
183- def random (input , zoom , reader , tms ):
232+ @click .option (
233+ "--reader-params" ,
234+ "-p" ,
235+ "reader_params" ,
236+ metavar = "NAME=VALUE" ,
237+ multiple = True ,
238+ callback = options_to_dict ,
239+ help = "Reader Options." ,
240+ )
241+ def random (input , zoom , reader , tms , reader_params ):
184242 """Get random tile."""
185243 tilematrixset = default_tms
186244 if tms :
@@ -193,12 +251,12 @@ def random(input, zoom, reader, tms):
193251 if not issubclass (reader , (BaseReader , MultiBandReader , MultiBaseReader )):
194252 warnings .warn (f"Invalid reader type: { type (reader )} " , stacklevel = 1 )
195253
196- Reader = reader or COGReader
254+ DstReader = reader or Reader
197255
198- with Reader (input , tms = tilematrixset ) as cog :
256+ with DstReader (input , tms = tilematrixset , ** reader_params ) as cog :
199257 if zoom is None :
200258 zoom = randint (cog .minzoom , cog .maxzoom )
201- w , s , e , n = cog .geographic_bounds
259+ w , s , e , n = cog .get_geographic_bounds ( tilematrixset . rasterio_geographic_crs )
202260
203261 # Truncate BBox to the TMS bounds
204262 w = max (tilematrixset .bbox .left , w )
@@ -237,7 +295,7 @@ def random(input, zoom, reader, tms):
237295@click .option (
238296 "--reader" ,
239297 type = str ,
240- help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.COGReader `" ,
298+ help = "rio-tiler Reader (BaseReader). Default is `rio_tiler.io.Reader `" ,
241299)
242300@click .option (
243301 "--config" ,
@@ -247,21 +305,31 @@ def random(input, zoom, reader, tms):
247305 callback = options ._cb_key_val ,
248306 help = "GDAL configuration options." ,
249307)
250- def viz (src_path , port , host , server_only , reader , config ):
308+ @click .option (
309+ "--reader-params" ,
310+ "-p" ,
311+ "reader_params" ,
312+ metavar = "NAME=VALUE" ,
313+ multiple = True ,
314+ callback = options_to_dict ,
315+ help = "Reader Options." ,
316+ )
317+ def viz (src_path , port , host , server_only , reader , config , reader_params ):
251318 """WEB UI to visualize VSI statistics for a web mercator tile requests."""
252319 if reader :
253320 module , classname = reader .rsplit ("." , 1 )
254321 reader = getattr (importlib .import_module (module ), classname ) # noqa
255- if not issubclass (reader , (BaseReader )):
322+ if not issubclass (reader , (BaseReader , MultiBandReader , MultiBaseReader )):
256323 warnings .warn (f"Invalid reader type: { type (reader )} " , stacklevel = 1 )
257324
258- Reader = reader or COGReader
325+ DstReader = reader or Reader
259326
260327 config = config or {}
261328
262329 application = TileDebug (
263330 src_path = src_path ,
264- reader = Reader ,
331+ reader = DstReader ,
332+ reader_params = reader_params ,
265333 port = port ,
266334 host = host ,
267335 config = config ,
0 commit comments