Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix plotting #63

Merged
merged 15 commits into from
Oct 14, 2021
Merged

fix plotting #63

merged 15 commits into from
Oct 14, 2021

Conversation

mkborregaard
Copy link
Member

This has been languishing for some time.
I think I deleted the wrong branch, so my old PR disappeared, so I'm making a new one.
I'm adding a number of PRs now. I'm doing them sequentially - they build on each other - so they should also be merged and rebased sequentially. Let me know when / if I can merge.

@coveralls
Copy link

coveralls commented Oct 11, 2021

Pull Request Test Coverage Report for Build 1339497475

  • 7 of 67 (10.45%) changed or added relevant lines in 3 files are covered.
  • 102 unchanged lines in 13 files lost coverage.
  • Overall coverage increased (+1.8%) to 58.81%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/Interface.jl 0 1 0.0%
src/metrics.jl 7 26 26.92%
src/plot.jl 0 40 0.0%
Files with Coverage Reduction New Missed Lines %
src/Branch.jl 1 70.0%
src/newick.jl 1 76.78%
src/Iterators.jl 2 95.05%
src/TreeSet.jl 3 43.75%
src/routes.jl 5 63.64%
src/Tree.jl 5 81.71%
src/rand.jl 6 61.34%
src/API.jl 7 53.33%
src/Node.jl 8 39.29%
src/plot.jl 9 0%
Totals Coverage Status
Change from base Build 1170060355: 1.8%
Covered Lines: 1275
Relevant Lines: 2168

💛 - Coveralls

Copy link
Member

@richardreeve richardreeve left a comment

Choose a reason for hiding this comment

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

I think there may be some redundant code in here?

