Skip to content

Instantly share code, notes, and snippets.

@asherp
Last active June 13, 2018 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asherp/674e2380a5dbc41f57574aeae9ecaf2d to your computer and use it in GitHub Desktop.
Save asherp/674e2380a5dbc41f57574aeae9ecaf2d to your computer and use it in GitHub Desktop.
Demonstrates saving state of previous camera when a new graph loads
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