Giter VIP home page Giter VIP logo

dash-deck's Introduction

Dash Deck

Dash Deck is a proof of concept library for building 3D interactive maps and graphical visualizations directly in Dash. Built on top of deck.gl, it supports maps built using pydeck and deck.gl’s JSON API.

demo

  • Try it in the Dash Deck Explorer
  • Read the announcement
  • Get it on PyPi, which has the latest version published by Plotly.
  • Get it on conda-forge, a community maintained package index. To ensure that this version is up to date, please verify on the PyPi page.

Getting started

Quickstart (Python)

First install this library:

pip install dash-deck

then, define your map using the deck.gl JSON API:

data = {
    "description": "A minimal deck.gl example rendering a circle with text",
    "initialViewState": {"longitude": -122.45, "latitude": 37.8, "zoom": 12},
    "layers": [
        {
            "@@type": "TextLayer",
            "data": [{"position": [-122.45, 37.8], "text": "Hello World"}],
        },
    ],
}

finally, create your component and add it to your layout:

import dash
import dash_deck
import dash_html_components as html

deck_component = dash_deck.DeckGL(data=data, id="deck-gl")

app = dash.Dash(__name__)
app.layout = html.Div(deck_component)

For a full example, see usage.py. To find examples of the JSON API, see the deck.gl playground.

Quickstart (R)

First, install the package from GitHub (the package is not yet available via CRAN):

remotes::install_github("plotly/dash-deck")

then, define your map using the deck.gl JSON API:

deck_data <- list(
    "description" = "A minimal deck.gl example rendering a circle with text",
    "initialViewState" = list("longitude" = -122.45, "latitude" = 37.8, "zoom" = 12),
    "layers" = list(
        list(
            "@@type" = "TextLayer",
            "data" = list(list("position" = list(-122.45, 37.8), "text" = "Hello World"))
        )
    )
)

finally, create your component and add it to your layout:

library(dash)
library(dashDeck)
library(dashHtmlComponents)

deck_component <- deckGL(data=deck_data, id="deck-gl")

app <- Dash$new()

app$layout(htmlDiv(deck_component))

pydeck integrations

Make sure you have pydeck installed:

pip install pydeck

then, define a layer using pdk and run it:

import pydeck as pdk

layer = pdk.Layer(
    "TextLayer",
    [{"position": [-122.45, 37.8], "text": "Hello World"}]
)

# Render
r = pdk.Deck(layers=[layer])

then, convert it to JSON and add it to your layout:

import dash
import dash_deck
import dash_html_components as html

deck_component = dash_deck.DeckGL(r.to_json(), id="deck-gl")

app = dash.Dash(__name__)
app.layout = html.Div(deck_component)

To learn how to use pydeck, read more in the official documentations. You can find a complete example in usage-pdk.py.

Mapbox tokens

Make sure that you have created a Mapbox access token, and export it as an environment variable. For example, you can add the following line to your .bashrc:

export MAPBOX_ACCESS_TOKEN="pk.ey..."

Then, inside your app, define retrieve and define it as mapbox_api_token:

import os
mapbox_api_token = os.getenv("MAPBOX_ACCESS_TOKEN")

When you define your component, simply pass it to DeckGL as an argument:

...

r = pdk.Deck(...)

deck_component = dash_deck.DeckGL(r.to_json(), id="deck-gl", mapboxKey=mapbox_api_token)

...

Running the demos

The Pydeck team has already created many amazing demos, which are shown in their doc gallery. We ported them for Dash Deck with minor modifications. You can read the docstring of each usage-<name>.py file, you will be able to find the source code of the original demo. You can also try them directly in the Dash Deck Explorer.

First, make sure you clone the project:

git clone https://github.com/plotly/dash-deck.git
cd dash-deck/

Create and activate a conda env:

conda create -n deck-demos python=3.7
conda activate deck-demos

Or a venv (make sure your python3 is 3.6+):

python3 -m venv venv
source venv/bin/activate  # for Windows, use venv\Scripts\activate.bat

Install all the dev and demo requirements:

