FigTreeKit
Programmatic styling of phylogenetic trees for FigTree visualization
Overview
FigTreeKit is a Python library for programmatic publication-ready styling of phylogenetic trees. It addresses the problem of reproducible, scriptable tree visualization in evolutionary biology and comparative genomics — turning raw Newick/Nexus trees into annotated, publication-quality figures compatible with FigTree.
Typical use cases include:
- Styling phylogenomic trees with taxonomic group highlights
- Batch-processing hundreds of gene trees with consistent formatting
- Validating and collapsing clades by taxonomic group name
- Generating publication-ready figures from BEAST/RAxML/IQ-TREE output
Key Features
- FigTree-Compatible Output: Generates Nexus files with
[&!hilight],[&!color],[&!font]annotations - Pythonic API: Method chaining for intuitive tree styling
- Taxonomy-Aware Analysis: Automatic taxonomy extraction from labels (embedded
_d_/_p_/_g_/_s_/_ss_format and tabled__/p__format) - Monophyly Detection: Check if taxa form monophyletic groups, with special identifiers (LUCA/LACA/LBCA)
- Clade Collapse: Collapse clades by taxonomic group name with monophyly validation
- Multi-Tree Handling: Detect and process multiple trees with
split/first/last/randommodes - Deep Input Validation: Structural checks, negative branch detection, duplicate tip names, malicious character scanning
- Real-Time Logging: ISO 8601 timestamps, stdout flush, optional log file output
- Self-Test Mode:
--self-testverifies dependencies, parsing, taxonomy, and monophyly logic - Batch Processing: Process multiple tree files via CLI
- Image Rendering: Export to PNG/PDF/SVG without opening FigTree GUI (requires FigTree JAR); for command-line rendering of very large trees, TreeViewer is also worth considering.
Comparison with Existing Tools
| Capability | FigTreeKit | FigTree GUI | DendroPy | ETE3 | TreeViewer |
|---|---|---|---|---|---|
| Programmatic / scriptable styling | ✅ | ❌ | ⚠️ limited | ⚠️ limited | ✅ (CLI) |
| Python API | ✅ | ❌ | ✅ | ✅ | ❌ |
Inject FigTree annotations (!hilight/!color/!font) |
✅ | N/A | ❌ | ❌ | ❌ |
| Taxonomy-aware collapse / monophyly check | ✅ | manual | ⚠️ partial | ⚠️ partial | ❌ |
| Deep input validation (brackets, negative branches, malicious chars) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Batch CLI processing | ✅ | ❌ | ❌ | ✅ | ✅ |
| Image rendering (PNG/PDF/SVG) | ✅ | ✅ | ❌ | ✅ | ✅ |
See docs/comparison_EN.md for the full comparison matrix and reproduction instructions.
Installation
From PyPI (Recommended)
pip install figtreekit
From Source
git clone https://github.com/ZengZichao/FigTreeKit.git
cd FigTreeKit
pip install -r requirements.txt
pip install -e .
Dependencies
- Required: Python 3.11, Biopython (>=1.80, <2.0)
- Optional: psutil (for memory logging), Java 8+ (for rendering)
- Tested on: macOS Tahoe 26.5.2 (Apple Silicon)
Self-Test
After installation, verify everything works:
figtreekit --self-test
This runs 11 built-in checks (dependencies, parsing, taxonomy, monophyly) and requires no external files. See the Quick Start section for expected output.
Quick Start
1. Verify Installation
figtreekit --self-test
[PASS] Dependency: biopython
[PASS] Dependency: python
[PASS] Parse: Newick example
[PASS] Taxonomy: embedded format extraction
[PASS] Taxonomy: table format extraction
[PASS] Monophyly: Cyanobacteriales (monophyletic)
[PASS] Special ID: LUCA resolves all taxa
[PASS] Special ID: LACA resolves Archaea only
[PASS] Export: Newick → Nexus round-trip
[PASS] Validation: FASTA example
[PASS] Security: control char detection
All 11 checks passed.
2. Basic Usage (Python API)
from figtreekit import FigTreeStyler, LayoutType, FontStyle
styler = FigTreeStyler().load_content("((A:0.1,B:0.2):0.3,(C:0.4,D:0.5):0.6);")
styler.set_layout(LayoutType.RECTILINEAR)
styler.set_appearance(background_color="#FAFAFA", branch_line_width=2.0)
styler.highlight_clade(["A", "B"], color="#FF0000")
styler.set_tip_labels(is_shown=True, font_size=12)
styler.export("output.nex")
3. Command Line Usage
figtreekit input.tre -o output.nex --layout polar --tip-labels-show
figtreekit input.tre --validate
figtreekit input.tre -o output.nex --clade Cyanobacteriota
4. Export and Render to Image
figtreekit --setup-figtree # one-time setup
figtreekit input.tre -o output.nex --render tree.png
figtreekit input.tre -o output.nex --render tree.pdf --render-width 1600
Taxonomy Analysis
Automatic Taxonomy Extraction
FigTreeKit can extract taxonomy from two formats:
Format A (Embedded) — taxonomy encoded in the label:
GB_GCA_000252485.1_d_Bacteria_p_Cyanobacteriota_c_Cyanobacteriia_o_Cyanobacteriales_f_Prochloraceae_g_Prochloron
Format B (Table) — semicolon-delimited taxonomy strings:
d__Archaea;p__Thermoproteota;c__Korarchaeia;o__Korarchaeales;f__Korarchaeaceae;g__WALU01;s__
Python API
from figtreekit import FigTreeStyler
styler = FigTreeStyler("tree.nwk")
# Check monophyly by group name (auto-detects format)
result = styler.check_monophyly_by_group("Cyanobacteriales")
print(result["is_monophyletic"]) # True/False
print(result["resolved_taxa"]) # list of taxon names
# Collapse a monophyletic clade
styler.collapse_by_group("Cyanobacteriales")
styler.export("collapsed.nex")
CLI Usage
# Collapse by taxon group name
figtreekit tree.nwk -o collapsed.nex --clade Cyanobacteriota
# Strict mode (abort if not monophyletic)
figtreekit tree.nwk -o collapsed.nex --clade Cyanobacteriota --strict
# Multiple clades
figtreekit tree.nwk -o out.nex --clade Cyanobacteriota --clade Proteobacteria
# Custom taxonomy parsing
figtreekit tree.nwk -o out.nex --taxonomy-delimiter-mode greedy
figtreekit tree.nwk -o out.nex --taxonomy-table-sep "|"
figtreekit tree.nwk -o out.nex --taxonomy-levels "k:kingdom,ss:subspecies"
Special Identifiers
| Identifier | Description |
|---|---|
LUCA |
Last Universal Common Ancestor (all Bacteria + Archaea) |
LACA |
Last Archaeal Common Ancestor |
LBCA |
Last Bacterial Common Ancestor |
root |
Root of the tree (all terminal taxa) |
result = styler.check_monophyly_by_group("LUCA")
External Taxonomy Table
When labels don't contain taxonomy, provide a mapping file (TSV/CSV, two-column format). See Input Format Details for the full specification.
figtreekit tree.nwk -o out.nex --clade Cyanobacteriales
Multi-Tree Handling
When a file contains multiple trees (e.g., Nexus with multiple tree statements):
# Default: print summary and abort (exit code 2)
figtreekit multi.nex -o out.nex
# Process all trees with numeric suffixes
figtreekit multi.nex -o out.nex --multi-tree split
# Process only the first/last tree
figtreekit multi.nex -o out.nex --multi-tree first
figtreekit multi.nex -o out.nex --multi-tree last
# Random selection
figtreekit multi.nex -o out.nex --multi-tree random
# Same as split (process all trees)
figtreekit multi.nex -o out.nex --multi-tree all
Sequence Validation
FigTreeKit can validate FASTA/FASTQ files:
# Validate FASTA
figtreekit sequences.fasta --validate
# Validate with expected molecule type
figtreekit sequences.fasta --validate --mol-type DNA
# Skip alignment length check
figtreekit aligned.fasta --validate --skip-length-check
# Cross-validate tree tips against sequence IDs
figtreekit tree.nwk -o out.nex --sequences sequences.fasta
# Cross-validate during validation mode
figtreekit tree.nwk --validate --sequences sequences.fasta
Note: When using
--validatewith a sequence file (FASTA/FASTQ), the CLI returns exit code 0 (success) if deep validation passes, even though the file is not a tree format. This allows independent sequence validation in scripts.
Checks include:
- Duplicate sequence IDs (ERROR)
- Alphabet validation (DNA/RNA/protein) with invalid character reporting
- Alignment length consistency (WARNING)
See Input Format Details for FASTA/FASTQ format specifications.
Deep Input Validation
FigTreeKit performs comprehensive validation on all input files:
Tree Files
| Check | Level |
|---|---|
| Bracket balance (parentheses, brackets) | ERROR with position |
| Negative branch lengths | CRITICAL (abort) |
| Empty node names | ERROR |
| Duplicate tip names | ERROR |
| Self-loop detection | ERROR |
| Control characters / Unicode bidi overrides | CRITICAL (abort) |
Sequence Files
| Check | Level |
|---|---|
| Duplicate sequence IDs | ERROR (abort) |
| Invalid characters for alphabet | ERROR with line number |
| Alignment length inconsistency | WARNING |
Adversarial Input Protection
- Control characters (
\x00-\x1f) in node names → CRITICAL - Unicode bidi overrides (
\u202E) → CRITICAL - Circular dependencies in taxonomy tables → ERROR
- Empty files (0 bytes) → CRITICAL
Output Format
Nexus File Structure
FigTreeKit exports FigTree-compatible Nexus files with three blocks:
#NEXUS
begin taxa;
dimensions ntax=3;
taxlabels A B C ;
end;
begin trees;
tree TREE1 = ((A:0.1,B:0.2):0.3,C:0.4);
end;
begin figtree;
set appearance.backgroundColour=#ffffff;
set layout.layoutType=POLAR;
set tipLabels.isShown=true;
end;
Annotation Format
FigTreeKit injects annotations into the Newick tree string:
| Annotation | Format | Description |
|---|---|---|
!hilight |
[&!hilight={tipCount,height,color}] |
Background highlight for a clade. tipCount = number of tips, height = node height from root, color = hex RGB. |
!color |
[&!color=#RRGGBB] |
Branch color applied to the MRCA node. |
!font |
[&!font=Name-STYLE-size] |
Font annotation (Java Font.decode() format). STYLE: PLAIN, BOLD, ITALIC, BOLDITALIC. |
!stroke |
[&!stroke=N] |
Branch stroke width (forward compatibility; FigTree 1.4.4 ignores this). |
Example — highlighting clade (A,B):
((A:0.1,B:0.2)[&!hilight={2,0.3,#ff0000}]:0.3,C:0.4);
Output File Naming
| Mode | Output Pattern |
|---|---|
| Single tree | <output>.nex (user-specified) |
| Batch | <input_stem>.nex in output directory |
| Multi-tree split | <output>_tree1.nex, <output>_tree2.nex, ... |
| Collapsed clade | Same as input (clade replaced in-place) |
Input Format Details
Format Standards
FigTreeKit follows these standards:
- Newick: Newick tree format — branch lengths are in substitution units (evolutionary distances from parent node)
- Nexus: Nexus file format — compliant with the Maddison et al. (1997) specification
- FASTA: FASTA format — standard bioinformatics sequence format
- FASTQ: FASTQ format — Illumina/Sanger quality encoding
Tree File Formats
Newick (.nwk, .newick, .tree, .tre, .treefile, .nh, .nhy, .nhx):
((A:0.1,B:0.2):0.3,C:0.4);
- Branch lengths are optional (default: no branch length displayed)
- Quoted names supported:
('Species A':0.1,'Species B':0.2); - Bracket comments preserved:
(A:0.1[&posterior=0.95],B:0.2);
Nexus (.nex, .nexus, .nx):
#NEXUS
begin taxa;
dimensions ntax=3;
taxlabels A B C ;
end;
begin trees;
tree TREE1 = ((A:0.1,B:0.2):0.3,C:0.4);
end;
- Translate blocks supported (BEAST format)
- Multiple trees preserved (all written to output)
- Existing
figtreeblock parsed and merged - BEAST output: Translate blocks and bracket annotations (e.g.
[&posterior=0.95]) are preserved
Taxonomy Mapping Files
Two-column format (auto-detected TSV/CSV):
With header:
name taxonomy
GB_GCA_000252485.1 d__Bacteria;p__Cyanobacteriota;c__Cyanobacteriia;o__Cyanobacteriales;f__Prochloraceae;g__Prochloron;s__
RS_GCF_000013425.1 d__Archaea;p__Euryarchaeota;c__Methanomicrobia;o__Methanosarcinales;f__Methanosarcinaceae;g__Methanosarcina;s__
Without header:
GB_GCA_000252485.1 d__Bacteria;p__Cyanobacteriota;c__Cyanobacteriia;o__Cyanobacteriales;f__Prochloraceae;g__Prochloron;s__
RS_GCF_000013425.1 d__Archaea;p__Euryarchaeota;c__Methanomicrobia;o__Methanosarcinales;f__Methanosarcinaceae;g__Methanosarcina;s__
- Delimiter: tab (
.tsv) or comma (.csv), auto-detected from extension - Force delimiter:
--table-sep "," - Missing ranks (e.g.
s__with no value) → stored as empty string - Malformed rows:
--ignore-malformedto skip instead of aborting
Supported Input Formats Summary
| Type | Format | Extensions |
|---|---|---|
| Tree | Newick | .nwk, .newick, .tree, .tre, .treefile, .nh, .nhy, .nhx |
| Tree | Nexus | .nex, .nexus, .nx |
| Tree | PhyloXML † | .xml, .phyloxml |
| Sequence | FASTA | .fasta, .fa, .fas, .fna, .faa, .ffn, .frn |
| Sequence | FASTQ | .fastq, .fq |
| Sequence | GenBank | .gb, .gbk, .genbank |
| Sequence | EMBL | .embl |
| Sequence | Stockholm | .stockholm, .sto |
| Sequence | Phylip | .phylip, .phy |
| Sequence | Clustal | .clustal, .aln |
| Taxonomy | TSV/CSV | .tsv, .csv |
† Format support scope: Tree styling and rendering (
FigTreeStylerand Nexus export) support Newick and Nexus only. PhyloXML is recognized by the input validator (--validate) but is not loaded, styled, or rendered by the tree styler. Sequence formats (FASTA, FASTQ, GenBank, EMBL, Stockholm, Phylip, Clustal) are supported for input validation and tree↔sequence cross-validation (--validate/--sequences), not for tree styling.
Processing Flow
Input File
│
▼
┌─────────────────┐
│ Format Detect │ (Newick / Nexus / FASTA / FASTQ)
└────────┬────────┘
▼
┌─────────────────┐
│ Deep Validation │ (brackets, branch lengths, duplicates, malicious chars)
└────────┬────────┘
▼
┌─────────────────┐
│ Multi-Tree Check │ (ask / split / first / last / random / all)
└────────┬────────┘
▼
┌─────────────────┐
│ Taxonomy Parse │ (embedded _d_/_p_ or table d__/p__)
└────────┬────────┘
▼
┌─────────────────┐
│ Style & Collapse │ (clade highlights, colors, monophyly check)
└────────┬────────┘
▼
┌─────────────────┐
│ Export / Render │ (Nexus output, optional PNG/PDF/SVG)
└─────────────────┘
Common Issues and Boundary Cases
- Quoted taxon names: Names with spaces or special characters must be single-quoted in Newick:
('Species A':0.1,'Species B':0.2); - Missing branch lengths: Trees without branch lengths are valid; FigTree will display equal-length branches
- Polytomies: Unresolved nodes (more than 2 children) are fully supported
- Translate blocks: BEAST-style numeric taxon IDs are automatically resolved
- Encoding: Files with BOM (UTF-8-sig) or legacy encodings (latin-1) are handled transparently
- Large trees: Trees with >10,000 tips trigger a resource warning; use
--low-memorymode - Empty taxa names: Detected and rejected as ERROR (cannot map taxonomy)
- Duplicate tip names: Detected and rejected as ERROR (would cause taxonomy mapping conflicts)
Real-Time Logging
All operations produce real-time log output with ISO 8601 timestamps:
2026-06-13T15:30:56.135 | [ INFO] | >>> Input file validation ...
2026-06-13T15:30:56.135 | [ INFO] | <<< Input file validation (0 ms)
2026-06-13T15:30:56.135 | [ INFO] | >>> Parsing tree file ...
2026-06-13T15:30:56.192 | [ INFO] | tree.nwk: parsed successfully, 3 taxa detected
2026-06-13T15:30:56.192 | [ INFO] | <<< Parsing tree file (57 ms)
2026-06-13T15:30:56.192 | [ INFO] | tree.nwk: DONE (total 0.06 s)
Log Levels
| Flag | Level | Description |
|---|---|---|
-q |
ERROR | Suppress all non-error output |
| (default) | WARNING | Warnings and errors only |
-v |
INFO | Normal operation flow |
-vv |
DEBUG | Detailed debugging info |
Log File
# Write logs to file (all levels, UTF-8)
figtreekit tree.nwk -o out.nex --log-file figtreekit.log
Command Line Interface
Basic Commands
figtreekit input.tre -o output.nex [OPTIONS]
figtreekit input.tre --validate
figtreekit --version
figtreekit --self-test
figtreekit --help
Common Options
For the complete and up-to-date list, run
figtreekit --help.
positional arguments:
input Input tree file or directory for batch processing
options:
-o, --output OUTPUT Output Nexus file (or directory for batch)
--validate Check compatibility without exporting
-v, --verbose Increase verbosity (-v INFO, -vv DEBUG) (default: WARNING)
-q, --quiet Suppress non-error output
--version Show version, git commit hash, date and dependencies
--self-test Run self-diagnostic checks
--config FILE JSON config file
--log-file FILE Write logs to file (UTF-8, all levels)
--force Overwrite existing output files
--no-clobber Skip if output exists
--strip-annotations Strip bracket comments (NHX/bootstrap/posterior) to reduce file size
Tree:
--clade NAME Collapse clade by taxonomic group name
--strict Abort on non-monophyletic clades (default: warn and skip)
--multi-tree MODE Multi-tree handling (default: ask)
Choices: ask/split/first/last/random/all
--rooted Set tree as rooted
--unrooted Set tree as unrooted (takes precedence over --rooted)
Taxonomy:
--taxonomy-levels SPEC Extend rank prefixes (e.g. "k:kingdom,ss:subspecies")
--taxonomy-delimiter-mode MODE reverse/greedy/segment (default: reverse)
--taxonomy-table-sep CHAR Separator for taxonomy strings (default: ";")
--taxonomy-source-priority P embedded/table (default: table)
--taxonomy-mapping-file FILE Path to taxonomy mapping file (TSV/CSV)
--table-sep CHAR Force column delimiter for mapping file
--ignore-malformed Skip malformed taxonomy rows
Sequence:
--mol-type TYPE DNA/RNA/protein (default: auto-detect)
--sequences FILE Sequence file for cross-validation against tree tips
--no-cross-check Skip tree-sequence label cross-validation
--skip-length-check Skip alignment length check
--low-memory Reduce memory usage for large files (streaming)
Rendering:
--render FILE Render tree to image (PNG/PDF/SVG/JPEG)
--render-format FORMAT Force render format (PNG/PDF/SVG/JPEG)
--render-width PX Image width (default: 1200)
--render-height PX Image height (default: 800)
--figtree-jar PATH Path to figtree.jar
--setup-figtree Download/compile FigTree JAR
--check-figtree Check if FigTree JAR is available
Config File
{
"layout.layoutType": "POLAR",
"appearance.backgroundColour": "#FAFAFA",
"tipLabels.isShown": true,
"tipLabels.fontName": "Arial",
"tipLabels.fontSize": 10
}
figtreekit input.tre -o output.nex --config style.json
Python API Reference
Tree Styling
from figtreekit import FigTreeStyler, LayoutType, FontStyle, TransformType
styler = FigTreeStyler("tree.nwk")
# Layout
styler.set_layout(LayoutType.POLAR)
styler.set_polar_layout(angular_range=270, root_angle=45)
# Appearance
styler.set_appearance(background_color="#FFFFFF", branch_line_width=2.0)
# Clade annotations
styler.highlight_clade(["A", "B"], color="#FF0000")
styler.set_clade_color(["A", "B"], color="#2196F3")
styler.set_clade_color_all(["A", "B"], color="#2196F3") # color all branches in subtree
# Note: set_clade_color + highlight_clade on the same taxa will drop the
# MRCA-level color to avoid FigTree ClassCastException.
# Use set_clade_color_all() as the recommended alternative.
styler.set_clade_font(["A"], font_name="Arial", font_style=FontStyle.BOLD, font_size=14)
# Labels
styler.set_tip_labels(is_shown=True, font_size=12)
styler.set_node_labels(is_shown=True, display_attribute="height")
styler.set_branch_labels(is_shown=True, display_attribute="length")
# Scale
styler.set_scale_bar(is_shown=True)
styler.set_scale_axis(is_shown=True)
styler.set_scale(root_age=1.0)
# Layout-specific settings
styler.set_radial_layout(spread=1.0)
styler.set_rectilinear_layout(curvature=0, root_length=0)
# Trees
styler.set_trees(rooting=True, transform=TransformType.PHYLOGRAM)
# Legend / node decorations
styler.set_legend(is_shown=True, position="bottom")
styler.set_node_bars(is_shown=True)
styler.set_node_shapes(is_shown=True)
# Apply from dict and reset
styler.apply_dict({"layout.layoutType": "POLAR"})
# Full reset: clears settings, annotations, taxonomy config, AND tree content
# Must reload tree via load_file / load_content before further operations
styler.reset()
# Or reset only styling, keeping the loaded tree
styler.reset(keep_tree=True)
# Export
styler.export("output.nex")
styler.render("tree.png")
styler.render("tree.pdf", format="PDF", width=1600, height=1000)
Monophyly & Collapse
# Check monophyly
result = styler.check_monophyly(["A", "B", "C"])
result = styler.check_monophyly_by_group("Cyanobacteriales")
result = styler.check_monophyly_by_group("LUCA")
# Collapse clades
styler.collapse_clade(["A", "B"], label="Clade1")
styler.collapse_by_group("Cyanobacteriales")
styler.collapse_by_group("Cyanobacteriales", label="Cyano")
# Nested collapse: collapse inner and outer clades simultaneously
# (automatically sorted by size, processed inner-first)
styler.collapse_clade(["A", "B"], label="Inner")
styler.collapse_clade(["A", "B", "C"], label="Outer") # Both labels appear in output
# Convenience: check + style in one call
styler.style_monophyletic_clade(
["A", "B", "C"],
color="#E91E63",
highlight_color="#FFCDD2",
font_name="Arial",
font_style=FontStyle.BOLD,
font_size=12,
)
# Clear pending operations
styler.clear_annotations()
styler.clear_clade_hilights()
styler.clear_collapses()
# Strip all bracket comments (NHX, bootstrap, posterior, etc.) to reduce output size
styler.strip_annotations()
# Get detailed clade information (MRCA, descendant tips, monophyly, etc.)
info = styler.get_clade_info(["A", "B", "C"])
print(info["is_monophyletic"], info["mrca_terminal_count"])
Loading & Access
# Load from string or file (auto-detect)
styler = FigTreeStyler().load_tree("((A:0.1,B:0.2):0.3,C:0.4);")
styler = FigTreeStyler().load_tree("tree.nwk") # auto-loads from file if exists
# Access annotations and collapses
annotations = styler.get_annotations() # get current annotations list
collapses = styler.get_collapses() # get current collapses list
# Set font with defaults
styler.set_clade_font(["A", "B"]) # uses defaults: Arial, PLAIN, 12
styler.set_clade_font(["A", "B"], font_name="Helvetica", font_style=FontStyle.BOLD, font_size=14)
Validation
from figtreekit import (
validate_input_file,
deep_validate_newick,
deep_validate_fasta,
deep_validate_fastq,
TreeValidator,
)
# File validation
result = validate_input_file("tree.nwk")
if not result["valid"]:
for err in result["errors"]:
print(err)
# Deep Newick validation
dv = deep_validate_newick(content, label="tree.nwk")
for err in dv["errors"]:
print(err)
# FASTA / FASTQ validation
dv = deep_validate_fasta("seqs.fasta", expected_alphabet="DNA")
dv = deep_validate_fastq("reads.fastq", expected_alphabet="DNA")
# Styler-level validation
issues = styler.validate()
# Biological plausibility check (degenerate trees, all-zero branches, large tree warnings)
warnings = TreeValidator.validate_biological_plausibility(newick)
Taxonomy
from figtreekit import (
parse_taxonomy_auto,
detect_taxonomy_format,
TaxonomyMapper,
MonophylyAnalyzer,
get_rank_prefixes,
extend_rank_prefixes,
)
# Apply settings from CLI arguments
from figtreekit import apply_cli_args
# apply_cli_args(styler, args) # args from argparse.Namespace
# Auto-detect and parse
tax = parse_taxonomy_auto("GB_GCA_000252485.1_d_Bacteria_p_Cyanobacteriota_c_Cyanobacteriia_o_Cyanobacteriales_f_Prochloraceae_g_Prochloron")
# {"domain": "Bacteria", "phylum": "Cyanobacteriota", ...}
tax = parse_taxonomy_auto("d__Archaea;p__Euryarchaeota;s__")
# {"domain": "Archaea", "phylum": "Euryarchaeota", "species": ""}
# Styler taxonomy configuration
styler.configure_taxonomy(
delimiter_mode="reverse", # reverse / greedy / segment
table_sep=";",
source_priority="table", # table / embedded
mapping_file="taxonomy.tsv",
ignore_malformed=False,
)
# Direct mapper usage
mapper = TaxonomyMapper()
mapper.load_mapping("taxonomy.tsv")
groups = mapper.identify_groups(rank="genus")
# Taxonomy analysis with automatic monophyly detection (requires pattern or mapping_file)
result = styler.analyze_taxonomy(mapping_file="taxonomy.tsv", rank="phylum")
# Convenience method: equivalent to analyze_taxonomy(mapping_file=...)
result = styler.analyze_taxonomy_from_mapping("taxonomy.tsv", rank="phylum")
# Parse taxonomy from labels (built-in patterns or custom regex)
taxonomy = styler.parse_label_taxonomy("genus_species")
# Check taxonomy data completeness
completeness = styler.check_taxonomy_completeness(mapping_file="taxonomy.tsv")
Library Mode API
from figtreekit import (
parse_taxonomy, # Standardized taxonomy parsing
is_monophyletic, # Monophyly check
load_tree, # Tree loading
cross_validate, # Cross-validation
# Standardized exception hierarchy
PhyloFormatError, # File format error (inherits from ParseError)
TaxonomyConflictError, # Taxonomy conflict (inherits from ValidationError)
MonophylyError, # Monophyly analysis error (inherits from ValidationError)
)
# Parse taxonomy label (standardized signature)
tax = parse_taxonomy("d__Bacteria;p__Cyanobacteriota", mode="reverse")
# -> {"domain": "Bacteria", "phylum": "Cyanobacteriota", ...}
# Check monophyly (standardized signature)
mono = is_monophyletic("tree.nwk", "Cyanobacteriota", rooted=True)
# -> True / False
# Load tree file (standardized signature)
styler = load_tree("tree.nwk", validate=True)
# Cross-validate tree and sequences (standardized signature)
report = cross_validate("tree.nwk", "sequences.fasta", strict=True)
# -> {"valid": True, "matched": 50, "tree_only": [], "seq_only": [], "errors": []}
Error Codes
| Code | Meaning | Description |
|---|---|---|
| 0 | Success | All operations completed successfully |
| 1 | Runtime error | Dependency issues, self-test failures |
| 2 | Usage error | Invalid command-line arguments, missing input |
| 3 | Data error | Invalid input data (malformed tree, bad sequences) |
| 130 | Interrupted | User pressed Ctrl+C (SIGINT) or SIGTERM received |
Exception Hierarchy
| Exception | Base Class | Purpose |
|---|---|---|
FigTreeKitError |
Exception |
Base class for all FigTreeKit exceptions |
ParseError |
FigTreeKitError |
Tree/sequence file parsing errors |
ValidationError |
FigTreeKitError |
Input validation failure |
ExportError |
FigTreeKitError |
Export/render errors |
PhyloFormatError |
ParseError |
File format error (library mode API alias) |
TaxonomyConflictError |
ValidationError |
Taxonomy conflict (library mode API alias) |
MonophylyError |
ValidationError |
Monophyly analysis error (library mode API alias) |
CompatibilityWarning |
UserWarning |
Compatibility warning |
Operational Notes
Output Control
figtreekit tree.nwk -o existing.nex --force # overwrite
figtreekit tree.nwk -o existing.nex --no-clobber # skip if exists
figtreekit tree.nwk -o new/dir/output.nex # auto-create dirs
User Interrupt
Press Ctrl+C to gracefully terminate — progress is displayed, temporary files are cleaned up, exit code 130.
Portability Design
- Encoding: UTF-8 with BOM and latin-1 fallback handled transparently
- Newlines: Unix
\non all platforms - Paths:
pathlib.Paththroughout (platform-independent path handling) - Temporary files: Auto-cleaned on exit, permissions set to 0o600 (HPC-safe), including Ctrl+C
Note: Although the codebase uses platform-independent patterns, FigTreeKit has only been tested on macOS Tahoe 26.5.2. Compatibility with Windows or Linux is not guaranteed.
Large-Scale Data
For trees with more than 10,000 tips:
- An INFO log entry warns about memory requirements
- Use
--low-memoryto stream sequence IDs during cross-validation - Install
psutilfor DEBUG-level memory logging
Resource Estimates
| Tree Size | Approx. Memory | Parse Time | Export Time |
|---|---|---|---|
| 100 tips | < 10 MB | < 0.01 s | < 0.01 s |
| 1,000 tips | ~ 20 MB | < 0.01 s | ~ 0.01 s |
| 10,000 tips | ~ 100 MB | ~ 0.01 s | ~ 0.1 s |
| 100,000 tips | ~ 1 GB | ~ 0.1 s | ~ 1 s |
FigTree Rendering Setup
Alternative note: FigTreeKit rendering relies on the FigTree JAR to preserve FigTree annotations and styles in automated workflows. If you only need a cross-platform GUI/CLI tool to render very large trees (>100,000 taxa) without FigTree-compatible Nexus annotations, consider TreeViewer.
# Check status
figtreekit --check-figtree
# Download and compile
figtreekit --setup-figtree
# Use existing JAR
figtreekit --setup-figtree --figtree-jar /path/to/figtree.jar
Rendering Output Formats
| Format | Extension | Best For |
|---|---|---|
| PNG | .png |
Web, presentations, quick preview |
.pdf |
Publication, vector editing (Adobe Illustrator) | |
| SVG | .svg |
Web, scalable vector graphics |
| JPEG | .jpg |
Email, small file size (lossy compression) |
# PNG (default, good for most uses)
figtreekit tree.nwk -o tree.nex --render tree.png
# PDF for publication
figtreekit tree.nwk -o tree.nex --render tree.pdf
# SVG for web
figtreekit tree.nwk -o tree.nex --render tree.svg
# Custom dimensions
figtreekit tree.nwk -o tree.nex --render tree.png --render-width 2000 --render-height 1500
# Explicit render format when extension is ambiguous
figtreekit tree.nwk -o tree.nex --render tree.out --render-format PNG
See docs/user_manual_EN.md for detailed compilation instructions.
Contact & Maintainer
- Author: Zeng Zichao (Shanghai Jiao Tong University)
- Email: zengzichao@sjtu.edu.cn
- GitHub Issues: https://github.com/ZengZichao/FigTreeKit/issues
- GitHub Discussions: https://github.com/ZengZichao/FigTreeKit/discussions
Citation
If you use FigTreeKit in your research, please cite:
@software{figtreekit2026,
author = {Zeng, Zichao},
title = {FigTreeKit: Programmatic styling of phylogenetic trees for FigTree visualization},
year = {2026},
url = {https://github.com/ZengZichao/FigTreeKit}
}
License
FigTreeKit is free software licensed under the GNU General Public License v2.0 or later (GPL-2.0-or-later).
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for details.
Third-party components
- FigTree (
figtreekit/figtree_patched.jar,_figtree_patch/, modified Java sources in_figtree_patch/src/figtree/): derived from FigTree v1.4.4 by Andrew Rambaut, licensed under GPL-2.0-or-later. The original unmodified JAR (_figtree_patch/figtree_original.jar) is also provided to satisfy GPL source-provision requirements; see_figtree_patch/README.mdfor rebuild instructions. - iText (bundled inside the FigTree JARs for PDF export): licensed under the GNU Affero General Public License v3 (AGPL-3.0).
- Biopython (runtime dependency): BSD-3-Clause.
When you redistribute FigTreeKit or the patched FigTree JAR, the copyleft terms of GPL-2.0-or-later and AGPL-3.0 apply.
License compatibility: FigTreeKit uses GPL-2.0-or-later, which allows upgrading to GPL-3.0, thereby achieving compatibility with iText's AGPL-3.0 license. GPL-3.0 and AGPL-3.0 have a defined compatibility path (AGPL-3.0 §13). Downstream users in strict compliance environments may treat FigTreeKit as a combined GPL-3.0 / AGPL-3.0 project.
Links
- Repository: https://github.com/ZengZichao/FigTreeKit
- PyPI: https://pypi.org/project/figtreekit/
- Zenodo Archive:
(auto-generated on each GitHub Release; see .zenodo.json)
- Documentation: docs/user_manual_EN.md
- FigTree: http://tree.bio.ed.ac.uk/software/figtree/
- TreeViewer: https://doi.org/10.1002/ece3.10873
- Biopython: https://biopython.org/
Tested Environment
This software is developed and tested on the following environment:
| OS | Python | Biopython | Status |
|---|---|---|---|
| macOS Tahoe 26.5.2 (Apple Silicon) | 3.11 | 1.88 | ✅ Pass |
Note: FigTreeKit has only been developed and tested on macOS Tahoe 26.5.2 with Python 3.11. Compatibility with other operating systems (Windows, Linux) or Python versions has not been verified.
To reproduce the exact environment:
pip install figtreekit==1.1.0 biopython==1.87
figtreekit --self-test
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file figtreekit-1.1.0.tar.gz.
File metadata
- Download URL: figtreekit-1.1.0.tar.gz
- Upload date:
- Size: 8.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb44e7943e32f59a41bf7ff670a96b38ec5990c7b2d2941fd9b7468d940d1fe7
|
|
| MD5 |
3fc63a4e36a4d6d2cd36af4df6af7d8c
|
|
| BLAKE2b-256 |
b89b00a7bf9069a91cf353462c87b90dc043553f69079da9475b36ddcd118e37
|
Provenance
The following attestation bundles were made for figtreekit-1.1.0.tar.gz:
Publisher:
ci.yml on ZengZichao/FigTreeKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
figtreekit-1.1.0.tar.gz -
Subject digest:
eb44e7943e32f59a41bf7ff670a96b38ec5990c7b2d2941fd9b7468d940d1fe7 - Sigstore transparency entry: 2595750147
- Sigstore integration time:
-
Permalink:
ZengZichao/FigTreeKit@c96d81fadffeec6763eb0b5a59a03d3225afc041 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/ZengZichao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@c96d81fadffeec6763eb0b5a59a03d3225afc041 -
Trigger Event:
push
-
Statement type:
File details
Details for the file figtreekit-1.1.0-py3-none-any.whl.
File metadata
- Download URL: figtreekit-1.1.0-py3-none-any.whl
- Upload date:
- Size: 3.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
428e62127d109f268942e90890165ad926c144048af552b1c66ef00cfbdf423c
|
|
| MD5 |
13235912e10cc83e643b8e8f564288e9
|
|
| BLAKE2b-256 |
7b60943469a4bf885fcc45ed83c22d536066e7ed5030016ce3593fd40605fa77
|
Provenance
The following attestation bundles were made for figtreekit-1.1.0-py3-none-any.whl:
Publisher:
ci.yml on ZengZichao/FigTreeKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
figtreekit-1.1.0-py3-none-any.whl -
Subject digest:
428e62127d109f268942e90890165ad926c144048af552b1c66ef00cfbdf423c - Sigstore transparency entry: 2595750325
- Sigstore integration time:
-
Permalink:
ZengZichao/FigTreeKit@c96d81fadffeec6763eb0b5a59a03d3225afc041 -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/ZengZichao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@c96d81fadffeec6763eb0b5a59a03d3225afc041 -
Trigger Event:
push
-
Statement type: