Skip to content

Commit 576f038

Browse files
authored
Add dashboards for generating meshes and mesh metrics (#274)
* Implement dashboards using streamlit / bokeh
1 parent b2e2564 commit 576f038

File tree

8 files changed

+575
-21
lines changed

8 files changed

+575
-21
lines changed

dash/bokeh_plots.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import itertools
2+
3+
import numpy as np
4+
from bokeh.models import LinearColorMapper
5+
from bokeh.palettes import Category10_10 as catpalette
6+
from bokeh.palettes import Viridis256 as palette
7+
from bokeh.plotting import figure
8+
from bokeh.transform import factor_cmap
9+
10+
from nanomesh import Image, metrics
11+
12+
13+
def image_plot(data):
14+
if isinstance(data, Image):
15+
data = data.image
16+
17+
fig = figure(tooltips=[('x', '$x'), ('y', '$y'), ('value', '@image')],
18+
match_aspect=True,
19+
border_fill_alpha=0.0,
20+
height=300)
21+
22+
fig.x_range.range_padding = fig.y_range.range_padding = 0
23+
24+
dw, dh = data.shape
25+
26+
# must give a vector of image data for image parameter
27+
fig.image(image=[data],
28+
x=0,
29+
y=0,
30+
dw=dw,
31+
dh=dh,
32+
palette='Viridis11',
33+
level='image')
34+
fig.grid.grid_line_width = 0.5
35+
return fig
36+
37+
38+
def contour_mesh(mesher):
39+
fig = figure(title='Line Mesh',
40+
tooltips=[('x', '$x'), ('y', '$y'), ('value', '@image')],
41+
match_aspect=True,
42+
border_fill_alpha=0.0)
43+
44+
c = mesher.contour
45+
46+
vert_x, vert_y = c.points.T
47+
48+
colors = itertools.cycle(catpalette)
49+
50+
for i in np.unique(c.cell_data['segment_markers']):
51+
color = next(colors)
52+
mask = c.cell_data['segment_markers'] != i
53+
54+
if mask is not None:
55+
cells = c.cells[~mask.squeeze()]
56+
57+
lines_x = (vert_x[cells] + 0.5).tolist()
58+
lines_y = (vert_y[cells] + 0.5).tolist()
59+
60+
fig.multi_line(lines_y,
61+
lines_x,
62+
legend_label=f'{i}',
63+
line_width=5,
64+
color=color)
65+
66+
fig.hover.point_policy = 'follow_mouse'
67+
68+
# image
69+
d = mesher.image
70+
71+
fig.x_range.range_padding = fig.y_range.range_padding = 0
72+
73+
dw, dh = d.shape
74+
# must give a vector of image data for image parameter
75+
fig.image(image=[d],
76+
x=0,
77+
y=0,
78+
dw=dw,
79+
dh=dh,
80+
palette='Viridis11',
81+
level='image')
82+
fig.grid.grid_line_width = 0.0
83+
return fig
84+
85+
86+
def get_meshplot(mesh):
87+
fig = figure(title='Meshplot',
88+
tooltips=[('Physical', '@physical'), ('(x, y)', '($x, $y)'),
89+
('index', '$index')],
90+
x_axis_label='x',
91+
y_axis_label='y',
92+
match_aspect=True)
93+
94+
color_mapper = LinearColorMapper(palette=palette)
95+
96+
xs = mesh.points[mesh.cells][:, :, 0]
97+
ys = mesh.points[mesh.cells][:, :, 1]
98+
cs = mesh.cell_data['physical']
99+
100+
data = {
101+
'x': xs.tolist(),
102+
'y': ys.tolist(),
103+
'physical':
104+
tuple(mesh.number_to_field.get(val, str(val)) for val in cs)
105+
}
106+
107+
factors = tuple(reversed(mesh.fields))
108+
109+
fig.patches(
110+
'x',
111+
'y',
112+
source=data,
113+
# line_color='white',
114+
fill_color=factor_cmap('physical', palette=catpalette,
115+
factors=factors),
116+
fill_alpha=0.7,
117+
line_width=1)
118+
fig.hover.point_policy = 'follow_mouse'
119+
120+
return fig
121+
122+
123+
def get_metric_hist(mesh, metric):
124+
metric_vals = getattr(metrics, metric)(mesh)
125+
126+
hist, edges = np.histogram(metric_vals, bins=50)
127+
128+
fig = figure(
129+
title=f'Histogram of triangle {metric}',
130+
x_axis_label=f'Triangle {metric}',
131+
y_axis_label='Frequency',
132+
tooltips=[
133+
('value', '@top'),
134+
],
135+
)
136+
fig.quad(top=hist,
137+
bottom=0,
138+
left=edges[:-1],
139+
right=edges[1:],
140+
fill_color='navy',
141+
line_color='white',
142+
alpha=0.5)
143+
fig.hover.point_policy = 'follow_mouse'
144+
145+
return fig
146+
147+
148+
def get_metric_2dplot(mesh, metric):
149+
metric_vals = getattr(metrics, metric)(mesh)
150+
151+
color_mapper = LinearColorMapper(palette=palette)
152+
153+
fig = figure(title=f'Triplot of triangle {metric}',
154+
tooltips=[('Physical', '@physical'),
155+
(metric.capitalize(), f'@{metric}'),
156+
('(x, y)', '($x, $y)')],
157+
x_axis_label='x',
158+
y_axis_label='y',
159+
match_aspect=True)
160+
161+
xs = mesh.points[mesh.cells][:, :, 0]
162+
ys = mesh.points[mesh.cells][:, :, 1]
163+
164+
cs = mesh.cell_data['physical']
165+
166+
data = {
167+
'x': xs.tolist(),
168+
'y': ys.tolist(),
169+
'label': cs.tolist(),
170+
metric: metric_vals.tolist(),
171+
}
172+
173+
fig.patches('x',
174+
'y',
175+
source=data,
176+
fill_color={
177+
'field': metric,
178+
'transform': color_mapper
179+
},
180+
line_width=1)
181+
fig.hover.point_policy = 'follow_mouse'
182+
183+
return fig

0 commit comments

Comments
 (0)