Working with Spatial Data: Single vs Tile
There are 2 main ways to work with spatial data in Fused:
Single UDF
Single UDFs are the default behavior in Fused. The UDF is run 1 time with the current viewport bounds.

Characteristics:
- 1 Single UDF is called on the entire Map Viewport
- Panning Map does NOT re-run the UDF
- "Results" Tab shows the output of the unique UDF called
Single HTTPS Call
A Single UDF is called like any other UDF via a HTTPS request:
https://www.fused.io/.../run/file?format=csv
Or via the Fused Python SDK:
fused.run("single_udf")
There are 2 types of Spatial Single UDFs:
Single (Viewport)
Will prioritize the current MAP VIEWPORT bounds, regardless of the bounds parameter.
@fused.udf
def udf(bounds: fused.types.Bounds = [-74.38,40.32,-73.31,41.29]):
    print(bounds) # This will be the current MAP VIEWPORT bounds, regardless of the `bounds` parameter
    return bounds
Single (Parameter)
Will use the bounds parameter, regardless of the current MAP VIEWPORT bounds.
@fused.udf
def udf(bounds: fused.types.Bounds = [-74.38,40.32,-73.31,41.29]):
    print(bounds) # This will be the `bounds` parameter, regardless of the current MAP VIEWPORT bounds
    return bounds
Example UDF
- Get Isochrone
- Returns an isochrone (how far a person cal walk / drive) polygon for a given point
 
Tile UDF
Tile UDFs tile the users viewport into a grid of smaller tiles and running a UDF for each.

Characteristics:
- Multiple Tile UDFs are called to cover the current Map Viewport
- Panning Map re-runs the UDF for each tile
- "Results" Tab shows the output of the latest tile called
Tile HTTPS Call
A Tile UDF is called by passing Web mercator XYZ tiles through the HTTPS request
Two ways to call the HTTPS endpoint:
1. Dynamic tile server (for map applications)
https://www.fused.io/.../run/tiles/{z}/{x}/{y}?format=png
Use this template URL in mapping libraries {z}/{x}/{y} gets automatically replaced with tile coordinates as users pan and zoom.
Example use cases:
2. Specific tile call
# Calls a single tile - San Francisco center at zoom 13
https://www.fused.io/.../run/tiles/13/1316/3169?format=png
Use this to fetch data for one specific tile location.
Or via the Fused Python SDK:
# With bounds parameter
fused.run("tile_udf", bounds=bounds)
# With x, y, z parameters
fused.run("tile_udf", x=1, y=2, z=3)
Example UDF
- Overture Maps Example
- Manipulate all the buildings from the Overture Maps dataset by leveraging Fused ingestion
 
- Landsat Tile Example
- Returns NDVI tile computed on the fly from Landsat data
 
Comparing Single and Tile UDFs
| Feature | Single UDF | Tile UDF | 
|---|---|---|
| UDF Calls | 1 | Multiple | 
| Parameters | bounds(Optional) | boundsorx,y,z | 
| Map rendering | Static | Dynamic | 
| HTTP Call | Single Call | Tile Server calls or Single Call (specific tile) | 
| Runtime Tab display | Unique output of the UDF called | Output of the latest tile called | 
| Use Case | Small static data | Calling large dataset through tile server | 
bounds
bounds is simply a list of 4 coordinates representing the bounds of a geometry. The 4 coordinates represent [xmin, ymin, xmax, ymax] of the bounds.
In Fused it is defined with the fused.types.Bounds type:
@fused.udf
def udf(bounds: fused.types.Bounds=None):
    print(bounds)
>>> [-1.52244399, 48.62747869, -1.50004107, 48.64359255]
bounds to GeoDataFrame
Converting bounds (list of 4 coordinates) to a GeoDataFrame:
- Fused common function
- shapely & geopandas
@fused.udf
def udf(bounds: fused.types.Bounds=None):
    common = fused.load("https://github.com/fusedio/udfs/tree/fbf5682/public/common/")
    return common.bounds_to_gdf(bounds)
@fused.udf
def udf(bounds: fused.types.Bounds=None):
    import shapely
    import geopandas as gpd
    box = shapely.box(*bounds)
    return gpd.GeoDataFrame(geometry=[box], crs=4326)
Legacy types
Legacy types that might still appear in older UDFs.
[Legacy] fused.types.Tile
This is a geopandas.GeoDataFrame with x, y, z, and geometry columns.
@fused.udf
def udf(bounds: fused.types.Tile=None):
    print(bounds)
>>>      x    y   z                                           geometry
>>> 0  327  790  11  POLYGON ((-122.0 37.0, -122.0 37.1, -122.1 37.1, -122.1 37.0, -122.0 37.0))
[Legacy] fused.types.TileGDF
This behaves the same as fused.types.Tile.
[Legacy] fused.types.ViewportGDF
This is a geopandas.geodataframe.GeoDataFrame with a geometry column corresponding to the Polygon geometry of the current viewport in the Map.
@fused.udf
def udf(bbox: fused.types.ViewportGDF=None):
    print(bbox)
    return bbox
>>>  geometry
>>>  POLYGON ((-122.0 37.0, -122.0 37.1, -122.1 37.1, -122.1 37.0, -122.0 37.0))
[Legacy] bbox object
UDFs defined using the legacy keyword bbox are automatically now mapped to bounds. Please update your code to use bounds directly as this alias will be removed in a future release.