pip install -r requirements.txt
pip install -r demos/requirements.txt

You can now run the demo you want to try (replace <name> with the layer type you want to try):

python demos/usage-<name>.py

Tips and Tricks

Side-by-side or overlapping maps with Views

If you want to show multiple maps side-by-side, you need to specify a "view" dict (when constructing your map dictionary) or pdk.View (which is given to pdk.Deck). For example, you would add the following parameter to your pdk.Deck:

map_view = pdk.View("MapView", width="75%", height="600px", controller=True)
r = pdk.Deck(..., views=[map_view])

or add the following dictionary to your data dictionary:

data = {
    "layer": ...,
    ...,
    "views": [{"@@type": "MapView", "width": "75%", "height": "600px"}],
}
deck_component = dash_deck.DeckGL(data, id="deck-gl")

See demos/usage-views.py for manually creating a view dictionary, and demos/usage-pdk-views.py for manually creating a pdk.View.

Use DeckGL style for custom styling (width, height, color)

You can also directly modify dash_deck.DeckGL's style:

deck_component = dash_deck.DeckGL(..., style={"width": "50vw", "height": "50vh"})

The style prop is useful for directly changing the CSS of Dash Deck. For example, you can also change the background-color. See demos/usage-style-prop.py for an example.

Callbacks and events

Various events are exposed as read-only props, and you can use them as Input or State to your callbacks. They are disabled by default in order to maximize performance for cases where a lot of data are passed through setProps.

To use them, either set enableEvents to True, or give a list with the gestures that you want to enable. For example, the two following lines are equivalent:

dash_deck.DeckGL(r.to_json(), enableEvents=True)
dash_deck.DeckGL(r.to_json(), enableEvents=['click', 'hover', 'dragStart', 'dragEnd'])

Two types of events are available. Info is the picking info describing the object being clicked and Event is the original gesture event (in JSON). You can read more about Info in the deck.gl developer guide.

The following props are available:

  • clickEvent, clickInfo
  • dragStartEvent, dragStartInfo
  • dragEndEvent, dragEndInfo
  • hoverEvent, hoverInfo

For an example of using events, please see demos/usage-events.py.

Using the tooltip

The pydeck tooltip can be used in Dash Deck. Moreover, rather than passing it to pdk.Deck, you will need to pass it to dash_deck.DeckGL:

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

You can also customize your tooltip:

deck_component = dash_deck.DeckGL(
    r.to_json(),
    id="deck-gl",
    tooltip={
        "html": ...,
        "style": ...
    }
)

To learn more about tooltips, please check out the section in the Pydeck docs. You will also be able to find some demos with custom tooltips.

Custom Layers

To build custom layers, you will need to create a custom version of Dash Deck. To do this you will need:

  1. Clone this project, create a venv, npm install and build (see CONTRIBUTING.md).
  2. Add necessary packages to your package.json. E.g. npm install turf, if you need a library called turn.
  3. Create a Javascript file inside dash-deck/src/lib/ that will contain your layer. See this as an example.
  4. Import the Javascript file in dash-deck/src/lib/components/DeckGL.react.js, e.g.:
...
import LabeledGeoJsonLayer from "../labeled-geojson-layer.js";
...
  1. Add it to the JSONConfiguration in the same file:
const configuration = {
  classes: Object.assign(
    {},
    ...,
    LabeledGeoJsonLayer
  ),
  enumerations: ...
}
  1. npm build
  2. Start creating an app that uses pydeck or JSON. See dash-deck/demos/other/usage-custom-layer.py.
  3. Run the tests (see contributing.md).
  4. When you are ready, create the installable distribution files by running python setup.py sdist inside dash-deck/.

Contributing

See CONTRIBUTING.md

License

Dash and Dash Deck are licensed under MIT. Please view LICENSE for more details.

Contact and Support

If you are interested in supporting the development of this library, check out our consulting & training page. For enterprise support and deployment, contact us.

References

This component lets you visualizes PyDeck and deck/json files directly in Dash. It also exposes various events (such as click, hover and drag) inside callbacks.

