Esempio n. 1
0
    def test_simple_element(self):
        # Build Holoviews Elements
        scatter = Scatter([0, 0])

        # Convert to Dash
        components = to_dash(self.app, [scatter])

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 1)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 0)

        callback_fn = self.app.callback.return_value.call_args[0][0]

        # Check registered callbacks
        self.assertEqual(self.app.callback.call_count, 1)
        self.assertEqual(self.decorator.call_count, 1)

        store_value = encode_store_data({})

        with patch.object(CallbackContext, "triggered", []):
            [fig, new_store] = callback_fn({}, store_value)

        # Check figure returned by callback
        self.assertEqual(len(fig["data"]), 1)
        self.assertEqual(fig["data"][0]["type"], "scatter")
    def test_kdims_dynamic_map(self):
        # Dynamic map with two key dimensions
        dmap = DynamicMap(lambda kdim1: Scatter([kdim1, kdim1]),
                          kdims=["kdim1"]).redim.values(kdim1=[1, 2, 3, 4])

        # Convert to Dash
        components = to_dash(self.app, [dmap])

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 1)
        self.assertEqual(len(components.kdims), 1)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 0)

        # Get arguments passed to @app.callback decorator
        decorator_args = list(self.app.callback.call_args_list[0])[0]
        outputs, inputs, states = decorator_args

        # Check outputs
        expected_outputs = [(g.id, "figure") for g in components.graphs] + \
                           [(components.store.id, "data")]
        self.assertEqual([(output.component_id, output.component_property)
                          for output in outputs], expected_outputs)

        # Check inputs
        expected_inputs = [
            (g.id, prop) for g in components.graphs
            for prop in ["selectedData", "relayoutData"]
        ] + [(list(components.kdims.values())[0].children[1].id, 'value')]

        self.assertEqual(
            [(ip.component_id, ip.component_property) for ip in inputs],
            expected_inputs,
        )

        # Check State
        expected_state = [(components.store.id, "data")]
        self.assertEqual(
            [(state.component_id, state.component_property)
             for state in states],
            expected_state,
        )

        # Get callback function
        callback_fn = self.decorator.call_args_list[0][0][0]

        # mimic initial callback invocation
        store_value = encode_store_data({"streams": {}})
        with patch.object(CallbackContext, "triggered", []):
            [fig, new_store] = callback_fn({}, {}, 3, None, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig["data"][0]["type"], "scatter")
        self.assertEqual(list(fig["data"][0]["x"]), [0, 1])
        self.assertEqual(list(fig["data"][0]["y"]), [3, 3])
    def test_simple_element(self):
        # Build Holoviews Elements
        scatter = Scatter([0, 0])

        # Convert to Dash
        components = to_dash(self.app, [scatter])

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 1)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 0)

        # Check initial figure
        fig = components.graphs[0].figure
        self.assertEqual(len(fig["data"]), 1)
        self.assertEqual(fig["data"][0]["type"], "scatter")
    np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000, )))
points2 = hv.Points(
    np.random.multivariate_normal((3, 3), [[1, 0.1], [0.1, 1]], (1000, )))

# Declare two selection streams and set points and points2 as the source of each
sel1 = streams.Selection1D(source=points)
sel2 = streams.Selection1D(source=points2)

# Declare DynamicMaps to show mean y-value of selection as HLine
hline1 = hv.DynamicMap(lambda index: hv.HLine(points['y'][index].mean()
                                              if index else -10),
                       streams=[sel1])
hline2 = hv.DynamicMap(lambda index: hv.HLine(points2['y'][index].mean()
                                              if index else -10),
                       streams=[sel2])

# Combine points and dynamic HLines
layout = (points * points2 * hline1 * hline2).opts(
    opts.Points(height=400, width=400))

# Create App
app = dash.Dash(__name__)

# Dash display
components = to_dash(app, [layout], reset_button=True)

app.layout = html.Div(components.children)

if __name__ == '__main__':
    app.run_server(debug=True)
Esempio n. 5
0
# Build HoloViews Dataset from large Pandas DataFrame
import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash
dataset = hv.Dataset(df)

# Build Datashaded Scatter and Histogram HoloViews Elements, and side-by-side layout
from holoviews.operation.datashader import datashade
scatter = datashade(
    hv.Scatter(dataset, kdims=["sepal_length"], vdims=["sepal_width"]))
