*/
package jalview.ext.jmol;
-import jalview.api.FeatureRenderer;
-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.structure.AtomSpec;
-import jalview.structure.StructureSelectionManager;
-import jalview.structures.models.AAStructureBindingModel;
-import jalview.util.MessageManager;
-
import java.awt.Container;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
-import java.util.BitSet;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.jmol.c.CBK;
import org.jmol.viewer.Viewer;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.api.SequenceRenderer;
+import jalview.bin.Cache;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.gui.IProgressIndicator;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.StructureFile;
+import jalview.structure.AtomSpec;
+import jalview.structure.StructureCommand;
+import jalview.structure.StructureCommandI;
+import jalview.structure.StructureSelectionManager;
+import jalview.structures.models.AAStructureBindingModel;
+import javajs.util.BS;
+
public abstract class JalviewJmolBinding extends AAStructureBindingModel
implements JmolStatusListener, JmolSelectionListener,
ComponentListener
return getViewerTitle("Jmol", true);
}
- public void closeViewer()
- {
- // remove listeners for all structures in viewer
- getSsm().removeStructureViewerListener(this, this.getStructureFiles());
- jmolViewer.dispose();
- lastCommand = null;
- jmolViewer = null;
- releaseUIResources();
- }
-
- /**
- * superpose the structures associated with sequences in the alignment
- * according to their corresponding positions.
- *
- * @deprecated not used - remove?
- */
- @Deprecated
- public void superposeStructures(AlignmentI alignment)
+ private String jmolScript(String script)
{
- superposeStructures(alignment, -1, null);
- }
+ Cache.log.debug(">>Jmol>> " + script);
+ String s = jmolViewer.scriptWait(script);
+ Cache.log.debug("<<Jmol<< " + s);
- /**
- * superpose the structures associated with sequences in the alignment
- * according to their corresponding positions. ded)
- *
- * @param refStructure
- * - select which pdb file to use as reference (default is -1 - the
- * first structure in the alignment)
- * @deprecated not used - remove?
- */
- @Deprecated
- public void superposeStructures(AlignmentI alignment, int refStructure)
- {
- superposeStructures(alignment, refStructure, null);
+ return s;
}
- /**
- * superpose the structures associated with sequences in the alignment
- * according to their corresponding positions. ded)
- *
- * @param refStructure
- * - select which pdb file to use as reference (default is -1 - the
- * first structure in the alignment)
- * @param hiddenCols
- * TODO
- * @deprecated not used - remove?
- */
- @Deprecated
- public void superposeStructures(AlignmentI alignment, int refStructure,
- HiddenColumns hiddenCols)
- {
- superposeStructures(new AlignmentI[] { alignment },
- new int[]
- { refStructure }, new HiddenColumns[] { hiddenCols });
- }
-
- /**
- * {@inheritDoc}
- */
@Override
- public String superposeStructures(AlignmentI[] _alignment,
- int[] _refStructure, HiddenColumns[] _hiddenCols)
- {
- while (jmolViewer.isScriptExecuting())
- {
- try
- {
- Thread.sleep(10);
- } catch (InterruptedException i)
- {
- }
- }
-
- /*
- * get the distinct structure files modelled
- * (a file with multiple chains may map to multiple sequences)
- */
- String[] files = getStructureFiles();
- if (!waitForFileLoad(files))
- {
- return null;
- }
-
- StringBuilder selectioncom = new StringBuilder(256);
- // In principle - nSeconds specifies the speed of animation for each
- // superposition - but is seems to behave weirdly, so we don't specify it.
- String nSeconds = " ";
- if (files.length > 10)
- {
- nSeconds = " 0.005 ";
- }
- else
- {
- nSeconds = " " + (2.0 / files.length) + " ";
- // if (nSeconds).substring(0,5)+" ";
- }
-
- // see JAL-1345 - should really automatically turn off the animation for
- // large numbers of structures, but Jmol doesn't seem to allow that.
- // nSeconds = " ";
- // union of all aligned positions are collected together.
- for (int a = 0; a < _alignment.length; a++)
- {
- int refStructure = _refStructure[a];
- AlignmentI alignment = _alignment[a];
- HiddenColumns hiddenCols = _hiddenCols[a];
- 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);
- refStructure = -1;
- }
-
- /*
- * 'matched' bit j will be set for visible alignment columns j where
- * all sequences have a residue with a mapping to the PDB structure
- */
- BitSet matched = new BitSet();
- for (int m = 0; m < alignment.getWidth(); m++)
- {
- if (hiddenCols == null || hiddenCols.isVisible(m))
- {
- matched.set(m);
- }
- }
-
- SuperposeData[] structures = new SuperposeData[files.length];
- for (int f = 0; f < files.length; f++)
- {
- structures[f] = new SuperposeData(alignment.getWidth());
- }
-
- /*
- * Calculate the superposable alignment columns ('matched'), and the
- * corresponding structure residue positions (structures.pdbResNo)
- */
- int candidateRefStructure = findSuperposableResidues(alignment,
- matched, structures);
- if (refStructure < 0)
- {
- /*
- * If no reference structure was specified, pick the first one that has
- * a mapping in the alignment
- */
- refStructure = candidateRefStructure;
- }
-
- String[] selcom = new String[files.length];
- int nmatched = matched.cardinality();
- if (nmatched < 4)
- {
- return (MessageManager.formatMessage("label.insufficient_residues",
- nmatched));
- }
-
- /*
- * generate select statements to select regions to superimpose structures
- */
- {
- // TODO extract method to construct selection statements
- for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
- {
- String chainCd = ":" + structures[pdbfnum].chain;
- int lpos = -1;
- boolean run = false;
- StringBuilder molsel = new StringBuilder();
- molsel.append("{");
-
- int nextColumnMatch = matched.nextSetBit(0);
- while (nextColumnMatch != -1)
- {
- int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
- if (lpos != pdbResNo - 1)
- {
- // discontinuity
- if (lpos != -1)
- {
- molsel.append(lpos);
- molsel.append(chainCd);
- molsel.append("|");
- }
- run = false;
- }
- else
- {
- // continuous run - and lpos >-1
- if (!run)
- {
- // at the beginning, so add dash
- molsel.append(lpos);
- molsel.append("-");
- }
- run = true;
- }
- lpos = pdbResNo;
- nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
- }
- /*
- * add final selection phrase
- */
- if (lpos != -1)
- {
- molsel.append(lpos);
- molsel.append(chainCd);
- molsel.append("}");
- }
- if (molsel.length() > 1)
- {
- 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;
- }
- }
- }
- StringBuilder command = new StringBuilder(256);
- // command.append("set spinFps 10;\n");
-
- for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
- {
- if (pdbfnum == refStructure || selcom[pdbfnum] == null
- || selcom[refStructure] == null)
- {
- continue;
- }
- command.append("echo ");
- command.append("\"Superposing (");
- command.append(structures[pdbfnum].pdbId);
- command.append(") against reference (");
- command.append(structures[refStructure].pdbId);
- command.append(")\";\ncompare " + nSeconds);
- command.append("{");
- command.append(Integer.toString(1 + pdbfnum));
- 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 ");
-
- // for (int s = 0; s < 2; s++)
- // {
- // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
- // }
- command.append(selcom[pdbfnum]);
- command.append(selcom[refStructure]);
- command.append(" ROTATE TRANSLATE;\n");
- }
- if (selectioncom.length() > 0)
- {
- // TODO is performing selectioncom redundant here? is done later on
- // System.out.println("Select regions:\n" + selectioncom.toString());
- executeCommand("select *; cartoons off; backbone; select ("
- + selectioncom.toString() + "); cartoons; ", false);
- // selcom.append("; ribbons; ");
- String cmdString = command.toString();
- // System.out.println("Superimpose command(s):\n" + cmdString);
-
- executeCommand(cmdString, false);
- }
- }
- if (selectioncom.length() > 0)
- {// finally, mark all regions that were superposed.
- if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
- {
- selectioncom.setLength(selectioncom.length() - 1);
- }
- // System.out.println("Select regions:\n" + selectioncom.toString());
- executeCommand("select *; cartoons off; backbone; select ("
- + selectioncom.toString() + "); cartoons; ", false);
- // evalStateCommand("select *; backbone; select "+selcom.toString()+";
- // cartoons; center "+selcom.toString());
- }
-
- return null;
- }
-
- @Override
- public List<String> executeCommand(String command, boolean getReply)
+ public List<String> executeCommand(StructureCommandI command,
+ boolean getReply)
{
if (command == null)
{
return null;
}
+ String cmd = command.getCommand();
jmolHistory(false);
- if (lastCommand == null || !lastCommand.equals(command))
+ if (lastCommand == null || !lastCommand.equals(cmd))
{
- jmolViewer.evalStringQuiet(command + "\n");
+ jmolScript(cmd + "\n");
}
jmolHistory(true);
- lastCommand = command;
+ lastCommand = cmd;
return null;
}
@Override
public synchronized String[] getStructureFiles()
{
- List<String> mset = new ArrayList<>();
if (jmolViewer == null)
{
return new String[0];
{
int modelCount = jmolViewer.ms.mc;
String filePath = null;
+ List<String> mset = new ArrayList<>();
for (int i = 0; i < modelCount; ++i)
{
+ /*
+ * defensive check for null as getModelFileName can return null
+ * even when model count ms.mc is > 0
+ */
filePath = jmolViewer.ms.getModelFileName(i);
- if (!mset.contains(filePath))
+ if (filePath != null && !mset.contains(filePath))
{
mset.add(filePath);
}
}
- modelFileNames = mset.toArray(new String[mset.size()]);
+ if (!mset.isEmpty())
+ {
+ modelFileNames = mset.toArray(new String[mset.size()]);
+ }
}
return modelFileNames;
{
if (resetLastRes.length() > 0)
{
- jmolViewer.evalStringQuiet(resetLastRes.toString());
+ jmolScript(resetLastRes.toString());
resetLastRes.setLength(0);
}
for (AtomSpec atom : atoms)
public void highlightAtom(int atomIndex, int pdbResNum, String chain,
String pdbfile)
{
- if (modelFileNames == null)
- {
- return;
- }
-
- // look up file model number for this pdbfile
- int mdlNum = 0;
- // may need to adjust for URLencoding here - we don't worry about that yet.
- while (mdlNum < modelFileNames.length
- && !pdbfile.equals(modelFileNames[mdlNum]))
- {
- mdlNum++;
- }
- if (mdlNum == modelFileNames.length)
+ String modelId = getModelIdForFile(pdbfile);
+ if (modelId.isEmpty())
{
return;
}
jmolHistory(false);
+ StringBuilder selection = new StringBuilder(32);
StringBuilder cmd = new StringBuilder(64);
- cmd.append("select ").append(String.valueOf(pdbResNum)); // +modelNum
-
- resetLastRes.append("select ").append(String.valueOf(pdbResNum)); // +modelNum
-
- cmd.append(":");
- resetLastRes.append(":");
+ selection.append("select ").append(String.valueOf(pdbResNum));
+ selection.append(":");
if (!chain.equals(" "))
{
- cmd.append(chain);
- resetLastRes.append(chain);
+ selection.append(chain);
}
- {
- cmd.append(" /").append(String.valueOf(mdlNum + 1));
- resetLastRes.append("/").append(String.valueOf(mdlNum + 1));
- }
- cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
+ selection.append(" /").append(modelId);
- resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
- + " and not hetero; spacefill 0;");
+ cmd.append(selection).append(";wireframe 100;").append(selection)
+ .append(" and not hetero;").append("spacefill 200;select none");
- cmd.append("spacefill 200;select none");
+ resetLastRes.append(selection).append(";wireframe 0;").append(selection)
+ .append(" and not hetero; spacefill 0;");
- jmolViewer.evalStringQuiet(cmd.toString());
+ jmolScript(cmd.toString());
jmolHistory(true);
-
}
private boolean debug = true;
private void jmolHistory(boolean enable)
{
- jmolViewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
+ jmolScript("History " + ((debug || enable) ? "on" : "off"));
}
public void loadInline(String string)
sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
.append(toks.nextToken());
sb.append("|").append(label).append("\"");
- executeCommand(sb.toString(), false);
+ executeCommand(new StructureCommand(sb.toString()), false);
}
}
{
/**
* this implements the toggle label behaviour copied from the original
- * structure viewer, MCView
+ * structure viewer, mc_view
*/
if (strData != null)
{
if (!atomsPicked.contains(picked))
{
- jmolViewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
+ jmolScript("select " + picked + ";label %n %r:%c");
atomsPicked.addElement(picked);
}
else
// see JAL-623 - need method of matching pasted data up
{
pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
- pdbfile, DataSourceType.PASTE,
- getIProgressIndicator());
+ pdbfile, DataSourceType.PASTE, getIProgressIndicator());
getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
matches = true;
foundEntry = true;
}
if (matches)
{
- // add an entry for every chain in the model
- for (int i = 0; i < pdb.getChains().size(); i++)
- {
- String chid = pdb.getId() + ":"
- + pdb.getChains().elementAt(i).id;
- addChainFile(chid, fileName);
- getChainNames().add(chid);
- }
+ stashFoundChains(pdb, fileName);
notifyLoaded = true;
}
}
// }
if (!isLoadingFromArchive())
{
- jmolViewer.evalStringQuiet(
+ jmolScript(
"model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
}
// register ourselves as a listener and notify the gui that it needs to
public void showHelp()
{
- showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
+ showUrl("http://wiki.jmol.org"
+ // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
+ , "jmolHelp");
}
/**
*/
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
* @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 = "";
jmolViewer.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);
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
}
@Override
- protected int getModelNoForFile(String pdbFile)
+ protected String getModelIdForFile(String pdbFile)
{
if (modelFileNames == null)
{
- return -1;
+ return "";
}
for (int i = 0; i < modelFileNames.length; i++)
{
if (modelFileNames[i].equalsIgnoreCase(pdbFile))
{
- return i;
+ return String.valueOf(i + 1);
}
}
- return -1;
+ return "";
+ }
+ @Override
+ protected ViewerType getViewerType()
+ {
+ return ViewerType.JMOL;
+ }
+
+ @Override
+ protected String getModelId(int pdbfnum, String file)
+ {
+ return String.valueOf(pdbfnum + 1);
+ }
+
+ /**
+ * Returns ".spt" - the Jmol session file extension
+ *
+ * @return
+ * @see https://chemapps.stolaf.edu/jmol/docs/#writemodel
+ */
+ @Override
+ public String getSessionFileExtension()
+ {
+ return ".spt";
+ }
+
+ @Override
+ public void selectionChanged(BS arg0)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
+ {
+ return new jalview.gui.SequenceRenderer(avp.getAlignViewport());
+ }
+
+ @Override
+ public String getHelpURL()
+ {
+ return "http://wiki.jmol.org"; // BH 2018
}
}