Keyword arguments:

  • data (dict | string; optional): Your map using the Deck.gl JSON format. This can be generated by calling pdk.Deck(...).to_json(). Both a Python dictionary and a JSON-string your map is accepted.
  • id (string; optional): The ID used to identify this component in Dash callbacks.
  • style (dict; optional): Custom CSS for your map. This is useful for changing the height, width, and sometimes the background color.
  • enableEvents (list of strings | boolean; default False): Either a boolean indicating if all event callbacks should be enabled, or a list of strings indicating which ones should be used. If it's a list, you will need to specify one of the following gestures: click, dragStart, dragEnd, hover.
  • tooltip (dict | boolean; default False): This can be a boolean value (e.g. True, False) to display the default tooltip. You can also give a dictionary specifying an html template and custom style using css. For more information about templating, see: https://pydeck.gl/tooltip.html
  • mapboxKey (string; optional): You will need a mapbox token to use deck.gl. Please create a mapbox and follow the instructions here: https://docs.mapbox.com/help/how-mapbox-works/access-tokens/
  • disableContext (boolean; default False): This is a boolean value (e.g. True, False) indicating whether or not to disable the default context menu that shows up when right clicking on the map. If set to True, right clicking to rotate a map or adjust its pitch will not trigger the default context menu.
  • clickEvent (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when an element in the map is clicked. This contains the original gesture event (in JSON).
  • clickInfo (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when an element in the map is clicked. This contains the picking info describing the object being clicked. Complete description here: https://deck.gl/docs/developer-guide/interactivity#the-picking-info-object
  • hoverEvent (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when an element in the map is hovered. This contains the original gesture event (in JSON).
  • hoverInfo (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when an element in the map is hovered. This contains the picking info describing the object being hovered. Complete description here: https://deck.gl/docs/developer-guide/interactivity#the-picking-info-object
  • dragStartEvent (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when the user starts dragging on the canvas. This contains the original gesture event (in JSON).
  • dragStartInfo (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when the user starts dragging on the canvas. This contains the picking info describing the object being dragged. Complete description here: https://deck.gl/docs/developer-guide/interactivity#the-picking-info-object
  • dragEndEvent (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when the user releases from dragging the canvas. This contains the original gesture event (in JSON).
  • dragEndInfo (dict; optional): Read-only prop. To use this, make sure that enableEvents is set to True, or that enableEvents is a list that contains this event type. This prop is updated when the user releases from dragging the canvas. This contains the picking info describing the object being dragged. Complete description here: https://deck.gl/docs/developer-guide/interactivity#the-picking-info-object

dash-deck's People

Contributors

alexcjohnson avatar bandersen23 avatar graingert-coef avatar jingningzhang1 avatar karosc avatar rpkyle avatar vogt31337 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dash-deck's Issues

Is it possible to update map in a callback function based on the value of other components?

Description

I am trying to update the rendered map through a callback function like this:

layer = pdk.Layer(
    "TripsLayer",
    df,
    get_path="coordinates",
    get_timestamps="timestamps",
    get_color=[253, 128, 93],
    opacity=0.8,
    width_min_pixels=5,
    rounded=True,
    trail_length=600,
    current_time=500,
)

r = pdk.Deck(layers=[layer])
deckgl_map = dash_deck.DeckGL(r.to_json(), id="map-graph", mapboxKey=mapbox_access_token)

@app.callback(
    Output("map-graph", < component_property ??!! >),
    [
        Input("date-picker", "date"),
        Input("trip-slider", "value")
    ],
)
def update_graph(datePicked, sliderValue):
    # use slider-value to filter / modify and update the map 

In my layout, there is a date picker and a slider. I want to update the map based on the values on the slider and the date picker or any other input.
However I do not know the syntax to do so or whether it can be done at all.
Also, if it is possible, what would be the component_property for the deck component ?

Mirrored into conda-forge?

This is an awesome set of components. I'm glad this was made. Any chance it could mirrored into conda-forge? Thanks!

Demo: ArcLayer

Resides in usage-arclayer.py. Currently, map style and tooltip are not working.

Map not displaying when using columnLayer

In the dash-deck gallery, the example for Column layers is not displaying the map.
https://dash.gallery/dash-deck-explorer/column-layer
I have tried to reproduce the example locally and the same issue holds.
So my sample code is the code given in the gallery.
I have created an app with different data and the issue persists.
Any indication why this may be so?
Thanks.

Description

Steps/Code to Reproduce

Expected Results

Actual Results

Versions

Render a Scenegraph Layer

Description

Hello,
I'm trying to render a Scenegraph layer with dash-deck but this does not seem possible.
I am getting an error Unexpected ":" at character 5

Steps/Code to Reproduce

Example:

import os
import dash
import dash_deck
import dash_html_components as html
import pydeck as pdk

mapbox_api_token = os.getenv("MAPBOX_ACCESS_TOKEN")

layer = pdk.Layer(
    "ScenegraphLayer",
    data=[{"coordinates": [-122.466233, 37.684638]}],
    draggable=True,
    scenegraph="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxAnimated/glTF-Binary/BoxAnimated.glb",
    get_position="coordinates",
    get_orientation=[0, 20, 90],
    get_color=[100, 100, 100, 100],
    size_scale=1,
    _lighting="pbr",
)

view_state = pdk.ViewState(
    latitude=37.7749295, longitude=-122.4194155, zoom=11, bearing=0, pitch=45
)

# Render
r = pdk.Deck(layers=[layer], initial_view_state=view_state)


app = dash.Dash(__name__)

app.layout = html.Div(
    dash_deck.DeckGL(r.to_json(), id="deck-gl", mapboxKey=mapbox_api_token)
)


if __name__ == "__main__":
    app.run_server(debug=True)

Versions

Dash Core Components 2.0.0
Dash HTML Components 2.0.0
Dash Deck 0.0.1

Dash Deck Data Allocation: GeoJSON Handling

I am using Dash Deck to create interactive maps, but I have a question about the geojson data I upload. I want to know if the geojson data is stored on the Carto server or if it is only used for rendering the map. I don't want my data to be reused by anyone else without my permission.

Line-layer demo shows far less data than equivalent deck.gl demo yet both use same data source.

Hi,

The line-layer demo: https://dash-gallery.plotly.host/dash-deck-explorer/line-layer

Hows far less data than the equivalent deck.gl demo. https://deck.gl/examples/line-layer/

Yet both load and parse the same data source file:
https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/line/heathrow-flights.json

Any ideas on why this is the case? I cannot see any obvious cause in the code.

Thanks

Darren

Cannot execute example code

Hello, i am trying to reproduce some example code but i cannot execute it.
Just keeps loading with a black screen. Here is the code example, maybe something change in the latest release?
Any idea? thank you!

import os

import dash
import dash_deck
import dash_html_components as html
import pydeck as pdk
import pandas as pd

mapbox_api_token = os.getenv("MAPBOX_ACCESS_TOKEN")

app = dash.Dash(__name__)


# Map of San Francisco from 1906
IMG_URL = '"https://i.imgur.com/W95ked7.jpg"'

# Specifies the corners of the image bounding box
BOUNDS = [
    [-122.52690000000051, 37.70313158980733],
    [-122.52690000000051, 37.816395657523195],
    [-122.34604834372873, 37.816134829424335],
    [-122.34656848822227, 37.70339041384273],
]

bitmap_layer = pdk.Layer(
    "BitmapLayer", data=None, image=IMG_URL, bounds=BOUNDS, opacity=0.7
)

view_state = pdk.ViewState(
    latitude=37.7576171, longitude=-122.5776844, zoom=10, bearing=-45, pitch=60,
)

r = pdk.Deck(
    bitmap_layer,
    initial_view_state=view_state,
    map_style=pdk.map_styles.SATELLITE,
    # mapbox_key=mapbox_api_token,
)


app.layout = html.Div(
    dash_deck.DeckGL(r.to_json(), id="deck-gl", mapboxKey=mapbox_api_token)
)


if __name__ == "__main__":
    app.run_server(debug=False)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.