{"spec_id":"tree-phylogenetic","library":"makie","language":"julia","code":"# anyplot.ai\n# tree-phylogenetic: Phylogenetic Tree Diagram\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 89/100 | Created: 2026-09-09\n\nusing CairoMakie\nusing Colors\n\n# Theme tokens (see prompts/default-style-guide.md \"Background\" + \"Theme-adaptive Chrome\")\nTHEME = get(ENV, \"ANYPLOT_THEME\", \"light\")\nPAGE_BG = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nINK = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nINK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\n\nBRAND = colorant\"#009E73\"  # Imprint palette position 1 — highlighted clade (Hominidae)\n\n# Data — simplified primate phylogeny from mitochondrial-DNA divergence,\n# pectinate topology. Leaves are ids 1-8, internal nodes 9-15; each dict\n# entry keys a node id to its children (internal) or its parent-branch\n# length (substitutions per site). No Newick parser / Phylo.jl in the CI\n# runtime, so the tree is expressed directly as id-based adjacency.\nspecies = Dict(\n    1 => \"Human\", 2 => \"Chimpanzee\", 3 => \"Gorilla\", 4 => \"Orangutan\",\n    5 => \"Gibbon\", 6 => \"Rhesus Macaque\", 7 => \"Common Marmoset\", 8 => \"Mouse Lemur\",\n)\nchildren = Dict(\n    9 => (1, 2), 10 => (9, 3), 11 => (10, 4), 12 => (11, 5),\n    13 => (12, 6), 14 => (13, 7), 15 => (14, 8),\n)\nbranch_length = Dict(\n    1 => 0.006, 2 => 0.006, 9 => 0.010, 3 => 0.016, 10 => 0.008,\n    4 => 0.024, 11 => 0.010, 5 => 0.034, 12 => 0.012, 6 => 0.046,\n    13 => 0.014, 7 => 0.060, 14 => 0.018, 8 => 0.078,\n)\nroot_id = 15\nleaf_order = [1, 2, 3, 4, 5, 6, 7, 8]  # top-to-bottom drawing order\nhominidae = Set([1, 2, 3, 4])  # great apes — the highlighted lineage\n\n# Layout — x is cumulative branch length from the root (ancestor at x=0,\n# present day at max x); y is leaf rank, with internal nodes placed at the\n# mean of their children's y (standard cladogram convention).\nnode_x = Dict{Int,Float64}(root_id => 0.0)\nfor nid in root_id:-1:9\n    i, j = children[nid]\n    node_x[i] = node_x[nid] + branch_length[i]\n    node_x[j] = node_x[nid] + branch_length[j]\nend\n\nnode_y = Dict{Int,Float64}()\nfor (rank, leaf) in enumerate(leaf_order)\n    node_y[leaf] = length(leaf_order) - rank + 1\nend\nfor nid in 9:root_id\n    i, j = children[nid]\n    node_y[nid] = (node_y[i] + node_y[j]) / 2\nend\n\n# Pure-clade color propagation: a node is \"in\" Hominidae only if every leaf\n# beneath it is a great ape, so the highlight stops exactly at the clade's\n# stem branch (mirrors the standard dendrogram color_threshold convention).\nin_clade = Dict{Int,Bool}(leaf => (leaf in hominidae) for leaf in leaf_order)\nfor nid in 9:root_id\n    i, j = children[nid]\n    in_clade[nid] = in_clade[i] && in_clade[j]\nend\n\nmax_x = maximum(values(node_x))\n\n# Plot — see default-style-guide.md \"Visual Sizing Defaults\" for the canvas + sizing values\ntitle_text = \"tree-phylogenetic · julia · makie · anyplot.ai\"\n\nfig = Figure(\n    resolution = (1600, 900),\n    fontsize = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title = title_text,\n    titlesize = 20,\n    titlecolor = INK,\n    backgroundcolor = PAGE_BG,\n)\nhidedecorations!(ax)\nhidespines!(ax)\nlimits!(ax, -0.004, max_x + 0.07, -1.1, 8.8)\n\n# Branches — one horizontal segment per node (parent x to node x) plus one\n# vertical connector per internal node joining its two children.\nfor nid in 9:root_id\n    i, j = children[nid]\n    xp, yp = node_x[nid], node_y[nid]\n    for c in (i, j)\n        edge_color = in_clade[c] ? BRAND : INK_SOFT\n        lines!(ax, [xp, node_x[c]], [node_y[c], node_y[c]]; color = edge_color, linewidth = 2.5)\n    end\n    connector_color = in_clade[nid] ? BRAND : INK_SOFT\n    lines!(ax, [xp, xp], [node_y[i], node_y[j]]; color = connector_color, linewidth = 2.5)\nend\n\n# Leaf tips and species labels.\nfor leaf in leaf_order\n    tip_color = in_clade[leaf] ? BRAND : INK_SOFT\n    label_color = in_clade[leaf] ? INK : INK_SOFT\n    scatter!(\n        ax, [node_x[leaf]], [node_y[leaf]];\n        color = tip_color, markersize = 14, strokewidth = 1.5, strokecolor = PAGE_BG,\n    )\n    text!(\n        ax, node_x[leaf] + max_x * 0.025, node_y[leaf];\n        text = species[leaf], align = (:left, :center), fontsize = 14, color = label_color,\n    )\nend\n\n# Clade callout — labels the highlighted great-ape lineage near its stem.\ntext!(\n    ax, node_x[10], node_y[10] + 1.0;\n    text = \"Hominidae\\n(great apes)\", align = (:left, :bottom),\n    fontsize = 12, color = BRAND, justification = :left,\n)\n\n# Scale bar — standard phylogenetic-tree convention for branch length units.\nscale_len = 0.02\nscale_y = -0.5\nlines!(ax, [0.0, scale_len], [scale_y, scale_y]; color = INK_SOFT, linewidth = 2.0)\nlines!(ax, [0.0, 0.0], [scale_y - 0.12, scale_y + 0.12]; color = INK_SOFT, linewidth = 2.0)\nlines!(ax, [scale_len, scale_len], [scale_y - 0.12, scale_y + 0.12]; color = INK_SOFT, linewidth = 2.0)\ntext!(\n    ax, scale_len / 2, scale_y - 0.35;\n    text = \"0.02 substitutions / site\", align = (:center, :top), fontsize = 12, color = INK_SOFT,\n)\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}