Click any figure for the code that produces it. Every example simulates with ZOMBI2 and plots with Phylustrator, a separate package — so to run one you need both:
pip install zombi2 phylustrator
Pure birth, no extinction — a forward tree of 100 lineages.
pure birth (Yule)The full history behind 50 survivors — their branches solid, extinct lineages dashed.
birth–deathA pulse at t = 3 culls 75% of lineages — the skyline drops sharply at the dashed line, then recovers.
mass extinction · + skylineSpeciation runs slow, then fast, then slow — the burst packs branches between the two dashed regime lines.
time-varying birthSpeciation slows as diversity fills up; the skyline rises and plateaus at the cap of 100.
birth–death · + skylineTwo thousand trees of 100 tips under each of two processes — diversity-dependence bends the lineage curves over (left), and the γ statistic separates the two sets of trees almost perfectly (right).
simulation study · 4000 treesA genome as a ring — genes evenly spaced by rank, coloured by family, arrows by strand. plot(g, layout="circular") + genes().
Two genomes, one per row; ribbons link same-family genes and cross where the order was rearranged. stack([a,b]) + synteny().
One family's history on the species tree: duplications (squares), losses (crosses) and transfers (arrows, donor→recipient). plot(tree) + branch_events(…).
A family × genome copy-number heatmap, its rows locked to the tips. beside(tree, heatmap(profiles)).
A real bacterium — Mycoplasma genitalium, 546 genes at their true base positions, coloured by strand; the forward/reverse switch marks the replication origin. read_gff(…).
One inversion on a circular genome: the affected segment is reversed and its strands flip (the arrows turn round). The band marks the segment in both rings. highlight(g, start, end) + genes().
Transfers steered to run between two clades (a Clades + Between kernel — topology, not a trait). Tree coloured by clade; the barplot counts transfers by clade pair, so A↔B towers over within-clade.
The clock tree the sequences evolve down — branch lengths are substitutions/site under an uncorrelated relaxed clock, so the tips are not level.
phylustrator · phylogramThe other clock we ship: under the autocorrelated clock the rate drifts parent→child, so related lineages share a rate — branches coloured by lineage rate move in blocks, not salt-and-pepper. substitution = FromParent(spread).
A small tree with its internal nodes numbered (0 = initial genome, 1 = crown, …); beside it the reconstructed sequence at each — one free-floating row per node, not aligned to the tips. seqs.ancestral.
A single-copy family across 20 species, residues coloured (with a nucleotide key), each row locked to its tip. beside(tree, alignment(aln)).
Free diffusion — sister lineages drift apart with time.
continuousPulled to an optimum: a high start (yellow) converges to blue.
continuousA two-state trait hops between habitats; each branch is painted by its state history.
discrete · MkTwo traits evolve together (r = 0.9) — two trees, coloured by each trait, and the tip scatter.
continuous · + scatterTwo binary characters where one's flip rate depends on the other's state. Two trees, coloured by each character (X green, Y purple), so you can see Y is present where X is; the 2×2 chain (arrow width = rate) is the model. simulate_discrete(states=("00",…), switch={…}).
A driver (a trait for the lifestyle) modifies the rate of loss (the target). Endosymbionts also gain genes more slowly, so their genomes shrink. The tree is coloured by the lifestyle and the bars are genome size at each tip.
trait → lossA driver (a trait for the strength of selection) modifies the rate of duplication (the target). Under relaxed selection duplicates accumulate and the genomes grow. The tree is coloured by the selection regime and the bars are genome size at each tip.
trait → duplicationA driver (a trait for competence) modifies who receives a transfer (the target), not a rate. Competent lineages take up DNA more often and their genomes grow. The tree is coloured by competence and the bars are genome size at each tip.
trait → transfer uptakeA driver (a diffusing continuous trait) modifies the rate of origination (the target). A Curve turns each value into a factor, so genome size follows the trait. The tree is coloured by the trait value and the bars are genome size at each tip.
A two-state trait drives speciation — the fast state's clades take over; the inset is the state Markov chain.
trait → speciationOne state dies far faster; the doomed lineages (dashed) drop out.
trait → extinctionThree graded speciation rates with constant death — the fastest state fills the tree, extinct lineages dashed.
trait → speciation