Networks#
Summary
On this page, you will see how to
use
.plot.graph
to plot networksplot data as the node size and/or color
plot data as the edge weights
highlight certain nodes and edges using
mark_nodes
andmark_edges
adjust the plot style and coloring
animate your network plot (see also the article on animations).
Complete example: Static network
static_network:
based_on:
- .creator.universe
- .plot.graph
select:
graph_group: nw
graph_creation:
node_props: [opinion]
edge_props: [edge_weights]
at_time_idx: -1
graph_drawing:
positions:
model: spring
k: 2
nodes:
node_color:
from_property: opinion
node_size:
from_property: degree
scale_to_interval: [1, 200]
cmap:
continuous: true
from_values:
0: *red
0.5: *yellow
1: *mediumblue
vmin: 0.
vmax: 1.0
colorbar:
label: opinion $\sigma$
edges:
width:
from_property: edge_weights
Complete example: Animated network
animated_network:
based_on:
- .creator.universe
- .plot.graph
- .animation.ffmpeg
select:
graph_group: nw
graph_creation:
node_props: [opinion]
edge_props: [edge_weights]
at_time_idx: -1
graph_drawing:
positions:
model: spring
k: 2
nodes:
node_color:
from_property: opinion
node_size:
from_property: degree
scale_to_interval: [1, 200]
cmap:
continuous: true
from_values:
0: *red
0.5: *yellow
1: *mediumblue
vmin: 0.0
vmax: 1.0
colorbar:
label: opinion $\sigma$
edges:
arrowsize: 4
width:
from_property: edge_weights
graph_animation:
sel:
time:
from_property: opinion
animation:
writer_kwargs:
ffmpeg:
init:
fps: 3
saving:
dpi: 192
The .plot.graph
plot function combines and extends the following four NetworkX plotting utilities:
It preserves the full configurability of the above functions while offering additional features, e.g. plotting directly from a GraphGroup
, automatically mapping data to layout properties, or creating graph animations.
Example#
Here is an example graph plot, using the Utopia Opinionet model:
Let’s go through the configuration step-by-step:
First, base the plot on .creator.universe
(this is a universe plot) and .plot.graph
(the default plot function for graphs
).
Then, select the GraphGroup
from your model: in the case of Opinionet, this is the nw
GraphGroup
.
Lastly, specify the time at which you wish to show the network:
graph:
based_on:
- .creator.universe
- .plot.graph
select:
graph_group: nw # Adjust this to your own model's case
graph_creation:
at_time_idx: -1 # This can be any time
This is already enough to plot a simple graph:
Plotting data as node and edge properties#
Next, let’s select the properties you wish to use for the graph plot.
In our case, we plot the network at the final time step of the model, and want both the user opinion
property, as well as the edge_weight
property to be shown in the plot.
Add the following entries to the graph_creation
entry above:
graph:
# Everything as above ...
graph_creation:
at_time_idx: -1 # as above
node_props: [opinion]
edge_props: [edge_weights]
If you only wish to plot node properties or edge properties, you can drop the irrelevant entry.
Now plot these properties on the graph using the graph_drawing
key:
graph:
# Everything as above ...
graph_drawing:
nodes:
node_color:
from_property: opinion
node_size:
from_property: degree
edges:
width:
from_property: edge_weights
This plots the opinion
as the node color and the node degree as its size, and the edge_weights
as the edge width:
Changing the layout and appearance#
Let’s modify the graph’s appearance.
The arrows are a bit large, so let’s reduce the arrowsize
.
The nodes in the above plot are a little small: let’s scale them up.
To do this, add the following entry to nodes/node_size
in the above configuration:
graph:
# Everything as before ...
graph_drawing:
nodes:
node_size:
from_property: degree
scale_to_interval: [1, 200]
edges:
# .. as above ..
arrowsize: 4
This will scale the node size to a value between the interval you pass. The same can be done for the edge widths.
NetworkX offers a large selection of drawing models for visualising a graph, which you can control from the config use the positions
key:
graph:
graph_drawing:
positions:
model: spring
k: 2
The above example uses the spring_layout()
with two passes (k: 2
) to adjust the node distances.
You could also do
graph:
graph_drawing:
positions:
model: circular
to place the nodes on a circle using circular_layout()
.
Fixing the seed
If you don’t fix a random seed, the network may look different every time you plot it, depending on the layout you choose.
You can resolve this by setting the seed
parameter.
For example, when using the spring layout, do
graph:
graph_drawing:
positions:
model: spring
k: 2
seed: 42
Hint
If you have pygraphviz installed, the graphviz
layouts become available.
Simply specify model: graphviz_dot
to use dot
for layouting; the other graphviz layouting programs are also available.
Color settings#
Let us change the colormap used for the nodes, and add a label to the colorbar; in the graph_drawing/nodes
entry above, add the following:
graph:
# Everything as above ...
graph_drawing:
nodes:
# Everything as above ...
cmap:
continuous: true
from_values:
0: crimson
0.5: gold
1: dodgerblue
vmin: 0.
vmax: 1.0
colorbar:
label: opinion $\sigma$
The cmap
entry makes use of the
ColorManager, and offers a wide range of capabilities, including using different norms; take a look at the style section for more details.
The colorbar is automatically shown whenever a property mapping was done for the node colors. You can turn it off by setting
colorbar:
enabled: false
You can also change location, size, or labels of the colorbar:
colorbar:
labels:
0: left
0.5: center
1: right
shrink: .5
aspect: 10
orientation: horizontal
Taken together, all these changes generate a plot like this:
Note
If you have all node_props
or edge_props
in one container (HDF5 dataset) respectively, there are two possibilities to make subselections in the containers:
When you only use either node or edge properties, or you want to make the same subselection on both your node and your edge dataset, you can simply do a
.sel: {property: my_prop}
, whereproperty
is your dataset dimension, andmy_prop
the coordinate, or you can do the respective.isel
When you need to perform different subselections on your node and edge datasets—say you want node betweenness centrality and edge weight—you need to specify them via the DAG’s select interface, and the procedure needs to include the following steps:
select:
graph_group: g_static
betw:
path: network/vertex_metrics
transform:
- .sel: [!dag_prev , {property: betweenness}]
- .squeeze_with_drop
wei:
path: network/edge_properties
transform:
- .sel: [!dag_prev , {property: weight}]
- .squeeze_with_drop
compute_only: [graph_group, betw, wei]
# Make the selected tags available as property maps
register_property_maps:
- betw
- wei
# clear_existing_property_maps: false
graph_creation:
at_time_idx: 0
edge_props: [wei]
node_props: [betw]
# sel: {time: 0} # applied to both properties
graph_drawing:
edges:
edge_color: k
width:
from_property: wei
scale_to_interval: [0.1, 2.0]
nodes:
node_color:
from_property: betw
See draw_graph()
and utopya.eval.plots.graph
for detailed interface information.
For detailed descriptions of the networkx plot functions that are used here, refer to the NetworkX docs.
Add labels and highlights#
You can add node and edge labels by adding the node_labels
and edge_labels
keys to the graph_drawing
entry:
graph:
# Everything as above ...
graph_drawing:
# Everything as above ...
# Just add these two entries:
node_labels:
enabled: True
edge_labels:
enabled: True
Labels need to be explicity enabled. Labelling all nodes and edges may crowd the plot, so let’s only label some of the nodes:
graph:
# Everything as above ...
graph_drawing:
# Everything as above ...
# Just add these two entries:
node_labels:
enabled: True
labels:
0: 'node 0'
1: 'node 1'
edge_labels:
enabled: True
edge_labels:
[0, 1]: "(0, 1)"
[1, 3]: "(1, 3)"
We can also highlight certain nodes and edges, to create a plot that looks like this:
To do this, use the graph_drawing/mark_nodes
and graph_drawing/mark_edges
keys.
You can also reduce the transparency of the unmarked edges to make the marked ones more prominent:
graph_highlighted:
# Everything as above ..
graph_drawing:
nodes:
# As before ...
# Reduce the transparency of the edge weights
edges:
edge_color: [0, 0, 0, 0.05]
width:
from_property: edge_weights
scale_to_interval: [0, 1]
# Add labels for the nodes in the path
node_labels:
enabled: True
show_only: &nodelist !range [2, 12] # [2, 3, .., 11]
# Mark the nodes in the nodelist
mark_nodes:
nodelist: *nodelist
color: crimson
# Mark some edges (will be ignored if they do not exist)
mark_edges:
colors:
[24, 11]: crimson
[18, 15]: crimson
[49, 15]: crimson
# add more edges to mark here ...
Animations#
You can animate your network plot by also basing your plot on one of the base animation functions (e.g. .animation.ffmpeg
) and adding a graph_animation
entry to your configuration:
animated_network:
based_on:
- .creator.universe
- .plot.graph
- .animation.ffmpeg # Use the ffmpeg writer
# Everything else as above.
# Just add this entry to make the 'opinion' change over time:
graph_animation:
sel:
time:
from_property: opinion
We discuss animations in more detail on the animations page, including how to increase the animation resolutions.