{"id":"etetoolkit","name":"etetoolkit","summary":"ETE 4で系統樹やその他の階層系統樹を分析、操作、比較、注釈、可視化します。","body":"# ETE Toolkit 4\n\n## Scope\n\nUse ETE 4 to work with an existing tree:\n\n- Read Newick/Nexus, then inspect, annotate, transform, root, prune, and write\n  Newick trees\n- Compare topologies and calculate phylogenetic distances\n- Find repeated subtree topologies with `TreePattern`\n- Analyze gene trees with `PhyloTree`\n- Query local NCBI or GTDB taxonomy databases\n- Explore large trees interactively with SmartView\n- Render PNG with SmartView or PNG/PDF/SVG with the optional Qt treeview\n\nETE does not replace sequence alignment or phylogenetic inference software. For\nraw sequences, first use MAFFT or another aligner and IQ-TREE 2, FastTree, or\nanother inference tool; then load the resulting tree into ETE.\n\n## Current Target\n\nThis skill targets **ETE 4.4.0**, released September 3, 2025 and verified as the\ncurrent PyPI release on July 23, 2026.\n\nUse `https://etetoolkit.github.io/ete/` for ETE 4 documentation. The\n`etetoolkit.org/docs/latest` pages are legacy ETE 3 documentation despite the\nURL name.\n\nDo not silently translate these examples back to ETE 3:\n\n- Package and import: `ete4`, not `ete3`\n- File input: pass an open file object; use strings for Newick text and do not\n  rely on path-string heuristics retained in ETE 4.4.0\n- Newick selection: `parser=`, not `format=`\n- Node metadata: `props`, `add_prop()`, and `add_props()`\n- Iteration: `leaves()`, `descendants()`, and related methods return iterators\n- Predicates: `node.is_leaf` and `node.is_root` are properties, not methods\n- Node lookup: `tree[\"name\"]`, not `tree & \"name\"`\n\nFor porting older code, load\n[`references/migration-ete3-to-ete4.md`](references/migration-ete3-to-ete4.md).\n\n## Installation\n\nInstall the pinned base package:\n\n```bash\nuv pip install \"ete4==4.4.0\"\n```\n\nAdd only the visualization extra required by the workflow:\n\n```bash\n# SmartView static PNG screenshots\nuv pip install \"ete4[render-sm]==4.4.0\"\n\n# Legacy Qt renderer for PNG, PDF, and SVG\nuv pip install \"ete4[treeview]==4.4.0\"\n```\n\nConfirm the active environment:\n\n```bash\nuv run --with \"ete4==4.4.0\" python -c \"import ete4; print(ete4.__version__)\"\n```\n\nNo credentials are required. NCBI and GTDB workflows download public taxonomy\ndata and can consume substantial disk space; see\n[`references/taxonomy.md`](references/taxonomy.md) before the first update.\n\n## Quick Start\n\n```python\nfrom pathlib import Path\n\nfrom ete4 import Tree\n\n# Use an open file object for files; reserve strings for Newick text.\nwith Path(\"tree.nw\").open(encoding=\"utf-8\") as handle:\n    tree = Tree(handle, parser=1)  # parser 1: internal node names\n\nprint(tree.to_str(props=[\"name\", \"dist\"], compact=True))\nprint(\"Leaves:\", list(tree.leaf_names()))\n\n# Search and annotate.\nfocal = tree[\"species1\"]\nfocal.add_props(host=\"human\", status=\"focal\")\n\n# Keep selected tips while preserving pairwise branch-length distances.\ntree.prune(\n    [\"species1\", \"species2\", \"species3\"],\n    preserve_branch_length=True,\n)\n\n# Root and serialize explicitly.\ntree.set_midpoint_outgroup()\ntree.write(\n    outfile=\"processed.nw\",\n    parser=1,\n    props=[\"host\", \"status\"],\n)\n```\n\nChoose the parser deliberately. A parser mismatch is the most common cause of\n`NewickError`, lost internal labels, or support values being read as names.\nSee [`references/api_reference.md`](references/api_reference.md).\n\n## Core Workflows\n\n### Inspect and transform a tree\n\n```python\nfrom ete4 import Tree\n\ntree = Tree(\"((A:1,B:1)CladeAB:0.4,C:2)Root;\", parser=1)\n\nfor node in tree.traverse(\"preorder\"):\n    label = node.name if node.name is not None else node.id\n    print(label, node.level, node.is_leaf, node.dist)\n\ntree[\"A\"].add_prop(\"group\", \"case\")\ntree[\"B\"].add_prop(\"group\", \"control\")\n\nmrca = tree.common_ancestor(\"A\", \"B\")\nprint(mrca.name)\n\ntree.write(\n    outfile=\"annotated.nhx\",\n    parser=1,\n    props=[\"group\"],\n    format_root_node=True,\n)\n```\n\nNode names need not be unique. `tree[\"A\"]` returns the first match; use\n`list(tree.search_nodes(name=\"A\"))` and validate the count when duplicates are\npossible.\n\n### Compare two topologies\n\n```python\nfrom ete4 import Tree\n\ntree_a = Tree(\"((A,B),(C,D));\")\ntree_b = Tree(\"((A,C),(B,D));\")\n\n(\n    rf,\n    max_rf,\n    common_leaves,\n    edges_a,\n    edges_b,\n    discarded_a,\n    discarded_b,\n) = tree_a.robinson_foulds(tree_b)\n\nnormalized_rf = rf / max_rf if max_rf else 0.0\nprint(rf, max_rf, normalized_rf, sorted(common_leaves))\n```\n\nRF comparison uses shared leaf labels and requires meaningful, preferably\nunique names. Decide explicitly whether rooted or unrooted comparison is\nscientifically appropriate.\n\n### Detect duplication and speciation events\n\n```python\nfrom ete4 import PhyloTree\n\ngene_tree = PhyloTree(\n    \"((Hsa|g1,Ptr|g1),(Hsa|g2,Mmu|g1));\",\n    sp_naming_function=lambda name: name.split(\"|\", 1)[0],\n)\n\nfor event in gene_tree.get_descendant_evol_events(sos_thr=0.0):\n    relationship = \"speciation/orthology\" if event.etype == \"S\" else \"duplication/paralogy\"\n    print(relationship, sorted(event.in_seqs), sorted(event.out_seqs))\n```\n\nSpecies-overlap calls are inferences from the supplied topology and naming\nfunction, not independent evidence of orthology. Pass the naming function\nexplicitly, and use a rooted, fully bifurcating gene tree. For strict\nreconciliation, use a curated species tree and\n`gene_tree.reconcile(species_tree)`.\n\n### Query taxonomy\n\n```python\nfrom ete4 import NCBITaxa\n\nncbi = NCBITaxa()\nnames = [\"Homo sapiens\", \"Pan troglodytes\", \"Mus musculus\"]\nname_to_taxids = ncbi.get_name_translator(names)\n\nmissing = [name for name in names if name not in name_to_taxids]\nif missing:\n    raise ValueError(f\"Names not resolved by NCBI taxonomy: {missing}\")\n\ntaxids = [name_to_taxids[name][0] for name in names]\ntaxonomy_tree = ncbi.get_topology(taxids)\nprint(taxonomy_tree.to_str(props=[\"sci_name\", \"rank\"]))\n```\n\nETE 4 also provides `GTDBTaxa` for genome-centric bacterial and archaeal\ntaxonomy. Do not mix NCBI numeric TaxIDs and GTDB string identifiers.\n\n### Visualize\n\nInteractive SmartView:\n\n```python\nfrom ete4 import Tree\n\ntree = Tree(\"((A:1,B:1)90:0.2,C:1);\", parser=\"support\")\ntree.explore()\n```\n\nStatic SmartView screenshot:\n\n```python\ntree.render_sm(\"tree.png\", w=1200, h=800)\n```\n\n`render_sm()` produces PNG screenshot data; use the Qt treeview renderer when\nthe deliverable must be vector PDF or SVG. Load\n[`references/visualization.md`](references/visualization.md) for layouts,\nfaces, remote exploration, and renderer selection.\n\n## Bundled Scripts\n\nRun from this skill directory. The commands below use a pinned, isolated ETE 4\nruntime through `uv run --with`.\n\n### Tree operations\n\n```bash\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  stats tree.nw --parser 1\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  ascii tree.nw --parser 1 --props name,dist\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  convert tree.nw output.nw \\\n  --input-parser 1 --output-parser 1\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  reroot tree.nw rooted.nw \\\n  --parser 1 --midpoint\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  prune tree.nw pruned.nw \\\n  --parser 1 --keep species1 species2 species3\nuv run --with \"ete4==4.4.0\" python scripts/tree_operations.py \\\n  compare tree_a.nw tree_b.nw\n```\n\nUse `--keep-file taxa.txt` instead of `--keep ...` for one taxon per line.\nThe script refuses ambiguous or missing requested names rather than silently\nproducing a partial tree.\n\n### Visualization\n\n```bash\n# Interactive SmartView\nuv run --with \"ete4==4.4.0\" python scripts/quick_visualize.py \\\n  tree.nw --parser 1\n\n# SmartView PNG (requires ete4[render-sm])\nuv run --with \"ete4[render-sm]==4.4.0\" python scripts/quick_visualize.py \\\n  tree.nw tree.png \\\n  --parser support --mode circular --show-support --color-by-support\n\n# Vector output via Qt treeview (requires ete4[treeview])\nuv run --with \"ete4[treeview]==4.4.0\" python scripts/quick_visualize.py \\\n  tree.nw tree.svg \\\n  --parser 1 --engine treeview --title \"Species phylogeny\"\n```\n\n## Quality and Interpretation Checks\n\nBefore reporting a result:\n\n1. Confirm the parser preserves the intended internal names, support, and\n   branch lengths.\n2. Check for empty and duplicate leaf names before name-based lookup or RF\n   comparison.\n3. State whether the tree is treated as rooted or unrooted.\n4. Preserve branch lengths when pruning only if retained pairwise distances\n   should remain unchanged.\n5. Treat arbitrary polytomy resolution as a display/algorithmic convenience,\n   not evolutionary evidence.\n6. Record ETE version, parser, rooting method, pruning set, and taxonomy\n   database snapshot in reproducible analyses.\n7. Prefer iterators for large trees and `get_cached_content()` for repeated\n   descendant-content queries.\n\n## Reference Map\n\nLoad only the reference needed for the task:\n\n- [`references/api_reference.md`](references/api_reference.md) — ETE 4 core\n  classes, parsers, properties, traversal, I/O, topology, and comparison\n- [`references/workflows.md`](references/workflows.md) — complete analysis\n  patterns, validation, reconciliation, batching, and large-tree work\n- [`references/visualization.md`](references/visualization.md) — SmartView,\n  layouts/faces, PNG screenshots, and Qt vector rendering\n- [`references/taxonomy.md`](references/taxonomy.md) — NCBI and GTDB setup,\n  translation, topology, annotation, and reproducibility\n- [`references/migration-ete3-to-ete4.md`](references/migration-ete3-to-ete4.md)\n  — breaking API changes and porting checklist\n\n## Authoritative Upstream Sources\n\n- Documentation: https://etetoolkit.github.io/ete/\n- ETE 3 to ETE 4 migration: https://etetoolkit.github.io/ete/3to4.html\n- Releases: https://github.com/etetoolkit/ete/releases\n- PyPI: https://pypi.org/project/ete4/\n- Source: https://github.com/etetoolkit/ete\n- Visualization gallery: https://github.com/etetoolkit/ete-gallery","author":"@K-Dense-AI","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/K-Dense-AI/scientific-agent-skills/tree/main/skills/etetoolkit","license":"MIT","category":"writing","lang":"en","tokens":2630,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/api_reference.md","size":14323,"sha256":"d269745b05668ba3f99758f0dfe88f9cb04fd5ed4e5bac87c62db8e8b84df1b6"},{"path":"references/migration-ete3-to-ete4.md","size":11766,"sha256":"54a5336026594827cdfb600accddd8a250589fc0be0ace7ce986436040c704e6"},{"path":"references/taxonomy.md","size":9003,"sha256":"e75a018938b928d995da821a0500741d390295e778d11fb5ada883851d070b2e"},{"path":"references/visualization.md","size":11946,"sha256":"ded811491fb1dd274671cc9055f7c5c4864078d1ab468b5e7547078c64632a7e"},{"path":"references/workflows.md","size":15330,"sha256":"bd91cd86a28f4551a76d5624b079c773c192b107ecc69d1c06c18f1f65f7c12f"},{"path":"scripts/quick_visualize.py","size":15016,"sha256":"2142ffd468d988d6f4ea20e018b3a05139b9002a30b630359dea3c0b7bc9ea99"},{"path":"scripts/tree_operations.py","size":15763,"sha256":"36fc5cfc1d7d6d3c672444594634ea454054c71785942d6b650a857a1e805227"}],"requires":{"mcp":[],"tools":["Read Write Edit Bash Python"]},"safety":{"flags":[{"code":"net.endpoints","kind":"exfiltration","excerpt":"etetoolkit.github.io, gtdb.ecogenomic.org, www.ncbi.nlm.nih.gov","message":"bundled scripts reach 3 external host(s)","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":["etetoolkit.github.io","gtdb.ecogenomic.org","www.ncbi.nlm.nih.gov"]}}