Fiona reads and writes spatial data files
88
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.
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."""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}")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
"""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)# 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)# 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 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'
})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)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-fionadocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10