{"spec_id":"heatmap-adjacency","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nheatmap-adjacency: Network Adjacency Matrix Heatmap\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 90/100 | Created: 2026-05-08\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.transforms import blended_transform_factory\n\n\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\nCOMM_COLORS = [\"#009E73\", \"#C475FD\", \"#4467A3\"]  # Okabe-Ito positions 1–3\n\n# Data: research collaboration network with 3 communities\nnp.random.seed(42)\n\ncommunity_sizes = [10, 12, 8]\ncommunity_names = [\"Neuro Lab\", \"CS Group\", \"Psych Dept\"]\nn_nodes = sum(community_sizes)\n\ncommunities = []\nfor idx, size in enumerate(community_sizes):\n    communities.extend([idx] * size)\ncommunities = np.array(communities)\n\nprefixes = [\"N\", \"C\", \"P\"]\nnode_labels = []\ncounts_per_comm = [0, 0, 0]\nfor c in communities:\n    counts_per_comm[c] += 1\n    node_labels.append(f\"{prefixes[c]}{counts_per_comm[c]:02d}\")\n\n# Weighted adjacency matrix with block-diagonal community structure\nadj = np.zeros((n_nodes, n_nodes))\nfor i in range(n_nodes):\n    for j in range(i + 1, n_nodes):\n        same = communities[i] == communities[j]\n        if np.random.random() < (0.72 if same else 0.12):\n            w = np.random.uniform(0.5, 1.0) if same else np.random.uniform(0.05, 0.3)\n            adj[i, j] = adj[j, i] = w\n\n# Absent edges become NaN so they render as page background\nadj_masked = np.where(adj == 0, np.nan, adj)\n\n# Plot\nfig, ax = plt.subplots(figsize=(12, 12), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\ncmap = plt.cm.viridis.copy()\ncmap.set_bad(color=PAGE_BG)\n\nim = ax.imshow(adj_masked, cmap=cmap, vmin=0, vmax=1.0, aspect=\"equal\", interpolation=\"nearest\")\n\n# Axis ticks\nax.set_xticks(range(n_nodes))\nax.set_yticks(range(n_nodes))\nax.set_xticklabels(node_labels, fontsize=11, color=INK_SOFT, rotation=90)\nax.set_yticklabels(node_labels, fontsize=11, color=INK_SOFT)\nax.tick_params(axis=\"both\", length=0, pad=3)\n\n# Community boundary lines\ncum = np.cumsum(community_sizes[:-1])\nfor b in cum:\n    ax.axhline(b - 0.5, color=INK, linewidth=2.0, alpha=0.45)\n    ax.axvline(b - 0.5, color=INK, linewidth=2.0, alpha=0.45)\n\n# Community group labels above the x-axis using a blended transform\ntrans_x = blended_transform_factory(ax.transData, ax.transAxes)\nboundaries = [0] + list(cum) + [n_nodes]\nfor i, (name, color) in enumerate(zip(community_names, COMM_COLORS, strict=True)):\n    mid = (boundaries[i] + boundaries[i + 1] - 1) / 2\n    ax.text(\n        mid,\n        1.01,\n        name,\n        transform=trans_x,\n        ha=\"center\",\n        va=\"bottom\",\n        fontsize=15,\n        fontweight=\"bold\",\n        color=color,\n        clip_on=False,\n    )\n\n# Spines\nfor spine in ax.spines.values():\n    spine.set_edgecolor(INK_SOFT)\n    spine.set_linewidth(0.8)\n\n# Axis labels\nax.set_xlabel(\"Node (sorted by community)\", fontsize=20, color=INK, labelpad=8)\nax.set_ylabel(\"Node (sorted by community)\", fontsize=20, color=INK, labelpad=8)\n\n# Colorbar\ncbar = fig.colorbar(im, ax=ax, fraction=0.045, pad=0.03, shrink=0.75)\ncbar.set_label(\"Connection Strength\", fontsize=18, color=INK, labelpad=12)\ncbar.ax.tick_params(labelsize=14, labelcolor=INK_SOFT, color=INK_SOFT)\ncbar.outline.set_edgecolor(INK_SOFT)\n\n# Title\nax.set_title(\"heatmap-adjacency · matplotlib · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK, pad=36)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}