Skip to content

Advanced Tutorial (short)

This tutorial is for you, if you are already familiar with python and just want to understand the basic idea and the workflow. We also have a short look at networkx.

1. Setup

  1. Install networkx and net-bench (we suggest to do that via pip)
    pip install dsslab-net-bench
    pip install networkx
    
  2. We use the following aliases:
    import networkx as nx
    import dsslab.net_bench as dnb
    

2. Networkx (short)

If you aren't familiar with networkx, have a look at paragraph 1 in the entry-level tutorial and the networkx documentation.

A fast introduction/as a reminder:

  • There is always a graph: graph = nx.Graph()
  • The graph has nodes graph.add_nodes_from(["A", "B", "C", "D"])
  • that are connected by edges graph.add_edges_from([("A", "B"), ("B", "C"), ("C", "D"), ("D", "A")])

The nodes and edges can have attributes that we want to visualise. That's what net-bench is for.

3. Processing: setting positions

We set the positions of the nodes for the visualisation of the graph. We have two options to do that:

  1. NetworkX: Easy and already installed.
  2. Graphviz: Advanced and needs a complicated installation for Windows. Yields better layouts.

In this example we will use NetworkX for the positions. This works as follows:

layouter = dnb.Layouter()
positions = layouter.read_or_create_layout("positions.json", graph, seed=1234, k=1)
The layout in this context means the positions of the nodes in the image that is created later. The method for creating a layout (positions) takes in four parameters:

  • The path to which the positions file is written
  • The graph itself
  • A so-called seed. The seed determines the "randomness" of the positions
  • k is relevant_for_the_used_layout and determines the optimal distance between nodes. If nodes are too close together, increasing this value can yield better images.

The method returns a dictionary with the saved positions. If there already exists a file with this name at the specified path, this file is used and no new file is created.

4. Creation of images

The layout can now be used for visualisations. We use dnb.ImageGenerator to do that:

image_generator = dnb.ImageGenerator(graph)
image_generator.nodes.set_positions(positions)

Hint

When setting the positions with image_generator.nodes.set_positions(), you can either use the dict or the path to the positions file. The file is created, so that positions can be set within teams and can be tracked via Git.

Now we can choose different settings. We can for example, color all the edges grey:

image_generator.edges.set_colors("grey")

For the coloring of the nodes according to an existing, coded attribute with a qualitative mapping, see mappings. One example for a mapping is filter, which allows for filtering with a condition which you can define yourself:

image_generator.nodes.set_colors(dnb.qualitative("Attribute1", cmap="Set2"))

Where do attributes come from?

The attributes which are used for coding are the ones that can be defined in networkx: graph.nodes["A"]["Attribute1"] = "Value 1". In the workflow with net-bench they usually come from the different textsearch functions.

We want to scale the nodes according to their degree ("degree" being the cue, which internally starts the calculation of the degree). outrange defines, how big the smallest and biggest node can get:

# Different mappings would also be possible here
image_generator.nodes.set_sizes(dnb.sequential("degree", out_range=(100, 500)))

At this point we want to encourage you to have a deeper look at the different mapping_strategies. net-bench has many further possibilities for visualising graphs, some of them more complex.

Note

You can also use indegree, outdegree, betweenness, closeness as automatically calculated cues.

Last, the image is drawn and written to a file:

image_generator.draw().write_file("./image.svg")

Note

This can be shortened to:

image_generator = dnb.ImageGenerator(graph)
(
    image_generator.nodes.set_positions(positions)
    .set_colors(dnb.qualitative("Unser Attribute", cmap="Set2"))
    .set_sizes(dnb.sequential("degree", out_range=(100, 500)))
)
image_generator.edges.set_colors("grey")
image_generator.draw().write_file("./abbildung.svg")

5. An example of a workflow

This is an example of how net-bench can be useful for big graphs, like you probably will be working with.

Step 1: Reading in of an existing graph

There are multiple options to read in an existing graph in net-bench as well as NetworkX. Because this is an easy example, we want to use an existing network. Download this_file and save it.

Step 2: Creating a layout and setting the positions

import networkx as nx
import dsslab.net_bench as dnb

layouter = dnb.Layouter()
positions = layouter.read_or_create_layout("positions.json", graph, seed=1234, k=1)

# Creating an ImageGenerator object. An ImageGenerator is created with a graph and
# different settings for one (!) image.
image_generator = dnb.ImageGenerator(graph)

# Set the positions in the ImageGenerator.
image_generator.nodes.set_positions(positions)

Step 3: Setting sizes and colors

# Set the colors for the edges.
image_generator.edges.set_colors("grey")

# Set colors for the nodes. We use a qualitative mapping. This
# means that different categories can be colored differently.
image_generator.nodes.set_colors(dnb.qualitative("stage_of_sf", cmap="Set2"))

# Set node sizes. We use a sequential mapping. This means that continuous
# values are mapped onto a chosen scale (`out_range`).
# In this case, the node with the smallest degree would get circumference 5, the node
# with the biggest degree would get circumference 500.
image_generator.nodes.set_sizes(dnb.sequential("degree", out_range=(5, 500)))

Step 4: Creating and saving the image

# We draw and save the file. Drawing and writing are done separately
# because it is possible to create an image on different layers.
image_generator.draw().write_file("./image.svg")

The whole possible workflow can be downloaded_here. Try around with it for yourself!