{"spec_id":"contour-density","library":"bokeh","language":"python","code":"\"\"\" anyplot.ai\ncontour-density: Density Contour Plot\nLibrary: bokeh 3.9.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-16\n\"\"\"\n\nimport os\nimport sys\nimport time\nfrom pathlib import Path\n\n\n# Fix import path collision with local library files in same directory\nsys.path = [p for p in sys.path if not p.endswith((\"bokeh.py\", \"implementations/python\"))]\n\nimport numpy as np\nfrom bokeh.io import output_file, save\nfrom bokeh.models import ColumnDataSource\nfrom bokeh.plotting import figure\nfrom scipy import stats\nfrom selenium import webdriver\nfrom selenium.webdriver.chrome.options import Options\n\n\nmpl_module = __import__(\"matplotlib\")\nmpl_module.use(\"Agg\")\nplt = __import__(\"matplotlib.pyplot\", fromlist=[\"pyplot\"])\n\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\"\nBRAND = \"#009E73\"\n\n# Data - bivariate distribution with clusters\nnp.random.seed(42)\nn_points = 500\n\ncluster1_x = np.random.normal(25, 4, n_points // 2)\ncluster1_y = np.random.normal(35, 5, n_points // 2)\ncluster2_x = np.random.normal(40, 6, n_points // 2)\ncluster2_y = np.random.normal(50, 4, n_points // 2)\n\nx = np.concatenate([cluster1_x, cluster2_x])\ny = np.concatenate([cluster1_y, cluster2_y])\n\n# Compute 2D KDE\nkde = stats.gaussian_kde([x, y])\n\n# Create grid for contour evaluation\nx_min, x_max = x.min() - 3, x.max() + 3\ny_min, y_max = y.min() - 3, y.max() + 3\nxx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np.linspace(y_min, y_max, 100))\npositions = np.vstack([xx.ravel(), yy.ravel()])\ndensity = kde(positions).reshape(xx.shape)\n\n# Extract contour lines using matplotlib (for calculation only)\nfig_temp, ax_temp = plt.subplots()\ncontour_set = ax_temp.contour(xx, yy, density, levels=8)\nplt.close(fig_temp)\n\n# Create Bokeh figure\np = figure(\n    width=4800,\n    height=2700,\n    title=\"contour-density · bokeh · anyplot.ai\",\n    x_axis_label=\"Measurement A (units)\",\n    y_axis_label=\"Measurement B (units)\",\n    x_range=(x_min, x_max),\n    y_range=(y_min, y_max),\n)\n\n# Contour colors - blue gradient (low to high density)\ncolors = [\"#e8f4f8\", \"#c6e4f2\", \"#94cfea\", \"#5bb4e0\", \"#306998\", \"#1f5070\", \"#143848\", \"#0a1c24\"]\n\n# Plot contour lines\nfor i, level_segs in enumerate(contour_set.allsegs):\n    color = colors[min(i, len(colors) - 1)]\n    for seg in level_segs:\n        if len(seg) > 1:\n            p.line(x=seg[:, 0], y=seg[:, 1], line_width=3, line_color=color, line_alpha=0.9)\n\n# Overlay scatter points (using Okabe-Ito first series)\nsource = ColumnDataSource(data={\"x\": x, \"y\": y})\np.scatter(x=\"x\", y=\"y\", source=source, size=8, color=BRAND, alpha=0.4, legend_label=\"Data points\")\n\n# Styling\np.title.text_font_size = \"28pt\"\np.title.text_color = INK\np.xaxis.axis_label_text_font_size = \"22pt\"\np.yaxis.axis_label_text_font_size = \"22pt\"\np.xaxis.axis_label_text_color = INK\np.yaxis.axis_label_text_color = INK\np.xaxis.major_label_text_font_size = \"18pt\"\np.yaxis.major_label_text_font_size = \"18pt\"\np.xaxis.major_label_text_color = INK_SOFT\np.yaxis.major_label_text_color = INK_SOFT\n\np.background_fill_color = PAGE_BG\np.border_fill_color = PAGE_BG\np.outline_line_color = INK_SOFT\np.xaxis.axis_line_color = INK_SOFT\np.yaxis.axis_line_color = INK_SOFT\n\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\n\np.legend.label_text_font_size = \"18pt\"\np.legend.location = \"top_left\"\np.legend.label_text_color = INK_SOFT\np.legend.background_fill_color = PAGE_BG\np.legend.border_line_color = INK_SOFT\n\n# Save 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"}