{"spec_id":"tree-phylogenetic","library":"bokeh","language":"python","code":"\"\"\" anyplot.ai\ntree-phylogenetic: Phylogenetic Tree Diagram\nLibrary: bokeh 3.9.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-15\n\"\"\"\n\nimport os\nimport time\nfrom pathlib import Path\n\nfrom bokeh.io import output_file, save\nfrom bokeh.models import ColumnDataSource, HoverTool, Label, Legend, LegendItem\nfrom bokeh.plotting import figure\nfrom selenium import webdriver\nfrom selenium.webdriver.chrome.options import Options\n\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\"\nBRAND = \"#009E73\"\n\n# Phylogenetic tree data - Primate species (mitochondrial DNA based)\n# Structure: ((((Human, Chimp), Gorilla), Orangutan), Gibbon)\n# Rectangular cladogram layout\n\nspecies = [\"Human\", \"Chimpanzee\", \"Gorilla\", \"Orangutan\", \"Gibbon\"]\n\n# Leaf node positions (x = evolutionary distance, y = vertical position)\nleaf_y = [5, 4, 3, 2, 1]\nleaf_x = [0.75, 0.75, 0.65, 0.45, 0.25]\n\n# Internal node positions\ninternal_x = [0.60, 0.40, 0.20, 0.00]\ninternal_y = [4.5, 3.75, 2.875, 1.9375]\n\n# Horizontal branches from leaves to ancestors\nh_branch_x = [\n    [internal_x[0], leaf_x[0]],\n    [internal_x[0], leaf_x[1]],\n    [internal_x[1], leaf_x[2]],\n    [internal_x[2], leaf_x[3]],\n    [internal_x[3], leaf_x[4]],\n    [internal_x[1], internal_x[0]],\n    [internal_x[2], internal_x[1]],\n    [internal_x[3], internal_x[2]],\n]\n\nh_branch_y = [\n    [leaf_y[0], leaf_y[0]],\n    [leaf_y[1], leaf_y[1]],\n    [leaf_y[2], leaf_y[2]],\n    [leaf_y[3], leaf_y[3]],\n    [leaf_y[4], leaf_y[4]],\n    [internal_y[0], internal_y[0]],\n    [internal_y[1], internal_y[1]],\n    [internal_y[2], internal_y[2]],\n]\n\n# Vertical branches connecting nodes\nv_branch_x = [\n    [internal_x[0], internal_x[0]],\n    [internal_x[1], internal_x[1]],\n    [internal_x[2], internal_x[2]],\n    [internal_x[3], internal_x[3]],\n]\n\nv_branch_y = [\n    [leaf_y[0], leaf_y[1]],\n    [internal_y[0], leaf_y[2]],\n    [internal_y[1], leaf_y[3]],\n    [internal_y[2], leaf_y[4]],\n]\n\n# Create figure\np = figure(\n    width=4800,\n    height=2700,\n    title=\"Primate Evolution · tree-phylogenetic · bokeh · anyplot.ai\",\n    x_axis_label=\"Evolutionary Distance (substitutions per site)\",\n    y_axis_label=\"\",\n    x_range=(-0.15, 1.05),\n    y_range=(0.3, 5.7),\n)\n\n# Style the figure with theme-adaptive colors\np.background_fill_color = PAGE_BG\np.border_fill_color = PAGE_BG\np.outline_line_color = INK_SOFT\n\np.title.text_font_size = \"28pt\"\np.title.text_color = INK\n\np.xaxis.axis_label_text_font_size = \"22pt\"\np.xaxis.axis_label_text_color = INK\np.xaxis.major_label_text_font_size = \"18pt\"\np.xaxis.major_label_text_color = INK_SOFT\np.xaxis.axis_line_color = INK_SOFT\np.xaxis.major_tick_line_color = INK_SOFT\n\np.yaxis.visible = False\np.grid.visible = False\n\n# Draw horizontal branches using brand color\nfor hx, hy in zip(h_branch_x, h_branch_y, strict=True):\n    p.line(hx, hy, line_width=4, line_color=BRAND)\n\n# Draw vertical branches using brand color\nfor vx, vy in zip(v_branch_x, v_branch_y, strict=True):\n    p.line(vx, vy, line_width=4, line_color=BRAND)\n\n# Draw leaf nodes\nleaf_source = ColumnDataSource(\n    data={\n        \"x\": leaf_x,\n        \"y\": leaf_y,\n        \"species\": species,\n        \"type\": [\"Leaf Node\"] * len(species),\n        \"info\": [\n            \"Modern human (Homo sapiens)\",\n            \"Chimpanzee (Pan troglodytes)\",\n            \"Western gorilla (Gorilla gorilla)\",\n            \"Bornean orangutan (Pongo pygmaeus)\",\n            \"White-handed gibbon (Hylobates lar)\",\n        ],\n    }\n)\nleaf_scatter = p.scatter(\n    \"x\", \"y\", source=leaf_source, size=24, color=BRAND, line_color=INK_SOFT, line_width=3, name=\"leaf_nodes\"\n)\n\n# Draw internal nodes\ninternal_names = [\"Human-Chimp Ancestor\", \"Great Ape Ancestor\", \"Hominid Ancestor\", \"Root (Common Ancestor)\"]\ninternal_source = ColumnDataSource(\n    data={\"x\": internal_x, \"y\": internal_y, \"type\": [\"Internal Node\"] * len(internal_x), \"info\": internal_names}\n)\ninternal_scatter = p.scatter(\"x\", \"y\", source=internal_source, size=18, color=INK_SOFT, name=\"internal_nodes\")\n\n# Add hover tool\nhover = HoverTool(\n    renderers=[leaf_scatter, internal_scatter], tooltips=[(\"Type\", \"@type\"), (\"Info\", \"@info\")], mode=\"mouse\"\n)\np.add_tools(hover)\n\n# Add species labels with theme-adaptive color\nfor i, sp in enumerate(species):\n    label = Label(\n        x=leaf_x[i] + 0.02, y=leaf_y[i], text=sp, text_font_size=\"20pt\", text_baseline=\"middle\", text_color=INK\n    )\n    p.add_layout(label)\n\n# Add scale bar\nscale_bar_y = 0.6\np.line([0, 0.1], [scale_bar_y, scale_bar_y], line_width=4, line_color=INK_SOFT)\nscale_label = Label(\n    x=0.0, y=scale_bar_y - 0.15, text=\"0.1 substitutions/site\", text_font_size=\"16pt\", text_color=INK_SOFT\n)\np.add_layout(scale_label)\n\n# Add clade annotations with theme-adaptive color\nclade_labels = [\n    {\"x\": 0.58, \"y\": 4.5, \"text\": \"Hominini\"},\n    {\"x\": 0.38, \"y\": 3.75, \"text\": \"Homininae\"},\n    {\"x\": 0.18, \"y\": 2.875, \"text\": \"Hominidae\"},\n]\n\nfor clade in clade_labels:\n    bracket_label = Label(\n        x=clade[\"x\"] - 0.15,\n        y=clade[\"y\"],\n        text=clade[\"text\"],\n        text_font_size=\"20pt\",\n        text_font_style=\"italic\",\n        text_color=INK_SOFT,\n        text_baseline=\"middle\",\n    )\n    p.add_layout(bracket_label)\n\n# Add legend with theme-adaptive styling\nlegend = Legend(\n    items=[\n        LegendItem(label=\"Extant Species (Leaf Nodes)\", renderers=[leaf_scatter]),\n        LegendItem(label=\"Ancestral Nodes (Internal)\", renderers=[internal_scatter]),\n    ],\n    location=\"top_right\",\n    label_text_font_size=\"18pt\",\n    label_text_color=INK_SOFT,\n    spacing=10,\n    padding=15,\n    background_fill_color=ELEVATED_BG,\n    background_fill_alpha=0.9,\n    border_line_color=INK_SOFT,\n)\np.add_layout(legend)\n\n# Save HTML (required catalog artifact)\noutput_file(f\"plot-{THEME}.html\")\nsave(p)\n\n# Screenshot with Selenium/headless Chrome\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"}