-
Notifications
You must be signed in to change notification settings - Fork 0
/
metrics_dash.py
120 lines (89 loc) · 3.09 KB
/
metrics_dash.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
import os
import tempfile
from pathlib import Path
import altair as alt
import pandas as pd
import streamlit as st
from bokeh_plots import get_meshplot
from nanomesh import MeshContainer, data, metrics
st.set_page_config(page_title='Nanomesh metrics',
page_icon='📊',
initial_sidebar_state='expanded')
st.title('Compare mesh metrics')
st.write('Upload your own mesh or use the example data to generate metrics!')
def load_mesh(data_file):
suffix = Path(data_file.name).suffix
tmp = tempfile.NamedTemporaryFile(dir='.', suffix=suffix, delete=False)
tmp.write(data_file.getbuffer())
tmp.close()
mesh = MeshContainer.read(tmp.name).get('triangle')
os.unlink(tmp.name)
return mesh
@st.cache
def load_example_mesh(opts):
print('loading', opts)
return data.blob_mesh2d(opts=opts).get('triangle')
meshes = []
opts_choices = (
'q30a10',
'a10',
'q30',
'q30a5',
)
with st.sidebar:
st.markdown("""
This dashboard uses *nanomesh* to generate mesh metrics. For
more info, click
[here](https://nanomesh.readthedocs.io/en/latest/).
""")
st.header('Data')
if st.checkbox('Use example data'):
meshes = [load_example_mesh(opts=opts) for opts in opts_choices]
else:
st.markdown('Upload up to 4 meshes')
meshes = []
for n in range(4):
st.header(f'Mesh #{n+1}')
uploaded_file = st.file_uploader('Upload your mesh',
key=f'upload_{n}')
if uploaded_file:
mesh = load_mesh(uploaded_file)
meshes.append(mesh)
else:
break
if not meshes:
st.stop()
st.header('Metrics')
def format_func(raw_string):
return metrics._metric_dispatch[raw_string].name
metrics_list = st.multiselect('Select which metrics to plot',
default=('min_angle', 'max_angle'),
options=list(metrics._metric_dispatch),
format_func=format_func)
dfs = []
for i, mesh in enumerate(meshes):
with st.expander(f'Click to expand - Mesh #{i+1}'):
c1, c2 = st.columns(2)
with c1:
fig = get_meshplot(mesh)
st.bokeh_chart(fig, use_container_width=True)
with c2:
st.text(mesh)
df = pd.DataFrame(metrics.calculate_all_metrics(mesh))
dfs.append(df)
LEVEL = 'Mesh index'
df = pd.concat({i + 1: df for i, df in enumerate(dfs)}, names=(LEVEL, ))
df = df.reset_index(level=LEVEL)
for metric in metrics_list:
m = metrics._metric_dispatch[metric]
xlabel = f'{m.name} ({m.units})' if m.units else m.name
st.header(m.name)
st.markdown(m.description)
c = alt.Chart(df).mark_bar(opacity=0.3, binSpacing=1).encode(
x=alt.X(f'{metric}:Q', bin=alt.Bin(maxbins=50), title=xlabel),
y=alt.Y('count()', stack=None), # zero, center, normalize
color=f'{LEVEL}:N',
column=f'{LEVEL}:N',
tooltip=[f'count({metric})'])
# c.properties(title=desc.name, )
st.altair_chart(c)