rasterix.raster_index

Module Contents

rasterix.raster_index.assign_index(obj, *, x_dim=None, y_dim=None, crs=True)[source]

Assign a RasterIndex to an Xarray DataArray or Dataset.

By default, the affine transform is guessed by first looking for a GeoTransform attribute on a CF “grid mapping” variable (commonly "spatial_ref"). If not present, then the affine is determined from 1D coordinate variables named x_dim and y_dim provided to this function.

Parameters:
objxarray.DataArray or xarray.Dataset

The object to assign the index to.

x_dimstr, optional

Name of the x dimension. If None, will be automatically detected from Zarr spatial:dimensions convention metadata if present, else from common dimension names and CF attributes.

y_dimstr, optional

Name of the y dimension. If None, will be automatically detected from Zarr spatial:dimensions convention metadata if present, else from common dimension names and CF attributes.

crs: bool, optional

Auto-detect CRS using xproj?

Returns:
xarray.DataArray or xarray.Dataset

The input object with RasterIndex coordinates assigned.

Notes

The “grid mapping” variable is determined following the CF conventions:

  • If a DataArray is provided, we look for an attribute named "grid_mapping".

  • For a Dataset, we pull the first detected "grid_mapping" attribute when iterating over data variables.

The value of this attribute is a variable name containing projection information (commonly "spatial_ref"). We then look for a "GeoTransform" attribute on this variable (following GDAL convention).

References

Examples

>>> import xarray as xr
>>> import rioxarray  # Required for reading TIFF
>>> da = xr.open_dataset("path/to/raster.tif", engine="rasterio")
>>> indexed_da = assign_index(da)
class rasterix.raster_index.RasterIndex(index, crs=None)[source]

Bases: xarray.Index, xproj.ProjIndexMixin

Xarray index for raster coordinate indexing and spatial operations.

RasterIndex provides spatial indexing capabilities for raster data by wrapping one or more Xarray indexes that handle coordinate transformations. It supports both rectilinear and non-rectilinear (rotated/skewed) raster grids.

The internal structure depends on the affine transformation:

  • Non-rectilinear or rotated grids: Uses a single 2D CoordinateTransformIndex for coupled x/y coordinates that handles rotation and skew.

  • Rectilinear grids: Uses separate 1D indexes for independent x/y axes, enabling more efficient slicing operations.

RasterIndex is CRS-aware, i.e., it has a crs property that is used for checking equality or compatibility with other RasterIndex instances. CRS is optional.

Do not use __init__() directly. Instead use from_transform() or assign_index().

Attributes:
bboxBoundingBox

Spatial bounding box of the raster index.

Methods

from_transform

Create RasterIndex from affine transform and dimensions.

transform

Get affine transform for pixel top-left corners.

center_transform

Get affine transform for pixel centers.

Notes

For rectilinear grids without rotation, RasterIndex creates separate 1D indexes for x and y coordinates, which enables efficient slicing operations. For grids with rotation or skew, it uses a coupled 2D transform.

Examples

Create a RasterIndex from an affine transform:

>>> from affine import Affine
>>> transform = Affine(1.0, 0.0, 0.0, 0.0, -1.0, 100.0)
>>> index = RasterIndex.from_transform(transform, width=100, height=100)
>>> print(index.bbox)
BoundingBox(left=0.0, bottom=0.0, right=100.0, top=100.0)
property xy_shape: tuple[int, int][source]

Return the dimension size of the X and Y axis, respectively.

property xy_dims: tuple[str, str][source]

Return the dimension name of the X and Y axis, respectively.

property xy_coord_names: tuple[collections.abc.Hashable, collections.abc.Hashable][source]

Return the name of the coordinate variables representing labels on the X and Y axis, respectively.

classmethod from_transform(affine, *, width, height, x_dim='x', y_dim='y', x_coord_name='xc', y_coord_name='yc', crs=None)[source]

Create a RasterIndex from an affine transform and raster dimensions.

Parameters:
affineaffine.Affine

Affine transformation matrix defining the mapping from pixel coordinates to spatial coordinates. Should represent pixel top-left corners.

widthint

Number of pixels in the x direction.

heightint

Number of pixels in the y direction.

x_dimstr, optional

Name for the x dimension.

y_dimstr, optional

Name for the y dimension.

x_coord_namestr, optional

Name for the x dimension. For non-rectilinear transforms only.

y_coord_namestr, optional

Name for the y dimension. For non-rectilinear transforms only.

crspyproj.crs.CRS or any, optional

The coordinate reference system. Any value accepted by pyproj.crs.CRS.from_user_input().

Returns:
RasterIndex

A new RasterIndex object with appropriate internal structure.

Notes

For rectilinear transforms (no rotation/skew), separate AxisAffineTransformIndex objects are created for x and y coordinates. For non-rectilinear transforms, a single coupled CoordinateTransformIndex is used.

Examples

Create a simple rectilinear index:

