{"spec_id":"contour-filled","library":"bokeh","language":"python","code":"\"\"\" anyplot.ai\ncontour-filled: Filled Contour Plot\nLibrary: bokeh 3.9.0 | Python 3.13.13\nQuality: 86/100 | Updated: 2026-05-11\n\"\"\"\n\nimport os\nimport time\nfrom pathlib import Path\n\nimport bokeh.io\nimport bokeh.models\nimport bokeh.palettes\nimport bokeh.plotting\nimport numpy as np\nfrom contourpy import contour_generator\nfrom selenium import webdriver\nfrom selenium.webdriver.chrome.options import Options\n\n\noutput_file = bokeh.io.output_file\nsave = bokeh.io.save\nBasicTicker = bokeh.models.BasicTicker\nColorBar = bokeh.models.ColorBar\nHoverTool = bokeh.models.HoverTool\nLinearColorMapper = bokeh.models.LinearColorMapper\nViridis256 = bokeh.palettes.Viridis256\nfigure = bokeh.plotting.figure\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\n# Data - Terrain elevation surface with multiple peaks\nnp.random.seed(42)\nx = np.linspace(-3, 3, 80)\ny = np.linspace(-3, 3, 80)\nX, Y = np.meshgrid(x, y)\n\n# Create surface with multiple Gaussian peaks (terrain elevation in meters)\nZ = (\n    1.5 * np.exp(-((X - 1) ** 2 + (Y - 1) ** 2))\n    + 2.0 * np.exp(-((X + 1.5) ** 2 + (Y + 0.5) ** 2) / 1.5)\n    + 1.0 * np.exp(-((X - 0.5) ** 2 + (Y + 1.5) ** 2) / 0.8)\n    - 0.5 * np.exp(-((X + 0.5) ** 2 + (Y - 1.5) ** 2) / 0.5)\n)\n\n# Scale to realistic elevation values (0-2000 meters)\nZ = (Z - Z.min()) / (Z.max() - Z.min()) * 2000\n\n# Create figure at 4800x2700 px with interactive tools\np = figure(\n    width=4800,\n    height=2700,\n    title=\"contour-filled · bokeh · anyplot.ai\",\n    x_range=(x.min(), x.max()),\n    y_range=(y.min(), y.max()),\n    tools=\"pan,wheel_zoom,box_zoom,reset,save\",\n)\n\n# Explicitly set axis labels after figure creation\np.xaxis.axis_label = \"Distance East (km)\"\np.yaxis.axis_label = \"Distance North (km)\"\n\n# Color mapper for the filled surface\ncolor_mapper = LinearColorMapper(palette=Viridis256, low=Z.min(), high=Z.max())\n\n# Draw the filled surface using image\np.image(image=[Z], x=x.min(), y=y.min(), dw=x.max() - x.min(), dh=y.max() - y.min(), color_mapper=color_mapper)\n\n# Overlay contour lines at specific levels for precise identification\nn_contour_lines = 12\ncontour_levels = np.linspace(Z.min(), Z.max(), n_contour_lines + 2)[1:-1]\n\n# Create contour generator\ncont_gen = contour_generator(x=X, y=Y, z=Z)\n\n# Theme-aware contour line colors\ncontour_base = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\ncontour_outline = INK\n\n# Draw contour lines with high contrast (base color + outline)\nfor level in contour_levels:\n    lines = cont_gen.lines(level)\n    for line in lines:\n        # Draw base line for visibility\n        p.line(line[:, 0], line[:, 1], line_width=4, color=contour_base, alpha=0.9)\n        # Draw thinner outline on top for contrast\n        p.line(line[:, 0], line[:, 1], line_width=1.5, color=contour_outline, alpha=0.8)\n\n# Add colorbar with terrain context\ncolor_bar = ColorBar(\n    color_mapper=color_mapper,\n    ticker=BasicTicker(desired_num_ticks=10),\n    label_standoff=25,\n    title=\"Terrain Elevation (m)\",\n    title_text_font_size=\"24pt\",\n    title_standoff=20,\n    major_label_text_font_size=\"18pt\",\n    width=50,\n    padding=40,\n)\np.add_layout(color_bar, \"right\")\n\n# Style text for large canvas\np.title.text_font_size = \"28pt\"\np.xaxis.axis_label_text_font_size = \"22pt\"\np.yaxis.axis_label_text_font_size = \"22pt\"\np.xaxis.major_label_text_font_size = \"18pt\"\np.yaxis.major_label_text_font_size = \"18pt\"\n\n# Grid styling - very subtle with reduced opacity and width\np.xgrid.grid_line_color = INK\np.ygrid.grid_line_color = INK\np.xgrid.grid_line_alpha = 0.10\np.ygrid.grid_line_alpha = 0.10\np.xgrid.grid_line_width = 1\np.ygrid.grid_line_width = 1\np.xgrid.level = \"overlay\"\np.ygrid.level = \"overlay\"\n\n# Add hover tool for interactive elevation display\n# Create a grid of hover points for better interactivity\nhover_x, hover_y, hover_z = [], [], []\nstep = 4  # Sample every 4th point for responsive hovering\nfor i in range(0, len(x), step):\n    for j in range(0, len(y), step):\n        hover_x.append(x[i])\n        hover_y.append(y[j])\n        hover_z.append(round(Z[j, i], 1))\n\n# Add invisible scatter points for hover detection\nhover_renderer = p.scatter(hover_x, hover_y, size=30, fill_alpha=0, line_alpha=0, name=\"hover_points\")\nhover_renderer.data_source.data[\"elevation\"] = hover_z\n\n# Configure hover tool to show elevation values\nhover = HoverTool(\n    renderers=[hover_renderer],\n    tooltips=[(\"Location\", \"(@x{0.0} km E, @y{0.0} km N)\"), (\"Elevation\", \"@elevation{0} m\")],\n    mode=\"mouse\",\n)\np.add_tools(hover)\n\n# Theme-adaptive chrome\np.background_fill_color = PAGE_BG\np.border_fill_color = PAGE_BG\np.outline_line_color = INK_SOFT\n\np.title.text_color = INK\np.xaxis.axis_label_text_color = INK\np.yaxis.axis_label_text_color = INK\np.xaxis.major_label_text_color = INK_SOFT\np.yaxis.major_label_text_color = INK_SOFT\np.xaxis.axis_line_color = INK_SOFT\np.yaxis.axis_line_color = INK_SOFT\np.xaxis.major_tick_line_color = INK_SOFT\np.yaxis.major_tick_line_color = INK_SOFT\n\nif p.legend:\n    p.legend.background_fill_color = ELEVATED_BG\n    p.legend.border_line_color = INK_SOFT\n    p.legend.label_text_color = INK_SOFT\n\n# Colorbar text styling\nif p.right:\n    for renderer in p.right:\n        if hasattr(renderer, \"label_text_color\"):\n            renderer.label_text_color = INK_SOFT\n        if hasattr(renderer, \"title_text_color\"):\n            renderer.title_text_color = INK\n\n# Save as HTML\noutput_file(f\"plot-{THEME}.html\")\nsave(p)\n\n# Screenshot with Selenium\nW, H = 4800, 2700\nopts = Options()\nfor arg in (\n    \"--headless=new\",\n    \"--no-sandbox\",\n    \"--disable-dev-shm-usage\",\n    \"--disable-gpu\",\n    f\"--window-size={W},{H}\",\n    \"--hide-scrollbars\",\n):\n    opts.add_argument(arg)\ndriver = webdriver.Chrome(options=opts)\ndriver.set_window_size(W, H)\ndriver.get(f\"file://{Path(f'plot-{THEME}.html').resolve()}\")\ntime.sleep(3)\ndriver.save_screenshot(f\"plot-{THEME}.png\")\ndriver.quit()\n"}