arklumpus / TreeViewer

Cross-platform software to draw phylogenetic trees
GNU Affero General Public License v3.0
188 stars 9 forks source link

Searching for Modules/Further Transformations #35

Open eacattle opened 5 months ago

eacattle commented 5 months ago

Hi there! I'm using TreeViewer to simplify a very large (700+OTU) tree by collapsing clades down by species, but it becomes very cumbersome to try to undo any of these changes longer after-the-fact. the find function can help me navigate to the nodes I'm trying to make changes to on the tree display itself, but this doesn't seem to be a functionality that extends to transformations. Is there a way to search within transformations you've made, in the event you've made 300+ of them? I'm still new to TreeViewer, so it took me a long time to comb through them all by hand. Very robust program! Lots of wonderful functions.

arklumpus commented 5 months ago

Hi! Wow, that sounds like a tremendous task! How were the nodes collapsed? Did you just use the Collapse node further transformation?

eacattle commented 5 months ago

Hi there! Yes, it's a pretty comprehensive tree. Yes, I used collapse on further transformations and then also added a name attribute to show a new name for each collapsed clade.

Sincerely, Escher Cattle (He/Him) NCSU Graduate Student- Entomology

On Thu, May 30, 2024, 3:28 PM Giorgio Bianchini @.***> wrote:

Hi! Wow, that sounds like a tremendous task! How were the nodes collapsed? Did you just use the Collapse node further transformation?

— Reply to this email directly, view it on GitHub https://github.com/arklumpus/TreeViewer/issues/35#issuecomment-2140732536, or unsubscribe https://github.com/notifications/unsubscribe-auth/BDKKAN72SUZDC76H6OGYPWLZE54UHAVCNFSM6AAAAABIRKIE2CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNBQG4ZTENJTGY . You are receiving this because you authored the thread.Message ID: @.***>

arklumpus commented 5 months ago

Ah, I see... I think that adding the names actually made things more complicated for you 😅

Normally, you wouldn't need to manually find the module you need to disable, as clicking on the Toggle collapse button would do this for you. However, if you added a name to the node after having collapsed it, this will not work.

I think the easiest solution for this situation is a custom action script. To run this, click on the Custom script button in the Actions tab, and enter the following code (completely replacing the template):

Source code ```CSharp using System; using System.Threading.Tasks; using TreeViewer; using System.Collections.Generic; using PhyloTree; using System.Linq; namespace a9c1d7cd9ce034a2898ac8d376634524a { //Do not change class name public static class CustomCode { //Do not change method signature public static async Task PerformAction(MainWindow parentWindow, Action progressAction) { // Nodes that you want to de-collapse. string[] nodeNames = { "Node1", "Node2" }; // When a node is collapsed, two of its descendants are preserved, while the rest are deleted. // For each of the nodes you want to de-collapse, we now need to get the names of those two descendants. List[] preservedDescendants = new List[nodeNames.Length]; for (int i = 0; i < nodeNames.Length; i++) { preservedDescendants[i] = parentWindow.TransformedTree.GetNodeFromName(nodeNames[i]).GetLeafNames(); } // Now we need to find those Further Transformation modules that act on the nodes. // First, get all the Further Transformation modules that are currently enabled. List furtherTransformations = parentWindow.StateData.FurtherTransformationModules(); for (int i = 0; i < furtherTransformations.Count; i++) { if (furtherTransformations[i].Id == "3812314b-e821-4399-abfd-2a929a7a7d80") // Id for the "Collapse node" module. { // Get the node that is collapsed by the module (represented as a list of taxa whose LCA is the node in question). string[] nodeSelection = (string[])parentWindow.StateData.GetFurtherTransformationModulesParamters(i)["Node:"]; // We need to de-collapse this node if there is ANY element x of `preservedDescendants` (which is a list of two // leaf names) such that ALL those leaf names are present in the `nodeSelection` array. if (preservedDescendants.Any(x => x.All(y => nodeSelection.Contains(y)))) { parentWindow.StateData.RemoveFurtherTransformationModule(i); // Remove the module that was collapsing this node. furtherTransformations = parentWindow.StateData.FurtherTransformationModules(); // Update the list of modules. i--; // Go back by one to account for the module that has been removed. } } } // Update the plot. await parentWindow.UpdateFurtherTransformations(0); } } } ```

The main think you will need to change in the script is the nodeNames array in line 17, where the names of the nodes that you want to de-collapse are specified. Just add as many as you need there, then click on Run and those nodes should be de-collapsed. I added some comments to the code if you want to understand what it's doing, but you shouldn't need to worry about anything other than line 17.

I hope this works, let me know if it doesn't! For the future, a better solution would be to add the node names before collapsing the nodes; in this way, you would just need to click on the Toggle collapse button. Unfortunately, you can't simply reorder the modules, because unless you re-select all the collapsed nodes, the settings for the Collapse node button will not pick up the new node name.