Visualization Guide¶
How LaNet-vi Plots Work¶
LaNet-vi creates hierarchical network visualizations using a circular, shell-based layout that reveals the k-core structure.
Layout Algorithm¶
The placement is the one of the C++ LaNet-vi (Alvarez-Hamelin, Dall'Asta, Barrat &
Vespignani, NIPS 2005; -coordDistributionAlgorithm classic):
- Nested components. Inside the component of index k (all its nodes have index ≥ k), the connected pieces of the nodes with index > k become child components of index k + 1; the nodes with index exactly k form the component's clusters. The whole graph is the root component of index 0, so every k-core, k-dense or d-core level is a layer of this tree.
- Radii. The top core of a branch gets a disc whose radius grows with the square root of the sum of the squared log-degrees of its nodes; each enclosing shell adds one unit of radius. Shells are therefore rings one unit apart, the highest index innermost.
- Centers. A component with siblings is offset from its parent's center by
rho = 1 - size / siblings(a lone child is concentric), at an angle that grows with the cumulative size of the siblings before it, and drawn at a smaller scaleu = sqrt(size / siblings) / delta. - Nodes. A node of index k sits at
rho = R (1 - epsilon) + epsilon R avg, whereavgmeasures how deep its higher-index neighbors are (closer to the center when they are deep), and at the circular average of the angles of those neighbors, which are placed first. Top cores are split into cliques, each laid along a U-shaped path in its own angular sector.--no-cliquesspreads top cores uniformly and gives every cluster its own sector instead (formula (2) of the paper). gammascales the whole picture;--draw-circlesdraws every component's disc.
Node radius is 0.4 (log(1 + d) / log(d_max))^0.7 layout units (strength-based for
weighted graphs), never less than one pixel; --node-size-scale multiplies it.
Parameters:
- epsilon (0.18): thickness of each ring as a fraction of its radius
- delta (1.3): how much smaller sibling components are drawn (classic)
- gamma (1.5): component diameter / picture scale
- unit_length (1.0): the root scale u
- coord_distribution (classic): pow / log circle packing of siblings, see below
- alpha (0.3), beta (1.0): constant and exponent of the packing's disc area law
- ratio_constant (auto): node radius factor of the pow / log modes
- seed: random seed (cluster order, ties, the random angle frame, the packing)
K-dense and d-core pictures use this same placement, with the component tree built from the edge dense index (k-dense) or the minimum endpoint index (d-cores).
The pow and log coordinate distributions¶
--coord-distribution pow (or log) replaces steps 2 and 3 with the circle packing of
the C++ findCoordinatesModern / distribute_components:
- The whole network is a disc of radius 1 (the frame is
gamma * u). Inside a component of radiusRits children share a smaller disc of radiusR': forpow,((T - S) / T)^(1/8) Rcapped at0.96 R, withTandSthe sums of the squared log-degrees of the component and of its own shell; forlog,sqrt((n - s) / n) Rwithnandsthe node counts. The nodes of the shell sit on the ring betweenR'andR(step 4 unchanged). - Sibling components are packed as non-overlapping discs inside that disc. Each starts
with radius
R' sqrt(alpha w^beta)(log(1 + w)inlogmode), wherewis its share ofsum(log(1 + d)^(2 / beta))over its nodes, at a random spot; discs that leave the container or overlap are moved to random free spots (the smaller of a pair first), and while everything settlesalphagrows by 1 %; the last round is undone by dividingalphaby 1.1. The packing is seeded by--seed. - Node radius is
0.007 ratio_constant log(1 + d)^1.5(ratio_constant log(1 + s) / log(s_max)on weighted graphs);--ratio-constantsets the factor, default 1.
K-dense pictures in these modes use the variant of kdenses_component.cpp, the only
placement the C++ had for k-dense (with its default flags it behaved as pow): the
children's disc is a fixed 0.92 R (0.97 at index ≤ 1), neighbors of the same index
count in the ring position (formula (1)) and in the angle, epsilon is scaled by
tau = (R - R') / R, u does not enter the positions, and the node radius is
ratio_constant sqrt(log(1 + d)) with ratio_constant lowered by every top core to
0.5 R / sqrt(sum log(1 + d)^2) unless --ratio-constant is given. Note that with many
levels (the CAIDA k-denses reach 105) the 0.92 shrink leaves the inner cores a tiny
disc; the mode was designed for shallower decompositions.
Deliberate deviations from the C++: inflated discs keep their angle and are pulled
towards their container's center (the C++ pulled them towards the picture's origin and
mixed the updated x with the old y, skewing the angle); neighbors not yet placed are
skipped in the angle (the C++ read a zero position); alpha defaults to the C++ 0.3.
Node Visualization¶
Node Color¶
Nodes are colored by their shell (or dense) index with the color scale of the C++
LaNet-vi (types.cpp):
col(default): magenta → blue → cyan → green → yellow → red from the periphery to the maximum index. Consecutive shells alternate a luminosity of 0.7 and 1.2 so that neighboring rings stay distinguishable (k-dense pictures on a white background use a constant 0.9 instead).bw: white → gray → black from the periphery to the maximum index.bwi: the same scale interlaced: indices with the parity of the maximum take the dark half, the others the light half, so adjacent shells contrast strongly.
With --kconn the nodes that are not k-connected ignore the scale: they are black on a
white background, white on a black one, and squares instead of circles in bw / bwi
(the C++ drew blocks instead of spheres); their edges take those colors too
(usage guide).
color_scale_max_value (--color-scale-max) fixes the index drawn with the last color;
higher indices share it, which makes pictures of different networks comparable. For k-dense
pictures with measure = mcore (the default) the value is an m-core number (k-dense
minus 2), as in the C++. A network with a single shell is red.
A colors file (--colors-file) replaces the shell colors; nodes absent from it are white
on a black background and black on a white one, and the color legend is not drawn.
Node Size¶
Node radius follows the C++ computeHostRatio in layout units: 0.4 (log(1+d) /
log(dmax))^0.7 for degree d (a strength-based law on weighted graphs), never smaller
than one pixel; the pow / log modes use 0.007 ratio_constant log(1+d)^1.5 (k-dense:
ratio_constant sqrt(log(1+d))). node_size_scale multiplies it (1.0 is the C++ size).
Edge Visualization¶
Gradient Edge Coloring¶
Each edge is drawn as two halves meeting at the midpoint, as the two cylinders of the C++:
the half next to node A takes the color of node B and vice versa, darkened by 0.75 in
col pictures and lightened by 1.2 in bw/bwi ones. K-dense edges are one color, the
color of their own dense index, darkened by 0.5. gradient_edges: false draws plain
edges in the text color instead.
Edges are drawn under the nodes in increasing index order, so the edges of the core end up on top of the peripheral ones.
Edge Width¶
The width of an edge is 0.2 host radii of the smaller endpoint degree
(0.2 * 0.4 (log(1+d) / log(dmax))^0.7 layout units, the C++ ratioEdge), never thinner
than one pixel. min_edge_width / max_edge_width are deprecated and have no effect.
Edge Filtering¶
For large networks, only a subset of edges is drawn: every edge is kept independently with
probability max(edges_percent, min_edges / E), the C++ Bernoulli draw, seeded with the
layout seed so the same seed gives the same picture.
edges_percent: fraction of the edges to show (0.0-1.0)min_edges: minimum number of edges (raises the probability on small networks)
Edge Styling¶
opacity: edge opacity (0.0 = invisible, 1.0 = opaque), the C++-opacity(edge_alphais a deprecated alias)gradient_edges: enable/disable gradient coloring
Picture Size¶
The picture is exactly width x height pixels. The layout frame (1.6 x 1.2 times the
network radius, the C++ viewport) is scaled uniformly to fit and centered, so any aspect
ratio works without distorting the network; the legends sit in the margins of the frame.
--window HSTART HEND VSTART VEND (the C++ -window) renders only that part of the
frame, as fractions of its width and height measured from the top-left corner, at the
full pixel size: --window 0 0.5 0 0.5 is the top-left quarter, --window 0.25 0.75
0.25 0.75 the central half (a 2x zoom on the core). Whatever falls outside, legends
included, is not drawn. The window is scaled uniformly to fit the picture and centered
(the SVG "meet" rule of the C++), so give --width/--height the window's own aspect
ratio — 4 (hend - hstart) : 3 (vend - vstart) — for an exact crop; a wider or taller
picture shows extra margin on the longer side.
The output format follows the extension of --output: PNG, and also PDF or SVG (vector,
every node a circle), through matplotlib.
Component Circles¶
Optional component border circles:
- Drawn around connected components
- Useful for fragmented networks
- Controlled by
draw_circlesparameter
Legends¶
Both legends are drawn in layout units at the positions of the C++ generateNetworkFile,
so they scale with the picture.
Color Legend (Right Side)¶
One circle per index from the lowest (1 for k-cores and d-cores, 2 for k-denses) to the
maximum, in a column to the right of the network, each labeled in its own color. When
there are more than 15 indices only every max // 15 + 1-th one, counted from the top, is
labeled. For k-dense pictures the labels follow measure: mcore (default) prints the
m-core number (k-dense minus 2) under the title m-core; kdense prints the k-dense index.
Degree Legend (Left Side)¶
Up to five sample nodes with degrees dmax, dmax/4, dmax/16, ... (down to 2), drawn
with the radius the nodes of that degree have in the picture, white on a black background
and gray on a white one. Weighted graphs show strengths smax / 4^i instead (unless no
strength exceeds 1, where the radii follow the degree law and so does the legend).
Legend Configuration¶
show_color_legend: Show/hide the shell/dense index color legendshow_degree_scale: Show/hide the degree (node size) legend, as the C++-showDegreeScale(show_size_legendis a deprecated alias)legend_fontsize: Manual font size in points (default: the C++ size, which scales with the picture)- Text color: Automatic (white on dark, black on light)
Background and Colors¶
background:black(default) orwhitecolor_scheme:col(color),bw(black & white) orbwi(interlaced black & white)
Recommendation: Black background with color scheme for large networks (better contrast).
Example Interpretation¶
CAIDA AS-Relationships Visualization¶
Looking at a typical output:
Center (red): - High k-core (k≈100-149 in the 2025 CAIDA snapshot) - Tier-1 ISPs and backbone providers - Dense interconnection - Few nodes, many edges between them
Middle rings (yellow/green/cyan): - Medium k-core (k=20-50) - Regional ISPs and medium providers - Moderate connectivity - Transitional layer
Outer rings (blue/magenta): - Low k-core (k=1-20) - Stub networks and end users - Sparse connections - Many nodes, few connections each
Edges: - Bright inner edges: Backbone interconnections - Gradient edges: Provider-customer relationships - Outer sparse edges: Access connections
Customization Tips¶
For Large Networks (>10K nodes)¶
config.visualization.edges_percent = 0.1 # Show 10% of edges
config.visualization.opacity = 0.2 # Faint edges (the default)
config.visualization.node_size_scale = 0.4 # Smaller nodes
For Small Networks (<1K nodes)¶
config.visualization.edges_percent = 1.0 # Show all edges
config.visualization.opacity = 0.8 # More opaque
config.visualization.node_size_scale = 2.0 # Larger nodes
config.visualization.epsilon = 0.3 # Thicker rings
For Publication-Quality¶
config.visualization.width = 3600 # High resolution
config.visualization.height = 3600
config.visualization.background = "white"
config.visualization.opacity = 0.6