Python interface to PROJ library for cartographic projections and coordinate transformations
—
PyProj provides various utility functions for version information, data management, network configuration, and package diagnostics. These functions support package administration, debugging, and integration with other geospatial workflows.
Access version details for PyProj and underlying PROJ library components.
def show_versions() -> None:
"""
Print comprehensive version information for PyProj and dependencies.
Displays:
- PyProj version
- PROJ library version (runtime and compile-time)
- Python version and platform information
- PROJ data directory location
- Available optional dependencies
Note:
Useful for debugging compatibility issues and system configuration.
Output includes both PyProj package version and underlying PROJ C library version.
"""
# Version constants available at module level
__version__: str # PyProj package version (e.g., "3.7.2")
__proj_version__: str # Runtime PROJ library version
__proj_compiled_version__: str # Compile-time PROJ library version
proj_version_str: str # Alias for __proj_version__ (legacy compatibility)
# Additional version constants (importable but not in __all__)
PROJ_VERSION: tuple[int, ...] # Runtime PROJ library version as tuple
PROJ_VERSION_STR: str # Runtime PROJ library version as string
PROJ_COMPILED_VERSION: tuple[int, ...] # Compile-time PROJ version as tuple
PROJ_COMPILED_VERSION_STR: str # Compile-time PROJ version as stringConfigure and query PROJ data directory locations for grid files and database access.
def get_data_dir() -> str:
"""
Get current PROJ data directory path.
Returns:
Path to PROJ data directory as string
Note:
This directory contains PROJ database and transformation grid files.
Location affects available CRS definitions and transformation accuracy.
"""
def set_data_dir(proj_data_dir: str | Path) -> None:
"""
Set PROJ data directory path.
Args:
proj_data_dir: Path to PROJ data directory
Raises:
DataDirError: If directory doesn't exist or doesn't contain required files
Note:
Changes affect all subsequent PyProj operations.
Directory must contain proj.db and associated PROJ resources.
"""
def append_data_dir(proj_data_dir: str | Path) -> None:
"""
Add additional PROJ data directory to search path.
Args:
proj_data_dir: Path to additional PROJ data directory
Raises:
DataDirError: If directory is invalid
Note:
Enables access to supplementary grid files and custom CRS definitions.
Directories are searched in order they were added.
"""
def get_user_data_dir() -> str:
"""
Get user-specific PROJ data directory.
Returns:
Path to user PROJ data directory
Note:
Location for user-installed grid files and custom definitions.
Automatically created if it doesn't exist.
"""Configure network access for downloading transformation grids and accessing remote PROJ resources.
def is_network_enabled() -> bool:
"""
Check if network access is enabled for PROJ operations.
Returns:
True if network access is enabled, False otherwise
Note:
Network access enables automatic download of transformation grids
and access to CDN-hosted PROJ resources.
"""
def set_network_enabled(enabled: bool) -> None:
"""
Enable or disable network access for PROJ operations.
Args:
enabled: Whether to enable network access
Note:
When enabled, PROJ can download missing transformation grids
and access remote resources for improved accuracy.
Disabled by default for security and performance reasons.
"""
def set_ca_bundle_path(ca_bundle_path: str | None = None) -> None:
"""
Set certificate authority bundle path for network operations.
Args:
ca_bundle_path: Path to CA certificate bundle file,
or None to use system default
Note:
Required for secure HTTPS connections when downloading grids.
Typically needed in restricted network environments.
"""
# Context management (importable but not in __all__)
def set_use_global_context(active: bool | None = None) -> None:
"""
Configure use of global PROJ context vs per-thread contexts.
Args:
active: True to use global context, False for per-thread contexts,
None to query current setting
Note:
Global context can improve performance but may cause thread safety issues.
Per-thread contexts (default) are safer for multithreaded applications.
"""Standalone transformation functions providing direct coordinate conversion without object creation.
def transform(
p1: Proj | Transformer | CRS | str,
p2: Proj | Transformer | CRS | str,
x,
y,
z=None,
tt=None,
radians: bool = False,
errcheck: bool = False,
always_xy: bool = False,
**kwargs
) -> tuple:
"""
Transform coordinates between projections or coordinate systems.
Args:
p1: Source projection, CRS, or definition string
p2: Target projection, CRS, or definition string
x: X coordinate(s) (longitude, easting, etc.)
y: Y coordinate(s) (latitude, northing, etc.)
z: Z coordinate(s) (height, elevation, etc.), optional
tt: Time coordinate(s), optional
radians: Input coordinates are in radians (for geographic CRS)
errcheck: Raise exception on transformation errors
always_xy: Force x,y axis order regardless of CRS definitions
**kwargs: Additional transformation parameters
Returns:
Tuple of transformed coordinates matching input dimensions
Raises:
ProjError: If transformation fails (when errcheck=True)
Note:
Convenience function that creates temporary transformer internally.
For multiple transformations, use Transformer class for better performance.
"""
def itransform(
p1: Proj | Transformer | CRS | str,
p2: Proj | Transformer | CRS | str,
points,
switch: bool = False,
time_3rd: bool = False,
radians: bool = False,
errcheck: bool = False,
always_xy: bool = False,
**kwargs
) -> Iterator:
"""
Transform iterator of coordinate points between projections.
Args:
p1: Source projection, CRS, or definition string
p2: Target projection, CRS, or definition string
points: Iterable of coordinate tuples [(x1,y1), (x2,y2), ...]
switch: Switch x,y coordinate order in input points
time_3rd: Treat third coordinate as time instead of height
radians: Input coordinates are in radians
errcheck: Raise exception on transformation errors
always_xy: Force x,y axis order regardless of CRS definitions
**kwargs: Additional transformation parameters
Yields:
Transformed coordinate tuples
Raises:
ProjError: If transformation fails for any point (when errcheck=True)
Note:
Memory-efficient for processing large coordinate datasets.
Creates temporary transformer internally for each call.
"""Helper classes and functions for data processing and type conversion.
def is_null(value: Any) -> bool:
"""
Check if value represents null/missing data.
Args:
value: Value to check
Returns:
True if value is NaN, None, or represents missing data
Note:
Handles numpy NaN values and Python None consistently.
Used internally for coordinate validation.
"""
def strtobool(value: Any) -> bool:
"""
Convert string-like value to boolean.
Args:
value: String, boolean, or numeric value to convert
Returns:
Boolean interpretation of input value
Raises:
ValueError: If value cannot be interpreted as boolean
Note:
Accepts 'true'/'false', 'yes'/'no', '1'/'0', and variations.
Case-insensitive string comparison.
"""
class NumpyEncoder(json.JSONEncoder):
"""
JSON encoder that handles NumPy data types.
Converts NumPy arrays and scalars to JSON-serializable types.
Used for exporting coordinate data and CRS information as JSON.
"""
def default(self, obj):
"""
Convert NumPy objects to JSON-serializable equivalents.
Args:
obj: Object to serialize
Returns:
JSON-serializable representation of object
"""
class DataType(Enum):
"""Enumeration of data types for internal processing."""
FLOAT = "FLOAT"
LIST = "LIST"
TUPLE = "TUPLE"
ARRAY = "ARRAY"Package-level constants and pre-computed data for common operations.
# Ellipsoid parameter dictionary (from geod.py)
pj_ellps: dict[str, dict[str, float]]
"""
Dictionary of ellipsoid parameters.
Maps ellipsoid names to parameter dictionaries containing:
- 'a': Semi-major axis in meters
- 'b': Semi-minor axis in meters
- 'f': Flattening
- Other ellipsoid-specific parameters
"""
# PROJ operations dictionary (from proj.py)
pj_list: dict[str, str]
"""
Dictionary of available PROJ operations.
Maps operation names to descriptions of available
projections and coordinate operations.
"""
# Geodesic library version (from geod.py)
geodesic_version_str: str
"""Version string of GeographicLib used for geodesic calculations."""
# Functions to access PROJ reference data
def get_ellps_map() -> dict[str, dict[str, float]]:
"""
Get dictionary of ellipsoid parameters from PROJ database.
Returns:
Dictionary mapping ellipsoid names to parameter dictionaries.
Each ellipsoid entry contains keys like 'a', 'b', 'f' for
semi-major axis, semi-minor axis, and flattening.
Note:
This is the source data for the pj_ellps module variable.
"""
def get_prime_meridians_map() -> dict[str, str]:
"""
Get dictionary of prime meridian definitions from PROJ database.
Returns:
Dictionary mapping prime meridian names to their definitions.
Contains standard prime meridians like 'Greenwich', 'Paris', etc.
Note:
Values are PROJ-format definitions of prime meridian locations.
"""
def get_proj_operations_map() -> dict[str, str]:
"""
Get dictionary of available PROJ operations from PROJ database.
Returns:
Dictionary mapping operation names to their descriptions.
Includes projections, transformations, and other coordinate operations.
Note:
This is the source data for the pj_list module variable.
"""import pyproj
from pyproj import show_versions
# Display comprehensive version information
show_versions()
# Access version constants
print(f"PyProj version: {pyproj.__version__}")
print(f"PROJ runtime version: {pyproj.__proj_version__}")
print(f"PROJ compiled version: {pyproj.__proj_compiled_version__}")
# Check geodesic library version
from pyproj.geod import geodesic_version_str
print(f"GeographicLib version: {geodesic_version_str}")from pyproj.datadir import get_data_dir, set_data_dir, append_data_dir, get_user_data_dir
from pathlib import Path
# Check current data directory
current_dir = get_data_dir()
print(f"Current PROJ data directory: {current_dir}")
# Get user data directory
user_dir = get_user_data_dir()
print(f"User PROJ data directory: {user_dir}")
# Add supplementary data directory
# (Useful for custom grids or organization-specific CRS definitions)
try:
custom_data_path = Path("/path/to/custom/proj/data")
if custom_data_path.exists():
append_data_dir(custom_data_path)
print(f"Added custom data directory: {custom_data_path}")
except Exception as e:
print(f"Could not add custom directory: {e}")
# Set different data directory (use with caution)
# set_data_dir("/alternative/proj/data/path")from pyproj.network import is_network_enabled, set_network_enabled, set_ca_bundle_path
# Check network status
network_status = is_network_enabled()
print(f"Network access enabled: {network_status}")
# Enable network for grid downloads
if not network_status:
set_network_enabled(True)
print("Network access enabled for grid downloads")
# Configure CA certificate bundle for secure connections
# set_ca_bundle_path("/path/to/ca-bundle.crt")
# Disable network access for security/offline operation
# set_network_enabled(False)from pyproj import transform, itransform
# Single point transformation
x, y = transform('EPSG:4326', 'EPSG:32633', 10.0, 60.0, always_xy=True)
print(f"Transformed coordinates: {x:.2f}, {y:.2f}")
# Multiple points using iterator
points = [(10.0, 60.0), (11.0, 61.0), (12.0, 62.0)]
transformed = list(itransform('EPSG:4326', 'EPSG:32633', points, always_xy=True))
print("Transformed points:")
for i, (x, y) in enumerate(transformed):
print(f" Point {i+1}: {x:.2f}, {y:.2f}")
# Transform with height coordinates
x, y, z = transform(
'EPSG:4326', # WGS84 geographic
'EPSG:4978', # WGS84 geocentric
10.0, 60.0, 100.0, # lon, lat, height
always_xy=True
)
print(f"Geocentric coordinates: {x:.2f}, {y:.2f}, {z:.2f}")from pyproj.utils import is_null, strtobool, DataType
import numpy as np
# Check for null/missing values
test_values = [0.0, np.nan, None, 42.0, float('inf')]
for value in test_values:
null_status = is_null(value)
print(f"is_null({value}): {null_status}")
# String to boolean conversion
bool_strings = ['true', 'FALSE', 'yes', 'NO', '1', '0', 'on', 'off']
for string in bool_strings:
try:
bool_value = strtobool(string)
print(f"strtobool('{string}'): {bool_value}")
except ValueError as e:
print(f"strtobool('{string}'): Error - {e}")from pyproj.geod import pj_ellps
from pyproj.proj import pj_list
# Explore available ellipsoids
print("Available ellipsoids:")
for name, params in list(pj_ellps.items())[:5]:
a = params.get('a', 'N/A')
b = params.get('b', 'N/A')
print(f" {name}: a={a}, b={b}")
# Explore available projections
print(f"\nTotal PROJ operations: {len(pj_list)}")
print("Sample operations:")
for name, desc in list(pj_list.items())[:5]:
print(f" {name}: {desc}")
# Find specific projection types
utm_ops = {k: v for k, v in pj_list.items() if 'utm' in k.lower()}
print(f"\nUTM-related operations: {len(utm_ops)}")from pyproj.utils import NumpyEncoder
import json
import numpy as np
# Data with NumPy arrays
coordinate_data = {
'points': np.array([[10.0, 60.0], [11.0, 61.0]]),
'elevation': np.array([100.0, 150.0]),
'metadata': {
'crs': 'EPSG:4326',
'accuracy': np.float64(1.5)
}
}
# Serialize with NumPy support
json_string = json.dumps(coordinate_data, cls=NumpyEncoder, indent=2)
print("JSON with NumPy support:")
print(json_string)
# Load back from JSON
loaded_data = json.loads(json_string)
print(f"Loaded points: {loaded_data['points']}")from pyproj import ProjError, CRSError, GeodError, DataDirError
from pyproj import transform
import logging
# Configure logging for debugging
logging.basicConfig(level=logging.DEBUG)
# Error handling examples
try:
# Invalid CRS code
result = transform('INVALID:999', 'EPSG:4326', 0.0, 0.0, errcheck=True)
except (ProjError, CRSError) as e:
print(f"Transformation error: {e}")
try:
# Invalid data directory
from pyproj.datadir import set_data_dir
set_data_dir("/nonexistent/path")
except DataDirError as e:
print(f"Data directory error: {e}")
# Validate transformations with error checking
try:
x, y = transform(
'EPSG:4326',
'EPSG:32633',
180.0, 85.0, # Extreme coordinates
errcheck=True,
always_xy=True
)
print(f"Transformation successful: {x:.2f}, {y:.2f}")
except ProjError as e:
print(f"Transformation failed: {e}")# Exception classes
class ProjError(RuntimeError):
"""General PROJ library errors."""
class CRSError(ProjError):
"""CRS-specific errors (invalid definitions, unsupported operations)."""
class GeodError(RuntimeError):
"""Geodesic computation errors."""
class DataDirError(RuntimeError):
"""PROJ data directory errors (missing files, invalid paths)."""
# Utility enumerations
class DataType(Enum):
"""Data type classification for internal processing."""
FLOAT = "FLOAT"
LIST = "LIST"
TUPLE = "TUPLE"
ARRAY = "ARRAY"
# Type aliases for common patterns
ProjectionLike = Union[Proj, Transformer, CRS, str]
"""Type hint for objects that can be used as projection definitions."""
CoordinateSequence = Union[list, tuple, np.ndarray]
"""Type hint for coordinate data containers."""Install with Tessl CLI
npx tessl i tessl/pypi-pyproj