Black Lives Matter. Please consider donating to Black Girls Code today.
Dash Enterprise delivers an incredible 21x cost savings 💸Download the e-book!

📣 Initial release of Dash Deck, a library for rendering webgl & 3D maps with pydeck and deck.gl in Dash

Today, we are releasing the initial version of Dash Deck, a library for building 3D interactive maps and graphical visualizations directly in Dash. Built on top of deck.gl, it offers seamless support for maps built with pydeck, and also support deck.gl’s JSON API (which you can try out here).

If you want to directly dive into the demos and the code, check out this Dash Deck Explorer, which will look like this:

You can also check our the source code in the Github repository. It also contains an extensive Readme to help you get started, as well as tips & tricks for more advanced Dash Deck use cases.


If you haven’t used pydeck before, you can check out the Getting Started section. In essence, it ports deck.gl into Jupyter, allowing you to create maps like the ones in the explorer shown above.

First, you need to ensure that your environment variable MAPBOX_ACCESS_TOKEN is a valid environment variable (more details in the Readme). Then, you can install pydeck like this:

pip install pydeck

Inside a notebook, you can build a 3D interactive map with pydeck using the following code (borrowed from the official docs):

import os
import pydeck as pdk

mapbox_api_token = os.getenv("MAPBOX_ACCESS_TOKEN")

# 2014 locations of car accidents in the UK
UK_ACCIDENTS_DATA = ('https://raw.githubusercontent.com/uber-common/'
                     'deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv')

# Define a layer to display on a map
layer = pdk.Layer(
    'HexagonLayer',
    UK_ACCIDENTS_DATA,
    get_position=['lng', 'lat'],
    auto_highlight=True,
    elevation_scale=50,
    pickable=True,
    elevation_range=[0, 3000],
    extruded=True,                 
    coverage=1)

# Set the viewport location
view_state = pdk.ViewState(
    longitude=-1.415,
    latitude=52.2323,
    zoom=6,
    min_zoom=5,
    max_zoom=15,
    pitch=40.5,
    bearing=-27.36)

# Render
r = pdk.Deck(layers=[layer], initial_view_state=view_state, mapbox_key=mapbox_api_token)
r.to_html('demo.html')

and you will get a map similar to what is shown in this demo.

If you want to use it in Dash, you need to first install the library:

pip install dash-deck

Then, create the component:

import dash_deck
deck_component = dash_deck.DeckGL(
    r.to_json(), id="deck-gl", tooltip=True, mapboxKey=r.mapbox_key
)

Now, you can directly use this deck_component inside your Dash app, and interact with it using callbacks!


This initial version (v0.0.1) already contains 28 demos, mostly ported from Pydeck. They can handle many complex scenarios, including beta-features like lighting and globe views. Nonetheless, the API is still at an early stage and it has not been extensively integrated in the Dash ecosystem. If you find any bugs, would like to add new features, or contribute a new demo, feel free to open an issue! From there, we would be happy to work with you to fix them and provide a better experience for the Dash community.

For any feedback, suggestion, ideas, feel free to share them in this thread. We are happy to know what you are planning to build with the library, and don’t forget to share what you’ve made with Dash Deck in the #show-and-tell thread!

6 Likes

Hi, I am trying to merge a deck compoment into a dcc.Graph, but I get an error. Is it possible?

mapa_movilidad = dash_deck.DeckGL(
r.to_json(),
id=“deck-gl”,
mapboxKey=r.mapbox_key
)

html.Div(
id=“graph-container”,
children=dcc.Loading(
className=“graph-wrapper”,
children=dcc.Graph(id=“graph-mov”, figure=mapa_movilidad),
style={“display”: “default”},
),
),

Hi! dash_deck.DeckGL is a stand-alone component that is not related to dcc.Graph. I’d recommend to directly feed it as a children of html.Div:

mapa_movilidad = dash_deck.DeckGL(
r.to_json(),
id=“deck-gl”,
mapboxKey=r.mapbox_key
)

html.Div(
id=“graph-container”,
children=dcc.Loading(
className=“graph-wrapper”,
children=mapa_movilidad
style={“display”: “default”},
),
),

Hi xhlu,
I have some questions about applying dash_deck for building dashboards

If i want to set pydeck_graphs into a container, what kind of css would be fit for it.


for example, the pic above, i want my dash-deck graph fit in a proper container.

