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

SAWilsonBalding does not keep root node number convention #16

Open
rbouckaert opened this issue Sep 20, 2019 · 8 comments
Open

SAWilsonBalding does not keep root node number convention #16

rbouckaert opened this issue Sep 20, 2019 · 8 comments

Comments

@rbouckaert
Copy link
Member

This may be a minor issue, but by convention, trees are assumed to have root node as highest numbered node, but the SAWilsonBalding operator can propose trees with root nodes of lower number since it calls Tree.setRootOnly() instead of Tree.setRoot() and the former does not automatically reorder nodes. The comment in the Tree says exactly that, but it gives no explanation why, so I am not sure why Tree.setRoot() is not called. Please let me know if you know why.

If an SAWilsonBalding proposal is followed by a NodeReight proposal in a StarBeast2 analysis, the latter does call Tree.setRoot() and changes node order so the root is highest numbered.

Perhaps other operators (SAExchange?) behave the same.

I bumped into this issue trying to find out why some caching issue on metadata of the species tree failed and caused a bit of trouble to identify the root, which I expected to be the highest numbered node.

@alexeid
Copy link
Member

alexeid commented Sep 20, 2019 via email

@rbouckaert
Copy link
Member Author

The reason it is convenient to have root as highest number is so that meta data attached to branches can be stored in parameters with indices 0...2N-2 for N taxa, like for branch rates in clock models. If the root cannot be relied upon to have number 2N-1, it will require more effort to map metadata to branches. Also, it means the relaxed clocks with sampled ancestors on a gene tree node may run into problems in the current implementation.

At the moment, Operators manipulate individual nodes, not the tree itself. Since nodes can have children added or removed (I think any reasonable API for nodes should allow this), that allows the tree to be left in an invalid state during the proposal() method. It will be hard to prevent operator implementation not to use such API.

What is not clear to me is why SAWilsonBalding calls Tree.setRootOnly() instead of Tree.setRoot(), which might solve this issue.

@alexeid
Copy link
Member

alexeid commented Sep 20, 2019 via email

@gavryushkina
Copy link
Contributor

What is not clear to me is why SAWilsonBalding calls Tree.setRootOnly() instead of Tree.setRoot(), which might solve this issue.

I don't remember why it is so but it was definitely for a reason. So changing to Tree.setRoot() may lead to some problems. Sorry I can't help currently with figuring this out.

@alexeid
Copy link
Member

alexeid commented Sep 24, 2019 via email

@rbouckaert
Copy link
Member Author

Removing the SAWilsonBalding operator from the XML solved my particular issue, so other SA operators appear to be no problem.

Tree.setRoot() calls getNodeCount(), which might have returned a different number of nodes in a past implementation where SA-trees were not binary trees with zero branch lengths for ancestral nodes. That might explain why Tree.setRootOnly() is called instead of Tree.setRoot(). Does that ring a bell?

Since SA-trees are now implemented as binary trees, this should not be a problem any more.

@alexeid
Copy link
Member

alexeid commented Sep 25, 2019 via email

@Anaphory
Copy link

Anaphory commented Jul 20, 2021

I ran into this issue these days with the Optimized Relaxed Clock. It took me a while to figure out why I had certain issues.

I have documented my attempts at fixing or at least mitigating the issue in CompEvol/beast2#984, but I got the impression that the core of the issue on the SA side is this order of operations:

if (jP != null) {
jP.removeChild(j); // remove <jP, j>
jP.addChild(iP); // add <jP, iP>
jP.makeDirty(Tree.IS_FILTHY);
} else {
iP.setParent(null); // completely remove <PiP, iP>
tree.setRootOnly(iP);
}
iP.addChild(j);

It could maybe be solved by pulling the

         iP.addChild(j);

into the two branches of the if, to be able to put it before the tree.setRootOnly(iP); (or then instead tree.setRoot(iP)) in the else block.

Anaphory added a commit to Anaphory/sampled-ancestors that referenced this issue Jul 21, 2021
This should fix one of the symptoms of CompEvol/beast2#984 and also CompEvol#16
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

4 participants