Breaking changes¶
rio-tiler
version 4.0 introduced many breaking changes. This
document aims to help with migrating your code to use rio-tiler
4.0.
Python >=3.8¶
As for rasterio, we removed python 3.7 support (rasterio/rasterio#2445)
COGReader -> Reader¶
Because the main reader will not only work with COG but most of GDAL supported raster, we choose to rename it to Reader
.
# before
from rio_tiler.io import COGReader
from rio_tiler.io.cogeo import COGReader
# now
from rio_tiler.io import Reader
from rio_tiler.io.rasterio import Reader
Note: We created rio_tiler.io.COGReader
alias to Reader
for compatibility.
rio_tiler.io.cogeo -> rio_tiler.io.rasterio¶
Reader's submodule now reflect the backend they use (rasterio, xarray, stac, ...)
# before
from rio_tiler.io.cogeo import COGReader
# now
from rio_tiler.io.rasterio import Reader
Band names¶
Band names are now prefixed with b
(e.g b1
, b2
)
# before
with COGReader(
"http://oin-hotosm.s3.amazonaws.com/5a95f32c2553e6000ce5ad2e/0/10edab38-1bdd-4c06-b83d-6e10ac532b7d.tif"
) as src:
stats = src.statistics()
print(list(stats))
>>> ["1", "2", "3"]
info = src.info()
print(info.band_metadata)
>>> [("1", {}), ("2", {}), ("3", {})]
print(info.band_descriptions)
>>> [("1", ""), ("2", ""), ("3", "")]
# now
with Reader(
"http://oin-hotosm.s3.amazonaws.com/5a95f32c2553e6000ce5ad2e/0/10edab38-1bdd-4c06-b83d-6e10ac532b7d.tif"
) as src:
stats = src.statistics()
print(list(stats))
>>> ["b1", "b2", "b3"]
info = src.info()
print(info.band_metadata)
>>> [("b1", {}), ("b2", {}), ("b3", {})]
print(info.band_descriptions)
>>> [("b1", ""), ("b2", ""), ("b3", "")]
MultiBaseReader _get_asset_url
¶
We replaced _get_asset_url
method in MultibaseReader
by _get_asset_info
which should return a dictionary in form of {"url": ..., "env": ...}
(ref: cogeotiff/rio-tiler!552)
# before
with STACReader("stac.json") as stac:
print(stac._get_asset_url("green"))
>>> "green.tif"
# new
with STACReader("stac.json") as stac:
print(stac._get_asset_info("green"))
>>> {"url": "green.tif", "env": {}}
MultiBaseReader Expressions¶
We updated the expression
format for MultiBaseReader
(e.g STAC) to include band names and not only the asset name
# before
with STACReader("stac.json") as stac:
stac.tile(701, 102, 8, expression="green/red")
# now
with STACReader("stac.json") as stac:
stac.tile(701, 102, 8, expression="green_b1/red_b1")
In addition we also removed asset_expression
option in MultiBaseReader
. This can be achieved directly using expression.
# before
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac:
img = stac.tile(
145,
103,
8,
tilesize=256,
assets=["B01", "B02"],
asset_expression={
"B01": "b1+500", # add 500 to the first band
"B02": "b1-100", # substract 100 to the first band
}
)
# now
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac:
img = stac.tile(
145,
103,
8,
tilesize=256,
expression="B01_b1+500;B02_b1-100",
)
No more GCPCOGReader¶
rio_tiler.io.Reader
will now recognize if the files has internal GCPS.
# before
from rio_tiler.io import GCPCOGReader
with GCPCOGReader("my_tif_with_gcps.tif") as src:
pass
# now
from rio_tiler.io import Reader
with Reader("my_tif_with_gcps.tif") as src:
pass
PointData object¶
As for method returning images
, methods returning point values (Reader.point()
) now return a PointData
object.
# before
with COGReader("cog.tif") as cog:
print(cog.point(10.20, -42.0))
>>> [0, 0, 0]
# now
with Reader("cog.tif") as src:
print(src.point(10.20, -42.0))
>>> PointData(
data=array([3744], dtype=uint16),
mask=array([255], dtype=uint8),
band_names=['b1'],
coordinates=(10.20, -42),
crs=CRS.from_epsg(4326),
assets=['cog.tif'],
metadata={}
)
Low-level reader methods return ImageData and PointData objects¶
rio_tiler.reader.read
and rio_tiler.readers.part
now return ImageData
object instead of Tuple[ndarray, ndarray]
.
from rio_tiler.reader import read, part, point
from rio_tiler.models import ImageData, PointData
# before
with rasterio.open("image.tif") as src:
data, mask = read(src)
pts = point(10.20, -42.0)
print(pts)
>>> [0, 0, 0]
# now
with rasterio.open("image.tif") as src:
img = read(src)
assert isinstance(img, ImageData)
pts = point(src, (10.20, -42.0))
assert isinstance(pts, PointData)
print(pts)
>>> PointData(
data=array([3744], dtype=uint16),
mask=array([255], dtype=uint8),
band_names=['b1'],
coordinates=(10.20, -42),
crs=CRS.from_epsg(4326),
assets=['cog.tif'],
metadata={}
)
Reader options¶
We removed nodata
, unscale
, resampling_method
, vrt_options
and post_process
options to rio_tiler.io.Reader
init method and replaced with a global options
:
# before
with COGReader("cog.tif", nodata=1, resampling_method="bilinear") as cog:
data = cog.preview()
# now
with Reader(COGEO, options={"nodata": 1, "resampling_method": "bilinear"}) as src:
data = src.preview()
Base classes minzoom and maxzoom¶
We moved min/max zoom attribute from the SpatialMixin
to the base classes definition directly. This means that each class should now take care of the definition of those two variables.
# before
@attr.s
class BandFileReader(MultiBandReader):
"""Test MultiBand"""
input: str = attr.ib()
tms: morecantile.TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS)
reader: Type[BaseReader] = attr.ib(init=False, default=Reader)
reader_options: Dict = attr.ib(factory=dict)
def __attrs_post_init__(self):
...
# now
@attr.s
class BandFileReader(MultiBandReader):
"""Test MultiBand"""
input: str = attr.ib()
tms: morecantile.TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS)
reader: Type[BaseReader] = attr.ib(init=False, default=Reader)
reader_options: Dict = attr.ib(factory=dict)
minzoom: int = attr.ib()
maxzoom: int = attr.ib()
@minzoom.default
def _minzoom(self):
return self.tms.minzoom
@maxzoom.default
def _maxzoom(self):
return self.tms.maxzoom
def __attrs_post_init__(self):
...
New Features¶
Non-Geo reader¶
Because not all raster are geo-referenced, we added rio_tiler.io.ImageReader
to allow opening and reading non-geo images. All methods are returning data in the pixel coordinate system.
with ImageReader("image.jpg") as src:
info = src.info()
stats = src.statistics()
# Part of the image (Origin is top-lef, coordinates should be in form of (left, bottom, right, top))
im = src.part((0, 100, 100, 0))
# 256x256 Tile (Origin of the TMS is top-lef)
im = src.tile(0, 0, src.maxzoom)
# read pixel x=10, y=5 (Origin is top-left)
pt = src.point(10, 5)
Xarray reader¶
We added an optional xarray compatible reader in rio-tiler v4.0. The reader takes a xarray.DataArray as input which should have a CRS and geo-spatial variables (x,y or longitude,latitude).
import rioxarray
import xarray
from rio_tiler.io import XarrayReader
with xarray.open_dataset(
"https://ncsa.osn.xsede.org/Pangeo/pangeo-forge/noaa-coastwatch-geopolar-sst-feedstock/noaa-coastwatch-geopolar-sst.zarr",
engine="zarr",
decode_coords="all"
) as src:
ds = src["analysed_sst"][:1]
# the SST dataset do not have a CRS info
# so we need to add it to `virtualy` within the Xarray DataArray
ds.rio.write_crs("epsg:4326", inplace=True)
with XarrayReader(ds) as dst:
print(dst.info())
img = dst.tile(1, 1, 2)
Note: Users might experience some really bad performance depending on the chunking of the original zarr.
Dataset Statistics¶
Starting with rio-tiler 4.0, if the input dataset has statistics
(e.g STATISTICS_MINIMUM
, STATISTICS_MAXIMUM
) within its metadata, rio-tiler will try to use it to rescale automatically the output image.
from rio_tiler.io import Reader
with Reader("https://data.geo.admin.ch/ch.swisstopo.swissalti3d/swissalti3d_2019_2573-1085/swissalti3d_2019_2573-1085_0.5_2056_5728.tif") as src:
info = src.info()
print(info.band_metadata)
>>> [('b1',
{'STATISTICS_COVARIANCES': '10685.98787505646',
'STATISTICS_EXCLUDEDVALUES': '-9999',
'STATISTICS_MAXIMUM': '2015.0944824219',
'STATISTICS_MEAN': '1754.471184271',
'STATISTICS_MINIMUM': '1615.8128662109',
'STATISTICS_SKIPFACTORX': '1',
'STATISTICS_SKIPFACTORY': '1',
'STATISTICS_STDDEV': '103.37305197708'})]
img = src.preview()
# The min/max statistics are saved within every output image object
print(img.dataset_statistics)
>>> [(1615.8128662109, 2015.0944824219)]
buffer = img.render()
>>> rio-tiler/rio_tiler/models.py:516: InvalidDatatypeWarning: Invalid type: `float32` for the `PNG` driver. Data will be rescaled using min/max type bounds or dataset_statistics.