{"spec_id":"tree-phylogenetic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\ntree-phylogenetic: Phylogenetic Tree Diagram\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-15\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    coord_cartesian,\n    element_blank,\n    element_rect,\n    element_text,\n    geom_point,\n    geom_segment,\n    geom_text,\n    ggplot,\n    labs,\n    scale_color_manual,\n    theme,\n    theme_void,\n)\n\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\"\n\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\nnp.random.seed(42)\n\n# Phylogenetic tree data for primate evolution (mitochondrial DNA based)\nspecies = [\"Human\", \"Chimpanzee\", \"Gorilla\", \"Orangutan\", \"Gibbon\", \"Macaque\", \"Baboon\", \"Lemur\"]\nn_species = len(species)\n\nleaf_y = {species[i]: i for i in range(n_species)}\n\nbranch_data = {\n    \"root\": 0.0,\n    \"haplorrhini\": 0.15,\n    \"strepsirrhini\": 0.15,\n    \"catarrhini\": 0.25,\n    \"hylobatidae\": 0.25,\n    \"hominoidea\": 0.35,\n    \"cercopithecidae\": 0.35,\n    \"homininae\": 0.45,\n    \"ponginae\": 0.45,\n    \"hominini\": 0.55,\n    \"gorillini\": 0.55,\n}\n\nleaf_x = {\n    \"Human\": 0.65,\n    \"Chimpanzee\": 0.65,\n    \"Gorilla\": 0.60,\n    \"Orangutan\": 0.55,\n    \"Gibbon\": 0.50,\n    \"Macaque\": 0.55,\n    \"Baboon\": 0.55,\n    \"Lemur\": 0.45,\n}\n\ninternal_y = {\n    \"hominini\": (leaf_y[\"Human\"] + leaf_y[\"Chimpanzee\"]) / 2,\n    \"gorillini\": leaf_y[\"Gorilla\"],\n    \"homininae\": (leaf_y[\"Human\"] + leaf_y[\"Chimpanzee\"] + leaf_y[\"Gorilla\"]) / 3,\n    \"ponginae\": leaf_y[\"Orangutan\"],\n    \"hominoidea\": (leaf_y[\"Human\"] + leaf_y[\"Chimpanzee\"] + leaf_y[\"Gorilla\"] + leaf_y[\"Orangutan\"]) / 4,\n    \"hylobatidae\": leaf_y[\"Gibbon\"],\n    \"catarrhini\": (leaf_y[\"Human\"] + leaf_y[\"Chimpanzee\"] + leaf_y[\"Gorilla\"] + leaf_y[\"Orangutan\"] + leaf_y[\"Gibbon\"])\n    / 5,\n    \"cercopithecidae\": (leaf_y[\"Macaque\"] + leaf_y[\"Baboon\"]) / 2,\n    \"haplorrhini\": (\n        leaf_y[\"Human\"]\n        + leaf_y[\"Chimpanzee\"]\n        + leaf_y[\"Gorilla\"]\n        + leaf_y[\"Orangutan\"]\n        + leaf_y[\"Gibbon\"]\n        + leaf_y[\"Macaque\"]\n        + leaf_y[\"Baboon\"]\n    )\n    / 7,\n    \"strepsirrhini\": leaf_y[\"Lemur\"],\n    \"root\": sum(leaf_y.values()) / len(leaf_y),\n}\n\nsegments = [\n    {\n        \"x\": branch_data[\"root\"],\n        \"xend\": branch_data[\"haplorrhini\"],\n        \"y\": internal_y[\"haplorrhini\"],\n        \"yend\": internal_y[\"haplorrhini\"],\n        \"clade\": \"Haplorrhini\",\n    },\n    {\n        \"x\": branch_data[\"root\"],\n        \"xend\": branch_data[\"strepsirrhini\"],\n        \"y\": internal_y[\"strepsirrhini\"],\n        \"yend\": internal_y[\"strepsirrhini\"],\n        \"clade\": \"Strepsirrhini\",\n    },\n    {\n        \"x\": branch_data[\"root\"],\n        \"xend\": branch_data[\"root\"],\n        \"y\": internal_y[\"haplorrhini\"],\n        \"yend\": internal_y[\"strepsirrhini\"],\n        \"clade\": \"Root\",\n    },\n    {\n        \"x\": branch_data[\"strepsirrhini\"],\n        \"xend\": leaf_x[\"Lemur\"],\n        \"y\": leaf_y[\"Lemur\"],\n        \"yend\": leaf_y[\"Lemur\"],\n        \"clade\": \"Strepsirrhini\",\n    },\n    {\n        \"x\": branch_data[\"haplorrhini\"],\n        \"xend\": branch_data[\"catarrhini\"],\n        \"y\": internal_y[\"catarrhini\"],\n        \"yend\": internal_y[\"catarrhini\"],\n        \"clade\": \"Haplorrhini\",\n    },\n    {\n        \"x\": branch_data[\"haplorrhini\"],\n        \"xend\": branch_data[\"catarrhini\"],\n        \"y\": internal_y[\"cercopithecidae\"],\n        \"yend\": internal_y[\"cercopithecidae\"],\n        \"clade\": \"Haplorrhini\",\n    },\n    {\n        \"x\": branch_data[\"haplorrhini\"],\n        \"xend\": branch_data[\"haplorrhini\"],\n        \"y\": internal_y[\"catarrhini\"],\n        \"yend\": internal_y[\"cercopithecidae\"],\n        \"clade\": \"Haplorrhini\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": branch_data[\"hominoidea\"],\n        \"y\": internal_y[\"hominoidea\"],\n        \"yend\": internal_y[\"hominoidea\"],\n        \"clade\": \"Hominoidea\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": leaf_x[\"Gibbon\"],\n        \"y\": leaf_y[\"Gibbon\"],\n        \"yend\": leaf_y[\"Gibbon\"],\n        \"clade\": \"Hylobatidae\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": branch_data[\"catarrhini\"],\n        \"y\": internal_y[\"hominoidea\"],\n        \"yend\": leaf_y[\"Gibbon\"],\n        \"clade\": \"Catarrhini\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": leaf_x[\"Macaque\"],\n        \"y\": leaf_y[\"Macaque\"],\n        \"yend\": leaf_y[\"Macaque\"],\n        \"clade\": \"Cercopithecidae\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": leaf_x[\"Baboon\"],\n        \"y\": leaf_y[\"Baboon\"],\n        \"yend\": leaf_y[\"Baboon\"],\n        \"clade\": \"Cercopithecidae\",\n    },\n    {\n        \"x\": branch_data[\"catarrhini\"],\n        \"xend\": branch_data[\"catarrhini\"],\n        \"y\": leaf_y[\"Macaque\"],\n        \"yend\": leaf_y[\"Baboon\"],\n        \"clade\": \"Cercopithecidae\",\n    },\n    {\n        \"x\": branch_data[\"hominoidea\"],\n        \"xend\": branch_data[\"homininae\"],\n        \"y\": internal_y[\"homininae\"],\n        \"yend\": internal_y[\"homininae\"],\n        \"clade\": \"Homininae\",\n    },\n    {\n        \"x\": branch_data[\"hominoidea\"],\n        \"xend\": leaf_x[\"Orangutan\"],\n        \"y\": leaf_y[\"Orangutan\"],\n        \"yend\": leaf_y[\"Orangutan\"],\n        \"clade\": \"Ponginae\",\n    },\n    {\n        \"x\": branch_data[\"hominoidea\"],\n        \"xend\": branch_data[\"hominoidea\"],\n        \"y\": internal_y[\"homininae\"],\n        \"yend\": leaf_y[\"Orangutan\"],\n        \"clade\": \"Hominoidea\",\n    },\n    {\n        \"x\": branch_data[\"homininae\"],\n        \"xend\": branch_data[\"hominini\"],\n        \"y\": internal_y[\"hominini\"],\n        \"yend\": internal_y[\"hominini\"],\n        \"clade\": \"Hominini\",\n    },\n    {\n        \"x\": branch_data[\"homininae\"],\n        \"xend\": leaf_x[\"Gorilla\"],\n        \"y\": leaf_y[\"Gorilla\"],\n        \"yend\": leaf_y[\"Gorilla\"],\n        \"clade\": \"Gorillini\",\n    },\n    {\n        \"x\": branch_data[\"homininae\"],\n        \"xend\": branch_data[\"homininae\"],\n        \"y\": internal_y[\"hominini\"],\n        \"yend\": leaf_y[\"Gorilla\"],\n        \"clade\": \"Homininae\",\n    },\n    {\n        \"x\": branch_data[\"hominini\"],\n        \"xend\": leaf_x[\"Human\"],\n        \"y\": leaf_y[\"Human\"],\n        \"yend\": leaf_y[\"Human\"],\n        \"clade\": \"Hominini\",\n    },\n    {\n        \"x\": branch_data[\"hominini\"],\n        \"xend\": leaf_x[\"Chimpanzee\"],\n        \"y\": leaf_y[\"Chimpanzee\"],\n        \"yend\": leaf_y[\"Chimpanzee\"],\n        \"clade\": \"Hominini\",\n    },\n    {\n        \"x\": branch_data[\"hominini\"],\n        \"xend\": branch_data[\"hominini\"],\n        \"y\": leaf_y[\"Human\"],\n        \"yend\": leaf_y[\"Chimpanzee\"],\n        \"clade\": \"Hominini\",\n    },\n]\n\ndf_segments = pd.DataFrame(segments)\ndf_leaves = pd.DataFrame({\"x\": [leaf_x[s] for s in species], \"y\": [leaf_y[s] for s in species], \"species\": species})\n\nclade_colors = {\n    \"Root\": \"#999999\",\n    \"Strepsirrhini\": IMPRINT[0],\n    \"Haplorrhini\": IMPRINT[1],\n    \"Catarrhini\": IMPRINT[2],\n    \"Hylobatidae\": IMPRINT[3],\n    \"Hominoidea\": IMPRINT[4],\n    \"Cercopithecidae\": IMPRINT[5],\n    \"Homininae\": IMPRINT[6],\n    \"Ponginae\": IMPRINT[0],\n    \"Gorillini\": IMPRINT[1],\n    \"Hominini\": IMPRINT[2],\n}\n\ndf_segments[\"color\"] = df_segments[\"clade\"].map(clade_colors)\n\nplot = (\n    ggplot()\n    + geom_segment(df_segments, aes(x=\"x\", xend=\"xend\", y=\"y\", yend=\"yend\", color=\"clade\"), size=2.5)\n    + geom_point(df_leaves, aes(x=\"x\", y=\"y\"), size=5, color=IMPRINT[0])\n    + geom_text(df_leaves, aes(x=\"x\", y=\"y\", label=\"species\"), ha=\"left\", nudge_x=0.02, size=14, color=INK)\n    + scale_color_manual(values=clade_colors)\n    + annotate(\"segment\", x=0.0, xend=0.1, y=-0.8, yend=-0.8, size=2.5, color=INK_SOFT)\n    + annotate(\"text\", x=0.05, y=-1.3, label=\"0.1 substitutions/site\", size=16, color=INK_SOFT)\n    + labs(title=\"tree-phylogenetic · plotnine · anyplot.ai\", x=\"Evolutionary Distance (substitutions per site)\")\n    + coord_cartesian(xlim=(-0.05, 0.85), ylim=(-1.5, 7.5))\n    + theme_void()\n    + theme(\n        figure_size=(16, 9),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        plot_title=element_text(size=24, ha=\"center\", color=INK),\n        legend_position=(0.88, 0.75),\n        legend_background=element_rect(fill=PAGE_BG, alpha=0.95),\n        legend_title=element_text(size=14, color=INK),\n        legend_text=element_text(size=12, color=INK_SOFT),\n        legend_key=element_blank(),\n        plot_margin=0.05,\n    )\n    + labs(color=\"Clade\")\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=300, verbose=False)\n"}