From 18415b6a6cc83bc4eac8b734fc6453136ccd9dbd Mon Sep 17 00:00:00 2001 From: Renia Correya Date: Tue, 8 Oct 2024 12:22:06 +0100 Subject: [PATCH] JAL-4435 Reformatting tree node labels and tree sub group names --- src/jalview/analysis/AlignmentUtils.java | 29 ++++++- .../SecondaryStructureDistanceModel.java | 8 +- src/jalview/gui/TreeCanvas.java | 90 ++++++++++++++++++-- src/jalview/util/Constants.java | 12 +++ 4 files changed, 127 insertions(+), 12 deletions(-) diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index 31670fd..41e491c 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -38,6 +38,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.Vector; +import java.util.stream.Collectors; import jalview.api.AlignCalcWorkerI; import jalview.bin.Console; @@ -3202,4 +3203,30 @@ public class AlignmentUtils } return false; } -} + + // Method to get the key for a given provider value + public static String getProviderKey(String providerValue) { + for (Map.Entry entry : Constants.STRUCTURE_PROVIDERS.entrySet()) { + if (entry.getValue().equals(providerValue)) { + return entry.getKey(); // Return the key (abbreviation) for the matching provider value + } + } + return null; // Return null if no match is found + } + + public static String reduceLabelLength(String label) { + // Split the input by " | " + String[] parts = label.split(" \\| "); + + // Map the full names to their abbreviations + String reducedLabel = Arrays.stream(parts) + .map(fullName -> Constants.STRUCTURE_PROVIDERS.entrySet().stream() + .filter(entry -> entry.getValue().equals(fullName)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(fullName)) // Use fullName if no abbreviation is found + .collect(Collectors.joining(" | ")); + + return reducedLabel; // Return the reduced label if abbreviations were applied + } +} \ No newline at end of file diff --git a/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java b/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java index 6ed94b2..52a60d1 100644 --- a/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java +++ b/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java @@ -130,7 +130,8 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel newSequences.add(alSeq); if (alSeq != null) { - labels.add("No Secondary Structure"); + //labels.add("No Secondary Structure"); + labels.add(Constants.STRUCTURE_PROVIDERS.get("None")); } SeqCigar newSeqCigar = scig; // new SeqCigar(scig); newCigs.add(newSeqCigar); @@ -142,8 +143,9 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel { if (alSeq != null) { - labels.add(AlignmentUtils - .extractSSSourceFromAnnotationDescription(ssec.get(i))); + String provider = AlignmentUtils.extractSSSourceFromAnnotationDescription(ssec.get(i)); + //String providerAbbreviation = AlignmentUtils.getProviderKey(provider); + labels.add(provider); } // newSequences.add(seq); newSequences.add(alSeq); diff --git a/src/jalview/gui/TreeCanvas.java b/src/jalview/gui/TreeCanvas.java index 08ecba6..49b569a 100755 --- a/src/jalview/gui/TreeCanvas.java +++ b/src/jalview/gui/TreeCanvas.java @@ -51,6 +51,7 @@ import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; +import jalview.analysis.AlignmentUtils; import jalview.analysis.Conservation; import jalview.analysis.TreeModel; import jalview.api.AlignViewportI; @@ -112,6 +113,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, int offy; private float threshold; + + int labelLengthThreshold = 4; String longestName; @@ -127,6 +130,9 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, BinaryNode highlightNode; boolean applyToAllViews = false; + + //Map to store label positions (BinaryNode -> List of bounding rectangles for the label) + private Map> labelBoundsMap = new HashMap<>(); /** * Creates a new TreeCanvas object. @@ -285,7 +291,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, */ public void drawNode(Graphics g, BinaryNode node, double chunk, double wscale, int width, int offx, int offy) - { + { if (node == null) { return; @@ -441,10 +447,41 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, } if (node.hasLabel()) { - nodeLabel = node.getLabel() + " " + nodeLabel; + String label = node.getLabel(); + + if(label.length() > labelLengthThreshold) { + + //label = AlignmentUtils.reduceLabelLength(label); + } + + nodeLabel = label + " | " + nodeLabel; + + // Split the nodeLabel by "|" + String[] lines = nodeLabel.split("\\|"); + + // Iterate over the lines and draw each line separately + String longestLabelString = ""; + int i = 0; + for (i = 0; i < lines.length; i++) { + g.drawString(lines[i].trim(), xstart + 2, ypos - 2 - (i * fm.getHeight())); + if(longestLabelString.length() < lines[i].trim().length()) { + longestLabelString = lines[i].trim(); + } + } + + int labelWidth = fm.stringWidth(longestLabelString); + int labelHeight = fm.getHeight() * (i-1); + + // Calculate the bounding box of the string + int xLabelPos = xstart + 2; + int yLabelPos = ypos - 2; + Rectangle labelBounds = new Rectangle(xLabelPos, yLabelPos - labelHeight, labelWidth, labelHeight); + + // Add the bounding box to the map for this node (list allows multiple bounding boxes) + labelBoundsMap.computeIfAbsent(node, k -> new ArrayList<>()).add(labelBounds); } - if (!nodeLabel.equals("")) + else if (!nodeLabel.equals("")) { g.drawString(nodeLabel, xstart + 2, ypos - 2); } @@ -936,6 +973,10 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, av.setCurrentTree(tree); Object ob = findElement(evt.getX(), evt.getY()); + + // Get mouse coordinates + int mouseX = evt.getX(); + int mouseY = evt.getY(); if (ob instanceof BinaryNode) { @@ -946,13 +987,35 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, } else - { + { + if (highlightNode != null) { highlightNode = null; setToolTipText(null); repaint(); } + + // Iterate through the map of label bounding boxes + for (Map.Entry> entry : labelBoundsMap.entrySet()) { + BinaryNode node = entry.getKey(); + List boundsList = entry.getValue(); + + // Check each bounding box for this node + for (Rectangle labelBounds : boundsList) { + if (labelBounds.contains(mouseX, mouseY)) { + // Show tooltip for this node's label + String nodeLabel = node.getDisplayName(); + this.setToolTipText(nodeLabel); + repaint(); + return; // Exit once we find a matching label + } + } + } + // Clear tooltip if no label is hovered + setToolTipText(null); + repaint(); + } } @@ -1075,7 +1138,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, gatherLabelsTo(groups.get(i), l); if (!tp.isColumnWise()) { - createSeqGroupFor(aps, l, col); + createSeqGroupFor(aps, l, col, groups.get(i).getLabel()); } else { @@ -1137,7 +1200,12 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, sb.append(" | "); } first = false; +// if(labelsForNode.size()>1) { +// String providerAbbreviation = AlignmentUtils.getProviderKey(label); +// sb.append(providerAbbreviation); +// } sb.append(label); + } binaryNode.setLabel(sb.toString()); } @@ -1299,7 +1367,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, } public void createSeqGroupFor(AlignmentPanel[] aps, Vector l, - Color col) + Color col, String label) { Vector sequences = new Vector<>(); @@ -1317,8 +1385,14 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, ColourSchemeI cs = null; SequenceGroup _sg = new SequenceGroup(sequences, null, cs, true, true, false, 0, av.getAlignment().getWidth() - 1); - - _sg.setName("JTreeGroup:" + _sg.hashCode()); + + if(label != null && !label.isEmpty()) { + label = AlignmentUtils.reduceLabelLength(label); + _sg.setName("JTreeGroup:" + label); + } + else { + _sg.setName("JTreeGroup:" + _sg.hashCode()); + } _sg.setIdColour(col); for (int a = 0; a < aps.length; a++) diff --git a/src/jalview/util/Constants.java b/src/jalview/util/Constants.java index 5f01895..b8afeeb 100644 --- a/src/jalview/util/Constants.java +++ b/src/jalview/util/Constants.java @@ -59,4 +59,16 @@ public class Constants // Secondary structure consensus label public static final String SECONDARY_STRUCTURE_CONSENSUS_LABEL = "Secondary Structure Consensus"; + + //A map that stores abbreviations of structure providers as keys and their full names as values. + public static final Map STRUCTURE_PROVIDERS = new HashMap<>(); + + static { + STRUCTURE_PROVIDERS.put("None", "No Secondary Structure"); + STRUCTURE_PROVIDERS.put("AF", "AlphaFold DB"); + STRUCTURE_PROVIDERS.put("SM", "SWISS-MODEL"); + STRUCTURE_PROVIDERS.put("PDB", "PDB"); + STRUCTURE_PROVIDERS.put("JP", "JPred"); + STRUCTURE_PROVIDERS.put("AFill", "AlphaFill"); + } } -- 1.7.10.2