# Overview: the chain layer and its relation to the core API GridR exposes two layers for grid resampling: - **Core layer** -- `array_grid_resampling` (and the standalone preprocessing helper) works on in-memory NumPy arrays. The caller owns the buffers and pays the cost of holding everything in RAM. - **Chain layer** -- `basic_grid_resampling_chain` works on rasterio datasets opened from disk. It iterates over output strips and tiles, reading and writing only what is needed at each step. This notebook clarifies which core features are also available through the chain layer, how the chain reuses core code internally, and how to map each core argument to its chain counterpart. **What you'll learn** - The conceptual difference between *core* and *chain* layers - Why `standalone` does not exist in the chain layer - How masking strategies are shared between the two layers - A complete `core kwarg ↔ chain kwarg` correspondence table ## The chain layer wraps the core layer `basic_grid_resampling_chain` does **not** reimplement resampling. For each tile of its output strip loop, it eventually calls `array_grid_resampling` with the relevant slice of input data and the relevant slice of the grid. The chain layer is responsible for: - Splitting the output into strips and tiles (`io_strip_size`, `tile_shape`). - Computing the minimal source-raster read window for each tile (`array_compute_resampling_grid_geometries`). - Reading the input raster, grid and masks from disk through rasterio. - Merging the source raster mask with the rasterized geometry masks into a single validity mask suitable for the core layer. - Forwarding all interpolation-related parameters (`interp`, `nodata_out`, `boundary_condition`, `trust_padding`, ...) directly to the core call. - Writing the resampled output (and optional mask) back to disk. > **Note** -- The masking strategy code is shared between the two> layers. Whether you call `array_grid_resampling` in standalone mode> or `basic_grid_resampling_chain`, the same module decides how each> mask propagates through the interpolator and to the output mask;> only the *application context* differs (a single in-memory call vs.> a per-tile chain call). Consequently, every masking feature> documented in the core tutorials (input mask, grid mask, output> mask) behaves identically through the chain. ## Why `standalone` is not a chain argument At the core layer, `standalone=True` instructs `array_grid_resampling` to perform on-the-fly preprocessing (boundary extension, padding for the interpolator support, mask consolidation) before resampling. `standalone=False` skips this step and expects the caller to have provided a pre-padded source array. The chain layer's whole purpose is to provide a turnkey, file-to-file resampling: it always perform the preprocessing itself and calls the underlying core with standalone mode turned off. There is therefore no `standalone` argument on the chain side. ## Core `↔` Chain argument correspondence The table below maps every relevant core argument to its chain counterpart. Arguments marked *forwarded* are passed verbatim from the chain to the core layer for each tile call. Arguments marked *chain-only* govern the chain's I/O loop and have no equivalent in the core API. ### Resampling parameters | Core kwarg | Chain kwarg | Notes | |---|---|---| | `interp` | `interp` | Chain always initialize the interpolator object. | | `grid_resolution` | `grid_resolution` | Forwarded as-is. | | `nodata_out` | `nodata_out` | Forwarded as-is. | | `boundary_condition` | `boundary_condition` | Forwarded as-is. | | `trust_padding` | `trust_padding` | Forwarded as-is. | | `standalone` | *(none)* | Chain always behaves as standalone; see above. | | `array_in_origin` | *(none, managed internally)* | Set per tile by the chain to account for the tile's origin within the source raster. | | `win` | `win` | Forwarded as-is; expressed in full-resolution output coordinates. | | `grid_shift` *(N/A)* | `grid_shift` | Chain-only; offset applied to grid coordinates before any geometry computation. | ### Input source data | Core kwarg | Chain kwarg | Notes | |---|---|---| | `array_in` (NumPy) | `array_src_ds` + `array_src_bands` | The chain reads the relevant tile from disk and forwards it. | | `grid_row`, `grid_col` (NumPy) | `grid_ds` + `grid_row_coords_band` + `grid_col_coords_band` (or separate `grid_col_ds`) | Same idea; the chain reads the grid coordinates from disk. | ### Masks | Core kwarg | Chain kwarg | Notes | |---|---|---| | `array_in_mask` (NumPy) | `array_src_mask_ds` + `array_src_mask_band` + `array_src_mask_validity_pair` | Source raster mask; the chain reads the relevant tile of the mask and forwards it. | | *(N/A)* | `array_src_geometry_pair` + `array_src_geometry_origin` | Chain-only; rasterized at tile level and merged with the source raster mask before forwarding to the core. | | `grid_mask` (NumPy) | `grid_mask_in_ds` + `grid_mask_in_band` + `grid_mask_in_unmasked_value` | Grid validity mask; forwarded after rebinarisation to the GridR `1/0` convention. | ### Outputs | Core kwarg | Chain kwarg | Notes | |---|---|---| | return: `array_out` | `array_out_ds` | The chain writes each tile back to disk in place of allocating a return buffer. | | return: `mask_out` | `mask_out_ds` | Optional. Same per-tile write pattern. | ### Chain-only: I/O loop | Chain kwarg | Purpose | |---|---| | `io_strip_size` | Maximum strip height (in output rows by default). `0` disables stripping. | | `io_strip_size_target` | Whether `io_strip_size` is interpreted as output rows (`GridRIOMode.OUTPUT`) or input grid rows (`GridRIOMode.INPUT`). | | `tile_shape` | Sub-divide each strip into `(nrows, ncols)` tiles for the core calls. `None` disables tiling. | | `logger` | Optional `logging.Logger` for debug tracing of the strip / tile loop. | ## What this means in practice If you have already mastered the *core* tutorial series, switching to the chain layer for a production-scale, file-oriented workflow only requires: 1. Replacing NumPy buffer arguments by their rasterio dataset equivalents (per the table above). 2. Adding the chain-only I/O parameters that match your memory budget (`io_strip_size`, `tile_shape`). 3. Optionally taking advantage of chain-only conveniences such as geometry masks and `grid_shift`. Every other parameter you know from the core API still applies, with the same meaning and the same defaults.