Python interface to PROJ library for cartographic projections and coordinate transformations
—
The Proj class provides the legacy PROJ.4 interface for cartographic projections, maintaining backward compatibility while offering direct projection operations. It inherits from Transformer and provides callable projection functionality with additional projection-specific methods.
Create Proj objects for cartographic projections using various initialization methods and parameter formats.
class Proj:
def __init__(
self,
projparams: Any | None = None,
preserve_units: bool = True,
**kwargs
) -> None:
"""
Create a Proj object for cartographic projections.
Args:
projparams: Projection parameters (PROJ string, dict, CRS object, etc.)
preserve_units: Preserve units from projection definition
**kwargs: Additional projection parameters (e.g., proj='utm', zone=33)
Raises:
CRSError: If projection parameters are invalid
ProjError: If projection cannot be created
"""
@property
def definition_string(self) -> str:
"""Get the definition string of the projection."""
@property
def srs(self) -> str:
"""Get the SRS (Spatial Reference System) string."""
@property
def crs(self) -> CRS:
"""Get the associated CRS object."""
@property
def is_latlong(self) -> bool:
"""Check if projection is geographic (latitude/longitude)."""
@property
def is_geocent(self) -> bool:
"""Check if projection is geocentric."""
@property
def has_inverse(self) -> bool:
"""Check if projection has inverse operation."""Perform forward and inverse projection transformations using the callable interface.
class Proj:
def __call__(
self,
longitude,
latitude,
inverse: bool = False,
errcheck: bool = False,
radians: bool = False,
**kwargs
) -> tuple:
"""
Transform coordinates using projection (callable interface).
Args:
longitude: Longitude coordinate(s) or x coordinate(s) for inverse
latitude: Latitude coordinate(s) or y coordinate(s) for inverse
inverse: Perform inverse projection (projected -> geographic)
errcheck: Check for transformation errors
radians: Input/output coordinates in radians
**kwargs: Additional transformation parameters
Returns:
Tuple of transformed coordinates:
- Forward: (x, y) projected coordinates
- Inverse: (lon, lat) geographic coordinates
Raises:
ProjError: If projection transformation fails
"""Analyze projection properties including scale factors, convergence, and distortion characteristics.
class Proj:
def get_factors(
self,
longitude: float,
latitude: float,
radians: bool = False,
errcheck: bool = False
) -> "Factors":
"""
Get projection factors at specified geographic location.
Args:
longitude: Longitude coordinate in degrees (or radians)
latitude: Latitude coordinate in degrees (or radians)
radians: Input coordinates are in radians
errcheck: Check for calculation errors
Returns:
Factors object containing projection distortion information
Raises:
ProjError: If factor calculation fails or point is outside projection domain
"""
def is_exact_same(self, other: "Proj") -> bool:
"""
Check if two Proj objects are exactly the same.
Args:
other: Another Proj object to compare
Returns:
True if projections are identical, False otherwise
"""Methods for backward compatibility with older PROJ.4 workflows and coordinate system conversion.
class Proj:
def to_latlong_def(self) -> str | None:
"""
Get latitude/longitude definition string.
Returns:
PROJ definition string for corresponding geographic CRS,
or None if projection doesn't have a clear geographic equivalent
Note:
Legacy method for PROJ.4 compatibility
"""
def to_latlong(self) -> "Proj":
"""
Create corresponding geographic (lat/long) projection.
Returns:
Proj object for geographic coordinates using same datum/ellipsoid
Raises:
ProjError: If geographic equivalent cannot be determined
"""Detailed projection distortion analysis for cartographic quality assessment and scale calculations.
class Factors:
"""Projection factors and distortion information at a specific point."""
@property
def meridional_scale(self) -> float:
"""Scale factor along meridian (north-south direction)."""
@property
def parallel_scale(self) -> float:
"""Scale factor along parallel (east-west direction)."""
@property
def areal_scale(self) -> float:
"""Areal (area) scale factor."""
@property
def angular_distortion(self) -> float:
"""Maximum angular distortion in radians."""
@property
def meridian_parallel_angle(self) -> float:
"""Angle between meridian and parallel in radians."""
@property
def meridian_convergence(self) -> float:
"""Meridian convergence angle in radians."""
@property
def tissot_semimajor(self) -> float:
"""Semi-major axis of Tissot indicatrix."""
@property
def tissot_semiminor(self) -> float:
"""Semi-minor axis of Tissot indicatrix."""
def __str__(self) -> str:
"""String representation of projection factors."""from pyproj import Proj
# Create UTM Zone 33N projection
utm = Proj(proj='utm', zone=33, ellps='WGS84')
# Forward transformation: geographic -> projected
lon, lat = 10.0, 60.0
x, y = utm(lon, lat)
print(f"UTM coordinates: {x:.2f}, {y:.2f}")
# Inverse transformation: projected -> geographic
lon_back, lat_back = utm(x, y, inverse=True)
print(f"Geographic coordinates: {lon_back:.6f}, {lat_back:.6f}")
# Check projection properties
print(f"Is geographic: {utm.is_latlong}")
print(f"Has inverse: {utm.has_inverse}")
print(f"Definition: {utm.definition_string}")from pyproj import Proj
# Web Mercator projection
web_mercator = Proj(proj='merc', a=6378137, b=6378137)
# Albers Equal Area projection for continental mapping
albers = Proj(
proj='aea', # Albers Equal Area
lat_1=29.5, # First standard parallel
lat_2=45.5, # Second standard parallel
lat_0=37.5, # Latitude of origin
lon_0=-96, # Central meridian
x_0=0, # False easting
y_0=0, # False northing
ellps='GRS80' # Ellipsoid
)
# Lambert Conformal Conic for regional mapping
lambert = Proj(
proj='lcc',
lat_1=33,
lat_2=45,
lat_0=39,
lon_0=-96,
ellps='WGS84'
)
# Test point
lon, lat = -100.0, 40.0
# Project with different projections
web_merc_xy = web_mercator(lon, lat)
albers_xy = albers(lon, lat)
lambert_xy = lambert(lon, lat)
print(f"Web Mercator: {web_merc_xy}")
print(f"Albers: {albers_xy}")
print(f"Lambert: {lambert_xy}")from pyproj import Proj
# Create projection for analysis
utm = Proj(proj='utm', zone=15, ellps='WGS84')
# Test point in central Texas
lon, lat = -99.0, 31.0
# Get projection factors
factors = utm.get_factors(lon, lat)
print("Projection Distortion Analysis:")
print(f"Meridional scale: {factors.meridional_scale:.6f}")
print(f"Parallel scale: {factors.parallel_scale:.6f}")
print(f"Areal scale: {factors.areal_scale:.6f}")
print(f"Angular distortion: {factors.angular_distortion:.6f} radians")
print(f"Meridian convergence: {factors.meridian_convergence:.6f} radians")
# Calculate distortion percentage
scale_distortion = abs(factors.meridional_scale - 1.0) * 100
area_distortion = abs(factors.areal_scale - 1.0) * 100
print(f"Scale distortion: {scale_distortion:.3f}%")
print(f"Area distortion: {area_distortion:.3f}%")from pyproj import Proj
import numpy as np
# State Plane projection (Texas Central)
texas_central = Proj(
proj='lcc',
lat_1=30.116666667,
lat_2=31.883333333,
lat_0=29.666666667,
lon_0=-100.333333333,
x_0=700000,
y_0=3000000,
ellps='GRS80'
)
# Multiple points across Texas
longitudes = np.array([-99.0, -100.0, -101.0, -98.5])
latitudes = np.array([31.0, 30.5, 31.5, 30.8])
# Transform all points
x_coords, y_coords = texas_central(longitudes, latitudes)
print("Projected coordinates:")
for i, (x, y) in enumerate(zip(x_coords, y_coords)):
print(f"Point {i+1}: {x:.2f}, {y:.2f}")
# Inverse transformation
lons_back, lats_back = texas_central(x_coords, y_coords, inverse=True)
print("Verification (should match input):")
for i, (lon, lat) in enumerate(zip(lons_back, lats_back)):
print(f"Point {i+1}: {lon:.6f}, {lat:.6f}")from pyproj import Proj
# Create projection
utm = Proj(proj='utm', zone=33, ellps='WGS84')
# Get corresponding geographic projection
geo_proj = utm.to_latlong()
print(f"Original projection: {utm.definition_string}")
print(f"Geographic projection: {geo_proj.definition_string}")
print(f"Geographic definition: {utm.to_latlong_def()}")
# Verify geographic properties
print(f"Is geographic: {geo_proj.is_latlong}")
print(f"Same ellipsoid: {utm.ellipsoid == geo_proj.ellipsoid}")from pyproj import Proj
# Create from parameter dictionary
params = {
'proj': 'stere', # Stereographic
'lat_0': 90, # North pole
'lat_ts': 70, # Standard parallel
'lon_0': -45, # Central meridian
'k_0': 0.994, # Scale factor
'x_0': 2000000, # False easting
'y_0': 2000000, # False northing
'ellps': 'WGS84'
}
polar_stereo = Proj(params)
# Test Arctic location
lon, lat = -45.0, 75.0 # Greenland
x, y = polar_stereo(lon, lat)
print(f"Polar stereographic: {x:.2f}, {y:.2f}")
# Access projection parameters
print(f"Definition: {polar_stereo.definition_string}")
print(f"Associated CRS: {polar_stereo.crs.name}")from pyproj import Proj, ProjError
try:
# Valid projection
utm = Proj(proj='utm', zone=33, ellps='WGS84')
# Test point
lon, lat = 10.0, 60.0
x, y = utm(lon, lat, errcheck=True) # Enable error checking
# Point outside valid domain
invalid_lon, invalid_lat = 180.0, 85.0
try:
x_invalid, y_invalid = utm(invalid_lon, invalid_lat, errcheck=True)
except ProjError as e:
print(f"Projection error for invalid point: {e}")
# Test factors at edge of projection
factors = utm.get_factors(15.0, 60.0, errcheck=True) # Near zone edge
if factors.meridional_scale > 1.001:
print("High distortion warning")
except ProjError as e:
print(f"Projection creation failed: {e}")# Global constants from proj.py
pj_list: dict[str, str] # Dictionary of available PROJ operations
# Projection parameters for common ellipsoids (from geod.py)
pj_ellps: dict[str, dict[str, float]] # Ellipsoid parameter dictionary
# Common projection parameter keys
class ProjParams:
"""Common PROJ parameter names and values."""
# Projection types
PROJ_UTM = 'utm'
PROJ_MERCATOR = 'merc'
PROJ_LAMBERT_CONFORMAL_CONIC = 'lcc'
PROJ_ALBERS_EQUAL_AREA = 'aea'
PROJ_TRANSVERSE_MERCATOR = 'tmerc'
PROJ_STEREOGRAPHIC = 'stere'
PROJ_SINUSOIDAL = 'sinu'
PROJ_ROBINSON = 'robin'
# Common ellipsoids
ELLPS_WGS84 = 'WGS84'
ELLPS_GRS80 = 'GRS80'
ELLPS_NAD83 = 'GRS80'
ELLPS_NAD27 = 'clrk66'
# Parameter names
LAT_0 = 'lat_0' # Latitude of origin
LON_0 = 'lon_0' # Central meridian
LAT_1 = 'lat_1' # First standard parallel
LAT_2 = 'lat_2' # Second standard parallel
LAT_TS = 'lat_ts' # True scale latitude
K_0 = 'k_0' # Scale factor
X_0 = 'x_0' # False easting
Y_0 = 'y_0' # False northing
ZONE = 'zone' # UTM zone numberInstall with Tessl CLI
npx tessl i tessl/pypi-pyproj