Source code for eodal.core.utils.raster
"""
Raster utilities to extract raster band attributes
Copyright (C) 2022 Lukas Valentin Graf
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import math
import numpy as np
import rasterio as rio
from rasterio import Affine
from typing import Any, Dict, Tuple
[docs]
def get_raster_attributes(riods: rio.io.DatasetReader) -> Dict[str, Any]:
"""
extracts immutable raster attributes (not changed by reprojections,
resampling) and returns them as a dictionary.
Code taken from
https://github.com/pydata/xarray/blob/960010b00119367ff6b82e548f2b54ca25c7a59c/xarray/backends/rasterio_.py#L359
:param riods:
opened ``rasterio`` data set reader
:returns:
dictionary with extracted raster attributes (attrs)
"""
attrs = {}
if hasattr(riods, "is_tiled"):
# Is the TIF tiled? (bool)
# We cast it to an int for netCDF compatibility
attrs["is_tiled"] = np.uint8(riods.is_tiled)
if hasattr(riods, "nodatavals"):
# The nodata values for the raster bands
attrs["nodatavals"] = tuple(
np.nan if nodataval is None else nodataval for nodataval in riods.nodatavals
)
if hasattr(riods, "scales"):
# The scale values for the raster bands
attrs["scales"] = riods.scales
if hasattr(riods, "offsets"):
# The offset values for the raster bands
attrs["offsets"] = riods.offsets
if hasattr(riods, "descriptions") and any(riods.descriptions):
# Descriptions for each dataset band
attrs["descriptions"] = riods.descriptions
if hasattr(riods, "units") and any(riods.units):
# A list of units string for each dataset band
attrs["units"] = riods.units
return attrs
[docs]
def spatial_to_image_coordinates(
x: float, y: float, affine: Affine, op=math.floor
) -> Tuple[int, int]:
"""
Convert spatial x and y coordinat to image coordinates (row + column)
.. versionadded:: 0.1.1
taken from:
`rasterstats` package under BSD 3-Clause "New" or "Revised" License
Copyright (c) 2013 Matthew Perry
https://github.com/perrygeo/python-rasterstats/blob/d05f0dbda82c7a54fbb99d893af6e3182c225005/src/rasterstats/io.py#L137
"""
r = int(op((y - affine.f) / affine.e))
c = int(op((x - affine.c) / affine.a))
return r, c
[docs]
def bounds_window(
bounds: Tuple[float, float, float, float], affine: Affine
) -> Tuple[Tuple[int, int], Tuple[int, int]]:
"""
Create a full cover rasterio-style window
.. versionadded:: 0.1.1
taken from:
`rasterstats` package under BSD 3-Clause "New" or "Revised" License
Copyright (c) 2013 Matthew Perry
https://github.com/perrygeo/python-rasterstats/blob/d05f0dbda82c7a54fbb99d893af6e3182c225005/src/rasterstats/io.py#L145
"""
w, s, e, n = bounds
row_start, col_start = spatial_to_image_coordinates(w, n, affine)
row_stop, col_stop = spatial_to_image_coordinates(e, s, affine, op=math.ceil)
return row_start, row_stop, col_start, col_stop