JAL-3026 Jmol functioning; some issues
[jalview.git] / src / jalview / ext / jmol / JalviewJmolBinding.java
index 5de554b..babebc5 100644 (file)
@@ -27,6 +27,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.gui.IProgressIndicator;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
 import jalview.schemes.ColourSchemeI;
@@ -72,7 +73,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   private boolean associateNewStructs = false;
 
-  Vector<String> atomsPicked = new Vector<String>();
+  Vector<String> atomsPicked = new Vector<>();
 
   private List<String> chainNames;
 
@@ -165,7 +166,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   {
     // remove listeners for all structures in viewer
     getSsm().removeStructureViewerListener(this, this.getStructureFiles());
-    viewer.dispose();
+    if (viewer != null)
+      viewer.dispose();
     lastCommand = null;
     viewer = null;
     releaseUIResources();
@@ -225,8 +227,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           HiddenColumns hiddenCols)
   {
     superposeStructures(new AlignmentI[] { alignment },
-            new int[] { refStructure },
- new HiddenColumns[] { hiddenCols });
+            new int[]
+            { refStructure }, new HiddenColumns[] { hiddenCols });
   }
 
   /**
@@ -279,18 +281,16 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       int refStructure = _refStructure[a];
       AlignmentI alignment = _alignment[a];
       HiddenColumns hiddenCols = _hiddenCols[a];
-      if (a > 0
-              && selectioncom.length() > 0
-              && !selectioncom.substring(selectioncom.length() - 1).equals(
-                      "|"))
+      if (a > 0 && selectioncom.length() > 0 && !selectioncom
+              .substring(selectioncom.length() - 1).equals("|"))
       {
         selectioncom.append("|");
       }
       // process this alignment
       if (refStructure >= files.length)
       {
-        System.err.println("Invalid reference structure value "
-                + refStructure);
+        System.err.println(
+                "Invalid reference structure value " + refStructure);
         refStructure = -1;
       }
 
@@ -332,8 +332,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       int nmatched = matched.cardinality();
       if (nmatched < 4)
       {
-        return (MessageManager.formatMessage(
-"label.insufficient_residues",
+        return (MessageManager.formatMessage("label.insufficient_residues",
                 nmatched));
       }
 
@@ -429,7 +428,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         command.append(".1} {");
         command.append(Integer.toString(1 + refStructure));
         // conformation=1 excludes alternate locations for CA (JAL-1757)
-        command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
+        command.append(
+                ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
 
         // for (int s = 0; s < 2; s++)
         // {
@@ -461,7 +461,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       // System.out.println("Select regions:\n" + selectioncom.toString());
       evalStateCommand("select *; cartoons off; backbone; select ("
               + selectioncom.toString() + "); cartoons; ");
-      // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
+      // evalStateCommand("select *; backbone; select "+selcom.toString()+";
+      // cartoons; center "+selcom.toString());
     }
 
     return null;
@@ -472,12 +473,13 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     jmolHistory(false);
     if (lastCommand == null || !lastCommand.equals(command))
     {
-      viewer.evalStringQuiet(command + "\n");
+      jmolScript(command + "\n");
     }
     jmolHistory(true);
     lastCommand = command;
   }
 
+  Thread colourby = null;
   /**
    * Sends a set of colour commands to the structure viewer
    * 
@@ -485,15 +487,28 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   @Override
   protected void colourBySequence(
-          StructureMappingcommandSet[] colourBySequenceCommands)
+          final StructureMappingcommandSet[] colourBySequenceCommands)
   {
-    for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
+    if (colourby != null)
     {
-      for (String cbyseq : cpdbbyseq.commands)
+      colourby.interrupt();
+      colourby = null;
+    }
+    colourby = new Thread(new Runnable()
+    {
+      @Override
+      public void run()
       {
-        executeWhenReady(cbyseq);
+        for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
+        {
+          for (String cbyseq : cpdbbyseq.commands)
+          {
+            executeWhenReady(cbyseq);
+          }
+        }
       }
-    }
+    });
+    colourby.start();
   }
 
   /**
@@ -549,7 +564,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   }
 
   @Override
-  public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
+  public float[][][] functionXYZ(String functionName, int nx, int ny,
+          int nz)
   {
     // TODO Auto-generated method stub
     return null;
@@ -610,7 +626,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     }
     if (modelFileNames == null)
     {
-      List<String> mset = new ArrayList<String>();
+      List<String> mset = new ArrayList<>();
       _modelFileNameMap = new int[viewer.ms.mc];
       String m = viewer.ms.getModelFileName(0);
       if (m != null)
@@ -622,9 +638,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         } catch (AccessControlException x)
         {
           // usually not allowed to do this in applet
-          System.err
-                  .println("jmolBinding: Using local file string from Jmol: "
-                          + m);
+          System.err.println(
+                  "jmolBinding: Using local file string from Jmol: " + m);
         }
         if (filePath.indexOf("/file:") != -1)
         {
@@ -647,7 +662,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           } catch (AccessControlException x)
           {
             // usually not allowed to do this in applet, so keep raw handle
-            // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
+            // System.err.println("jmolBinding: Using local file string from
+            // Jmol: "+m);
           }
         }
 
@@ -670,7 +686,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   @Override
   public synchronized String[] getStructureFiles()
   {
-    List<String> mset = new ArrayList<String>();
+    List<String> mset = new ArrayList<>();
     if (viewer == null)
     {
       return new String[0];
@@ -693,6 +709,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
     return modelFileNames;
   }
+
   /**
    * map from string to applet
    */
