JAL-1213 JAL-674 - import a PDB file using Jmol data api and decorate any peptide...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Tue, 4 Dec 2012 11:06:45 +0000 (11:06 +0000)
committerJim Procter <jprocter@compbio.dundee.ac.uk>
Wed, 13 Feb 2013 18:05:51 +0000 (18:05 +0000)
src/jalview/ext/jmol/PDBFileWithJmol.java [new file with mode: 0644]
src/jalview/io/AppletFormatAdapter.java
test/jalview/ext/jmol/PDBFileWithJmolTest.java [new file with mode: 0644]

diff --git a/src/jalview/ext/jmol/PDBFileWithJmol.java b/src/jalview/ext/jmol/PDBFileWithJmol.java
new file mode 100644 (file)
index 0000000..962fe3c
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
+ * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+ * 
+ * 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.
+ *  
+ * 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/>.
+ */
+package jalview.ext.jmol;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.jmol.api.JmolStatusListener;
+import org.jmol.api.JmolViewer;
+import org.jmol.constant.EnumCallback;
+import org.jmol.constant.EnumStructure;
+import org.jmol.modelset.Chain;
+import org.jmol.modelset.Group;
+import org.jmol.modelset.Model;
+import org.jmol.modelset.ModelSet;
+import org.jmol.modelset.Polymer;
+import org.jmol.modelsetbio.BioPolymer;
+import org.jmol.viewer.Viewer;
+import org.openscience.jmol.app.JmolApp;
+import org.xml.sax.SAXException;
+
+import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
+import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
+import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;
+import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.io.AlignFile;
+
+/**
+ * Import and process PDB files with Jmol
+ * 
+ * @author jprocter
+ * 
+ */
+public class PDBFileWithJmol extends AlignFile implements
+        JmolStatusListener
+{
+
+  JmolApp jmolApp = null;
+
+  Viewer viewer = null;
+
+  public PDBFileWithJmol(String inFile, String type)
+          throws ExceptionUnmatchedClosingParentheses, IOException,
+          ExceptionFileFormatOrSyntax, ParserConfigurationException,
+          SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed,
+          InterruptedException
+  {
+    super(inFile, type);
+  }
+
+  public PDBFileWithJmol()
+  {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * create a headless jmol instance for dataprocessing
+   * 
+   * @return
+   */
+  private Viewer getJmolData()
+  {
+    if (viewer == null)
+    { // note that -o -n -x are all implied
+      jmolApp = new JmolApp();
+      jmolApp.isDataOnly = true;
+      jmolApp.haveConsole = false;
+      jmolApp.haveDisplay = false;
+      jmolApp.exitUponCompletion = true;
+      try
+      {
+        viewer = (Viewer) JmolViewer.allocateViewer(null, null, null, null,
+                null, jmolApp.commandOptions, this);
+        viewer.setScreenDimension(jmolApp.startupWidth,
+                jmolApp.startupHeight);
+        jmolApp.startViewer(viewer, null);
+      } catch (ClassCastException x)
+      {
+        throw new Error(
+                "Jmol version "
+                        + JmolViewer.getJmolVersion()
+                        + " is not compatible with this version of Jalview. Report this problem at issues.jalview.org",
+                x);
+      }
+    }
+    return viewer;
+  }
+
+  private void waitForScript(Viewer jmd)
+  {
+    while (jmd.isScriptExecuting())
+    {
+      try
+      {
+        Thread.sleep(50);
+
+      } catch (InterruptedException x)
+      {
+      }
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see jalview.io.AlignFile#parse()
+   */
+  @Override
+  public void parse() throws IOException, ExceptionFileFormatOrSyntax,
+          ParserConfigurationException, SAXException,
+          ExceptionPermissionDenied, ExceptionLoadingFailed,
+          InterruptedException, ExceptionUnmatchedClosingParentheses
+  {
+    Viewer jmd = getJmolData();
+    jmd.openReader(getDataName(), getDataName(), getReader());
+    waitForScript(jmd);
+    if (jmd.getModelCount() > 0)
+    {
+      ModelSet ms = jmd.getModelSet();
+      String structs = ms.calculateStructures(null, true, false, true);
+      // System.out.println("Structs\n"+structs);
+      for (Model model : ms.getModels())
+      {
+        for (int _bp = 0, _bpc = model.getBioPolymerCount(); _bp < _bpc; _bp++)
+        {
+          Polymer bp = model.getBioPolymer(_bp);
+          if (bp instanceof BioPolymer)
+          {
+            BioPolymer biopoly = (BioPolymer) bp;
+            char _lastChainId = 0;
+            int[] groups = biopoly.getLeadAtomIndices();
+            Group[] bpgrp = biopoly.getGroups();
+            char seq[] = new char[groups.length], secstr[] = new char[groups.length], secstrcode[] = new char[groups.length];
+            int groupc = 0, len = 0, firstrnum = 1, lastrnum = 0;
+            do
+            {
+              if (groupc >= groups.length
+                      || ms.atoms[groups[groupc]].getChainID() != _lastChainId)
+              {
+                if (len > 0)
+                {
+                  char newseq[] = new char[len];
+                  System.arraycopy(seq, 0, newseq, 0, len);
+                  Annotation asecstr[] = new Annotation[len];
+                  for (int p = 0; p < len; p++)
+                  {
+                    if (secstr[p] >= 'A' && secstr[p] <= 'z')
+                    {
+                      asecstr[p] = new Annotation("" + secstr[p], null,
+                              secstrcode[p], Float.NaN);
+                    }
+                  }
+                  SequenceI sq = new Sequence("" + getDataName() + "|"
+                          + model.getModelTitle() + "|" + _lastChainId,
+                          newseq, firstrnum, lastrnum);
+                  PDBEntry pdbe = new PDBEntry();
+                  pdbe.setFile(getDataName());
+                  pdbe.setId(getDataName());
+                  sq.addPDBId(pdbe);
+                  seqs.add(sq);
+                  if (!(biopoly.isDna() || biopoly.isRna()))
+                  {
+                    AlignmentAnnotation ann = new AlignmentAnnotation(
+                            "Secondary Structure",
+                            "Secondary Structure from PDB File", asecstr);
+                    sq.addAlignmentAnnotation(ann);
+                    annotations.add(ann);
+                  }
+                }
+                len = 0;
+                firstrnum = 1;
+                lastrnum = 0;
+              }
+              if (groupc < groups.length)
+              {
+                if (len == 0)
+                {
+                  firstrnum = bpgrp[groupc].getResno();
+                  _lastChainId = bpgrp[groupc].getChainID();
+                }
+                else
+                {
+                  lastrnum = bpgrp[groupc].getResno();
+                }
+                seq[len] = bpgrp[groupc].getGroup1();
+                switch (bpgrp[groupc].getProteinStructureSubType())
+                {
+                case HELIX_310:
+                  if (secstr[len] == 0)
+                  {
+                    secstr[len] = '3';
+                  }
+                case HELIX_ALPHA:
+                  if (secstr[len] == 0)
+                  {
+                    secstr[len] = 'H';
+                  }
+                case HELIX_PI:
+                  if (secstr[len] == 0)
+                  {
+                    secstr[len] = 'P';
+                  }
+                case HELIX:
+                  if (secstr[len] == 0)
+                  {
+                    secstr[len] = 'H';
+                  }
+                  secstrcode[len] = 'H';
+                  break;
+                case SHEET:
+                  secstr[len] = 'E';
+                  secstrcode[len] = 'E';
+                  break;
+                default:
+                  secstr[len] = 0;
+                  secstrcode[len] = 0;
+                }
+                len++;
+              }
+            } while (groupc++ < groups.length);
+
+          }
+        }
+      }
+
+      /*
+       * lastScriptTermination = -9465; String dsspOut =
+       * jmd.evalString("calculate STRUCTURE"); if (dsspOut.equals("pending")) {
+       * while (lastScriptTermination == -9465) { try { Thread.sleep(50); }
+       * catch (Exception x) { } ; } } System.out.println(lastConsoleEcho);
+       */
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see jalview.io.AlignFile#print()
+   */
+  @Override
+  public String print()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void setCallbackFunction(String callbackType,
+          String callbackFunction)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  /*
+   * @Override public void notifyCallback(EnumCallback type, Object[] data) {
+   * try { switch (type) { case ERROR: case SCRIPT:
+   * notifyScriptTermination((String) data[2], ((Integer) data[3]).intValue());
+   * break; case MESSAGE: sendConsoleMessage((data == null) ? ((String) null) :
+   * (String) data[1]); break; case LOADSTRUCT: notifyFileLoaded((String)
+   * data[1], (String) data[2], (String) data[3], (String) data[4], ((Integer)
+   * data[5]).intValue());
+   * 
+   * break; default: // System.err.println("Unhandled callback " + type + " " //
+   * + data[1].toString()); break; } } catch (Exception e) {
+   * System.err.println("Squashed Jmol callback handler error:");
+   * e.printStackTrace(); } }
+   */
+  public void notifyCallback(EnumCallback type, Object[] data)
+  {
+    String strInfo = (data == null || data[1] == null ? null : data[1]
+            .toString());
+    switch (type)
+    {
+    case ECHO:
+      sendConsoleEcho(strInfo);
+      break;
+    case SCRIPT:
+      notifyScriptTermination((String) data[2],
+              ((Integer) data[3]).intValue());
+      break;
+    case MEASURE:
+      String mystatus = (String) data[3];
+      if (mystatus.indexOf("Picked") >= 0
+              || mystatus.indexOf("Sequence") >= 0) // picking mode
+        sendConsoleMessage(strInfo);
+      else if (mystatus.indexOf("Completed") >= 0)
+        sendConsoleEcho(strInfo.substring(strInfo.lastIndexOf(",") + 2,
+                strInfo.length() - 1));
+      break;
+    case MESSAGE:
+      sendConsoleMessage(data == null ? null : strInfo);
+      break;
+    case PICK:
+      sendConsoleMessage(strInfo);
+      break;
+    default:
+      break;
+    }
+  }
+
+  private void notifyFileLoaded(String string, String string2,
+          String string3, String string4, int intValue)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  String lastConsoleEcho = "";
+
+  private void sendConsoleEcho(String string)
+  {
+    lastConsoleEcho += string;
+    lastConsoleEcho += "\n";
+  }
+
+  String lastConsoleMessage = "";
+
+  private void sendConsoleMessage(String string)
+  {
+    lastConsoleMessage += string;
+    lastConsoleMessage += "\n";
+  }
+
+  int lastScriptTermination = -1;
+
+  String lastScriptMessage = "";
+
+  private void notifyScriptTermination(String string, int intValue)
+  {
+    lastScriptMessage += string;
+    lastScriptMessage += "\n";
+    lastScriptTermination = intValue;
+  }
+
+  @Override
+  public boolean notifyEnabled(EnumCallback callbackPick)
+  {
+    switch (callbackPick)
+    {
+    case MESSAGE:
+    case SCRIPT:
+    case ECHO:
+    case LOADSTRUCT:
+    case ERROR:
+      return true;
+    case MEASURE:
+    case PICK:
+    case HOVER:
+    case RESIZE:
+    case SYNC:
+    case CLICK:
+    case ANIMFRAME:
+    case MINIMIZATION:
+    }
+    return false;
+  }
+
+  @Override
+  public String eval(String strEval)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public float[][] functionXY(String functionName, int x, int y)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String createImage(String fileName, String type,
+          Object text_or_bytes, int quality)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public Map<String, Object> getRegistryInfo()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void showUrl(String url)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void resizeInnerPanel(String data)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+}
index 637db81..85ea8e0 100755 (executable)
@@ -228,6 +228,8 @@ public class AppletFormatAdapter
       else if (format.equals("PDB"))
       {
         afile = new MCview.PDBfile(inFile, type);        
+        // Uncomment to test Jmol data based PDB processing: JAL-1213
+        // afile = new jalview.ext.jmol.PDBFileWithJmol(inFile, type);
       }
       else if (format.equals("STH"))
       {
diff --git a/test/jalview/ext/jmol/PDBFileWithJmolTest.java b/test/jalview/ext/jmol/PDBFileWithJmolTest.java
new file mode 100644 (file)
index 0000000..2b53822
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * 
+ */
+package jalview.ext.jmol;
+
+import static org.junit.Assert.*;
+
+import java.util.Vector;
+
+import jalview.datamodel.SequenceI;
+
+import org.junit.Test;
+
+/**
+ * @author jimp
+ *
+ */
+public class PDBFileWithJmolTest
+{
+
+  @Test
+  public void test() throws Exception
+  {
+    PDBFileWithJmol jtest=new PDBFileWithJmol("./examples/1vsp", jalview.io.AppletFormatAdapter.FILE);
+    Vector<SequenceI> seqs=jtest.getSeqs();
+    assertTrue("No sequences extracted from testfile", seqs!=null && seqs.size()>0);
+    assertTrue("No annotation generated.", seqs.get(0).getAnnotation()!=null && seqs.get(0).getAnnotation().length!=0);
+    
+  }
+
+}