Fiona reads and writes spatial data files
88
Fiona's data model is built around GeoJSON-like Python objects that provide an intuitive interface for working with geospatial features. The core classes Feature, Geometry, and Properties represent the fundamental building blocks of vector geospatial data, following GeoJSON conventions while providing additional functionality for validation and manipulation.
Represents a complete geospatial feature with geometry, properties, and optional ID. Features are the primary unit of geospatial data in Fiona, corresponding to rows in a shapefile or individual objects in a GeoJSON file.
class Feature:
def __init__(self, geometry=None, id=None, properties=None, **data):
"""
Create a GeoJSON-like feature.
Parameters:
- geometry: dict or Geometry, the feature's geometry
- id: str or int, unique identifier for the feature
- properties: dict or Properties, feature attributes
- data: dict, additional key-value pairs
"""
@classmethod
def from_dict(cls, ob=None, **kwargs):
"""
Create Feature from dictionary or GeoJSON-like object.
Parameters:
- ob: dict, GeoJSON-like feature dictionary
- kwargs: dict, additional parameters
Returns:
Feature instance
"""
@property
def geometry(self):
"""Get the feature's geometry object."""
@property
def id(self):
"""Get the feature's unique identifier."""
@property
def properties(self):
"""Get the feature's properties/attributes."""
@property
def type(self):
"""Always returns 'Feature'."""from fiona.model import Feature, Geometry, Properties
# Create a point feature
geometry = {'type': 'Point', 'coordinates': [-122.5, 37.5]}
properties = {'name': 'San Francisco', 'population': 875000}
feature = Feature(geometry=geometry, properties=properties, id='sf_001')
print(f"Feature type: {feature.type}")
print(f"Feature ID: {feature.id}")
print(f"Geometry type: {feature.geometry['type']}")
print(f"Properties: {feature.properties}")
# Create from dictionary (GeoJSON-like)
feature_dict = {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': [[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]]]
},
'properties': {'area': 4.0, 'name': 'Square'},
'id': 'poly_001'
}
feature = Feature.from_dict(feature_dict)
print(f"Created feature: {feature.id}")
# Access feature components
coords = feature.geometry['coordinates']
area = feature.properties['area']Represents the spatial component of a feature, supporting all OGR geometry types including points, lines, polygons, and multi-geometries with optional Z and M coordinates.
class Geometry:
def __init__(self, coordinates=None, type=None, geometries=None, **data):
"""
Create a GeoJSON-like geometry.
Parameters:
- coordinates: list, coordinate sequences for the geometry
- type: str, geometry type (Point, LineString, Polygon, etc.)
- geometries: list, constituent geometries for GeometryCollection
- data: dict, additional key-value pairs
"""
@classmethod
def from_dict(cls, ob=None, **kwargs):
"""
Create Geometry from dictionary or GeoJSON-like object.
Parameters:
- ob: dict, GeoJSON-like geometry dictionary
- kwargs: dict, additional parameters
Returns:
Geometry instance
"""
@property
def coordinates(self):
"""Get the geometry's coordinate sequence."""
@property
def type(self):
"""Get the geometry type."""
@property
def geometries(self):
"""Get constituent geometries (for GeometryCollection)."""from fiona.model import Geometry
# Create a point geometry
point = Geometry(coordinates=[-122.5, 37.5], type='Point')
print(f"Point coordinates: {point.coordinates}")
# Create a linestring geometry
linestring = Geometry(
coordinates=[[-122.5, 37.5], [-122.4, 37.6], [-122.3, 37.7]],
type='LineString'
)
print(f"LineString length: {len(linestring.coordinates)} points")
# Create a polygon geometry (with exterior ring and hole)
polygon = Geometry(
coordinates=[
# Exterior ring
[[-1, -1], [1, -1], [1, 1], [-1, 1], [-1, -1]],
# Interior ring (hole)
[[-0.5, -0.5], [0.5, -0.5], [0.5, 0.5], [-0.5, 0.5], [-0.5, -0.5]]
],
type='Polygon'
)
# Create from dictionary
geometry_dict = {
'type': 'MultiPoint',
'coordinates': [[-122.5, 37.5], [-122.4, 37.6]]
}
multipoint = Geometry.from_dict(geometry_dict)
print(f"MultiPoint has {len(multipoint.coordinates)} points")
# Create a geometry collection
collection = Geometry(
type='GeometryCollection',
geometries=[
{'type': 'Point', 'coordinates': [0, 0]},
{'type': 'LineString', 'coordinates': [[0, 0], [1, 1]]}
]
)
print(f"Collection has {len(collection.geometries)} geometries")Represents the attribute data associated with a feature, providing a dictionary-like interface for feature properties and metadata.
class Properties:
def __init__(self, **kwds):
"""
Create feature properties mapping.
Parameters:
- kwds: dict, property key-value pairs
"""
@classmethod
def from_dict(cls, mapping=None, **kwargs):
"""
Create Properties from dictionary.
Parameters:
- mapping: dict, property dictionary
- kwargs: dict, additional properties
Returns:
Properties instance
"""from fiona.model import Properties
# Create properties from keyword arguments
props = Properties(name='Golden Gate Bridge', length=2737, year_built=1937)
print(f"Bridge name: {props['name']}")
print(f"Length: {props['length']} meters")
# Create from dictionary
prop_dict = {
'population': 875000,
'area_km2': 121.4,
'country': 'USA',
'founded': 1776
}
city_props = Properties.from_dict(prop_dict)
# Properties behave like dictionaries
city_props['timezone'] = 'PST'
print(f"City area: {city_props['area_km2']} km²")
# Iterate over properties
for key, value in city_props.items():
print(f"{key}: {value}")OGR geometry type constants for working with different geometry types programmatically.
class OGRGeometryType(Enum):
"""Enumeration of OGR geometry type constants."""
Unknown = 0
Point = 1
LineString = 2
Polygon = 3
MultiPoint = 4
MultiLineString = 5
MultiPolygon = 6
GeometryCollection = 7
CircularString = 8
CompoundCurve = 9
CurvePolygon = 10
MultiCurve = 11
MultiSurface = 12
Curve = 13
Surface = 14
PolyhedralSurface = 15
TIN = 16
Triangle = 17
NONE = 100
LinearRing = 101
# Z variants (3D)
CircularStringZ = 1008
CompoundCurveZ = 1009
# M variants (measured)
PointM = 2001
LineStringM = 2002
# ZM variants (3D + measured)
PointZM = 3001
LineStringZM = 3002
# 25D variants (legacy 3D)
Point25D = 0x80000001
LineString25D = 0x80000002from fiona.model import OGRGeometryType
# Check geometry type
geom_type = OGRGeometryType.Point
print(f"Point type value: {geom_type.value}")
# Use in schema definition
schema = {
'geometry': OGRGeometryType.Polygon.name, # 'Polygon'
'properties': {'name': 'str', 'area': 'float'}
}
# Compare geometry types
if geom_type == OGRGeometryType.Point:
print("This is a point geometry")
# Work with 3D geometries
if geom_type.value > 1000 and geom_type.value < 2000:
print("This is a 3D (Z) geometry type")
# Work with measured geometries (M coordinates)
point_m = OGRGeometryType.PointM
if 2000 <= point_m.value < 3000:
print("This geometry has measure (M) coordinates")
# Work with 3D + measured geometries (ZM coordinates)
point_zm = OGRGeometryType.PointZM
if point_zm.value >= 3000:
print("This geometry has both Z and M coordinates")
# Practical geometry type checking
def get_coordinate_dimensions(geom_type):
"""Determine coordinate dimensions from geometry type."""
if geom_type.value >= 3000:
return "ZM (3D + Measured)"
elif geom_type.value >= 2000:
return "M (Measured)"
elif geom_type.value >= 1000:
return "Z (3D)"
elif geom_type.value >= 0x80000000: # 25D variants
return "25D (Legacy 3D)"
else:
return "2D"
# Example usage
for geom_type in [OGRGeometryType.Point, OGRGeometryType.PointM,
OGRGeometryType.Point25D, OGRGeometryType.PointZM]:
dims = get_coordinate_dimensions(geom_type)
print(f"{geom_type.name}: {dims}")Features, geometries, and properties include validation methods to ensure data integrity:
# Validate feature structure
feature = Feature(
geometry={'type': 'Point', 'coordinates': [0, 0]},
properties={'name': 'Origin'}
)
# Validate geometry coordinates
try:
invalid_geom = Geometry(coordinates='invalid', type='Point')
except ValueError as e:
print(f"Validation error: {e}")
# Properties validate against expected types
schema = {'name': 'str', 'count': 'int'}
# This would be validated when writing to a collectionAutomatic conversion between dictionaries and Fiona objects:
# Dict to Fiona objects
feature_dict = {
'type': 'Feature',
'geometry': {'type': 'Point', 'coordinates': [0, 0]},
'properties': {'name': 'Test'}
}
# Automatic conversion when reading from collections
with fiona.open('data.geojson', 'r') as collection:
for feature in collection: # Already Feature-like objects
geom = feature['geometry'] # Dictionary access
props = feature['properties'] # Dictionary access
# Explicit conversion
feature_obj = Feature.from_dict(feature_dict)The data model classes integrate seamlessly with Fiona's Collection interface:
# Writing Feature objects to collections
with fiona.open('output.geojson', 'w', **collection_kwargs) as output:
feature = Feature(
geometry=Geometry(coordinates=[0, 0], type='Point'),
properties=Properties(name='Test Point')
)
output.write(feature) # Automatic serialization
# Reading returns feature-like dictionaries
with fiona.open('input.geojson', 'r') as input_data:
for feature in input_data:
# feature behaves like Feature but is actually a dict
print(f"Geometry: {feature['geometry']['type']}")
print(f"Properties: {feature['properties']}")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