hist = hv.operation.histogram(dataset, dimension="petal_width", normed=False)
row = scatter + hist

# Link selections across subplots
linked_row = hv.selection.link_selections(row)

# Set plot title
linked_row.opts(title="Datashader with %d points" % len(dataset))

# Build Dash app
import dash
app = dash.Dash(__name__)
components = to_dash(app, [linked_row], reset_button=True)

# Build Dash layout
import dash_html_components as html
app.layout = html.Div(components.children)

if __name__ == "__main__":
    app.run_server(debug=True)
Esempio n. 6
0
import dash
import dash_html_components as html
from plotly.data import iris

import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash
from holoviews.operation.datashader import datashade

import numpy as np 
import pandas as pd 

# Load iris dataset and replicate with noise to create large dataset
df_original = iris()[["sepal_length", "sepal_width", "petal_length", "petal_width"]]
df = pd.concat([
    df_original + np.random.randn(*df_original.shape) * 0.1
    for i in range(10000)
])
dataset = hv.Dataset(df)

scatter = datashade(
    hv.Scatter(dataset, kdims=['sepal_length'], vdims=['sepal_width'])
).opts(width=600).opts(title="Datashader with %d points" % len(dataset))

app = dash.Dash(__name__)
components = to_dash(app, [scatter], reset_button=True)

app.layout = html.Div(components.children)

if __name__ == '__main__':
    app.run_server(debug=True)
# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
from plotly.data import iris

import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash

# Load dataset
df = iris()
dataset = hv.Dataset(df)

scatter = hv.Scatter(dataset, kdims=["sepal_length"], vdims=["sepal_width"])
hist = hv.operation.histogram(dataset, dimension="petal_width", normed=False)

app = dash.Dash(__name__)
components = to_dash(app, [scatter, hist])

app.layout = html.Div(components.children)

if __name__ == "__main__":
    app.run_server(debug=True)
Esempio n. 8
0
import dash
import dash_html_components as html
import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash
from holoviews.element.tiles import CartoDark
from plotly.data import carshare

# Convert from lon/lat to web-mercator easting/northing coordinates
df = carshare()
df["easting"], df["northing"] = hv.Tiles.lon_lat_to_easting_northing(
    df["centroid_lon"], df["centroid_lat"])

points = hv.Points(df, ["easting", "northing"]).opts(color="crimson")
tiles = CartoDark()
overlay = tiles * points

app = dash.Dash(__name__)
components = to_dash(app, [overlay])

app.layout = html.Div(components.children)

if __name__ == '__main__':
    app.run_server(debug=True)
Esempio n. 9
0
from plotly.data import iris
df = iris()

# Build HoloViews Dataset from Pandas DataFrame
import holoviews as hv
dataset = hv.Dataset(df)

# Build HoloViews Elements
scatter = hv.Scatter(dataset, kdims=["sepal_length"], vdims=["sepal_width"])
hist = hv.operation.histogram(
    dataset, dimension="petal_width", normed=False
)

# Build side-by-side subplot of scatter and histogram
row = scatter + hist

# Build Dash app
import dash
app = dash.Dash(__name__)

# Build Dash components from HoloViews row Layout
from holoviews.plotting.plotly.dash import to_dash
components = to_dash(app, [row])

# Build Dash layout
import dash_html_components as html
app.layout = html.Div(components.children)

if __name__ == "__main__":
    app.run_server(debug=True)
# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
from plotly.data import iris

import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash

# Load dataset
df = iris()
dataset = hv.Dataset(df)

scatter = hv.Scatter(dataset, kdims=["sepal_length"], vdims=["sepal_width"])

# Set scatter size and color using options system
scatter.opts(size=15, color="purple")

# Set default drag mode to pan using a plot hook
def hook(plot, element):
    fig = plot.state
    fig["layout"]["dragmode"] = "pan"
scatter.opts(hooks=[hook])

app = dash.Dash(__name__)
components = to_dash(app, [scatter])

app.layout = html.Div(components.children)

if __name__ == "__main__":
    app.run_server(debug=True)
                                                  y=(bounds[1], bounds[3])),
                     streams=[box])

# Compute histograms of selection along x-axis and y-axis
yhist = hv.operation.histogram(dmap,
                               bin_range=points.range('y'),
                               dimension='y',
                               dynamic=True,
                               normed=False)
