JAL-1636 typed collections now in ResidueProperties
[jalview.git] / src / jalview / ext / jmol / JalviewJmolBinding.java
index 8dfb9fd..30998bd 100644 (file)
@@ -1,19 +1,21 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
  * Copyright (C) 2014 The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
  *  
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  * PURPOSE.  See the GNU General Public License for more details.
  * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.ext.jmol;
@@ -30,9 +32,12 @@ import jalview.datamodel.SequenceI;
 import jalview.io.AppletFormatAdapter;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ResidueProperties;
+import jalview.structure.AtomSpec;
 import jalview.structure.StructureListener;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureSelectionManager;
+import jalview.structures.models.SequenceStructureBindingModel;
+import jalview.util.MessageManager;
 
 import java.awt.Color;
 import java.awt.Container;
@@ -41,8 +46,8 @@ import java.awt.event.ComponentListener;
 import java.io.File;
 import java.net.URL;
 import java.security.AccessControlException;
-import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
@@ -54,26 +59,13 @@ import org.jmol.api.JmolViewer;
 import org.jmol.constant.EnumCallback;
 import org.jmol.popup.JmolPopup;
 
-public abstract class JalviewJmolBinding implements StructureListener,
+public abstract class JalviewJmolBinding extends SequenceStructureBindingModel implements StructureListener,
         JmolStatusListener, SequenceStructureBinding,
         JmolSelectionListener, ComponentListener,
         StructureSelectionManagerProvider
 
 {
   /**
-   * set if Jmol state is being restored from some source - instructs binding
-   * not to apply default display style when structure set is updated for first
-   * time.
-   */
-  private boolean loadingFromArchive = false;
-  
-  /**
-   * second flag to indicate if the jmol viewer should ignore sequence colouring
-   * events from the structure manager because the GUI is still setting up
-   */
-  private boolean loadingFinished = true;
-
-  /**
    * state flag used to check if the Jmol viewer's paint method can be called
    */
   private boolean finishedInit = false;
@@ -241,7 +233,9 @@ public abstract class JalviewJmolBinding implements StructureListener,
               + (1 + getModelNum((String) chainFile.get(lbl))) + " or ");
     }
     if (cmd.length() > 0)
+    {
       cmd.setLength(cmd.length() - 4);
+    }
     evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
   }
 
@@ -328,13 +322,15 @@ public abstract class JalviewJmolBinding implements StructureListener,
 
     String[] files = getPdbFile();
     // check to see if we are still waiting for Jmol files
-    long starttime=System.currentTimeMillis();
-    boolean waiting=true;
-    do {
-      waiting=false;
-      for (String file:files)
+    long starttime = System.currentTimeMillis();
+    boolean waiting = true;
+    do
+    {
+      waiting = false;
+      for (String file : files)
       {
-        try {
+        try
+        {
           // HACK - in Jalview 2.8 this call may not be threadsafe so we catch
           // every possible exception
           StructureMapping[] sm = ssm.getMapping(file);
@@ -351,10 +347,12 @@ public abstract class JalviewJmolBinding implements StructureListener,
         }
       }
       // we wait around for a reasonable time before we give up
-    } while (waiting && System.currentTimeMillis()<(10000+1000*files.length+starttime));
+    } while (waiting
+            && System.currentTimeMillis() < (10000 + 1000 * files.length + starttime));
     if (waiting)
     {
-      System.err.println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures.");
+      System.err
+              .println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures.");
       return;
     }
     StringBuffer selectioncom = new StringBuffer();
@@ -418,7 +416,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
         // Jmol callback has completed.
         if (mapping == null || mapping.length < 1)
         {
-          throw new Error("Implementation error - Jmol seems to be still working on getting its data - report at http://issues.jalview.org/browse/JAL-1016");
+          throw new Error(MessageManager.getString("error.implementation_error_jmol_getting_data"));
         }
         int lastPos = -1;
         for (int s = 0; s < sequence[pdbfnum].length; s++)
@@ -484,7 +482,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
           }
         }
       }
