{"spec_id":"box-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nbox-basic: Basic Box Plot\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent this file (named matplotlib.py) from shadowing the installed matplotlib package\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.realpath(p or \".\") != _here]\ndel _here\n\nimport matplotlib.patheffects as pe\nimport matplotlib.pyplot as plt\nimport numpy as np\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\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Data — annual salary distributions (USD thousands) across five job sectors\nnp.random.seed(42)\nsectors = [\"Technology\", \"Finance\", \"Healthcare\", \"Education\", \"Retail\"]\nsalary_data = [\n    np.clip(np.random.normal(118, 28, 80), 55, 260),  # Technology: high, moderate spread\n    np.clip(np.random.normal(108, 35, 75), 45, 300),  # Finance: high, wide spread\n    np.clip(np.random.normal(94, 20, 85), 42, 200),  # Healthcare: moderate, tight\n    np.clip(np.random.normal(66, 14, 70), 35, 120),  # Education: lower, narrow\n    np.clip(np.random.normal(50, 11, 65), 28, 95),  # Retail: lowest, tight\n]\n\n# Inject deliberate outliers for feature coverage\nsalary_data[0] = np.append(salary_data[0], [228, 246])  # Tech: senior engineers\nsalary_data[1] = np.append(salary_data[1], [268, 290, 47])  # Finance: top earners + entry-level\n\n# Plot\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nbp = ax.boxplot(\n    salary_data,\n    tick_labels=sectors,\n    patch_artist=True,\n    widths=0.55,\n    showmeans=True,\n    notch=True,\n    meanprops={\"marker\": \"D\", \"markerfacecolor\": PAGE_BG, \"markeredgecolor\": INK, \"markersize\": 6, \"zorder\": 5},\n    flierprops={\n        \"marker\": \"o\",\n        \"markerfacecolor\": INK_MUTED,\n        \"markersize\": 5,\n        \"alpha\": 0.65,\n        \"markeredgecolor\": PAGE_BG,\n        \"markeredgewidth\": 0.5,\n    },\n    medianprops={\"color\": INK, \"linewidth\": 2.5},\n    whiskerprops={\"linewidth\": 1.8, \"color\": INK_SOFT, \"linestyle\": \"--\"},\n    capprops={\"linewidth\": 2.0, \"color\": INK_SOFT},\n)\n\n# Apply Imprint palette colors to boxes with theme-adaptive path effect depth\nfor patch, color in zip(bp[\"boxes\"], IMPRINT_PALETTE[:5], strict=False):\n    patch.set_facecolor(color)\n    patch.set_alpha(0.75)\n    patch.set_edgecolor(color)\n    patch.set_linewidth(2.0)\n    patch.set_path_effects([pe.withStroke(linewidth=3.5, foreground=INK_SOFT)])\n\n# Compute stats for data-driven annotations\niqrs = [np.percentile(d, 75) - np.percentile(d, 25) for d in salary_data]\nmedians = [np.median(d) for d in salary_data]\nq3s = [np.percentile(d, 75) for d in salary_data]\n\ntightest_idx = int(np.argmin(iqrs))\nwidest_idx = int(np.argmax(iqrs))\nbest_idx = int(np.argmax(medians))\n\n# Annotation — highest median salary (Technology, directly above box)\nax.annotate(\n    f\"Highest median\\n${medians[best_idx]:.0f}K\",\n    xy=(best_idx + 1, q3s[best_idx] + 1),\n    xytext=(best_idx + 1, q3s[best_idx] + 52),\n    fontsize=8,\n    fontweight=\"bold\",\n    color=IMPRINT_PALETTE[best_idx],\n    ha=\"center\",\n    va=\"bottom\",\n    arrowprops={\"arrowstyle\": \"->\", \"color\": IMPRINT_PALETTE[best_idx], \"lw\": 1.5},\n    bbox={\"boxstyle\": \"round,pad=0.3\", \"facecolor\": ELEVATED_BG, \"edgecolor\": IMPRINT_PALETTE[best_idx], \"alpha\": 0.9},\n)\n\n# Annotation — widest IQR (Finance, placed higher to clear Healthcare box region)\nax.annotate(\n    f\"Widest spread\\nIQR=${iqrs[widest_idx]:.0f}K\",\n    xy=(widest_idx + 1, medians[widest_idx]),\n    xytext=(widest_idx + 1.7, medians[widest_idx] + 65),\n    fontsize=8,\n    fontweight=\"bold\",\n    color=IMPRINT_PALETTE[widest_idx],\n    ha=\"left\",\n    arrowprops={\n        \"arrowstyle\": \"->\",\n        \"connectionstyle\": \"arc3,rad=-0.3\",\n        \"color\": IMPRINT_PALETTE[widest_idx],\n        \"lw\": 1.5,\n    },\n    bbox={\n        \"boxstyle\": \"round,pad=0.3\",\n        \"facecolor\": ELEVATED_BG,\n        \"edgecolor\": IMPRINT_PALETTE[widest_idx],\n        \"alpha\": 0.9,\n    },\n)\n\n# Annotation — tightest IQR (Retail, placed directly above Retail's box)\n# Placed at x=tightest_idx+1 (same column as Retail) so it cannot overlap Healthcare (x=3).\n# Use INK text color in dark theme: #AE3030 on dark elevated bg has marginal contrast.\n_tight_text_color = INK if THEME == \"dark\" else IMPRINT_PALETTE[tightest_idx]\nax.annotate(\n    f\"Tightest spread\\nIQR=${iqrs[tightest_idx]:.0f}K\",\n    xy=(tightest_idx + 1, q3s[tightest_idx] + 1),\n    xytext=(tightest_idx + 1, q3s[tightest_idx] + 42),\n    fontsize=8,\n    fontweight=\"bold\",\n    color=_tight_text_color,\n    ha=\"center\",\n    va=\"bottom\",\n    arrowprops={\"arrowstyle\": \"->\", \"color\": IMPRINT_PALETTE[tightest_idx], \"lw\": 1.5},\n    bbox={\n        \"boxstyle\": \"round,pad=0.3\",\n        \"facecolor\": ELEVATED_BG,\n        \"edgecolor\": IMPRINT_PALETTE[tightest_idx],\n        \"alpha\": 0.9,\n    },\n)\n\n# Style\ntitle = \"box-basic · python · matplotlib · anyplot.ai\"\ntitle_fontsize = max(8, round(12 * 67 / len(title))) if len(title) > 67 else 12\n\nax.set_xlabel(\"Sector\", fontsize=10, color=INK)\nax.set_ylabel(\"Annual Salary (USD thousands)\", fontsize=10, color=INK)\nax.set_title(\n    title,\n    fontsize=title_fontsize,\n    fontweight=\"medium\",\n    color=INK,\n    pad=15,\n    path_effects=[pe.withStroke(linewidth=3, foreground=PAGE_BG)],\n)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT, labelcolor=INK_SOFT)\nax.tick_params(axis=\"x\", length=0, pad=6)\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\nax.set_axisbelow(True)\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\nfig.subplots_adjust(left=0.12, right=0.97, top=0.88, bottom=0.13)\n\n# Save\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}