xhist = hv.operation.histogram(dmap,
                               bin_range=points.range('x'),
                               dimension='x',
                               dynamic=True,
                               normed=False)

layout = datashade(points).opts(
    opts.Points(size=6)) * mean_sel * bounds << yhist << xhist

# Create App
app = dash.Dash(__name__)
components = to_dash(
    app,
    [layout],
    reset_button=True,
    use_ranges=False,
)

app.layout = html.Div(components.children)

if __name__ == "__main__":
    app.run_server(debug=True)
    def test_boundsxy_dynamic_map(self):
        # Build Holoviews Elements
        scatter = Scatter([0, 0])
        boundsxy = BoundsXY(source=scatter)
        dmap = DynamicMap(lambda bounds: Bounds(bounds)
                          if bounds is not None else Bounds((0, 0, 0, 0)),
                          streams=[boundsxy])

        # Convert to Dash
        components = to_dash(self.app, [scatter, dmap], reset_button=True)

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 2)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 1)

        # Get arguments passed to @app.callback decorator
        decorator_args = list(self.app.callback.call_args_list[0])[0]
        outputs, inputs, states = decorator_args

        # Check outputs
        expected_outputs = [(g.id, "figure") for g in components.graphs] + \
                           [(components.store.id, "data")]
        self.assertEqual([(output.component_id, output.component_property)
                          for output in outputs], expected_outputs)

        # Check inputs
        expected_inputs = [(g.id, prop) for g in components.graphs
                           for prop in ["selectedData", "relayoutData"]
                           ] + [(components.resets[0].id, "n_clicks")]

        self.assertEqual(
            [(ip.component_id, ip.component_property) for ip in inputs],
            expected_inputs,
        )

        # Check State
        expected_state = [(components.store.id, "data")]
        self.assertEqual(
            [(state.component_id, state.component_property)
             for state in states],
            expected_state,
        )

        # Check initial figures
        fig1 = components.graphs[0].figure
        fig2 = components.graphs[1].figure
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds the bounds element
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(fig2["layout"]["shapes"][0]["path"],
                         "M0 0L0 0L0 0L0 0L0 0Z")

        # Get callback function
        callback_fn = self.app.callback.return_value.call_args[0][0]

        # # mimic initial callback invocation
        store_value = encode_store_data(
            {"streams": {
                id(boundsxy): boundsxy.contents
            }})

        # Update store, then mimic a box selection on scatter figure
        # store_value = new_store
        with patch.object(
                CallbackContext, "triggered",
            [{
                "prop_id": inputs[0].component_id + ".selectedData"
            }]):
            [fig1, fig2,
             new_store] = callback_fn({"range": {
                 "x": [1, 2],
                 "y": [3, 4]
             }}, {}, {}, {}, 0, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds the bounds element
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(
            fig2["layout"]["shapes"][0]["path"],
            "M1 3L1 4L2 4L2 3L1 3Z",
        )

        # Check that store was updated
        self.assertEqual(decode_store_data(new_store), {
            "streams": {
                id(boundsxy): {
                    "bounds": (1, 3, 2, 4)
                }
            },
            "kdims": {}
        })

        # Click reset button
        with patch.object(CallbackContext, "triggered",
                          [{
                              "prop_id": components.resets[0].id + ".n_clicks"
                          }]):
            [fig1, fig2,
             new_store] = callback_fn({"range": {
                 "x": [1, 2],
                 "y": [3, 4]
             }}, {}, {}, {}, 1, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds reset bounds elemnt
        self.assertEqual(len(fig2["data"]), 0)
        self.assertEqual(len(fig2["layout"]["shapes"]), 1)
        self.assertEqual(fig2["layout"]["shapes"][0]["path"],
                         "M0 0L0 0L0 0L0 0L0 0Z")

        # Reset button should clear bounds in store
        self.assertEqual(
            decode_store_data(new_store), {
                "streams": {
                    id(boundsxy): {
                        "bounds": None
                    }
                },
                "reset_nclicks": 1,
                "kdims": {}
            })
    def test_selection1d_dynamic_map(self):
        # Create dynamic map that inputs selection1d, returns overlay of scatter on
        # selected points
        scatter = Scatter([[0, 0], [1, 1], [2, 2]])
        selection1d = Selection1D(source=scatter)
        dmap = DynamicMap(
            lambda index: scatter.iloc[index].opts(size=len(index) + 1),
            streams=[selection1d])

        # Convert to Dash
        components = to_dash(self.app, [scatter, dmap], reset_button=True)

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 2)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 1)

        # Get arguments passed to @app.callback decorator
        decorator_args = list(self.app.callback.call_args_list[0])[0]
        outputs, inputs, states = decorator_args

        # Check outputs
        expected_outputs = [(g.id, "figure") for g in components.graphs] + \
                           [(components.store.id, "data")]
        self.assertEqual([(output.component_id, output.component_property)
                          for output in outputs], expected_outputs)

        # Check inputs
        expected_inputs = [(g.id, prop) for g in components.graphs
                           for prop in ["selectedData", "relayoutData"]
                           ] + [(components.resets[0].id, "n_clicks")]

        self.assertEqual(
            [(ip.component_id, ip.component_property) for ip in inputs],
            expected_inputs,
        )

        # Check State
        expected_state = [(components.store.id, "data")]
        self.assertEqual(
            [(state.component_id, state.component_property)
             for state in states],
            expected_state,
        )

        # Check initial figures
        fig1 = components.graphs[0].figure
        fig2 = components.graphs[1].figure

        # Figure holds the scatter trace
        self.assertEqual(len(fig2["data"]), 1)

        # Check expected marker size
        self.assertEqual(fig2["data"][0]["marker"]["size"], 1)
        self.assertEqual(list(fig2["data"][0]["x"]), [])
        self.assertEqual(list(fig2["data"][0]["y"]), [])

        # Get callback function
        callback_fn = self.app.callback.return_value.call_args[0][0]

        # mimic initial callback invocation
        store_value = encode_store_data(
            {"streams": {
                id(selection1d): selection1d.contents
            }})

        # Update store, then mimick a selection on scatter figure
        # store_value = new_store
        with patch.object(
                CallbackContext, "triggered",
            [{
                "prop_id": inputs[0].component_id + ".selectedData"
            }]):
            [fig1, fig2, new_store] = callback_fn(
                {
                    "points": [{
                        "curveNumber": 0,
                        "pointNumber": 0,
                        "pointIndex": 0,
                    }, {
                        "curveNumber": 0,
                        "pointNumber": 2,
                        "pointIndex": 2,
                    }]
                }, {}, 0, store_value)

        # Figure holds the scatter trace
        self.assertEqual(len(fig2["data"]), 1)

        # Check expected marker size
        self.assertEqual(fig2["data"][0]["marker"]["size"], 3)
        self.assertEqual(list(fig2["data"][0]["x"]), [0, 2])
        self.assertEqual(list(fig2["data"][0]["y"]), [0, 2])

        # Check that store was updated
        self.assertEqual(decode_store_data(new_store), {
            "streams": {
                id(selection1d): {
                    "index": [0, 2]
                }
            },
            "kdims": {}
        })

        # Click reset button
        store = new_store
        with patch.object(CallbackContext, "triggered",
                          [{
                              "prop_id": components.resets[0].id + ".n_clicks"
                          }]):
            [fig1, fig2, new_store] = callback_fn({}, {}, 1, store)

        # Figure holds the scatter trace
        self.assertEqual(len(fig2["data"]), 1)

        # Check expected marker size
        self.assertEqual(fig2["data"][0]["marker"]["size"], 1)
        self.assertEqual(list(fig2["data"][0]["x"]), [])
        self.assertEqual(list(fig2["data"][0]["y"]), [])

        # Check that store was updated
        self.assertEqual(
            decode_store_data(new_store),
            {
                "streams": {
                    id(selection1d): {
                        "index": []
                    }
                },
                'reset_nclicks': 1,
                "kdims": {}
            },
        )
    def test_rangexy_dynamic_map(self):

        # Create dynamic map that inputs rangexy, returns scatter on bounds
        scatter = Scatter([[0, 1], [0, 1]], kdims=["x"], vdims=["y"])
        rangexy = RangeXY(source=scatter)

        def dmap_fn(x_range, y_range):
            x_range = (0, 1) if x_range is None else x_range
            y_range = (0, 1) if y_range is None else y_range
            return Scatter(
                [[x_range[0], y_range[0]], [x_range[1], y_range[1]]],
                kdims=["x1"],
                vdims=["y1"])

        dmap = DynamicMap(dmap_fn, streams=[rangexy])

        # Convert to Dash
        components = to_dash(self.app, [scatter, dmap], reset_button=True)

        # Check returned components
        self.assertIsInstance(components, DashComponents)
        self.assertEqual(len(components.graphs), 2)
        self.assertEqual(len(components.kdims), 0)
        self.assertIsInstance(components.store, Store)
        self.assertEqual(len(components.resets), 1)

        # Get arguments passed to @app.callback decorator
        decorator_args = list(self.app.callback.call_args_list[0])[0]
        outputs, inputs, states = decorator_args

        # Check outputs
        expected_outputs = [(g.id, "figure") for g in components.graphs] + \
                           [(components.store.id, "data")]
        self.assertEqual([(output.component_id, output.component_property)
                          for output in outputs], expected_outputs)

        # Check inputs
        expected_inputs = [(g.id, prop) for g in components.graphs
                           for prop in ["selectedData", "relayoutData"]
                           ] + [(components.resets[0].id, "n_clicks")]

        self.assertEqual(
            [(ip.component_id, ip.component_property) for ip in inputs],
            expected_inputs,
        )

        # Check State
        expected_state = [(components.store.id, "data")]
        self.assertEqual(
            [(state.component_id, state.component_property)
             for state in states],
            expected_state,
        )

        # Get callback function
        callback_fn = self.app.callback.return_value.call_args[0][0]

        # mimic initial callback invocation
        store_value = encode_store_data(
            {"streams": {
                id(rangexy): rangexy.contents
            }})
        with patch.object(
                CallbackContext, "triggered",
            [{
                "prop_id": components.graphs[0].id + ".relayoutData"
            }]):
            [fig1, fig2, new_store] = callback_fn({}, {
                "xaxis.range[0]": 1,
                "xaxis.range[1]": 3,
                "yaxis.range[0]": 2,
                "yaxis.range[1]": 4
            }, {}, {}, None, store_value)

        # First figure is the scatter trace
        self.assertEqual(fig1["data"][0]["type"], "scatter")

        # Second figure holds the bounds element
        self.assertEqual(len(fig2["data"]), 1)
        self.assertEqual(list(fig2["data"][0]["x"]), [1, 3])
        self.assertEqual(list(fig2["data"][0]["y"]), [2, 4])

        # Check updated store
        self.assertEqual(
            decode_store_data(new_store), {
                "streams": {
                    id(rangexy): {
                        'x_range': (1, 3),
                        'y_range': (2, 4)
                    }
                },
                "kdims": {}
            })
