X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fext%2Farchaeopteryx%2FJalviewBinding.java;h=41d18f5759c6754c09eb165060704b04275ccffc;hb=edf34f58d16e4fa687d4b8ed5d83513178da1387;hp=95c07ef6d304041ca865c9ae0d2464cc76b91211;hpb=3ac81fd809de84210546a5cd39bab1778320488e;p=jalview.git diff --git a/src/jalview/ext/archaeopteryx/JalviewBinding.java b/src/jalview/ext/archaeopteryx/JalviewBinding.java index 95c07ef..41d18f5 100644 --- a/src/jalview/ext/archaeopteryx/JalviewBinding.java +++ b/src/jalview/ext/archaeopteryx/JalviewBinding.java @@ -1,22 +1,34 @@ package jalview.ext.archaeopteryx; +import jalview.analysis.AlignmentSorter; +import jalview.analysis.Conservation; +import jalview.api.AlignViewportI; +import jalview.commands.CommandI; +import jalview.commands.OrderCommand; 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.AlignmentPanel; 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.Graphics; +import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -26,11 +38,14 @@ import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; import org.forester.archaeopteryx.MainFrame; 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 @@ -43,6 +58,8 @@ import org.forester.phylogeny.PhylogenyNode; public final class JalviewBinding implements ExternalTreeViewerBindingI { + private final MainFrame aptxFrame; + private org.forester.archaeopteryx.TreePanel treeView; private AlignmentViewport parentAvport; @@ -51,10 +68,20 @@ public final class JalviewBinding private final StructureSelectionManager ssm; + private AlignmentPanel[] associatedPanels; + private Map sequencesBoundToNodes; private Map nodesBoundToSequences; + private float rootX; + + private float furthestNodeX; + + private int nrTreeGroups = 0; + + private boolean applyToAllViews = false; + /** * * @param archaeopteryx @@ -82,10 +109,11 @@ public final class JalviewBinding MessageManager.getString("label.tabs_detected_archaeopteryx"), MessageManager.getString("label.problem_reading_tree_file"), JvOptionPane.WARNING_MESSAGE); - ; + } // deal with/prohibit null values here as that will cause problems + aptxFrame = archaeopteryx; parentAvport = jalviewAlignmentViewport; sequencesBoundToNodes = alignMappedToNodes; nodesBoundToSequences = nodesMappedToAlign; @@ -96,7 +124,22 @@ public final class JalviewBinding ssm.addSelectionListener(this); treeView.addMouseListener(this); + PaintRefresher.Register(treeView, parentAvport.getSequenceSetId()); + associatedPanels = PaintRefresher + .getAssociatedPanels(parentAvport.getSequenceSetId()); + + aptxFrame.addInternalFrameListener(new InternalFrameAdapter() + { + + @Override + public void internalFrameClosed(InternalFrameEvent e) + { + AptxInit.getAllAptxFrames().remove(aptxFrame); + ssm.removeSelectionListener(JalviewBinding.this); + } + + }); treeTabs.addChangeListener(new ChangeListener() { @@ -134,6 +177,8 @@ public final class JalviewBinding @Override public void actionPerformed(ActionEvent e) { + // aptxFrame.actionPerformed(e); + } @Override @@ -161,11 +206,14 @@ public final class JalviewBinding } else { - partitionTree(e.getX()); + partitionTree(e.getX()); } - PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId()); + treeView.repaint(); + + + } }); @@ -204,17 +252,29 @@ public final class JalviewBinding treeView.setFoundNodes0( new HashSet(seqsel.getSequences().size())); + for (SequenceI selectedSequence : seqsel.getSequences()) { PhylogenyNode matchingNode = sequencesBoundToNodes.get(selectedSequence); 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,22 +289,209 @@ public final class JalviewBinding if (!tree.isEmpty()) { - double treeDepth = tree.calculateHeight(true); - if (treeDepth != 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 < 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(); - g.drawLine(x, 0, x, panelHeight); - int viewWidth = treeView.getWidth(); - float threshold = (float) x / (float) viewWidth; + float threshold = (x - rootX) / (furthestNodeX - rootX); + List foundNodes = getNodesAboveThreshold(threshold, + tree.getRoot()); } } } - + + public List getNodesAboveThreshold(double threshold, + PhylogenyNode node) + { + + List nodesAboveThreshold = new ArrayList<>(); + + 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; + + } + + /** + * Partially refactored from TreeCanvas colourGroups (can be made nicer). + * + * @param nodeList + * @param threshold + * @param treeLength + * @param node + * @return + */ + private List colourNodesAboveThreshold( + List nodeList, double threshold, + PhylogenyNode node) + { + + for (PhylogenyNode childNode : node.getDescendants()) + { + childNode.getBranchData() + .setBranchColor(new BranchColor(Color.black)); + float nodeCutoff = (childNode.getXcoord() - rootX) + / (furthestNodeX - rootX); + + if (nodeCutoff > threshold) + { + nodeList.add(childNode); + + Color randomColour = new Color((int) (Math.random() * 255), + (int) (Math.random() * 255), (int) (Math.random() * 255)); + childNode.getBranchData() + .setBranchColor(new BranchColor(randomColour)); + + List groupSeqs = new ArrayList<>(); + SequenceI seq = nodesBoundToSequences.get(childNode); + if (seq != null) + { + groupSeqs.add(seq); + parentAvport.setSequenceColour(seq, randomColour); + } + + List descendantNodes = PhylogenyMethods + .getAllDescendants(childNode); + // .forEach instead? + for (PhylogenyNode descNode : descendantNodes) + { + seq = nodesBoundToSequences.get(descNode); + if (seq != null) + { + groupSeqs.add(seq); + parentAvport.setSequenceColour(seq, randomColour); + } + + descNode.getBranchData() + .setBranchColor(new BranchColor(randomColour)); + } + + if (groupSeqs != null) + { + nrTreeGroups++; + groupThresholdSequences(groupSeqs, randomColour); + }} + + else + { + colourNodesAboveThreshold(nodeList, threshold, childNode); + } + } + + + for (AlignmentPanel associatedPanel : associatedPanels) { + + associatedPanel.updateAnnotation(); + + final AlignViewportI codingComplement = associatedPanel.getAlignViewport() + .getCodingComplement(); + if (codingComplement != null) + { + // GROSS + ((AlignViewport) codingComplement).getAlignPanel() + .updateAnnotation(); + } + } + + + return nodeList; + } + + public void groupThresholdSequences(List groupedSeqs, + Color groupColour) + { + SequenceGroup treeGroup = new SequenceGroup(groupedSeqs, 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(treeGroup, + ColourSchemeProperty.getColourName( + parentAvport.getGlobalColourScheme())); + } + + } + treeGroup.setColourScheme(cs); + treeGroup.getGroupColourScheme().setThreshold( + parentAvport.getResidueShading().getThreshold(), + parentAvport.isIgnoreGapsConsensus()); + + treeGroup.setName("Tree Group " + nrTreeGroups); + treeGroup.setIdColour(groupColour); + + for (AlignmentPanel associatedPanel : associatedPanels) + { + AlignViewportI altViewport = associatedPanel + .getAlignViewport(); + + if (altViewport.getGlobalColourScheme() != null + && altViewport.getResidueShading() + .conservationApplied()) + { + Conservation conserv = new Conservation(treeGroup.getName(), + treeGroup.getSequences(null), treeGroup.getStartRes(), + treeGroup.getEndRes()); + conserv.calculate(); + conserv.verdict(false, altViewport.getConsPercGaps()); + treeGroup.getGroupColourScheme().setConservation(conserv); + } + + altViewport.getAlignment().addGroup(treeGroup); + // TODO can we push all of the below into AlignViewportI? + final AlignViewportI codingComplement = altViewport + .getCodingComplement(); + if (codingComplement != null) + { + SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(treeGroup, + parentAvport, codingComplement); + if (mappedGroup.getSequences().size() > 0) + { + codingComplement.getAlignment().addGroup(mappedGroup); + for (SequenceI seq : mappedGroup.getSequences()) + { + codingComplement.setSequenceColour(seq, groupColour.brighter()); + } + } + } + + } + + } /** * may or may not need an extra repaint on the alignment view (check what kira @@ -288,6 +535,8 @@ public final class JalviewBinding @Override public void showMatchingChildSequences(final PhylogenyNode parentNode) { + // redundancy here, Forester already iterates through tree to get all + // descendants List childNodes = PhylogenyMethods .getAllDescendants(parentNode); @@ -336,79 +585,94 @@ public final class JalviewBinding } } - public void sortByTree_actionPerformed() { - // parentAvport.mirrorCommand(command, undo, ssm, source); - // alignFrame + @Override + public void sortByTree_actionPerformed()// modify for Aptx + { + + // if (treeCanvas.applyToAllViews) + // { + // final ArrayList commands = new ArrayList<>(); + // for (AlignmentPanel ap : PaintRefresher + // .getAssociatedPanels(parentAvport.getSequenceSetId())) + // { + // commands.add(sortAlignmentIn(ap.av.getAlignPanel())); + // } + // parentAvport.getAlignPanel().alignFrame.addHistoryItem(new CommandI() + // { + // + // @Override + // public void undoCommand(AlignmentI[] views) + // { + // for (CommandI tsort : commands) + // { + // tsort.undoCommand(views); + // } + // } + // + // @Override + // public int getSize() + // { + // return commands.size(); + // } + // + // @Override + // public String getDescription() + // { + // return "Tree Sort (many views)"; + // } + // + // @Override + // public void doCommand(AlignmentI[] views) + // { + // + // for (CommandI tsort : commands) + // { + // tsort.doCommand(views); + // } + // } + // }); + // for (AlignmentPanel ap : PaintRefresher + // .getAssociatedPanels(av.getSequenceSetId())) + // { + // // ensure all the alignFrames refresh their GI after adding an undo item + // ap.alignFrame.updateEditMenuBar(); + // } + // } + // else + // { + // treeCanvas.ap.alignFrame // .addHistoryItem(sortAlignmentIn(treeCanvas.ap)); - + // } + } - - /** - * sort the associated alignment view by the current tree. - * - * @param e - */ - // @Override - // public void sortByTree_actionPerformed()// modify for Aptx - // { - // - // // if (treeCanvas.applyToAllViews) - // - // final ArrayList commands = new ArrayList<>(); - // for (AlignmentPanel ap : PaintRefresher - // .getAssociatedPanels(parentAvport.getSequenceSetId())) - // { - // commands.add(sortAlignmentIn(ap.av.getAlignPanel())); - // } - // av.getAlignPanel().alignFrame.addHistoryItem(new CommandI() - // { - // - // @Override - // public void undoCommand(AlignmentI[] views) - // { - // for (CommandI tsort : commands) - // { - // tsort.undoCommand(views); - // } - // } - // - // @Override - // public int getSize() - // { - // return commands.size(); - // } - // - // @Override - // public String getDescription() - // { - // return "Tree Sort (many views)"; - // } - // - // @Override - // public void doCommand(AlignmentI[] views) - // { - // - // for (CommandI tsort : commands) - // { - // tsort.doCommand(views); - // } - // } - // }); - // for (AlignmentPanel ap : PaintRefresher - // .getAssociatedPanels(av.getSequenceSetId())) - // { - // // ensure all the alignFrames refresh their GI after adding an undo item - // ap.alignFrame.updateEditMenuBar(); - // } - // } - // else - // { - // treeCanvas.ap.alignFrame - // .addHistoryItem(sortAlignmentIn(treeCanvas.ap)); - // } + public CommandI sortAlignmentIn(AlignmentPanel ap) + { + // TODO: move to alignment view controller + + AlignmentViewport viewport = ap.av; + SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray(); + try + { + AlignmentSorter.sortByTree(viewport.getAlignment(), + nodesBoundToSequences, + treeView.getPhylogeny()); + CommandI undo; + undo = new OrderCommand("Tree Sort", oldOrder, + viewport.getAlignment()); + + ap.paintAlignment(true, false); + return undo; + } catch (Exception e) + { + System.err.println(e.getMessage()); + } + return null; + + } + /** @@ -439,6 +703,17 @@ public final class JalviewBinding { this.parentAvport = parentAvport; } + + public AlignmentPanel[] getAssociatedPanels() + { + return associatedPanels; + } + + public void setAssociatedPanels(AlignmentPanel[] associatedPanels) + { + this.associatedPanels = associatedPanels; + } + }