Networks#

Summary

On this page, you will see how to

  • use .plot.graph to plot networks

  • plot data as the node size and/or color

  • plot data as the edge weights

  • highlight certain nodes and edges using mark_nodes and mark_edges

  • adjust the plot style and coloring

  • animate your network plot (see also the article on animations).

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:

Example graph plot

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:

Simple graph plot

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:

Graph plot with some properties

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
Graph plot with positions according to spring model

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:

Styled-up graph plot with custom colormap and colorbar

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:

  1. 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}, where property is your dataset dimension, and my_prop the coordinate, or you can do the respective .isel

  2. 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:

A graph with highlights

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.