CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-fiona

Fiona reads and writes spatial data files

88

1.10x
Overview
Eval results
Files

crs.mddocs/

Coordinate Reference Systems

Comprehensive CRS handling including creation from various formats (EPSG, WKT, PROJ), conversion between formats, and validation. The CRS system is essential for proper geospatial data processing, ensuring that coordinates are interpreted correctly and can be transformed between different projections and datums.

Capabilities

CRS Class

The main interface for working with coordinate reference systems. Supports creation from and conversion to multiple formats including EPSG codes, WKT strings, and PROJ parameter dictionaries.

class CRS:
    def __init__(self, initialdata=None, **kwargs):
        """
        Create a CRS from PROJ parameters or other CRS data.
        
        Parameters:
        - initialdata: dict or CRS, initial CRS data
        - kwargs: dict, additional PROJ parameters
        """
    
    @classmethod
    def from_epsg(cls, code):
        """
        Create CRS from EPSG authority code.
        
        Parameters:
        - code: int, EPSG code (e.g., 4326 for WGS84)
        
        Returns:
        CRS instance
        
        Raises:
        - CRSError: If EPSG code is invalid or not found
        """
    
    @classmethod 
    def from_wkt(cls, wkt, morph_from_esri_dialect=False):
        """
        Create CRS from Well-Known Text string.
        
        Parameters:
        - wkt: str, WKT representation of CRS
        - morph_from_esri_dialect: bool, convert from ESRI WKT format
        
        Returns:
        CRS instance
        
        Raises:
        - CRSError: If WKT string is invalid
        """
    
    @classmethod
    def from_dict(cls, initialdata=None, **kwargs):
        """
        Create CRS from PROJ parameter dictionary.
        
        Parameters:
        - initialdata: dict, PROJ parameters
        - kwargs: dict, additional PROJ parameters
        
        Returns:
        CRS instance
        """
    
    @classmethod
    def from_string(cls, value, morph_from_esri_dialect=False):
        """
        Create CRS from various string formats.
        
        Parameters:
        - value: str, CRS string (PROJ4, WKT, EPSG:code, etc.)
        - morph_from_esri_dialect: bool, convert from ESRI format
        
        Returns:
        CRS instance
        
        Raises:
        - CRSError: If string format is not recognized
        """
    
    @classmethod
    def from_user_input(cls, value, morph_from_esri_dialect=False):
        """
        Create CRS from flexible user input.
        
        Parameters:
        - value: str, dict, or CRS, various input formats
        - morph_from_esri_dialect: bool, convert from ESRI format
        
        Returns:
        CRS instance
        """
    
    @classmethod
    def from_authority(cls, auth_name, code):
        """
        Create CRS from authority name and code.
        
        Parameters:
        - auth_name: str, authority name (e.g., 'EPSG', 'ESRI')
        - code: str or int, authority code
        
        Returns:
        CRS instance
        """
    
    def to_dict(self, projjson=False):
        """
        Convert CRS to PROJ parameter dictionary.
        
        Parameters:
        - projjson: bool, return PROJJSON format if True
        
        Returns:
        dict: PROJ parameters or PROJJSON
        """
    
    def to_wkt(self, morph_to_esri_dialect=False, version=None):
        """
        Convert CRS to Well-Known Text string.
        
        Parameters:
        - morph_to_esri_dialect: bool, convert to ESRI WKT format
        - version: WktVersion, WKT format version
        
        Returns:
        str: WKT representation
        """
    
    def to_epsg(self, confidence_threshold=70):
        """
        Convert CRS to EPSG code if possible.
        
        Parameters:
        - confidence_threshold: int, minimum confidence for match (0-100)
        
        Returns:
        int or None: EPSG code if found
        """
    
    def to_authority(self, confidence_threshold=70):
        """
        Convert CRS to authority name and code.
        
        Parameters:
        - confidence_threshold: int, minimum confidence for match
        
        Returns:
        tuple or None: (authority_name, code) if found
        """
    
    def to_string(self):
        """
        Convert CRS to string representation.
        
        Returns:
        str: PROJ4 or WKT string representation
        """
    
    @property
    def data(self):
        """Get PROJ4 dictionary representation."""
    
    @property
    def wkt(self):
        """Get OGC WKT representation."""
    
    @property
    def is_valid(self):
        """Test if CRS is valid."""
    
    @property
    def is_geographic(self):
        """Test if CRS is geographic (lat/lon)."""
    
    @property
    def is_projected(self):
        """Test if CRS is projected."""
    
    @property
    def is_epsg_code(self):
        """Test if CRS is defined by an EPSG code."""
    
    @property
    def linear_units(self):
        """Get short name for linear units."""
    
    @property
    def linear_units_factor(self):
        """Get linear units and conversion factor to meters."""

