-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplotlyDash_annotations.py
146 lines (130 loc) · 3.75 KB
/
plotlyDash_annotations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from dash import Dash, dcc, html, Input, Output, State
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate
import plotly.express as px
import numpy as np
# create image and plotly express object
img = np.random.randint(0, 255, (90, 160))
fig = px.imshow(img, color_continuous_scale='Blugrn')
# update layout
fig.update_layout(
template='plotly_dark',
plot_bgcolor='rgba(0, 0, 0, 0)',
paper_bgcolor='rgba(0, 0, 0, 0)',
width=700,
height=500,
margin={
'l': 0,
'r': 0,
't': 20,
'b': 0,
}
)
# hide color bar
fig.update_coloraxes(showscale=False)
# Build App
app = Dash(
__name__,
external_stylesheets=[dbc.themes.SLATE],
meta_tags=[
{
'name': 'viewport',
'content': 'width=device-width, initial-scale=1.0'
}
]
)
# app layout
app.layout = dbc.Container(
[
dbc.Row(
dbc.Col(
dcc.Graph(
id='graph',
figure=fig,
config={
'scrollZoom': True,
'displayModeBar': False,
}
),
width={'size': 5, 'offset': 0}
), justify='around'
),
dbc.Row(
[
dbc.Col(
[
html.A(
html.Button(
'Refresh Page',
id='refresh_button'
),
href='/'
),
dcc.Markdown(
'''
# Functionality:
- click anywhere on the image, shape is created at click position
- use the "Refresh Page" button to reload the image
'''
)
], width={'size': 5, 'offset': 0}
),
], justify='around'
)
], fluid=True
)
@ app.callback(
Output('graph', 'figure'),
State('graph', 'figure'),
Input('graph', 'clickData')
)
def get_click(graph_figure, clickData):
if not clickData:
raise PreventUpdate
else:
points = clickData.get('points')[0]
x = points.get('x')
y = points.get('y')
# create new shape
new_shape = create_shape(x=x, y=y, size=5)
# get existing shapes
shapes = graph_figure['layout'].get('shapes', [])
shapes.extend(new_shape)
# update figure layout
graph_figure['layout'].update(shapes=shapes)
return graph_figure
def create_shape(x, y, size=4, color='rgba(39,43,48,255)'):
"""
function creates a shape for a dcc.Graph object
Args:
x: x coordinate of center point for the shape
y: y coordinate of center point for the shape
size: size of annotation (diameter)
color: (rgba / rgb / hex) string or any other color string recognized by plotly
Returns:
a list containing a dictionary, keys corresponding to dcc.Graph layout update
"""
shape = [
{
'editable': True,
'xref': 'x',
'yref': 'y',
'layer': 'above',
'opacity': 1,
'line': {
'color': color,
'width': 1,
'dash': 'solid'
},
'fillcolor': color,
'fillrule': 'evenodd',
'type': 'circle',
'x0': x - size / 2,
'y0': y - size / 2,
'x1': x + size / 2,
'y1': y + size / 2
}
]
return shape
if __name__ == '__main__':
app.run_server(debug=True, port=8053)