Esempio n. 15
0

linked_hist.opts(hv.opts.Histogram(hooks=[set_dragmode]))

# Set plot margins, ordered (left, bottom, right, top)
linked_hist.opts(margins=(60, 40, 30, 30))
linked_map_overlay.opts(margins=(30, 30, 30, 30))

# Build Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server

# Build Dash components from multiple HoloViews Elements
components = to_dash(
    app,
    [linked_map_overlay, linked_hist],
    reset_button=True,
    button_class=dbc.Button,
)

# Build Dash layout using Dash Bootstrap Components
app.layout = dbc.Container([
    html.H1("NYC Taxi Demo", style={"padding-top": 40}),
    html.
    H3("Crossfiltering 10 million trips with Dash, Datashader, and HoloViews"),
    html.Hr(),
    dbc.Row([
        dbc.Col(children=[
            dbc.Card([
                dbc.CardHeader("Drop off locations"),
                dbc.CardBody(children=[
                    components.graphs[0],
Esempio n. 16
0
# -*- coding: utf-8 -*-
import dash
import dash_html_components as html

import numpy as np
import holoviews as hv
from holoviews.plotting.plotly.dash import to_dash

frequencies = [0.5, 0.75, 1.0, 1.25]


def sine_curve(phase, freq):
    xvals = [0.1 * i for i in range(100)]
    return hv.Curve((xvals, [np.sin(phase + freq * x) for x in xvals]))


# When run live, this cell's output should match the behavior of the GIF below
dmap = hv.DynamicMap(sine_curve, kdims=['phase', 'frequency'])
dmap = dmap.redim.range(phase=(0.5, 1), frequency=(0.5, 1.25))

# Create App
app = dash.Dash(__name__)

# Dash display
components = to_dash(app, [dmap])

app.layout = html.Div(components.children)

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