{"spec_id":"range-interval","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nrange-interval: Range Interval Chart\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-18\n\"\"\"\n\nimport os\n\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\"\n\nBRAND = \"#009E73\"  # Okabe-Ito position 1\nACCENT1 = \"#C475FD\"  # Okabe-Ito position 2\nACCENT2 = \"#4467A3\"  # Okabe-Ito position 3\n\n# Data: Monthly temperature ranges (°C) for a weather station\ndata = {\n    \"month\": [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"],\n    \"min_temp\": [-2, 0, 4, 8, 13, 17, 19, 18, 14, 9, 4, 0],\n    \"max_temp\": [6, 8, 12, 17, 22, 26, 29, 28, 24, 18, 11, 7],\n}\n\ndf = pd.DataFrame(data)\n\n# Calculate midpoint for reference markers\ndf[\"mid_temp\"] = (df[\"min_temp\"] + df[\"max_temp\"]) / 2\n\n# Preserve month order\ndf[\"month\"] = pd.Categorical(df[\"month\"], categories=data[\"month\"], ordered=True)\n\n# Create range interval chart\nplot = (\n    ggplot(df)\n    # Range bars as thick vertical segments (data-driven)\n    + geom_segment(aes(x=\"month\", xend=\"month\", y=\"min_temp\", yend=\"max_temp\"), size=8, color=BRAND, alpha=0.7)\n    # Min endpoint markers (hollow circles)\n    + geom_point(aes(x=\"month\", y=\"min_temp\"), size=5, color=BRAND, shape=1, stroke=2)\n    # Max endpoint markers (triangles)\n    + geom_point(aes(x=\"month\", y=\"max_temp\"), size=5, color=ACCENT1, shape=2, stroke=2)\n    # Midpoint markers (solid circles)\n    + geom_point(aes(x=\"month\", y=\"mid_temp\"), size=4, color=ACCENT2, shape=16)\n    # Labels and title\n    + labs(x=\"Month\", y=\"Temperature (°C)\", title=\"range-interval · python · letsplot · anyplot.ai\")\n    # Theme for large canvas and theme-adaptive styling\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_grid_major_y=element_line(color=INK_SOFT, size=0.3),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        axis_line_x=element_line(color=INK_SOFT, size=0.4),\n        axis_line_y=element_line(color=INK_SOFT, size=0.4),\n        plot_title=element_text(size=24, face=\"bold\", color=INK),\n        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n    )\n    + ggsize(1600, 900)\n)\n\n# Save as PNG (scale 3x for 4800x2700)\nggsave(plot, f\"plot-{THEME}.png\", scale=3, path=\".\")\n\n# Save as HTML for interactive viewing\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}