This is an example of using pydeck to visualize a Google Earth Engine FeatureCollection
of lines.
To install and run this notebook locally, refer to the Pydeck Earth Engine documentation.
To see this example online, view the JavaScript version.
Import required packages:
from pydeck_earthengine_layers import EarthEngineLayer
import pydeck as pdk
import ee
Using Earth Engine requires authentication. If you don't have a Google account approved for use with Earth Engine, you'll need to request access. For more information and to sign up, go to https://signup.earthengine.google.com/.
try:
ee.Initialize()
except Exception as e:
ee.Authenticate()
ee.Initialize()
This example uses the NOAA Atlantic Hurricane catalog, a dataset with positions of hurricanes and related attributes from 1851 to 2018. In this example we'll look only at hurricanes in 2017.
# Hurricane tracks and points for 2017.
hurricanes = ee.FeatureCollection('NOAA/NHC/HURDAT2/atlantic')
year = '2017'
points = hurricanes.filter(ee.Filter.date(ee.Date(year).getRange('year')))
# Find all of the hurricane ids.
def get_id(point):
return ee.Feature(point).get('id')
storm_ids = points.toList(1000).map(get_id).distinct()
# Create a line for each hurricane.
def create_line(storm_id):
pts = points.filter(ee.Filter.eq('id', ee.String(storm_id)))
pts = pts.sort('system:time_start')
line = ee.Geometry.LineString(pts.geometry().coordinates())
feature = ee.Feature(line)
return feature.set('id', storm_id)
lines = ee.FeatureCollection(storm_ids.map(create_line))
Now we're ready to create the Pydeck layer. The EarthEngineLayer
makes this simple. Just pass the Earth Engine object to the class.
lines_layer = EarthEngineLayer(
lines,
{'color': 'red'},
id="tracks",
)
points_layer = EarthEngineLayer(
points,
{'color': 'black'},
id="points",
)
Then just pass this layer to a pydeck.Deck
instance, and call .show()
to create a map:
view_state = pdk.ViewState(latitude=36, longitude=-53, zoom=3)
r = pdk.Deck(
layers=[points_layer, lines_layer],
initial_view_state=view_state
)
r.show()
Note that by default maps rendered with the EarthEngineLayer
are rendered as rasters. That is, the vector geometries are converted into PNG images on Google's servers before downloading. deck.gl and pydeck excel at vector rendering, where the geometries themselves are downloaded.
Let's plot these layers again, but as a vector dataset, instead of a raster dataset
lines_layer = EarthEngineLayer(
lines,
# Download vector geometries
as_vector=True,
# GeoJsonLayer styling properties
get_line_color=[100, 100, 200],
getLineWidth=1000,
lineWidthMinPixels=3,
id="tracks",
)
points_layer = EarthEngineLayer(
points,
# Download vector geometries
as_vector=True,
# Properties from FeatureCollection to include in download
selectors=['name', 'max_wind_kts', 'datetime'],
# GeoJsonLayer styling properties
get_fill_color=[255, 125, 0, 180],
pointRadiusMinPixels=2,
# Point radius scales with wind speed
getRadius='properties.max_wind_kts * 500',
getLineColor=[255, 255, 255],
pointRadiusUnits='meters',
lineWidthMinPixels=0.5,
stroked=True,
id="points",
pickable=True,
auto_highlight=True,
)
view_state = pdk.ViewState(latitude=36, longitude=-53, zoom=3)
r = pdk.Deck(
layers=[lines_layer, points_layer],
initial_view_state=view_state
)
r.show()
We can also use pydeck's event handling capabilities to render information about the feature that is clicked.
Important: pydeck's event handling is new in the 0.5.0 release. To upgrade, run:
pip install -U 'pydeck>=0.5.0-beta.1'
Here we render text information about a hurricane whenever a point on the map is clicked. This uses the on_click
callback that Pydeck exposes.
from ipywidgets import HTML
from dateutil.parser import parse
from datetime import datetime
text = HTML(value='Click on a point')
def create_text(payload):
properties = payload['data']['object']['properties']
name = properties['name']
wind_speed = properties['max_wind_kts']
time = parse(properties['datetime']).strftime('%c')
return f'Name: {name} <br/> Max Wind Speed: {wind_speed} knots <br/> Date: {time}'
def on_click(widget_instance, payload):
text.value = create_text(payload)
r.deck_widget.on_click(on_click)
display(text)
r.show()
After clicking on a point, you can also get the data underlying that point using the selected_data
attribute, e.g.:
r.selected_data
Should show you something like:
[{'geometry': {'coordinates': [-73.09999665539969, 33.900003621748546],
'type': 'Point'},
'properties': {'datetime': '2017-09-26T18:00:00',
'max_wind_kts': 65,
'name': 'MARIA'},
'type': 'Feature'}]