use kuva::plot::{PhyloTree, TreeBranchStyle, TreeOrientation};
use kuva::backend::svg::SvgBackend;
use kuva::render::render::render_multiple;
use kuva::render::layout::Layout;
use kuva::render::plots::Plot;
const OUT: &str = "docs/src/assets/phylo";
fn main() {
std::fs::create_dir_all(OUT).expect("could not create docs/src/assets/phylo");
basic();
phylogram();
circular();
clade_color();
upgma();
println!("Phylo SVGs written to {OUT}/");
}
fn basic() {
let tree = PhyloTree::from_newick(
"((TaxonA:1.0,TaxonB:2.0)95:1.0,(TaxonC:0.5,TaxonD:0.5)88:1.5,TaxonE:3.0);"
)
.with_support_threshold(80.0);
let plots = vec![Plot::PhyloTree(tree)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Rectangular Tree");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/basic.svg"), svg).unwrap();
}
fn phylogram() {
let tree = PhyloTree::from_newick(
"((A:1.0,B:3.0)90:1.0,(C:2.0,(D:0.5,E:1.5)85:1.0):2.0);"
)
.with_orientation(TreeOrientation::Top)
.with_phylogram()
.with_support_threshold(80.0);
let plots = vec![Plot::PhyloTree(tree)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Phylogram (Top orientation)");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/phylogram.svg"), svg).unwrap();
}
fn circular() {
let newick = concat!(
"(((((Sp_A:0.05,Sp_B:0.08):0.12,(Sp_C:0.07,Sp_D:0.06):0.10):0.15,",
"((Sp_E:0.09,Sp_F:0.11):0.08,(Sp_G:0.06,Sp_H:0.10):0.13):0.12):0.20,",
"(((Sp_I:0.08,Sp_J:0.12):0.10,(Sp_K:0.05,Sp_L:0.09):0.11):0.15,",
"((Sp_M:0.07,Sp_N:0.08):0.09,(Sp_O:0.10,Sp_P:0.06):0.12):0.14):0.18):0.10,",
"((Sp_Q:0.15,Sp_R:0.12):0.20,(Sp_S:0.08,Sp_T:0.10):0.18):0.25);"
);
let tree = PhyloTree::from_newick(newick)
.with_branch_style(TreeBranchStyle::Circular)
.with_phylogram();
let plots = vec![Plot::PhyloTree(tree)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Circular Tree — 20 Taxa");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/circular.svg"), svg).unwrap();
}
fn clade_color() {
let edges: Vec<(&str, &str, f64)> = vec![
("root", "Bacteria", 1.5),
("root", "Eukarya", 2.0),
("Bacteria", "E. coli", 0.5),
("Bacteria", "B. subtilis", 0.7),
("Eukarya", "Yeast", 1.0),
("Eukarya", "Human", 0.8),
];
let tree = PhyloTree::from_edges(&edges)
.with_clade_color(1, "#e41a1c") .with_clade_color(2, "#377eb8") .with_legend("Domains");
let plots = vec![Plot::PhyloTree(tree)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Clade Coloring by Domain");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/clade_color.svg"), svg).unwrap();
}
fn upgma() {
let labels = ["Wolf", "Cat", "Whale", "Human"];
let dist = vec![
vec![0.0, 0.5, 0.9, 0.8],
vec![0.5, 0.0, 0.9, 0.8],
vec![0.9, 0.9, 0.0, 0.7],
vec![0.8, 0.8, 0.7, 0.0],
];
let tree = PhyloTree::from_distance_matrix(&labels, &dist)
.with_phylogram();
let plots = vec![Plot::PhyloTree(tree)];
let layout = Layout::auto_from_plots(&plots)
.with_title("UPGMA Tree from Distance Matrix");
let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write(format!("{OUT}/upgma.svg"), svg).unwrap();
}