-      
+
       // TODO: consider bailing if nmatched less than 4 because superposition
       // not
       // well defined.
@@ -543,22 +541,30 @@ public abstract class JalviewJmolBinding implements StructureListener,
             molsel.append(chainCd);
             molsel.append("}");
           }
-          selcom[pdbfnum] = molsel.toString();
-          selectioncom.append("((");
-          selectioncom.append(selcom[pdbfnum].substring(1,
-                  selcom[pdbfnum].length() - 1));
-          selectioncom.append(" )& ");
-          selectioncom.append(pdbfnum + 1);
-          selectioncom.append(".1)");
-          if (pdbfnum < files.length - 1)
+          if (molsel.length() > 1)
           {
-            selectioncom.append("|");
+            selcom[pdbfnum] = molsel.toString();
+            selectioncom.append("((");
+            selectioncom.append(selcom[pdbfnum].substring(1,
+                    selcom[pdbfnum].length() - 1));
+            selectioncom.append(" )& ");
+            selectioncom.append(pdbfnum + 1);
+            selectioncom.append(".1)");
+            if (pdbfnum < files.length - 1)
+            {
+              selectioncom.append("|");
+            }
+          }
+          else
+          {
+            selcom[pdbfnum] = null;
           }
         }
       }
       for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
       {
-        if (pdbfnum == refStructure)
+        if (pdbfnum == refStructure || selcom[pdbfnum] == null
+                || selcom[refStructure] == null)
         {
           continue;
         }
@@ -567,7 +573,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
         command.append(chainNames[pdbfnum]);
         command.append(") against reference (");
         command.append(chainNames[refStructure]);
-        command.append(")\";\ncompare "+nSeconds);
+        command.append(")\";\ncompare " + nSeconds);
         command.append("{");
         command.append(1 + pdbfnum);
         command.append(".1} {");
@@ -582,13 +588,17 @@ public abstract class JalviewJmolBinding implements StructureListener,
         }
         command.append(" ROTATE TRANSLATE;\n");
       }
-      System.out.println("Select regions:\n" + selectioncom.toString());
-      evalStateCommand("select *; cartoons off; backbone; select ("
-              + selectioncom.toString() + "); cartoons; ");
-      // selcom.append("; ribbons; ");
-      System.out.println("Superimpose command(s):\n" + command.toString());
-
-      evalStateCommand(command.toString());
+      if (selectioncom.length() > 0)
+      {
+        System.out.println("Select regions:\n" + selectioncom.toString());
+        evalStateCommand("select *; cartoons off; backbone; select ("
+                + selectioncom.toString() + "); cartoons; ");
+        // selcom.append("; ribbons; ");
+        System.out
+                .println("Superimpose command(s):\n" + command.toString());
+
+        evalStateCommand(command.toString());
+      }
     }
     if (selectioncom.length() > 0)
     {// finally, mark all regions that were superposed.
@@ -622,8 +632,10 @@ public abstract class JalviewJmolBinding implements StructureListener,
   public void colourBySequence(boolean showFeatures,
           jalview.api.AlignmentViewPanel alignmentv)
   {
-    if (!colourBySequence || !loadingFinished)
+    if (!colourBySequence || !isLoadingFinished())
+    {
       return;
+    }
     if (ssm == null)
     {
       return;
@@ -642,10 +654,12 @@ public abstract class JalviewJmolBinding implements StructureListener,
     for (jalview.structure.StructureMappingcommandSet cpdbbyseq : JmolCommands
             .getColourBySequenceCommand(ssm, files, sequence, sr, fr,
                     alignment))
+    {
       for (String cbyseq : cpdbbyseq.commands)
       {
         evalStateCommand(cbyseq);
       }
+    }
   }
 
   public boolean isColourBySequence()
@@ -695,7 +709,9 @@ public abstract class JalviewJmolBinding implements StructureListener,
           String pdbfile)
   {
     if (getModelNum(pdbfile) < 0)
+    {
       return null;
+    }
     // TODO: verify atomIndex is selecting correct model.
     return new Color(viewer.getAtomArgb(atomIndex));
   }
@@ -728,7 +744,9 @@ public abstract class JalviewJmolBinding implements StructureListener,
     for (int i = 0; i < mfn.length; i++)
     {
       if (mfn[i].equalsIgnoreCase(modelFileName))
+      {
         return i;
+      }
     }
     return -1;
   }
