Readers
rio-tiler
's Reader are built from its abstract base classes (BaseReader
, MultiBandReader
, MultiBaseReader
). Those Classes implements defaults interfaces which helps the integration in broader application. To learn more about rio-tiler
's base classes see Base classes and custom readers
rio_tiler.io.rasterio.Reader¶
The Reader
is designed to work with simple raster datasets (e.g COG, GeoTIFF, ...).
The class is derived from the rio_tiler.io.base.BaseReader
base class.
from rio_tiler.io import Reader
Reader.__mro__
>>> (rio_tiler.io.rasterio.Reader,
rio_tiler.io.base.BaseReader,
rio_tiler.io.base.SpatialMixin,
object)
Attributes¶
- input (str): filepath
- dataset (rasterio dataset, optional): rasterio opened dataset
- tms (morecantile.TileMatrixSet, optional): morecantile TileMatrixSet used for tile reading (defaults to WebMercator)
- colormap (dict, optional): dataset's colormap
- options (rio_tiler.reader.Options, optional): Options to forward to rio_tiler.reader functions (e.g nodata, vrt_options, resampling)
Properties¶
- bounds: dataset's bounds (in dataset crs)
- crs: dataset's crs
- minzoom: dataset's minzoom (in TMS)
- maxzoom: dataset's maxzoom (in TMS)
- transform: dataset's Affine transform
- height: dataset's height
- width: dataset's width
from rio_tiler.io import Reader
with Reader("myfile.tif") as src:
print(src.dataset)
print(src.tms.identifier)
print(src.minzoom)
print(src.maxzoom)
print(src.bounds)
print(src.crs)
print(src.colormap)
>> <open DatasetReader name='myfile.tif' mode='r'>
WebMercatorQuad
16
22
(683715.3266400001, 1718548.5702, 684593.2680000002, 1719064.90736)
EPSG:32620
{}
Methods¶
-
get_geographic_bounds(crs: rasterio.crs.CRS): Get dataset bounds in geographic projection
from rio_tiler.io import Reader with Reader("myfile.tif") as src: print(src.get_geographic_bounds("EPSG:4326")) (-61.287001876638215, 15.537756794450583, -61.27877967704677, 15.542486503997608)
-
read(): Read the entire dataset
from rio_tiler.io import Reader from rio_tiler.models import ImageData with Reader("myfile.tif") as src: img = src.read() assert isinstance(img, ImageData) assert img.crs == src.dataset.crs assert img.assets == ["myfile.tif"] assert img.width == src.dataset.width assert img.height == src.dataset.height assert img.count == src.dataset.count # With indexes with Reader("myfile.tif") as src: img = src.read(indexes=1) # or src.read(indexes=(1,)) assert img.count == 1 assert img.band_names == ["b1"] # With expression with Reader("myfile.tif") as src: img = src.read(expression="b1/b2") assert img.count == 1 assert img.band_names == ["b1/b2"]
-
tile(): Read map tile from a raster
from rio_tiler.contants import WEB_MERCATOR_CRS from rio_tiler.io import Reader from rio_tiler.models import ImageData with Reader("myfile.tif") as src: # src.tile(tile_x, tile_y, tile_z, **kwargs) img = src.tile(1, 2, 3, tilesize=256) assert isinstance(img, ImageData) assert img.crs == WEB_MERCATOR_CRS assert img.assets == ["myfile.tif"] # With indexes with Reader("myfile.tif") as src: img = src.tile(1, 2, 3, tilesize=256, indexes=1) assert img.count == 1 # With expression with Reader("myfile.tif") as src: img = src.tile(1, 2, 3, tilesize=256, expression="B1/B2") assert img.count == 1 # Using buffer # Sometime, to avoid edge artefacts, you may want to read buffered tile data. # ref: # - https://github.com/cogeotiff/rio-tiler/issues/365 # - https://github.com/cogeotiff/rio-tiler/pull/405 with Reader("myfile.tif") as src: # add 0.5 pixel on each side of the tile img = src.tile(1, 2, 3, buffer=0.5) assert img.width == 257 assert img.height == 257 # add 1 pixel on each side of the tile img = src.tile(1, 2, 3, buffer=1) assert img.width == 258 assert img.height == 258
-
part(): Read a raster for a given bounding box (
bbox
). By default the bbox is considered to be in WGS84.from rio_tiler.io import Reader from rio_tiler.models import ImageData with Reader("myfile.tif") as src: # src.part((minx, miny, maxx, maxy), **kwargs) img = src.part((10, 10, 20, 20)) assert isinstance(img, ImageData) assert img.crs == WGS84_CRS assert img.assets == ["myfile.tif"] assert img.bounds == (10, 10, 20, 20) # Pass bbox in WGS84 (default) but return data in the input dataset CRS with Reader("myfile.tif") as src: img = src.part((10, 10, 20, 20), dst_crs=src.dataset.crs) assert img.crs == src.dataset.crs # Limit output size with Reader("myfile.tif") as src: img = src.part((10, 10, 20, 20), max_size=2000) # With indexes with Reader("myfile.tif") as src: img = src.part((10, 10, 20, 20), indexes=1) # With expression with Reader("myfile.tif") as src: img = src.part((10, 10, 20, 20), expression="b1/b2")
-
feature(): Read a raster for a geojson feature. By default the feature is considered to be in WGS84.
from rio_tiler.constants import WGS84_CRS from rio_tiler.io import Reader from rio_tiler.models import ImageData feat = { "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [ [-54.45, 73.05], [-55.05, 72.79], [-55.61, 72.46], [-53.83, 72.36], [-54.45, 73.05], ] ], }, } with Reader("myfile.tif") as src: # src.part(geojson_feature, **kwargs) img = src.feature(feat) assert isinstance(img, ImageData) assert img.crs == WGS84_CRS assert img.assets == ["myfile.tif"] assert img.bounds == (-55.61, 72.36, -53.83, 73.05) # bbox of the input feature # Pass bbox in WGS84 (default) but return data in the input dataset CRS with Reader("myfile.tif") as src: img = src.feature(feat, dst_crs=src.dataset.crs) assert img.crs == src.dataset.crs # Limit output size with Reader("myfile.tif") as src: img = src.feature(feat, max_size=2000) # Read high resolution with Reader("myfile.tif") as src: img = src.feature(feat, max_size=None) # With indexes with Reader("myfile.tif") as src: img = src.feature(feat, indexes=1) # With expression with Reader("myfile.tif") as src: img = src.feature(feat, expression="b1/b2")
-
preview(): Read a preview of a raster
from rio_tiler.io import Reader from rio_tiler.models import ImageData with Reader("myfile.tif") as src: img = src.preview() assert isinstance(img, ImageData) # With indexes with Reader("myfile.tif") as src: img = src.preview(indexes=1) # With expression with Reader("myfile.tif") as src: img = src.preview(expression="b1+2;b1*4")
-
point(): Read the pixel values of a raster for a given
lon, lat
coordinates. By default the coordinates are considered to be in WGS84.from rio_tiler.io import Reader from rio_tiler.models import PointData with Reader("myfile.tif") as src: # src.point(lon, lat) pt = src.point(-100, 25) assert isinstance(pt, PointData) # With indexes with Reader("myfile.tif") as src: pt = src.point(-100, 25, indexes=1) print(pt.data) >>> [1] # With expression with Reader("myfile.tif") as src: pt = src.point(-100, 25, expression="b1+2;b1*4") print(pt.data) >>> [3, 4]
-
info(): Return simple metadata about the dataset
from rio_tiler.io import Reader from rio_tiler.models import Info with Reader("myfile.tif") as src: info = src.info() assert isinstance(info, Info) print(info.model_dump(exclude_none=True)) >>> { "bounds": [373185.0, 8019284.949381611, 639014.9492102272, 8286015.0], "crs": "http://www.opengis.net/def/crs/EPSG/0/32621" "band_metadata": [["b1", {}]], "band_descriptions": [["b1", ""]], "dtype": "int8", "colorinterp": ["palette"], "nodata_type": "Nodata", "colormap": { "0": [0, 0, 0, 0], "1": [0, 61, 0, 255], ... }, "driver": "GTiff", "count": 1, "width": 1000, "height": 2000, "overviews": [2, 4, 8], }
-
statistics(): Return image statistics (Min/Max/Stdev)
from rio_tiler.io import Reader with Reader("myfile.tif") as src: stats = src.statistics() assert isinstance(stats, dict) # stats will be in form or {"band": BandStatistics(), ...} print(stats) >>> { 'b1': BandStatistics(...), 'b2': BandStatistics(...), 'b3': BandStatistics(...) } print(stats["b1"].model_dump()) >>> { "min": 1, "max": 7872, "mean": 2107.524612053134, "count": 1045504, "sum": 2203425412, "std": 2271.0065537857326, "median": 2800, "majority": 1, "minority": 7072, "unique": 15, "histogram": [ [...], [...] ], "valid_percent": 100, "masked_pixels": 0, "valid_pixels": 1045504, "percentile_98": 6896, "percentile_2": 1 } with Reader("myfile_with_colormap.tif") as src: stats = src.statistics(categorical=True, categories=[1, 2]) # we limit the categories to 2 defined value (defaults to all dataset values) assert isinstance(stats, dict) print(stats) >>> { 'b1': BandStatistics(...) } # For categorical data, the histogram will represent the density of EACH value. print(stats["b1"].model_dump()) >>> { ... "histogram": [ [1, 2], [100, 20000] ], ... }
Read Options¶
Reader
accepts several input options which will be forwarded to the rio_tiler.reader.read
function (low level function accessing the data), those options can be set as reader's attribute or within each method calls:
- nodata: Overwrite the nodata value (or set if not present)
- unscale: Apply internal rescaling factors
- vrt_options: Pass WarpedVRT Option (see: gdal.org/api/gdalwarp_cpp.html?highlight=vrt#_CPPv415GDALWarpOptions)
- resampling_method: Set default
resampling_method
- reprojection_method: Set default
reprojection_method
- post_process: Function to apply after the read operations
with Reader("my_cog.tif", options={"nodata": 0}) as src:
src.tile(1, 1, 1)
# is equivalent to
with Reader("my_cog.tif") as src:
src.tile(1, 1, 1, nodata=0)
rio_tiler.io.stac.STACReader¶
In rio-tiler
v2, we added a rio_tiler.io.STACReader
to allow tile/metadata fetching of assets withing a STAC item.
The class is derived from the rio_tiler.io.base.MultiBaseReader
base class which help handling responses from multiple BaseReader
(each asset will be read with a BaseReader
).
from rio_tiler.io import STACReader
STACReader.__mro__
>>> (rio_tiler.io.stac.STACReader,
rio_tiler.io.base.MultiBaseReader,
rio_tiler.io.base.BaseReader,
rio_tiler.io.base.SpatialMixin,
object)
Attributes¶
- input (str): STAC Item path, URL or S3 URL
- item: PySTAC item
- tms (morecantile.TileMatrixSet, optional): morecantile TileMatrixSet used for tile reading (defaults to WebMercator)
- minzoom (int, optional): dataset's minimum zoom level (for input tms)
- maxzoom (int, optional): dataset's maximum zoom level (for input tms)
- include_assets (set, optional): Set of assets to include from the
available
asset list - exclude_assets (set, optional): Set of assets to exclude from the
available
asset list - include_asset_types (set, optional): asset types to consider as valid type for the reader
- exclude_asset_types (set, optional): asset types to consider as invalid type for the reader
- default_assets (sequence, optional): default assets to use for the reader if nothing else is provided.
- reader (BaseReader, optional): Reader to use to read assets (defaults to rio_tiler.io.rasterio.Reader)
- reader_options (dict, optional): Options to forward to the reader init
- fetch_options (dict, optional): Options to pass to the
httpx.get
orboto3
when fetching the STAC item
Properties¶
- assets: Asset list.
- bounds: dataset's bounds (in dataset crs)
- crs: dataset's crs
- transform: dataset's Affine transform (from PROJ extension)
- height: dataset's height (from PROJ extension)
- width: dataset's width (from PROJ extension)
from rio_tiler.io import STACReader
with STACReader(
"https://1tqdbvsut9.execute-api.us-west-2.amazonaws.com/v0/collections/sentinel-s2-l2a-cogs/items/S2A_34SGA_20200318_0_L2A",
exclude_assets={"thumbnail"}
) as stac:
print(stac.input)
print(stac.item)
print(stac.assets)
print(stac.tms.identifier)
print(stac.minzoom)
print(stac.maxzoom)
print(stac.bounds)
print(stac.crs)
>>> https://1tqdbvsut9.execute-api.us-west-2.amazonaws.com/v0/collections/sentinel-s2-l2a-cogs/items/S2A_34SGA_20200318_0_L2A
<Item id=S2A_34SGA_20200318_0_L2A>
['overview', 'visual', 'B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08', 'B8A', 'B09', 'B11', 'B12', 'AOT', 'WVP', 'SCL']
WebMercatorQuad
0
24
[23.293255090449595, 31.505183020453355, 24.296453548295318, 32.51147809805106]
EPSG:4326
Methods¶
The STACReader
has the same methods as the Reader
(defined by the BaseReader/MultiBaseReader classes).
Important
- Most of
STACReader
methods require to set eitherassets=
orexpression=
option. asset_indexes
andasset_expression
are available for all STACReader methods exceptinfo
.
-
tile(): Read map tile from a STAC Item
from rio_tiler.io import STACReader stac_url = "https://1tqdbvsut9.execute-api.us-west-2.amazonaws.com/v0/collections/sentinel-s2-l2a-cogs/items/S2A_34SGA_20200318_0_L2A" # Using `assets=` with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.tile(x, y, z, assets=?, expression=?, asset_expression=?, asset_indexes=?, **kwargs) img = stac.tile( 145, 103, 8, tilesize=256, assets=["B01", "B02"], ) assert img.count == 2 # each assets have one band print(img.assets) >>> [ 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/34/S/GA/2020/3/S2A_34SGA_20200318_0_L2A/B01.tif', 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/34/S/GA/2020/3/S2A_34SGA_20200318_0_L2A/B02.tif', ] print(img.band_names) >>> ['B01_b1', 'B02_b1'] # Using `expression=` with STACReader(stac_url, exclude_assets={"thumbnail"}) as stac: img = stac.tile( 145, 103, 8, tilesize=256, expression="B01_b1/B02_b1", ) assert img.count == 1 # Using `assets=` + `asset_indexes` (select a specific index in an asset) with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: img = stac.tile( 145, 103, 8, tilesize=256, assets=["B01"], asset_indexes={ "B01": (1, 1, 1), # return the first band 3 times } ) assert img.count == 3
-
part(): Read a STAC item for a given bounding box (
bbox
). By default the bbox is considered to be in WGS84.bbox = (23.8, 31.9, 24.1, 32.2) with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.part((minx, miny, maxx, maxy), assets=?, expression=?, asset_expression=?, asset_indexes=?, **kwargs) img = stac.part(bbox, assets=["B01", "B02"], max_size=128) assert img.count == 2 # each assets have one band
-
feature(): Read a STAC item for a geojson feature. By default the feature is considered to be in WGS84.
feat = { "type": "Feature", "geometry": { "coordinates": [ [ [23.8, 32.2], [23.8, 31.9], [24.1, 31.9], [24.1, 32.2], [23.8, 32.2] ] ], "type": "Polygon" } } with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.feature(feature, assets=?, expression=?, asset_expression=?, asset_indexes=?, **kwargs) img = stac.feature(feat, assets=["B01", "B02"], max_size=128) assert img.count == 2 # each assets have one band
-
preview(): Read a preview of STAC Item
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.preview(assets=?, expression=?, asset_expression=?, asset_indexes=?, **kwargs) img = stac.preview(assets=["B01", "B02"], max_size=128) assert img.count == 2 # each assets have one band
-
point(): Read the pixel values for assets for a given
lon, lat
coordinates. By default the coordinates are considered to be in WGS84.with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.point(lon, lat, assets=?, expression=?, asset_expression=?, asset_indexes=?, **kwargs) data = stac.point(24.1, 31.9, assets=["B01", "B02"]) print(data.data) >>> [ 3595, # values for B01 3198 # values for B02 ]
-
info(): Return simple metadata about the assets
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.info(assets=?, **kwargs) info = stac.info(assets=["B01", "B02"]) print(list(info)) >>> ["B01", "B02"] print(info["B01"].json(exclude_none=True)) >>> { "bounds": [373185.0, 8019284.949381611, 639014.9492102272, 8286015.0], "crs": "http://www.opengis.net/def/crs/EPSG/0/32621" "band_metadata": [["b1", {}]], "band_descriptions": [["b1", ""]], "dtype": "uint16", "nodata_type": "Nodata", "colorinterp": ["gray"], "nodata_value": 0.0, "width": 1830, "driver": "GTiff", "height": 1830, "overviews": [2, 4, 8], "count": 1 }
-
statistics(): Return per assets statistics (Min/Max/Stdev)
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac: # stac.statistics(assets=?, asset_expression=?, asset_indexes=?, **kwargs) stats = stac.statistics(assets=["B01", "B02"], max_size=128) # stats will be in form or {"asset": {"band": BandStatistics(), ...}, ...} print(list(stats)) >>> ["B01", "B02"] print(list(stats["B01"])) >>> ["b1"] # B01 has only one band entry "1" print(stats["B01"]["b1"].json(exclude_none=True)) { "min": 283.0, "max": 7734.0, "mean": 1996.959687371452, "count": 12155.0, "sum": 24273045.0, "std": 1218.4455268717047, "median": 1866.0, "majority": 322.0, "minority": 283.0, "unique": 4015.0, "histogram": [ [3257.0, 2410.0, 2804.0, 1877.0, 1050.0, 423.0, 199.0, 93.0, 31.0, 11.0], [283.0, 1028.1, 1773.2, 2518.3, 3263.4, 4008.5, 4753.6, 5498.7, 6243.8, 6988.900000000001, 7734.0] ], "valid_percent": 74.19, "masked_pixels": 4229.0, "valid_pixels": 12155.0, "percentile_2": 326.08000000000004, "percentile_98": 5026.76 }
-
merged_statistics(): Return statistics when merging assets
The merged_statistics
enable the use of expression
to perform assets mixing (e.g "asset1/asset2"
). The main difference with the statistics
method is that we will first use the self.preview
method to obtain a merged array and then calculate the statistics.
```python
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac:
# stac.statistics(assets=?, asset_expression=?, asset_indexes=?, **kwargs)
stats = stac.merged_statistics(assets=["B01", "B02"], max_size=128)
# stats will be in form or {"band": BandStatistics(), ...}
print(list(stats))
>>> ["B01_b1", "B02_b1"]
assert isinstance(stats["B01_b1"], BandStatistics)
print(info["B01_b1"].json(exclude_none=True))
{
"min": 283.0,
"max": 7734.0,
"mean": 1996.959687371452,
"count": 12155.0,
"sum": 24273045.0,
"std": 1218.4455268717047,
"median": 1866.0,
"majority": 322.0,
"minority": 283.0,
"unique": 4015.0,
"histogram": [
[3257.0, 2410.0, 2804.0, 1877.0, 1050.0, 423.0, 199.0, 93.0, 31.0, 11.0],
[283.0, 1028.1, 1773.2, 2518.3, 3263.4, 4008.5, 4753.6, 5498.7, 6243.8, 6988.900000000001, 7734.0]
],
"valid_percent": 74.19,
"masked_pixels": 4229.0,
"valid_pixels": 12155.0,
"percentile_2": 326.08000000000004,
"percentile_98": 5026.76
}
with STACReader(stac_url, exclude_assets={"thumbnail"},) as stac:
# stac.statistics(assets=?, asset_expression=?, asset_indexes=?, **kwargs)
stats = stac.merged_statistics(expression=["B01_b1/B02_b1"], max_size=128)
print(list(stats))
>>> ["B01_b1/B02_b1"]
assert isinstance(stats["B01_b1/B02_b1"], BandStatistics)
```
STAC Expression¶
When using expression
, the user will need to explicitly pass the band number to use within the asset e.g: asset1_b1 + asset2_b2
.
Asset As Band¶
in rio-tiler 4.1.0
, we've added asset_as_band: bool
option to the data methods (tile, feature, part, preview, point) to tell the reader to treat each asset as a dataset band. This is specifically useful for expression
# For expression, without `asset_as_band` tag, users have to pass `_b{n}` suffix to indicate the band index
with STACReader(STAC_PATH) as stac:
img = stac.tile(71, 102, 8, expression="green_b1/red_b1")
assert img.band_names == ["green_b1/red_b1"]
# With `asset_as_band=True`, expression can be the asset names
with STACReader(STAC_PATH) as stac:
img = stac.tile(71, 102, 8, expression="green/red", asset_as_band=True)
assert img.band_names == ["green/red"]
rio_tiler.io.rasterio.ImageReader¶
The Reader
is designed to work with simple raster datasets in their pixel coordinates.
The class is derived from the rio_tiler.io.rasterio.Reader
class.
from rio_tiler.io import ImageReader
ImageReader.__mro__
>>> (rio_tiler.io.rasterio.ImageReader,
rio_tiler.io.rasterio.Reader,
rio_tiler.io.base.BaseReader,
rio_tiler.io.base.SpatialMixin,
object)
Attributes¶
- input (str): filepath
- dataset (rasterio dataset, optional): rasterio opened dataset
- colormap (dict, optional): dataset's colormap
- options (rio_tiler.reader.Options, optional): Options to forward to rio_tiler.reader functions (e.g nodata, vrt_options, resampling)
Properties¶
- bounds: dataset's bounds (in dataset crs)
- transform: dataset Affine transform (in pixel coordinates)
- minzoom: dataset minzoom
- maxzoom: dataset maxzoom
- transform: dataset's Affine transform
- height: dataset's height
- width: dataset's width
from rio_tiler.io import ImageReader
with ImageReader("image.jpg") as src:
print(src.dataset)
print(src.minzoom)
print(src.maxzoom)
print(src.transform)
print(src.bounds)
print(src.colormap)
>> <open DatasetReader name='image.jpeg' mode='r'>
0
3
Affine(1.0, 0.0, 0.0, 0.0, 1.0, 0.0)
(0, 2000, 2000, 0)
{}
Methods¶
-
read(): Read the entire dataset
from rio_tiler.io import ImageReader from rio_tiler.models import ImageData with ImageReader("image.jpeg") as src: img = src.read() assert isinstance(img, ImageData) assert not img.crs assert img.assets == ["image.jpeg"] assert img.width == src.dataset.width assert img.height == src.dataset.height assert img.count == src.dataset.count # With indexes with ImageReader("image.jpeg") as src: img = src.read(indexes=1) # or src.read(indexes=(1,)) assert img.count == 1 assert img.band_names == ["b1"] # With expression with ImageReader("image.jpeg") as src: img = src.read(expression="b1/b2") assert img.count == 1 assert img.band_names == ["b1/b2"]
-
tile(): Read tile from the image
For ImageReader we are using a custom LocalTileMatrixSet
constructed from the dataset width and height. The origin is the Top-Left of the image.
```python
from rio_tiler.io import ImageReader
from rio_tiler.models import ImageData
with ImageReader("image.jpeg") as src:
# src.tile(tile_x, tile_y, tile_z, **kwargs)
img = src.tile(0, 0, src.maxzoom)
assert isinstance(img, ImageData)
assert not img.crs
assert img.bounds == (0, 256, 256, 0)
img = src.tile(0, 0, src.minzoom)
assert isinstance(img, ImageData)
assert img.bounds[0] == 0
assert img.bounds[3] == 0
# With indexes
with ImageReader("image.jpeg") as src:
img = src.tile(1, 2, 3, tilesize=256, indexes=1)
assert img.count == 1
# With expression
with ImageReader("image.jpeg") as src:
img = src.tile(1, 2, 3, tilesize=256, expression="B1/B2")
assert img.count == 1
```
-
part(): Read an image for a given bounding box (
bbox
). The origin is the Top-Left of the image.from rio_tiler.io import ImageReader from rio_tiler.models import ImageData with ImageReader("image.jpeg") as src: # src.part((left, bottom, right, top), **kwargs) img = src.part((0, 256, 256, 0)) # read the top-left 256x256 square of the image assert isinstance(img, ImageData) assert img.assets == ["myfile.tif"] assert img.bounds == (0, 256, 256, 0) # Limit output size with ImageReader("image.jpeg") as src: img = src.part((0, 256, 256, 0), max_size=50) # With indexes with ImageReader("image.jpeg") as src: img = src.part((0, 256, 256, 0), indexes=1) # With expression with ImageReader("image.jpeg") as src: img = src.part((0, 256, 256, 0), expression="b1/b2")
-
feature(): Read an image for a geojson feature. In the pixel coordinate system.
from rio_tiler.io import ImageReader from rio_tiler.models import ImageData feat = { "coordinates": [ [ [-100.0, -100.0], [1000.0, 100.0], [500.0, 1000.0], [-50.0, 500.0], [-100.0, -100.0], ] ], "type": "Polygon", } with ImageReader("image.jpeg") as src: # src.part(geojson_feature, **kwargs) img = src.feature(feat) assert isinstance(img, ImageData) assert img.assets == ["image.jpeg"] assert img.bounds == (-100.0, 1000.0, 1000.0, -100.0) # bbox of the input feature # Limit output size with ImageReader("image.jpeg") as src: img = src.feature(feat, max_size=100) # Read high resolution with ImageReader("image.jpeg") as src: img = src.feature(feat, max_size=None) # With indexes with ImageReader("image.jpeg") as src: img = src.feature(feat, indexes=1) # With expression with ImageReader("image.jpeg") as src: img = src.feature(feat, expression="b1/b2")
-
preview(): Read a preview of a raster
from rio_tiler.io import ImageReader from rio_tiler.models import ImageData with ImageReader("image.jpeg") as src: img = src.preview() assert isinstance(img, ImageData) # With indexes with ImageReader("image.jpeg") as src: img = src.preview(indexes=1) # With expression with ImageReader("image.jpeg") as src: img = src.preview(expression="b1+2;b1*4")
-
point(): Read the pixel values of a raster for a given
x, y
coordinates. The origin is the Top-Left of the image.from rio_tiler.io import ImageReader from rio_tiler.models import PointData with ImageReader("image.jpeg") as src: # src.point(x, y) pt = src.point(0, 0) # pixel at the origin assert isinstance(pt, PointData) # With indexes with ImageReader("image.jpeg") as src: pt = src.point(0,0 , indexes=1) print(pt.data) >>> [1] # With expression with ImageReader("image.jpeg") as src: pt = src.point(0, 0, expression="b1+2;b1*4") print(pt.data) >>> [3, 4]
-
info(): Return simple metadata about the dataset
from rio_tiler.io import ImageReader from rio_tiler.models import Info with ImageReader("image.jpeg") as src: info = src.info() assert isinstance(info, Info) print(info.model_dump(exclude_none=True)) >>> { "bounds": [0, 4000, 4000, 0], "band_metadata": [["b1", {}]], "band_descriptions": [["b1", ""]], "dtype": "int8", "colorinterp": ["palette"], "nodata_type": "Nodata", "colormap": { "0": [0, 0, 0, 0], "1": [0, 61, 0, 255], ... }, "driver": "GTiff", "count": 1, "width": 4000, "height": 4000, "overviews": [2, 4, 8], }
-
statistics(): Return image statistics (Min/Max/Stdev)
from rio_tiler.io import ImageReader with ImageReader("image.jpeg") as src: stats = src.statistics() assert isinstance(stats, dict) # stats will be in form or {"band": BandStatistics(), ...} print(stats) >>> { 'b1': BandStatistics(...), 'b2': BandStatistics(...), 'b3': BandStatistics(...) } print(stats["b1"].model_dump()) >>> { "min": 1, "max": 7872, "mean": 2107.524612053134, "count": 1045504, "sum": 2203425412, "std": 2271.0065537857326, "median": 2800, "majority": 1, "minority": 7072, "unique": 15, "histogram": [ [...], [...] ], "valid_percent": 100, "masked_pixels": 0, "valid_pixels": 1045504, "percentile_98": 6896, "percentile_2": 1 }
rio_tiler.io.xarray.XarrayReader¶
The Reader
is designed to work with xarray.DataReader
with full geo-reference metadata (CRS) and variables (X,Y)
The class is derived from the rio_tiler.io.base.BaseReader
class.
from rio_tiler.io.xarray import XarrayReader
XarrayReader.__mro__
>>> (rio_tiler.io.xarray.XarrayReader,
rio_tiler.io.base.BaseReader,
rio_tiler.io.base.SpatialMixin,
object)
Attributes¶
- input (xarray.DataArray): Xarray DataArray
- tms (morecantile.TileMatrixSet, optional): morecantile TileMatrixSet used for tile reading (defaults to WebMercator)
Properties¶
- bounds: dataset's bounds (in dataset crs)
- crs: dataset's crs
- minzoom: dataset minzoom (in TMS)
- maxzoom: dataset maxzoom (in TMS)
- transform: dataset's Affine transform
- height: dataset's height
- width: dataset's width
- band_names: list of dataArray dims
import numpy
import xarray
from datetime import datetime
from rio_tiler.io.xarray import XarrayReader
arr = numpy.random.randn(1, 33, 35)
data = xarray.DataArray(
arr,
dims=("time", "y", "x"),
coords={
"x": list(range(-170, 180, 10)),
"y": list(range(-80, 85, 5)),
"time": [datetime(2022, 1, 1)],
},
)
data.attrs.update({"valid_min": arr.min(), "valid_max": arr.max()})
data.rio.write_crs("epsg:4326", inplace=True)
with XarrayReader(data) as src:
print(src.input)
print(src.tms.identifier)
print(src.minzoom)
print(src.maxzoom)
print(src.bounds)
print(src.crs)
>> <xarray.DataArray (time: 1, y: 33, x: 35)>
WebMercatorQuad
0
0
(-175.0, -82.5, 175.0, 82.5)
EPSG:4326
Methods¶
-
tile(): Read map tile from a raster
from rio_tiler.constants import WEB_MERCATOR_CRS from rio_tiler.io import XarrayReader from rio_tiler.models import ImageData with XarrayReader(data) as src: # src.tile(tile_x, tile_y, tile_z, tilesize, reproject_method, auto_expand, nodata) img = src.tile(1, 2, 3) assert isinstance(img, ImageData) assert img.crs == WEB_MERCATOR_CRS
-
part(): Read a DataArray for a given bounding box (
bbox
). By default the bbox is considered to be in WGS84.from rio_tiler.io import XarrayReader from rio_tiler.models import ImageData with XarrayReader(data) as src: # src.part((minx, miny, maxx, maxy), dst_crs, bounds_crs, reproject_method, auto_expand, nodata, max_size, height, width, resampling_method) img = src.part((10, 10, 20, 20)) assert isinstance(img, ImageData) assert img.crs == WGS84_CRS assert img.bounds == (10, 10, 20, 20) # Pass bbox in WGS84 (default) but return data in the input dataset CRS with XarrayReader(data) as src: img = src.part((10, 10, 20, 20), dst_crs=src.dataset.crs) assert img.crs == src.dataset.crs
-
feature(): Read a DataArray for a geojson feature. By default the feature is considered to be in WGS84.
from rio_tiler.constants import WGS84_CRS from rio_tiler.io import XarrayReader from rio_tiler.models import ImageData feat = { "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [ [-54.45, 73.05], [-55.05, 72.79], [-55.61, 72.46], [-53.83, 72.36], [-54.45, 73.05], ] ], }, } with XarrayReader(data) as src: # src.part(geojson_feature, dst_crs, shape_crs, auto_expand, nodata, max_size, height, width, resampling_method) img = src.feature(feat) assert isinstance(img, ImageData) assert img.crs == WGS84_CRS assert img.bounds == (-55.61, 72.36, -53.83, 73.05) # bbox of the input feature # Pass bbox in WGS84 (default) but return data in the input dataset CRS with XarrayReader(data) as src: img = src.feature(feat, dst_crs=src.dataset.crs) assert img.crs == src.dataset.crs
-
point(): Read the pixel values of a DataArray for a given
lon, lat
coordinates. By default the coordinates are considered to be in WGS84.from rio_tiler.io import XarrayReader from rio_tiler.models import PointData with XarrayReader(data) as src: # src.point(lon, lat, coord_crs) pt = src.point(-100, 25) assert isinstance(pt, PointData)
-
info(): Return simple metadata about the DataArray
from rio_tiler.io import XarrayReader from rio_tiler.models import Info with XarrayReader(data) as src: info = src.info() assert isinstance(info, Info) print(info.json(exclude_none=True)) >>> { "bounds": [-175.0, -82.5, 175.0, 82.5], "crs": "http://www.opengis.net/def/crs/EPSG/0/4326" "band_metadata": [["b1", {}]], "band_descriptions": [["b1", "2022-01-01T00:00:00.000000000"]], "dtype": "float64", "nodata_type": "None", "width": 35, "attrs": { "valid_min": -3.148671506292848, "valid_max": 4.214148915352746 }, "count": 1, "height": 33 }
-
preview(): Return low-resolution representation of the DataArray
from rio_tiler.io import XarrayReader from rio_tiler.models import ImageData with XarrayReader(data) as src: # src.preview(dst_crs, reproject_method, nodata, max_size, height, width, resampling_method) img = src.preview() assert isinstance(img, ImageData) assert img.crs == data.rio.crs assert img.bounds == data.rio.bounds() with XarrayReader(data) as src: img = src.preview(WGS84_CRS, max_size=100) assert img.crs == WGS84_CRS
Warnings
This method will read the whole DataArray into memory
-
statistics(): Return DataArray statistics (Min/Max/Stdev)
from rio_tiler.io import XarrayReader from rio_tiler.models import ImageData with XarrayReader(data) as src: stats = src.statistics() assert isinstance(stats, dict) # stats will be in form or {"band": BandStatistics(), ...} print(stats) >>> { '2022-01-01T00:00:00.000000000': BandStatistics(...), } print(stats["2022-01-01T00:00:00.000000000"].model_dump()) >>> { "min": 1, "max": 7872, "mean": 2107.524612053134, "count": 1045504, "sum": 2203425412, "std": 2271.0065537857326, "median": 2800, "majority": 1, "minority": 7072, "unique": 15, "histogram": [ [...], [...] ], "valid_percent": 100, "masked_pixels": 0, "valid_pixels": 1045504, "percentile_98": 6896, "percentile_2": 1 }
Warnings
This method will read the whole DataArray into memory