Skip to content

Commit

Permalink
Merge pull request #87 from EcoJulia/rr/parser
Browse files Browse the repository at this point in the history
Add fully recursive types, speed up parser, improve testing
  • Loading branch information
richardreeve authored Dec 7, 2023
2 parents 505323a + 6f1b300 commit 27c0d92
Show file tree
Hide file tree
Showing 23 changed files with 1,062 additions and 184 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# NEWS

- v0.5.0
- Add recursive tree, node and branch types
- Improve testing
- Note, this is a breaking change because the RootedTree type is now an alias for RecursiveTree, not LinkTree for efficiency
- v0.4.24
- Fix workflows
- v0.4.23
Expand Down
16 changes: 10 additions & 6 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Phylo"
uuid = "aea672f4-3940-5932-aa44-993d1c3ff149"
author = ["Richard Reeve <Richard.Reeve@glasgow.ac.uk>"]
version = "0.4.24"
version = "0.5.0"

[deps]
AxisArrays = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
Expand All @@ -12,6 +12,8 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
IterableTables = "1c8ee90f-4401-5389-894e-7a04a3dc0f4d"
Missings = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
ParserCombinator = "fae87a5f-d1ad-5cf0-8f61-c941e1580b46"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Expand All @@ -22,6 +24,7 @@ Tokenize = "0796e94c-ce3b-5d07-9a54-7f471281c624"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[weakdeps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
RCall = "6f49c342-dc21-5d91-9882-a32aef131414"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"

Expand All @@ -37,18 +40,19 @@ Distributions = "0.24, 0.25"
Graphs = "1"
IterableTables = "1"
Missings = "1"
ParserCombinator = "2"
Plots = "1"
Printf = "1"
Printf = "1.6"
RCall = "0.13"
Random = "1"
Random = "1.6"
RecipesBase = "1"
Requires = "1"
SimpleTraits = "0.9"
Statistics = "1"
Test = "1"
Statistics = "1.6"
Test = "1.6"
Tokenize = "0.5"
Unitful = "1"
julia = "1"
julia = "1.6"

[extras]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Expand Down
1 change: 1 addition & 0 deletions docs/src/man/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ getbranch
getbranches
gettreeinfo
validate!
invalidate!
branchdims
treetype
```
Expand Down
11 changes: 5 additions & 6 deletions docs/src/man/plotting.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ the same way

```@example plotting
plot(hummers,
size = (400, 800),
linecolor = :orange, linewidth = 5,
markersize = 10, markercolor = :steelblue, markerstrokecolor = :white,
series_annotations = text.(1:nnodes(hummers), 5, :center, :center, :white,
tipfont = (4,))
)
size = (400, 800),
linecolor = :orange, linewidth = 5,
markersize = 10, markercolor = :steelblue, markerstrokecolor = :white,
series_annotations = text.(1:nnodes(hummers), 5, :center, :center, :white),
tipfont = (4,))
```

The `marker_group` and `line_group` keywords allow plotting discrete values onto
Expand Down
9 changes: 3 additions & 6 deletions docs/src/man/treetypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This package offers a number of different types of tree, each
optimised for a specific usage

```@docs
RecursiveTree
LinkTree
NamedBinaryTree
BinaryTree
Expand All @@ -27,17 +28,13 @@ PolytomousTree
NamedPolytomousTree
```

## Node types
## Node and Branch types

```@docs
RecursiveElt
LinkNode
BinaryNode
Node
```

## Branch types

```@docs
LinkBranch
Branch
```
Expand Down
28 changes: 16 additions & 12 deletions src/API.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Phylo
using Phylo: Rootedness, Rooted, TreeType, TraversalOrder
using Phylo: AbstractNode, AbstractBranch, AbstractTree
using Phylo: AbstractElt, AbstractNode, AbstractBranch, AbstractTree
using SimpleTraits
using Unitful

Expand Down Expand Up @@ -30,7 +30,6 @@ using Unitful

"""
_prefernodeobjects(::Type{<:AbstractTree})
_prefernodeobjects(::Type{<:AbstractNode})
Does this tree or node type prefer nodes to be objects or names? Must be
implemented for every node type.
Expand All @@ -41,7 +40,6 @@ _prefernodeobjects(::Type{<:AbstractTree{TT, RT, NL, N, B}}) where

"""
_preferbranchobjects(::Type{<:AbstractTree})
_preferbranchobjects(::Type{<:AbstractBranch})
Does this tree or branch type prefer branches to be objects or names? Must be
implemented for every branch type.
Expand Down Expand Up @@ -410,8 +408,7 @@ or a pair) from a tree. Must be implemented for PreferBranchObjects tree types.
function _getbranchname end
_getbranchname(::AbstractTree{OneTree, RT, NL, N},
pair::Pair{NL, N}) where {RT, NL, N} = pair[1]
_getbranchname(::AbstractTree{OneTree, RT},
branchname::Int) where RT = branchname
_getbranchname(::AbstractTree{OneTree}, id::Int) = id

"""
_getbranches(tree::AbstractTree)
Expand Down Expand Up @@ -515,11 +512,18 @@ function _clearrootheight! end
"""
_validate!(::AbstractTree)
Check whether the tree is internally valid.
"""
function _validate! end
_validate!(::AbstractTree) = true

"""
_invalidate!(::AbstractTree, state)
Confirm that the tree is no longer necessarily valid, and remove cache information.
"""
function _invalidate! end

"""
_traversal(tree::AbstractTree, order::TraversalOrder, todo, sofar)
Expand Down Expand Up @@ -632,7 +636,7 @@ _indegree(tree::AbstractTree{OneTree, Unrooted}, node) =
Is there space for a new inbound connection on a node?
"""
function _hasinboundspace end
_hasinboundspace(tree::AbstractTree{OneTree}, node) =
_hasinboundspace(tree::AbstractTree{OneTree, <: Rooted}, node) =
!_hasinbound(tree, node)

"""
Expand All @@ -644,7 +648,7 @@ function _outdegree end
_outdegree(tree::AbstractTree{OneTree, <: Rooted}, node) =
length(_getoutbounds(tree, node))
_outdegree(tree::AbstractTree{OneTree, Unrooted},
node::AbstractNode{Unrooted}) =
node::AbstractElt{Unrooted}) =
_degree(tree, node) == 0 ? 0 : missing

"""
Expand Down Expand Up @@ -751,9 +755,9 @@ Return the child node(s) for this node. May be implemented for any rooted
AbstractNode subtype.
"""
function _getchildren end
_getchildren(tree::T, node::N) where {RT <: Rooted, NL, N <: AbstractNode, B, T <: AbstractTree{OneTree, RT, NL, N, B}} =
_getchildren(tree::AbstractTree{OneTree, RT}, node::N) where {RT <: Rooted, N <: AbstractElt{RT}} =
N[_dst(tree, branch) for branch in _getoutbounds(tree, node)]
_getchildren(tree::T, node::NL) where {RT <: Rooted, NL, N <: AbstractNode, B, T <: AbstractTree{OneTree, RT, NL, N, B}} =
_getchildren(tree::AbstractTree{OneTree, RT, NL}, node::NL) where {RT <: Rooted, NL} =
NL[_dst(tree, branch) for branch in _getoutbounds(tree, node)]

"""
Expand Down Expand Up @@ -834,10 +838,10 @@ end

# AbstractBranch methods
"""
_src(branch::AbstractBranch)
_src(tree, branch)
Return source node for a branch. Must be implemented for any rooted
AbstractBranch subtype.
branch type.
"""
function _src end
_src(::T, ::B) where {T, B} = error("No _src() function for $T, $B")
Expand Down
44 changes: 19 additions & 25 deletions src/Interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,48 @@ using SimpleTraits
Returns tree number (OneTree, ManyTrees) from a tree type.
"""
treetype(::Type{T}) where {TT <: TreeType, RT, NL, N, B,
T <: AbstractTree{TT, RT, NL, N, B}} = TT
treetype(::Type{T}) where {TT, T <: AbstractTree{TT}} = TT

"""
roottype(::Type{AbstractTree})
roottype(::Type{AbstractNode})
roottype(::Type{AbstractBranch})
roottype(::Type{AbstractElt})
Returns root type from a tree type.
Returns root type from a tree, node, branch or other element type.
"""
roottype(::Type{T}) where {TT, RT <: Rootedness, NL, N, B,
T <: AbstractTree{TT, RT, NL, N, B}} = RT
roottype(::Type{N}) where {RT <: Rootedness, NL,
N <: AbstractNode{RT, NL}} = RT
roottype(::Type{B}) where {RT <: Rootedness, NL,
B <: AbstractBranch{RT, NL}} = RT
roottype(::Type{T}) where {TT, RT, T <: AbstractTree{TT, RT}} = RT
roottype(::Type{E}) where {RT, E <: AbstractElt{RT}} = RT

"""
nodenametype(::Type{AbstractTree})
nodenametype(::Type{AbstractNode})
nodenametype(::Type{AbstractBranch})
nodenametype(::Type{AbstractElt})
Returns type of node names from a tree type.
"""
nodenametype(::Type{T}) where {TT, RT, NL, N, B,
T <: AbstractTree{TT, RT, NL, N, B}} = NL
nodenametype(::Type{N}) where {RT <: Rootedness, NL,
N <: AbstractNode{RT, NL}} = NL
nodenametype(::Type{B}) where {RT <: Rootedness, NL,
B <: AbstractBranch{RT, NL}} = NL
nodenametype(::Type{T}) where {TT, RT, NL, T <: AbstractTree{TT, RT, NL}} = NL
nodenametype(::Type{E}) where {RT, NL, E <: AbstractElt{RT, NL}} = NL

"""
nodetype(::Type{AbstractTree})
Returns type of nodes from a tree type.
"""
nodetype(::Type{T}) where {TT, RT, NL, N <: AbstractNode, B,
T <: AbstractTree{TT, RT, NL, N, B}} = N
nodetype(::Type{T}) where {TT, RT, NL, NT, T <: AbstractTree{TT, RT, NL, NT}} = NT

"""
branchnametype(::AbstractTree)
Returns type of branch names from a branch type.
"""
branchnametype(::Type{<: AbstractTree}) = Int
branchnametype(::Type{<: AbstractNode}) = Int
branchnametype(::Type{<: AbstractBranch}) = Int
branchnametype(::Type{<: AbstractElt}) = Int

"""
branchtype(::Type{AbstractTree})
Returns type of branches from a tree type.
"""
branchtype(::Type{T}) where {TT, RT, NL, N, B <: AbstractBranch,
T <: AbstractTree{TT, RT, NL, N, B}} = B
branchtype(::Type{T}) where {TT, RT, NL, NT, BT <: AbstractElt,
T <: AbstractTree{TT, RT, NL, NT, BT}} = BT

"""
treenametype(::Type{AbstractTree})
Expand Down Expand Up @@ -1241,6 +1228,13 @@ function validate!(tree::T) where
return _validate!(tree)
end

"""
invalidate!(tree::AbstractTree, state = missing)
Confirm that the tree is no longer necessarily valid, and remove cache information.
"""
invalidate!(tree::AbstractTree, state = missing) = _invalidate!(tree, state)

"""
traversal(::AbstractTree, ::TraversalOrder)
traversal(::AbstractTree, ::TraversalOrder, init)
Expand Down
Loading

2 comments on commit 27c0d92

@richardreeve
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

Breaking changes

  • Add recursive tree, node and branch types, allowing type stability.
  • Note, this is a breaking change because the RootedTree and UnrootedTree types are now an alias for RecursiveTree, not LinkTree for efficiency.

Other changes

  • Improve testing, more type stability and validation

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/96688

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.0 -m "<description of version>" 27c0d921860db8947fae418fb2f1800b17210897
git push origin v0.5.0

Please sign in to comment.