I have tried some css styles but they all ended as covering up everything. Below is the code and outcome. (its copied from dash gallary: https://github.com/plotly/dash-sample-apps/tree/master/apps/dash-oil-and-gas)

html.Div(
[
html.Div(
id=“deck_component”,
children=dcc.Loading(
className=“pretty_container five columns”,
children=deck_component,
style={“display”: “default”},
))

Please let me know what shall I do, what shall I read.

I really like this powerful plugin, its broderning the boundaries of Dash.

Sincerely,
Kris.

Hi Kris,

Thanks for raising this issue! It is indeed a pretty difficult one.

Behind the scene, Dash Deck passes a style prop to deck.gl, and lets it handle it. This means that you can directly modify the CSS style of the component itself, as shown in this example.

You will find that we define the component in the following way:

        dash_deck.DeckGL(
            r.to_json(),
            id="deck-gl",
            tooltip=True,
            mapboxKey=r.mapbox_key,
            style={"width": "55vw", "height": "75vh"},
        )

Which will look like this:

Now, what if you want to style a html.Div, where one of the children is this component? Here’s the logical way to do this:

        html.Div(
            dash_deck.DeckGL(
                r.to_json(),
                id="deck-gl",
                tooltip=True,
                mapboxKey=r.mapbox_key
            ),
            style={
                'width': '55vw',
                'height': '75vh',
                'display': 'inline'
            }
        )

note I’m adding inline display since html Div would usually be a block display

You will notice that the style was not correctly passed to the child component:

One way is to set the style of Deck GL to inherit the style of its parent:

        html.Div(
            dash_deck.DeckGL(
                r.to_json(),
                id="deck-gl",
                tooltip=True,
                mapboxKey=r.mapbox_key,
                style={'height': 'inherit', 'width': 'inherit'}
            ),
            style={
                'width': '55vw',
                'height': '75vh',
                'display': 'inline'
            }
        )

careful! only inherit the ones you need, don’t do “all”: “inherit” since it might cause problems

Ok, now it shows up correctly:

This will also work with CSS classes. For example, if you define this class in your assets/styles.css:

.superCoolClass {
    width: 55vw;
    height: 75vh;
    display: inline;
}

And assign that class to the parent div:

        html.Div(
            dash_deck.DeckGL(
                r.to_json(),
                id="deck-gl",
                tooltip=True,
                mapboxKey=r.mapbox_key,
                style={'height': 'inherit', 'width': 'inherit'}
            ),
            className='superCoolClass'
        )

You will get the exact same result.


Hope this helps! I am not very familiar with the oil and gas demo, so I went with this example since it’s easier to reproduce and more generic.

1 Like

Returned to leave a thank message!

It worked! Now all know dash+dash_deck can achieve my exact goal,the only way for me to go from here is up.

I will definately share this with my friends.

2 Likes

@xhlu When I use your example, everything works fine. But if I download the UK_ACCIDENTS_DATA csv:

UK_ACCIDENTS_DATA = ('https://raw.githubusercontent.com/uber-common/'
                     'deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv')
s=requests.get(UK_ACCIDENTS_DATA).content
c=pd.read_csv(io.StringIO(s.decode('utf-8')))

layer = pdk.Layer(
    'HexagonLayer',
    c,
    get_position=['lng', 'lat'],
    auto_highlight=True,
    elevation_scale=50,
    pickable=True,
    elevation_range=[0, 3000],
    extruded=True,
    coverage=1)

I get the following React Error in the console:

Warning: Cannot update a component from inside the function body of a different component.
    in n (created by CheckedComponent)
    in CheckedComponent (created by BaseTreeContainer)
    in ComponentErrorBoundary (created by BaseTreeContainer)
    in BaseTreeContainer (created by Context.Consumer)
    in Unknown (created by BaseTreeContainer)
    in div (created by u)
    in u (created by CheckedComponent)
    in CheckedComponent (created by BaseTreeContainer)
    in ComponentErrorBoundary (created by BaseTreeContainer)
    in BaseTreeContainer (created by Context.Consumer)
    in Unknown (created by UnconnectedContainer)
    in div (created by UnconnectedGlobalErrorContainer)
    in div (created by GlobalErrorOverlay)
    in div (created by GlobalErrorOverlay)
    in GlobalErrorOverlay (created by DebugMenu)
    in div (created by DebugMenu)
    in DebugMenu (created by UnconnectedGlobalErrorContainer)
    in div (created by UnconnectedGlobalErrorContainer)
    in UnconnectedGlobalErrorContainer (created by withRadiumContexts(UnconnectedGlobalErrorContainer))
    in withRadiumContexts(UnconnectedGlobalErrorContainer) (created by ConnectFunction)
    in ConnectFunction (created by UnconnectedContainer)
    in UnconnectedContainer (created by ConnectFunction)
    in ConnectFunction (created by UnconnectedAppContainer)
    in UnconnectedAppContainer (created by ConnectFunction)
    in ConnectFunction (created by AppProvider)
    in Provider (created by AppProvider)
    in AppProvider

Note that I did this exercise because I was originally trying to do it with another DataFrame, and I was getting this error, so I tried reproducing it with your example

Any idea what’s happening?

This is weird. I’ve used pydeck and Dash-deck with various dataframes and it worked well.

Have you tried:

  • pd.read_csv(url) instead of pd.read_csv(io.StringIO(s.decode('utf-8')))?
  • run this example inside a notebook with pydeck? Code is here.
  • c.head() and compare that with the actual CSV to see if it looks the same?

I had tried your first and third point before answering your post. I’ll try to do it on pydeck and let you know. thanks!