{"spec_id":"line-confidence","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nline-confidence: Line Plot with Confidence Interval\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-09\n\"\"\"\n\nimport os\nimport shutil\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\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\"\nRULE = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\nBRAND = \"#009E73\"  # Okabe-Ito position 1\n\n# Data - Monthly sales forecast with 95% confidence interval\nnp.random.seed(42)\nmonths = np.arange(1, 25)\ntrend = 50 + months * 2.5 + np.sin(months * np.pi / 6) * 10\nnoise = np.random.normal(0, 3, len(months))\ny = trend + noise\n\n# Calculate confidence interval (simulating forecast uncertainty that grows over time)\nstd_error = 3 + months * 0.3\ny_lower = y - 1.96 * std_error\ny_upper = y + 1.96 * std_error\n\ndf = pd.DataFrame({\"Month\": months, \"Sales\": y, \"Lower\": y_lower, \"Upper\": y_upper})\n\n# Create plot with legend\nplot = (\n    ggplot(df)\n    + geom_ribbon(aes(x=\"Month\", ymin=\"Lower\", ymax=\"Upper\", fill=\"95% Confidence Interval\"), alpha=0.25)\n    + geom_line(aes(x=\"Month\", y=\"Sales\", color=\"Sales Forecast\"), size=2)\n    + geom_point(aes(x=\"Month\", y=\"Sales\"), color=BRAND, size=4)\n    + scale_color_manual(values=[BRAND])\n    + scale_fill_manual(values=[BRAND])\n    + labs(x=\"Month\", y=\"Sales (thousands)\", title=\"line-confidence · letsplot · anyplot.ai\")\n    + scale_x_continuous(breaks=list(range(0, 25, 3)))\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=RULE, size=0.3),\n        panel_grid_minor=element_blank(),\n        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT, size=0.5),\n        plot_title=element_text(size=24, color=INK),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_title=element_text(size=16, color=INK),\n        legend_position=\"top\",\n    )\n    + ggsize(1600, 900)\n)\n\n# Save as PNG with explicit pixel dimensions (4800 × 2700 px)\npng_path = ggsave(plot, f\"plot-{THEME}.png\", w=4800, h=2700, unit=\"px\", dpi=100)\nshutil.move(png_path, f\"plot-{THEME}.png\")\n\n# Save as HTML for interactive viewing\nhtml_path = ggsave(plot, f\"plot-{THEME}.html\")\nshutil.move(html_path, f\"plot-{THEME}.html\")\n"}