Enhance your data with GERS IDs
The Global Entity Reference System (GERS) is a framework that structures, encodes, and matches map data to a shared universal reference within Overture. GERS helps organizations identify and reference their own datasets with standard identifiers to Overture data to help unify datasets.
In this blog post we show how to create simple endpoints with Fused UDFs to enrich a dataset with GERS IDs. We'll use the Overture Building footprints to first enrich a polygon with GERS IDs then another one to look-up metadata for a specified GERS ID.
The benefit of GERSβ
When third-party dataset is spatially matched to an Overture feature it's "enriched" with that feature's GERS ID and becomes "GERS-enabled". This makes it easy to associate it by ID to any other GERS-enabled dataset.
gers_id buliding_name
0 08b2a1072534cfff020018b8a6efde22 James A. Farley Building
1 08b2a100d2cb6fff02000821de8bdff1 Pennsylvania Station
For example, a municipal government with a dataset of building footprints for local offices, coffee shops, and museums could match those entities to a GERS ID. This would enable the government to easily join its data other "GERS-enabled" datasets to enrich them with additional information such as insurance data, historical property values, restaurant reviews, fire risk, or rooftop solar potential.
Create a UDF to enrich a polygon with GERS IDsβ
We can create a UDF that takes in a polygon and returns a GERS ID. This UDF will spatially match the polygon to Overture Buildings and return the GERS ID of the building that intersects the polygon. This is useful for enriching a dataset with GERS IDs.
Users can design and preview the workflow interactively, allowing them to test assumptions and visualize their effect. Parameters can be adjusted, and the output can be previewed before running the UDF on the entire dataset.
import json
aoi = json.dumps({"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-73.9945443706057,40.751205998161026],[-73.9945443706057,40.749882643934455],[-73.99222917395902,40.749882643934455],[-73.99222917395902,40.751205998161026],[-73.9945443706057,40.751205998161026]]],"type":"Polygon"}}]})
@fused.udf
def udf(bbox: fused.types.TileGDF=aoi):
import geopandas as gpd
# 1. Convert bbox to GeoDataFrame
if isinstance(bbox, str):
bbox = gpd.GeoDataFrame.from_features(json.loads(bbox))
# 2. Load Overture Buildings that intersect the given bbox centroid
gdf = fused.utils.Overture_Maps_Example.get_overture(bbox=bbox.geometry.centroid, overture_type='building', min_zoom=10)
# How many Overture buildings fall within the bbox centroid?
print("Buildings in centroid: ", len(gdf))
# 3. Rule to set only one GERS on the input polygon
bbox['id'] = gdf.id.values[0]
return bbox
Create an HTTP endpointβ
With Fused, it's easy to turn your UDF into an HTTP endpoint. This enables you to run the UDF it programmatically via HTTP requests to integrate the functionality into various workflows and applications.
This endpoint runs a public UDF with the code above. You can call it with a geojson of a single polygon in the bbox query parameter and it will return a geojson with the polygon and an assigned GERS ID.
https://www.fused.io/server/v1/realtime-shared/UDF_Overture_Buildings_GERS_Enrich/run/file?dtype_out_vector=geojson&bbox={"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-73.9945443706057,40.751205998161026],[-73.9945443706057,40.749882643934455],[-73.99222917395902,40.749882643934455],[-73.99222917395902,40.751205998161026],[-73.9945443706057,40.751205998161026]]],"type":"Polygon"}}]}
Create a UDF to look-up metadata for a GERS IDsβ
We can also create a sample UDF to do a reverse operation: look-up a Building and its attributes by passing a GERS id. A user will be able to pass a GERS id and the UDF will look-up the building and return its geometry along with attributes about the building.
To do this, we create a UDF that takes in a gers_id
parameter. Because the first 16 digits of GERS correspond to an H3 cell, we can use the ID to create a polygon to spatially filter the dataset. It'll bring up any buildings that intersect the H3 cell. Once we have the building, we can easily work with its geometry object and attributes using GeoPandas.
@fused.udf
def udf(gers_id: str='08b2a100d2cb6fff02000821de8bdff1'):
import h3
from shapely.geometry import Polygon
import geopandas as gpd
import pandas as pd
# 1. H3 from GERS
h3_index = gers_id[:16]
print('h3_index', h3_index)
# 2. Polygon from H3
bounds = Polygon([coord[::-1] for coord in h3.cell_to_boundary(h3_index)])
bbox = gpd.GeoDataFrame({'h3_index': [h3_index], 'geometry': [bounds]})
# 3. Load Overture Buildings
gdf = fused.utils.Overture_Maps_Example.get_overture(bbox=bbox, overture_type='building', min_zoom=10)
# 4. Subselect building
gdf = gdf[gdf['id'] == gers_id]
# 5. De-struct the names column
normalized_df = pd.json_normalize(gdf['names'])
gdf = gdf.reset_index(drop=True).join(normalized_df)
return gdf[['id', 'primary', 'subtype', 'class', 'geometry']]
Create an HTTP endpointβ
Here's how you can create and use an HTTP endpoint for your GERS building lookup UDF.
This endpoint returns a CSV table of the building's GERS ID, primary name, subtype, class, and geometry. You can use this endpoint to enrich your dataset with GERS IDs by calling it with a GERS ID query parameter.
https://www.fused.io/server/v1/realtime-shared/UDF_Overture_Buildings_GERS_Lookup/run/file?08b2a100d2cb6fff02000821de8bdff1&dtype_out_vector=csv
For example, you could call this endpoint from a Google Sheet (docs) to enrich a dataset with GERS IDs. This sample Google Sheet returns the enriches the βprimaryβ name column for any given Building GERS. Just drag the formula to apply it to any row below. It works by calling the "GERS lookup" endpoint with a GERS ID query parameter.