{"spec_id":"parliament-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nparliament-basic: Parliament Seat Chart\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 86/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\n\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\nIMPRINT = [\n    \"#009E73\",  # bluish green (brand)\n    \"#C475FD\",  # vermillion\n    \"#4467A3\",  # blue\n    \"#BD8233\",  # reddish purple\n    \"#AE3030\",  # orange\n    \"#2ABCCD\",  # sky blue\n]\n\n# Data: Sports league team distribution across regional conferences\n# Different decay pattern: geometric progression instead of linear\nconferences = [\"North\", \"South\", \"East\", \"West\", \"Central\"]\nteams = [90, 54, 32, 20, 12]  # Geometric decay pattern (roughly 0.6x each step)\ntotal_seats = sum(teams)\n\n# Set seaborn theme with proper chrome tokens\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# Create figure\nfig, ax = plt.subplots(figsize=(16, 9))\n\n# Calculate parliament layout - semicircular arrangement with 5 rows\nn_rows = 5\nrow_proportions = [(i + 1) for i in range(n_rows)]\ntotal_prop = sum(row_proportions)\nseats_per_row = [int(total_seats * p / total_prop) for p in row_proportions]\nseats_per_row[-1] += total_seats - sum(seats_per_row)  # Adjust for rounding\n\n# Create all seat positions in concentric arcs\nall_positions = []\nfor row_idx, n_seats_row in enumerate(seats_per_row):\n    radius = 0.4 + row_idx * 0.15\n    angles = np.linspace(np.pi, 0, n_seats_row)\n    for angle in angles:\n        all_positions.append((radius * np.cos(angle), radius * np.sin(angle), row_idx))\n\n# Sort positions left to right for natural group ordering\nall_positions.sort(key=lambda p: (p[0], -p[1]))\n\n# Build DataFrame for seaborn plotting\nx_coords, y_coords, group_labels = [], [], []\nseat_idx = 0\nfor group_idx, n_seats in enumerate(teams):\n    for _ in range(n_seats):\n        if seat_idx < len(all_positions):\n            x_coords.append(all_positions[seat_idx][0])\n            y_coords.append(all_positions[seat_idx][1])\n            group_labels.append(conferences[group_idx])\n            seat_idx += 1\n\n# Create DataFrame for seaborn\ndf = pd.DataFrame({\"x\": x_coords, \"y\": y_coords, \"group\": group_labels})\n\n# Plot seats using seaborn scatterplot\nsns.scatterplot(\n    data=df,\n    x=\"x\",\n    y=\"y\",\n    hue=\"group\",\n    hue_order=conferences,\n    palette=IMPRINT[: len(conferences)],\n    s=350,\n    edgecolor=PAGE_BG,\n    linewidth=1.5,\n    legend=False,\n    ax=ax,\n    zorder=2,\n)\n\n# Add majority threshold line\nmajority = total_seats // 2 + 1\nax.axhline(y=0, color=INK_SOFT, linestyle=\"--\", linewidth=2, alpha=0.5, zorder=1)\nax.text(0.85, 0.02, f\"Majority: {majority} seats\", fontsize=14, color=INK_SOFT, ha=\"right\", transform=ax.transAxes)\n\n# Create legend with seat counts\nlegend_elements = [\n    plt.scatter([], [], c=[IMPRINT[i % len(IMPRINT)]], s=200, label=f\"{conf}: {count}\")\n    for i, (conf, count) in enumerate(zip(conferences, teams, strict=True))\n]\nax.legend(\n    handles=legend_elements,\n    loc=\"upper left\",\n    fontsize=14,\n    frameon=True,\n    facecolor=ELEVATED_BG,\n    edgecolor=INK_SOFT,\n    title=\"Conferences\",\n    title_fontsize=16,\n)\n\n# Style adjustments\nax.set_xlim(-1.1, 1.1)\nax.set_ylim(-0.15, 1.0)\nax.set_aspect(\"equal\")\nax.axis(\"off\")\n\n# Title\nax.set_title(\"parliament-basic · seaborn · anyplot.ai\", fontsize=24, fontweight=\"bold\", pad=20, color=INK)\n\n# Add total seats annotation\nax.text(0.5, -0.08, f\"Total: {total_seats} teams\", fontsize=18, ha=\"center\", transform=ax.transAxes, color=INK)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}