Code
import networkx as nx
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
def jgraph_from_multiple_origins(G, origins, fig_size=(10, 4)):
"""
Draws a Justified graph (J-graph) from multiple origins with a gradient color range.
Handles both a list of origins or a single origin by treating it as a list.
Parameters:
G (networkx.Graph): The graph to visualize.
origins: A single origin or a list of origin nodes for path calculations.
fig_size (tuple): The dimensions for the figure size (width, height).
Returns:
None: Displays the graph visualization with a gradient color scale.
"""
# Ensure origins is a list even if a single node is provided
if not isinstance(origins, list):
= [origins]
origins
# Initialize dictionary to keep the shortest paths from any origins
= {}
min_path_lengths
# Calculate shortest paths from each origin and update the minimum path length
for origin in origins:
= nx.single_source_shortest_path_length(G, source=origin)
path_lengths for node, length in path_lengths.items():
if node in min_path_lengths:
= min(min_path_lengths[node], length)
min_path_lengths[node] else:
= length
min_path_lengths[node]
# Create a new graph to visualize
= nx.Graph()
G_vis
# Adding nodes with minimum path length as attribute
for node, length in min_path_lengths.items():
=length)
G_vis.add_node(node, steps
# Preserve original edges
G_vis.add_edges_from(G.edges())
# Use a colormap and normalize based on the max path length for color mapping
= max(min_path_lengths.values())
max_depth = mcolors.Normalize(vmin=0, vmax=max_depth)
norm = plt.cm.viridis
cmap
# Prepare color values according to the normalized data
= [cmap(norm(min_path_lengths[node])) for node in G_vis.nodes()]
colors
# Positioning nodes by topological steps
= nx.multipartite_layout(
pos ="steps", align="horizontal", scale=1.75
G_vis, subset_key
)
# Drawing the graph
= plt.subplots(figsize=fig_size)
fig, ax =pos, node_color=colors, with_labels=True, node_size=800, ax=ax)
nx.draw(G_vis, pos
# Adding a colorbar with correct axis context
= plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm
sm.set_array([])=ax, label="Shortest path length to nearest origin")
plt.colorbar(sm, ax
# Calculating and displaying graph metrics
= sum(min_path_lengths.values()) / len(min_path_lengths)
mean_depth print(f"Mean depth = {mean_depth:.2f}")
print(f"Maximum topological steps = {max_depth}")