Skip to content

Commit 9e93501

Browse files
authored
fix #201, #205, Documenter v1, ready for v0.16.3 (#206)
* fix #205: AbstractString in signatures * fix #201: error instead of warning if 2-cycle * up to v0.16.3
1 parent 3f1e097 commit 9e93501

11 files changed

+122
-192
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PhyloNetworks"
22
uuid = "33ad39ac-ed31-50eb-9b15-43d0656eaa72"
33
license = "MIT"
4-
version = "0.16.2"
4+
version = "0.16.3"
55

66
[deps]
77
BioSequences = "7e6ae17a-c86d-528c-b3b9-7f778a29fe59"

docs/Project.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ BioSymbols = "3c28c6f8-a34d-59c4-9654-267d177fcfa9"
33
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
44
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
55
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
6-
DocumenterMarkdown = "997ab1e6-3595-5248-9280-8efb232c3433"
76
PhyloNetworks = "33ad39ac-ed31-50eb-9b15-43d0656eaa72"
87
PhyloPlots = "c0d5b6db-e3fc-52bc-a87d-1d050989ed3b"
98
RCall = "6f49c342-dc21-5d91-9882-a32aef131414"
109
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
1110
StatsModels = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
1211

1312
[compat]
14-
Documenter = "~0.27"
13+
Documenter = "~1"
1514
PhyloPlots = "1"

docs/make.jl

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Documenter, DocumenterMarkdown
1+
using Documenter
22

