From 39c97de2f7b8ef87b42f121f37d4f158d1651fe9 Mon Sep 17 00:00:00 2001 From: James Procter Date: Thu, 19 Oct 2023 18:27:33 +0100 Subject: [PATCH] JAL-4307 View->Ligands submenu, implementation for Jmol and documentation --- help/help/html/features/jmol.html | 6 +- help/markdown/releases/release-2_11_3_0.md | 1 + resources/lang/Messages.properties | 1 + .../api/structures/JalviewStructureDisplayI.java | 10 ++ src/jalview/ext/jmol/JalviewJmolBinding.java | 24 ++++- src/jalview/ext/jmol/JmolCommands.java | 25 +++++ src/jalview/gui/StructureViewerBase.java | 97 +++++++++++++++++++- src/jalview/jbgui/GStructureViewer.java | 6 ++ src/jalview/structure/StructureCommandsI.java | 5 + .../structures/models/AAStructureBindingModel.java | 15 +++ 10 files changed, 187 insertions(+), 3 deletions(-) diff --git a/help/help/html/features/jmol.html b/help/help/html/features/jmol.html index ac2489b..491a03f 100644 --- a/help/help/html/features/jmol.html +++ b/help/help/html/features/jmol.html @@ -160,7 +160,11 @@
  • Show Chains
    Select which of the PDB file's chains are to be displayed.
  • -
  • Colour by ..
    Submenu +
  • Ligands
    +
    When available, allows the display of all, none or specific + ligands (also known as HETATM groups) in the Jmol view, using CPK + spacefilling.
  • +
  • Colour by ..
    Submenu allowing specific alignment views to be selected for colouring associated chains in the structure display. This menu contains all the alignment views associated with the diff --git a/help/markdown/releases/release-2_11_3_0.md b/help/markdown/releases/release-2_11_3_0.md index 8847eb2..d7bdd25 100644 --- a/help/markdown/releases/release-2_11_3_0.md +++ b/help/markdown/releases/release-2_11_3_0.md @@ -19,6 +19,7 @@ channel: "release" - Visible adjuster marks to grab and adjust annotation panel height and id width - Adjustable ID margin when alignment is wrapped - Command line options and configurable bitmap export preferences for height, width and scale factor +- Show or hide ligands in a Jmol structure view via View Ligands submenu ### Improved support for working with computationally determined models - Alphafold red/orange/yellow/green colourscheme for structures diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 70eeb95..58f9805 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1468,3 +1468,4 @@ label.command_line_arguments = Command Line Arguments warning.using_old_command_line_arguments = It looks like you are using old command line arguments. These are now deprecated and will be removed in a future release of Jalview.\nFind out about the new command line arguments at\n warning.using_mixed_command_line_arguments = Jalview cannot use both old (-arg) and new (--arg) command line arguments. Please check your command line arguments.\ne.g. {0} and {1} warning.the_following_errors = The following errors and warnings occurred whilst processing files: +action.show_hetatm = Show Ligands (HETATM) diff --git a/src/jalview/api/structures/JalviewStructureDisplayI.java b/src/jalview/api/structures/JalviewStructureDisplayI.java index 532e545..77f2b6d 100644 --- a/src/jalview/api/structures/JalviewStructureDisplayI.java +++ b/src/jalview/api/structures/JalviewStructureDisplayI.java @@ -21,6 +21,8 @@ package jalview.api.structures; import java.io.File; +import java.util.Collections; +import java.util.List; import jalview.api.AlignmentViewPanel; import jalview.datamodel.PDBEntry; @@ -192,4 +194,12 @@ public interface JalviewStructureDisplayI File saveSession(); + /** + * + * @return heteroatoms in a form suitable for display and passing to command generator to display hetatms + */ + default List getHetatms() { + return Collections.EMPTY_LIST; + } + } diff --git a/src/jalview/ext/jmol/JalviewJmolBinding.java b/src/jalview/ext/jmol/JalviewJmolBinding.java index dc18369..c8ce3cd 100644 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@ -26,6 +26,8 @@ import java.awt.event.ComponentListener; import java.io.File; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -41,6 +43,8 @@ import org.jmol.api.JmolViewer; import org.jmol.c.CBK; import org.jmol.viewer.Viewer; +import com.google.common.collect.Lists; + import jalview.api.AlignmentViewPanel; import jalview.api.FeatureRenderer; import jalview.api.FeatureSettingsModelI; @@ -184,7 +188,25 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel // End StructureListener // ////////////////////////// - + + //////////////////////////// + // HETATM get + // + + @Override + public List getHetatmNames() + { + HashMap hetlist=new HashMap(); + for (int mc=0;mc hets = jmolViewer.ms.getHeteroList(mc); + hetlist.putAll(hets); + } + return Arrays.asList(hetlist.keySet().toArray(new String[0])); + } + // + //////////////////////////// + @Override public float[][] functionXY(String functionName, int x, int y) { diff --git a/src/jalview/ext/jmol/JmolCommands.java b/src/jalview/ext/jmol/JmolCommands.java index f9ba1e4..106d458 100644 --- a/src/jalview/ext/jmol/JmolCommands.java +++ b/src/jalview/ext/jmol/JmolCommands.java @@ -323,6 +323,31 @@ public class JmolCommands extends StructureCommandsBase "restore STATE \"" + Platform.escapeBackslashes(filePath) + "\""); } + @Override + public List showHetatms(List toShow) + { + // always clear the current hetero cpk display + + StringBuilder sb = new StringBuilder(); + sb.append("select hetero; cpk off;"); + + if (toShow != null && !toShow.isEmpty()) + { + // select what was requested + sb.append("select "); + boolean or = false; + for (String k : toShow) + { + sb.append(or ? " or " : " "); + sb.append(k); + or = true; + } + // and show as + sb.append("; cpk;"); + } + + return Arrays.asList(new StructureCommand(sb.toString())); + } /** * Obsolete method, only referenced from * jalview.javascript.MouseOverStructureListener diff --git a/src/jalview/gui/StructureViewerBase.java b/src/jalview/gui/StructureViewerBase.java index ed42ffa..09d2dcb 100644 --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@ -141,6 +141,8 @@ public abstract class StructureViewerBase extends GStructureViewer protected boolean allChainsSelected = false; + protected boolean allHetatmBeingSelected = false; + protected JMenu viewSelectionMenu; /** @@ -604,6 +606,80 @@ public abstract class StructureViewerBase extends GStructureViewer chainMenu.add(menuItem); } } + void setHetatmMenuItems(List hetatmNames) + { + hetatmMenu.removeAll(); + if (hetatmNames == null || hetatmNames.isEmpty()) + { + hetatmMenu.setVisible(false); + return; + } + hetatmMenu.setVisible(true); + allHetatmBeingSelected=false; + JMenuItem allMenuItem = new JMenuItem( + MessageManager.getString("label.all")); + JMenuItem noneMenuItem = new JMenuItem( + MessageManager.getString("label.none")); + allMenuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) { + { + allHetatmBeingSelected=true; + // Toggle state of everything - on + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + ((JCheckBoxMenuItem) hetatmMenu.getItem(i)).setSelected(true); + } + } + allHetatmBeingSelected=false; + showSelectedHetatms(); + } + }}); + + noneMenuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) { + { + allHetatmBeingSelected=true; + // Toggle state of everything off + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + ((JCheckBoxMenuItem) hetatmMenu.getItem(i)).setSelected(false); + } + } + allHetatmBeingSelected=false; + showSelectedHetatms(); + } + }}); + hetatmMenu.add(noneMenuItem); + hetatmMenu.add(allMenuItem); + + for (String chain : hetatmNames) + { + JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(chain, false); + menuItem.addItemListener(new ItemListener() + { + @Override + public void itemStateChanged(ItemEvent evt) + { + if (!allHetatmBeingSelected) + { + // update viewer only when we were clicked, not programmatically + // checked/unchecked + showSelectedHetatms(); + } + } + }); + + hetatmMenu.add(menuItem); + } + } /** * Action on selecting one of Jalview's registered colour schemes @@ -1009,6 +1085,7 @@ public abstract class StructureViewerBase extends GStructureViewer return; } setChainMenuItems(binding.getChainNames()); + setHetatmMenuItems(binding.getHetatmNames()); this.setTitle(binding.getViewerTitle(getViewerName(), true)); @@ -1158,7 +1235,25 @@ public abstract class StructureViewerBase extends GStructureViewer } getBinding().showChains(toshow); } - + /** + * Display selected hetatms in viewer + */ + protected void showSelectedHetatms() + { + List toshow = new ArrayList<>(); + for (int i = 0; i < hetatmMenu.getItemCount(); i++) + { + if (hetatmMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + JCheckBoxMenuItem item = (JCheckBoxMenuItem) hetatmMenu.getItem(i); + if (item.isSelected()) + { + toshow.add(item.getText()); + } + } + } + getBinding().showHetatms(toshow); + } /** * Tries to fetch a PDB file and save to a temporary local file. Returns the * saved file path if successful, or null if not. diff --git a/src/jalview/jbgui/GStructureViewer.java b/src/jalview/jbgui/GStructureViewer.java index 18e4c9f..fceb50c 100644 --- a/src/jalview/jbgui/GStructureViewer.java +++ b/src/jalview/jbgui/GStructureViewer.java @@ -52,6 +52,8 @@ public abstract class GStructureViewer extends JInternalFrame protected JMenu chainMenu; + protected JMenu hetatmMenu; + protected JMenu viewerActionMenu; protected JMenuItem alignStructs; @@ -152,6 +154,9 @@ public abstract class GStructureViewer extends JInternalFrame chainMenu = new JMenu(); chainMenu.setText(MessageManager.getString("action.show_chain")); + hetatmMenu = new JMenu(); + hetatmMenu.setText(MessageManager.getString("action.show_hetatm")); + fitToWindow = new JMenuItem(); fitToWindow.setText(MessageManager.getString("label.fit_to_window")); fitToWindow.addActionListener(new ActionListener() @@ -197,6 +202,7 @@ public abstract class GStructureViewer extends JInternalFrame savemenu.add(png); savemenu.add(eps); viewMenu.add(chainMenu); + viewMenu.add(hetatmMenu); helpMenu.add(helpItem); menuBar.add(fileMenu); diff --git a/src/jalview/structure/StructureCommandsI.java b/src/jalview/structure/StructureCommandsI.java index b1e1486..8ba94b0 100644 --- a/src/jalview/structure/StructureCommandsI.java +++ b/src/jalview/structure/StructureCommandsI.java @@ -21,6 +21,7 @@ package jalview.structure; import java.awt.Color; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -254,4 +255,8 @@ public interface StructureCommandsI StructureCommandI getResidueAttributes(String attName); List centerViewOn(List residues); + + default List showHetatms(List toShow) { + return Collections.EMPTY_LIST; + } } diff --git a/src/jalview/structures/models/AAStructureBindingModel.java b/src/jalview/structures/models/AAStructureBindingModel.java index dcedafa..55955a8 100644 --- a/src/jalview/structures/models/AAStructureBindingModel.java +++ b/src/jalview/structures/models/AAStructureBindingModel.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -2006,4 +2007,18 @@ public abstract class AAStructureBindingModel { return 0; } + + public List getHetatmNames() { + return Collections.EMPTY_LIST; + } + /** + * Generates and executes a command to show the given hetatm types as CPK + * + * @param toShow - one or more of strings from getHetatmNames + */ + public void showHetatms(List toShow) + { + executeCommands(commandGenerator.showHetatms(toShow), false, "Adjusting hetatm visibility"); + } + } -- 1.7.10.2