Usage Examples

from fiona.crs import CRS

# Create CRS from EPSG code (most common)
wgs84 = CRS.from_epsg(4326)  # WGS84 geographic
utm_zone_10n = CRS.from_epsg(32610)  # UTM Zone 10N
web_mercator = CRS.from_epsg(3857)  # Web Mercator

print(f"WGS84 is geographic: {wgs84.is_geographic}")
print(f"UTM is projected: {utm_zone_10n.is_projected}")

# Create from PROJ4 dictionary
proj_dict = {
    'proj': 'lcc',  # Lambert Conformal Conic
    'lat_1': 33,    # Standard parallel 1
    'lat_2': 45,    # Standard parallel 2  
    'lat_0': 39,    # Latitude of origin
    'lon_0': -96,   # Central meridian
    'x_0': 0,       # False easting
    'y_0': 0,       # False northing
    'datum': 'NAD83',
    'units': 'm',
    'no_defs': True
}
lcc_crs = CRS.from_dict(proj_dict)

# Create from WKT string
wkt_string = '''
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563]],
    PRIMEM["Greenwich",0],
    UNIT["degree",0.0174532925199433]]
'''
wkt_crs = CRS.from_wkt(wkt_string)

# Create from various string formats
epsg_string_crs = CRS.from_string('EPSG:4326')
proj4_string_crs = CRS.from_string('+proj=longlat +datum=WGS84 +no_defs')

# Flexible user input (automatically detects format)
user_crs = CRS.from_user_input('EPSG:4326')  # EPSG code
user_crs2 = CRS.from_user_input(wgs84)       # Existing CRS object
user_crs3 = CRS.from_user_input(proj_dict)   # PROJ dict

# Convert between formats
crs = CRS.from_epsg(4326)

# Convert to different representations
proj_dict = crs.to_dict()
wkt_repr = crs.to_wkt()
epsg_code = crs.to_epsg()
authority = crs.to_authority()

print(f"PROJ dict: {proj_dict}")
print(f"WKT: {wkt_repr}")
print(f"EPSG: {epsg_code}")
print(f"Authority: {authority}")

# Check CRS properties
print(f"Linear units: {utm_zone_10n.linear_units}")
print(f"Units factor: {utm_zone_10n.linear_units_factor}")
print(f"Is valid: {crs.is_valid}")

CRS Utility Functions

Helper functions for working with coordinate reference systems and coordinate order conventions.

def epsg_treats_as_latlong(input_crs):
    """
    Test if CRS should use latitude/longitude coordinate order.
    
    Parameters:
    - input_crs: CRS or CRS-like object
    
    Returns:
    bool: True if lat/lon order should be used
    """

def epsg_treats_as_northingeasting(input_crs):
    """
    Test if CRS should use northing/easting coordinate order.
    
    Parameters:
    - input_crs: CRS or CRS-like object
    
    Returns:
    bool: True if northing/easting order should be used
    """

Usage Examples

from fiona.crs import CRS, epsg_treats_as_latlong, epsg_treats_as_northingeasting

# Check coordinate order conventions
wgs84 = CRS.from_epsg(4326)
utm = CRS.from_epsg(32610)

print(f"WGS84 uses lat/lon order: {epsg_treats_as_latlong(wgs84)}")
print(f"UTM uses northing/easting: {epsg_treats_as_northingeasting(utm)}")

# This affects how you should interpret coordinates
if epsg_treats_as_latlong(wgs84):
    # Coordinates should be interpreted as (latitude, longitude)
    coords = (37.7749, -122.4194)  # San Francisco
