0
# I/O and Data Utilities
1
2
Core input/output utilities and data handling classes that support rasterstats functionality. These utilities handle reading vector data from various sources, managing raster data access, and providing coordinate system transformations.
3
4
## Capabilities
5
6
### Raster Data Access
7
8
The `Raster` class provides unified access to raster data from files or numpy arrays.
9
10
```python { .api }
11
from rasterstats.io import Raster
12
13
class Raster:
14
"""
15
Raster abstraction for data access to 2/3D array-like things.
16
17
Use as a context manager to ensure dataset gets closed properly.
18
19
Parameters:
20
- raster: 2/3D array-like data source (path to raster file or numpy array)
21
- affine: Affine transformation (required if raster is ndarray)
22
- nodata: Override nodata value (default: None)
23
- band: Raster band number, counting from 1 (default: 1)
24
"""
25
26
def __init__(self, raster, affine=None, nodata=None, band=1): ...
27
28
def index(self, x, y):
29
"""
30
Convert (x, y) coordinates in CRS to (row, column) indices.
31
32
Parameters:
33
- x: X coordinate in coordinate reference system
34
- y: Y coordinate in coordinate reference system
35
36
Returns:
37
Tuple of (row, column) indices
38
"""
39
40
def read(self, bounds=None, window=None, masked=False, boundless=True):
41
"""
42
Read data from the raster source.
43
44
Parameters:
45
- bounds: Bounding box (w, s, e, n) (default: None)
46
- window: Rasterio-style window ((row_start, row_stop), (col_start, col_stop)) (default: None)
47
- masked: Return masked numpy array (default: False)
48
- boundless: Allow reading beyond dataset extent (default: True)
49
50
Returns:
51
Raster object with updated affine and array info
52
53
Raises:
54
ValueError if both bounds and window specified or neither specified
55
"""
56
57
# Context manager methods
58
def __enter__(self): ...
59
def __exit__(self, *args): ...
60
```
61
62
### Vector Data Reading
63
64
Functions for reading vector data from various sources including files, GeoJSON, and geometric objects.
65
66
```python { .api }
67
from rasterstats.io import read_features, read_featurecollection
68
69
def read_features(obj, layer=0):
70
"""
71
Read vector features from various input sources.
72
73
Supports:
74
- File paths (Shapefile, GeoJSON, etc.)
75
- GeoJSON strings or dictionaries
76
- Feature collections
77
- Iterables of feature-like objects
78
- Objects with __geo_interface__
79
- WKT/WKB geometry strings/bytes
80
81
Parameters:
82
- obj: Vector data source
83
- layer: Layer index or name for multi-layer sources (default: 0)
84
85
Returns:
86
Iterator yielding GeoJSON-like Feature dictionaries
87
88
Raises:
89
ValueError if object is not a recognized source of features
90
"""
91
92
def read_featurecollection(obj, layer=0):
93
"""
94
Read vector features and return as GeoJSON FeatureCollection.
95
96
Parameters:
97
- obj: Vector data source (same as read_features)
98
- layer: Layer index or name (default: 0)
99
100
Returns:
101
GeoJSON FeatureCollection dictionary with all features loaded
102
"""
103
104
def parse_feature(obj):
105
"""
106
Parse a single object into a GeoJSON-like Feature.
107
108
Attempts to convert various input formats:
109
- Objects with __geo_interface__
110
- WKT/WKB strings/bytes
111
- GeoJSON geometry or feature dictionaries
112
113
Parameters:
114
- obj: Object to parse as feature
115
116
Returns:
117
GeoJSON-like Feature dictionary
118
119
Raises:
120
ValueError if object cannot be parsed as a feature
121
"""
122
```
123
124
### Coordinate and Window Utilities
125
126
Functions for coordinate system transformations and window calculations.
127
128
```python { .api }
129
from rasterstats.io import rowcol, bounds_window, window_bounds
130
131
def rowcol(x, y, affine, op=math.floor):
132
"""
133
Convert x/y coordinates to row/column indices.
134
135
Parameters:
136
- x: X coordinate
137
- y: Y coordinate
138
- affine: Affine transformation
139
- op: Rounding operation function (default: math.floor)
140
141
Returns:
142
Tuple of (row, column) indices
143
"""
144
145
def bounds_window(bounds, affine):
146
"""
147
Create rasterio-style window from bounding box.
148
149
Parameters:
150
- bounds: Bounding box (west, south, east, north)
151
- affine: Affine transformation
152
153
Returns:
154
Window tuple ((row_start, row_stop), (col_start, col_stop))
155
"""
156
157
def window_bounds(window, affine):
158
"""
159
Calculate bounding box from rasterio-style window.
160
161
Parameters:
162
- window: Window tuple ((row_start, row_stop), (col_start, col_stop))
163
- affine: Affine transformation
164
165
Returns:
166
Bounding box tuple (west, south, east, north)
167
"""
168
169
def beyond_extent(window, shape):
170
"""
171
Check if window references pixels beyond raster extent.
172
173
Parameters:
174
- window: Window tuple ((row_start, row_stop), (col_start, col_stop))
175
- shape: Raster shape tuple (height, width)
176
177
Returns:
178
Boolean indicating if window extends beyond raster bounds
179
"""
180
```
181
182
### Array Utilities
183
184
Functions for handling boundless array operations and data access.
185
186
```python { .api }
187
from rasterstats.io import boundless_array
188
189
def boundless_array(arr, window, nodata, masked=False):
190
"""
191
Extract array data for window that may extend beyond array bounds.
192
193
Areas outside the array extent are filled with nodata values.
194
195
Parameters:
196
- arr: Input numpy array (2D or 3D)
197
- window: Window tuple ((row_start, row_stop), (col_start, col_stop))
198
- nodata: Value to use for areas outside array bounds
199
- masked: Return masked array (default: False)
200
201
Returns:
202
Numpy array (optionally masked) with data for requested window
203
204
Raises:
205
ValueError if array is not 2D or 3D
206
"""
207
```
208
209
### Warning Classes
210
211
Custom warning classes for I/O operations.
212
213
```python { .api }
214
from rasterstats.io import NodataWarning
215
216
class NodataWarning(UserWarning):
217
"""
218
Warning raised for nodata handling issues.
219
220
Issued when:
221
- No nodata value is specified and default (-999) is used
222
- Dataset masks are detected and masked reading is automatically enabled
223
"""
224
```
225
226
## Usage Examples
227
228
### Working with Raster Data
229
230
```python
231
from rasterstats.io import Raster
232
from affine import Affine
233
import numpy as np
234
235
# Using file-based raster
236
with Raster("elevation.tif") as rast:
237
# Get pixel indices for coordinates
238
row, col = rast.index(100.5, 200.7)
239
240
# Read full raster
241
full_data = rast.read()
242
243
# Read specific window
244
window = ((10, 50), (20, 60))
245
subset = rast.read(window=window, masked=True)
246
247
# Read by bounding box
248
bounds = (100, 200, 150, 250) # w, s, e, n
249
clipped = rast.read(bounds=bounds, boundless=True)
250
251
# Using numpy array
252
raster_array = np.random.rand(100, 100) * 1000
253
transform = Affine.translation(0, 100) * Affine.scale(1, -1)
254
255
with Raster(raster_array, affine=transform, nodata=-999) as rast:
256
subset = rast.read(bounds=(10, 10, 50, 50))
257
print(f"Shape: {subset.array.shape}")
258
print(f"Affine: {subset.affine}")
259
```
260
261
### Reading Vector Data
262
263
```python
264
from rasterstats.io import read_features, read_featurecollection
265
266
# Read from shapefile
267
features = list(read_features("watersheds.shp"))
268
print(f"Found {len(features)} features")
269
270
# Read from GeoJSON string
271
geojson_str = '''{"type": "Point", "coordinates": [100, 200]}'''
272
point_features = list(read_features(geojson_str))
273
274
# Read from feature collection
275
fc = read_featurecollection("polygons.geojson")
276
print(f"FeatureCollection with {len(fc['features'])} features")
277
278
# Read from list of geometries
279
geometries = [
280
{"type": "Point", "coordinates": [100, 200]},
281
{"type": "Point", "coordinates": [150, 250]}
282
]
283
point_list = list(read_features(geometries))
284
285
# Handle multi-layer sources
286
layers = list(read_features("multilayer.gpkg", layer="roads"))
287
```
288
289
### Coordinate Transformations
290
291
```python
292
from rasterstats.io import rowcol, bounds_window, window_bounds
293
from affine import Affine
294
import math
295
296
# Create sample transform
297
transform = Affine.translation(100, 200) * Affine.scale(1, -1)
298
299
# Convert coordinates to pixel indices
300
row, col = rowcol(105.5, 195.3, transform)
301
print(f"Pixel location: row {row}, col {col}")
302
303
# Using ceiling operation for different rounding
304
row_ceil, col_ceil = rowcol(105.5, 195.3, transform, op=math.ceil)
305
306
# Create window from bounds
307
bounds = (100, 150, 200, 250) # w, s, e, n
308
window = bounds_window(bounds, transform)
309
print(f"Window: {window}")
310
311
# Get bounds back from window
312
calculated_bounds = window_bounds(window, transform)
313
print(f"Bounds: {calculated_bounds}")
314
```
315
316
### Handling Boundless Operations
317
318
```python
319
from rasterstats.io import boundless_array, beyond_extent
320
import numpy as np
321
322
# Create sample array
323
arr = np.random.rand(50, 50) * 100
324
shape = arr.shape
325
326
# Define window that extends beyond array
327
large_window = ((45, 65), (45, 65)) # Extends 15 pixels beyond
328
329
if beyond_extent(large_window, shape):
330
print("Window extends beyond array bounds")
331
332
# Extract data with nodata fill
333
result = boundless_array(arr, large_window, nodata=-999, masked=True)
334
print(f"Result shape: {result.shape}")
335
print(f"Original array shape: {arr.shape}")
336
print(f"Nodata pixels: {(result == -999).sum()}")
337
```
338
339
## Types
340
341
```python { .api }
342
from typing import Union, List, Dict, Any, Optional, Tuple, Iterator
343
from numpy import ndarray
344
from affine import Affine
345
346
# Input types
347
VectorSource = Union[str, Dict, List[Dict], bytes] # Various vector input formats
348
RasterSource = Union[str, ndarray] # File path or numpy array
349
LayerSpec = Union[int, str] # Layer index or name
350
GeometryDict = Dict[str, Any] # GeoJSON geometry dictionary
351
FeatureDict = Dict[str, Any] # GeoJSON feature dictionary
352
353
# Coordinate types
354
Bounds = Tuple[float, float, float, float] # (west, south, east, north)
355
Window = Tuple[Tuple[int, int], Tuple[int, int]] # ((row_start, row_stop), (col_start, col_stop))
356
Coordinates = Tuple[float, float] # (x, y) coordinate pair
357
PixelIndices = Tuple[int, int] # (row, column) indices
358
359
# Array types
360
BoundlessArray = Union[ndarray, np.ma.MaskedArray] # Regular or masked array
361
ArrayShape = Tuple[int, int] # (height, width) for 2D arrays
362
```