{"spec_id":"hive-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nhive-basic: Basic Hive Plot\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-07\n\"\"\"\n\nimport os\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\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\n# Okabe-Ito palette (canonical order)\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Apply seaborn theme with theme-adaptive colors\nsns.set_theme(\n    style=\"white\",\n    context=\"talk\",\n    font_scale=1.2,\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: Software module dependency network\nnp.random.seed(42)\n\n# Define nodes with module types (3 categories for 3 axes)\nnode_data = {\n    \"id\": [f\"M{i}\" for i in range(30)],\n    \"type\": [\"core\"] * 10 + [\"utility\"] * 10 + [\"interface\"] * 10,\n    \"degree\": np.random.randint(1, 15, 30),\n}\nnodes_df = pd.DataFrame(node_data)\n\n# Define edges between modules\nedges = [\n    # Core to utility connections\n    (\"M0\", \"M10\"),\n    (\"M0\", \"M11\"),\n    (\"M1\", \"M12\"),\n    (\"M2\", \"M13\"),\n    (\"M3\", \"M14\"),\n    (\"M4\", \"M15\"),\n    (\"M5\", \"M16\"),\n    (\"M6\", \"M17\"),\n    (\"M7\", \"M18\"),\n    (\"M8\", \"M19\"),\n    # Utility to interface connections\n    (\"M10\", \"M20\"),\n    (\"M11\", \"M21\"),\n    (\"M12\", \"M22\"),\n    (\"M13\", \"M23\"),\n    (\"M14\", \"M24\"),\n    (\"M15\", \"M25\"),\n    (\"M16\", \"M26\"),\n    (\"M17\", \"M27\"),\n    (\"M18\", \"M28\"),\n    (\"M19\", \"M29\"),\n    # Core to interface connections (direct)\n    (\"M0\", \"M20\"),\n    (\"M1\", \"M23\"),\n    (\"M3\", \"M25\"),\n    (\"M5\", \"M27\"),\n    (\"M9\", \"M29\"),\n    # Internal connections\n    (\"M0\", \"M1\"),\n    (\"M2\", \"M3\"),\n    (\"M10\", \"M11\"),\n    (\"M20\", \"M21\"),\n]\n\n# Hive plot configuration: 3 axes at 120 degrees apart\naxis_angles = {\"core\": np.pi / 2, \"utility\": np.pi / 2 + 2 * np.pi / 3, \"interface\": np.pi / 2 + 4 * np.pi / 3}\n\n# Use Okabe-Ito palette for axis colors\naxis_colors = {\n    \"core\": IMPRINT[0],  # #009E73 (brand green)\n    \"utility\": IMPRINT[1],  # #C475FD (vermillion)\n    \"interface\": IMPRINT[2],  # #4467A3 (blue)\n}\n\n# Calculate node positions on radial axes (normalized by degree within each type)\nnodes_df[\"angle\"] = nodes_df[\"type\"].map(axis_angles)\nfor node_type in [\"core\", \"utility\", \"interface\"]:\n    mask = nodes_df[\"type\"] == node_type\n    degrees = nodes_df.loc[mask, \"degree\"]\n    min_deg, max_deg = degrees.min(), degrees.max()\n    if max_deg > min_deg:\n        nodes_df.loc[mask, \"radius\"] = 0.3 + 0.7 * (degrees - min_deg) / (max_deg - min_deg)\n    else:\n        nodes_df.loc[mask, \"radius\"] = 0.65\n\n# Convert to cartesian coordinates\nnodes_df[\"x\"] = nodes_df[\"radius\"] * np.cos(nodes_df[\"angle\"])\nnodes_df[\"y\"] = nodes_df[\"radius\"] * np.sin(nodes_df[\"angle\"])\n\n# Create figure\nfig, ax = plt.subplots(figsize=(12, 12), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Draw axis lines (radial spokes)\nfor axis_name, angle in axis_angles.items():\n    ax.plot([0, 1.1 * np.cos(angle)], [0, 1.1 * np.sin(angle)], color=INK_SOFT, linewidth=2, alpha=0.3, zorder=1)\n    ax.text(\n        1.2 * np.cos(angle),\n        1.2 * np.sin(angle),\n        axis_name.upper(),\n        fontsize=18,\n        fontweight=\"bold\",\n        ha=\"center\",\n        va=\"center\",\n        color=axis_colors[axis_name],\n    )\n\n# Build edge curves as DataFrame for seaborn lineplot\nnode_pos = nodes_df.set_index(\"id\")[[\"x\", \"y\"]]\nedge_curves = []\nfor edge_id, (source, target) in enumerate(edges):\n    src_x, src_y = node_pos.loc[source]\n    tgt_x, tgt_y = node_pos.loc[target]\n    t = np.linspace(0, 1, 50)\n    ctrl_x, ctrl_y = 0.1 * (src_x + tgt_x), 0.1 * (src_y + tgt_y)\n    curve_x = (1 - t) ** 2 * src_x + 2 * (1 - t) * t * ctrl_x + t**2 * tgt_x\n    curve_y = (1 - t) ** 2 * src_y + 2 * (1 - t) * t * ctrl_y + t**2 * tgt_y\n    for i in range(len(t)):\n        edge_curves.append({\"edge_id\": edge_id, \"x\": curve_x[i], \"y\": curve_y[i]})\nedges_df = pd.DataFrame(edge_curves)\n\n# Draw edges using seaborn lineplot with theme-adaptive color\nsns.lineplot(\n    data=edges_df,\n    x=\"x\",\n    y=\"y\",\n    hue=\"edge_id\",\n    palette=[INK_SOFT] * len(edges),\n    alpha=0.2,\n    linewidth=1.5,\n    legend=False,\n    units=\"edge_id\",\n    estimator=None,\n    ax=ax,\n    zorder=2,\n)\n\n# Draw nodes using seaborn scatterplot\nsns.scatterplot(\n    data=nodes_df,\n    x=\"x\",\n    y=\"y\",\n    hue=\"type\",\n    palette=[axis_colors[t] for t in [\"core\", \"utility\", \"interface\"]],\n    s=400,\n    alpha=0.9,\n    edgecolor=PAGE_BG,\n    linewidth=2,\n    ax=ax,\n    legend=False,\n    zorder=3,\n)\n\n# Create legend\nlegend_handles = [\n    mpatches.Patch(color=axis_colors[\"core\"], label=\"Core Modules\"),\n    mpatches.Patch(color=axis_colors[\"utility\"], label=\"Utility Modules\"),\n    mpatches.Patch(color=axis_colors[\"interface\"], label=\"Interface Modules\"),\n]\nax.legend(\n    handles=legend_handles, loc=\"upper right\", fontsize=16, framealpha=0.95, facecolor=ELEVATED_BG, edgecolor=INK_SOFT\n)\n\n# Styling\nax.set_xlim(-1.5, 1.5)\nax.set_ylim(-1.5, 1.5)\nax.set_aspect(\"equal\")\nax.axis(\"off\")\nax.set_title(\"hive-basic · seaborn · anyplot.ai\", fontsize=24, fontweight=\"bold\", pad=20, color=INK)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}