@@ -824,64 +842,76 @@ public abstract class JalviewJmolBinding implements StructureListener,
     jmolpopup.show(x, y);
   }
 
-  // jmol/ssm only
-  public void highlightAtom(int atomIndex, int pdbResNum, String chain,
-          String pdbfile)
+  /**
+   * Highlight the specified atoms in the structure.
+   * 
+   * @param atoms
+   */
+  @Override
+  public void highlightAtoms(List<AtomSpec> atoms)
   {
     if (modelFileNames == null)
     {
       return;
     }
 
-    // look up file model number for this pdbfile
-    int mdlNum = 0;
-    String fn;
-    // may need to adjust for URLencoding here - we don't worry about that yet.
-    while (mdlNum < modelFileNames.length
-            && !pdbfile.equals(modelFileNames[mdlNum]))
-    {
-      // System.out.println("nomatch:"+pdbfile+"\nmodelfn:"+fn);
-      mdlNum++;
-    }
-    if (mdlNum == modelFileNames.length)
+    for (AtomSpec atom : atoms)
     {
-      return;
-    }
+      String pdbfile = atom.getPdbId();
+      int pdbResNum = atom.getPdbResNum();
+      String chain = atom.getChain();
+
+      // look up file model number for this pdbfile
+      int mdlNum = 0;
+      String fn;
+      // may need to adjust for URLencoding here - we don't worry about that
+      // yet.
+      while (mdlNum < modelFileNames.length
+              && !pdbfile.equals(modelFileNames[mdlNum]))
+      {
+        // System.out.println("nomatch:"+pdbfile+"\nmodelfn:"+fn);
+        mdlNum++;
+      }
+      if (mdlNum == modelFileNames.length)
+      {
+        return;
+      }
 
-    jmolHistory(false);
-    // if (!pdbfile.equals(pdbentry.getFile()))
-    // return;
-    if (resetLastRes.length() > 0)
-    {
-      viewer.evalStringQuiet(resetLastRes.toString());
-    }
+      jmolHistory(false);
+      // if (!pdbfile.equals(pdbentry.getFile()))
+      // return;
+      if (resetLastRes.length() > 0)
+      {
+        viewer.evalStringQuiet(resetLastRes.toString());
+      }
 
-    eval.setLength(0);
-    eval.append("select " + pdbResNum); // +modelNum
+      eval.setLength(0);
+      eval.append("select " + pdbResNum); // +modelNum
 
-    resetLastRes.setLength(0);
-    resetLastRes.append("select " + pdbResNum); // +modelNum
+      resetLastRes.setLength(0);
+      resetLastRes.append("select " + pdbResNum); // +modelNum
 
-    eval.append(":");
-    resetLastRes.append(":");
-    if (!chain.equals(" "))
-    {
-      eval.append(chain);
-      resetLastRes.append(chain);
-    }
-    {
-      eval.append(" /" + (mdlNum + 1));
-      resetLastRes.append("/" + (mdlNum + 1));
-    }
-    eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
+      eval.append(":");
+      resetLastRes.append(":");
+      if (!chain.equals(" "))
+      {
+        eval.append(chain);
+        resetLastRes.append(chain);
+      }
+      {
+        eval.append(" /" + (mdlNum + 1));
+        resetLastRes.append("/" + (mdlNum + 1));
+      }
+      eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
 
-    resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
-            + " and not hetero; spacefill 0;");
+      resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
+              + " and not hetero; spacefill 0;");
 
-    eval.append("spacefill 200;select none");
+      eval.append("spacefill 200;select none");
 
-    viewer.evalStringQuiet(eval.toString());
-    jmolHistory(true);
+      viewer.evalStringQuiet(eval.toString());
+      jmolHistory(true);
+    }
 
   }
 
