{"spec_id":"venn-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nvenn-basic: Venn Diagram\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 82/100 | Updated: 2026-05-15\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Data: Programming language preference survey\nset_labels = [\"Python\", \"JavaScript\", \"SQL\"]\nset_sizes = [100, 80, 60]\n\nab_overlap = 30  # Python & JavaScript\nac_overlap = 20  # Python & SQL\nbc_overlap = 25  # JavaScript & SQL\nabc_overlap = 10  # All three\n\nonly_a = set_sizes[0] - ab_overlap - ac_overlap + abc_overlap\nonly_b = set_sizes[1] - ab_overlap - bc_overlap + abc_overlap\nonly_c = set_sizes[2] - ac_overlap - bc_overlap + abc_overlap\nonly_ab = ab_overlap - abc_overlap\nonly_ac = ac_overlap - abc_overlap\nonly_bc = bc_overlap - abc_overlap\n\n# Radii proportional to set size (area ∝ count)\nr_base = 1.0\nradii = [r_base * np.sqrt(s / set_sizes[0]) for s in set_sizes]\n\n# Equilateral triangle arrangement\nangle_offset = np.pi / 2\nangles = [angle_offset, angle_offset + 2 * np.pi / 3, angle_offset + 4 * np.pi / 3]\ndistance = 0.6\ncx = [distance * np.cos(a) for a in angles]\ncy = [distance * np.sin(a) for a in angles]\n\n# Okabe-Ito palette with transparency\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\"]\nfill_colors = [\"rgba(0, 158, 115, 0.45)\", \"rgba(196, 117, 253, 0.45)\", \"rgba(68, 103, 163, 0.45)\"]\n\nhover_texts = [\n    f\"<b>Python</b><br>Total: {set_sizes[0]}<br>Only Python: {only_a}<br>Python ∩ JS: {only_ab}<br>Python ∩ SQL: {only_ac}\",\n    f\"<b>JavaScript</b><br>Total: {set_sizes[1]}<br>Only JavaScript: {only_b}<br>JS ∩ Python: {only_ab}<br>JS ∩ SQL: {only_bc}\",\n    f\"<b>SQL</b><br>Total: {set_sizes[2]}<br>Only SQL: {only_c}<br>SQL ∩ Python: {only_ac}<br>SQL ∩ JS: {only_bc}\",\n]\n\ntheta = np.linspace(0, 2 * np.pi, 200)\nfig = go.Figure()\n\nfor i in range(3):\n    r = radii[i]\n    x_circle = cx[i] + r * np.cos(theta)\n    y_circle = cy[i] + r * np.sin(theta)\n    fig.add_trace(\n        go.Scatter(\n            x=x_circle,\n            y=y_circle,\n            fill=\"toself\",\n            fillcolor=fill_colors[i],\n            line={\"color\": IMPRINT[i], \"width\": 3},\n            mode=\"lines\",\n            name=set_labels[i],\n            showlegend=False,\n            hoverinfo=\"text\",\n            hovertext=hover_texts[i],\n        )\n    )\n\n# Set labels outside each circle\nlabel_positions = [\n    (cx[0], cy[0] + radii[0] + 0.32, set_labels[0], set_sizes[0]),\n    (cx[1] - radii[1] - 0.32, cy[1], set_labels[1], set_sizes[1]),\n    (cx[2] + radii[2] + 0.32, cy[2], set_labels[2], set_sizes[2]),\n]\n\nfor x, y, label, size in label_positions:\n    fig.add_annotation(\n        x=x,\n        y=y,\n        text=f\"<b>{label}</b><br>({size})\",\n        showarrow=False,\n        font={\"size\": 28, \"color\": INK},\n        xanchor=\"center\",\n        yanchor=\"middle\",\n    )\n\n# Region annotation positions\npos_a = (cx[0], cy[0] + 0.32)\npos_b = (cx[1] - 0.32, cy[1] - 0.18)\npos_c = (cx[2] + 0.32, cy[2] - 0.18)\npos_ab = ((cx[0] + cx[1]) / 2 - 0.12, (cy[0] + cy[1]) / 2 + 0.12)\npos_ac = ((cx[0] + cx[2]) / 2 + 0.12, (cy[0] + cy[2]) / 2 + 0.12)\npos_bc = ((cx[1] + cx[2]) / 2, (cy[1] + cy[2]) / 2 - 0.22)\npos_abc = (0, 0)\n\nregion_annotations = [\n    (*pos_a, only_a, \"Only<br>Python\"),\n    (*pos_b, only_b, \"Only<br>JavaScript\"),\n    (*pos_c, only_c, \"Only<br>SQL\"),\n    (*pos_ab, only_ab, \"\"),\n    (*pos_ac, only_ac, \"\"),\n    (*pos_bc, only_bc, \"\"),\n    (*pos_abc, abc_overlap, \"All\"),\n]\n\nfor x, y, value, desc in region_annotations:\n    if desc:\n        text = f\"<b>{value}</b><br><span style='font-size:18px'>{desc}</span>\"\n    else:\n        text = f\"<b>{value}</b>\"\n    fig.add_annotation(\n        x=x, y=y, text=text, showarrow=False, font={\"size\": 24, \"color\": INK}, xanchor=\"center\", yanchor=\"middle\"\n    )\n\nfig.update_layout(\n    title={\n        \"text\": \"venn-basic · plotly · anyplot.ai\",\n        \"font\": {\"size\": 36, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n        \"y\": 0.95,\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    showlegend=False,\n    xaxis={\"visible\": False, \"range\": [-2.5, 2.5], \"scaleanchor\": \"y\", \"scaleratio\": 1},\n    yaxis={\"visible\": False, \"range\": [-2.2, 2.5]},\n    margin={\"l\": 40, \"r\": 40, \"t\": 100, \"b\": 40},\n)\n\nfig.write_image(f\"plot-{THEME}.png\", width=1200, height=1200, scale=3)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}