Skip to content

Commit 1431723

Browse files
authored
read / write phylogenies with internal node names (JuliaPhylo#98)
read root name dropped "#" from hybrid names write internal names read option: names -> namelabel
1 parent 904580d commit 1431723

11 files changed

+166
-124
lines changed

docs/src/man/expectedCFs.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ R"plot(0:1, 0:1, type='l', bty='L', lwd=0.3, col='#008080', xlab='quartet CF obs
3535
R"set.seed"(1234); # hide
3636
R"points(jitter($obsCF,amount=0.005),jitter($expCF,amount=0.005),col='#008080',bg='#00808090',pch=21)"; # hide
3737
R"dev.off()"; # hide
38+
nothing # hide
3839
```
3940
To install ggplot2 if not installed already, do:
4041
`R"install.packages('ggplot2', dep=TRUE)"`

docs/src/man/snaq_plot.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ net3.loglik = 28.315067218909626
1919
## Network Estimation
2020

2121
SNaQ implements the statistical inference method in
22-
[Solís-Lemus and Ané 2016](http://journals.plos.org/plosgenetics/article?id=10.1371/journal.pgen.1005896).
22+
[Solís-Lemus & Ané 2016](http://journals.plos.org/plosgenetics/article?id=10.1371/journal.pgen.1005896).
2323
The procedure involves a numerical optimization of branch lengths and inheritance
2424
probabilities and a heuristic search in the space of phylogenetic networks.
2525

@@ -47,6 +47,7 @@ R"svg(name('snaqplot_net0_1.svg'), width=4, height=3)" # hide
4747
R"par"(mar=[0,0,0,0]) # hide
4848
plot(net0, :R);
4949
R"dev.off()"; # hide
50+
nothing # hide
5051
```
5152
![net0_1](../assets/figures/snaqplot_net0_1.svg)
5253

@@ -69,6 +70,7 @@ R"svg(name('snaqplot_net1_1.svg'), width=4, height=3)" # hide
6970
R"par"(mar=[0,0,0,0]) # hide
7071
plot(net1, :R, showGamma=true);
7172
R"dev.off()"; # hide
73+
nothing # hide
7274
```
7375
![net1_1](../assets/figures/snaqplot_net1_1.svg)
7476

@@ -123,6 +125,7 @@ R"mtext"("hmax=2") # add text annotation: title here
123125
plot(net3, :R, showGamma=true);
124126
R"mtext"("hmax=3")
125127
R"dev.off()"; # hide
128+
nothing # hide
126129
```
127130
![net23](../assets/figures/snaqplot_net23.svg)
128131

@@ -272,6 +275,7 @@ R"svg(name('snaqplot_scores_heuristic.svg'), width=4, height=3)" # hide
272275
R"par"(mar=[2.5,2.5,.5,.5], mgp=[1.4,.4,0], tck=-0.02); # hide
273276
R"plot"(scores, type="b", ylab="network score", xlab="hmax", col="blue");
274277
R"dev.off()"; # hide
278+
nothing # hide
275279
```
276280
![scores_heuristic](../assets/figures/snaqplot_scores_heuristic.svg)
277281

@@ -306,6 +310,7 @@ R"svg(name('snaqplot_net1_2.svg'), width=4, height=3)" # starts image file
306310
R"par"(mar=[0,0,0,0]) # to reduce margins (no margins at all here)
307311
plot(net1, :R, showGamma=true, showEdgeNumber=true); # network is plotted & sent to file
308312
R"dev.off()"; # wrap up and save image file
313+
nothing # hide
309314
```
310315
![net1_2](../assets/figures/snaqplot_net1_2.svg)
311316

@@ -322,6 +327,7 @@ R"svg(name('snaqplot_net1_3.svg'), width=4, height=3)" # hide
322327
R"par"(mar=[0,0,0,0]) # hide
323328
plot(net1, :R, showEdgeLength=true, minorHybridEdgeColor="tan")
324329
R"dev.off()"; # hide
330+
nothing # hide
325331
```
326332
![net1_3](../assets/figures/snaqplot_net1_3.svg)
327333

@@ -342,6 +348,7 @@ R"par"(mar=[0,0,0,0]) # hide
342348
plot(net1,:R, tipOffset=0.5, showNodeNumber=true, edgeColor="tomato4",
343349
minorHybridEdgeColor="skyblue", majorHybridEdgeColor="tan");
344350
R"dev.off()"; # hide
351+
nothing # hide
345352
```
346353
![net1_4](../assets/figures/snaqplot_net1_4.svg)
347354

src/auxiliary.jl

+31-16
Original file line numberDiff line numberDiff line change
@@ -1210,44 +1210,59 @@ function switchHybridNode!(net::HybridNetwork, hybrid::Node, newHybrid::Node)
12101210
end
12111211

12121212
"""
1213-
`assignhybridnames!(net)`
1213+
assignhybridnames!(net)
12141214
1215-
Assign names to hybrid nodes in the network `net`. Hybrid nodes with an empty `name` field ("")
1216-
are modified with a name that does not conflict with other hybrid names in the network.
1217-
The preferred name is "#H3" if the node number is 3 or -3, but an index other than 3 would be
1218-
used if "#H3" were the name of another hybrid node already.
1215+
Assign names to hybrid nodes in the network `net`.
1216+
Hybrid nodes with an empty `name` field ("") are modified with a name that
1217+
does not conflict with other hybrid names in the network. The preferred name
1218+
is "H3" if the node number is 3 or -3, but an index other than 3 would be used
1219+
if "H3" were the name of another node already.
12191220
12201221
If two hybrid nodes have non-empty and equal names, the name of one of them is changed and
12211222
re-assigned as described above (with a warning).
12221223
"""
12231224
function assignhybridnames!(net::HybridNetwork)
1224-
hybnum = Int[] # indices 'i' in hybrid names: #Hi
1225+
rx = r"^H(\d+)$"
1226+
# prep: collect indices 'i' of any tree nodes named like Hi
1227+
trenum = Int[] # indices 'i' in tree node name, in case some are named Hi
1228+
for n in net.node
1229+
!n.hybrid || continue # do nothing if node n is hybrid
1230+
m = match(rx, n.name)
1231+
m == nothing || push!(trenum, parse(Int, m[1]))
1232+
end
12251233
# first: go through *all* existing non-empty names
1234+
hybnum = Int[] # indices 'i' in hybrid names: Hi
12261235
for ih in 1:length(net.hybrid)
1227-
lab = net.hybrid[ih].name
1236+
hnode = net.hybrid[ih]
1237+
lab = hnode.name
12281238
lab != "" || continue # do nothing if label is missing
12291239
jh = findfirst(isequal(lab), [net.hybrid[j].name for j in 1:ih-1])
12301240
if jh !== nothing # set repeated names to ""
1231-
@warn "hybrid nodes $(net.hybrid[ih].number) and $(net.hybrid[jh].number) have the same label: $lab. Will change the name of the former."
1232-
net.hybrid[ih].name = ""
1233-
else
1234-
m = match(r"^#H(\d+)$", lab)
1235-
if m != nothing # make full list of existing indices "i" in #Hi
1236-
push!(hybnum, parse(Int, m[1]))
1241+
@warn "hybrid nodes $(hnode.number) and $(net.hybrid[jh].number) have the same label: $lab. Will change the name of the former."
1242+
hnode.name = ""
1243+
else # fill in list of existing indices "i" in Hi
1244+
m = match(rx, lab)
1245+
m != nothing || continue # skip the rest if name is not of the form Hi
1246+
ind = parse(Int, m[1])
1247+
if ind in trenum
1248+
@warn "hybrid node $(hnode.number) had same label as a tree node: H$ind. Will change hybrid name."
1249+
hnode.name = ""
1250+
else
1251+
push!(hybnum, ind)
12371252
end
12381253
end
12391254
end
1240-
# second: assign empty names to #Hi
1255+
# second: assign empty names to "Hi" for some i
12411256
hnext = 1
12421257
for ih in 1:length(net.hybrid)
12431258
net.hybrid[ih].name == "" || continue # do nothing if non-empty label
12441259
hnum = abs(net.hybrid[ih].number)
1245-
while in(hnum, hybnum)
1260+
while hnum in hybnum || hnum in trenum
12461261
hnum = hnext # not efficient, but rare
12471262
hnext += 1 # and okay on small networks
12481263
end
12491264
push!(hybnum, hnum)
1250-
net.hybrid[ih].name = "#H$hnum"
1265+
net.hybrid[ih].name = "H$hnum"
12511266
end
12521267
end
12531268

src/descriptive.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function Base.show(io::IO, obj::HybridNetwork)
153153
try
154154
# par = writeTopology(obj,round=true) # but writeTopology changes the network, not good
155155
s = IOBuffer()
156-
writeSubTree!(s, obj, false,true, true,3)
156+
writeSubTree!(s, obj, false,true, true,3,false)
157157
par = String(take!(s))
158158
catch err
159159
println("ERROR with writeSubTree!:")

0 commit comments

Comments
 (0)