Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/_static/style.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.sidebar-log {
max-width: 70%;
.sidebar-logo {
max-width: 50%;
}

.xr-wrap {
Expand Down
148 changes: 0 additions & 148 deletions docs/heuristics.md

This file was deleted.

2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ caption: Raster Index
hidden:
---
raster_index/intro
raster_index/creating
raster_index/indexing
raster_index/crs
raster_index/aligning
raster_index/combining
raster_index/tolerance
raster_index/design_choices
raster_index/heuristics
```

```{toctree}
Expand Down
2 changes: 1 addition & 1 deletion docs/raster_index/aligning.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kernelspec:
---

```{eval-rst}
.. currentmodule:: rasterix
.. currentmodule:: rasterix.raster_index
```

```{code-cell} python
Expand Down
2 changes: 1 addition & 1 deletion docs/raster_index/combining.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kernelspec:
---

```{eval-rst}
.. currentmodule:: rasterix
.. currentmodule:: rasterix.raster_index
```

```{code-cell} python
Expand Down
185 changes: 185 additions & 0 deletions docs/raster_index/creating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
---
jupytext:
text_representation:
format_name: myst
kernelspec:
display_name: Python 3
name: python
---

```{eval-rst}
.. currentmodule:: rasterix.raster_index
```

```{code-cell} python
---
tags: [remove-cell]
---
%xmode minimal
import xarray as xr
xr.set_options(display_expand_indexes=True);
```

# Creating

There are several ways to create a {py:class}`RasterIndex`, depending on the source of your data and the metadata conventions it uses.

```{code-cell}
import numpy as np
import xarray as xr
import rasterix
```

## Using `assign_index`

The easiest way to create a RasterIndex is using {py:func}`assign_index`. This function automatically detects the affine transform from various metadata conventions, including:

- [GDAL GeoTransform](https://gdal.org/en/stable/tutorials/geotransforms_tut.html) (from rioxarray/GeoTIFF files)
- [GeoTIFF](https://docs.ogc.org/is/19-008r4/19-008r4.html) tiepoint and pixel scale attributes
- [STAC projection extension](https://github.com/stac-extensions/projection) `proj:transform` metadata
- [Zarr Spatial Convention](https://zarr-specs.readthedocs.io/en/latest/v3/conventions/spatial/v1.0.html) (`spatial:transform`)
- 1D coordinate arrays (common in NetCDF files)

See {doc}`/raster_index/heuristics` for the full priority order and detection logic.

```{code-cell}
import pyproj

# Example: dataset with GDAL-style GeoTransform metadata
ds = xr.Dataset(
{"temperature": (("y", "x"), np.random.rand(100, 100))},
coords={
"spatial_ref": (
(),
0,
pyproj.CRS.from_epsg(32610).to_cf() | {"GeoTransform": "400000.0 10.0 0.0 5000000.0 0.0 -10.0"},
)
},
attrs={"grid_mapping": "spatial_ref"},
)

# assign_index auto-detects the convention and creates the RasterIndex
ds = rasterix.assign_index(ds)
ds
```

## Direct construction with class methods

For more control, you can create a {py:class}`RasterIndex` directly using class methods. This is useful when you have the transform parameters available directly, or when working with data that doesn't have embedded metadata.

### From an Affine transform

Use {py:meth}`RasterIndex.from_transform` to create from an [Affine](https://github.com/rasterio/affine) transform directly (corresponds to [GDAL GeoTransform](https://gdal.org/en/stable/tutorials/geotransforms_tut.html) convention):

```{code-cell}
from affine import Affine

transform = Affine(10.0, 0.0, 400000.0, 0.0, -10.0, 5000000.0)
index = rasterix.RasterIndex.from_transform(
transform,
width=100,
height=100,
crs="EPSG:32610",
)
index
```

```{code-cell}
# Assign to data
ds_manual = xr.Dataset(
{"data": (("y", "x"), np.random.rand(100, 100))},
coords=xr.Coordinates.from_xindex(index),
)
ds_manual
```

### From a GeoTransform

Use {py:meth}`RasterIndex.from_geotransform` to create from a [GDAL GeoTransform](https://gdal.org/en/stable/tutorials/geotransforms_tut.html), either as a sequence or a space-separated string:

```{code-cell}
# From a tuple
geotransform = (400000.0, 10.0, 0.0, 5000000.0, 0.0, -10.0)
index = rasterix.RasterIndex.from_geotransform(
geotransform,
width=100,
height=100,
crs="EPSG:32610",
)
index
```

```{code-cell}
# From a string (as commonly stored in netCDF attributes)
geotransform = "400000.0 10.0 0.0 5000000.0 0.0 -10.0"
index = rasterix.RasterIndex.from_geotransform(
geotransform,
width=100,
height=100,
crs="EPSG:32610",
)
index
```

### From GeoTIFF tiepoint and scale

Use {py:meth}`RasterIndex.from_tiepoint_and_scale` to create from [GeoTIFF](https://docs.ogc.org/is/19-008r4/19-008r4.html)-style tiepoint and pixel scale attributes:

```{code-cell}
index = rasterix.RasterIndex.from_tiepoint_and_scale(
tiepoint=[0.0, 0.0, 0.0, 323400.0, 4265400.0, 0.0],
scale=[30.0, 30.0, 0.0],
width=100,
height=100,
crs="EPSG:32610",
)
index
```

### From STAC projection metadata

Use {py:meth}`RasterIndex.from_stac_proj_metadata` to create from [STAC projection extension](https://github.com/stac-extensions/projection) metadata:

```{code-cell}
metadata = {"proj:transform": [30.0, 0.0, 323400.0, 0.0, -30.0, 4268400.0]}
index = rasterix.RasterIndex.from_stac_proj_metadata(
metadata,
width=100,
height=100,
crs="EPSG:32610",
)
index
```

## Accessing transform information

Once created, you can access the affine transform using methods on {py:class}`RasterIndex`:

```{code-cell}
ds = rasterix.assign_index(
xr.Dataset(
{"data": (("y", "x"), np.random.rand(100, 100))},
coords={
"spatial_ref": ((), 0, {"GeoTransform": "400000.0 10.0 0.0 5000000.0 0.0 -10.0"}),
},
)
)

# Top-left corner transform (GDAL convention) via transform()
ds.xindexes["x"].transform()
```

```{code-cell}
# Pixel center transform via center_transform()
ds.xindexes["x"].center_transform()
```

```{code-cell}
# Bounding box via the bbox property
ds.xindexes["x"].bbox
```

```{code-cell}
# As GeoTransform string (for saving) via as_geotransform()
ds.xindexes["x"].as_geotransform()
```
4 changes: 2 additions & 2 deletions docs/raster_index/design_choices.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
```{eval-rst}
.. currentmodule:: rasterix
.. currentmodule:: rasterix.raster_index
```

# Design Choices
Expand Down Expand Up @@ -55,7 +55,7 @@ GDAL _chooses_ to track the affine transform using a `GeoTransform` attribute on
the grid mapping variable. Thus, {py:class}`RasterIndex` _cannot_ keep the `"GeoTransform"` attribute on `"spatial_ref"` up-to-date
because it does not control it.

Thus, {py:func}`assign_index` will delete the `"GeoTransform"` attribute on the grid mapping variable if it is detected, after using it
Thus, {py:func}`~rasterix.assign_index` will delete the `"GeoTransform"` attribute on the grid mapping variable if it is detected, after using it
to construct the affine matrix.

If you wish to extract the GeoTransform attribute to write it to a location of your choosing use {py:meth}`RasterIndex.as_geotransform`.
Expand Down
Loading
Loading