JAL-1757 match only first altloc CA in PDB structure for superposition
[jalview.git] / src / jalview / ext / rbvi / chimera / JalviewChimeraBinding.java
index 1434c76..98f2e1a 100644 (file)
@@ -23,7 +23,6 @@ package jalview.ext.rbvi.chimera;
 import java.awt.Color;
 import java.net.BindException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -41,6 +40,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.httpserver.AbstractRequestHandler;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.AtomSpec;
@@ -53,6 +53,8 @@ import jalview.util.MessageManager;
 
 public abstract class JalviewChimeraBinding extends AAStructureBindingModel
 {
+  // Chimera clause to exclude alternate locations in atom selection
+  private static final String NO_ALTLOCS = "&~@.B-Z&~@.2-9";
 
   private static final boolean debug = false;
 
@@ -70,7 +72,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   /*
    * Object which listens to Chimera notifications
    */
-  private ChimeraListener chimeraListener;
+  private AbstractRequestHandler chimeraListener;
 
   /*
    * set if chimera state is being restored from some source - instructs binding
@@ -625,9 +627,12 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
         // TODO: handle sub-models
         command.append(selcom[pdbfnum]);
         command.append("@" + atomSpec[pdbfnum]);
+        // JAL-1757 exclude alternative CA locations
+        command.append(NO_ALTLOCS);
         command.append(" #" + refStructure /* +".1" */);
         command.append(selcom[refStructure]);
         command.append("@" + atomSpec[refStructure]);
+        command.append(NO_ALTLOCS);
       }
       if (selectioncom.length() > 0)
       {
@@ -931,58 +936,43 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    */
   public void highlightChimeraSelection()
   {
+    /*
+     * Ask Chimera for its current selection
+     */
     List<String> selection = viewer.getSelectedResidueSpecs();
-    // System.out.println("Chimera selection: " + selection.toString());
 
-    // TODO handle more than one!!
-    if (selection.size() > 0)
-    {
-      highlightChimeraSelection(selection);
-    }
-  }
-
-  private void log(String message)
-  {
-    System.err.println("## Chimera log: " + message);
-  }
-
-  private void viewerCommandHistory(boolean enable)
-  {
-    // log("(Not yet implemented) History "
-    // + ((debug || enable) ? "on" : "off"));
-  }
-
-  /**
-   * Propagate atom selections from Chimera
-   * 
-   * @param atoms
-   *          for example "#0:70.A" (model/residue/chain)
-   */
-  public void highlightChimeraSelection(List<String> atoms)
-  {
+    /*
+     * Parse model number, residue and chain for each selected position,
+     * formatted as #0:123.A or #1.2:87.B (#model.submodel:residue.chain)
+     */
     List<AtomSpec> atomSpecs = new ArrayList<AtomSpec>();
-    for (String atomSpec : atoms)
+    for (String atomSpec : selection)
     {
-      int hashPos = atomSpec.indexOf("#");
       int colonPos = atomSpec.indexOf(":");
-      int dotPos = atomSpec.indexOf(".");
-
       if (colonPos == -1)
       {
         continue; // malformed
       }
-      int pdbResNum = Integer.parseInt(dotPos == -1 ? atomSpec
-              .substring(colonPos) : atomSpec.substring(colonPos + 1,
-              dotPos));
-
-      String chainId = dotPos == -1 ? "" : atomSpec.substring(dotPos + 1);
+    
+      int hashPos = atomSpec.indexOf("#");
+      String modelSubmodel = atomSpec.substring(hashPos + 1, colonPos);
+      int dotPos = modelSubmodel.indexOf(".");
       int modelId = 0;
       try {
-        modelId = Integer.valueOf(atomSpec.substring(hashPos + 1, colonPos));
+        modelId = Integer.valueOf(dotPos == -1 ? modelSubmodel
+                : modelSubmodel.substring(0, dotPos));
       } catch (NumberFormatException e) {
         // ignore, default to model 0
       }
-
+    
+      String residueChain = atomSpec.substring(colonPos + 1);
+      dotPos = residueChain.indexOf(".");
+      int pdbResNum = Integer.parseInt(dotPos == -1 ? residueChain
+              : residueChain.substring(0, dotPos));
+    
+      String chainId = dotPos == -1 ? "" : residueChain
+              .substring(dotPos + 1);
+    
       /*
        * Work out the pdbfilename from the model number
        */
@@ -1000,10 +990,23 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       }
       atomSpecs.add(new AtomSpec(pdbfilename, chainId, pdbResNum, 0));
     }
-    if (!atomSpecs.isEmpty())
-    {
-      getSsm().mouseOverStructure(atomSpecs);
-    }
+
+    /*
+     * Broadcast the selection (which may be empty, if the user just cleared all
+     * selections)
+     */
+    getSsm().mouseOverStructure(atomSpecs);
+  }
+
+  private void log(String message)
+  {
+    System.err.println("## Chimera log: " + message);
+  }
+
+  private void viewerCommandHistory(boolean enable)
+  {
+    // log("(Not yet implemented) History "
+    // + ((debug || enable) ? "on" : "off"));
   }
 
   public long getLoadNotifiesHandled()
@@ -1020,23 +1023,16 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       return;
     }
 
-    int index;
-    Color col;
     // Chimera expects RBG values in the range 0-1
     final double normalise = 255D;
     viewerCommandHistory(false);
-    // TODO: Switch between nucleotide or aa selection expressions
     StringBuilder command = new StringBuilder(128);
-    command.append("color white;");
-    for (String res : ResidueProperties.aa3Hash.keySet())
-    {
-      index = ResidueProperties.aa3Hash.get(res).intValue();
-      if (index > 20)
-      {
-        continue;
-      }
 
-      col = cs.findColour(ResidueProperties.aa[index].charAt(0));
+    List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
+            false);
+    for (String res : residueSet)
+    {
+      Color col = cs.findColour(res.charAt(0));
       command.append("color " + col.getRed() / normalise + ","
               + col.getGreen() / normalise + "," + col.getBlue()
               / normalise + " ::" + res + ";");