Slices Module¶
The georeader.slices module provides utilities for dividing large raster datasets
into smaller tiles (chips/windows) for batch processing, machine learning inference,
and memory-efficient workflows.
Overview¶
When working with large satellite images that don't fit in memory, or when running ML models that require fixed-size inputs, you need to tile the data into smaller chunks. This module handles the complexity of:
- Generating tile coordinates without loading data
- Overlap handling for seamless predictions
- Edge cases at image boundaries
- Multi-dimensional support (time, bands, spatial)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TILING WORKFLOW OVERVIEW β
β β
β Large Raster (10000 Γ 10000) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β βββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββ β β
β β β 1 β 2 β 3 β 4 β 5 β 6 β 7 β 8 β β β
β β βββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββ€ β β
β β β 9 β 10 β 11 β 12 β 13 β 14 β 15 β16 β β β
β β βββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββ€ β β
β β β 17 β 18 β ... β β β β β β β β
β β βββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββ€ β β
β β β β β β β β β β β β tiles = β
β β βββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββ β create_ β
β β β windows() β
β β Each tile: 256 Γ 256 pixels β β
β β Edge tiles may be smaller (trim_incomplete=True) β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Process each tile independently β combine results β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Functions¶
create_windows¶
Generates a list of rasterio.windows.Window objects for tiling a raster:
from georeader.slices import create_windows
# Create 256Γ256 tiles with 32px overlap
windows = create_windows(
geodata_shape=(4000, 5600), # (height, width)
window_size=(256, 256), # (height, width)
overlap=(32, 32), # (row_overlap, col_overlap)
include_incomplete=True, # Include edge tiles
trim_incomplete=True # Edge tiles have actual size, not padded
)
print(f"Created {len(windows)} tiles")
# Each window has: window.row_off, window.col_off, window.height, window.width
create_slices¶
Lower-level function using dictionaries for named dimensions:
from georeader.slices import create_slices
# For multi-dimensional data (e.g., time series)
named_shape = {"time": 12, "y": 4000, "x": 5600}
dims = {"y": 256, "x": 256}
overlap = {"y": 32, "x": 32}
slices = create_slices(named_shape, dims, overlap=overlap)
# Returns: [{"y": slice(0, 256), "x": slice(0, 256)}, ...]
Overlap Strategies¶
Overlap is crucial for ML inference to avoid edge artifacts:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OVERLAP HANDLING β
β β
β Without Overlap (artifacts at tile edges) β
β ββββββββββ¬βββββββββ¬βββββββββ β
β β β β β Each tile processed independently β
β β Tile β Tile β Tile β β visible seams in output β
β β 1 β 2 β 3 β β
β ββββββββββ΄βββββββββ΄βββββββββ β
β β β β
β seams seams β
β β
β With Overlap (seamless predictions) β
β ββββββββββββββββββββββββββββ β
β β ββββββββ β Tiles overlap by N pixels β
β β Tile βOverlapβ Tile β β blend or crop overlap region β
β β 1 βRegion β 2 β β seamless output β
β β ββββββββ β β
β ββββββββββββββββββββββββββββ β
β ββ overlap ββ β
β β
β Overlap = kernel_size / 2 is a good rule of thumb for CNNs β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Typical Overlap Values¶
| Model Type | Recommended Overlap | Reason |
|---|---|---|
| Simple CNN | 16-32 px | Receptive field edge effects |
| U-Net | 32-64 px | Multi-scale features |
| Vision Transformer | patch_size / 2 | Patch boundary artifacts |
| Segmentation | class_boundary_width | Smooth boundaries |
Examples¶
For complete examples of using tiling for ML inference workflows, including handling edge cases and stitching predictions, see the Tiling and Stitching tutorial.
Handling Edge Cases¶
Incomplete Tiles at Edges¶
# Option 1: Include smaller edge tiles (default)
windows = create_windows(shape, tile_size,
include_incomplete=True,
trim_incomplete=True)
# Edge tiles have actual size: 256Γ200 for a 200px remainder
# Option 2: Pad edge tiles to full size
windows = create_windows(shape, tile_size,
include_incomplete=True,
trim_incomplete=False)
# Edge tiles request 256Γ256 even if image is smaller β needs padding
# Option 3: Exclude edge tiles entirely
windows = create_windows(shape, tile_size,
include_incomplete=False)
# Only tiles that fit completely are included
Negative Offsets for Symmetric Padding¶
# For predictions where you want overlap on ALL edges (including first/last tile)
windows = create_windows(shape, tile_size,
overlap=(64, 64),
start_negative_if_padding=True)
# First window starts at row=-32, col=-32
# Requires handling out-of-bounds reads with padding
Performance Considerations¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PERFORMANCE TRADEOFFS β
β β
β Tile Size vs Overhead β
β β
β Small tiles (64Γ64) Large tiles (512Γ512) β
β βββββββββββββββββββ βββββββββββββββββββββ β
β β Low memory per tile β Less overhead per tile β
β β Many tiles = overhead β Better GPU utilization β
β β More edge artifacts β Higher memory requirement β
β β
β Overlap Impact β
β ββββββββββββββ β
β Small overlap (16px) Large overlap (128px) β
β βββββββββββββββββββ βββββββββββββββββββββ β
β β Fewer total tiles β Cleaner predictions β
β β Possible edge artifacts β Significant overhead β
β β
β Rule of thumb: β
β - tile_size = 256-512 for most GPU workflows β
β - overlap = 10-20% of tile_size β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
API Reference¶
georeader.slices
¶
Slices Module: Generate windows for tiled/chunked raster processing.
This module provides utilities to divide large rasters into overlapping or non-overlapping tiles (slices) for memory-efficient processing. Essential for processing datasets that don't fit in memory.
Tiling Strategies¶
Choosing the right tiling approach for your use case::
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TILING STRATEGIES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Non-overlapping (overlap=0) Overlapping (overlap>0) β
β βββββββββββββββββββββββββ ββββββββββββββββββββββ β
β β
β ββββββ¬βββββ¬βββββ¬βββββ ββββββ¬βββββ¬βββββ¬βββββ β
β β 1 β 2 β 3 β 4 β β 1 ββΌβ 2 βΌβ 3 βΌβ 4 β β
β ββββββΌβββββΌβββββΌβββββ€ βββββ¬βΌββββ¬βΌββββ¬βΌββββ¬β€ β
β β 5 β 6 β 7 β 8 β β 5 ββ 6 ββ 7 ββ 8 ββ β
β ββββββΌβββββΌβββββΌβββββ€ βββββΌβΌββββΌβΌββββΌβΌββββΌβ€ β
β β 9 β 10 β 11 β 12 β β 9 ββ10 ββ11 ββ12 ββ β
β ββββββ΄βββββ΄βββββ΄βββββ βββββ΄β΄ββββ΄β΄ββββ΄β΄ββββ΄β β
β ββ overlap region β
β Best for: Best for: β
β β’ Independent tiles β’ Edge-sensitive algorithms β
β β’ Aggregation tasks β’ Convolutions/filters β
β β’ Simple mosaicking β’ Seamline blending β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Slice Coordinates vs Windows¶
Understanding the relationship between slices and windows::
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SLICES (Python) vs WINDOWS (Rasterio) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β slice(start, stop) Window(col_off, row_off, width, height)β
β ββββββββββββββββββ βββββββββββββββββββββββββββββββββββββββ
β β
β β’ Python array indexing β’ Rasterio file reading β
β β’ 2D: (row_slice, col_slice) β’ 2D: explicit offsets + sizes β
β β’ End-exclusive β’ Width/height inclusive β
β β
β Conversion: β
β slices_to_windows((row_slice, col_slice)) β Window β
β window_to_slices(window) β (row_slice, col_slice) β
β β
β Example: β
β slice(100, 356), slice(200, 456) β Window(200, 100, 256, 256) β
β (rows 100-355, cols 200-455) (col=200, row=100, 256x256) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Edge Handling Options¶
What happens when tiles don't fit evenly::
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β EDGE HANDLING OPTIONS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Raster: 500px, Tile: 128px, Overlap: 0 β
β ββββββββββββββββββββββββββββββββββββββ β
β β
β include_incomplete=True (default): β
β ββββββββββ¬βββββββββ¬βββββββββ¬βββββββββ¬βββββ β
β β 128 β 128 β 128 β 128 β 12 β β 5 tiles, last is 12px β
β ββββββββββ΄βββββββββ΄βββββββββ΄βββββββββ΄βββββ β
β β
β include_incomplete=False: β
β ββββββββββ¬βββββββββ¬βββββββββ β
β β 128 β 128 β 128 β β 3 tiles, drops edge β
β ββββββββββ΄βββββββββ΄βββββββββ β
β β
β trim_incomplete=True: β
β Same as include_incomplete=True but last slice is trimmed β
β slice(384, 500) instead of slice(384, 512) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Module Functions Overview¶
Slice Generation
- :func:
_slices: Generate 1D slices for a single dimension - :func:
_slices_nd: Generate N-dimensional slice tuples - :func:
_slices_2d: Generate 2D (row, col) slice tuples
Window Conversion
- :func:
slices_to_windows: Convert (row_slice, col_slice) β Window - :func:
window_to_slices: Convert Window β (row_slice, col_slice) - :func:
windows_from_shape: Generate Windows covering a shape
Quick Start¶
Generate tiles for processing a large raster::
from georeader import slices
import rasterio
# Generate 256x256 tiles with 32px overlap
with rasterio.open("large_raster.tif") as src:
tiles = slices._slices_2d(
shape=(src.height, src.width),
size=(256, 256),
overlap=(32, 32)
)
for row_slice, col_slice in tiles:
# Read this tile
data = src.read(window=slices.slices_to_windows((row_slice, col_slice)))
# Process...
Convert between slices and windows::
from georeader import slices
# Slices to Window
row_s, col_s = slice(100, 356), slice(200, 456)
window = slices.slices_to_windows((row_s, col_s))
# Window(col_off=200, row_off=100, width=256, height=256)
# Window to slices
row_s, col_s = slices.window_to_slices(window)
# slice(100, 356), slice(200, 456)
See Also¶
georeader.mosaic : Mosaic processing using tiles georeader.read : Reading functions that accept Windows rasterio.windows : Window class documentation
create_windows(geodata_shape, window_size, overlap=None, include_incomplete=True, start_negative_if_padding=False, trim_incomplete=True)
¶
Generate rasterio Window objects covering a raster in tiles.
This is the primary function for tiled raster processing with rasterio/georeader. It creates a list of Windows that can be passed directly to read functions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
geodata_shape
|
Tuple[int, int]
|
Spatial shape of the raster as (height, width) or equivalently (n_rows, n_cols). Note: height first, matching numpy convention. |
required |
window_size
|
Tuple[int, int]
|
Size of each tile as (height, width). Example: (256, 256) for 256Γ256 pixel tiles. |
required |
overlap
|
Optional[Tuple[int, int]]
|
Overlap in pixels as (row_overlap, col_overlap). Example: (32, 32) for 32-pixel overlap in both dimensions. Default None (no overlap, stride = window_size). |
None
|
include_incomplete
|
bool
|
Include edge tiles that are smaller than window_size. Default True. |
True
|
start_negative_if_padding
|
bool
|
Start tiling at -overlap//2 for symmetric edge padding. Requires boundless=True when reading. Default False. |
False
|
trim_incomplete
|
bool
|
Trim edge tiles to raster bounds rather than extending beyond. Default True. |
True
|
Returns:
| Type | Description |
|---|---|
List[Window]
|
List[rasterio.windows.Window]: Windows covering the raster. Each window has integer col_off, row_off, width, height attributes. |
Examples:
Generate tiles for a raster:
>>> from georeader import slices
>>> import rasterio
>>>
>>> # 1000Γ1200 raster into 256Γ256 tiles
>>> windows = slices.create_windows(
... geodata_shape=(1000, 1200),
... window_size=(256, 256)
... )
>>> len(windows)
20 # 4 rows Γ 5 cols
>>> windows[0]
Window(col_off=0, row_off=0, width=256, height=256)
Process raster in tiles:
>>> with rasterio.open("large_image.tif") as src:
... windows = slices.create_windows(
... geodata_shape=(src.height, src.width),
... window_size=(512, 512),
... overlap=(64, 64)
... )
... for window in windows:
... data = src.read(window=window)
... # Process tile...
With GeoTensor:
>>> from georeader import read
>>> windows = slices.create_windows(
... geodata_shape=geotensor.shape[-2:], # (H, W)
... window_size=(256, 256)
... )
>>> for window in windows:
... tile = read.read_from_window(geotensor, window)
See Also
create_slices: Returns dict of slices for xarray-style indexing. georeader.read.read_from_window: Read data using a Window.
Source code in georeader/slices.py
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | |
create_slices(named_shape, dims, overlap=None, include_incomplete=True, start_negative_if_padding=False, trim_incomplete=True)
¶
Generate N-dimensional slice combinations for tiled array processing.
This function extends 1D slicing (:func:_slices) to multiple named dimensions,
returning all combinations of slices as a Cartesian product. Designed for
xarray-style named dimensions but works with any string keys.
The function is useful for processing large multidimensional datasets in chunks, such as temporal-spatial data cubes or multi-resolution pyramids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
named_shape
|
Dict[str, int]
|
Shape of the array with named dimensions.
Example: |
required |
dims
|
Dict[str, int]
|
Size of tiles for each dimension to slice.
Only dimensions in this dict will be sliced; others are left whole.
Example: |
required |
overlap
|
Optional[Dict[str, int]]
|
Overlap pixels per dimension.
Example: |
None
|
include_incomplete
|
bool
|
Include edge tiles smaller than |
True
|
start_negative_if_padding
|
bool
|
Start at -overlap//2 for symmetric edge handling. Default False. |
False
|
trim_incomplete
|
bool
|
Trim edge tiles to actual array bounds rather than extending beyond. Default True. |
True
|
Returns:
| Type | Description |
|---|---|
List[Dict[str, slice]]
|
List[Dict[str, slice]]: List of slice dictionaries, one per tile. Each dict maps dimension names to slice objects. Total count = product of tile counts per dimension. |
Examples:
Simple 2D tiling:
>>> named_shape = {"x": 500, "y": 400}
>>> dims = {"x": 256, "y": 256}
>>> tiles = create_slices(named_shape, dims)
>>> len(tiles) # 2 in x Γ 2 in y = 4 tiles
4
>>> tiles[0]
{'x': slice(0, 256), 'y': slice(0, 256)}
With overlap for ML inference:
>>> tiles = create_slices(
... named_shape={"x": 1000, "y": 1000},
... dims={"x": 512, "y": 512},
... overlap={"x": 64, "y": 64}
... )
>>> # stride = 512 - 64 = 448
>>> len(tiles) # 3 in x Γ 3 in y = 9 tiles
9
Use with xarray:
>>> import xarray as xr
>>> data = xr.DataArray(np.random.rand(400, 500), dims=['y', 'x'])
>>> tiles = create_slices(
... named_shape={"x": data.sizes["x"], "y": data.sizes["y"]},
... dims={"x": 128, "y": 128}
... )
>>> for tile_slices in tiles:
... chunk = data.isel(tile_slices) # Extract tile
... # Process chunk...
See Also
create_windows: Returns rasterio.windows.Window objects instead of dicts. _slices: Underlying 1D slicing function.
Source code in georeader/slices.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
See Also¶
- Read Module - Image reading and reprojection
- Mosaic Module - Combining multiple rasters
georeader.read.read_from_window- Reading tiles from GeoData