>>> from affine import Affine
>>> transform = Affine(1.0, 0.0, 0.0, 0.0, -1.0, 100.0)
>>> index = RasterIndex.from_transform(transform, width=100, height=100)

Create a non-rectilinear index:

>>> index = RasterIndex.from_transform(
...     Affine.rotation(45), width=100, height=100, x_coord_name="x1", y_coord_name="x2"
... )
classmethod from_geotransform(geotransform, *, width, height, x_dim='x', y_dim='y', x_coord_name='xc', y_coord_name='yc', crs=None)[source]

Create a RasterIndex from a GDAL-style GeoTransform.

Parameters:
geotransformsequence of float or str

GDAL GeoTransform as a 6-element sequence (c, a, b, f, d, e) or a space-separated string of 6 numbers. The elements are: - c: x-coordinate of the upper-left corner of the upper-left pixel - a: pixel width (x-direction resolution) - b: row rotation (typically 0) - f: y-coordinate of the upper-left corner of the upper-left pixel - d: column rotation (typically 0) - e: pixel height (y-direction resolution, typically negative)

widthint

Number of pixels in the x direction.

heightint

Number of pixels in the y direction.

x_dimstr, optional

Name for the x dimension.

y_dimstr, optional

Name for the y dimension.

x_coord_namestr, optional

Name for the x coordinate. For non-rectilinear transforms only.

y_coord_namestr, optional

Name for the y coordinate. For non-rectilinear transforms only.

crspyproj.crs.CRS or any, optional

The coordinate reference system. Any value accepted by pyproj.crs.CRS.from_user_input().

Returns:
RasterIndex

A new RasterIndex object with appropriate internal structure.

See also

from_transform

Create from an Affine transform.

as_geotransform

Convert RasterIndex back to GeoTransform string.

References

Examples

Create from a sequence:

>>> geotransform = (323400.0, 30.0, 0.0, 4265400.0, 0.0, -30.0)
>>> index = RasterIndex.from_geotransform(geotransform, width=100, height=100)

Create from a string (as stored in netCDF attributes):

>>> geotransform = "323400.0 30.0 0.0 4265400.0 0.0 -30.0"
>>> index = RasterIndex.from_geotransform(geotransform, width=100, height=100)
classmethod from_tiepoint_and_scale(*, tiepoint, scale, width, height, x_dim='x', y_dim='y', x_coord_name='xc', y_coord_name='yc', crs=None)[source]

Create a RasterIndex from GeoTIFF tiepoint and pixel scale metadata.

Parameters:
tiepointlist or tuple

GeoTIFF model tiepoint in format [I, J, K, X, Y, Z] where (I, J, K) are pixel coords and (X, Y, Z) are world coords.

scalelist or tuple

GeoTIFF model pixel scale in format [ScaleX, ScaleY, ScaleZ].

widthint

Number of pixels in the x direction.

heightint

Number of pixels in the y direction.

x_dimstr, optional

Name for the x dimension.

y_dimstr, optional

Name for the y dimension.

x_coord_namestr, optional

Name for the x coordinate. For non-rectilinear transforms only.

y_coord_namestr, optional

Name for the y coordinate. For non-rectilinear transforms only.

crspyproj.crs.CRS or any, optional

The coordinate reference system. Any value accepted by pyproj.crs.CRS.from_user_input().

Returns:
RasterIndex

A new RasterIndex object with appropriate internal structure.

Raises:
AssertionError

If ScaleZ is not 0 (only 2D rasters are supported).

Examples

Create an index from GeoTIFF metadata:

>>> tiepoint = [0.0, 0.0, 0.0, 323400.0, 4265400.0, 0.0]
>>> scale = [30.0, 30.0, 0.0]
>>> index = RasterIndex.from_tiepoint_and_scale(tiepoint=tiepoint, scale=scale, width=100, height=100)
classmethod from_stac_proj_metadata(metadata, *, width, height, x_dim='x', y_dim='y', x_coord_name='xc', y_coord_name='yc', crs=None)[source]

Create a RasterIndex from STAC projection metadata.

Parameters:
metadatadict

Dictionary containing STAC metadata. Must contain a ‘proj:transform’ key with the affine transformation as a flat array.

widthint

Number of pixels in the x direction.

heightint

Number of pixels in the y direction.

x_dimstr, optional

Name for the x dimension.

y_dimstr, optional

Name for the y dimension.

x_coord_namestr, optional

Name for the x coordinate. For non-rectilinear transforms only.

y_coord_namestr, optional

Name for the y coordinate. For non-rectilinear transforms only.

crspyproj.crs.CRS or any, optional

The coordinate reference system. Any value accepted by pyproj.crs.CRS.from_user_input().

Returns:
RasterIndex

A new RasterIndex object with appropriate internal structure.

Raises:
ValueError

If ‘proj:transform’ is not found in metadata or has invalid format.

Examples

Create an index from STAC metadata:

>>> metadata = {"proj:transform": [30.0, 0.0, 323400.0, 0.0, 30.0, 4268400.0]}
>>> index = RasterIndex.from_stac_proj_metadata(metadata, width=100, height=100)
classmethod from_variables(variables, *, options)[source]
Abstractmethod:

