Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
FoodInformatics
msx-tool
Commits
fa056eec
Commit
fa056eec
authored
Jul 22, 2021
by
Jim Hoekstra
👋🏻
Browse files
fix node positions in graph
parent
d3179f12
Changes
2
Hide whitespace changes
Inline
Side-by-side
dash_app/callbacks.py
View file @
fa056eec
...
...
@@ -11,13 +11,33 @@ from dash_app.words import AssociatedWords
word2vec_model
=
AssociatedWords
()
@
app
.
callback
(
Output
(
component_id
=
'msx-graph'
,
component_property
=
'autoRefreshLayout'
),
Input
(
component_id
=
'submit-word-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'add-word-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'extend-graph-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'remove-word-button'
,
component_property
=
'n_clicks'
),
State
(
component_id
=
'msx-graph-div'
,
component_property
=
'children'
),
)
def
set_auto_refresh_layout
(
submit_word_button
,
add_word_button
,
extend_graph_button
,
remove_word_button
,
msx_graph
):
callback_context
=
dash
.
callback_context
button_id
=
callback_context
.
triggered
[
0
][
'prop_id'
].
split
(
'.'
)[
0
]
if
button_id
==
'submit-word-button'
:
return
True
else
:
return
False
@
app
.
callback
(
Output
(
component_id
=
'msx-graph-div'
,
component_property
=
'children'
),
Input
(
component_id
=
'submit-word-button'
,
component_property
=
'n_clicks'
),
State
(
component_id
=
'base-word-input'
,
component_property
=
'value'
),
)
def
update_graph_div
(
submit_word_button
):
def
update_graph_div
(
submit_word_button
,
base_word_input
):
graph
=
Graph
()
graph
.
set_nodes_and_edges
({
'nodes'
:
[],
'edges'
:
[]})
base_word_lower
=
base_word_input
.
lower
()
graph
.
add_node
(
base_word_lower
,
is_base_node
=
1
)
# graph.set_nodes_and_edges({'nodes': [], 'edges': []})
return
graph
.
get_cytoscape_graph
(
'msx-graph'
)
...
...
@@ -39,26 +59,25 @@ def update_base_word(submit_word_button, base_word_input):
@
app
.
callback
(
Output
(
component_id
=
'graph-elements-div'
,
component_property
=
'children'
),
Input
(
component_id
=
'
submit-word-button
'
,
component_property
=
'
n_clicks
'
),
Input
(
component_id
=
'
base-word-div
'
,
component_property
=
'
children
'
),
Input
(
component_id
=
'add-word-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'extend-graph-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'remove-word-button'
,
component_property
=
'n_clicks'
),
State
(
component_id
=
'base-word-input'
,
component_property
=
'value'
),
State
(
component_id
=
'add-word-input'
,
component_property
=
'value'
),
State
(
component_id
=
'graph-elements-div'
,
component_property
=
'children'
),
State
(
component_id
=
'msx-graph-div'
,
component_property
=
'children'
),
State
(
component_id
=
'msx-graph'
,
component_property
=
'selectedNodeData'
),
State
(
component_id
=
'base-word-div'
,
component_property
=
'children'
),
prevent_initial_call
=
True
)
def
update_graph_elements
(
submit_word_button
,
add_word_button
,
extend_graph_button
,
remove_word_button
,
base_word_input
,
add_word_input
,
nodes_and_edges
,
selected_nodes
,
base_word_state
):
def
update_graph_elements
(
base_word_state
,
add_word_button
,
extend_graph_button
,
remove_word_button
,
base_word_input
,
add_word_input
,
nodes_and_edges
,
msx_graph
,
selected_nodes
):
callback_context
=
dash
.
callback_context
button_id
=
callback_context
.
triggered
[
0
][
'prop_id'
].
split
(
'.'
)[
0
]
graph
=
Graph
()
if
button_id
==
'
submit-word-button
'
:
if
button_id
==
'
base-word-div
'
:
if
base_word_input
is
not
None
:
if
base_word_input
!=
''
:
graph
.
fill_with_associations
(
word2vec_model
,
base_word_input
)
...
...
@@ -107,25 +126,8 @@ def update_graph_elements(submit_word_button, add_word_button, extend_graph_butt
@
app
.
callback
(
Output
(
component_id
=
'msx-graph'
,
component_property
=
'elements'
),
Input
(
component_id
=
'graph-elements-div'
,
component_property
=
'children'
),
prevent_initial_call
=
True
)
def
update_graph
(
nodes_and_edges
):
graph
=
Graph
()
graph
.
set_nodes_and_edges
(
json
.
loads
(
nodes_and_edges
))
return
graph
.
get_elements
()
@
app
.
callback
(
Output
(
component_id
=
'msx-graph'
,
component_property
=
'autoRefreshLayout'
),
Input
(
component_id
=
'add-word-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'extend-graph-button'
,
component_property
=
'n_clicks'
),
Input
(
component_id
=
'remove-word-button'
,
component_property
=
'n_clicks'
),
prevent_initial_call
=
True
)
def
set_auto_refresh_layout
(
add_word_button
,
extend_graph_button
,
remove_word_button
):
callback_context
=
dash
.
callback_context
button_id
=
callback_context
.
triggered
[
0
][
'prop_id'
].
split
(
'.'
)[
0
]
if
button_id
==
'add-word-button'
or
button_id
==
'remove-word-button'
:
return
False
if
button_id
==
'extend-graph-button'
:
return
True
dash_app/graph.py
View file @
fa056eec
import
dash_cytoscape
as
cyto
import
pandas
as
pd
import
numpy
as
np
from
math
import
factorial
...
...
@@ -8,6 +9,7 @@ class Graph:
def
__init__
(
self
):
self
.
nodes
=
[]
self
.
edges
=
[]
self
.
positions
=
{}
self
.
COUNT_THRESHOLD
=
2
self
.
MAX_NUM_WORDS
=
10
...
...
@@ -34,13 +36,32 @@ class Graph:
self
.
add_node
(
node
)
def
add_node
(
self
,
node
,
is_base_node
=
0
):
node_dict
=
{
'data'
:
{
'id'
:
node
,
'label'
:
node
,
'is_base_node'
:
is_base_node
}}
node_dict
=
{
'data'
:
{
'id'
:
node
,
'label'
:
node
,
'is_base_node'
:
is_base_node
}
,
'position'
:
self
.
get_node_position
(
node
,
is_base_node
)
}
if
is_base_node
:
node_dict
[
'selectable'
]
=
False
node_dict
[
'grabbable'
]
=
False
if
node_dict
not
in
self
.
nodes
:
self
.
nodes
.
append
(
node_dict
)
def
get_node_position
(
self
,
node_id
,
is_base_node
):
if
is_base_node
:
return
{
'x'
:
0
,
'y'
:
0
}
else
:
position_id
=
0
while
str
(
position_id
)
in
self
.
positions
:
position_id
+=
1
length
=
position_id
*
4
+
80
angle
=
((
90.0
-
37.5
*
position_id
)
/
180.0
)
*
np
.
pi
if
angle
<
-
np
.
pi
:
angle
+=
(
2
*
np
.
pi
)
x
=
length
*
np
.
cos
(
angle
)
y
=
length
*
np
.
sin
(
angle
)
position
=
{
'x'
:
x
,
'y'
:
-
y
}
self
.
positions
[
str
(
position_id
)]
=
node_id
return
position
def
add_edges
(
self
,
source
,
targets
):
for
target
in
targets
:
self
.
add_edge
(
source
,
target
)
...
...
@@ -57,6 +78,7 @@ class Graph:
if
node_idx_to_remove
>=
0
:
self
.
nodes
.
pop
(
node_idx_to_remove
)
self
.
positions
=
{
position_id
:
node_id
for
position_id
,
node_id
in
self
.
positions
.
items
()
if
node_id
!=
node
}
self
.
remove_edges
(
node
)
def
remove_edges
(
self
,
node
):
...
...
@@ -69,11 +91,12 @@ class Graph:
self
.
edges
.
pop
(
edge_idx_to_remove
)
def
get_nodes_and_edges
(
self
):
return
{
'nodes'
:
self
.
nodes
,
'edges'
:
self
.
edges
}
return
{
'nodes'
:
self
.
nodes
,
'edges'
:
self
.
edges
,
'positions'
:
self
.
positions
}
def
set_nodes_and_edges
(
self
,
nodes_and_edges
):
self
.
nodes
=
nodes_and_edges
[
'nodes'
]
self
.
edges
=
nodes_and_edges
[
'edges'
]
self
.
positions
=
nodes_and_edges
[
'positions'
]
def
get_elements
(
self
):
elements
=
[]
...
...
@@ -84,8 +107,8 @@ class Graph:
def
get_cytoscape_graph
(
self
,
component_id
):
elements
=
self
.
get_elements
()
return
cyto
.
Cytoscape
(
id
=
component_id
,
autoRefreshLayout
=
Tru
e
,
layout
=
{
'name'
:
'
cose'
,
'animate'
:
True
},
autoRefreshLayout
=
Fals
e
,
layout
=
{
'name'
:
'
preset'
},
style
=
{
'width'
:
'100%'
,
'height'
:
'100%'
},
elements
=
elements
,
userZoomingEnabled
=
False
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment