0
# Coordinate Systems
1
2
Comprehensive coordinate reference system (CRS) management including setting, transforming, and reprojecting coordinate systems. These capabilities enable working with geospatial data across different projections and coordinate systems.
3
4
## Capabilities
5
6
### CRS Properties and Access
7
8
Get and set coordinate reference system information for DataArrays and Datasets.
9
10
```python { .api }
11
@property
12
def crs(self) -> Optional[rasterio.crs.CRS]:
13
"""
14
Retrieve projection from xarray Dataset or DataArray.
15
16
Returns:
17
rasterio.crs.CRS or None: The coordinate reference system
18
"""
19
```
20
21
#### Usage Examples
22
23
```python
24
import rioxarray
25
import xarray as xr
26
27
# Open raster with CRS
28
da = rioxarray.open_rasterio('geo_file.tif')
29
print(da.rio.crs) # <rasterio.crs.CRS object>
30
31
# Check if data has CRS
32
if da.rio.crs is not None:
33
print(f"CRS: {da.rio.crs}")
34
else:
35
print("No CRS defined")
36
37
# Get CRS string representation
38
print(da.rio.crs.to_string()) # 'EPSG:4326'
39
```
40
41
### Setting CRS
42
43
Set coordinate reference system without modifying the underlying data coordinates.
44
45
```python { .api }
46
def set_crs(
47
self,
48
input_crs: Any,
49
inplace: bool = True
50
) -> Union[xarray.Dataset, xarray.DataArray]:
51
"""
52
Set the CRS value for the Dataset/DataArray without modifying
53
the dataset/data array.
54
55
Parameters:
56
- input_crs: CRS in various formats (EPSG code, PROJ string, CRS object, etc.)
57
- inplace: If True, modify in place and return None (default: True)
58
59
Returns:
60
Dataset/DataArray with CRS set (if inplace=False)
61
"""
62
```
63
64
#### Usage Examples
65
66
```python
67
import rioxarray
68
69
# Open data without CRS
70
da = rioxarray.open_rasterio('file_no_crs.tif')
71
72
# Set CRS using EPSG code
73
da.rio.set_crs('EPSG:4326')
74
75
# Set CRS using different formats
76
da.rio.set_crs(4326) # EPSG integer
77
da.rio.set_crs('+proj=longlat +datum=WGS84') # PROJ string
78
da.rio.set_crs({'init': 'epsg:4326'}) # Dictionary format
79
80
# Create new object with CRS (inplace=False)
81
da_with_crs = da.rio.set_crs('EPSG:3857', inplace=False)
82
```
83
84
### Writing CRS to File
85
86
Write CRS information to dataset attributes for file output.
87
88
```python { .api }
89
def write_crs(
90
self,
91
input_crs: Optional[Any] = None,
92
grid_mapping_name: Optional[str] = None,
93
inplace: bool = False
94
) -> Union[xarray.Dataset, xarray.DataArray]:
95
"""
96
Write the CRS to the dataset as a coordinate variable.
97
98
Parameters:
99
- input_crs: CRS to write (uses current CRS if None)
100
- grid_mapping_name: Name for grid mapping variable
101
- inplace: If True, modify in place
102
103
Returns:
104
Dataset/DataArray with CRS written to attributes
105
"""
106
```
107
108
#### Usage Examples
109
110
```python
111
import rioxarray
112
113
da = rioxarray.open_rasterio('file.tif')
114
115
# Write current CRS to attributes
116
da_with_attrs = da.rio.write_crs(inplace=False)
117
118
# Write specific CRS
119
da_with_attrs = da.rio.write_crs('EPSG:4326', inplace=False)
120
121
# Custom grid mapping name
122
da_with_attrs = da.rio.write_crs(
123
grid_mapping_name='my_projection',
124
inplace=False
125
)
126
```
127
128
### UTM CRS Estimation
129
130
Automatically estimate the appropriate UTM coordinate system based on data bounds.
131
132
```python { .api }
133
def estimate_utm_crs(self, datum_name: str = "WGS 84") -> rasterio.crs.CRS:
134
"""
135
Returns the estimated UTM CRS based on the bounds of the dataset.
136
137
Parameters:
138
- datum_name: Datum name for UTM CRS (default: "WGS 84")
139
140
Returns:
141
rasterio.crs.CRS: Estimated UTM CRS
142
143
Raises:
144
MissingCRS: If dataset has no CRS defined
145
"""
146
```
147
148
#### Usage Examples
149
150
```python
151
import rioxarray
152
153
# Open geographic data (lat/lon)
154
da = rioxarray.open_rasterio('geographic_data.tif') # EPSG:4326
155
156
# Estimate best UTM zone
157
utm_crs = da.rio.estimate_utm_crs()
158
print(utm_crs) # UTM Zone 33N or similar
159
160
# Estimate with different datum
161
utm_crs = da.rio.estimate_utm_crs(datum_name="NAD83")
162
163
# Use estimated CRS for reprojection
164
reprojected = da.rio.reproject(utm_crs)
165
```
166
167
### Transform Operations
168
169
Get and manipulate the affine transformation matrix that defines the pixel-to-coordinate mapping.
170
171
```python { .api }
172
def transform(self, recalc: bool = False) -> rasterio.Affine:
173
"""
174
Get the affine transformation matrix.
175
176
Parameters:
177
- recalc: Recalculate transform from coordinates (default: False)
178
179
Returns:
180
rasterio.Affine: The affine transformation matrix
181
"""
182
183
def write_transform(self, transform: Optional[rasterio.Affine] = None, inplace: bool = False):
184
"""
185
Write the affine transform to the dataset.
186
187
Parameters:
188
- transform: Affine transform to write (uses current if None)
189
- inplace: If True, modify in place
190
191
Returns:
192
Dataset/DataArray with transform written to attributes
193
"""
194
```
195
196
#### Usage Examples
197
198
```python
199
import rioxarray
200
from rasterio.transform import from_bounds
201
202
da = rioxarray.open_rasterio('file.tif')
203
204
# Get current transform
205
transform = da.rio.transform()
206
print(transform) # Affine transformation matrix
207
208
# Create custom transform
209
new_transform = from_bounds(-180, -90, 180, 90, 360, 180)
210
211
# Apply custom transform
212
da_transformed = da.rio.write_transform(new_transform, inplace=False)
213
```
214
215
### Resolution Information
216
217
Get pixel resolution from the affine transformation matrix.
218
219
```python { .api }
220
def resolution(self, recalc: bool = False) -> tuple[float, float]:
221
"""
222
Determine the resolution of the grid.
223
If the transformation has rotation, the sign of the resolution is lost.
224
225
Parameters:
226
- recalc: Recalculate resolution from coordinates (default: False)
227
228
Returns:
229
tuple[float, float]: (x_resolution, y_resolution)
230
"""
231
```
232
233
#### Usage Examples
234
235
```python
236
import rioxarray
237
238
da = rioxarray.open_rasterio('file.tif')
239
240
# Get pixel resolution
241
x_res, y_res = da.rio.resolution()
242
print(f"X resolution: {x_res}, Y resolution: {y_res}")
243
244
# Recalculate from coordinates
245
x_res, y_res = da.rio.resolution(recalc=True)
246
```
247
248
### Bounds Operations
249
250
Get spatial bounds and transform bounds between coordinate systems.
251
252
```python { .api }
253
def bounds(self, recalc: bool = False) -> tuple[float, float, float, float]:
254
"""
255
Get the spatial bounds of the dataset.
256
257
Parameters:
258
- recalc: Recalculate bounds from coordinates (default: False)
259
260
Returns:
261
tuple: (left, bottom, right, top) bounds
262
"""
263
264
def transform_bounds(
265
self,
266
dst_crs: Any,
267
*,
268
densify_pts: int = 21,
269
recalc: bool = False
270
) -> tuple[float, float, float, float]:
271
"""
272
Transform bounds from src_crs to dst_crs.
273
274
Parameters:
275
- dst_crs: Destination CRS
276
- densify_pts: Number of points to use for densification (default: 21)
277
- recalc: Recalculate source bounds (default: False)
278
279
Returns:
280
tuple: Transformed (left, bottom, right, top) bounds
281
"""
282
```
283
284
#### Usage Examples
285
286
```python
287
import rioxarray
288
289
da = rioxarray.open_rasterio('file.tif') # UTM coordinates
290
291
# Get current bounds
292
left, bottom, right, top = da.rio.bounds()
293
print(f"Bounds: {left}, {bottom}, {right}, {top}")
294
295
# Transform bounds to geographic coordinates
296
geo_bounds = da.rio.transform_bounds('EPSG:4326')
297
print(f"Geographic bounds: {geo_bounds}")
298
299
# Transform with more densification points
300
detailed_bounds = da.rio.transform_bounds('EPSG:4326', densify_pts=50)
301
```
302
303
### Grid Mapping Operations
304
305
Write grid mapping information for CF-compliant NetCDF files.
306
307
```python { .api }
308
def write_grid_mapping(
309
self,
310
grid_mapping_name: Optional[str] = None,
311
inplace: bool = False
312
) -> Union[xarray.Dataset, xarray.DataArray]:
313
"""
314
Write the grid mapping to the dataset.
315
316
Parameters:
317
- grid_mapping_name: Name for the grid mapping variable
318
- inplace: If True, modify in place
319
320
Returns:
321
Dataset/DataArray with grid mapping written
322
"""
323
324
def write_coordinate_system(self, inplace: bool = False):
325
"""
326
Write the coordinate system information to the dataset.
327
328
Parameters:
329
- inplace: If True, modify in place
330
331
Returns:
332
Dataset/DataArray with coordinate system information
333
"""
334
```
335
336
#### Usage Examples
337
338
```python
339
import rioxarray
340
341
da = rioxarray.open_rasterio('projected_data.tif')
342
343
# Write grid mapping for CF compliance
344
cf_da = da.rio.write_grid_mapping(inplace=False)
345
346
# Write complete coordinate system
347
coord_da = da.rio.write_coordinate_system(inplace=False)
348
349
# Save as CF-compliant NetCDF
350
cf_da.to_netcdf('cf_compliant.nc')
351
```
352
353
## CRS Utility Functions
354
355
Helper functions for working with coordinate reference systems.
356
357
```python { .api }
358
def crs_from_user_input(crs_input: Any) -> rasterio.crs.CRS:
359
"""
360
Return a rasterio.crs.CRS from user input.
361
362
Handles various CRS input formats and transitions between GDAL versions.
363
364
Parameters:
365
- crs_input: CRS in various formats
366
367
Returns:
368
rasterio.crs.CRS: Standardized CRS object
369
"""
370
```
371
372
#### Usage Examples
373
374
```python
375
from rioxarray.crs import crs_from_user_input
376
377
# Convert various CRS formats to standard CRS object
378
crs1 = crs_from_user_input('EPSG:4326')
379
crs2 = crs_from_user_input(4326)
380
crs3 = crs_from_user_input('+proj=longlat +datum=WGS84')
381
crs4 = crs_from_user_input({'init': 'epsg:4326'})
382
383
# All return equivalent rasterio.crs.CRS objects
384
print(crs1 == crs2 == crs3 == crs4) # True
385
```
386
387
## Common CRS Operations
388
389
### CRS Validation and Conversion
390
```python
391
import rioxarray
392
393
da = rioxarray.open_rasterio('data.tif')
394
395
# Check if CRS is geographic (lat/lon)
396
is_geographic = da.rio.crs.is_geographic
397
print(f"Is geographic: {is_geographic}")
398
399
# Check if CRS is projected
400
is_projected = da.rio.crs.is_projected
401
print(f"Is projected: {is_projected}")
402
403
# Get CRS as different formats
404
epsg_code = da.rio.crs.to_epsg() # EPSG integer or None
405
proj_string = da.rio.crs.to_proj4() # PROJ.4 string
406
wkt = da.rio.crs.to_wkt() # Well-Known Text
407
```
408
409
### Working with Different CRS Formats
410
```python
411
import rioxarray
412
413
da = rioxarray.open_rasterio('file.tif')
414
415
# Set CRS using various input formats
416
da.rio.set_crs('EPSG:4326') # EPSG string
417
da.rio.set_crs(4326) # EPSG integer
418
da.rio.set_crs('+proj=utm +zone=33 +datum=WGS84') # PROJ string
419
da.rio.set_crs({'init': 'epsg:32633'}) # Dictionary
420
421
# Use with CRS objects
422
from rasterio.crs import CRS
423
crs_obj = CRS.from_epsg(4326)
424
da.rio.set_crs(crs_obj)
425
```