JAL-3390 Chimera showStructures() respects visible/chain selections
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 5 Aug 2019 12:00:32 +0000 (13:00 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 5 Aug 2019 12:00:32 +0000 (13:00 +0100)
src/jalview/appletgui/AppletJmol.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/StructureViewerBase.java
src/jalview/jbgui/GStructureViewer.java
src/jalview/structures/models/AAStructureBindingModel.java

index 3d1442d..f5ab595 100644 (file)
@@ -406,7 +406,8 @@ public class AppletJmol extends EmbmenuFrame implements
         }
       }
     }
-    jmb.centerViewer(toshow);
+    jmb.setChainsToShow(toshow);
+    jmb.centerViewer();
   }
 
   void closeViewer()
index 762b08e..e5a1733 100644 (file)
@@ -135,15 +135,12 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   /**
    * prepare the view for a given set of models/chains. chainList contains
    * strings of the form 'pdbfilename:Chaincode'
-   * 
-   * @param chainList
-   *          list of chains to make visible
    */
-  public void centerViewer(Vector<String> chainList)
+  public void centerViewer()
   {
     StringBuilder cmd = new StringBuilder(128);
     int mlength, p;
-    for (String lbl : chainList)
+    for (String lbl : chainsToShow)
     {
       mlength = 0;
       do
@@ -159,7 +156,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     {
       cmd.setLength(cmd.length() - 4);
     }
-    evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
+    String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
+    evalStateCommand(command);
   }
 
   public void closeViewer()
@@ -1419,8 +1417,9 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   @Override
-  public void showStructures(AlignViewportI av)
+  public void showStructures(AlignViewportI av, boolean refocus)
   {
     // TODO show Jmol structure optionally restricted to visible alignment
+    // and/or selected chains
   }
 }
index 6fa06d2..1731a05 100644 (file)
@@ -32,7 +32,6 @@ import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.datamodel.VisibleContigsIterator;
 import jalview.httpserver.AbstractRequestHandler;
 import jalview.io.DataSourceType;
 import jalview.schemes.ColourSchemeI;
@@ -54,6 +53,7 @@ import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collections;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -251,43 +251,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
-   * Tells Chimera to display only the specified chains
-   * 
-   * @param toshow
-   */
-  public void showChains(List<String> toshow)
-  {
-    /*
-     * Construct a chimera command like
-     * 
-     * ~display #*;~ribbon #*;ribbon :.A,:.B
-     */
-    StringBuilder cmd = new StringBuilder(64);
-    boolean first = true;
-    for (String chain : toshow)
-    {
-      int modelNumber = getModelNoForChain(chain);
-      String showChainCmd = modelNumber == -1 ? ""
-              : modelNumber + ":." + chain.split(":")[1];
-      if (!first)
-      {
-        cmd.append(",");
-      }
-      cmd.append(showChainCmd);
-      first = false;
-    }
-
-    /*
-     * could append ";focus" to this command to resize the display to fill the
-     * window, but it looks more helpful not to (easier to relate chains to the
-     * whole)
-     */
-    final String command = "~display #*; ~ribbon #*; ribbon :"
-            + cmd.toString();
-    sendChimeraCommand(command, false);
-  }
-
-  /**
    * Close down the Jalview viewer and listener, and (optionally) the associated
    * Chimera window.
    */
@@ -1324,20 +1287,20 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   @Override
-  public void showStructures(AlignViewportI av)
+  public void showStructures(AlignViewportI av, boolean refocus)
   {
     StringBuilder cmd = new StringBuilder(128);
     cmd.append("~display; ~ribbon;");
-    if (isShowAlignmentOnly())
+    String atomSpec = getMappedResidues(av);
+    cmd.append("ribbon ").append(atomSpec);
+    if (!isShowAlignmentOnly())
     {
-      String atomSpec = getMappedResidues(av);
-      cmd.append("ribbon ").append(atomSpec);
+      cmd.append("chain @CA|P; ribbon");
     }
-    else
+    if (refocus)
     {
-      cmd.append("chain @CA|P; ribbon");
+      cmd.append("; focus");
     }
-    cmd.append("; focus");
     sendChimeraCommand(cmd.toString(), false);
   }
 
@@ -1382,10 +1345,21 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
                   && alignment.findIndex(theSequence) > -1)
           {
             String chainCd = mapping.getChain();
-
-            // TODO only process sequence ranges within visible columns
-            VisibleContigsIterator visible = alignment.getHiddenColumns()
+            if (!isShowChain(mapping.getPdbId(), chainCd))
+            {
+              continue;
+            }
+            Iterator<int[]> visible;
+            if (isShowAlignmentOnly())
+            {
+              visible = alignment.getHiddenColumns()
                     .getVisContigsIterator(0, width, true);
+            }
+            else
+            {
+              visible = Collections.singletonList(new int[] { 0, width })
+                      .iterator();
+            }
             while (visible.hasNext())
             {
               int[] visibleRegion = visible.next();
index c847260..bdf4711 100644 (file)
@@ -459,9 +459,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                     af.setMenusForViewport();
                   }
 
+                  avp.setSelected(true);
                   AlignmentPanel ap = (AlignmentPanel) avp;
                   ap.updateLayout();
-                  ap.setSelected(true);
                   ap.alignFrame.setMenusForViewport();
                 }
               }
