UCRS - Unified CRS
Stop juggling CRS formats. Start using UCRS.
Working with geospatial data in Python means dealing with different CRS representations:
- pyproj →
pyproj.CRS - cartopy →
cartopy.crs.CRSandcartopy.crs.Projection - GDAL/osgeo →
osgeo.osr.SpatialReference
Converting between these is well-documented but tedious. UCRS provides a single class that accepts any CRS input and seamlessly converts to whatever you need.
Features
- Universal Input: Accepts EPSG codes, WKT, PROJ strings, WKT files, or library-specific CRS objects
- Lazy Conversion: Only imports and converts when you access a specific property
- Cached Results: Conversions are cached - repeated access returns the same object
- Type Safe: Full type annotations for IDE support
- Inheritance: UCRS is a
pyproj.CRS, so it works anywhere pyproj does
Quick Start
from ucrs import UCRS
# Create from any CRS representation
crs = UCRS(4326) # EPSG code
crs = UCRS("EPSG:4326") # EPSG string
crs = UCRS("+proj=longlat +datum=WGS84") # PROJ string
crs = UCRS(wkt_string) # WKT
crs = UCRS(pyproj.CRS.from_epsg(4326)) # pyproj.CRS
crs = UCRS(cartopy.crs.PlateCarree()) # cartopy CRS
crs = UCRS(srs) # osgeo.osr.SpatialReference
crs = UCRS.from_file("path/to/crs.wkt") # WKT from file
# Use as pyproj.CRS (UCRS inherits from it)
crs.to_epsg() # Returns 4326
crs.is_geographic # Returns True
crs.to_wkt() # WKT string
# Convert to other libraries (lazy, cached)
crs.cartopy # Returns cartopy CRS (requires cartopy)
crs.osgeo # Returns SpatialReference (requires GDAL)
Example Use Cases
Working with matplotlib and cartopy:
import matplotlib.pyplot as plt
from ucrs import UCRS
# Create from EPSG code
crs = UCRS(3857) # Web Mercator
# Use in cartopy plot
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection=crs.cartopy)
ax.coastlines()
Converting between GDAL and pyproj:
from osgeo import gdal
from ucrs import UCRS
# Get CRS from GDAL dataset
dataset = gdal.Open("myfile.tif")
gdal_srs = dataset.GetSpatialRef()
# Convert to UCRS
crs = UCRS(gdal_srs)
# Now use pyproj methods
print(f"EPSG: {crs.to_epsg()}")
print(f"Is projected: {crs.is_projected}")
Transforming coordinates:
from pyproj import Transformer
from ucrs import UCRS
wgs84 = UCRS(4326)
web_mercator = UCRS(3857)
# Since UCRS inherits from pyproj.CRS, use it directly
transformer = Transformer.from_crs(wgs84, web_mercator)
x, y = transformer.transform(40.7128, -74.0060) # NYC coordinates
Loading CRS from WKT files:
from pathlib import Path
from ucrs import UCRS
# Many GIS workflows store CRS definitions in .wkt or .prj files
crs = UCRS.from_file("projection.prj") # Shapefile projection file
crs = UCRS.from_file(Path("data/crs.wkt")) # Also accepts Path objects
# Use immediately with any library
print(f"EPSG: {crs.to_epsg()}")
ax.set_projection(crs.cartopy)
dataset.SetProjection(crs.osgeo.ExportToWkt())
How It Works
UCRS inherits from pyproj.CRS, making it a drop-in replacement that works anywhere a pyproj CRS is expected. All conversions follow this pattern:
- Input (any format) →
pyproj.CRS(during initialization) pyproj.CRS→ Output format (via lazy, cached properties)
Since UCRS inherits from pyproj.CRS, you can use all pyproj methods directly. Conversions to cartopy and osgeo are performed lazily when their properties are first accessed, then cached for subsequent use.
Requirements
- Python 3.10+
- pyproj (required)
- cartopy (optional)
- GDAL (optional)
Installation
# Minimal installation (pyproj only)
pip install ucrs
# With cartopy support
pip install ucrs[cartopy]
# With GDAL support
pip install ucrs[gdal]
# With all optional dependencies
pip install ucrs[complete]
License
MIT License - see LICENSE file for details.
Metadata
Release files for ucrs 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ucrs-0.5.1.tar.gz | 8.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ucrs-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.6 kB
Release files / ucrs-0.5.1.tar.gz
| Download URL | ucrs-0.5.1.tar.gz |
|---|---|
| Size | 8.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b8292709ce65d931ff8cfeb1acce4d22b4e8b5538d5452283d03e893e2ccbd8
|
|
BLAKE2b-256 checksum How to use checksums |
fe5aebc4d529e51d9f7c409b36694f049e1cc03e9e67554adc14803d7be04161
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.1 CPython/3.14.3 Linux/6.19.8-arch1-1
|
Release files / ucrs-0.5.1-py3-none-any.whl
| Download URL | ucrs-0.5.1-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f4b756e4dd258acb8beab4ea459bd847a3ad0706fad3a3178fd8014a1f09e409
|
|
BLAKE2b-256 checksum How to use checksums |
b06803ad05d3367643ac92fb4c5ef2cd4372116c5c150f1a86403ae2c0d356c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.1 CPython/3.14.3 Linux/6.19.8-arch1-1
|