2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.ext.jmol;
23 import jalview.api.AlignViewportI;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.api.FeatureRenderer;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.HiddenColumns;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.SequenceI;
30 import jalview.ext.rbvi.chimera.AtomSpecModel;
31 import jalview.gui.IProgressIndicator;
32 import jalview.io.DataSourceType;
33 import jalview.io.StructureFile;
34 import jalview.schemes.ColourSchemeI;
35 import jalview.schemes.ResidueProperties;
36 import jalview.structure.AtomSpec;
37 import jalview.structure.StructureSelectionManager;
38 import jalview.structures.models.AAStructureBindingModel;
39 import jalview.util.MessageManager;
41 import java.awt.Color;
42 import java.awt.Container;
43 import java.awt.event.ComponentEvent;
44 import java.awt.event.ComponentListener;
47 import java.util.ArrayList;
48 import java.util.BitSet;
49 import java.util.Hashtable;
50 import java.util.List;
52 import java.util.StringTokenizer;
53 import java.util.Vector;
55 import org.jmol.adapter.smarter.SmarterJmolAdapter;
56 import org.jmol.api.JmolAppConsoleInterface;
57 import org.jmol.api.JmolSelectionListener;
58 import org.jmol.api.JmolStatusListener;
59 import org.jmol.api.JmolViewer;
60 import org.jmol.c.CBK;
61 import org.jmol.script.T;
62 import org.jmol.viewer.Viewer;
64 public abstract class JalviewJmolBinding extends AAStructureBindingModel
65 implements JmolStatusListener, JmolSelectionListener,
68 private String lastMessage;
70 boolean allChainsSelected = false;
73 * when true, try to search the associated datamodel for sequences that are
74 * associated with any unknown structures in the Jmol view.
76 private boolean associateNewStructs = false;
78 Vector<String> atomsPicked = new Vector<>();
80 private List<String> chainNames;
82 Hashtable<String, String> chainFile;
85 * the default or current model displayed if the model cannot be identified
86 * from the selection message
90 // protected JmolGenericPopup jmolpopup; // not used - remove?
96 StringBuffer resetLastRes = new StringBuffer();
100 public JalviewJmolBinding(StructureSelectionManager ssm,
101 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
102 DataSourceType protocol)
104 super(ssm, pdbentry, sequenceIs, protocol);
106 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
107 * "jalviewJmol", ap.av.applet .getDocumentBase(),
108 * ap.av.applet.getCodeBase(), "", this);
110 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
114 public JalviewJmolBinding(StructureSelectionManager ssm,
115 SequenceI[][] seqs, Viewer theViewer)
120 viewer.setJmolStatusListener(this);
121 viewer.addSelectionListener(this);
125 * construct a title string for the viewer window based on the data jalview
130 public String getViewerTitle()
132 return getViewerTitle("Jmol", true);
136 * prepare the view for a given set of models/chains. chainList contains
137 * strings of the form 'pdbfilename:Chaincode'
139 public void centerViewer()
141 StringBuilder cmd = new StringBuilder(128);
143 for (String lbl : chainsToShow)
149 mlength = lbl.indexOf(":", p);
150 } while (p < mlength && mlength < (lbl.length() - 2));
151 // TODO: lookup each pdb id and recover proper model number for it.
152 cmd.append(":" + lbl.substring(mlength + 1) + " /"
153 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
155 if (cmd.length() > 0)
157 cmd.setLength(cmd.length() - 4);
159 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
160 evalStateCommand(command);
163 public void closeViewer()
165 // remove listeners for all structures in viewer
166 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
170 releaseUIResources();
174 public void colourByChain()
176 colourBySequence = false;
177 // TODO: colour by chain should colour each chain distinctly across all
179 // TODO: http://issues.jalview.org/browse/JAL-628
180 evalStateCommand("select *;color chain");
184 public void colourByCharge()
186 colourBySequence = false;
187 evalStateCommand("select *;color white;select ASP,GLU;color red;"
188 + "select LYS,ARG;color blue;select CYS;color yellow");
192 * superpose the structures associated with sequences in the alignment
193 * according to their corresponding positions.
195 public void superposeStructures(AlignmentI alignment)
197 superposeStructures(alignment, -1, null);
201 * superpose the structures associated with sequences in the alignment
202 * according to their corresponding positions. ded)
204 * @param refStructure
205 * - select which pdb file to use as reference (default is -1 - the
206 * first structure in the alignment)
208 public void superposeStructures(AlignmentI alignment, int refStructure)
210 superposeStructures(alignment, refStructure, null);
214 * superpose the structures associated with sequences in the alignment
215 * according to their corresponding positions. ded)
217 * @param refStructure
218 * - select which pdb file to use as reference (default is -1 - the
219 * first structure in the alignment)
223 public void superposeStructures(AlignmentI alignment, int refStructure,
224 HiddenColumns hiddenCols)
226 superposeStructures(new AlignmentI[] { alignment },
228 { refStructure }, new HiddenColumns[] { hiddenCols });
235 public String superposeStructures(AlignmentI[] _alignment,
236 int[] _refStructure, HiddenColumns[] _hiddenCols)
238 while (viewer.isScriptExecuting())
243 } catch (InterruptedException i)
249 * get the distinct structure files modelled
250 * (a file with multiple chains may map to multiple sequences)
252 String[] files = getStructureFiles();
253 if (!waitForFileLoad(files))
258 StringBuilder selectioncom = new StringBuilder(256);
259 // In principle - nSeconds specifies the speed of animation for each
260 // superposition - but is seems to behave weirdly, so we don't specify it.
261 String nSeconds = " ";
262 if (files.length > 10)
264 nSeconds = " 0.005 ";
268 nSeconds = " " + (2.0 / files.length) + " ";
269 // if (nSeconds).substring(0,5)+" ";
272 // see JAL-1345 - should really automatically turn off the animation for
273 // large numbers of structures, but Jmol doesn't seem to allow that.
275 // union of all aligned positions are collected together.
276 for (int a = 0; a < _alignment.length; a++)
278 int refStructure = _refStructure[a];
279 AlignmentI alignment = _alignment[a];
280 HiddenColumns hiddenCols = _hiddenCols[a];
281 if (a > 0 && selectioncom.length() > 0 && !selectioncom
282 .substring(selectioncom.length() - 1).equals("|"))
284 selectioncom.append("|");
286 // process this alignment
287 if (refStructure >= files.length)
290 "Invalid reference structure value " + refStructure);
295 * 'matched' bit j will be set for visible alignment columns j where
296 * all sequences have a residue with a mapping to the PDB structure
298 BitSet matched = new BitSet();
299 for (int m = 0; m < alignment.getWidth(); m++)
301 if (hiddenCols == null || hiddenCols.isVisible(m))
307 SuperposeData[] structures = new SuperposeData[files.length];
308 for (int f = 0; f < files.length; f++)
310 structures[f] = new SuperposeData(alignment.getWidth());
314 * Calculate the superposable alignment columns ('matched'), and the
315 * corresponding structure residue positions (structures.pdbResNo)
317 int candidateRefStructure = findSuperposableResidues(alignment,
318 matched, structures);
319 if (refStructure < 0)
322 * If no reference structure was specified, pick the first one that has
323 * a mapping in the alignment
325 refStructure = candidateRefStructure;
328 String[] selcom = new String[files.length];
329 int nmatched = matched.cardinality();
332 return (MessageManager.formatMessage("label.insufficient_residues",
337 * generate select statements to select regions to superimpose structures
340 // TODO extract method to construct selection statements
341 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
343 String chainCd = ":" + structures[pdbfnum].chain;
346 StringBuilder molsel = new StringBuilder();
349 int nextColumnMatch = matched.nextSetBit(0);
350 while (nextColumnMatch != -1)
352 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
353 if (lpos != pdbResNo - 1)
359 molsel.append(chainCd);
366 // continuous run - and lpos >-1
369 // at the beginning, so add dash
376 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
379 * add final selection phrase
384 molsel.append(chainCd);
387 if (molsel.length() > 1)
389 selcom[pdbfnum] = molsel.toString();
390 selectioncom.append("((");
391 selectioncom.append(selcom[pdbfnum].substring(1,
392 selcom[pdbfnum].length() - 1));
393 selectioncom.append(" )& ");
394 selectioncom.append(pdbfnum + 1);
395 selectioncom.append(".1)");
396 if (pdbfnum < files.length - 1)
398 selectioncom.append("|");
403 selcom[pdbfnum] = null;
407 StringBuilder command = new StringBuilder(256);
408 // command.append("set spinFps 10;\n");
410 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
412 if (pdbfnum == refStructure || selcom[pdbfnum] == null
413 || selcom[refStructure] == null)
417 command.append("echo ");
418 command.append("\"Superposing (");
419 command.append(structures[pdbfnum].pdbId);
420 command.append(") against reference (");
421 command.append(structures[refStructure].pdbId);
422 command.append(")\";\ncompare " + nSeconds);
424 command.append(Integer.toString(1 + pdbfnum));
425 command.append(".1} {");
426 command.append(Integer.toString(1 + refStructure));
427 // conformation=1 excludes alternate locations for CA (JAL-1757)
429 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
431 // for (int s = 0; s < 2; s++)
433 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
435 command.append(selcom[pdbfnum]);
436 command.append(selcom[refStructure]);
437 command.append(" ROTATE TRANSLATE;\n");
439 if (selectioncom.length() > 0)
441 // TODO is performing selectioncom redundant here? is done later on
442 // System.out.println("Select regions:\n" + selectioncom.toString());
443 evalStateCommand("select *; cartoons off; backbone; select ("
444 + selectioncom.toString() + "); cartoons; ");
445 // selcom.append("; ribbons; ");
446 String cmdString = command.toString();
447 // System.out.println("Superimpose command(s):\n" + cmdString);
449 evalStateCommand(cmdString);
452 if (selectioncom.length() > 0)
453 {// finally, mark all regions that were superposed.
454 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
456 selectioncom.setLength(selectioncom.length() - 1);
458 // System.out.println("Select regions:\n" + selectioncom.toString());
459 evalStateCommand("select *; cartoons off; backbone; select ("
460 + selectioncom.toString() + "); cartoons; ");
461 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
462 // cartoons; center "+selcom.toString());
468 public void evalStateCommand(String command)
471 if (lastCommand == null || !lastCommand.equals(command))
473 viewer.evalStringQuiet(command + "\n");
476 lastCommand = command;
479 Thread colourby = null;
482 * Sends a set of colour commands to the structure viewer
487 protected void colourBySequence(final String[] commands)
489 if (colourby != null)
491 colourby.interrupt();
494 colourby = new Thread(new Runnable()
499 for (String cmd : commands)
501 executeWhenReady(cmd);
514 protected String[] getColourBySequenceCommands(
515 String[] files, AlignmentViewPanel viewPanel)
517 Map<Object, AtomSpecModel> map = buildColoursMap(viewPanel);
519 return JmolCommands.getColourBySequenceCommand(map);
525 protected void executeWhenReady(String command)
527 evalStateCommand(command);
530 public void createImage(String file, String type, int quality)
532 System.out.println("JMOL CREATE IMAGE");
536 public String createImage(String fileName, String type,
537 Object textOrBytes, int quality)
539 System.out.println("JMOL CREATE IMAGE");
544 public String eval(String strEval)
546 // System.out.println(strEval);
547 // "# 'eval' is implemented only for the applet.";
551 // End StructureListener
552 // //////////////////////////
555 public float[][] functionXY(String functionName, int x, int y)
561 public float[][][] functionXYZ(String functionName, int nx, int ny,
564 // TODO Auto-generated method stub
568 public Color getColour(int atomIndex, int pdbResNum, String chain,
571 if (getModelNum(pdbfile) < 0)
575 // TODO: verify atomIndex is selecting correct model.
576 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
577 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
578 return new Color(colour);
582 * instruct the Jalview binding to update the pdbentries vector if necessary
583 * prior to matching the jmol view's contents to the list of structure files
584 * Jalview knows about.
586 public abstract void refreshPdbEntries();
588 private int getModelNum(String modelFileName)
590 String[] mfn = getStructureFiles();
595 for (int i = 0; i < mfn.length; i++)
597 if (mfn[i].equalsIgnoreCase(modelFileName))
606 * map between index of model filename returned from getPdbFile and the first
607 * index of models from this file in the viewer. Note - this is not trimmed -
608 * use getPdbFile to get number of unique models.
610 private int _modelFileNameMap[];
613 public synchronized String[] getStructureFiles()
615 List<String> mset = new ArrayList<>();
618 return new String[0];
621 if (modelFileNames == null)
623 int modelCount = viewer.ms.mc;
624 String filePath = null;
625 for (int i = 0; i < modelCount; ++i)
627 filePath = viewer.ms.getModelFileName(i);
628 if (!mset.contains(filePath))
633 modelFileNames = mset.toArray(new String[mset.size()]);
636 return modelFileNames;
640 * map from string to applet
643 public Map<String, Object> getRegistryInfo()
645 // TODO Auto-generated method stub
649 // ///////////////////////////////
650 // JmolStatusListener
652 public void handlePopupMenu(int x, int y)
654 // jmolpopup.show(x, y);
655 // jmolpopup.jpiShow(x, y);
659 * Highlight zero, one or more atoms on the structure
662 public void highlightAtoms(List<AtomSpec> atoms)
666 if (resetLastRes.length() > 0)
668 viewer.evalStringQuiet(resetLastRes.toString());
669 resetLastRes.setLength(0);
671 for (AtomSpec atom : atoms)
673 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
674 atom.getChain(), atom.getPdbFile());
680 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
683 if (modelFileNames == null)
688 // look up file model number for this pdbfile
690 // may need to adjust for URLencoding here - we don't worry about that yet.
691 while (mdlNum < modelFileNames.length
692 && !pdbfile.equals(modelFileNames[mdlNum]))
696 if (mdlNum == modelFileNames.length)
703 StringBuilder cmd = new StringBuilder(64);
704 cmd.append("select " + pdbResNum); // +modelNum
706 resetLastRes.append("select " + pdbResNum); // +modelNum
709 resetLastRes.append(":");
710 if (!chain.equals(" "))
713 resetLastRes.append(chain);
716 cmd.append(" /" + (mdlNum + 1));
717 resetLastRes.append("/" + (mdlNum + 1));
719 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
721 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
722 + " and not hetero; spacefill 0;");
724 cmd.append("spacefill 200;select none");
726 viewer.evalStringQuiet(cmd.toString());
731 boolean debug = true;
733 private void jmolHistory(boolean enable)
735 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
738 public void loadInline(String string)
742 // viewer.loadInline(strModel, isAppend);
744 // construct fake fullPathName and fileName so we can identify the file
746 // Then, construct pass a reader for the string to Jmol.
747 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
748 // fileName, null, reader, false, null, null, 0);
749 viewer.openStringInline(string);
752 protected void mouseOverStructure(int atomIndex, final String strInfo)
755 int alocsep = strInfo.indexOf("^");
756 int mdlSep = strInfo.indexOf("/");
757 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
759 if (chainSeparator == -1)
761 chainSeparator = strInfo.indexOf(".");
762 if (mdlSep > -1 && mdlSep < chainSeparator)
764 chainSeparator1 = chainSeparator;
765 chainSeparator = mdlSep;
768 // handle insertion codes
771 pdbResNum = Integer.parseInt(
772 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
777 pdbResNum = Integer.parseInt(
778 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
782 if (strInfo.indexOf(":") > -1)
784 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
785 strInfo.indexOf("."));
792 String pdbfilename = modelFileNames[frameNo]; // default is first or current
796 if (chainSeparator1 == -1)
798 chainSeparator1 = strInfo.indexOf(".", mdlSep);
800 String mdlId = (chainSeparator1 > -1)
801 ? strInfo.substring(mdlSep + 1, chainSeparator1)
802 : strInfo.substring(mdlSep + 1);
805 // recover PDB filename for the model hovered over.
806 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
807 if (_modelFileNameMap != null)
809 int _mp = _modelFileNameMap.length - 1;
811 while (mnumber < _modelFileNameMap[_mp])
815 pdbfilename = modelFileNames[_mp];
819 if (mnumber >= 0 && mnumber < modelFileNames.length)
821 pdbfilename = modelFileNames[mnumber];
824 if (pdbfilename == null)
826 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
830 } catch (Exception e)
836 * highlight position on alignment(s); if some text is returned,
837 * show this as a second line on the structure hover tooltip
839 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
843 // change comma to pipe separator (newline token for Jmol)
844 label = label.replace(',', '|');
845 StringTokenizer toks = new StringTokenizer(strInfo, " ");
846 StringBuilder sb = new StringBuilder();
847 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
848 .append(chainId).append("/1");
849 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
850 .append(toks.nextToken());
851 sb.append("|").append(label).append("\"");
852 evalStateCommand(sb.toString());
856 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
858 if (strInfo.equals(lastMessage))
862 lastMessage = strInfo;
865 System.err.println("Ignoring additional hover info: " + data
866 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
868 mouseOverStructure(atomIndex, strInfo);
872 * { if (history != null && strStatus != null &&
873 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
877 public void notifyAtomPicked(int atomIndex, String strInfo,
881 * this implements the toggle label behaviour copied from the original
882 * structure viewer, MCView
886 System.err.println("Ignoring additional pick data string " + strData);
888 int chainSeparator = strInfo.indexOf(":");
890 if (chainSeparator == -1)
892 chainSeparator = strInfo.indexOf(".");
895 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
897 String mdlString = "";
898 if ((p = strInfo.indexOf(":")) > -1)
900 picked += strInfo.substring(p, strInfo.indexOf("."));
903 if ((p = strInfo.indexOf("/")) > -1)
905 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
907 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
911 if (!atomsPicked.contains(picked))
913 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
914 atomsPicked.addElement(picked);
918 viewer.evalString("select " + picked + ";label off");
919 atomsPicked.removeElement(picked);
922 // TODO: in application this happens
924 // if (scriptWindow != null)
926 // scriptWindow.sendConsoleMessage(strInfo);
927 // scriptWindow.sendConsoleMessage("\n");
933 public void notifyCallback(CBK type, Object[] data)
940 notifyFileLoaded((String) data[1], (String) data[2],
941 (String) data[3], (String) data[4],
942 ((Integer) data[5]).intValue());
946 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
948 // also highlight in alignment
949 // deliberate fall through
951 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
955 notifyScriptTermination((String) data[2],
956 ((Integer) data[3]).intValue());
959 sendConsoleEcho((String) data[1]);
963 (data == null) ? ((String) null) : (String) data[1]);
966 // System.err.println("Ignoring error callback.");
977 "Unhandled callback " + type + " " + data[1].toString());
980 } catch (Exception e)
982 System.err.println("Squashed Jmol callback handler error:");
988 public boolean notifyEnabled(CBK callbackPick)
990 switch (callbackPick)
1006 // incremented every time a load notification is successfully handled -
1007 // lightweight mechanism for other threads to detect when they can start
1008 // referrring to new structures.
1009 private long loadNotifiesHandled = 0;
1011 public long getLoadNotifiesHandled()
1013 return loadNotifiesHandled;
1016 public void notifyFileLoaded(String fullPathName, String fileName2,
1017 String modelName, String errorMsg, int modelParts)
1019 if (errorMsg != null)
1021 fileLoadingError = errorMsg;
1025 // TODO: deal sensibly with models loaded inLine:
1026 // modelName will be null, as will fullPathName.
1028 // the rest of this routine ignores the arguments, and simply interrogates
1029 // the Jmol view to find out what structures it contains, and adds them to
1030 // the structure selection manager.
1031 fileLoadingError = null;
1032 String[] oldmodels = modelFileNames;
1033 modelFileNames = null;
1034 chainNames = new ArrayList<>();
1035 chainFile = new Hashtable<>();
1036 boolean notifyLoaded = false;
1037 String[] modelfilenames = getStructureFiles();
1038 // first check if we've lost any structures
1039 if (oldmodels != null && oldmodels.length > 0)
1042 for (int i = 0; i < oldmodels.length; i++)
1044 for (int n = 0; n < modelfilenames.length; n++)
1046 if (modelfilenames[n] == oldmodels[i])
1048 oldmodels[i] = null;
1052 if (oldmodels[i] != null)
1059 String[] oldmfn = new String[oldm];
1061 for (int i = 0; i < oldmodels.length; i++)
1063 if (oldmodels[i] != null)
1065 oldmfn[oldm++] = oldmodels[i];
1068 // deregister the Jmol instance for these structures - we'll add
1069 // ourselves again at the end for the current structure set.
1070 getSsm().removeStructureViewerListener(this, oldmfn);
1073 refreshPdbEntries();
1074 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1076 String fileName = modelfilenames[modelnum];
1077 boolean foundEntry = false;
1078 StructureFile pdb = null;
1079 String pdbfile = null;
1080 // model was probably loaded inline - so check the pdb file hashcode
1083 // calculate essential attributes for the pdb data imported inline.
1084 // prolly need to resolve modelnumber properly - for now just use our
1086 pdbfile = viewer.getData(
1087 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1089 // search pdbentries and sequences to find correct pdbentry for this
1091 for (int pe = 0; pe < getPdbCount(); pe++)
1093 boolean matches = false;
1094 addSequence(pe, getSequence()[pe]);
1095 if (fileName == null)
1098 // see JAL-623 - need method of matching pasted data up
1100 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1101 pdbfile, DataSourceType.PASTE,
1102 getIProgressIndicator());
1103 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1110 File fl = new File(getPdbEntry(pe).getFile());
1111 matches = fl.equals(new File(fileName));
1115 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1118 // to be tested. See mantis bug
1119 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1120 DataSourceType protocol = DataSourceType.URL;
1125 protocol = DataSourceType.FILE;
1127 } catch (Exception e)
1132 // Explicitly map to the filename used by Jmol ;
1133 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1134 fileName, protocol, getIProgressIndicator());
1135 // pdbentry[pe].getFile(), protocol);
1141 // add an entry for every chain in the model
1142 for (int i = 0; i < pdb.getChains().size(); i++)
1144 String chid = new String(
1145 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1146 chainFile.put(chid, fileName);
1147 chainNames.add(chid);
1149 notifyLoaded = true;
1153 if (!foundEntry && associateNewStructs)
1155 // this is a foreign pdb file that jalview doesn't know about - add
1156 // it to the dataset and try to find a home - either on a matching
1157 // sequence or as a new sequence.
1158 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1160 // parse pdb file into a chain, etc.
1161 // locate best match for pdb in associated views and add mapping to
1163 // if properly registered then
1164 notifyLoaded = true;
1169 // so finally, update the jmol bits and pieces
1170 // if (jmolpopup != null)
1172 // // potential for deadlock here:
1173 // // jmolpopup.updateComputedMenus();
1175 if (!isLoadingFromArchive())
1177 viewer.evalStringQuiet(
1178 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1180 // register ourselves as a listener and notify the gui that it needs to
1182 getSsm().addStructureViewerListener(this);
1185 FeatureRenderer fr = getFeatureRenderer(null);
1191 loadNotifiesHandled++;
1193 setLoadingFromArchive(false);
1197 public List<String> getChainNames()
1202 protected IProgressIndicator getIProgressIndicator()
1207 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1209 notifyAtomPicked(iatom, strMeasure, null);
1212 public abstract void notifyScriptTermination(String strStatus,
1216 * display a message echoed from the jmol viewer
1220 public abstract void sendConsoleEcho(String strEcho); /*
1221 * { showConsole(true);
1223 * history.append("\n" +
1227 // /End JmolStatusListener
1228 // /////////////////////////////
1232 * status message - usually the response received after a script
1235 public abstract void sendConsoleMessage(String strStatus);
1238 public void setCallbackFunction(String callbackType,
1239 String callbackFunction)
1241 System.err.println("Ignoring set-callback request to associate "
1242 + callbackType + " with function " + callbackFunction);
1247 public void setJalviewColourScheme(ColourSchemeI cs)
1249 colourBySequence = false;
1257 StringBuilder command = new StringBuilder(128);
1258 command.append("select *;color white;");
1259 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1261 for (String resName : residueSet)
1263 char res = resName.length() == 3
1264 ? ResidueProperties.getSingleCharacterCode(resName)
1265 : resName.charAt(0);
1266 Color col = cs.findColour(res, 0, null, null, 0f);
1267 command.append("select " + resName + ";color[" + col.getRed() + ","
1268 + col.getGreen() + "," + col.getBlue() + "];");
1271 evalStateCommand(command.toString());
1275 public void showHelp()
1277 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1281 * open the URL somehow
1285 public abstract void showUrl(String url, String target);
1288 * called when the binding thinks the UI needs to be refreshed after a Jmol
1289 * state change. this could be because structures were loaded, or because an
1290 * error has occured.
1292 public abstract void refreshGUI();
1295 * called to show or hide the associated console window container.
1299 public abstract void showConsole(boolean show);
1302 * @param renderPanel
1304 * - when true will initialise jmol's file IO system (should be false
1305 * in applet context)
1307 * @param documentBase
1309 * @param commandOptions
1311 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1312 String htmlName, URL documentBase, URL codeBase,
1313 String commandOptions)
1315 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1316 codeBase, commandOptions, null, null);
1321 * @param renderPanel
1323 * - when true will initialise jmol's file IO system (should be false
1324 * in applet context)
1326 * @param documentBase
1328 * @param commandOptions
1329 * @param consolePanel
1330 * - panel to contain Jmol console
1331 * @param buttonsToShow
1332 * - buttons to show on the console, in ordr
1334 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1335 String htmlName, URL documentBase, URL codeBase,
1336 String commandOptions, final Container consolePanel,
1337 String buttonsToShow)
1339 if (commandOptions == null)
1341 commandOptions = "";
1343 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1344 (jmolfileio ? new SmarterJmolAdapter() : null),
1345 htmlName + ((Object) this).toString(), documentBase, codeBase,
1346 commandOptions, this);
1348 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1350 console = createJmolConsole(consolePanel, buttonsToShow);
1351 if (consolePanel != null)
1353 consolePanel.addComponentListener(this);
1359 protected abstract JmolAppConsoleInterface createJmolConsole(
1360 Container consolePanel, String buttonsToShow);
1362 protected org.jmol.api.JmolAppConsoleInterface console = null;
1365 public void setBackgroundColour(java.awt.Color col)
1368 viewer.evalStringQuiet("background [" + col.getRed() + ","
1369 + col.getGreen() + "," + col.getBlue() + "];");
1374 public int[] resizeInnerPanel(String data)
1376 // Jalview doesn't honour resize panel requests
1383 protected void closeConsole()
1385 if (console != null)
1389 console.setVisible(false);
1392 } catch (Exception x)
1401 * ComponentListener method
1404 public void componentMoved(ComponentEvent e)
1409 * ComponentListener method
1412 public void componentResized(ComponentEvent e)
1417 * ComponentListener method
1420 public void componentShown(ComponentEvent e)
1426 * ComponentListener method
1429 public void componentHidden(ComponentEvent e)
1435 public void showStructures(AlignViewportI av, boolean refocus)
1437 StringBuilder cmd = new StringBuilder(128);
1439 if (isShowAlignmentOnly())
1441 cmd.append("hide *;");
1443 AtomSpecModel model = getShownResidues(av);
1444 String atomSpec = JmolCommands.getAtomSpec(model);
1446 cmd.append("display ").append(atomSpec);
1450 cmd.append("display *");
1452 cmd.append("; cartoon");
1455 cmd.append("; zoom 100");
1457 evalStateCommand(cmd.toString());
1461 * Answers a Jmol syntax style structure model specification. Model number 0, 1,
1462 * 2... is formatted as "1.1", "2.1", "3.1" etc.
1465 public String getModelSpec(int model)
1467 return String.valueOf(model + 1) + ".1";