{"spec_id":"line-confidence","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nline-confidence: Line Plot with Confidence Interval\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 82/100 | Updated: 2026-05-09\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme tokens\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\n# Okabe-Ito palette\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - Model predictions with 95% confidence interval\nnp.random.seed(42)\nx = np.linspace(0, 12, 50)\n\n# Central prediction: exponential growth pattern\ny_center = 1000 + 500 * (1 - np.exp(-0.3 * x)) + np.random.randn(50) * 20\ny_center = np.convolve(y_center, np.ones(5) / 5, mode=\"same\")\ny_center[0:2] = y_center[2]\ny_center[-2:] = y_center[-3]\n\n# Confidence interval widens over time\nuncertainty = 30 + 15 * x\ny_lower = y_center - uncertainty\ny_upper = y_center + uncertainty\n\n# Custom style for 4800x2700 canvas\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT,\n    title_font_size=28,\n    label_font_size=22,\n    major_label_font_size=18,\n    legend_font_size=16,\n    stroke_width=3,\n)\n\n# Create XY chart\nchart = pygal.XY(\n    style=custom_style,\n    width=4800,\n    height=2700,\n    title=\"line-confidence · pygal · anyplot.ai\",\n    x_title=\"Time (weeks)\",\n    y_title=\"Predicted Users\",\n    show_dots=False,\n    show_x_guides=True,\n    show_y_guides=True,\n    range=(float(y_lower.min() - 50), float(y_upper.max() + 50)),\n)\n\n# Create confidence band as closed polygon for fill\nconfidence_band = []\nfor xi, yi in zip(x, y_upper, strict=True):\n    confidence_band.append((float(xi), float(yi)))\nfor xi, yi in zip(reversed(x), reversed(y_lower), strict=True):\n    confidence_band.append((float(xi), float(yi)))\n\n# Center line data\ncenter_data = [(float(xi), float(yi)) for xi, yi in zip(x, y_center, strict=True)]\n\n# Add series: confidence band with solid fill (uses first color from palette)\nchart.add(\"95% Confidence Interval\", confidence_band, show_dots=False, fill=True, stroke=False)\n\n# Add center line (uses second color from palette)\nchart.add(\"Predicted Mean\", center_data, fill=False, stroke=True, show_dots=False, stroke_width=6)\n\n# Save outputs\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}