Geospatial Data
To use this notebook you must have a (free) FEO account, available here. You may then install the feo-client library, if necessary, and then use the package to log in. You can also run notebook in a Colab notebook via the badge below.
%pip install "feo-client[geo]"
from feo.client.auth import login
login()
Geospatial Data¶
Object-oriented interface for Vector Features and Geometries via the Python client
FEO comprises a wide variety of geospatial data, covering vector and raster data types. Vector types include node geometries
, hydrobasins
, exclusive economic zones
and protected areas
. Each of these exists as a Collection
that can be browsed and searched via several methods.
In this notebook we will gather some vector data for a node, namely:
- The node geometry
- The protected areas intersecting the node geometry
from feo.client import Features, Node
# Let's use Bali
node_name = "Bali"
nodes = Node.search(node_name)
try:
bali = nodes[0]
print(bali)
except IndexError:
raise IndexError(f"No nodes found for {node_name}")
For a more detailed exploration of Nodes see the Nodes notebook.
# Access the node's geometry
bali_geom = bali.geometry
type(bali_geom)
The geometry
property is a Geometry
class. This class exposes the geometry type and its (longitude, latitude) coordinates as properties.
# The Bali geometry is a MultiPolygon; it comprises multiply polygon geometries
bali_geom.type
# The coordinates list is a nested list of coordinate pairs that define the geometry
bali_geom.coordinates[0]
# E.g. convert to GeoJSON string
print(bali_geom.to_geojson()[:100], "...}") # sliced to limit output
A shapely geometry provides access to some core geospatial operations and, in notebooks, can be rendered as an image.
# Create shapely geometry
bali_geom_shply = bali_geom.to_shape()
centroid = bali_geom_shply.centroid
print(
"Bali centroid:", f"\tLON: {centroid.x:0.6f}", f"\tLAT: {centroid.y:0.6f}", sep="\n"
)
bali_geom_shply
Search for other vector data¶
FEO provides access to a range of supplimentary geospatial datasets. In this example we search for Protected Areas within Bali. The FEO catalogue will continue to grow!
# Search for Protected Areas
pa_feats = Features.search(collection_id="biodiversity-wdpa", geometry=bali_geom)
pa_feats
is a Features
objects; a collection of features, each with properties and a geometry
# How many protected areas were returned?
len(pa_feats.features)
# Examine a feature
ft = pa_feats.features[0]
ft.properties
# Render its geometry
ft.geometry.to_shape()
If you have the geo
dependencies installed you can convert the Features
object to a GeoDataFrame
gdf = pa_feats.to_geodataframe()
gdf
Visualise the data¶
Features
and Geometry
objects both have GeoJSON representations, allowing for easy interoperability with other geospatial tools. In this example, we use folium
to plot an interactive map of Bali and its protected areas.
%pip install folium
import folium
from folium.features import GeoJson
# Define the layer styles
bali_style = {"fillColor": "#f2ff00", "color": "#f2ff00"}
pa_style = {"fillColor": "#000000", "color": "#000000"}
bali_geom_shply = (
bali_geom.to_shape()
) # convert our Geometry object to a shapely object
map_center = bali_geom_shply.centroid # access the centroid using the shape property
# Configure the map
map = folium.Map(location=(map_center.y, map_center.x), zoom_start=10)
# Add vector data to the map via the GeoJSON interface
map.add_child(
GeoJson(bali_geom.to_geojson(), name="Bali", style_function=lambda x: bali_style)
)
map.add_child(
GeoJson(
pa_feats.to_geojson(),
name="World Database on Protected Areas",
style_function=lambda x: pa_style,
popup=folium.GeoJsonPopup(fields=["name", "designation"]),
)
)
folium.LayerControl().add_to(map)
map