JAL-2844 entirely X coord based partitioning
[jalview.git] / src / jalview / ext / archaeopteryx / JalviewBinding.java
index e382364..1649b62 100644 (file)
@@ -1,18 +1,26 @@
 package jalview.ext.archaeopteryx;
 
+import jalview.analysis.Conservation;
+import jalview.api.AlignViewportI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
+import jalview.gui.AlignViewport;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 import jalview.gui.PaintRefresher;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeProperty;
+import jalview.schemes.UserColourScheme;
 import jalview.structure.SelectionSource;
 import jalview.structure.StructureSelectionManager;
+import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
+import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
@@ -29,9 +37,11 @@ import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
 import org.forester.archaeopteryx.MainFrame;
+import org.forester.archaeopteryx.TreePanelUtil;
 import org.forester.phylogeny.Phylogeny;
 import org.forester.phylogeny.PhylogenyMethods;
 import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.data.BranchColor;
 
 /**
  * Class for binding the Archaeopteryx tree viewer to the Jalview alignment that
@@ -56,6 +66,10 @@ public final class JalviewBinding
 
   private Map<PhylogenyNode, SequenceI> nodesBoundToSequences;
 
+  private float rootX;
+
+  private float furthestNodeX;
+
   /**
    * 
    * @param archaeopteryx
@@ -163,9 +177,13 @@ public final class JalviewBinding
         }
         else
         {
+
           partitionTree(e.getX());
       }
         PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
+
+
+
       }
     });
 
@@ -210,11 +228,22 @@ public final class JalviewBinding
         if (matchingNode != null)
         {
           treeView.getFoundNodes0().add(matchingNode.getId());
+
+
+          if (!matchingNode.getBranchData().isHasBranchColor())
+          {
+            Color foundNodesColour = treeView.getTreeColorSet()
+                    .getFoundColor0();
+          matchingNode.getBranchData()
+                    .setBranchColor(new BranchColor(foundNodesColour));
+
+          }
+
         }
 
       }
-      treeView.repaint();
 
+      treeView.repaint();
     }
 
 
@@ -229,31 +258,25 @@ public final class JalviewBinding
 
     if (!tree.isEmpty())
     {
-      double longestBranch = tree.calculateHeight(true);
-      if (longestBranch != 0)
+      // should be calculated on each partition as the tree can theoretically
+      // change in the meantime
+      PhylogenyNode furthestNode = PhylogenyMethods
+              .calculateNodeWithMaxDistanceToRoot(tree);
+      furthestNodeX = furthestNode.getXcoord();
+      rootX = tree.getRoot().getXcoord();
+
+      if (furthestNodeX != rootX && x < furthestNodeX) // don't bother if 0
+                                                       // distance tree or
+                                                       // clicked x lies outside
+                                                       // of tree
       {
         Graphics g = treeView.getGraphics();
         int panelHeight = treeView.getHeight();
-        int viewWidth = treeView.getWidth();
         g.drawLine(x, 0, x, panelHeight);
 
-        // double relativeTreeWidth = treeDepth / viewWidth;
-        //
-        // System.out.println(relativeTreeWidth);
-
-        double threshold = x / longestBranch;
-        System.out.println(threshold);
+        float threshold = (x - rootX) / (furthestNodeX - rootX);
         List<PhylogenyNode> foundNodes = getNodesAboveThreshold(threshold,
-                longestBranch, tree.getRoot());
-        for (PhylogenyNode foundNode : foundNodes)
-        {
-          System.out.println(foundNode);
-        }
-
-        // groupNodes(threshold, tree.getRoot(), longestBranch);
-
-
-
+                tree.getRoot());
 
       }
     }
@@ -262,42 +285,148 @@ public final class JalviewBinding
   }
 
   public List<PhylogenyNode> getNodesAboveThreshold(double threshold,
-          double treeLength, PhylogenyNode node)
+          PhylogenyNode node)
   {
 
     List<PhylogenyNode> nodesAboveThreshold = new ArrayList<>();
 
-    iterateNodesAboveThreshold(nodesAboveThreshold, threshold, treeLength,
+    parentAvport.setSelectionGroup(null);
+    parentAvport.getAlignment().deleteAllGroups();
+    parentAvport.clearSequenceColours();
+    if (parentAvport.getCodingComplement() != null)
+    {
+      parentAvport.getCodingComplement().setSelectionGroup(null);
+      parentAvport.getCodingComplement().getAlignment().deleteAllGroups();
+      parentAvport.getCodingComplement().clearSequenceColours();
+    }
+
+
+    colourNodesAboveThreshold(nodesAboveThreshold, threshold,
             node);
     return nodesAboveThreshold;
 
   }
 
-  private List<PhylogenyNode> iterateNodesAboveThreshold(
+  /**
+   * Partially refactored from TreeCanvas colourGroups (can be made nicer).
+   * 
+   * @param nodeList
+   * @param threshold
+   * @param treeLength
+   * @param node
+   * @return
+   */
+  private List<PhylogenyNode> colourNodesAboveThreshold(
           List<PhylogenyNode> nodeList, double threshold,
-          double treeLength, PhylogenyNode node)
+          PhylogenyNode node)
   {
+    // could also use PhylogenyMethods.getAllDescendants
     for (PhylogenyNode childNode : node.getDescendants())
     {
-      double nodeCutoff = childNode.calculateDistanceToRoot() / treeLength;
+      childNode.getBranchData()
+              .setBranchColor(new BranchColor(Color.black));
+      float nodeCutoff = (childNode.getXcoord() - rootX)
+              / (furthestNodeX - rootX);
 
       if (nodeCutoff > threshold)
       {
-        nodeList.add(node);
+        nodeList.add(childNode);
+
+        Color randomColor = new Color((int) (Math.random() * 255),
+                (int) (Math.random() * 255), (int) (Math.random() * 255));
+        TreePanelUtil.colorizeSubtree(childNode,
+                new BranchColor(randomColor));
+        List<PhylogenyNode> descendantNodes = childNode
+                .getAllExternalDescendants();
+        List<SequenceI> descendantSeqs = new ArrayList<>(); // .forEach instead?
+        for (PhylogenyNode descNode : descendantNodes)
+        {
+          descendantSeqs.add(nodesBoundToSequences.get(descNode));
+        }
+
+        SequenceGroup sg = new SequenceGroup(descendantSeqs, null, null,
+                true, true, false, 0,
+                parentAvport.getAlignment().getWidth() - 1);
+
+        ColourSchemeI cs = null;
+        if (parentAvport.getGlobalColourScheme() != null)
+        {
+          if (parentAvport.getGlobalColourScheme() instanceof UserColourScheme)
+          {
+            cs = new UserColourScheme(
+                    ((UserColourScheme) parentAvport.getGlobalColourScheme())
+                            .getColours());
+          }
+          else
+          {
+            cs = ColourSchemeProperty.getColourScheme(sg, ColourSchemeProperty
+                    .getColourName(parentAvport.getGlobalColourScheme()));
+          }
+        }
+        sg.setColourScheme(cs);
+        sg.getGroupColourScheme().setThreshold(
+                parentAvport.getResidueShading().getThreshold(),
+                parentAvport.isIgnoreGapsConsensus());
+        // sg.recalcConservation();
+        sg.setName("Tree Group:" + sg.hashCode());
+        sg.setIdColour(randomColor);
+
+        if (parentAvport.getGlobalColourScheme() != null
+                && parentAvport.getResidueShading().conservationApplied())
+        {
+          Conservation c = new Conservation("Group", sg.getSequences(null),
+                  sg.getStartRes(), sg.getEndRes());
+          c.calculate();
+          c.verdict(false, parentAvport.getConsPercGaps());
+          sg.cs.setConservation(c);
+        }
+
+        parentAvport.getAlignment().addGroup(new SequenceGroup(sg));
+        // TODO can we push all of the below into AlignViewportI?
+        final AlignViewportI codingComplement = parentAvport
+                .getCodingComplement();
+        if (codingComplement != null)
+        {
+          SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
+                  parentAvport,
+                  codingComplement);
+          if (mappedGroup.getSequences().size() > 0)
+          {
+            codingComplement.getAlignment().addGroup(mappedGroup);
+            for (SequenceI seq : mappedGroup.getSequences())
+            {
+              codingComplement.setSequenceColour(seq,
+                      randomColor.brighter());
+            }
+          }
+        }
+
+
       }
 
       else
       {
-      iterateNodesAboveThreshold(nodeList, threshold, treeLength,
+        colourNodesAboveThreshold(nodeList, threshold,
                 childNode);
       }
+    }
+
+    // GROSS
+    ((AlignViewport) parentAvport).getAlignPanel().updateAnnotation();
 
+    final AlignViewportI codingComplement = parentAvport
+            .getCodingComplement();
+    if (codingComplement != null)
+    {
+      ((AlignViewport) codingComplement).getAlignPanel().updateAnnotation();
     }
+
     return nodeList;
   }
 
 
 
+
   // public List<PhylogenyNode> groupNodes(float threshold, PhylogenyNode root,
   // double treeHeight)
   // {
@@ -444,9 +573,9 @@ public final class JalviewBinding
   // for (AlignmentPanel ap : PaintRefresher
   // .getAssociatedPanels(parentAvport.getSequenceSetId()))
   // {
-  // commands.add(sortAlignmentIn(ap.av.getAlignPanel()));
+  // commands.add(sortAlignmentIn(ap.parentAvport.getAlignPanel()));
   // }
-  // av.getAlignPanel().alignFrame.addHistoryItem(new CommandI()
+  // parentAvport.getAlignPanel().alignFrame.addHistoryItem(new CommandI()
   // {
   //
   // @Override
@@ -481,7 +610,7 @@ public final class JalviewBinding
   // }
   // });
   // for (AlignmentPanel ap : PaintRefresher
-  // .getAssociatedPanels(av.getSequenceSetId()))
+  // .getAssociatedPanels(parentAvport.getSequenceSetId()))
   // {
   // // ensure all the alignFrames refresh their GI after adding an undo item
   // ap.alignFrame.updateEditMenuBar();