Last active
June 13, 2018 18:38
-
-
Save asherp/674e2380a5dbc41f57574aeae9ecaf2d to your computer and use it in GitHub Desktop.
Demonstrates saving state of previous camera when a new graph loads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dash | |
from dash.dependencies import Input, Output, State, Event | |
import dash_core_components as dcc | |
import dash_html_components as html | |
import plotly.graph_objs as go | |
import numpy as np | |
class dccType(object): | |
def __init__(self, divtype, component_property = 'value', string = str, **kwargs): | |
self.divtype = divtype | |
self.kwargs = kwargs | |
self.component_property = component_property | |
self.string = string | |
def div(self, *args, **kwargs): | |
div_dict = {} | |
for k,v in self.kwargs.items(): | |
try: | |
div_dict[k] = v(*args) | |
except: | |
div_dict[k] = v | |
for k,v in kwargs.items(): | |
div_dict[k] = v | |
return self.divtype(**div_dict) | |
def input(self, *args, **kwargs): | |
component_property = kwargs.pop('component_property', self.component_property) | |
try: | |
return Input(self.id(*args), component_property) | |
except: | |
return Input(self.kwargs['id'], component_property) | |
def output(self, *args, **kwargs): | |
component_property = kwargs.pop('component_property', self.component_property) | |
try: | |
return Output(self.id(*args), component_property) | |
except: | |
return Output(self.kwargs['id'], component_property) | |
def state(self, *args, **kwargs): | |
component_property = kwargs.pop('component_property', self.component_property) | |
try: | |
return State(self.id(*args), component_property) | |
except: | |
return State(self.kwargs['id'], component_property) | |
def event(self, *args, **kwargs): | |
component_property = kwargs.pop('component_property', self.component_property) | |
try: | |
return Event(self.id(*args), component_property) | |
except: | |
return Event(self.kwargs['id'], component_property) | |
def id(self, *args): | |
return self.kwargs['id'](*args) | |
def get_random_points(n = 200): | |
x, y, z = np.random.multivariate_normal(np.array([0,0,0]), np.eye(3), n).transpose() | |
trace1 = go.Scatter3d( | |
x=x, | |
y=y, | |
z=z, | |
mode='markers', | |
marker=dict( | |
size=12, | |
line=dict( | |
color='rgba(217, 217, 217, 0.14)', | |
width=0.5 | |
), | |
opacity=0.8 | |
) | |
) | |
return trace1 | |
def get_layout(x_limits, y_limits, z_limits, title = 'slice plot'): | |
return go.Layout( | |
scene = dict( | |
aspectmode = 'manual', | |
xaxis = dict(range=x_limits), | |
yaxis = dict(range=y_limits), | |
zaxis = dict(range=z_limits), | |
aspectratio = { | |
'x':(x_limits[1]-x_limits[0])/10., | |
'y':(y_limits[1]-y_limits[0])/10., | |
'z':(z_limits[1]-z_limits[0])/10.}), | |
legend=dict(x=-.1, y=1.2), | |
autosize = False, | |
# width=700, | |
height=600, | |
margin=go.Margin( | |
l=30, | |
r=30, | |
# b=0, | |
t=50, | |
pad=4 ), | |
title = title, | |
showlegend = True, ) | |
app = dash.Dash() | |
app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'}) | |
app.config['suppress_callback_exceptions']=False | |
greeting = dccType( | |
html.Div, | |
id = 'an-id-you-never-need-to-type-again', | |
children = ['Hello World'], | |
className = 'one columns', | |
component_property = 'children') | |
greeting_options = dccType( | |
dcc.Dropdown, | |
id = 'dropdown-id-blah-blah', | |
options=[ | |
{'label': 'Hi there!', 'value': 'Hi there!'}, | |
{'label': 'Hello Cleveland!', 'value': 'Hello Cleveland!'}, | |
{'label': 'Hi San Francisco!', 'value': 'Hi San Francisco!'} | |
], | |
value='Hi there!', #the default component_property is 'value' | |
) | |
### Lambdas for component properties allows for more component reuse | |
greeting_style = dccType( | |
dcc.Dropdown, | |
id = lambda prefix: '{}-style'.format(prefix), | |
options = [ | |
dict(label = 'white', value = 'white'), | |
dict(label = 'red', value = 'red'), | |
dict(label = 'blue', value = 'blue') | |
], | |
value = 'white') | |
n_points = dccType( | |
dcc.Slider, | |
id = 'my-slider', | |
min = 1, | |
max = 200, | |
step = 1, | |
updatemode = 'mouseup', | |
) | |
options_outer = dccType( | |
html.Div, | |
children = [greeting_options.div(), | |
greeting_style.div('background'), | |
greeting_style.div('text'), | |
html.Br(), | |
n_points.div()], | |
className = 'two columns') | |
my_graph = dccType( | |
dcc.Graph, | |
id = 'my-graph', | |
figure = dict(data = [get_random_points()], layout = get_layout([-5, 5], [-5, 5], [-5, 5])), | |
component_property = 'figure', | |
className = 'four columns') | |
app.layout = html.Div(children=[greeting.div(), options_outer.div(), my_graph.div()]) | |
@app.callback(greeting.output(), [greeting_options.input()]) | |
def update_greeting(dropdown_value): | |
return dropdown_value | |
@app.callback( | |
greeting.output(component_property = 'style'), | |
[greeting_style.input('background'), greeting_style.input('text')]) | |
def update_greeting_style(bgcolor, textcolor): | |
return dict(background = bgcolor, color = textcolor) | |
@app.callback(my_graph.output(), [n_points.input()], [my_graph.state(component_property = 'relayoutData')]) | |
def update_graph(n, relayoutData): | |
layout = get_layout([-5, 5], [-5, 5], [-5, 5]) | |
if relayoutData is not None: | |
if 'scene.camera' in relayoutData.keys(): | |
print 'update_main_graph camera updating' | |
layout['scene']['camera'] = relayoutData['scene.camera'] | |
return dict(data = [get_random_points(n)], layout = layout) | |
if __name__ == '__main__': | |
app.run_server(debug=True, port = 8000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment