Concepts¶
pyproj is a Python interface to the PROJ library. Most of what it does comes down to answering two questions about a pair (or triple) of numbers:
Where on the Earth is this? The numbers are only meaningful once you know the Coordinate Reference System (CRS) they belong to. pyproj describes a CRS with the
pyproj.crs.CRSclass.What are these same points in a different CRS? Converting coordinates between two CRSes is a coordinate operation. pyproj does this with the
pyproj.transformer.Transformerclass.
A third helper, pyproj.Geod, answers questions like “how far apart
are these two points?” directly on the curved Earth without picking a
projection at all.
This page explains the ideas behind these classes without much code. The Getting Started page shows how to use the classes themselves and the Glossary defines the terms used throughout the documentation. If you already know what a CRS, a datum, and an EPSG code are, you can skip straight to Getting Started.
Coordinate Reference Systems (CRS)¶
A pair of numbers like (-93.58, 42.03) does not identify a location on its
own. Is it longitude and latitude in degrees? Or is it latitude first? Is it
meters east and north of some origin? On which model of the Earth? A
Coordinate Reference System (CRS) is the description that answers those
questions so that the numbers can be tied to a real place.
A CRS bundles a few things together:
A datum: a model of the shape of the Earth (an ellipsoid) plus how that model is positioned relative to the real Earth. The WGS 84 datum used by GPS is the most common one you will meet.
A coordinate system: which axes there are, what units they use, and what order they come in (see axis order).
For a projected CRS, the projection: the recipe for flattening the curved Earth onto a plane.
The pyproj.crs.CRS class stores all of this and lets you inspect each
part (crs.datum, crs.ellipsoid, crs.axis_info,
crs.coordinate_operation, …).
Geographic CRS¶
A geographic CRS describes positions as angles on the ellipsoid:
longitude and latitude, usually in degrees. No projection is involved. The
best-known example is WGS 84 (EPSG:4326), the datum used by GPS receivers
and many web APIs.
Projected CRS¶
A projected CRS takes a geographic CRS and applies a map projection to
it so that positions become distances on a flat plane, usually in meters.
Working on a plane makes distances, areas, and gridded data much simpler to
handle. Common examples are the UTM zones (for example
EPSG:26917, NAD83 / UTM zone 17N) and Web Mercator (EPSG:3857), the
projection used by most online map tiles.
Every projection distorts something (shapes, areas, distances, or directions) and each one is designed to keep that distortion small over a particular region, its area of use. Using a CRS far outside its area of use gives poor or nonsensical results. PROJ documents the theory in its cartographic projection page and lists every supported projection with pictures in Projections.
Why it matters¶
The same numbers can refer to different places in different CRSes. Two datasets that both report “longitude and latitude” may still disagree by tens of meters if they use different datums. When combining data from different sources, make sure the CRS of each source is known and compatible, transforming the coordinates into one common CRS where necessary.
How a CRS is written down¶
There are several textual ways to describe a CRS, and pyproj accepts all of them. Understanding the three most common ones explains most of what you will see in the examples.
Well-Known Text (WKT)¶
Well-Known Text (WKT) is a standard, human-readable format that spells
out the complete definition of a CRS: its name, datum, ellipsoid, axes,
units, projection parameters, and authority identifiers. It is what
print(crs.to_wkt(pretty=True)) shows you and what most geospatial file
formats and databases store internally. WKT can describe any CRS, including
ones that have no authority code, without losing information. There are two
generations of the format; WKT2 is the current one and is preferred.
PROJ strings (+proj=latlon)¶
A PROJ string is PROJ’s own compact +key=value syntax, for example
+proj=utm +zone=17 +datum=NAD83 or +proj=latlon. The +proj key
names the projection and the remaining keys set its parameters; the available
keys for each projection are documented on the PROJ page for that projection
in Projections. +proj=latlon (an alias of +proj=longlat) is the
special case of “no projection, just longitude and latitude”, so
+proj=latlon and EPSG:4326 describe a very similar CRS.
PROJ strings are convenient for building a CRS by hand, and much of the older documentation and code you will find online uses them. However, they cannot express everything a CRS can contain, so converting a CRS to a PROJ string may silently drop information. Prefer an authority code or WKT for storing or sharing a CRS; see Gotchas/FAQ and the PROJ FAQ for details.
Other forms¶
pyproj also accepts PROJ JSON (a JSON equivalent of WKT), Python dictionaries
of PROJ parameters, and objects from other libraries that have a to_wkt()
method. pyproj.crs.CRS.from_user_input() lists everything that is
accepted, and Getting Started shows each form in use.
Transformations between CRSes¶
A coordinate operation takes coordinates expressed in one CRS and
produces the coordinates of the same physical points in another CRS. In
everyday use any such operation is called a “transformation”, and that is the
sense in which pyproj’s pyproj.transformer.Transformer class is
named. PROJ (following the ISO 19111 standard) reserves the word for one of
two more specific kinds of operation:
A conversion is pure mathematics with an exact answer, such as turning longitude/latitude into UTM meters on the same datum.
A transformation changes datum, for example from NAD27 to WGS 84. Because the relationship between two datums is measured rather than defined, transformations are approximate, have an associated accuracy, and the most accurate ones often rely on transformation grid files that are downloaded separately (see Transformation Grids).
Going between two arbitrary CRSes often involves both kinds, chained
together. When you call Transformer.from_crs(source_crs, target_crs)
pyproj asks PROJ to find the best available chain of operations between the
two CRSes for your area of interest and wraps it in a single
pyproj.transformer.Transformer; the transformer’s repr tells you
which kind it ended up with (Conversion Transformer or
Transformation Transformer). The PROJ page on
geodetic transformation explains what
happens underneath.
Axis order¶
One surprise for newcomers is axis order. Many CRS definitions,
including EPSG:4326, officially list latitude first and longitude
second, while many software packages and file formats (GeoJSON, for example)
assume longitude/latitude (x/y).
pyproj follows the official definition by default, so
transformer.transform(lat, lon) is correct for EPSG:4326 input. If you
prefer to always work in x/y (longitude/latitude) order, create the
transformer with always_xy=True. The Gotchas/FAQ page has more on this.
Geodesic calculations¶
Sometimes you do not want a projection at all; you want the distance between
two points or the area of a polygon on the curved surface of the Earth.
These are geodesic calculations and pyproj provides them through
pyproj.Geod, which only needs to know the ellipsoid (for example
WGS 84). See PROJ’s geodesic calculations page for the
background.
Further reading¶
PROJ’s own quick start and cartographic projection pages.