{"spec_id":"band-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nband-basic: Basic Band Plot\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-29\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent this file's directory from shadowing the installed plotly package.\n# When Python runs \"python plotly.py\" it inserts the script's directory as\n# sys.path[0], which causes \"import plotly\" to resolve to this file itself.\n_impl_dir = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if p != \"\" and os.path.normpath(p) != os.path.normpath(_impl_dir)]\ndel _impl_dir\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens (Imprint palette — see prompts/default-style-guide.md)\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\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\nBRAND = \"#009E73\"  # Imprint palette position 1 — ALWAYS first series\nBAND_FILL = \"rgba(0,158,115,0.25)\" if THEME == \"light\" else \"rgba(0,158,115,0.4)\"\n\n# Data\nhours = np.linspace(0, 48, 100)\n# Sensor temperature reading with slight oscillation\ntemperature = 20 + 0.15 * hours + 1.5 * np.sin(hours * 0.3)\n# Measurement uncertainty grows over time (sensor drift)\nuncertainty = 0.4 + 0.02 * hours\ntemp_lower = temperature - 1.96 * uncertainty\ntemp_upper = temperature + 1.96 * uncertainty\n\n# Plot\nfig = go.Figure()\n\n# Band (fill between lower and upper bounds using concat/toself pattern)\nfig.add_trace(\n    go.Scatter(\n        x=np.concatenate([hours, hours[::-1]]),\n        y=np.concatenate([temp_upper, temp_lower[::-1]]),\n        fill=\"toself\",\n        fillcolor=BAND_FILL,\n        line={\"width\": 0},\n        hoverinfo=\"skip\",\n        showlegend=True,\n        name=\"95% Confidence Interval\",\n    )\n)\n\n# Central trend line with custom hover showing confidence bounds\nfig.add_trace(\n    go.Scatter(\n        x=hours,\n        y=temperature,\n        mode=\"lines\",\n        line={\"color\": BRAND, \"width\": 3},\n        name=\"Measured Temperature\",\n        customdata=np.stack([temp_lower, temp_upper], axis=-1),\n        hovertemplate=(\n            \"<b>Hour:</b> %{x:.1f} h<br>\"\n            \"<b>Temp:</b> %{y:.1f} °C<br>\"\n            \"<b>CI:</b> [%{customdata[0]:.1f}, %{customdata[1]:.1f}] °C\"\n            \"<extra></extra>\"\n        ),\n    )\n)\n\ntitle = \"band-basic · python · plotly · anyplot.ai\"\n\n# Layout\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    title={\"text\": title, \"font\": {\"size\": 16, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\"},\n    xaxis={\n        \"title\": {\"text\": \"Elapsed Time (hours)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": False,\n        \"linecolor\": INK_SOFT,\n        \"showline\": True,\n        \"mirror\": False,\n        \"showgrid\": False,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Temperature (°C)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": False,\n        \"linecolor\": INK_SOFT,\n        \"showline\": True,\n        \"mirror\": False,\n        \"showgrid\": True,\n    },\n    legend={\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"yanchor\": \"top\",\n        \"y\": 0.99,\n        \"xanchor\": \"left\",\n        \"x\": 0.01,\n    },\n    margin={\"l\": 80, \"r\": 60, \"t\": 80, \"b\": 60},\n    hoverlabel={\"font\": {\"size\": 14}},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}