{"spec_id":"network-hierarchical","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nnetwork-hierarchical: Hierarchical Network Graph with Tree Layout\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove current directory from path to avoid matplotlib module conflict\nsys.path = [p for p in sys.path if p != \"\" and not p.endswith(os.path.dirname(__file__))]\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n\n# Theme configuration\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Okabe-Ito palette\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\n# Data: Software Module Hierarchy (24 nodes, 4 levels)\nnp.random.seed(42)\n\nnodes = [\n    # Level 0 - Root\n    (\"app\", \"App\", 0, None),\n    # Level 1 - Core modules (4 nodes)\n    (\"core\", \"Core\", 1, \"app\"),\n    (\"ui\", \"UI\", 1, \"app\"),\n    (\"data\", \"Data\", 1, \"app\"),\n    (\"utils\", \"Utils\", 1, \"app\"),\n    # Level 2 - Sub-modules (8 nodes - 2 per parent)\n    (\"auth\", \"Auth\", 2, \"core\"),\n    (\"config\", \"Config\", 2, \"core\"),\n    (\"widgets\", \"Widget\", 2, \"ui\"),\n    (\"themes\", \"Theme\", 2, \"ui\"),\n    (\"models\", \"Models\", 2, \"data\"),\n    (\"store\", \"Store\", 2, \"data\"),\n    (\"logger\", \"Logger\", 2, \"utils\"),\n    (\"helpers\", \"Helper\", 2, \"utils\"),\n    # Level 3 - Leaf modules (11 nodes)\n    (\"login\", \"Login\", 3, \"auth\"),\n    (\"session\", \"Sess\", 3, \"auth\"),\n    (\"buttons\", \"Btns\", 3, \"widgets\"),\n    (\"forms\", \"Forms\", 3, \"widgets\"),\n    (\"grid\", \"Grid\", 3, \"themes\"),\n    (\"user\", \"User\", 3, \"models\"),\n    (\"product\", \"Prod\", 3, \"models\"),\n    (\"cache\", \"Cache\", 3, \"store\"),\n    (\"db\", \"DB\", 3, \"store\"),\n    (\"rest\", \"REST\", 3, \"logger\"),\n    (\"format\", \"Fmt\", 3, \"helpers\"),\n]\n\n# Create lookup dictionaries\nhierarchy = {n[0]: (n[1], n[2], n[3]) for n in nodes}\n\n# Group nodes by level\nlevels = {0: [], 1: [], 2: [], 3: []}\nfor node_id, _label, level, _parent in nodes:\n    levels[level].append(node_id)\n\n# Calculate positions using breadth-first approach\npositions = {}\ny_positions = {0: 8.5, 1: 6.0, 2: 3.5, 3: 1.0}\n\n# Position level 3 (leaves) first with even spacing\nlevel3_nodes = levels[3]\nn_leaves = len(level3_nodes)\nx_positions_l3 = np.linspace(1, 15.5, n_leaves)\nfor i, node_id in enumerate(level3_nodes):\n    positions[node_id] = (x_positions_l3[i], y_positions[3])\n\n# Position level 2 - center each parent over its children\nfor node_id in levels[2]:\n    children = [n[0] for n in nodes if n[3] == node_id]\n    if children:\n        child_xs = [positions[c][0] for c in children]\n        positions[node_id] = (np.mean(child_xs), y_positions[2])\n    else:\n        idx = levels[2].index(node_id)\n        positions[node_id] = (2 + idx * 1.6, y_positions[2])\n\n# Position level 1 - center each parent over its children\nfor node_id in levels[1]:\n    children = [n[0] for n in nodes if n[3] == node_id]\n    if children:\n        child_xs = [positions[c][0] for c in children]\n        positions[node_id] = (np.mean(child_xs), y_positions[1])\n\n# Position level 0 - center over children\nfor node_id in levels[0]:\n    children = [n[0] for n in nodes if n[3] == node_id]\n    if children:\n        child_xs = [positions[c][0] for c in children]\n        positions[node_id] = (np.mean(child_xs), y_positions[0])\n\n# Use Okabe-Ito palette for levels\nlevel_colors = {\n    0: IMPRINT[0],  # Brand green (#009E73)\n    1: IMPRINT[1],  # Vermillion (#C475FD)\n    2: IMPRINT[2],  # Blue (#4467A3)\n    3: IMPRINT[3],  # Reddish purple (#BD8233)\n}\nlevel_names = [\"Root Module\", \"Core Modules\", \"Sub-modules\", \"Leaf Modules\"]\n\n# Create figure\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Draw edges (parent-child connections)\nfor node_id, _label, _level, parent_id in nodes:\n    if parent_id is not None:\n        x1, y1 = positions[parent_id]\n        x2, y2 = positions[node_id]\n        ax.plot([x1, x2], [y1, y2], color=INK_SOFT, linewidth=2.5, alpha=0.4, zorder=1)\n\n# Draw nodes by level\nfor level in [3, 2, 1, 0]:\n    level_node_ids = levels[level]\n    for node_id in level_node_ids:\n        x, y = positions[node_id]\n        label = hierarchy[node_id][0]\n        color = level_colors[level]\n\n        # Node size based on level\n        node_size = {0: 3200, 1: 2400, 2: 1800, 3: 1300}[level]\n\n        ax.scatter(x, y, s=node_size, c=color, edgecolors=\"white\", linewidths=2.5, zorder=10 + level, alpha=0.95)\n\n        # Add label inside node\n        font_size = {0: 16, 1: 14, 2: 12, 3: 10}[level]\n        text_color = \"white\"\n\n        ax.annotate(\n            label,\n            (x, y),\n            ha=\"center\",\n            va=\"center\",\n            fontsize=font_size,\n            fontweight=\"bold\",\n            color=text_color,\n            zorder=20 + level,\n        )\n\n# Create legend\nlegend_handles = [mpatches.Patch(color=level_colors[i], label=level_names[i]) for i in range(4)]\nleg = ax.legend(\n    handles=legend_handles, loc=\"upper left\", fontsize=16, frameon=True, facecolor=ELEVATED_BG, edgecolor=INK_SOFT\n)\nfor text in leg.get_texts():\n    text.set_color(INK_SOFT)\n\n# Styling\nax.set_title(\"Software Module Hierarchy\", fontsize=24, fontweight=\"medium\", color=INK, pad=20)\nax.set_xlim(-0.5, 17)\nax.set_ylim(-0.5, 10)\nax.axis(\"off\")\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}