@@ -703,8 +720,6 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return null;
   }
 
-  
-
   // ///////////////////////////////
   // JmolStatusListener
 
@@ -724,7 +739,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     {
       if (resetLastRes.length() > 0)
       {
-        viewer.evalStringQuiet(resetLastRes.toString());
+        jmolScript(resetLastRes.toString());
         resetLastRes.setLength(0);
       }
       for (AtomSpec atom : atoms)
@@ -782,7 +797,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
     cmd.append("spacefill 200;select none");
 
-    viewer.evalStringQuiet(cmd.toString());
+    jmolScript(cmd.toString());
     jmolHistory(true);
 
   }
@@ -791,7 +806,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   private void jmolHistory(boolean enable)
   {
-    viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
+    jmolScript("History " + ((debug || enable) ? "on" : "off"));
   }
 
   public void loadInline(String string)
@@ -827,14 +842,14 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     // handle insertion codes
     if (alocsep != -1)
     {
-      pdbResNum = Integer.parseInt(strInfo.substring(
-              strInfo.indexOf("]") + 1, alocsep));
+      pdbResNum = Integer.parseInt(
+              strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
 
     }
     else
     {
-      pdbResNum = Integer.parseInt(strInfo.substring(
-              strInfo.indexOf("]") + 1, chainSeparator));
+      pdbResNum = Integer.parseInt(
+              strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
     }
     String chainId;
 
@@ -856,24 +871,36 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
       {
         chainSeparator1 = strInfo.indexOf(".", mdlSep);
       }
-      String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
-              chainSeparator1) : strInfo.substring(mdlSep + 1);
+      String mdlId = (chainSeparator1 > -1)
+              ? strInfo.substring(mdlSep + 1, chainSeparator1)
+              : strInfo.substring(mdlSep + 1);
       try
       {
         // recover PDB filename for the model hovered over.
-        int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
-                .intValue() - 1;
-        while (mnumber < _modelFileNameMap[_mp])
+        int mnumber = new Integer(mdlId).intValue() - 1;
+        if (_modelFileNameMap != null)
         {
-          _mp--;
+          int _mp = _modelFileNameMap.length - 1;
+
+          while (mnumber < _modelFileNameMap[_mp])
+          {
+            _mp--;
+          }
+          pdbfilename = modelFileNames[_mp];
         }
-        pdbfilename = modelFileNames[_mp];
-        if (pdbfilename == null)
+        else
         {
-          pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
-                  .getAbsolutePath();
-        }
+          if (mnumber >= 0 && mnumber < modelFileNames.length)
+          {
+            pdbfilename = modelFileNames[mnumber];
+          }
 
+          if (pdbfilename == null)
+          {
+            pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
+                    .getAbsolutePath();
+          }
+        }
       } catch (Exception e)
       {
       }
@@ -903,11 +930,12 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    * } }
    */
 
-  public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
+  public void notifyAtomPicked(int atomIndex, String strInfo,
+          String strData)
   {
     /**
      * this implements the toggle label behaviour copied from the original
-     * structure viewer, MCView
+     * structure viewer, mc_view
      */
     if (strData != null)
     {
@@ -938,7 +966,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
     if (!atomsPicked.contains(picked))
     {
-      viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
+      jmolScript("select " + picked + ";label %n %r:%c");
       atomsPicked.addElement(picked);
     }
     else
@@ -974,6 +1002,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
                 (String) data[0]);
         // also highlight in alignment
+        // deliberate fall through
       case HOVER:
         notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
                 (String) data[0]);
@@ -986,8 +1015,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         sendConsoleEcho((String) data[1]);
         break;
       case MESSAGE:
-        sendConsoleMessage((data == null) ? ((String) null)
-                : (String) data[1]);
+        sendConsoleMessage(
+                (data == null) ? ((String) null) : (String) data[1]);
         break;
       case ERROR:
         // System.err.println("Ignoring error callback.");
@@ -1000,8 +1029,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
       case CLICK:
       default:
-        System.err.println("Unhandled callback " + type + " "
-                + data[1].toString());
+        System.err.println(
+                "Unhandled callback " + type + " " + data[1].toString());
         break;
       }
     } catch (Exception e)
@@ -1058,8 +1087,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     fileLoadingError = null;
     String[] oldmodels = modelFileNames;
     modelFileNames = null;
-    chainNames = new ArrayList<String>();
-    chainFile = new Hashtable<String, String>();
+    chainNames = new ArrayList<>();
+    chainFile = new Hashtable<>();
     boolean notifyLoaded = false;
     String[] modelfilenames = getStructureFiles();
     // first check if we've lost any structures