Returns the number of internal nodes of a single tree, or a Dict of numbers of nodes
for multiple trees.
"""
ninternal(tree::AbstractTree) = nnodes(tree) - nleaves(tree)
Copy link
Member

Choose a reason for hiding this comment

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

Is the root node internal?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes!
What I'm trying to address here is that people coming from R's ape library will be confused, because it distinguishes between "tips" (which you call "leaves") and "nodes" which are all the nodes that aren't tips! Phylo doesn't seem to have a concept for that, but I use it a lot - so that's why I suggest the name "internal" for these.

Copy link
Member Author

Choose a reason for hiding this comment

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

So ape:::Nnode(tree) + ape:::Ntip(tree) in R equals Phylo.nnodes(tree)!

Copy link
Member

Choose a reason for hiding this comment

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

Cool, okay. As I've said often, I'm not a phylogeneticist and I just wasn't sure whether the root was internal, but it obviously is...

src/metrics.jl Outdated
Comment on lines 16 to 35
function nodedepths(tree::Phylo.AbstractTree)
function finddepths!(clade::String, parentdepth::Float64 = 0.0)
mydepth = parentdepth
push!(names, clade)
if hasinbound(tree, clade)
mydepth += getlength(tree, getinbound(tree, clade))
end
depth[clade] = mydepth
for ch in getchildren(tree, clade)
finddepths!(ch, mydepth)
end
end

depth = Dict{String, Float64}()
names = String[]
sizehint!(depth, nnodes(tree))
sizehint!(names, nnodes(tree))
root = getnodename(tree, getroot(tree))
finddepths!(root)
depth, names
Copy link
Member

Choose a reason for hiding this comment

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

I haven't had time to check, but isn't this just heightstoroot()?

function heightstoroot(tree::AbstractTree)

Copy link
Member Author

Choose a reason for hiding this comment

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

Not exactly - nodedepths also includes internal nodes, heightstoroot is only for tips/leaves (although I agree that's not clear from the names). nodedepths is also quite a bit faster

julia> @btime heightstoroot(hummers)
  2.311 ms (4247 allocations: 383.22 KiB)

julia> @btime nodedepths(hummers)
  633.794 μs (2771 allocations: 111.23 KiB)

Copy link
Member

Choose a reason for hiding this comment

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

Okay, in that case can we move distance(), distances(), heighttoroot() and heightstoroot() into this file (I didn't really notice it appearing a few months ago) and rewrite heightstoroot() to call this? It seems unwise to have two functions with such overlapping functionality. We also ought to decide on whether we are going to call this measurement height or depth... we shouldn't use both.

Copy link
Member Author

Choose a reason for hiding this comment

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

I could rename _nodeheights to _nodedepths, nodedepths to nodeheights and heightstoroot to leafheights for consistency though?

Copy link
Member

Choose a reason for hiding this comment

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

I don't really understand what you're saying here. I was wondering if we could agree on a single name for distances inside the tree, but you seem to be suggesting switching heights and depths in different contexts?

Copy link
Member

Choose a reason for hiding this comment

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

@mkborregaard - I appreciate you're in a hurry! Why don't you do the renames you suggest, revise nodeheights() function with a leavesonly keyword, and just copy the heightstoroot() function across for now but don't do anything with it. If Claire's okay with it, we'll deprecate that, and if not, we'll rewrite it later to call nodeheights().

Copy link
Member Author

Choose a reason for hiding this comment

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

For now I could just keep my function nodeheight to do what it does and we can always deprecate heightstoroot later if it becomes redundant. I can unexport nodeheight for now to not confuse the interface.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, sorry - just saw your response. I wouldn't go with the symbols option, but I'm neutral about the other option. We could also add in a keyword to say what the height is relative to. I think all of these may be refinements for later though. The simpler answer would be just your leavesonly keyword - I'm happy with that for now. I'm (honestly!) trying not to add too much work here :)

Copy link
Member

Choose a reason for hiding this comment

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

I'd keep nodeheights() exported and add the keyword and we'll (very likely) deal with heightstoroot() later if Claire is okay with it being deprecated.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I've changed the names, and added onlyleaves and noleaves keywords - I guess it would be good to standardize on some keywords to use everywhere but we can discuss that. I implement the keywords by filtering after the fact, because we need to calculate all the values anyway.

I also return an AxisArray now for consistency. It makes the function run like 50% slower, which I guess isn't a disaster if it's important to get an AxisArray out.

I have also reimplemented heightstoroot to just be nodeheights(tree, onlyleaves = true), which makes it 15 times faster on the h1n1 tree while giving the exact same result.

julia> @btime heightstoroot(tree1) # old
  161.813 ms (39269 allocations: 3.51 MiB)

julia> @btime heightstoroot(tree1) # new
  11.970 ms (13699 allocations: 562.05 KiB)

@richardreeve richardreeve mentioned this pull request Oct 13, 2021
@mkborregaard
Copy link
Member Author

Ready to merge

Copy link
Member

@richardreeve richardreeve left a comment

Choose a reason for hiding this comment

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

Looks good - happy to merge with a couple of minor fixes except that it's still failing the 1.4 tests.

src/metrics.jl Outdated
end

"""
height(tree::AbstractTree, node)
Copy link
Member

Choose a reason for hiding this comment

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

Bug in the original docs:

Suggested change
height(tree::AbstractTree, node)
heighttoroot(tree::AbstractTree, node)

src/metrics.jl Outdated
end

"""
heights(tree::AbstractTree)
Copy link
Member

Choose a reason for hiding this comment

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

Bug in the original docs:

Suggested change
heights(tree::AbstractTree)
heightstoroot(tree::AbstractTree)

src/plot.jl Outdated
@@ -292,7 +292,7 @@ end


# a function to update a value successively from the root to the tips
function map_depthfirst(FUN, start, tree, eltype = nothing)
function map_heightfirst(FUN, start, tree, eltype = nothing)
Copy link
Member

Choose a reason for hiding this comment

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

Despite preferring heights for trees, I don't think anyone would fine heightfirst more intuitive than depthfirst for a search algorithm:

Suggested change
function map_heightfirst(FUN, start, tree, eltype = nothing)
function map_depthfirst(FUN, start, tree, eltype = nothing)

It's not clear to me this function is used incidentally.

@mkborregaard mkborregaard merged commit 9a98a56 into dev Oct 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants