#!/usr/bin/env python # coding: utf-8 # ## How to use Earth Engine with pydeck for 3D visualization # # ### Requirements # - [earthengine-api](https://github.com/google/earthengine-api): a Python client library for calling the Google Earth Engine API. # - [pydeck](https://pydeck.gl/index.html): a WebGL-powered framework for visual exploratory data analysis of large datasets. # - [pydeck-earthengine-layers](https://github.com/UnfoldedInc/earthengine-layers/tree/master/py): a pydekc wrapper for Google Earth Engine. For documentation please visit this [website](https://earthengine-layers.com/). # - [Mapbox API key](https://pydeck.gl/installation.html#getting-a-mapbox-api-key): you will need this add basemap tiles to pydeck. # # ### Installation # # - conda create -n deck python # - conda activate deck # - conda install mamba -c conda-forge # - mamba install earthengine-api pydeck pydeck-earthengine-layers -c conda-forge # - jupyter nbextension install --sys-prefix --symlink --overwrite --py pydeck # - jupyter nbextension enable --sys-prefix --py pydeck # ### Using ee.Image with pydeck # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee # Initialize Earth Engine library try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() # Create an Earth Engine object image = ee.Image('CGIAR/SRTM90_V4') # Define Earth Engine visualization parameters vis_params = { "min": 0, "max": 4000, 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'] } # Create a pydeck EarthEngineLayer object, using the Earth Engine object and # desired visualization parameters ee_layer = EarthEngineLayer(image, vis_params) # Define the initial viewport for the map view_state = pdk.ViewState(latitude=37.7749295, longitude=-122.4194155, zoom=10, bearing=0, pitch=45) # Create a Deck instance, and display in Jupyter r = pdk.Deck(layers=[ee_layer], initial_view_state=view_state) r.show() # Adding multiple Earth Engine images # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee # Initialize Earth Engine library try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() # Add Earth Engine dataset image = ee.Image('USGS/SRTMGL1_003') hillshade = ee.Terrain.hillshade(image) demRGB = image.visualize(**{ 'min': 0, 'max': 4000, 'bands': ['elevation'], 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], 'opacity': 0.5 }) hillshadeRGB = hillshade.visualize(**{'bands': ['hillshade']}) blend = hillshadeRGB.blend(demRGB) ee_layer = EarthEngineLayer(blend, {}) # Define the initial viewport for the map view_state = pdk.ViewState(latitude=37.7749295, longitude=-122.4194155, zoom=10, bearing=0, pitch=45) # Create a Deck instance, and display in Jupyter r = pdk.Deck(layers=[ee_layer], initial_view_state=view_state) r.show() # ### Using ee.ImageCollection with pydeck # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee # Initialize Earth Engine library try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() # Initialize an ee.ImageColllection object referencing the Global Forecast System dataset image_collection = ee.ImageCollection('NOAA/GFS0P25') # Select images from December 22, 2018 image_collection = image_collection.filterDate('2018-12-22', '2018-12-23') # Choose the first 24 images in the ImageCollection image_collection = image_collection.limit(24) # Select a single band to visualize image_collection = image_collection.select('temperature_2m_above_ground') # Style temperature values between -40C and 35C, # with lower values shades of blue, purple, and cyan, # and higher values shades of green, yellow, and red vis_params = { 'min': -40.0, 'max': 35.0, 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'] }; layer = EarthEngineLayer( image_collection, vis_params, animate=True, id="global_weather") view_state = pdk.ViewState(latitude=36, longitude=10, zoom=1) r = pdk.Deck( layers=[layer], initial_view_state=view_state ) # layer.visible = True # layer.opacity = 0.2 r.show() # ### Using ee.FeatureCollection (points) with pydeck # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() # Load the FeatureCollection table = ee.FeatureCollection("WRI/GPPD/power_plants") # Create color palette fuel_color = ee.Dictionary({ 'Coal': '000000', 'Oil': '593704', 'Gas': 'BC80BD', 'Hydro': '0565A6', 'Nuclear': 'E31A1C', 'Solar': 'FF7F00', 'Waste': '6A3D9A', 'Wind': '5CA2D1', 'Geothermal': 'FDBF6F', 'Biomass': '229A00' }) # List of fuels to add to the map fuels = ['Coal', 'Oil', 'Gas', 'Hydro', 'Nuclear', 'Solar', 'Waste', 'Wind', 'Geothermal', 'Biomass'] def add_style(point): """Computes size from capacity and color from fuel type. Args: - point: (ee.Geometry.Point) A Point Returns: (ee.Geometry.Point): Input point with added style dictionary """ size = ee.Number(point.get('capacitymw')).sqrt().divide(10).add(2) color = fuel_color.get(point.get('fuel1')) return point.set('styleProperty', ee.Dictionary({'pointSize': size, 'color': color})) # Make a FeatureCollection out of the power plant data table pp = ee.FeatureCollection(table).map(add_style) # Create a layer for each fuel type layers = [] for fuel in fuels: layer = EarthEngineLayer( pp.filter(ee.Filter.eq('fuel1', fuel)).style(styleProperty='styleProperty', neighborhood=50), id=fuel, opacity=0.65, ) layers.append(layer) view_state = pdk.ViewState(latitude=36, longitude=-53, zoom=3) r = pdk.Deck( layers=layers, initial_view_state=view_state ) r.show() # ### Using ee.FeatureCollection (lines) with pydeck # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() # 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)) lines_layer = EarthEngineLayer( lines, {'color': 'red'}, id="tracks", ) points_layer = EarthEngineLayer( points, {'color': 'green'}, id="points", ) 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() # In[ ]: from pydeck_earthengine_layers import EarthEngineLayer import pydeck as pdk import ee try: ee.Initialize() except Exception as e: ee.Authenticate() ee.Initialize() dataset = ee.FeatureCollection('FAO/GAUL/2015/level0') countries = dataset.style( fillColor='b5ffb4', color='00909F', width=3 ) layer = EarthEngineLayer(countries, id="international_boundaries") view_state = pdk.ViewState(latitude=36, longitude=10, zoom=3) r = pdk.Deck( layers=[layer], initial_view_state=view_state ) r.show()