@@ -1110,8 +1139,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
         // calculate essential attributes for the pdb data imported inline.
         // prolly need to resolve modelnumber properly - for now just use our
         // 'best guess'
-        pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
-                + ".0", "PDB");
+        pdbfile = viewer.getData(
+                "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
       }
       // search pdbentries and sequences to find correct pdbentry for this
       // model
@@ -1125,7 +1154,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           // see JAL-623 - need method of matching pasted data up
           {
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    pdbfile, DataSourceType.PASTE);
+                    pdbfile, DataSourceType.PASTE,
+                    getIProgressIndicator());
             getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
             matches = true;
             foundEntry = true;
@@ -1157,7 +1187,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             }
             // Explicitly map to the filename used by Jmol ;
             pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
-                    fileName, protocol);
+                    fileName, protocol, getIProgressIndicator());
             // pdbentry[pe].getFile(), protocol);
 
           }
@@ -1167,8 +1197,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
           // add an entry for every chain in the model
           for (int i = 0; i < pdb.getChains().size(); i++)
           {
-            String chid = new String(pdb.getId() + ":"
-                    + pdb.getChains().elementAt(i).id);
+            String chid = new String(
+                    pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
             chainFile.put(chid, fileName);
             chainNames.add(chid);
           }
@@ -1200,7 +1230,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     // }
     if (!isLoadingFromArchive())
     {
-      viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
+      jmolScript(
+              "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
     }
     // register ourselves as a listener and notify the gui that it needs to
     // update itself.
@@ -1224,6 +1255,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return chainNames;
   }
 
+  protected abstract IProgressIndicator getIProgressIndicator();
+
   public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
   {
     notifyAtomPicked(iatom, strMeasure, null);
@@ -1280,8 +1313,9 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
             false);
     for (String resName : residueSet)
     {
-      char res = resName.length() == 3 ? ResidueProperties
-              .getSingleCharacterCode(resName) : resName.charAt(0);
+      char res = resName.length() == 3
+              ? ResidueProperties.getSingleCharacterCode(resName)
+              : resName.charAt(0);
       Color col = cs.findColour(res, 0, null, null, 0f);
       command.append("select " + resName + ";color[" + col.getRed() + ","
               + col.getGreen() + "," + col.getBlue() + "];");
@@ -1317,7 +1351,17 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    */
   public abstract void showConsole(boolean show);
 
+  
+  public static Viewer getJmolData(JmolParser jmolParser)
+  {
+    return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
+            "-x -o -n", jmolParser);
+  }
+
   /**
+   * 
+   * 
+   * 
    * @param renderPanel
    * @param jmolfileio
    *          - when true will initialise jmol's file IO system (should be false
@@ -1348,25 +1392,33 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
    * @param consolePanel
    *          - panel to contain Jmol console
    * @param buttonsToShow
-   *          - buttons to show on the console, in ordr
+   *          - buttons to show on the console, in order
    */
   public void allocateViewer(Container renderPanel, boolean jmolfileio,
           String htmlName, URL documentBase, URL codeBase,
           String commandOptions, final Container consolePanel,
           String buttonsToShow)
   {
+    
+    System.err.println("Allocating Jmol Viewer: " + commandOptions);
+    
     if (commandOptions == null)
     {
       commandOptions = "";
     }
     viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
-            (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
-                    + ((Object) this).toString(), documentBase, codeBase,
+            (jmolfileio ? new SmarterJmolAdapter() : null),
+            htmlName + ((Object) this).toString(), documentBase, codeBase,
             commandOptions, this);
 
     viewer.setJmolStatusListener(this); // extends JmolCallbackListener
 
-    console = createJmolConsole(consolePanel, buttonsToShow);
+    try {
+      console = createJmolConsole(consolePanel, buttonsToShow);
+    } catch (Throwable e) {
+      System.err.println("Could not create Jmol application console. " + e.getMessage());
+      e.printStackTrace();
+    }
     if (consolePanel != null)
     {
       consolePanel.addComponentListener(this);
@@ -1378,17 +1430,32 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   protected abstract JmolAppConsoleInterface createJmolConsole(
           Container consolePanel, String buttonsToShow);
 
+  // BH 2018 -- Jmol console is not working due to problems with styled documents.
+  
+
   protected org.jmol.api.JmolAppConsoleInterface console = null;
 
   @Override
   public void setBackgroundColour(java.awt.Color col)
   {
     jmolHistory(false);
-    viewer.evalStringQuiet("background [" + col.getRed() + ","
+    jmolScript("background [" + col.getRed() + ","
             + col.getGreen() + "," + col.getBlue() + "];");
     jmolHistory(true);
   }
 
+  private String jmolScript(String script)
+  {
+    
+    System.err.println(">>Jmol>> " + script);
+    
+    String s = viewer.scriptWait(script);
+    
+    System.err.println("<<Jmol<< " + s);
+    
+    return s;
+  }
+
   @Override
   public int[] resizeInnerPanel(String data)
   {
@@ -1449,4 +1516,5 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   {
     showConsole(false);
   }
+
 }