@@ -937,8 +967,10 @@ public abstract class JalviewJmolBinding implements StructureListener,
     String chainId;
 
     if (strInfo.indexOf(":") > -1)
+    {
       chainId = strInfo.substring(strInfo.indexOf(":") + 1,
               strInfo.indexOf("."));
+    }
     else
     {
       chainId = " ";
@@ -976,7 +1008,9 @@ public abstract class JalviewJmolBinding implements StructureListener,
       ;
     }
     if (lastMessage == null || !lastMessage.equals(strInfo))
+    {
       ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename);
+    }
 
     lastMessage = strInfo;
   }
@@ -1010,13 +1044,17 @@ public abstract class JalviewJmolBinding implements StructureListener,
     int chainSeparator = strInfo.indexOf(":");
     int p = 0;
     if (chainSeparator == -1)
+    {
       chainSeparator = strInfo.indexOf(".");
+    }
 
     String picked = strInfo.substring(strInfo.indexOf("]") + 1,
             chainSeparator);
     String mdlString = "";
     if ((p = strInfo.indexOf(":")) > -1)
+    {
       picked += strInfo.substring(p + 1, strInfo.indexOf("."));
+    }
 
     if ((p = strInfo.indexOf("/")) > -1)
     {
@@ -1264,7 +1302,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
             for (int i = 0; i < pdb.chains.size(); i++)
             {
               String chid = new String(pdb.id + ":"
-                      + ((MCview.PDBChain) pdb.chains.elementAt(i)).id);
+                      + pdb.chains.elementAt(i).id);
               chainFile.put(chid, fileName);
               chainNames.addElement(chid);
             }
@@ -1357,21 +1395,23 @@ public abstract class JalviewJmolBinding implements StructureListener,
     colourBySequence = false;
 
     if (cs == null)
+    {
       return;
+    }
 
-    String res;
     int index;
     Color col;
     jmolHistory(false);
     // TODO: Switch between nucleotide or aa selection expressions
-    Enumeration en = ResidueProperties.aa3Hash.keys();
-    StringBuffer command = new StringBuffer("select *;color white;");
-    while (en.hasMoreElements())
+    StringBuilder command = new StringBuilder(128);
+    command.append("select *;color white;");
+    for (String res : ResidueProperties.aa3Hash.keySet())
     {
-      res = en.nextElement().toString();
-      index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
+      index = ResidueProperties.aa3Hash.get(res).intValue();
       if (index > 20)
+      {
         continue;
+      }
 
       col = cs.findColour(ResidueProperties.aa[index].charAt(0));
 
@@ -1490,30 +1530,6 @@ public abstract class JalviewJmolBinding implements StructureListener,
     showConsole(false);
   }
 
-  public void setLoadingFromArchive(boolean loadingFromArchive)
-  {
-    this.loadingFromArchive = loadingFromArchive;
-  }
-  
-  /**
-   * 
-   * @return true if Jmol is still restoring state or loading is still going on (see setFinsihedLoadingFromArchive)
-   */
-  public boolean isLoadingFromArchive()
-  {
-    return loadingFromArchive && !loadingFinished;
-  }
-
-  /**
-   * modify flag which controls if sequence colouring events are honoured by the binding. 
-   * Should be true for normal operation
-   * @param finishedLoading
-   */
-  public void setFinishedLoadingFromArchive(boolean finishedLoading)
-  {
-    loadingFinished = finishedLoading;
-  }
-
   public void setBackgroundColour(java.awt.Color col)
   {
     jmolHistory(false);
@@ -1591,9 +1607,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
   {
     if (pe < 0 || pe >= pdbentry.length)
     {
-      throw new Error(
-              "Implementation error - no corresponding pdbentry (for index "
-                      + pe + ") to add sequences mappings to");
+      throw new Error(MessageManager.formatMessage("error.implementation_error_no_pdbentry_from_index", new String[]{Integer.valueOf(pe).toString()}));
     }
     final String nullChain = "TheNullChain";
     Vector s = new Vector();