Getting started with the GridR resampling chain

This tutorial introduces basic_grid_resampling_chain, the file-oriented wrapper around array_grid_resampling. The core function works on in-memory NumPy arrays; the chain layer manages all I/O against rasterio datasets and processes the output in memory-efficient strips and tiles.

This first notebook shows the minimal call: open a source raster, open a grid file, open a destination file, and let the chain do the rest.

What you’ll learn

  • How to prepare on-disk inputs for the chain (raster + grid)

  • How to open input/output rasterio datasets in a with block

  • How to call basic_grid_resampling_chain with minimal arguments

  • How grid_resolution controls the output size

Setting things up

The chain reads from rasterio DatasetReader and writes to DatasetWriter objects opened by the caller. Before calling it we need:

  1. A source raster on disk – here, the mandrill image.

  2. A grid file on disk – a two-band GeoTIFF where band 1 holds row coordinates and band 2 holds column coordinates.

Both files are created above by the tutorial setup cell using the write_array and create_grid helpers from chain_notebook_utils.

The grid is an affine-parameterised regular grid of shape (50, 40) mapped onto the source raster’s coordinate frame. The figure below overlays its nodes on the source image.

grid_on_image.png

First call: identity resolution

At grid_resolution=(1, 1) the output has exactly as many pixels as there are grid nodes (50 × 40). The output dataset must be opened with matching dimensions.

output_shape_1_1 = grid_row_f64.shape

raster_out_open_args_1_1 = {
    "driver": "GTiff", "dtype": np.float64,
    "height": output_shape_1_1[0], "width": output_shape_1_1[1], "count": 1,
}

with rasterio.open(GRID_IN_F64, "r") as grid_in_ds, \
        rasterio.open(RASTER_IN, "r") as array_src_ds, \
        rasterio.open(output_raster_path, "w", **raster_out_open_args_1_1) as array_out_ds:

    basic_grid_resampling_chain(
        grid_ds              = grid_in_ds,
        grid_row_coords_band = 1,
        grid_col_coords_band = 2,
        grid_resolution      = (1, 1),
        array_src_ds         = array_src_ds,
        array_src_bands      = 1,
        array_out_ds         = array_out_ds,
        interp               = "cubic",
        nodata_out           = 0,
    )

resampling_1_1.png

The output is small because the grid subsamples the source raster heavily (each node is several source pixels apart). Out-of-domain nodes are filled with nodata_out.

Zooming with grid_resolution

grid_resolution inserts additional output samples between adjacent grid nodes by bilinear interpolation of the node coordinates. Setting it to (8, 8) multiplies the output dimensions by 8 in each direction. The output shape must be sized accordingly using grid_full_resolution_shape.

from gridr.core.grid.grid_commons import grid_full_resolution_shape

grid_resolution = (8, 8)

output_shape = grid_full_resolution_shape(
    shape=grid_row_f64.shape, resolution=grid_resolution,
)

raster_out_open_args = {
    "driver": "GTiff", "dtype": np.float64,
    "height": output_shape[0], "width": output_shape[1], "count": 1,
}
print(f"output shape: {output_shape}")
output shape: (393, 313)
with rasterio.open(GRID_IN_F64, "r") as grid_in_ds, \
        rasterio.open(RASTER_IN, "r") as array_src_ds, \
        rasterio.open(output_raster_path, "w", **raster_out_open_args) as array_out_ds:

    basic_grid_resampling_chain(
        grid_ds              = grid_in_ds,
        grid_row_coords_band = 1,
        grid_col_coords_band = 2,
        grid_resolution      = grid_resolution,
        array_src_ds         = array_src_ds,
        array_src_bands      = 1,
        array_out_ds         = array_out_ds,
        interp               = "cubic",
        nodata_out           = 0,
    )

resampling_8_8.png

The next notebooks build on this minimal call by adding masks, geometry constraints, coordinate shifts and I/O controls one at a time.