Create a new index object from one or more coordinate variables.

This factory method must be implemented in all subclasses of Index.

The coordinate variables may be passed here in an arbitrary number and order and each with arbitrary dimensions. It is the responsibility of the index to check the consistency and validity of these coordinates.

Parameters:
variablesdict-like

Mapping of Variable objects holding the coordinate labels to index.

optionsdict-like

Keyword arguments passed to this constructor. Propagated from the **options argument of xarray.DataArray.set_xindex() or xarray.Dataset.set_xindex().

Returns:
indexIndex

A new Index object.

create_variables(variables=None)[source]

Maybe create new coordinate variables from this index.

This method is useful if the index data can be reused as coordinate variable data. It is often the case when the underlying index structure has an array-like interface, like pandas.Index objects.

The variables given as argument (if any) are either returned as-is (default behavior) or can be used to copy their metadata (attributes and encoding) into the new returned coordinate variables.

Note: the input variables may or may not have been filtered for this index.

Parameters:
variablesdict-like, optional

Mapping of Variable objects.

Returns:
index_variablesdict-like

Dictionary of Variable or IndexVariable objects.

property crs: pyproj.CRS | None[source]

Returns the coordinate reference system (CRS) of the index as a pyproj.crs.CRS object, or None if CRS is undefined.

isel(indexers)[source]

Maybe returns a new index from the current index itself indexed by positional indexers.

This method should be re-implemented in subclasses of Index if the wrapped index structure supports indexing operations. For example, indexing a pandas.Index is pretty straightforward as it behaves very much like an array. By contrast, it may be harder doing so for a structure like a kd-tree that differs much from a simple array.

If not re-implemented in subclasses of Index, this method returns None, i.e., calling Dataset.isel() will either drop the index in the resulting dataset or pass it unchanged if its corresponding coordinate(s) are not indexed.

Parameters:
indexersdict

A dictionary of positional indexers as passed from Dataset.isel() and where the entries have been filtered for the current index.

Returns:
maybe_indexIndex

A new Index object or None.

sel(labels, method=None, tolerance=None)[source]

Query the index with arbitrary coordinate label indexers.

Implementation is optional but required in order to support label-based selection. Otherwise it will raise an error when trying to call Dataset.sel() with labels for this index coordinates.

Coordinate label indexers can be of many kinds, e.g., scalar, list, tuple, array-like, slice, Variable, DataArray, etc. It is the responsibility of the index to handle those indexers properly.

Parameters:
labelsdict

A dictionary of coordinate label indexers passed from Dataset.sel() and where the entries have been filtered for the current index.

Returns:
sel_resultsIndexSelResult

An index query result object that contains dimension positional indexers. It may also contain new indexes, coordinate variables, etc.

equals(other, *, exclude=None)[source]

Compare this index with another index of the same type.

Implementation is optional but required in order to support alignment.

Parameters:
otherIndex

The other Index object to compare with this object.

excludefrozenset of hashable, optional

Dimensions excluded from checking. It is None by default, (i.e., when this method is not called in the context of alignment). For a n-dimensional index this option allows an Index to optionally ignore any dimension in exclude when comparing self with other. For a 1-dimensional index this kwarg can be safely ignored, as this method is not called when all of the index’s dimensions are also excluded from alignment (note: the index’s dimensions correspond to the union of the dimensions of all coordinate variables associated with this index).

Returns:
is_equalbool

True if the indexes are equal, False otherwise.

transform()[source]

Affine transform for top-left corners.

as_geotransform(*, decimals=None)[source]

Convert the affine transform to a string suitable for saving as the GeoTransform attribute.

center_transform()[source]

Affine transform for cell centers.

property bbox: rasterix.odc_compat.BoundingBox[source]

Bounding Box for index.

Returns:
BoundingBox
classmethod concat(indexes, dim, positions=None)[source]

Create a new index by concatenating one or more indexes of the same type.

Implementation is optional but required in order to support concat. Otherwise it will raise an error if the index needs to be updated during the operation.

Parameters:
indexessequence of Index objects

Indexes objects to concatenate together. All objects must be of the same type.

dimHashable

Name of the dimension to concatenate along.

positionsNone or list of integer arrays, optional

List of integer arrays which specifies the integer positions to which to assign each dataset along the concatenated dimension. If not supplied, objects are concatenated in the provided order.

Returns:
indexIndex

A new Index object.

join(other, how='inner')[source]

Join two RasterIndexes by computing the union or intersection of their bounding boxes.

Transform compatibility is checked using the tolerance configured via rasterix.set_options() (transform_rtol and transform_atol).

reindex_like(other, method=None, tolerance=None)[source]

Query the index with another index of the same type.

Implementation is optional but required in order to support alignment.

Parameters:
otherIndex

The other Index object used to query this index.

Returns:
dim_positional_indexersdict

A dictionary where keys are dimension names and values are positional indexers.

__repr__()[source]