else:
    # Coordinates should be interpreted as (longitude, latitude)  
    coords = (-122.4194, 37.7749)

Common CRS Examples

Geographic Coordinate Systems

# World Geodetic System 1984 (most common for GPS data)
wgs84 = CRS.from_epsg(4326)

# North American Datum 1983
nad83 = CRS.from_epsg(4269)

# European Terrestrial Reference System 1989
etrs89 = CRS.from_epsg(4258)

Projected Coordinate Systems

# Web Mercator (used by Google Maps, OpenStreetMap)
web_mercator = CRS.from_epsg(3857)

# UTM zones (Universal Transverse Mercator)
utm_zone_10n = CRS.from_epsg(32610)  # UTM Zone 10N (California)
utm_zone_18n = CRS.from_epsg(32618)  # UTM Zone 18N (New York)

# State Plane systems (US)
ca_state_plane = CRS.from_epsg(2227)  # California Zone III

# National grids
british_national_grid = CRS.from_epsg(27700)  # UK

Custom Projections

# Custom Lambert Conformal Conic
custom_lcc = CRS.from_dict({
    'proj': 'lcc',
    'lat_1': 33,
    'lat_2': 45, 
    'lat_0': 39,
    'lon_0': -96,
    'x_0': 0,
    'y_0': 0,
    'datum': 'NAD83',
    'units': 'm'
})

# Custom Albers Equal Area
custom_albers = CRS.from_dict({
    'proj': 'aea',
    'lat_1': 29.5,
    'lat_2': 45.5,
    'lat_0': 37.5,
    'lon_0': -96,
    'x_0': 0,
    'y_0': 0,
    'datum': 'NAD83',
    'units': 'm'
})

Integration with Collections

CRS objects integrate seamlessly with Fiona collections for reading and writing geospatial data:

import fiona
from fiona.crs import CRS

# Reading: CRS is automatically parsed from data file
with fiona.open('input.shp', 'r') as collection:
    crs = collection.crs
    print(f"Input CRS: {crs}")
    print(f"Is geographic: {crs.is_geographic}")

# Writing: Specify CRS for output file
output_crs = CRS.from_epsg(4326)
schema = {
    'geometry': 'Point',
    'properties': {'name': 'str'}
}

with fiona.open('output.geojson', 'w', driver='GeoJSON',
                crs=output_crs, schema=schema) as collection:
    feature = {
        'geometry': {'type': 'Point', 'coordinates': [-122.4, 37.8]},
        'properties': {'name': 'San Francisco'}
    }
    collection.write(feature)

# CRS reprojection (requires separate transform step)
with fiona.open('input_utm.shp', 'r') as input_col:
    input_crs = input_col.crs
    output_crs = CRS.from_epsg(4326)  # Convert to WGS84
    
    with fiona.open('output_wgs84.geojson', 'w', 
                    driver='GeoJSON', crs=output_crs,
                    schema=input_col.schema) as output_col:
        
        for feature in input_col:
            # Transform coordinates (see transforms.md for details)
            transformed_feature = transform_feature(feature, input_crs, output_crs)
            output_col.write(transformed_feature)

Error Handling

CRS operations can encounter various errors that should be handled appropriately:

from fiona.errors import CRSError

try:
    # Invalid EPSG code
    invalid_crs = CRS.from_epsg(99999)
except CRSError as e:
    print(f"Invalid EPSG code: {e}")

try:
    # Invalid WKT string
    invalid_wkt = CRS.from_wkt("INVALID WKT STRING")
except CRSError as e:
    print(f"Invalid WKT: {e}")

try:
    # CRS that cannot be converted to EPSG
    custom_crs = CRS.from_dict({'proj': 'custom_projection'})
    epsg_code = custom_crs.to_epsg()
    if epsg_code is None:
        print("CRS cannot be matched to an EPSG code")
except CRSError as e:
    print(f"CRS conversion error: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-fiona

docs

cli.md

collection-management.md

crs.md

data-model.md

environment.md

file-io.md

index.md

schema.md

transforms.md

utilities.md

tile.json