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

Adding extra elements on tree plots #14

Open
andersonbrito opened this issue May 4, 2020 · 8 comments
Open

Adding extra elements on tree plots #14

andersonbrito opened this issue May 4, 2020 · 8 comments

Comments

@andersonbrito
Copy link

andersonbrito commented May 4, 2020

Hey, thank you for setting baltic up as a python package: the installation was much easier now. I installed it days ago, and since them I've been playing with its functionalities. I have a question about plotting extra elements on trees. I'm trying to achieve a result similar to this baltic figure.

The extra elements I want to plot are:

  1. Node markers indicating posterior probabilities
  2. tMRCA violin plots at internal nodes
  3. Date ticks in months
  4. A subtree, pruned from the imput tree

Concerning 1, I was wondering how I can achieve that using a function similar to plotPoints, but for nodes, not leaves.

Concerning 4, I tried to apply the function subtree, however, instead of getting a tree rooted at the selected commonAncestor tMRCA (2012.58), baltic is keeping the root of the original tree (1970.55). As a result, when using the cmap 'hsv', instead of having a gradient from blue to red, in the final plot I only see red/magenta hues (indicating the misplacement of the root decades before the expected).

Since I couldn't find specific instructions on austhecia or curonia, I was wondering if you have any examples on how to plot these elements.

Thank you.

Cheers

@gkarthik
Copy link
Contributor

gkarthik commented May 4, 2020

Hey!

  1. plotPoints() can be used to draw the posterior probability node markers. The default target function only filters the leaf_nodes.

You can customize and pass the following lambda functions to plotPoints(),

target=lambda k:k.branchType!='leaf'
size_function=lambda k: 50 if k.traits['posterior']>=0.5 else 10
colour_function=lambda k: "#000000" if k.traits['posterior']>=0.5 else "#ECECEC"

  1. Could you add the exact function call you used for subtree()?

@andersonbrito
Copy link
Author

andersonbrito commented May 4, 2020

Hey @gkarthik, thank you for your quick response.

For 1, your suggestion solved the issue! ✨ Thank you.

For 4, I've been defining the clade of interest from its ancestor, based a set of 42 target_tips.

keep_tips = [k.numName for k in treeFile.Objects if k.branchType == 'leaf' and k.name in target_tips]
ancestor = treeFile.commonAncestor(treeFile.getExternal(lambda k: k.numName in keep_tips))
subtree = treeFile.subtree(k=ancestor)

print(subtree.treeStats()) gives me this:

Tree height: 48.907069
Tree length: 90.130334
strictly bifurcating tree
annotations present

Numbers of objects in tree: 83 (41 nodes and 42 leaves)

and print(subtree.root.absoluteTime) shows 2010.2653139215834, which is actually the age of the parent node of the ancestor, not its expected tMRCA, which is 2012.58, height=6.87 (see long root and MRCA in this newly plotted subtree, with the posterior probabilities markers).

Any idea of what is wrong? 6.87 as height is the expected result, but baltic is using the original tree height (48.907069), despite ancestor being set as as the starting node of the subtree. It seems commonAncestor is returning the ancestor branch, not node.

@gkarthik
Copy link
Contributor

gkarthik commented May 4, 2020

The root of the tree is set to the mrca's parent. Could you confirm that len(subtree.root.children) is 1 and subtree.root.children[0].absoluteTime is 2012.58?

@andersonbrito
Copy link
Author

Correct:
len(subtree.root.children) = 1
subtree.root.children[0].absoluteTime = 2012.58

@gkarthik
Copy link
Contributor

gkarthik commented May 4, 2020

Seems like the parent of the mrca is the root of the entire tree?

A quick fix might be to pass a target lambda function excluding the root to plotTree.
target=lambda k: k != subtree.root.

@evogytis might have better suggestions (accounting for time zone differences 😄).

@andersonbrito
Copy link
Author

andersonbrito commented May 4, 2020

Thank you, @gkarthik.
I'm handling that using a pre-pruned tree in the meantime.

Do you have any suggestions concerning the points 2 (tMRCA violin plots) and 3 (Time ticks in months)?

@gkarthik
Copy link
Contributor

gkarthik commented May 4, 2020

  1. For the violin plots, I usually pull all the trees from the BEAST trees file and extract the height of the mrca. Following this, its a simple histogram that is shown in that figure. I have some ad hoc scripts lying around for this will see if I can dig them up.
  2. Haven't tested this much but this code should work to create tick labels at the first of every month of 2020 (01 Jan, 01 Feb .. ). You can modify it to fit the time interval you're considering.
import datetime as dt
new_ticks = [bt.decimalDate("2020-{}-01".format(i)) for i in range(1,13)]
new_tick_labels = ["01 "+dt.datetime.strptime("2020-{}-01".format(i), "%Y-%m-%d").strftime("%b") for i in range(1,13)]
ax.set_xticks(new_ticks)
ax.set_xticklabels(new_tick_labels)

@evogytis
Copy link
Owner

evogytis commented May 5, 2020

@gkarthik thanks for taking care of this! :)
1., 2., and 3. have been addressed well by Karthik. Let us know if you need code references for any of these.
4. The root of the subtree being the parent of the node you called subtree on is not a bug, but an intentional choice for producing the "exploded tree" plots with some branch length at its base. Admittedly, this is not ideal and this should ideally be an option (something like stem=True).
treeHeight being incorrect for the subtree is more worrying though, because the subtree function should only deep copy the branches that comprise the subtree and assign them to a completely new tree object which without a traversal should have treeHeight==0 by default. I can take a look at the data/code if neither is sensitive.

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

No branches or pull requests

3 participants