{"spec_id":"network-bipartite","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nnetwork-bipartite: Bipartite Network Graph\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 85/100 | Created: 2026-05-14\n\"\"\"\n\nimport os\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom matplotlib.lines import Line2D\n\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\nCOLOR_A = \"#009E73\"  # Okabe-Ito position 1 — researchers\nCOLOR_B = \"#C475FD\"  # Okabe-Ito position 2 — papers\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Data — researcher–paper authorship network\nnp.random.seed(42)\n\nresearchers = [\n    \"A. Chen\",\n    \"B. Patel\",\n    \"C. Nguyen\",\n    \"D. Kim\",\n    \"E. Santos\",\n    \"F. Okafor\",\n    \"G. Mueller\",\n    \"H. Tanaka\",\n    \"I. Rossi\",\n    \"J. Andersen\",\n]\n\npapers = [\n    \"P01: Deep Learning\",\n    \"P02: Graph Theory\",\n    \"P03: NLP Methods\",\n    \"P04: Optimization\",\n    \"P05: Bayesian ML\",\n    \"P06: Vision CNN\",\n    \"P07: Transfer Learn\",\n    \"P08: GAN Models\",\n    \"P09: Causal Inf.\",\n    \"P10: Reinforcement\",\n    \"P11: Clustering\",\n    \"P12: Fairness AI\",\n]\n\n# Generate authorship edges (each researcher authors 2–4 papers)\nraw_edges = []\nfor researcher in researchers:\n    n_papers = np.random.randint(2, 5)\n    chosen = np.random.choice(range(len(papers)), size=n_papers, replace=False)\n    for idx in chosen:\n        raw_edges.append((researcher, papers[idx]))\n\nedges = list(set(raw_edges))\n\n# Compute degrees\nresearcher_degree = dict.fromkeys(researchers, 0)\npaper_degree = dict.fromkeys(papers, 0)\nfor r, p in edges:\n    researcher_degree[r] += 1\n    paper_degree[p] += 1\n\n# Node positions: left column = researchers, right column = papers\nn_r = len(researchers)\nn_p = len(papers)\n\nresearcher_pos = {r: (0.0, 1.0 - i / (n_r - 1)) for i, r in enumerate(researchers)}\npaper_pos = {p: (1.0, 1.0 - i / (n_p - 1)) for i, p in enumerate(papers)}\n\n# Plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Draw edges\nfor researcher, paper in edges:\n    rx, ry = researcher_pos[researcher]\n    px, py = paper_pos[paper]\n    ax.plot([rx, px], [ry, py], color=INK_SOFT, alpha=0.22, linewidth=1.2, zorder=1)\n\n# Draw nodes — size encodes degree\nmin_s, max_s = 400, 1600\nmax_deg_r = max(researcher_degree.values())\nmax_deg_p = max(paper_degree.values())\n\nfor researcher in researchers:\n    x, y = researcher_pos[researcher]\n    deg = researcher_degree[researcher]\n    size = min_s + (max_s - min_s) * (deg / max_deg_r)\n    ax.scatter(x, y, s=size, color=COLOR_A, edgecolors=PAGE_BG, linewidth=2.5, zorder=3)\n\nfor paper in papers:\n    x, y = paper_pos[paper]\n    deg = paper_degree[paper]\n    size = min_s + (max_s - min_s) * (deg / max_deg_p)\n    ax.scatter(x, y, s=size, color=COLOR_B, edgecolors=PAGE_BG, linewidth=2.5, zorder=3)\n\n# Node labels\nfor researcher in researchers:\n    x, y = researcher_pos[researcher]\n    ax.text(x - 0.06, y, researcher, ha=\"right\", va=\"center\", fontsize=16, color=INK_SOFT)\n\nfor paper in papers:\n    x, y = paper_pos[paper]\n    ax.text(x + 0.06, y, paper, ha=\"left\", va=\"center\", fontsize=16, color=INK_SOFT)\n\n# Column headers\nax.text(0.0, 1.08, \"Researchers\", ha=\"center\", va=\"bottom\", fontsize=20, fontweight=\"bold\", color=COLOR_A)\nax.text(1.0, 1.08, \"Papers\", ha=\"center\", va=\"bottom\", fontsize=20, fontweight=\"bold\", color=COLOR_B)\n\n# Legend\nlegend_elements = [\n    mpatches.Patch(facecolor=COLOR_A, edgecolor=PAGE_BG, label=\"Researchers\"),\n    mpatches.Patch(facecolor=COLOR_B, edgecolor=PAGE_BG, label=\"Papers\"),\n    Line2D([0], [0], color=INK_SOFT, alpha=0.5, linewidth=2, label=\"Authorship\"),\n]\nlegend = ax.legend(\n    handles=legend_elements,\n    loc=\"lower center\",\n    bbox_to_anchor=(0.5, -0.04),\n    ncol=3,\n    fontsize=16,\n    framealpha=0.9,\n    facecolor=ELEVATED_BG,\n    edgecolor=INK_SOFT,\n)\nfor text in legend.get_texts():\n    text.set_color(INK)\n\nax.set_xlim(-0.48, 1.48)\nax.set_ylim(-0.14, 1.22)\nax.axis(\"off\")\n\nax.set_title(\n    \"Researcher–Paper Authorship · network-bipartite · seaborn · anyplot.ai\",\n    fontsize=23,\n    fontweight=\"medium\",\n    color=INK,\n    pad=16,\n)\n\nplt.tight_layout(pad=2.0)\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}