{"spec_id":"venn-labeled-items","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nvenn-labeled-items: Chartgeist-Style Venn Diagram with Labeled Items\nLibrary: plotnine 0.15.7 | Python 3.13.14\nQuality: 88/100 | Updated: 2026-06-25\n\"\"\"\n\nimport os\nimport sys\n\n\n_HERE = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p) != _HERE]\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    coord_fixed,\n    element_blank,\n    element_rect,\n    geom_label,\n    geom_polygon,\n    geom_text,\n    ggplot,\n    scale_color_identity,\n    scale_fill_identity,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n)\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint palette positions 1–3\nCOLOR_A = \"#009E73\"\nCOLOR_B = \"#C475FD\"\nCOLOR_C = \"#4467A3\"\n\n# Symmetric three-circle Venn geometry\nRADIUS = 1.5\ncircle_meta = [\n    (\"Peak Instagram\", -0.85, 0.50, COLOR_A),\n    (\"Actually Nutritious\", 0.85, 0.50, COLOR_B),\n    (\"Surprisingly Addictive\", 0.00, -1.00, COLOR_C),\n]\n\ntheta = np.linspace(0, 2 * np.pi, 240)\ncircle_rows = []\nfor name, cx, cy, color in circle_meta:\n    for t in theta:\n        circle_rows.append({\"name\": name, \"x\": cx + RADIUS * np.cos(t), \"y\": cy + RADIUS * np.sin(t), \"fill\": color})\ncircles_df = pd.DataFrame(circle_rows)\n\n# Items placed in their assigned Venn zones\nitems_df = pd.DataFrame(\n    [\n        # A only — Peak Instagram (upper-left)\n        (\"Cloud Bread\", -2.00, 1.30),\n        (\"Charcoal Ice Cream\", -2.30, 0.52),\n        (\"Butterfly Pea Tea\", -2.20, -0.05),\n        # B only — Actually Nutritious (upper-right)\n        (\"Sardines\", 2.00, 1.30),\n        (\"Kimchi\", 2.30, 0.52),\n        (\"Lentil Soup\", 2.20, -0.05),\n        # C only — Surprisingly Addictive (bottom)\n        (\"Takis\", -0.95, -2.25),\n        (\"Boba Tea\", 0.00, -2.58),\n        (\"Funyuns\", 0.95, -2.25),\n        # A ∩ B — photogenic and nutritious (top center)\n        (\"Avocado Toast\", 0.00, 1.35),\n        (\"Overnight Oats\", 0.00, 0.82),\n        # A ∩ C — photogenic and addictive (lower left, centered in zone)\n        (\"Cronuts\", -0.90, -0.55),\n        (\"Dirty Soda\", -0.90, -1.05),\n        # B ∩ C — nutritious and addictive (lower right, centered in zone)\n        (\"Greek Yogurt\", 0.90, -0.55),\n        (\"Edamame\", 0.90, -1.05),\n        # A ∩ B ∩ C (center)\n        (\"Sourdough\", 0.00, 0.28),\n        (\"Matcha\", 0.00, -0.22),\n    ],\n    columns=[\"label\", \"x\", \"y\"],\n)\n\n# Consolidated category labels — one DataFrame, one geom_text layer\ncat_df = pd.DataFrame(\n    {\n        \"label\": [\"Peak Instagram\", \"Actually Nutritious\", \"Surprisingly Addictive\"],\n        \"x\": [-1.80, 1.80, 0.00],\n        \"y\": [2.32, 2.32, -2.85],\n        \"color\": [COLOR_A, COLOR_B, COLOR_C],\n    }\n)\n\n# Editorial title and spec subtitle\ntitle_df = pd.DataFrame({\"label\": [\"Food Trend Taxonomy\"], \"x\": [0.0], \"y\": [3.22], \"color\": [INK]})\nsubtitle_df = pd.DataFrame(\n    {\"label\": [\"venn-labeled-items · python · plotnine · anyplot.ai\"], \"x\": [0.0], \"y\": [2.82], \"color\": [INK_MUTED]}\n)\n\n# Plot\nplot = (\n    ggplot()\n    + geom_polygon(\n        data=circles_df, mapping=aes(x=\"x\", y=\"y\", group=\"name\", fill=\"fill\"), color=INK_SOFT, alpha=0.22, size=0.6\n    )\n    # geom_label gives each item a clean background box — more readable in overlapping zones\n    + geom_label(\n        data=items_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=11,\n        color=INK,\n        fill=ELEVATED_BG,\n        label_size=0,\n        label_padding=0.12,\n        family=\"serif\",\n    )\n    # Consolidated category label layer (was three separate geom_text calls)\n    + geom_text(\n        data=cat_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\", color=\"color\"),\n        size=18,\n        fontweight=\"bold\",\n        family=\"serif\",\n        ha=\"center\",\n    )\n    + geom_text(\n        data=title_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\", color=\"color\"),\n        size=26,\n        fontweight=\"bold\",\n        fontstyle=\"italic\",\n        family=\"serif\",\n    )\n    + geom_text(data=subtitle_df, mapping=aes(x=\"x\", y=\"y\", label=\"label\", color=\"color\"), size=14, family=\"serif\")\n    + scale_fill_identity()\n    + scale_color_identity()\n    + scale_x_continuous(limits=(-3.5, 3.5), expand=(0, 0))\n    + scale_y_continuous(limits=(-3.5, 3.5), expand=(0, 0))\n    + coord_fixed(ratio=1)\n    + theme(\n        figure_size=(6, 6),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        axis_title=element_blank(),\n        axis_text=element_blank(),\n        axis_ticks=element_blank(),\n        axis_line=element_blank(),\n        panel_grid_major=element_blank(),\n        panel_grid_minor=element_blank(),\n        legend_position=\"none\",\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=6, height=6, units=\"in\", verbose=False)\n"}