diff --git a/CHANGES.txt b/CHANGES.txt index f8131c9..df6fdfb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +3.0b4 (2020-08-21) +------------------ +- Update to rio-tiler 2.0b7 and switch to attr (ref: https://github.com/cogeotiff/rio-tiler/pull/225) + 3.0b3 (2020-07-30) ------------------ - Update rio-tiler and raise MissingAsset exception instead of InvalidBandName (#10) @@ -8,4 +12,4 @@ 3.0b1 (2020-07-22) ------------------ -- Use rio-tiler 2.0b1 and its new COGReader and STACReader \ No newline at end of file +- Use rio-tiler 2.0b1 and its new COGReader and STACReader diff --git a/README.md b/README.md index cccf014..a253090 100644 --- a/README.md +++ b/README.md @@ -93,8 +93,6 @@ class COGReader: COG center + minzoom colormap: dict COG internal colormap. - info: dict - General information about the COG (datatype, indexes, ...) Methods ------- @@ -106,6 +104,8 @@ class COGReader: Read preview of the COG. point((10, 10), indexes=1) Read a point value from the COG. + info() + General information about the COG (datatype, indexes, ...) stats(pmin=5, pmax=95) Get Raster statistics. meta(pmin=5, pmax=95) @@ -126,28 +126,6 @@ class COGReader: - **bounds**: Return the dataset bounds in WGS84 - **center**: Return the center of the dataset + minzoom - **spatial_info**: Return the bounds, center and zoom infos -- **info**: Return simple metadata about the dataset - -```python -with COGReader("myfile.tif") as cog: - print(cog.info) -{ - "bounds": [-119.05915661478785, 13.102845359730287, -84.91821332299578, 33.995073647795806], - "center": [-101.98868496889182, 23.548959503763047, 3], - "minzoom": 3, - "maxzoom": 12, - "band_metadata": [[1, {}]], - "band_descriptions": [[1,"band1"]], - "dtype": "int8", - "colorinterp": ["palette"], - "nodata_type": "Nodata", - "colormap": { - "0": [0, 0, 0, 0], - "1": [0, 61, 0, 255], - ... - } -} -``` #### Methods - **tile()**: Read map tile from a raster @@ -228,6 +206,29 @@ with COGReader("myfile.tif") as cog: [3, 4] ``` +- **info**: Return simple metadata about the dataset + +```python +with COGReader("myfile.tif") as cog: + print(cog.info()) +{ + "bounds": [-119.05915661478785, 13.102845359730287, -84.91821332299578, 33.995073647795806], + "center": [-101.98868496889182, 23.548959503763047, 3], + "minzoom": 3, + "maxzoom": 12, + "band_metadata": [[1, {}]], + "band_descriptions": [[1,"band1"]], + "dtype": "int8", + "colorinterp": ["palette"], + "nodata_type": "Nodata", + "colormap": { + "0": [0, 0, 0, 0], + "1": [0, 61, 0, 255], + ... + } +} +``` + - **stats()**: Return image statistics (Min/Max/Stdev) Note: `tms` has no effect on `stats`. @@ -539,4 +540,4 @@ Verifying PEP257 Compliance..............................................Passed mypy.....................................................................Passed $ git push origin -``` \ No newline at end of file +``` diff --git a/rio_tiler_crs/cogeo.py b/rio_tiler_crs/cogeo.py index 67ba4ba..ea62ab4 100644 --- a/rio_tiler_crs/cogeo.py +++ b/rio_tiler_crs/cogeo.py @@ -1,9 +1,9 @@ """rio-tiler-crs.cogeo.""" from concurrent import futures -from dataclasses import dataclass from typing import Any, Dict, Optional, Sequence, Tuple +import attr import morecantile import numpy from rasterio.transform import from_bounds @@ -30,7 +30,7 @@ def geotiff_options( return dict(crs=tms.crs, transform=dst_transform) -@dataclass +@attr.s class COGReader(RioTilerReader): """ Cloud Optimized GeoTIFF Reader. @@ -90,7 +90,7 @@ class COGReader(RioTilerReader): """ - tms: morecantile.TileMatrixSet = default_tms + tms: morecantile.TileMatrixSet = attr.ib(default=default_tms) def _get_zooms(self): """Calculate raster min/max zoom level.""" @@ -120,8 +120,8 @@ def _zoom_for_pixelsize(pixel_size, max_z=24): ) min_zoom = _zoom_for_pixelsize(ovr_resolution) - self._minzoom = self._minzoom or min_zoom - self._maxzoom = self._maxzoom or max_zoom + self.minzoom = self.minzoom or min_zoom + self.maxzoom = self.maxzoom or max_zoom return diff --git a/rio_tiler_crs/stac.py b/rio_tiler_crs/stac.py index 29ba772..91f69c6 100644 --- a/rio_tiler_crs/stac.py +++ b/rio_tiler_crs/stac.py @@ -1,22 +1,20 @@ """rio-tiler-crs.stac.""" -from dataclasses import dataclass -from typing import Any, Optional, Sequence, Tuple, Union +from typing import Type +import attr import morecantile -import numpy -from rio_tiler.errors import MissingAssets -from rio_tiler.expression import apply_expression -from rio_tiler.io import STACReader as RioTilerReader +from rio_tiler.io import BaseReader +from rio_tiler.io import STACReader as RioTilerSTACReader -from .cogeo import multi_tile +from .cogeo import COGReader -TMS = morecantile.tms.get("WebMercatorQuad") +default_tms = morecantile.tms.get("WebMercatorQuad") -@dataclass -class STACReader(RioTilerReader): +@attr.s +class STACReader(RioTilerSTACReader): """ STAC + Cloud Optimized GeoTIFF Reader. @@ -80,48 +78,17 @@ class STACReader(RioTilerReader): """ - tms: morecantile.TileMatrixSet = TMS - maxzoom: int = TMS.maxzoom - minzoom: int = TMS.minzoom - - def tile( - self, - tile_x: int, - tile_y: int, - tile_z: int, - tilesize: int = 256, - assets: Union[Sequence[str], str] = None, - expression: Optional[str] = "", # Expression based on asset names - asset_expression: Optional[ - str - ] = "", # Expression for each asset based on index names - **kwargs: Any, - ) -> Tuple[numpy.ndarray, numpy.ndarray]: - """Read a TMS map tile from COGs.""" - if isinstance(assets, str): - assets = (assets,) - - if expression: - assets = self._parse_expression(expression) - - if not assets: - raise MissingAssets( - "assets must be passed either via expression or assets options." - ) - - asset_urls = self._get_href(assets) - data, mask = multi_tile( - asset_urls, - tile_x, - tile_y, - tile_z, - expression=asset_expression, - tms=self.tms, - **kwargs, - ) - - if expression: - blocks = expression.split(",") - data = apply_expression(blocks, assets, data) - - return data, mask + reader: Type[BaseReader] = attr.ib(default=COGReader) + tms: morecantile.TileMatrixSet = attr.ib(default=default_tms) + minzoom: int = attr.ib(default=None) + maxzoom: int = attr.ib(default=None) + + def __attrs_post_init__(self): + """forward tms to readers options and set min/max zoom.""" + self.reader_options.update({"tms": self.tms}) + + if self.minzoom is None: + self.minzoom = self.tms.minzoom + + if self.maxzoom is None: + self.maxzoom = self.tms.maxzoom diff --git a/setup.py b/setup.py index 6fac79f..7bd947f 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md") as f: long_description = f.read() -inst_reqs = ["morecantile>=1.1.0", "rio-tiler~=2.0b4", "boto3"] +inst_reqs = ["morecantile>=1.1.0", "rio-tiler>=2.0b7"] extra_reqs = { "test": ["pytest", "pytest-cov"], @@ -14,7 +14,7 @@ setup( name="rio-tiler-crs", - version="3.0b3", + version="3.0b4", python_requires=">=3", description=u"""A rio-tiler plugin to create tile for arbitraty grid""", long_description=long_description, diff --git a/tests/test_cogeo.py b/tests/test_cogeo.py index fe7daeb..7a04b95 100644 --- a/tests/test_cogeo.py +++ b/tests/test_cogeo.py @@ -178,7 +178,7 @@ def test_reader_get_zoom(): def test_reader_info(): """Test COGReader.info.""" with COGReader(COG_PATH) as cog: - info = cog.info + info = cog.info() assert info["minzoom"] == 5 assert info["maxzoom"] == 8 assert info["center"][-1] == 5 @@ -193,11 +193,11 @@ def test_reader_info(): assert not info.get("offset") with COGReader(COG_CMAP_PATH) as cog: - info = cog.info + info = cog.info() assert info["colormap"] with COGReader(COG_SCALE_PATH) as cog: - info = cog.info + info = cog.info() assert info["scale"] assert info["offset"] diff --git a/tests/test_stac.py b/tests/test_stac.py index 6791f04..bc8d2ed 100644 --- a/tests/test_stac.py +++ b/tests/test_stac.py @@ -94,6 +94,12 @@ def test_fetch_stac(): ) as stac: assert stac.assets == ["metadata"] + with STACReader(STAC_PATH, tms=morecantile.tms.get("WorldCRS84Quad")) as stac: + assert stac.minzoom == 0 + assert stac.maxzoom == 17 + tms = stac.reader_options.get("tms") + assert tms.identifier == "WorldCRS84Quad" + @patch("rio_tiler.io.cogeo.rasterio") def test_reader_tiles(rio):