index b28b81c..9179be6 100644 (file)
@@ -42,9 +42,7 @@ import java.awt.event.ActionEvent;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Vector;
 
-import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JSplitPane;
 import javax.swing.SwingUtilities;
@@ -263,19 +261,8 @@ public class AppJmol extends StructureViewerBase
   @Override
   void showSelectedChains()
   {
-    Vector<String> toshow = new Vector<>();
-    for (int i = 0; i < chainMenu.getItemCount(); i++)
-    {
-      if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
-      {
-        JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
-        if (item.isSelected())
-        {
-          toshow.addElement(item.getText());
-        }
-      }
-    }
-    jmb.centerViewer(toshow);
+    setSelectedChains();
+    jmb.centerViewer();
   }
 
   @Override
index fd84b37..1a5ed5e 100644 (file)
@@ -50,7 +50,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 
-import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
@@ -363,19 +362,12 @@ public class ChimeraViewFrame extends StructureViewerBase
   @Override
   void showSelectedChains()
   {
-    List<String> toshow = new ArrayList<>();
-    for (int i = 0; i < chainMenu.getItemCount(); i++)
-    {
-      if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
-      {
-        JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
-        if (item.isSelected())
-        {
-          toshow.add(item.getText());
-        }
-      }
-    }
-    jmb.showChains(toshow);
+    setSelectedChains();
+
+    /*
+     * refresh display without resizing - easier to see what changed
+     */
+    jmb.showStructures(getAlignmentPanel().getAlignViewport(), false);
   }
 
   /**
index 47bc823..cc431ac 100644 (file)
@@ -718,7 +718,8 @@ public abstract class StructureViewerBase extends GStructureViewer
       public void actionPerformed(ActionEvent e)
       {
         getBinding().setShowAlignmentOnly(showAlignmentOnly.isSelected());
-        getBinding().showStructures(getAlignmentPanel().getAlignViewport());
+        getBinding().showStructures(getAlignmentPanel().getAlignViewport(),
+                true);
       }
     });
     viewMenu.add(showAlignmentOnly);
index 2094201..418e413 100644 (file)
@@ -28,6 +28,8 @@ import java.awt.BorderLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JInternalFrame;
@@ -270,4 +272,27 @@ public abstract class GStructureViewer extends JInternalFrame
   {
 
   }
+
+  /**
+   * Saves the selected entries in the 'View Chain' menu into a list. Entries are
+   * formatted as "pdbid:chainid". Only the selected chains should be drawn in the
+   * structure display.
+   */
+  protected void setSelectedChains()
+  {
+    List<String> chains = new ArrayList<>();
+    for (int i = 0; i < chainMenu.getItemCount(); i++)
+    {
+      JMenuItem menuItem = chainMenu.getItem(i);
+      if (menuItem instanceof JCheckBoxMenuItem)
+      {
+        JCheckBoxMenuItem item = (JCheckBoxMenuItem) menuItem;
+        if (item.isSelected())
+        {
+          chains.add(item.getText());
+        }
+      }
+    }
+    getBinding().setChainsToShow(chains);
+  }
 }
index 6159757..1fc59ed 100644 (file)
@@ -97,6 +97,13 @@ public abstract class AAStructureBindingModel
 
   private boolean showAlignmentOnly;
 
+  /*
+   * a list of chains "pdbid:chainid" to show in the viewer;
+   * empty means show all
+   */
+  // TODO make private once showStructures() deals with this
+  protected List<String> chainsToShow;
+
   /**
    * Data bean class to simplify parameterisation in superposeStructures
    */
@@ -137,6 +144,7 @@ public abstract class AAStructureBindingModel
   {
     this.ssm = ssm;
     this.sequence = seqs;
+    chainsToShow = new ArrayList<>();
   }
 
   /**
@@ -156,6 +164,8 @@ public abstract class AAStructureBindingModel
     this.nucleotide = Comparison.isNucleotide(sequenceIs);
     this.pdbEntry = pdbentry;
     this.protocol = protocol;
+    chainsToShow = new ArrayList<>();
+
     resolveChains();
   }
 
@@ -862,8 +872,10 @@ public abstract class AAStructureBindingModel
    * mapped to visible regions of the alignment.
    * 
    * @param alignViewportI
+   * @param refocus
+   *                         if true, refit the display to the viewer
    */
-  public void showStructures(AlignViewportI alignViewportI) 
+  public void showStructures(AlignViewportI alignViewportI, boolean refocus)
   {
     // override with implementation
   }
@@ -882,4 +894,32 @@ public abstract class AAStructureBindingModel
       colourBySequence(ap);
     }
   }
+
+  /**
+   * Sets the list of chains to display (as "pdbid:chain"), where an empty list
+   * means show all
+   * 
+   * @param chains
+   */
+  public void setChainsToShow(List<String> chains)
+  {
+    chainsToShow = chains;
+  }
+
+  /**
+   * Answers true if the specified structure and chain are selected to be shown in
+   * the viewer, else false
+   * 
+   * @param pdbId
+   * @param chainId
+   * @return
+   */
+  protected boolean isShowChain(String pdbId, String chainId)
+  {
+    if (chainsToShow.isEmpty())
+    {
+      return true;
+    }
+    return chainsToShow.contains(pdbId + ":" + chainId);
+  }
 }