{"spec_id":"heatmap-adjacency","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nheatmap-adjacency: Network Adjacency Matrix Heatmap\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 85/100 | Created: 2026-05-08\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    element_blank,\n    element_rect,\n    element_text,\n    geom_tile,\n    ggplot,\n    ggsave,\n    ggsize,\n    labs,\n    scale_fill_viridis,\n    theme,\n)\n\n\nLetsPlot.setup_html()\n\n# Theme tokens\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\"\n\n# Data: Research collaboration network — 30 scientists across 3 departments\nnp.random.seed(42)\n\nnames = [\n    \"Alice\",\n    \"Bob\",\n    \"Carol\",\n    \"Dan\",\n    \"Eve\",\n    \"Frank\",\n    \"Grace\",\n    \"Hank\",\n    \"Iris\",\n    \"Jack\",  # Dept A\n    \"Kate\",\n    \"Leo\",\n    \"Mia\",\n    \"Ned\",\n    \"Olivia\",\n    \"Paul\",\n    \"Quinn\",\n    \"Rose\",\n    \"Sam\",\n    \"Tina\",  # Dept B\n    \"Uma\",\n    \"Victor\",\n    \"Wendy\",\n    \"Xavier\",\n    \"Yara\",\n    \"Zane\",\n    \"Anna\",\n    \"Blake\",\n    \"Cleo\",\n    \"Derek\",  # Dept C\n]\nn = len(names)  # 30\n\n# Build symmetric adjacency matrix with block-diagonal community structure\nweights = np.zeros((n, n))\nfor i in range(n):\n    for j in range(i + 1, n):\n        same_dept = (i // 10) == (j // 10)\n        prob = 0.70 if same_dept else 0.12\n        if np.random.rand() < prob:\n            lo, hi = (0.4, 1.0) if same_dept else (0.05, 0.35)\n            w = np.random.uniform(lo, hi)\n            weights[i, j] = weights[j, i] = w\n\n# Convert to long format; absent edges → NaN so they render as background color\nrows = []\nfor i in range(n):\n    for j in range(n):\n        w = weights[i, j]\n        rows.append({\"source\": names[i], \"target\": names[j], \"weight\": w if w > 0 else np.nan})\n\ndf = pd.DataFrame(rows)\n\n# Categorical ordering: x left-to-right = Dept A → C; y reversed so Dept A is at top\ndf[\"source\"] = pd.Categorical(df[\"source\"], categories=names, ordered=True)\ndf[\"target\"] = pd.Categorical(df[\"target\"], categories=names[::-1], ordered=True)\n\n# anyplot theme\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    panel_grid=element_blank(),\n    axis_title=element_text(color=INK, size=20),\n    axis_text=element_text(color=INK_SOFT, size=11),\n    axis_line=element_blank(),\n    plot_title=element_text(color=INK, size=24),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_text=element_text(color=INK_SOFT, size=16),\n    legend_title=element_text(color=INK, size=16),\n)\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"source\", y=\"target\", fill=\"weight\"))\n    + geom_tile()\n    + scale_fill_viridis(name=\"Collaboration\\nStrength\", na_value=PAGE_BG)\n    + labs(title=\"heatmap-adjacency · letsplot · anyplot.ai\", x=\"Researcher\", y=\"Researcher\")\n    + anyplot_theme\n    + theme(axis_text_x=element_text(angle=90, hjust=1, size=11))\n    + ggsize(1200, 1200)\n)\n\n# Save\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}