{"spec_id":"gauge-activity-rings","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\ngauge-activity-rings: Activity Rings Progress Chart\nLibrary: matplotlib 3.11.0 | Python 3.13.13\nQuality: 87/100 | Created: 2026-06-14\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.patches import Circle, Wedge\n\n\n# Theme tokens (Imprint palette + chrome)\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Daily fitness goal data — Move / Exercise / Stand\nmetrics = [\n    {\"name\": \"Move\", \"value\": 420, \"goal\": 600, \"unit\": \"kcal\"},\n    {\"name\": \"Exercise\", \"value\": 28, \"goal\": 30, \"unit\": \"min\"},\n    {\"name\": \"Stand\", \"value\": 9, \"goal\": 12, \"unit\": \"hr\"},\n]\nring_colors = IMPRINT_PALETTE[:3]  # green → lavender → blue\nradii = [0.78, 0.53, 0.28]  # outer → inner (mid-radius of each ring)\nRING_WIDTH = 0.115  # ring thickness in data units (~linewidth 20pt equivalent)\n\nfractions = [min(m[\"value\"] / m[\"goal\"], 1.0) for m in metrics]\navg_pct = sum(fractions) / len(fractions)\n\n# Plot — square canvas for circular rings\nfig, ax = plt.subplots(figsize=(6, 6), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\nax.set_aspect(\"equal\")\nax.set_xlim(-1.1, 1.1)\nax.set_ylim(-1.1, 1.1)\nax.axis(\"off\")\n\nfor _metric, color, r, frac in zip(metrics, ring_colors, radii, fractions, strict=False):\n    outer_r = r + RING_WIDTH / 2\n\n    # Background track — full Wedge ring at low opacity\n    ax.add_patch(\n        Wedge((0, 0), outer_r, 0, 360, width=RING_WIDTH, facecolor=color, edgecolor=\"none\", alpha=0.15, zorder=2)\n    )\n\n    if frac > 0:\n        # Progress arc — Wedge sweeping clockwise from 90° (12 o'clock)\n        # Wedge uses CCW angles from positive x-axis; clockwise sweep maps to theta2=90, theta1=90-frac*360\n        theta1_deg = 90 - frac * 360\n        ax.add_patch(\n            Wedge((0, 0), outer_r, theta1_deg, 90, width=RING_WIDTH, facecolor=color, edgecolor=\"none\", zorder=3)\n        )\n\n        # Rounded caps — half-circle at each endpoint of the progress arc\n        cap_r = RING_WIDTH / 2\n        # Start cap at 12 o'clock\n        ax.add_patch(Circle((0.0, r), cap_r, facecolor=color, edgecolor=\"none\", zorder=4))\n        # End cap at arc terminus\n        theta_end = np.radians(theta1_deg)\n        ax.add_patch(\n            Circle((r * np.cos(theta_end), r * np.sin(theta_end)), cap_r, facecolor=color, edgecolor=\"none\", zorder=4)\n        )\n\n# Center summary — overall average progress\nax.text(0, 0.06, f\"{avg_pct:.0%}\", ha=\"center\", va=\"center\", fontsize=22, fontweight=\"bold\", color=INK, zorder=5)\nax.text(0, -0.10, \"Daily Goals\", ha=\"center\", va=\"center\", fontsize=9, color=INK_MUTED, zorder=5)\n\n# Title\ntitle = \"gauge-activity-rings · python · matplotlib · anyplot.ai\"\nn = len(title)\ntitle_fs = max(8, round(12 * 67 / n)) if n > 67 else 12\nax.set_title(title, fontsize=title_fs, fontweight=\"medium\", color=INK, pad=14)\n\n# Per-ring metric labels below the chart (figure coordinates) — tightened gap\nfig.subplots_adjust(left=0.05, right=0.95, top=0.93, bottom=0.12)\nlabel_ys = [0.160, 0.127, 0.094]\n\nfor i, (metric, color, frac) in enumerate(zip(metrics, ring_colors, fractions, strict=False)):\n    pct = f\"{frac:.0%}\"\n    label = f\"●  {metric['name']}     {metric['value']} / {metric['goal']} {metric['unit']}     ({pct})\"\n    fig.text(0.50, label_ys[i], label, ha=\"center\", va=\"top\", fontsize=10, color=color)\n\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\nplt.close()\n"}