33
using Pkg
44
Pkg.add(PackageSpec(name="PhyloPlots", rev="master"))
@@ -11,7 +11,13 @@ makedocs(
1111
sitename = "PhyloNetworks.jl",
1212
authors = "Claudia Solís-Lemus, Cécile Ané, Paul Bastide and contributors.",
1313
modules = [PhyloNetworks], # to list methods from PhyloNetworks only, not from Base etc.
14-
format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"), # easier local build
14+
format = Documenter.HTML(
15+
prettyurls = get(ENV, "CI", nothing) == "true", # easier local build
16+
size_threshold = 600 * 2^10, size_threshold_warn = 500 * 2^10), # 600 KiB
17+
# exception, so warning-only for :missing_docs. List all others:
18+
warnonly = Documenter.except(:autodocs_block, :cross_references, :docs_block,
19+
:doctest, :eval_block, :example_block, :footnote, :linkcheck_remotes,
20+
:linkcheck, :meta_block, :parse_error, :setup_block),
1521
pages = [
1622
"Home" => "index.md",
1723
"Manual" => [

src/auxiliary.jl

+15-38
Original file line numberDiff line numberDiff line change
@@ -481,17 +481,6 @@ function getIndexHybrid(node::Node, net::Network)
481481
return i
482482
end
483483

484-
# function that given a hybrid node, it gives you the minor hybrid edge
485-
# warning: assumes level-1 network: see getparentedgeminor for a general network
486-
function getHybridEdge(node::Node)
487-
node.hybrid || error("node $(node.number) is not hybrid node, cannot get hybrid edges")
488-
a = nothing;
489-
for e in node.edge
490-
(e.hybrid && !e.isMajor) ? a = e : nothing; # assumes level-1: child of hybrid node must be a tree edge
491-
end
492-
isa(a,Nothing) ? error("hybrid node $(node.number) does not have minor hybrid edge, edges: $([e.number for e in node.edge])") : return a
493-
end
494-
495484

496485
# function that given two nodes, it gives you the edge that connects them
497486
# returns error if they are not connected by an edge
@@ -684,36 +673,24 @@ end
684673
# function to delete an internal node with only 2 edges
685674
function deleteIntNode!(net::Network, n::Node)
686675
size(n.edge,1) == 2 || error("node $(n.number) does not have only two edges")
687-
# isEqual(n,net.node[net.root]) && println("deleting the root $(n.number) because it has only two edges attached")
688676
index = n.edge[1].number < n.edge[2].number ? 1 : 2;
689-
edge1 = n.edge[index];
690-
edge2 = n.edge[index==1 ? 2 : 1];
691-
if(!edge1.hybrid && !edge2.hybrid)
692-
node1 = getOtherNode(edge1,n);
693-
node2 = getOtherNode(edge2,n);
694-
removeEdge!(node2,edge2);
695-
removeNode!(n,edge1);
696-
setEdge!(node2,edge1);
697-
setNode!(edge1,node2);
698-
deleteNode!(net,n);
699-
deleteEdge!(net,edge2);
700-
else
701-
@warn "the two edges $([edge1.number,edge2.number]) attached to node $(n.number) must be tree edges to delete node"
702-
if(edge1.hybrid)
703-
hybedge = edge1
704-
otheredge = edge2
705-
elseif(edge2.hybrid)
706-
hybedge = edge2
707-
otheredge = edge1
677+
edge1 = n.edge[index]; # edge1 will be kept
678+
edge2 = n.edge[index==1 ? 2 : 1] # we will delete edge2 and n, except if edge2 is hybrid
679+
if edge2.hybrid
680+
(edge2, edge1) = (edge1, edge2)
681+
if getchild(edge1) === n || edge2.hybrid
682+
@error "node with incoming hybrid edge or incident to 2 hybrid edges: will not be removed"
683+
return nothing
708684
end
709-
othernode = getOtherNode(otheredge,n)
710-
removeNode!(n,hybedge)
711-
removeEdge!(othernode,otheredge)
712-
setEdge!(othernode,hybedge)
713-
setNode!(hybedge,othernode)
714-
deleteNode!(net,n)
715-
deleteEdge!(net,otheredge)
716685
end
686+
node2 = getOtherNode(edge2,n)
687+
removeEdge!(node2,edge2)
688+
removeNode!(n,edge1)
689+
setEdge!(node2,edge1)
690+
setNode!(edge1,node2)
691+
deleteNode!(net,n)
692+
deleteEdge!(net,edge2)
693+
return nothing
717694
end
718695

719696

src/deleteHybrid.jl

+15-36
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
function identifyInCycle(net::Network,node::Node)
1717
node.hybrid || error("node $(node.number) is not hybrid, cannot identifyInCycle")
1818
start = node;
19-
hybedge = getHybridEdge(node);
20-
last = getOtherNode(hybedge,node);
19+
hybedge = getparentedgeminor(node)
20+
lastnode = getOtherNode(hybedge,node)
2121
dist = 0;
2222
queue = PriorityQueue();
2323
path = Node[];
@@ -33,32 +33,19 @@ function identifyInCycle(net::Network,node::Node)
3333
return true, net.edges_changed, net.nodes_changed
3434
else
3535
curr = dequeue!(queue);
36-
if(isEqual(curr,last))
36+
if isEqual(curr,lastnode)
3737
found = true;
3838
push!(path,curr);
39-
else
40-
if(!net.visited[getIndex(curr,net)])
41-
net.visited[getIndex(curr,net)] = true;
42-
if(isEqual(curr,start))
43-
for e in curr.edge
44-
if(!e.hybrid || e.isMajor)
45-
other = getOtherNode(e,curr);
46-
other.prev = curr;
47-
dist = dist+1;
48-
enqueue!(queue,other,dist);
49-
end
50-
end
51-
else
52-
for e in curr.edge
53-
if(!e.hybrid || e.isMajor)
54-
other = getOtherNode(e,curr);
55-
if(!other.leaf && !net.visited[getIndex(other,net)])
56-
other.prev = curr;
57-
dist = dist+1;
58-
enqueue!(queue,other,dist);
59-
end
60-
end
61-
end
39+
elseif !net.visited[getIndex(curr,net)]
40+
net.visited[getIndex(curr,net)] = true
41+
atstart = isEqual(curr,start)
42+
for e in curr.edge
43+
e.isMajor || continue
44+
other = getOtherNode(e,curr)
45+
if atstart || (!other.leaf && !net.visited[getIndex(other,net)])
46+
other.prev = curr
47+
dist = dist+1
48+
enqueue!(queue,other,dist)
6249
end
6350
end
6451
end
@@ -149,17 +136,9 @@ function deleteHybridizationUpdate!(net::HybridNetwork, hybrid::Node, random::Bo
149136
push!(edgesRoot, edges[2])
150137
undoContainRoot!(edgesRoot);
151138
end
152-
@debug begin
153-
msg = ""
154-
if edges[1].gamma < 0.5
155-
msg = "strange major hybrid edge $(edges[1].number) with gamma $(edges[1].gamma) less than 0.5"
156-
end
157-
if edges[1].gamma == 1.0
158-
msg = "strange major hybrid edge $(edges[1].number) with gamma $(edges[1].gamma) equal to 1.0"
159-
end
160-
msg
161-
end
162139
limit = edges[1].gamma
140+
@debug (limit < 0.5 ? "strange major hybrid edge $(edges[1].number) with γ $limit < 0.5" :
141+
(limit == 1.0 ? "strange major hybrid edge $(edges[1].number) with γ = $limit" : ""))
163142
if(random)
164143
minor = rand() < limit ? false : true
165144
else

src/manipulateNet.jl

+12-8
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,16 @@ end
9595

9696
"""
9797
hybridatnode!(net::HybridNetwork, nodeNumber::Integer)
98-
hybridatnode(net, nodeNumber)
9998
100-
Change the status of edges in network `net`,
99+
Change the direction and status of edges in network `net`,
101100
to move the hybrid node in a cycle to the node with number `nodeNumber`.
102101
This node must be in one (and only one) cycle, otherwise an error will be thrown.
102+
Check and update the nodes' field `inCycle`.
103103
104-
The second method does not modify `net`, checks that it's of level 1, and
105-
returns the new network after hybrid modification.
104+
Output: `net` after hybrid modification.
106105
107-
`net` is assumed to be of level 1, that is, each blob has a
106+
Assumption: `net` must be of level 1, that is, each blob has a
108107
single cycle with a single reticulation.
109-
Check and update the nodes' field `inCycle`.
110108
111109
# example
112110
@@ -150,7 +148,7 @@ Move the reticulation from `hybrid` to `newNode`,
150148
which must in the same cycle. `net` is assumed to be of level 1,
151149
but **no checks** are made and fields are supposed up-to-date.
152150
153-
Called by `hybridatnode!(net, node number)`, which is itself
151+
Called by `hybridatnode!(net, nodenumber)`, which is itself
154152
called by [`undirectedOtherNetworks`](@ref).
155153
"""
156154
function hybridatnode!(net::HybridNetwork, hybrid::Node, newNode::Node)
@@ -182,7 +180,13 @@ end
182180
# does not call hybridatnode! but repeats its code: oops! violates DRY principle
183181
# nodeNumber should correspond to the number assigned by readTopologyLevel1,
184182
# and the node numbers in `net` are irrelevant.
185-
@doc (@doc hybridatnode!) hybridatnode
183+
"""
184+
hybridatnode(net::HybridNetwork, nodeNumber::Integer)
185+
186+
Move the hybrid node in a cycle to make node number `nodeNumber` a hybrid node
187+
Compared to [`hybridatnode!`], this method checks that `net` is of level 1
188+
(required) and does not modify it.
189+
"""
186190
function hybridatnode(net0::HybridNetwork, nodeNumber::Integer)
187191
net = readTopologyLevel1(writeTopologyLevel1(net0)) # we need inCycle attributes
188192
ind = 0

src/readwrite.jl

+5-10
Original file line numberDiff line numberDiff line change
@@ -750,16 +750,11 @@ function cleanAfterRead!(net::HybridNetwork, leaveRoot::Bool)
750750
nodes = copy(net.node)
751751
for n in nodes
752752
if isNodeNumIn(n,net.node) # very important to check
753-
if size(n.edge,1) == 2
754-
if !n.hybrid
755-
if !leaveRoot || !isEqual(net.node[net.root],n) #if n is the root
756-
deleteIntNode!(net,n);
757-
end
758-
else
759-
hyb = count([e.hybrid for e in n.edge]);
760-
if hyb == 1
761-
deleteIntNode!(net,n);
762-
end
753+
if size(n.edge,1) == 2 # delete n if:
754+
if (!n.hybrid && (!leaveRoot || !isEqual(net.node[net.root],n)) ||
755+
(n.hybrid && sum(e.hybrid for e in n.edge) == 1))
756+
deleteIntNode!(net,n)
757+
continue # n was deleted: skip the rest
763758
end
764759
end
765760
if !n.hybrid

src/traitsLikDiscrete.jl

+8-8
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ The `rvsymbol` should be as required by [`RateVariationAcrossSites`](@ref).
133133
The network's gamma values are modified if they are missing. After that,
134134
a deep copy of the network is passed to the inner constructor.
135135
"""
136-
function StatisticalSubstitutionModel(net::HybridNetwork, fastafile::String,
136+
function StatisticalSubstitutionModel(net::HybridNetwork, fastafile::AbstractString,
137137
modsymbol::Symbol, rvsymbol=:noRV::Symbol, ratecategories=4::Int;
138138
maxhybrid=length(net.hybrid)::Int)
139139
for e in net.edge # check for missing or inappropriate γ values
@@ -449,14 +449,14 @@ end
449449

450450
#species, dat version, no ratemodel
451451
function fitdiscrete(net::HybridNetwork, model::SubstitutionModel,
452-
species::Array{String}, dat::DataFrame; kwargs...)
452+
species::Array{<:AbstractString}, dat::DataFrame; kwargs...)
453453
ratemodel = RateVariationAcrossSites(ncat=1)
454454
fitdiscrete(net, model, ratemodel, species, dat; kwargs...)
455455
end
456456

457457
#species, dat version with ratemodel
458458
function fitdiscrete(net::HybridNetwork, model::SubstitutionModel,
459-
ratemodel::RateVariationAcrossSites, species::Array{String},
459+
ratemodel::RateVariationAcrossSites, species::Array{<:AbstractString},
460460
dat::DataFrame; kwargs...)
461461
dat2 = traitlabels2indices(dat, model) # vec of vec, indices
462462
o, net = check_matchtaxonnames!(copy(species), dat2, net)
@@ -465,7 +465,7 @@ end
465465

466466
#wrapper: species, dat version with model symbol
467467
function fitdiscrete(net::HybridNetwork, modSymbol::Symbol,
468-
species::Array{String}, dat::DataFrame, rvSymbol=:noRV::Symbol; kwargs...)
468+
species::Array{<:AbstractString}, dat::DataFrame, rvSymbol=:noRV::Symbol; kwargs...)
469469
rate = startingrate(net)
470470
labels = learnlabels(modSymbol, dat)
471471
if modSymbol == :JC69
@@ -498,7 +498,7 @@ end
498498
#dnadata with dnapatternweights version with ratemodel
499499
function fitdiscrete(net::HybridNetwork, model::SubstitutionModel,
500500
ratemodel::RateVariationAcrossSites,dnadata::DataFrame,
501-
dnapatternweights::Array{Float64}; kwargs...)
501+
dnapatternweights::Array{<:AbstractFloat}; kwargs...)
502502
dat2 = traitlabels2indices(dnadata[!,2:end], model)
503503
o, net = check_matchtaxonnames!(dnadata[:,1], dat2, net)
504504
kwargs = (:siteweights => dnapatternweights, kwargs...)
@@ -508,7 +508,7 @@ end
508508

509509
#wrapper for dna data
510510
function fitdiscrete(net::HybridNetwork, modSymbol::Symbol, dnadata::DataFrame,
511-
dnapatternweights::Array{Float64}, rvSymbol=:noRV::Symbol; kwargs...)
511+
dnapatternweights::Array{<:AbstractFloat}, rvSymbol=:noRV::Symbol; kwargs...)
512512
rate = startingrate(net)
513513
if modSymbol == :JC69
514514
model = JC69([1.0], true) # 1.0 instead of rate because relative version
@@ -580,7 +580,7 @@ function fit!(obj::SSM; optimizeQ=true::Bool, optimizeRVAS=true::Bool,
580580
return obj
581581
end
582582
if optimizeQ
583-
function loglikfun(x::Vector{Float64}, grad::Vector{Float64}) # modifies obj
583+
function loglikfun(x::Vector{<:AbstractFloat}, grad::Vector{<:AbstractFloat}) # modifies obj
584584
setrates!(obj.model, x)
585585
res = discrete_corelikelihood!(obj)
586586
verbose && println("loglik: $res, model rates: $x")
@@ -609,7 +609,7 @@ function fit!(obj::SSM; optimizeQ=true::Bool, optimizeRVAS=true::Bool,
609609
verbose && println("got $(round(fmax, digits=5)) at $(round.(xmax, digits=5)) after $(optQ.numevals) iterations (return code $(ret))")
610610
end
611611
if optimizeRVAS
612-
function loglikfunRVAS(alpha::Vector{Float64}, grad::Vector{Float64})
612+
function loglikfunRVAS(alpha::Vector{<:AbstractFloat}, grad::Vector{<:AbstractFloat})
613613
setparameters!(obj.ratemodel, alpha)
614614
res = discrete_corelikelihood!(obj)
615615
verbose && println("loglik: $res, rate variation model shape parameter alpha: $(alpha[1])")

0 commit comments

Comments
 (0)