def get_layout(**kwargs): initial_text = kwargs.get("text", "Type some text into me!") return html.Div([ dbc.Container([ dbc.Row([ dcc.Markdown(""" # Upload File to Figure Upload a data file (single-row header), and then download the data out of the figure. This demo supports CSV and XLS file formats. You can find an example file in [`/examples/example_data.csv`](https://github.com/bcliang/dash-clientside-demo/blob/master/examples/example_upload_data.csv) This page is meant to demonstrate the ability of the clientside-based File download to exceeed browser size limitations. """) ], className="graph-header-row"), dbc.Row([ dcc.Upload([dbc.Button("Upload CSV File")], id='upload-data') ], className="graph-header-row"), dbc.Row([ dbc.Col( fig.ExtendableGraph( id='upload-signal', config=dict( showAxisDragHandles=True, showAxisRangeEntryBoxes=True, modeBarButtonsToRemove=[ 'sendDataToCloud', 'lasso2d', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'toggleSpikelines' ], displaylogo=False, ), figure=dict(data=[], layout=dict( showlegend=True, uirevision='upload-signal-layout', legend={ 'orientation': 'h', 'xanchor': 'right', 'yanchor': 'top', 'x': 0.98, 'y': 1.05, }, ))), ), ], className="graph-content-row"), dbc.Row([ dbc.Col([ dbc.Button('Download CSV', id='button-upload-download'), html.Div(id='button-upload-target', style=dict(display='none')) ], style={'text-align': 'left'}), ], className="graph-options-row") ]), ])
def test_extg003_extend_then_add_trace(dash_duo): app = dash.Dash(__name__) app.layout = html.Div( [ deg.ExtendableGraph( id="trace_will_extend_and_add", config={"displaylogo": False}, figure=dict(data=[{"x": [0, 1, 2, 3, 4], "y": [0, 0.5, 1, 0.5, 0]}],), ), html.Div(id="output"), dcc.Interval( id="interval_extendablegraph_update", interval=10, n_intervals=0, max_intervals=1, ), dcc.Interval( id="interval_check_figdata", interval=500, n_intervals=0, max_intervals=-1, ), ] ) @app.callback( Output("trace_will_extend_and_add", "extendData"), [Input("interval_extendablegraph_update", "n_intervals")], ) def trace_will_extend_then_add(n_intervals): if n_intervals is None or n_intervals < 1: raise PreventUpdate x_new = [5, 6, 7, 8, 9] y_new = [0.1, 0.2, 0.3, 0.4, 0.5] return [dict(x=x_new, y=y_new), dict(x=x_new, y=x_new)] @app.callback( Output("output", "children"), [Input("interval_check_figdata", "n_intervals")], [State("trace_will_extend_and_add", "figure")], ) def display_data(trigger, figure): return json.dumps(figure["data"]) dash_duo.start_server(app) dash_duo.find_element("#trace_will_extend_and_add") comparison = json.dumps( [ dict( x=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], y=[0, 0.5, 1, 0.5, 0, 0.1, 0.2, 0.3, 0.4, 0.5], ), dict(x=[5, 6, 7, 8, 9], y=[5, 6, 7, 8, 9]), ] ) dash_duo.wait_for_text_to_equal("#output", comparison)
def test_extg002_define_maxpoints(dash_duo): app = dash.Dash(__name__) app.layout = html.Div([ deg.ExtendableGraph( id="trace_will_extend_with_window", figure=dict( data=[dict(y=[0]), dict(x=[0, 1, 2, 3, 4], y=[0, 1, 2, 3, 4])], ), ), html.Div(id="output"), dcc.Interval( id="interval_extendablegraph_update", interval=500, n_intervals=0, max_intervals=8, ), ]) @app.callback( Output("trace_will_extend_with_window", "extendData"), [Input("interval_extendablegraph_update", "n_intervals")], [State("trace_will_extend_with_window", "figure")], ) def trace_will_extend_then_add(n_intervals, figure): if n_intervals is None or n_intervals < 1: raise PreventUpdate x_new = figure["data"][1]["x"][-1] + 1 y_new = figure["data"][1]["y"][-1] + 1 print([dict(x=[x_new], y=[y_new])]) return [dict(x=[x_new], y=[y_new])], [1], 8 @app.callback( Output("output", "children"), [Input("trace_will_extend_with_window", "extendData")], [State("trace_will_extend_with_window", "figure")], ) def display_data(trigger, figure): return json.dumps(figure["data"]) dash_duo.start_server(app) dash_duo.find_element("#trace_will_extend_with_window") comparison = json.dumps([ dict(y=[0]), dict(x=[5, 6, 7, 8, 9, 10, 11, 12], y=[5, 6, 7, 8, 9, 10, 11, 12]), ]) dash_duo.wait_for_text_to_equal("#output", comparison)
def test_extg009_prependData_repeatedly(dash_duo): app = dash.Dash(__name__) app.layout = html.Div([ deg.ExtendableGraph( id="trace_will_prepend", config={"displaylogo": False}, figure=dict(data=[{ "y": [0, 0.5, 1, 0.5, 0] }], ), ), html.Div(id="output"), dcc.Interval( id="interval_extendablegraph_update", interval=500, n_intervals=0, max_intervals=2, ), ]) @app.callback( Output("trace_will_prepend", "prependData"), [Input("interval_extendablegraph_update", "n_intervals")], ) def trace_will_prepend(n_intervals): if n_intervals is None or n_intervals < 1: raise PreventUpdate return [dict(y=[0.1, 0.2, 0.3, 0.4, 0.5])] @app.callback( Output("output", "children"), [Input("trace_will_prepend", "prependData")], [State("trace_will_prepend", "figure")], ) def display_data(trigger, figure): print(json.dumps(figure["data"][0])) return json.dumps(figure["data"][0]) dash_duo.start_server(app) dash_duo.find_element("#trace_will_prepend") comparison = json.dumps( dict(y=[ 0.1, 0.2, 0.3, 0.4, 0.5, 0.1, 0.2, 0.3, 0.4, 0.5, 0, 0.5, 1, 0.5, 0 ], )) dash_duo.wait_for_text_to_equal("#output", comparison)
def test_extg005_multiple_trace_types(dash_duo): app = dash.Dash(__name__) app.layout = html.Div( [ deg.ExtendableGraph(id="multi_trace_types", figure=dict(data=[])), html.Div(id="output"), dcc.Interval( id="interval_extendablegraph_update", interval=100, n_intervals=0, max_intervals=1, ), ] ) @app.callback( Output("multi_trace_types", "extendData"), [Input("interval_extendablegraph_update", "n_intervals")], ) def trace_will_extend(n_intervals): if n_intervals is None or n_intervals < 1: raise PreventUpdate return [ dict(x=[5, 6, 7, 8, 9], y=[0.1, 0.2, 0.3, 0.4, 0.5]), dict(y=[1, 2, 3, 4, 5]), ] @app.callback( Output("output", "children"), [Input("multi_trace_types", "extendData")], [State("multi_trace_types", "figure")], ) def display_data(trigger, figure): if figure is None: raise PreventUpdate return json.dumps(figure["data"]) dash_duo.start_server(app) dash_duo.find_element("#multi_trace_types") comparison = json.dumps( [dict(x=[5, 6, 7, 8, 9], y=[0.1, 0.2, 0.3, 0.4, 0.5]), dict(y=[1, 2, 3, 4, 5])] ) dash_duo.wait_for_text_to_equal("#output", comparison)
def test_extg004_extend_trace_selectively(dash_duo): app = dash.Dash(__name__) app.layout = html.Div( [ deg.ExtendableGraph( id="extend_trace_selectively", figure=dict(data=[dict(y=[0]), dict(y=[1])]), ), html.Div(id="output"), dcc.Interval( id="interval_extendablegraph_update", interval=100, n_intervals=0, max_intervals=1, ), ] ) @app.callback( Output("extend_trace_selectively", "extendData"), [Input("interval_extendablegraph_update", "n_intervals")], [State("extend_trace_selectively", "figure")], ) def trace_will_extend_selectively(n_intervals, figure): if n_intervals is None or n_intervals < 1: raise PreventUpdate return [dict(y=[2])], [1] @app.callback( Output("output", "children"), [Input("extend_trace_selectively", "extendData")], [State("extend_trace_selectively", "figure")], ) def display_data(trigger, figure): if figure is None: raise PreventUpdate return json.dumps(figure["data"]) dash_duo.start_server(app) dash_duo.find_element("#extend_trace_selectively") comparison = json.dumps([dict(y=[0]), dict(y=[1, 2])]) dash_duo.wait_for_text_to_equal("#output", comparison)
def test_extg007_clientside(dash_duo): app = dash.Dash(__name__) initial_graph_title = "initial title" header = html.Div( id="header", children=[html.Button(id="update-title", children=["Update Title"])], ) graph = html.Div( children=[ deg.ExtendableGraph( id="deg-clientside-test", figure=dict( layout=dict(title=initial_graph_title), data=[ dict(x=[1, 2, 3, 4], y=[5, 4, 3, 6], line=dict(shape="spline"),) ], ), ) ], ) app.clientside_callback( ClientsideFunction("pytest", "relayout"), Output("header", "style"), [Input("update-title", "n_clicks")], [State("deg-clientside-test", "figure")], ) app.layout = html.Div([header, graph]) dash_duo.start_server(app) dash_duo.wait_for_contains_text("#deg-clientside-test", initial_graph_title) dash_duo.wait_for_element("#update-title").click() dash_duo.wait_for_contains_text( "#deg-clientside-test", "{}-new".format(initial_graph_title) )
import dash_html_components as html import dash_core_components as dcc import random app = dash.Dash(__name__) app.scripts.config.serve_locally = True app.css.config.serve_locally = True app.layout = html.Div([ html.Div([ html.P("extend trace 0, add+extend trace 1"), deg.ExtendableGraph( id="extendablegraph_example1", figure=dict(data=[{ "x": [0, 1, 2, 3, 4], "y": [0, 0.5, 1, 0.5, 0] }], ), ), ]), html.Div([ html.P("extend only trace 0"), deg.ExtendableGraph( id="extendablegraph_example2", figure=dict(data=[ { "x": [0, 1], "y": [0, 0.5], "mode": "lines+markers" }, {
l2.append([i.x, i.y, i.z] * u.km) l = l2 external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"] app = Dash(__name__) server = app.server app.layout = html.Div(children=[ html.H1(children="Welcome to poliastro"), html.Div(children=""" Dash: A web application framework for Python. """), deg.ExtendableGraph(figure=iss.plot(use_3d=True, interactive=True), id="Figure"), dcc.Interval( id="interval-component", interval=100, n_intervals=0 # in milliseconds ), ]) @app.callback(Output("Figure", "extendData"), [Input("interval-component", "n_intervals")]) def change_figure(n_intervals): r = l[n_intervals % 500] # r = [r.x, r.y, r.z] * u.km radius = (norm(r) - Earth.R) * 0.5
style_table={ 'maxHeight': '600', 'overflowY': 'scroll', 'minWidth': '50', 'maxWidth': '300' }, ), html.Div(children=[ ## Currently, dcc.Loading is a bit immature, but will be kept here till it can be used # dcc.Loading(id='graph_loading_symbol', type='circle', children=[ deg.ExtendableGraph(id='Sentiment_Graph', figure={ 'layout': { 'title': '% of tweets positive or negative', 'barmode': 'overlay' }, 'data': [] }) # ]) ]) # <--- THIS HERE ], style={ 'display': 'grid', 'grid-template-columns': '50% 50%', 'column-gap': '20px', 'margin-top': '-25px' }), ## Hiding download button until css error changing its position is handled
def get_layout(**kwargs): # Note that if you need to access multiple values of an argument, you can # use args.getlist("param") return html.Div([ dbc.Container([ dbc.Row( [ dcc.Markdown(""" # BTC-USD Chart This page shows a live-streaming graph. The dropdowns and buttons use clientside callbacks for improved responsiveness. Notes: - JSON download saves the complete contents of the figure.data object (dict) to JSON (no interpretation/manipulation required). - CSV download relies on some data manipulation to transform the figure data into CSV format (see `figDataToStr` from [assets/app-download.js#L7](https://github.com/bcliang/dash-clientside-demo/blob/master/src/dash_clientside_demo/assets/app-download.js#L7)). In this case, the figure traces are of type ScatterGl, and the content saved is the `(x,y)` paired values. - The "Import Price History" button fetches a file from the application's web-accessible "assets" folder. """), dcc.Interval( id='btc-signal-interval', interval=5000, # 1 min max_intervals=-1) ], className="graph-header-row"), dbc.Row([ dbc.Col( fig.ExtendableGraph( id='btc-signal', config=dict( showAxisDragHandles=True, showAxisRangeEntryBoxes=True, modeBarButtonsToRemove=[ 'sendDataToCloud', 'lasso2d', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'toggleSpikelines' ], displaylogo=False, ), figure=dict(data=[], layout=dict( title='BTC-USD Spot Price (Coinbase)', showlegend=True, uirevision='btc-signal-layout', legend={ 'orientation': 'h', 'xanchor': 'right', 'yanchor': 'top', 'x': 0.98, 'y': 1.05, }, ))), ), ], className="graph-content-row"), dbc.Row([ dbc.Col('namespace: ui', style={'text-align': 'right'}), dbc.Col( make_dropdown('btc-dropdown-zoom', 'Zoom Mode', [ 'Scale', '5 min', '30 min', '1 hour', '3 hours', '12 hours', '1 day', '7 days' ], [ 0, 5 / 60 / 24, 30 / 60 / 24, 1 / 24, 3 / 24, .5, 1, 7 ]), ), dbc.Col( make_dropdown( 'btc-dropdown-title', 'Chart Title', ['BTC-USD', '+ latest timestamp', '+ latest value'], [0, 1, 2]), ), dbc.Col( make_dropdown( 'btc-dropdown-refresh', 'Refresh Rate', ['1 sec', '2 sec', '5 sec (default)', '60 sec'], [1000, 2000, 5000, 60000], 5000), ), html.Div(id='ui-relayout-target', style=dict(display='none')), ], className='ui-row'), dbc.Row([ dbc.Col('namespace: download', style={'text-align': 'right'}), dbc.Col([ dbc.Button('Download CSV', id='button-csv-download'), html.Div(id='button-csv-target', style=dict(display='none')) ], style={'text-align': 'left'}), dbc.Col([ dbc.Button('Download JSON', id='button-json-download'), html.Div(id='button-json-target', style=dict(display='none')) ], style={'text-align': 'left'}), dbc.Col([ dbc.Button('Import Price History', id='button-history-download'), html.Div(id='button-history-target', style=dict(display='none')) ], style={'text-align': 'left'}) ], className='ui-row'), ]), ]) """
def test_extg006_responsive(dash_duo, responsive, autosize, height, is_responsive): width = 600 # reduce test iterations, just check vs height (ignore width) app = dash.Dash(__name__) header_style = dict(padding="10px", backgroundColor="yellow", flex="0 0 100px") graph_style = dict(padding="10px", backgroundColor="red", flex="1 0 0") card_style = dict( display="flex", flexFlow="column", backgroundColor="green", padding="10px", height="500px", width="1000px", ) header = html.Div( id="header", style=header_style, children=[html.Button(id="resize", children=["Resize"])], ) graph = html.Div( style=graph_style, children=[ deg.ExtendableGraph( id="graph", responsive=is_responsive, style=dict(height="100%", width="100%"), config=dict(responsive=responsive), figure=dict( layout=dict(autosize=autosize, height=height, width=width), data=[ dict( x=[1, 2, 3, 4], y=[5, 4, 3, 6], line=dict(shape="spline"), ) ], ), ) ], ) app.layout = html.Div([ html.Div([ "responsive: {}, ".format(responsive), "autosize: {}, ".format(autosize), "height: {}, ".format(height), "width: {}, ".format(width), "is_responsive: {}".format(is_responsive), ]), html.Div(id="card", style=card_style, children=[header, graph]), ]) @app.callback( Output("header", "style"), [Input("resize", "n_clicks")], [State("header", "style")], ) def resize(n_clicks, style): if n_clicks is None: raise PreventUpdate return dict(style, **dict(flex="0 0 200px")) dash_duo.start_server(app) # autosize=true|udefined will make the graph fit its parent on first render, responsive has no impact on that behavior # # responsive=true will make the graph resize only if autosize=true|undefined, interestingly enough, responsive=undefined # behaves the same as responsive=false (https://github.com/plotly/plotly.js/blob/master/src/plot_api/plot_config.js#L122) initial_responsive = is_responsive is True or ( is_responsive == "auto" and autosize is not False and (height is None or width is None)) resize_responsive = is_responsive is True or ( is_responsive == "auto" and responsive is True and autosize is not False and (height is None or width is None)) initial_height = (360 if (initial_responsive and (height is None or is_responsive is True)) else 450 if height is None else height) resize_height = (260 if (resize_responsive and (height is None or is_responsive is True)) else initial_height if height is None else height) wait_for( # 500px card minus (100px header + 20px padding) minus (20px padding on container) -> 360px left lambda: dash_duo.wait_for_element("#graph svg.main-svg").size.get( "height", -1) == initial_height, lambda: "initial graph height {}, expected {}".format( dash_duo.wait_for_element("#graph svg.main-svg").size.get( "height", -1), initial_height, ), ) dash_duo.wait_for_element("#resize").click() wait_for( # 500px card minus (200px header + 20px padding) minus (20px padding on container) -> 260px left lambda: dash_duo.wait_for_element("#graph svg.main-svg").size.get( "height", -1) == resize_height, lambda: "resized graph height {}, expected {}".format( dash_duo.wait_for_element("#graph svg.main-svg").size.get( "height", -1), resize_height, ), )