| Hosted by CoCalc | Download
1
# -*- coding: utf-8 -*-
2
3
r"""
4
Bent function Cayley graph dashboard
5
6
A simple web interface to the databases of bent function Cayley graph
7
classifications. This version uses Plotly Dash and SQLite3.
8
9
Run with:
10
sage -python bent_function_cayley_graph_dashboard.py
11
12
AUTHORS:
13
14
- Paul Leopardi (2018-06-17): initial version
15
16
"""
17
18
#*****************************************************************************
19
# Copyright (C) 2018 Paul Leopardi [email protected]
20
#
21
# Distributed under the terms of the GNU General Public License (GPL)
22
# as published by the Free Software Foundation; either version 2 of
23
# the License, or (at your option) any later version.
24
# http://www.gnu.org/licenses/
25
#*****************************************************************************
26
27
from future import standard_library
28
standard_library.install_aliases()
29
import dash
30
import dash_core_components as dcc
31
import dash.dependencies as dd
32
import dash_html_components as html
33
import flask
34
import os
35
import pandas as pd
36
import plotly.graph_objs as go
37
import database_interface as db
38
import sys
39
40
from io import StringIO
41
from flask import Flask
42
from pandas import DataFrame
43
44
import sage.all
45
46
from boolean_cayley_graphs.bent_function import BentFunction
47
from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification
48
49
# From https://github.com/mbkupfer/dash-with-flask/blob/master/dash_app.py
50
server = Flask(__name__)
51
app = dash.Dash(__name__, server = server)
52
53
app.config.requests_pathname_prefix = ''
54
55
app.config['suppress_callback_exceptions'] = True
56
57
output_dir = 'downloads'
58
output_files = {
59
'1_bent_function': {
60
'filename': 'download_bent_function.csv',
61
'label': 'Bent function'},
62
'2_cg_class_list': {
63
'filename': 'download_cg_class_list.csv',
64
'label': 'Cayley graph class list'},
65
'3_matrices': {
66
'filename': 'download_matrices.csv',
67
'label': 'Contents of matrices'}}
68
69
app.layout = html.Div([
70
html.H2('Bent function--Cayley graph virtual laboratory (prototype)'),
71
html.Div([
72
html.H3('Choose a database'),
73
dcc.RadioItems(
74
options=[
75
{
76
'label': '2 dimensions',
77
'value': 'p2'
78
},
79
{
80
'label': '4 dimensions',
81
'value': 'p4'
82
},
83
{
84
'label': '6 dimensions',
85
'value': 'p6'
86
},
87
{
88
'label': '8 dimensions to degree 3',
89
'value': 'p8'
90
},
91
{
92
'label': 'sigma functions to 8 dimensions',
93
'value': 'sigma'
94
},
95
{
96
'label': 'tau functions to 8 dimensions',
97
'value': 'tau'
98
},
99
{
100
'label': 'CAST-128 S-box functions',
101
'value': 'cast128'
102
},
103
],
104
value='p2',
105
id='database-filter'
106
)
107
]),
108
html.Div([],
109
id='bent-function-filter-div'
110
),
111
html.Div([],
112
id='report-output-div'
113
),
114
html.Div([
115
html.H3(
116
'Select a CSV file to Download.'),
117
dcc.Dropdown(
118
id='download-dropdown',
119
value=output_files['1_bent_function']['filename'],
120
options=[{
121
'label': output_files[key]['label'],
122
'value': output_files[key]['filename']}
123
for key in sorted(output_files.keys())]),
124
html.A(
125
id='download-link',
126
children='Download the CSV file from this link.',
127
style={'padding-bottom': 200})])],
128
style={'font-family': ["Open Sans", "Helvetica", "Arial"]})
129
130
131
# From https://github.com/mbkupfer/dash-with-flask/blob/master/dash_app.py
132
@server.route('/')
133
def bfcgd():
134
return app
135
136
137
def bent_function_filter(options):
138
return [
139
html.H3('Choose a bent function'),
140
dcc.Dropdown(
141
options=options,
142
value=None,
143
id='bent-function-filter'
144
)
145
]
146
147
148
@app.callback(
149
dd.Output('bent-function-filter-div', 'children'),
150
[dd.Input('database-filter', 'value')])
151
def set_bent_function_options(selected_database):
152
153
try:
154
conn = db.connect_to_database(
155
selected_database)
156
except IOError:
157
print('Cannot connect to database {}.'.format(selected_database))
158
return
159
160
bent_function_names = pd.read_sql('''
161
SELECT name
162
FROM bent_function
163
''',
164
conn)
165
conn.close()
166
options=[
167
{
168
'label': opt[0],
169
'value': opt[0]
170
}
171
for opt in bent_function_names.values
172
]
173
return bent_function_filter(options)
174
175
176
class Capturing(list):
177
'''
178
From kindall:
179
https://stackoverflow.com/questions/16571150/how-to-capture-stdout-output-from-a-python-function-call
180
'''
181
def __enter__(self):
182
self._stdout = sys.stdout
183
sys.stdout = self._stringio = StringIO()
184
return self
185
def __exit__(self, *args):
186
self.extend(self._stringio.getvalue().splitlines())
187
del self._stringio # free up some memory
188
sys.stdout = self._stdout
189
190
191
def matrix_figure(matrix, colorscale='Earth'):
192
n = matrix.nrows()
193
return {
194
'data': [
195
go.Heatmap(
196
z=[
197
[
198
matrix[i,j]
199
for j in range(n)
200
]
201
for i in range(n)
202
],
203
colorscale=colorscale
204
)
205
],
206
'layout': {
207
'width': '512',
208
'height': '512',
209
'yaxis': {
210
'autorange': 'reversed'
211
}
212
}
213
}
214
215
216
@app.callback(
217
dd.Output('report-output-div', 'children'),
218
[dd.Input('bent-function-filter', 'value')],
219
[dd.State('database-filter', 'value')])
220
def select_bent_function(bentf_name, selected_database):
221
try:
222
conn = db.connect_to_database(
223
selected_database)
224
except IOError:
225
return ['Cannot connect to database {}.'.format(selected_database)]
226
227
if bentf_name is None:
228
return []
229
bentf_c = db.cdb.select_classification_where_name(
230
conn,
231
bentf_name)
232
bentf_path = os.path.join(output_dir, 'download')
233
bentf_c.save_as_csv(bentf_path)
234
with Capturing() as report:
235
bentf_c.report()
236
wc_matrix = bentf_c.weight_class_matrix
237
wc_graph = dcc.Graph(
238
figure=matrix_figure(wc_matrix),
239
id='wc-graph')
240
ci_matrix = bentf_c.bent_cayley_graph_index_matrix
241
ci_graph = dcc.Graph(
242
figure=matrix_figure(ci_matrix),
243
id='ci-graph')
244
di_matrix = bentf_c.dual_cayley_graph_index_matrix
245
di_graph = dcc.Graph(
246
figure=matrix_figure(di_matrix),
247
id='di-graph')
248
return [
249
html.P(bentf_name + ':')] + [
250
html.P(line)
251
for line in report] + [
252
html.Table(
253
# Header
254
[
255
html.Tr([
256
html.Div([
257
html.Div([
258
html.B('Weight class matrix')],
259
style={
260
'textAlign': 'center',
261
'width': '33%',
262
'display': 'inline-block'}),
263
html.Div([
264
html.B('Cayley graph index matrix')],
265
style={
266
'textAlign': 'center',
267
'width': '33%',
268
'display': 'inline-block'}),
269
html.Div([
270
html.B('Dual Cayley graph index matrix')],
271
style={
272
'textAlign': 'center',
273
'width': '33%',
274
'display': 'inline-block'})],
275
style={
276
'width': '100%',
277
'display': 'inline-block'})])] +
278
# Body
279
[
280
html.Tr([
281
html.Div([
282
html.Div(
283
wc_graph,
284
style={
285
'width': '33%',
286
'display': 'inline-block'}),
287
html.Div(
288
ci_graph,
289
style={
290
'width': '33%',
291
'display': 'inline-block'}),
292
html.Div(
293
di_graph,
294
style={
295
'width': '33%',
296
'display': 'inline-block'})],
297
style={
298
'width': '100%',
299
'display': 'inline-block'})])])]
300
301
302
@app.callback(dd.Output('download-link', 'href'),
303
[dd.Input('download-dropdown', 'value')])
304
def update_href(output_filename):
305
relative_filename = os.path.join(
306
output_dir,
307
output_filename)
308
return '/' + relative_filename
309
310
311
@app.server.route('/downloads/<path:path>')
312
def serve_static(path):
313
root_dir = os.getcwd()
314
return flask.send_from_directory(
315
os.path.join(root_dir, output_dir),
316
path,
317
as_attachment=True)
318
319
if __name__ == '__main__':
320
app.run_server(debug=False,host="0.0.0.0",port=8051)
321
322