0
# Windowing
1
2
Efficient reading and writing of rectangular subsets of raster data. The Window class and related functions support coordinate-based and index-based windowing with geometric operations for spatial subsetting.
3
4
## Capabilities
5
6
### Window Class
7
8
Represents a rectangular subset of a raster dataset defined by pixel coordinates.
9
10
```python { .api }
11
class Window:
12
"""Rectangular raster window."""
13
14
def __init__(self, col_off, row_off, width, height):
15
"""
16
Initialize window from pixel coordinates.
17
18
Parameters:
19
- col_off (float): Column (x) offset from dataset origin
20
- row_off (float): Row (y) offset from dataset origin
21
- width (float): Window width in pixels
22
- height (float): Window height in pixels
23
"""
24
25
# Properties
26
col_off: float # Column offset
27
row_off: float # Row offset
28
width: float # Window width
29
height: float # Window height
30
31
@property
32
def c(self):
33
"""Column offset (alias for col_off)."""
34
35
@property
36
def r(self):
37
"""Row offset (alias for row_off)."""
38
39
@property
40
def w(self):
41
"""Width (alias for width)."""
42
43
@property
44
def h(self):
45
"""Height (alias for height)."""
46
47
def flatten(self):
48
"""Return window as tuple (col_off, row_off, width, height)."""
49
50
def todict(self):
51
"""Return window as dictionary."""
52
53
def toslices(self):
54
"""Convert to array slices (row_slice, col_slice)."""
55
56
def round_lengths(self, op='floor', pixel_precision=3):
57
"""Round window dimensions."""
58
59
def round_offsets(self, op='floor', pixel_precision=3):
60
"""Round window offsets."""
61
```
62
63
Usage examples:
64
65
```python
66
from rasterio.windows import Window
67
68
# Create window from pixel coordinates
69
window = Window(100, 200, 512, 512) # col_off, row_off, width, height
70
71
# Access properties
72
print(f"Column offset: {window.col_off}") # 100
73
print(f"Row offset: {window.row_off}") # 200
74
print(f"Width: {window.width}") # 512
75
print(f"Height: {window.height}") # 512
76
77
# Alternative property access
78
print(f"Position: ({window.c}, {window.r})") # (100, 200)
79
print(f"Size: {window.w} x {window.h}") # 512 x 512
80
81
# Convert to different formats
82
window_tuple = window.flatten() # (100, 200, 512, 512)
83
window_dict = window.todict() # {'col_off': 100, 'row_off': 200, ...}
84
row_slice, col_slice = window.toslices() # Array slicing objects
85
86
# Use window for reading
87
with rasterio.open('large_raster.tif') as dataset:
88
# Read windowed data
89
data = dataset.read(1, window=window)
90
print(f"Read data shape: {data.shape}") # (512, 512)
91
```
92
93
### Window Creation Functions
94
95
Utilities for creating windows from various spatial parameters.
96
97
```python { .api }
98
def from_bounds(left, bottom, right, top, transform, height=None, width=None,
99
precision=None):
100
"""
101
Create window from geographic bounds.
102
103
Parameters:
104
- left (float): Left (minimum x) coordinate
105
- bottom (float): Bottom (minimum y) coordinate
106
- right (float): Right (maximum x) coordinate
107
- top (float): Top (maximum y) coordinate
108
- transform (Affine): Dataset geospatial transformation
109
- height (int): Dataset height for validation
110
- width (int): Dataset width for validation
111
- precision (int): Rounding precision for coordinates
112
113
Returns:
114
Window: Window covering the specified bounds
115
"""
116
117
def get_data_window(arr, nodata=None):
118
"""
119
Calculate window covering non-nodata pixels.
120
121
Parameters:
122
- arr (numpy.ndarray): Input raster array
123
- nodata (number): NoData value to exclude
124
125
Returns:
126
Window: Window covering valid data extent
127
"""
128
```
129
130
Usage examples:
131
132
```python
133
from rasterio.windows import from_bounds, get_data_window
134
import rasterio
135
136
# Create window from geographic bounds
137
with rasterio.open('dataset.tif') as dataset:
138
# Define area of interest
139
aoi_bounds = (-120.5, 35.2, -119.8, 35.9) # left, bottom, right, top
140
141
# Create window covering these bounds
142
window = from_bounds(*aoi_bounds, dataset.transform)
143
144
# Read data for area of interest
145
aoi_data = dataset.read(1, window=window)
146
147
# Get transform for windowed data
148
window_transform = dataset.window_transform(window)
149
150
# Find data extent window
151
with rasterio.open('sparse_dataset.tif') as dataset:
152
full_data = dataset.read(1)
153
154
# Get window covering only valid data
155
data_window = get_data_window(full_data, nodata=dataset.nodata)
156
157
# Read only the data extent
158
valid_data = dataset.read(1, window=data_window)
159
```
160
161
### Window Geometric Operations
162
163
Functions for combining and manipulating windows geometrically.
164
165
```python { .api }
166
def union(*windows):
167
"""
168
Create window covering the union of input windows.
169
170
Parameters:
171
- *windows: Variable number of Window objects
172
173
Returns:
174
Window: Window covering all input windows
175
"""
176
177
def intersection(*windows):
178
"""
179
Create window covering the intersection of input windows.
180
181
Parameters:
182
- *windows: Variable number of Window objects
183
184
Returns:
185
Window or None: Intersecting window, or None if no intersection
186
"""
187
188
def intersect(*windows):
189
"""
190
Test if windows intersect.
191
192
Parameters:
193
- *windows: Variable number of Window objects
194
195
Returns:
196
bool: True if all windows intersect
197
"""
198
```
199
200
Usage examples:
201
202
```python
203
from rasterio.windows import union, intersection, intersect
204
205
# Create overlapping windows
206
window1 = Window(0, 0, 100, 100) # Top-left quadrant
207
window2 = Window(50, 50, 100, 100) # Overlapping area
208
window3 = Window(200, 200, 50, 50) # Non-overlapping area
209
210
# Union of windows
211
combined_window = union(window1, window2)
212
print(f"Union covers: {combined_window}") # Covers both windows
213
214
# Intersection of windows
215
overlap_window = intersection(window1, window2)
216
if overlap_window:
217
print(f"Overlap area: {overlap_window}") # Window(50, 50, 50, 50)
218
219
# Test for intersection
220
has_overlap = intersect(window1, window2) # True
221
no_overlap = intersect(window1, window3) # False
222
223
# Multiple window operations
224
all_windows = union(window1, window2, window3) # Covers all three
225
common_area = intersection(window1, window2, window3) # None
226
```
227
228
### Window Coordinate Functions
229
230
Utilities for converting between window and geographic coordinates.
231
232
```python { .api }
233
def bounds(window, transform):
234
"""
235
Calculate geographic bounds of window.
236
237
Parameters:
238
- window (Window): Raster window
239
- transform (Affine): Geospatial transformation
240
241
Returns:
242
BoundingBox: Geographic bounds (left, bottom, right, top)
243
"""
244
245
def transform(window, src_transform):
246
"""
247
Calculate transformation matrix for windowed data.
248
249
Parameters:
250
- window (Window): Raster window
251
- src_transform (Affine): Source dataset transformation
252
253
Returns:
254
Affine: Transformation for windowed data
255
"""
256
```
257
258
Usage examples:
259
260
```python
261
from rasterio.windows import bounds, transform
262
from rasterio.coords import BoundingBox
263
264
# Calculate window bounds
265
window = Window(100, 200, 512, 512)
266
with rasterio.open('dataset.tif') as dataset:
267
# Get geographic bounds of window
268
window_bounds = bounds(window, dataset.transform)
269
print(f"Window bounds: {window_bounds}")
270
271
# Get transformation for windowed data
272
window_transform = transform(window, dataset.transform)
273
274
# Read windowed data
275
windowed_data = dataset.read(1, window=window)
276
277
# Windowed data has its own coordinate system
278
height, width = windowed_data.shape
279
windowed_bounds = array_bounds(height, width, window_transform)
280
281
# Should match window_bounds
282
assert windowed_bounds == window_bounds
283
```
284
285
### Window Validation and Utilities
286
287
Helper functions for window validation and manipulation.
288
289
```python { .api }
290
def crop(raster, window):
291
"""
292
Crop raster array using window.
293
294
Parameters:
295
- raster (numpy.ndarray): Input raster array
296
- window (Window): Cropping window
297
298
Returns:
299
numpy.ndarray: Cropped array
300
"""
301
302
def validate_window(window, height, width):
303
"""
304
Validate window against dataset dimensions.
305
306
Parameters:
307
- window (Window): Window to validate
308
- height (int): Dataset height
309
- width (int): Dataset width
310
311
Returns:
312
bool: True if window is valid
313
"""
314
```
315
316
Usage examples:
317
318
```python
319
# Crop array using window
320
full_array = dataset.read(1)
321
window = Window(100, 100, 200, 200)
322
cropped_array = crop(full_array, window)
323
324
# Validate window bounds
325
is_valid = validate_window(window, dataset.height, dataset.width)
326
if not is_valid:
327
print("Window extends beyond dataset bounds")
328
329
# Safe windowed reading with validation
330
def safe_read_window(dataset, window, band=1):
331
if validate_window(window, dataset.height, dataset.width):
332
return dataset.read(band, window=window)
333
else:
334
raise ValueError("Window extends beyond dataset bounds")
335
```
336
337
### Window Error Handling
338
339
Window operations can raise specific exceptions for invalid windows or operations:
340
341
```python { .api }
342
class WindowError(RasterioError):
343
"""Window operation related errors."""
344
```
345
346
Common error scenarios:
347
348
```python
349
from rasterio.errors import WindowError
350
351
try:
352
# Invalid window dimensions
353
invalid_window = Window(-10, -10, 100, 100) # Negative offsets
354
validate_window(invalid_window, 1000, 1000)
355
except WindowError as e:
356
print(f"Invalid window: {e}")
357
358
# Window extending beyond dataset
359
large_window = Window(900, 900, 200, 200) # Extends beyond 1000x1000 dataset
360
try:
361
with rasterio.open('small_dataset.tif') as dataset:
362
data = dataset.read(1, window=large_window) # May raise WindowError
363
except WindowError as e:
364
print(f"Window out of bounds: {e}")
365
```