0
# Coordinate Transformations
1
2
Coordinate transformations enable conversion between different coordinate reference systems with high precision. PyProj provides robust transformation capabilities through the Transformer class and global transformation functions, supporting transformation pipelines, accuracy estimation, and batch processing.
3
4
## Capabilities
5
6
### Transformer Creation
7
8
Create Transformer objects for coordinate transformations between different CRS with various configuration options.
9
10
```python { .api }
11
class Transformer:
12
def __init__(
13
self,
14
transformer_maker: TransformerMaker | None = None,
15
) -> None:
16
"""
17
Create a Transformer object (internal use only).
18
19
Note:
20
Transformer objects should be created using class methods:
21
- Transformer.from_crs() - most common
22
- Transformer.from_proj() - from PROJ strings
23
- Transformer.from_pipeline() - from PROJ pipelines
24
25
Args:
26
transformer_maker: Internal transformer creation strategy
27
28
Raises:
29
ProjError: If transformer_maker is invalid or None
30
"""
31
32
@classmethod
33
def from_crs(
34
cls,
35
crs_from: Any,
36
crs_to: Any,
37
always_xy: bool = False,
38
area_of_interest: AreaOfInterest | None = None,
39
authority: str | None = None,
40
accuracy: float | None = None,
41
allow_ballpark: bool | None = None,
42
force_over: bool = False,
43
only_best: bool | None = None,
44
) -> "Transformer":
45
"""
46
Create Transformer from coordinate reference systems.
47
48
Args:
49
crs_from: Source CRS (any format accepted by CRS.from_user_input)
50
crs_to: Target CRS (any format accepted by CRS.from_user_input)
51
always_xy: Force x,y axis order regardless of CRS definitions
52
area_of_interest: Constrain transformation search to area
53
authority: Authority to prefer for transformation selection
54
accuracy: Minimum required accuracy in meters
55
allow_ballpark: Allow approximate transformations if exact unavailable
56
force_over: Force Over transformation method selection
57
only_best: Use only the highest accuracy transformation
58
59
Returns:
60
Configured Transformer object
61
62
Raises:
63
CRSError: If CRS inputs are invalid
64
ProjError: If no suitable transformation found
65
"""
66
67
@classmethod
68
def from_proj(
69
cls,
70
proj_from: str,
71
proj_to: str,
72
always_xy: bool = False,
73
area_of_interest: AreaOfInterest | None = None,
74
**kwargs
75
) -> "Transformer":
76
"""
77
Create Transformer from PROJ strings.
78
79
Args:
80
proj_from: Source PROJ string
81
proj_to: Target PROJ string
82
always_xy: Force x,y axis order
83
area_of_interest: Area constraint for transformation
84
**kwargs: Additional parameters
85
86
Returns:
87
Transformer object from PROJ definitions
88
89
Raises:
90
ProjError: If PROJ strings are invalid
91
"""
92
93
@classmethod
94
def from_pipeline(cls, proj_pipeline: str) -> "Transformer":
95
"""
96
Create Transformer from PROJ pipeline string.
97
98
Args:
99
proj_pipeline: PROJ pipeline definition string
100
101
Returns:
102
Transformer object from pipeline
103
104
Raises:
105
ProjError: If pipeline string is invalid or unsupported
106
"""
107
```
108
109
### Coordinate Transformation
110
111
Transform coordinates between coordinate reference systems with support for various data formats and coordinate dimensions.
112
113
```python { .api }
114
class Transformer:
115
def transform(
116
self,
117
xx,
118
yy,
119
zz=None,
120
tt=None,
121
radians: bool = False,
122
errcheck: bool = False,
123
direction: TransformDirection = TransformDirection.FORWARD,
124
**kwargs
125
) -> tuple:
126
"""
127
Transform coordinates from source to target CRS.
128
129
Args:
130
xx: X coordinates (longitude, easting, etc.)
131
yy: Y coordinates (latitude, northing, etc.)
132
zz: Z coordinates (height, elevation, etc.), optional
133
tt: T coordinates (time), optional
134
radians: Input coordinates are in radians (for geographic CRS)
135
errcheck: Check for transformation errors
136
direction: Transformation direction (FORWARD, INVERSE, IDENT)
137
**kwargs: Additional transformation parameters
138
139
Returns:
140
Tuple of transformed coordinates (x, y) or (x, y, z) or (x, y, z, t)
141
142
Raises:
143
ProjError: If transformation fails
144
"""
145
146
def itransform(
147
self,
148
points,
149
switch: bool = False,
150
time_3rd: bool = False,
151
radians: bool = False,
152
errcheck: bool = False,
153
direction: TransformDirection = TransformDirection.FORWARD,
154
**kwargs
155
) -> Iterator:
156
"""
157
Transform iterator of coordinate points.
158
159
Args:
160
points: Iterable of coordinate tuples [(x1,y1), (x2,y2), ...]
161
switch: Switch x,y order in input points
162
time_3rd: Treat third coordinate as time instead of height
163
radians: Input coordinates are in radians
164
errcheck: Check for transformation errors
165
direction: Transformation direction
166
**kwargs: Additional parameters
167
168
Yields:
169
Transformed coordinate tuples
170
171
Raises:
172
ProjError: If transformation fails for any point
173
"""
174
175
def transform_bounds(
176
self,
177
left: float,
178
bottom: float,
179
right: float,
180
top: float,
181
densify_pts: int = 21,
182
radians: bool = False,
183
errcheck: bool = False,
184
direction: TransformDirection = TransformDirection.FORWARD,
185
**kwargs
186
) -> tuple[float, float, float, float]:
187
"""
188
Transform bounding box from source to target CRS.
189
190
Args:
191
left: Left boundary (min x)
192
bottom: Bottom boundary (min y)
193
right: Right boundary (max x)
194
top: Top boundary (max y)
195
densify_pts: Number of points to add along each boundary edge
196
radians: Boundaries are in radians
197
errcheck: Check for transformation errors
198
direction: Transformation direction
199
**kwargs: Additional parameters
200
201
Returns:
202
Tuple of transformed boundaries (left, bottom, right, top)
203
204
Raises:
205
ProjError: If transformation fails
206
"""
207
```
208
209
### Transformer Information and Metadata
210
211
Access information about transformation operations, accuracy, and available alternatives.
212
213
```python { .api }
214
class Transformer:
215
@property
216
def name(self) -> str | None:
217
"""Get the name of the transformation."""
218
219
@property
220
def description(self) -> str | None:
221
"""Get the description of the transformation."""
222
223
@property
224
def definition(self) -> str:
225
"""Get the definition string of the transformation."""
226
227
@property
228
def has_inverse(self) -> bool:
229
"""Check if transformation has an inverse operation."""
230
231
@property
232
def accuracy(self) -> float | None:
233
"""Get transformation accuracy in meters."""
234
235
@property
236
def area_of_use(self) -> AreaOfUse | None:
237
"""Get the area of use for the transformation."""
238
239
@property
240
def remarks(self) -> str | None:
241
"""Get remarks about the transformation."""
242
243
@property
244
def scope(self) -> str | None:
245
"""Get the scope of the transformation."""
246
247
@property
248
def operations(self) -> tuple[CoordinateOperation, ...] | None:
249
"""Get available transformation operations."""
250
251
@property
252
def is_network_enabled(self) -> bool:
253
"""Check if network access is enabled for grid downloads."""
254
255
@property
256
def source_crs(self) -> CRS:
257
"""Get the source coordinate reference system."""
258
259
@property
260
def target_crs(self) -> CRS:
261
"""Get the target coordinate reference system."""
262
263
def get_last_used_operation(self) -> "Transformer":
264
"""
265
Get the last used transformation operation.
266
267
Returns:
268
Transformer representing the last used operation
269
270
Raises:
271
ProjError: If no operation has been used yet
272
"""
273
```
274
275
### Transformer Export and Serialization
276
277
Export transformer definitions to various formats for interoperability and persistence.
278
279
```python { .api }
280
class Transformer:
281
def to_proj4(self, version: ProjVersion = ProjVersion.PROJ_5) -> str:
282
"""
283
Export transformation as PROJ.4 string.
284
285
Args:
286
version: PROJ version for compatibility
287
288
Returns:
289
PROJ.4 string representation
290
291
Raises:
292
ProjError: If transformation cannot be represented as PROJ.4
293
"""
294
295
def to_wkt(self, version: WktVersion = WktVersion.WKT2_2019, pretty: bool = False) -> str:
296
"""
297
Export transformation as WKT string.
298
299
Args:
300
version: WKT version to use
301
pretty: Whether to format with indentation
302
303
Returns:
304
WKT string representation
305
306
Raises:
307
ProjError: If transformation cannot be represented as WKT
308
"""
309
310
def to_json(self, pretty: bool = False, indentation: int = 2) -> str:
311
"""
312
Export transformation as JSON string.
313
314
Args:
315
pretty: Whether to format with indentation
316
indentation: Spaces for indentation
317
318
Returns:
319
JSON string representation
320
"""
321
322
def to_json_dict(self) -> dict:
323
"""
324
Export transformation as JSON dictionary.
325
326
Returns:
327
Dictionary containing JSON representation
328
"""
329
330
def is_exact_same(self, other: Any) -> bool:
331
"""
332
Check if two transformers are exactly the same.
333
334
Args:
335
other: Another Transformer object
336
337
Returns:
338
True if transformers are identical, False otherwise
339
"""
340
```
341
342
### Transformation Groups and Selection
343
344
Work with multiple transformation options and select optimal transformations for specific requirements.
345
346
```python { .api }
347
class TransformerGroup:
348
"""Group of transformers with different accuracy and area constraints."""
349
350
def __init__(
351
self,
352
crs_from: Any,
353
crs_to: Any,
354
always_xy: bool = False,
355
area_of_interest: AreaOfInterest | None = None,
356
**kwargs
357
) -> None:
358
"""
359
Create group of available transformers.
360
361
Args:
362
crs_from: Source CRS
363
crs_to: Target CRS
364
always_xy: Force x,y axis order
365
area_of_interest: Area constraint
366
**kwargs: Additional parameters
367
"""
368
369
@property
370
def transformers(self) -> list[Transformer]:
371
"""Get list of available transformers ordered by accuracy."""
372
373
@property
374
def unavailable_operations(self) -> list[CoordinateOperation]:
375
"""Get list of operations that are unavailable (missing grids, etc.)."""
376
377
@property
378
def best_available(self) -> Transformer:
379
"""Get the most accurate available transformer."""
380
381
def download_grids(self, verbose: bool = False) -> bool:
382
"""
383
Download transformation grids for unavailable operations.
384
385
Args:
386
verbose: Print download progress
387
388
Returns:
389
True if all grids downloaded successfully, False otherwise
390
"""
391
```
392
393
### Global Transformation Functions
394
395
Standalone functions for coordinate transformation without explicitly creating Transformer objects.
396
397
```python { .api }
398
def transform(
399
p1: Proj | Transformer | CRS | str,
400
p2: Proj | Transformer | CRS | str,
401
x,
402
y,
403
z=None,
404
tt=None,
405
radians: bool = False,
406
errcheck: bool = False,
407
always_xy: bool = False,
408
**kwargs
409
) -> tuple:
410
"""
411
Transform coordinates between projections.
412
413
Args:
414
p1: Source projection/CRS
415
p2: Target projection/CRS
416
x: X coordinates
417
y: Y coordinates
418
z: Z coordinates, optional
419
tt: Time coordinates, optional
420
radians: Coordinates in radians
421
errcheck: Check for errors
422
always_xy: Force x,y axis order
423
**kwargs: Additional parameters
424
425
Returns:
426
Tuple of transformed coordinates
427
428
Raises:
429
ProjError: If transformation fails
430
"""
431
432
def itransform(
433
p1: Proj | Transformer | CRS | str,
434
p2: Proj | Transformer | CRS | str,
435
points,
436
switch: bool = False,
437
time_3rd: bool = False,
438
radians: bool = False,
439
errcheck: bool = False,
440
always_xy: bool = False,
441
**kwargs
442
) -> Iterator:
443
"""
444
Transform iterator of points between projections.
445
446
Args:
447
p1: Source projection/CRS
448
p2: Target projection/CRS
449
points: Iterable of coordinate points
450
switch: Switch x,y order
451
time_3rd: Third coordinate is time
452
radians: Coordinates in radians
453
errcheck: Check for errors
454
always_xy: Force x,y axis order
455
**kwargs: Additional parameters
456
457
Yields:
458
Transformed coordinate tuples
459
460
Raises:
461
ProjError: If transformation fails
462
"""
463
```
464
465
## Usage Examples
466
467
### Basic Coordinate Transformation
468
469
```python
470
from pyproj import Transformer, CRS
471
472
# Create transformer between WGS84 and UTM Zone 33N
473
wgs84 = CRS.from_epsg(4326)
474
utm_33n = CRS.from_epsg(32633)
475
476
transformer = Transformer.from_crs(wgs84, utm_33n, always_xy=True)
477
478
# Transform single point
479
lon, lat = 10.0, 60.0
480
x, y = transformer.transform(lon, lat)
481
print(f"UTM: {x:.2f}, {y:.2f}")
482
483
# Transform multiple points
484
points = [(10.0, 60.0), (11.0, 61.0), (12.0, 62.0)]
485
transformed = list(transformer.itransform(points))
486
print(f"Transformed points: {transformed}")
487
```
488
489
### Transformation with Area of Interest
490
491
```python
492
from pyproj import Transformer, AreaOfInterest
493
494
# Define area of interest for better transformation accuracy
495
aoi = AreaOfInterest(
496
west_lon_degree=-180,
497
south_lat_degree=-90,
498
east_lon_degree=180,
499
north_lat_degree=90
500
)
501
502
transformer = Transformer.from_crs(
503
'EPSG:4326',
504
'EPSG:3857', # Web Mercator
505
area_of_interest=aoi,
506
accuracy=1.0 # Require 1 meter accuracy
507
)
508
509
# Transform coordinates
510
lon, lat = -74.0, 40.7 # New York
511
x, y = transformer.transform(lon, lat)
512
print(f"Web Mercator: {x:.2f}, {y:.2f}")
513
```
514
515
### Bounding Box Transformation
516
517
```python
518
from pyproj import Transformer
519
520
transformer = Transformer.from_crs('EPSG:4326', 'EPSG:32633')
521
522
# Transform bounding box
523
west, south, east, north = 9.0, 59.0, 11.0, 61.0
524
bbox_utm = transformer.transform_bounds(west, south, east, north)
525
print(f"UTM bounding box: {bbox_utm}")
526
527
# Transform with densification for curved boundaries
528
bbox_dense = transformer.transform_bounds(
529
west, south, east, north,
530
densify_pts=50 # Add more points along edges
531
)
532
```
533
534
### Inverse Transformation
535
536
```python
537
from pyproj import Transformer, TransformDirection
538
539
transformer = Transformer.from_crs('EPSG:4326', 'EPSG:32633')
540
541
# Forward transformation
542
lon, lat = 10.0, 60.0
543
x, y = transformer.transform(lon, lat)
544
545
# Inverse transformation
546
lon_back, lat_back = transformer.transform(
547
x, y,
548
direction=TransformDirection.INVERSE
549
)
550
print(f"Original: {lon:.6f}, {lat:.6f}")
551
print(f"Recovered: {lon_back:.6f}, {lat_back:.6f}")
552
```
553
554
### Working with Transformation Groups
555
556
```python
557
from pyproj import TransformerGroup
558
559
# Get all available transformations
560
group = TransformerGroup('EPSG:4326', 'EPSG:32633')
561
562
print(f"Available transformers: {len(group.transformers)}")
563
print(f"Best accuracy: {group.best_available.accuracy} meters")
564
565
# Check for unavailable operations
566
if group.unavailable_operations:
567
print(f"Unavailable: {len(group.unavailable_operations)} operations")
568
# Download missing grids if needed
569
success = group.download_grids(verbose=True)
570
print(f"Grid download success: {success}")
571
572
# Use the best available transformer
573
transformer = group.best_available
574
x, y = transformer.transform(10.0, 60.0)
575
```
576
577
### Pipeline Transformations
578
579
```python
580
from pyproj import Transformer
581
582
# Create transformer from PROJ pipeline
583
pipeline = "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart +ellps=WGS84"
584
transformer = Transformer.from_pipeline(pipeline)
585
586
# Transform geographic to geocentric
587
lon, lat, height = 10.0, 60.0, 100.0
588
x, y, z = transformer.transform(lon, lat, height)
589
print(f"Geocentric: {x:.2f}, {y:.2f}, {z:.2f}")
590
```
591
592
### Global Transform Functions
593
594
```python
595
from pyproj import transform, itransform
596
597
# Direct transformation without creating Transformer
598
x, y = transform('EPSG:4326', 'EPSG:32633', 10.0, 60.0, always_xy=True)
599
600
# Transform multiple points
601
points = [(10.0, 60.0), (11.0, 61.0)]
602
transformed = list(itransform('EPSG:4326', 'EPSG:32633', points, always_xy=True))
603
```
604
605
## Types
606
607
```python { .api }
608
# Supporting classes
609
class TransformerMaker:
610
"""Abstract base class for transformer creation strategies."""
611
612
class TransformerFromCRS(TransformerMaker):
613
"""Creates transformers from CRS objects."""
614
615
class TransformerFromPipeline(TransformerMaker):
616
"""Creates transformers from PROJ pipelines."""
617
618
# Wrapper classes
619
class TransformerUnsafe:
620
"""Transformer wrapper that skips error checking for performance."""
621
622
# Enumerations used in transformations
623
class TransformDirection(Enum):
624
FORWARD = "FORWARD"
625
INVERSE = "INVERSE"
626
IDENT = "IDENT"
627
```