Skip to content

Commit 5406ce1

Browse files
committed
.
1 parent ebf3726 commit 5406ce1

7 files changed

Lines changed: 41613 additions & 24807 deletions

File tree

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,12 @@ recmpox -i fasta/ -o output -ref Ia,Ib -include-indels
124124
- **potential_recombinants_diagnostic_sites.tsv**: Diagnostic site classification per potential recombinant (when any exist).
125125
- **diagnostic_snps.txt**: List of diagnostic SNP positions (ref1 vs ref2 alleles).
126126
- **.recmpox.log**: Log file (in output directory).
127-
- With **-extract-tracts**: **extracted_tracts/** — per-sample FASTA with only Ia tract positions (rest N) and only Ib tract positions (rest N).
128-
- With **-phylogeny**: **phylogeny/** folder containing all IQ-TREE outputs (e.g. alignment.treefile, alignment.log, alignment.iqtree), **phylogeny_tree.treefile** (midpoint-rooted so FigTree opens it rooted), and **phylogeny_tree.pdf** (tips as circles: dark red-pink = extracted tracts, grey = references). Intermediate files under `work/` are removed after the run.
127+
- With **-extract-tracts**: **tracts/** — per-sample FASTA with only Ia tract positions (rest N) and only Ib tract positions (rest N): `Ia_recombinant_ancestral_tract.fa`, `Ib_recombinant_ancestral_tract.fa` (clade names depend on -ref).
128+
- With **-phylogeny**: **phylogeny/** folder containing **phylogeny_alignment.fasta**, **phylogeny_tree.treefile** (midpoint-rooted), **phylogeny_tree.pdf**, and **phylogeny_tree.svg**. The pipeline runs a bundled R script (requires **ape**, **phytools**, **ggtree**, **ggplot2**). To test the R script on an existing tree (e.g. after a run where the R step failed), from your **output directory** run:
129+
```bash
130+
Rscript /path/to/recmpox/references/root_tree_figure.R phylogeny/phylogeny_tree.treefile
131+
```
132+
(Replace `/path/to/recmpox` with the RecMpox install or source path; the script writes **rooted.tree**, **tree_figure.pdf**, and **tree_figure.svg** into **phylogeny/**.)
129133

130134
## Interpretation
131135

conda-recipes/meta.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ requirements:
3232
- minimap2
3333
- samtools
3434
- squirrel
35+
- iqtree=2.4.0
36+
- r-base
37+
- r-ape
38+
- r-ggplot2
39+
- r-phytools
40+
- bioconductor-ggtree
3541

3642
test:
3743
imports:

environment-recmpox.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ dependencies:
88
- samtools
99
- squirrel
1010
- iqtree=2.4.0
11-
- ete3
11+
- r-base
12+
- r-ape
13+
- r-phytools
14+
- bioconductor-ggtree
15+
- r-ggplot2
1216
variables:
1317
PYTHONNOUSERSITE: "1"

recmpox/recmpox.py

Lines changed: 152 additions & 98 deletions
Large diffs are not rendered by default.

recmpox/references/mpox_references.fasta

Lines changed: 41342 additions & 24705 deletions
Large diffs are not rendered by default.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env Rscript
2+
#
3+
# Midpoint-root a phylogeny and plot tip labels as circles with clade colors.
4+
# Writes rooted.tree and tree_figure.pdf in the same directory as the input tree.
5+
#
6+
# Usage: Rscript root_tree_figure.R [treefile]
7+
# Default: alignment.treefile (when run from phylogeny dir)
8+
#
9+
# Requires: ape, phytools, ggtree, ggplot2.
10+
11+
args <- commandArgs(trailingOnly = TRUE)
12+
tree_path <- if (length(args) >= 1) args[1] else "alignment.treefile"
13+
out_dir <- dirname(tree_path)
14+
if (out_dir == "") out_dir <- "."
15+
16+
if (!file.exists(tree_path)) {
17+
stop("Tree file not found: ", tree_path)
18+
}
19+
20+
suppressPackageStartupMessages({
21+
library(ape)
22+
library(phytools)
23+
library(ggtree)
24+
library(ggplot2)
25+
})
26+
old_warn <- getOption("warn")
27+
on.exit(options(warn = old_warn), add = TRUE)
28+
options(warn = -1)
29+
30+
tr <- read.tree(tree_path)
31+
tr <- phytools::midpoint.root(tr)
32+
rooted_path <- file.path(out_dir, "rooted.tree")
33+
write.tree(tr, rooted_path)
34+
35+
labels <- tr$tip.label
36+
type <- ifelse(grepl("_tracts", labels, fixed = TRUE), "recombinant", "reference")
37+
clade <- rep("Ia", length(labels))
38+
clade[type == "recombinant"] <- "Recombinant"
39+
clade[grepl("sh2024Ib", labels, fixed = TRUE)] <- "sh2024Ib"
40+
clade[grepl("sh2023Ib", labels, fixed = TRUE)] <- "sh2024Ib"
41+
clade[grepl("sh2024[iI]a", labels)] <- "sh2024Ia"
42+
clade[grepl("sh2017IIb", labels, fixed = TRUE)] <- "sh2017IIb"
43+
clade[grepl("_IIa_", labels, fixed = TRUE)] <- "IIa"
44+
clade[grepl("^IIa_", labels)] <- "IIa"
45+
tip_data <- data.frame(label = labels, type = type, clade = clade, stringsAsFactors = FALSE)
46+
tip_data$plot_clade <- ifelse(tip_data$clade == "sh2024Ib", "sh2023Ib", tip_data$clade)
47+
48+
p <- ggtree(tr, linewidth = 0.65)
49+
clade_colors <- c(
50+
Recombinant = "#FF6B9D",
51+
Ia = "#1e5f72",
52+
sh2024Ia = "#b83c28",
53+
sh2023Ib = "#2d7a4a",
54+
sh2017IIb = "#c97a08",
55+
IIa = "#5c2270"
56+
)
57+
tip_size <- 4.2
58+
legend_order <- c("sh2023Ib", "sh2024Ia", "Ia", "sh2017IIb", "IIa", "Recombinant")
59+
legend_labels <- c(
60+
sh2023Ib = "Ib (sh2023Ib)",
61+
sh2024Ia = "Ia (sh2024Ia)",
62+
Ia = "Ia (non-sh2024Ia)",
63+
sh2017IIb = "IIb (sh2017IIb)",
64+
IIa = "IIa",
65+
Recombinant = "Potential recombinant"
66+
)
67+
68+
p <- p %<+% tip_data +
69+
geom_tippoint(aes(fill = plot_clade), size = tip_size, shape = 21, color = "black", stroke = 0.5) +
70+
scale_fill_manual(
71+
values = clade_colors,
72+
breaks = legend_order,
73+
labels = legend_labels,
74+
na.value = "grey70",
75+
name = "Clade",
76+
drop = FALSE
77+
) +
78+
theme(
79+
legend.position = c(0.18, 0.97),
80+
legend.justification = c(0.5, 1),
81+
legend.background = element_rect(fill = "white", colour = "black", linewidth = 0.4),
82+
legend.margin = margin(5, 5, 5, 5),
83+
legend.spacing.y = unit(4.5, "mm"),
84+
legend.key.size = unit(6.75, "mm"),
85+
legend.title = element_text(face = "bold", size = 15),
86+
legend.text = element_text(size = 13.5),
87+
text = element_text(family = "sans")
88+
)
89+
90+
tree_depth <- max(ape::node.depth.edgelength(tr))
91+
p <- p +
92+
geom_tiplab(aes(label = label), size = 2.4, hjust = -0.04, align = TRUE, linesize = 0.2) +
93+
xlim_tree(tree_depth * 1.25)
94+
p <- p + geom_treescale(x = 0, y = -1, width = 0.002, fontsize = 2.8, linesize = 0.4)
95+
96+
fig_height <- max(8, length(tr$tip.label) * 0.15)
97+
pdf_path <- file.path(out_dir, "tree_figure.pdf")
98+
ggsave(pdf_path, p, width = 12, height = fig_height, limitsize = FALSE)
99+
# Use base R SVG device (no svglite package required)
100+
svg_path <- file.path(out_dir, "tree_figure.svg")
101+
ggsave(svg_path, p, width = 12, height = fig_height, limitsize = FALSE, device = grDevices::svg)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
long_description=long_description,
1212
long_description_content_type="text/markdown",
1313
packages=find_packages(),
14-
package_data={"recmpox": ["references/*.fasta"]},
14+
package_data={"recmpox": ["references/*.fasta", "references/*.R"]},
1515
python_requires=">=3.9",
1616
install_requires=[], # matplotlib optional (for --plot)
1717
entry_points={

0 commit comments

Comments
 (0)