{"spec_id":"band-basic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nband-basic: Basic Band Plot\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-29\n\"\"\"\n\nimport os\nimport sys\n\n\n# Script is named plotnine.py — remove its directory from sys.path so the\n# installed plotnine package is found instead of this file.\n_this_dir = os.path.abspath(os.path.dirname(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p or os.getcwd()) != _this_dir]\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    coord_cartesian,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_line,\n    geom_ribbon,\n    ggplot,\n    labs,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\n\n\n# Theme-adaptive chrome tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\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 — first series is always #009E73\nBRAND = \"#009E73\"\n\n# Data: sensor readings with 95% confidence interval\nnp.random.seed(42)\nn_points = 60\ndays = np.linspace(0, 30, n_points)\n\n# Central trend: temperature rising then stabilizing (realistic sensor pattern)\ntemperature = 18 + 4 * (1 - np.exp(-0.15 * days)) + 1.5 * np.sin(0.4 * days)\ntemperature = temperature + np.random.normal(0, 0.3, n_points)\n\n# Uncertainty narrows as model calibrates, then widens for extrapolation\nuncertainty = 1.8 * np.exp(-0.08 * days) + 0.3 + 0.04 * np.maximum(days - 20, 0)\n\ntemp_lower = temperature - 1.96 * uncertainty\ntemp_upper = temperature + 1.96 * uncertainty\n\ndf = pd.DataFrame({\"days\": days, \"temperature\": temperature, \"temp_lower\": temp_lower, \"temp_upper\": temp_upper})\n\n# Title length ~73 chars → scale down: round(12 × 67 / 73) = 11\nplot = (\n    ggplot(df, aes(x=\"days\"))\n    + geom_ribbon(aes(ymin=\"temp_lower\", ymax=\"temp_upper\"), fill=BRAND, alpha=0.35)\n    + geom_line(aes(y=\"temperature\"), color=INK, size=1.0)\n    + annotate(\n        \"text\", x=7, y=temp_lower.min() - 0.8, label=\"Calibration Phase\", size=3.5, color=INK_SOFT, fontstyle=\"italic\"\n    )\n    + annotate(\n        \"text\", x=25, y=temp_lower.min() - 0.8, label=\"Extrapolation\", size=3.5, color=INK_SOFT, fontstyle=\"italic\"\n    )\n    + annotate(\n        \"segment\",\n        x=15,\n        xend=15,\n        y=temp_lower.min() - 1.6,\n        yend=temp_upper.max() + 0.5,\n        color=INK_SOFT,\n        size=0.5,\n        linetype=\"dashed\",\n    )\n    + labs(\n        x=\"Time (days)\",\n        y=\"Temperature (°C)\",\n        title=\"Sensor Calibration Forecast · band-basic · python · plotnine · anyplot.ai\",\n        subtitle=\"Shaded region shows 95% confidence interval — narrowing during calibration, widening for extrapolation\",\n    )\n    + scale_x_continuous(breaks=range(0, 31, 5))\n    + scale_y_continuous(labels=lambda lst: [f\"{v:.0f}°C\" for v in lst])\n    + coord_cartesian(expand=True)\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        text=element_text(size=7),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        plot_title=element_text(size=11, color=INK),\n        plot_subtitle=element_text(size=8, color=INK_SOFT),\n        panel_grid_major_y=element_line(color=INK, size=0.3, alpha=0.15),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        panel_border=element_blank(),\n        axis_line=element_line(color=INK_SOFT, size=0.5),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}