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 Hashtable<String, String> chainFile;
83 * the default or current model displayed if the model cannot be identified
84 * from the selection message
88 // protected JmolGenericPopup jmolpopup; // not used - remove?
94 StringBuffer resetLastRes = new StringBuffer();
98 public JalviewJmolBinding(StructureSelectionManager ssm,
99 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
100 DataSourceType protocol)
102 super(ssm, pdbentry, sequenceIs, protocol);
104 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
105 * "jalviewJmol", ap.av.applet .getDocumentBase(),
106 * ap.av.applet.getCodeBase(), "", this);
108 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
112 public JalviewJmolBinding(StructureSelectionManager ssm,
113 SequenceI[][] seqs, Viewer theViewer)
118 viewer.setJmolStatusListener(this);
119 viewer.addSelectionListener(this);
123 * construct a title string for the viewer window based on the data jalview
128 public String getViewerTitle()
130 return getViewerTitle("Jmol", true);
134 * prepare the view for a given set of models/chains. chainList contains strings
135 * of the form 'pdbfilename:Chaincode'
137 * @deprecated now only used by applet code
140 public void centerViewer()
142 StringBuilder cmd = new StringBuilder(128);
144 for (String lbl : chainsToShow)
150 mlength = lbl.indexOf(":", p);
151 } while (p < mlength && mlength < (lbl.length() - 2));
152 // TODO: lookup each pdb id and recover proper model number for it.
153 cmd.append(":" + lbl.substring(mlength + 1) + " /"
154 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
156 if (cmd.length() > 0)
158 cmd.setLength(cmd.length() - 4);
160 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
161 evalStateCommand(command);
164 public void closeViewer()
166 // remove listeners for all structures in viewer
167 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
171 releaseUIResources();
175 public void colourByChain()
177 colourBySequence = false;
178 // TODO: colour by chain should colour each chain distinctly across all
180 // TODO: http://issues.jalview.org/browse/JAL-628
181 evalStateCommand("select *;color chain");
185 public void colourByCharge()
187 colourBySequence = false;
188 evalStateCommand("select *;color white;select ASP,GLU;color red;"
189 + "select LYS,ARG;color blue;select CYS;color yellow");
193 * superpose the structures associated with sequences in the alignment
194 * according to their corresponding positions.
196 public void superposeStructures(AlignmentI alignment)
198 superposeStructures(alignment, -1, null);
202 * superpose the structures associated with sequences in the alignment
203 * according to their corresponding positions. ded)
205 * @param refStructure
206 * - select which pdb file to use as reference (default is -1 - the
207 * first structure in the alignment)
209 public void superposeStructures(AlignmentI alignment, int refStructure)
211 superposeStructures(alignment, refStructure, null);
215 * superpose the structures associated with sequences in the alignment
216 * according to their corresponding positions. ded)
218 * @param refStructure
219 * - select which pdb file to use as reference (default is -1 - the
220 * first structure in the alignment)
224 public void superposeStructures(AlignmentI alignment, int refStructure,
225 HiddenColumns hiddenCols)
227 superposeStructures(new AlignmentI[] { alignment },
229 { refStructure }, new HiddenColumns[] { hiddenCols });
236 public String superposeStructures(AlignmentI[] _alignment,
237 int[] _refStructure, HiddenColumns[] _hiddenCols)
239 while (viewer.isScriptExecuting())
244 } catch (InterruptedException i)
250 * get the distinct structure files modelled
251 * (a file with multiple chains may map to multiple sequences)
253 String[] files = getStructureFiles();
254 if (!waitForFileLoad(files))
259 StringBuilder selectioncom = new StringBuilder(256);
260 // In principle - nSeconds specifies the speed of animation for each
261 // superposition - but is seems to behave weirdly, so we don't specify it.
262 String nSeconds = " ";
263 if (files.length > 10)
265 nSeconds = " 0.005 ";
269 nSeconds = " " + (2.0 / files.length) + " ";
270 // if (nSeconds).substring(0,5)+" ";
273 // see JAL-1345 - should really automatically turn off the animation for
274 // large numbers of structures, but Jmol doesn't seem to allow that.
276 // union of all aligned positions are collected together.
277 for (int a = 0; a < _alignment.length; a++)
279 int refStructure = _refStructure[a];
280 AlignmentI alignment = _alignment[a];
281 HiddenColumns hiddenCols = _hiddenCols[a];
282 if (a > 0 && selectioncom.length() > 0 && !selectioncom
283 .substring(selectioncom.length() - 1).equals("|"))
285 selectioncom.append("|");
287 // process this alignment
288 if (refStructure >= files.length)
291 "Invalid reference structure value " + refStructure);
296 * 'matched' bit j will be set for visible alignment columns j where
297 * all sequences have a residue with a mapping to the PDB structure
299 BitSet matched = new BitSet();
300 for (int m = 0; m < alignment.getWidth(); m++)
302 if (hiddenCols == null || hiddenCols.isVisible(m))
308 SuperposeData[] structures = new SuperposeData[files.length];
309 for (int f = 0; f < files.length; f++)
311 structures[f] = new SuperposeData(alignment.getWidth());
315 * Calculate the superposable alignment columns ('matched'), and the
316 * corresponding structure residue positions (structures.pdbResNo)
318 int candidateRefStructure = findSuperposableResidues(alignment,
319 matched, structures);
320 if (refStructure < 0)
323 * If no reference structure was specified, pick the first one that has
324 * a mapping in the alignment
326 refStructure = candidateRefStructure;
329 String[] selcom = new String[files.length];
330 int nmatched = matched.cardinality();
333 return (MessageManager.formatMessage("label.insufficient_residues",
338 * generate select statements to select regions to superimpose structures
341 // TODO extract method to construct selection statements
342 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
344 String chainCd = ":" + structures[pdbfnum].chain;
347 StringBuilder molsel = new StringBuilder();
350 int nextColumnMatch = matched.nextSetBit(0);
351 while (nextColumnMatch != -1)
353 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
354 if (lpos != pdbResNo - 1)
360 molsel.append(chainCd);
367 // continuous run - and lpos >-1
370 // at the beginning, so add dash
377 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
380 * add final selection phrase
385 molsel.append(chainCd);
388 if (molsel.length() > 1)
390 selcom[pdbfnum] = molsel.toString();
391 selectioncom.append("((");
392 selectioncom.append(selcom[pdbfnum].substring(1,
393 selcom[pdbfnum].length() - 1));
394 selectioncom.append(" )& ");
395 selectioncom.append(pdbfnum + 1);
396 selectioncom.append(".1)");
397 if (pdbfnum < files.length - 1)
399 selectioncom.append("|");
404 selcom[pdbfnum] = null;
408 StringBuilder command = new StringBuilder(256);
409 // command.append("set spinFps 10;\n");
411 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
413 if (pdbfnum == refStructure || selcom[pdbfnum] == null
414 || selcom[refStructure] == null)
418 command.append("echo ");
419 command.append("\"Superposing (");
420 command.append(structures[pdbfnum].pdbId);
421 command.append(") against reference (");
422 command.append(structures[refStructure].pdbId);
423 command.append(")\";\ncompare " + nSeconds);
425 command.append(Integer.toString(1 + pdbfnum));
426 command.append(".1} {");
427 command.append(Integer.toString(1 + refStructure));
428 // conformation=1 excludes alternate locations for CA (JAL-1757)
430 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
432 // for (int s = 0; s < 2; s++)
434 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
436 command.append(selcom[pdbfnum]);
437 command.append(selcom[refStructure]);
438 command.append(" ROTATE TRANSLATE;\n");
440 if (selectioncom.length() > 0)
442 // TODO is performing selectioncom redundant here? is done later on
443 // System.out.println("Select regions:\n" + selectioncom.toString());
444 evalStateCommand("select *; cartoons off; backbone; select ("
445 + selectioncom.toString() + "); cartoons; ");
446 // selcom.append("; ribbons; ");
447 String cmdString = command.toString();
448 // System.out.println("Superimpose command(s):\n" + cmdString);
450 evalStateCommand(cmdString);
453 if (selectioncom.length() > 0)
454 {// finally, mark all regions that were superposed.
455 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
457 selectioncom.setLength(selectioncom.length() - 1);
459 // System.out.println("Select regions:\n" + selectioncom.toString());
460 evalStateCommand("select *; cartoons off; backbone; select ("
461 + selectioncom.toString() + "); cartoons; ");
462 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
463 // cartoons; center "+selcom.toString());
469 public void evalStateCommand(String command)
472 if (lastCommand == null || !lastCommand.equals(command))
474 viewer.evalStringQuiet(command + "\n");
477 lastCommand = command;
480 Thread colourby = null;
483 * Sends a set of colour commands to the structure viewer
488 protected void colourBySequence(final String[] commands)
490 if (colourby != null)
492 colourby.interrupt();
495 colourby = new Thread(new Runnable()
500 for (String cmd : commands)
502 executeWhenReady(cmd);
515 protected String[] getColourBySequenceCommands(
516 String[] files, AlignmentViewPanel viewPanel)
518 Map<Object, AtomSpecModel> map = buildColoursMap(viewPanel);
520 return JmolCommands.getColourBySequenceCommand(map);
526 protected void executeWhenReady(String command)
528 evalStateCommand(command);
531 public void createImage(String file, String type, int quality)
533 System.out.println("JMOL CREATE IMAGE");
537 public String createImage(String fileName, String type,
538 Object textOrBytes, int quality)
540 System.out.println("JMOL CREATE IMAGE");
545 public String eval(String strEval)
547 // System.out.println(strEval);
548 // "# 'eval' is implemented only for the applet.";
552 // End StructureListener
553 // //////////////////////////
556 public float[][] functionXY(String functionName, int x, int y)
562 public float[][][] functionXYZ(String functionName, int nx, int ny,
565 // TODO Auto-generated method stub
569 public Color getColour(int atomIndex, int pdbResNum, String chain,
572 if (getModelNum(pdbfile) < 0)
576 // TODO: verify atomIndex is selecting correct model.
577 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
578 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
579 return new Color(colour);
583 * instruct the Jalview binding to update the pdbentries vector if necessary
584 * prior to matching the jmol view's contents to the list of structure files
585 * Jalview knows about.
587 public abstract void refreshPdbEntries();
589 private int getModelNum(String modelFileName)
591 String[] mfn = getStructureFiles();
596 for (int i = 0; i < mfn.length; i++)
598 if (mfn[i].equalsIgnoreCase(modelFileName))
607 * map between index of model filename returned from getPdbFile and the first
608 * index of models from this file in the viewer. Note - this is not trimmed -
609 * use getPdbFile to get number of unique models.
611 private int _modelFileNameMap[];
614 public synchronized String[] getStructureFiles()
616 List<String> mset = new ArrayList<>();
619 return new String[0];
622 if (modelFileNames == null)
624 int modelCount = viewer.ms.mc;
625 String filePath = null;
626 for (int i = 0; i < modelCount; ++i)
628 filePath = viewer.ms.getModelFileName(i);
629 if (!mset.contains(filePath))
634 modelFileNames = mset.toArray(new String[mset.size()]);
637 return modelFileNames;
641 * map from string to applet
644 public Map<String, Object> getRegistryInfo()
646 // TODO Auto-generated method stub
650 // ///////////////////////////////
651 // JmolStatusListener
653 public void handlePopupMenu(int x, int y)
655 // jmolpopup.show(x, y);
656 // jmolpopup.jpiShow(x, y);
660 * Highlight zero, one or more atoms on the structure
663 public void highlightAtoms(List<AtomSpec> atoms)
667 if (resetLastRes.length() > 0)
669 viewer.evalStringQuiet(resetLastRes.toString());
670 resetLastRes.setLength(0);
672 for (AtomSpec atom : atoms)
674 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
675 atom.getChain(), atom.getPdbFile());
681 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
684 if (modelFileNames == null)
689 // look up file model number for this pdbfile
691 // may need to adjust for URLencoding here - we don't worry about that yet.
692 while (mdlNum < modelFileNames.length
693 && !pdbfile.equals(modelFileNames[mdlNum]))
697 if (mdlNum == modelFileNames.length)
704 StringBuilder cmd = new StringBuilder(64);
705 cmd.append("select " + pdbResNum); // +modelNum
707 resetLastRes.append("select " + pdbResNum); // +modelNum
710 resetLastRes.append(":");
711 if (!chain.equals(" "))
714 resetLastRes.append(chain);
717 cmd.append(" /" + (mdlNum + 1));
718 resetLastRes.append("/" + (mdlNum + 1));
720 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
722 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
723 + " and not hetero; spacefill 0;");
725 cmd.append("spacefill 200;select none");
727 viewer.evalStringQuiet(cmd.toString());
732 boolean debug = true;
734 private void jmolHistory(boolean enable)
736 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
739 public void loadInline(String string)
743 // viewer.loadInline(strModel, isAppend);
745 // construct fake fullPathName and fileName so we can identify the file
747 // Then, construct pass a reader for the string to Jmol.
748 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
749 // fileName, null, reader, false, null, null, 0);
750 viewer.openStringInline(string);
753 protected void mouseOverStructure(int atomIndex, final String strInfo)
756 int alocsep = strInfo.indexOf("^");
757 int mdlSep = strInfo.indexOf("/");
758 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
760 if (chainSeparator == -1)
762 chainSeparator = strInfo.indexOf(".");
763 if (mdlSep > -1 && mdlSep < chainSeparator)
765 chainSeparator1 = chainSeparator;
766 chainSeparator = mdlSep;
769 // handle insertion codes
772 pdbResNum = Integer.parseInt(
773 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
778 pdbResNum = Integer.parseInt(
779 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
783 if (strInfo.indexOf(":") > -1)
785 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
786 strInfo.indexOf("."));
793 String pdbfilename = modelFileNames[frameNo]; // default is first or current
797 if (chainSeparator1 == -1)
799 chainSeparator1 = strInfo.indexOf(".", mdlSep);
801 String mdlId = (chainSeparator1 > -1)
802 ? strInfo.substring(mdlSep + 1, chainSeparator1)
803 : strInfo.substring(mdlSep + 1);
806 // recover PDB filename for the model hovered over.
807 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
808 if (_modelFileNameMap != null)
810 int _mp = _modelFileNameMap.length - 1;
812 while (mnumber < _modelFileNameMap[_mp])
816 pdbfilename = modelFileNames[_mp];
820 if (mnumber >= 0 && mnumber < modelFileNames.length)
822 pdbfilename = modelFileNames[mnumber];
825 if (pdbfilename == null)
827 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
831 } catch (Exception e)
837 * highlight position on alignment(s); if some text is returned,
838 * show this as a second line on the structure hover tooltip
840 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
844 // change comma to pipe separator (newline token for Jmol)
845 label = label.replace(',', '|');
846 StringTokenizer toks = new StringTokenizer(strInfo, " ");
847 StringBuilder sb = new StringBuilder();
848 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
849 .append(chainId).append("/1");
850 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
851 .append(toks.nextToken());
852 sb.append("|").append(label).append("\"");
853 evalStateCommand(sb.toString());
857 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
859 if (strInfo.equals(lastMessage))
863 lastMessage = strInfo;
866 System.err.println("Ignoring additional hover info: " + data
867 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
869 mouseOverStructure(atomIndex, strInfo);
873 * { if (history != null && strStatus != null &&
874 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
878 public void notifyAtomPicked(int atomIndex, String strInfo,
882 * this implements the toggle label behaviour copied from the original
883 * structure viewer, MCView
887 System.err.println("Ignoring additional pick data string " + strData);
889 int chainSeparator = strInfo.indexOf(":");
891 if (chainSeparator == -1)
893 chainSeparator = strInfo.indexOf(".");
896 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
898 String mdlString = "";
899 if ((p = strInfo.indexOf(":")) > -1)
901 picked += strInfo.substring(p, strInfo.indexOf("."));
904 if ((p = strInfo.indexOf("/")) > -1)
906 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
908 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
912 if (!atomsPicked.contains(picked))
914 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
915 atomsPicked.addElement(picked);
919 viewer.evalString("select " + picked + ";label off");
920 atomsPicked.removeElement(picked);
923 // TODO: in application this happens
925 // if (scriptWindow != null)
927 // scriptWindow.sendConsoleMessage(strInfo);
928 // scriptWindow.sendConsoleMessage("\n");
934 public void notifyCallback(CBK type, Object[] data)
941 notifyFileLoaded((String) data[1], (String) data[2],
942 (String) data[3], (String) data[4],
943 ((Integer) data[5]).intValue());
947 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
949 // also highlight in alignment
950 // deliberate fall through
952 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
956 notifyScriptTermination((String) data[2],
957 ((Integer) data[3]).intValue());
960 sendConsoleEcho((String) data[1]);
964 (data == null) ? ((String) null) : (String) data[1]);
967 // System.err.println("Ignoring error callback.");
978 "Unhandled callback " + type + " " + data[1].toString());
981 } catch (Exception e)
983 System.err.println("Squashed Jmol callback handler error:");
989 public boolean notifyEnabled(CBK callbackPick)
991 switch (callbackPick)
1007 // incremented every time a load notification is successfully handled -
1008 // lightweight mechanism for other threads to detect when they can start
1009 // referrring to new structures.
1010 private long loadNotifiesHandled = 0;
1012 public long getLoadNotifiesHandled()
1014 return loadNotifiesHandled;
1017 public void notifyFileLoaded(String fullPathName, String fileName2,
1018 String modelName, String errorMsg, int modelParts)
1020 if (errorMsg != null)
1022 fileLoadingError = errorMsg;
1026 // TODO: deal sensibly with models loaded inLine:
1027 // modelName will be null, as will fullPathName.
1029 // the rest of this routine ignores the arguments, and simply interrogates
1030 // the Jmol view to find out what structures it contains, and adds them to
1031 // the structure selection manager.
1032 fileLoadingError = null;
1033 String[] oldmodels = modelFileNames;
1034 modelFileNames = null;
1035 chainNames = new ArrayList<>();
1036 chainFile = new Hashtable<>();
1037 boolean notifyLoaded = false;
1038 String[] modelfilenames = getStructureFiles();
1039 // first check if we've lost any structures
1040 if (oldmodels != null && oldmodels.length > 0)
1043 for (int i = 0; i < oldmodels.length; i++)
1045 for (int n = 0; n < modelfilenames.length; n++)
1047 if (modelfilenames[n] == oldmodels[i])
1049 oldmodels[i] = null;
1053 if (oldmodels[i] != null)
1060 String[] oldmfn = new String[oldm];
1062 for (int i = 0; i < oldmodels.length; i++)
1064 if (oldmodels[i] != null)
1066 oldmfn[oldm++] = oldmodels[i];
1069 // deregister the Jmol instance for these structures - we'll add
1070 // ourselves again at the end for the current structure set.
1071 getSsm().removeStructureViewerListener(this, oldmfn);
1074 refreshPdbEntries();
1075 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1077 String fileName = modelfilenames[modelnum];
1078 boolean foundEntry = false;
1079 StructureFile pdb = null;
1080 String pdbfile = null;
1081 // model was probably loaded inline - so check the pdb file hashcode
1084 // calculate essential attributes for the pdb data imported inline.
1085 // prolly need to resolve modelnumber properly - for now just use our
1087 pdbfile = viewer.getData(
1088 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1090 // search pdbentries and sequences to find correct pdbentry for this
1092 for (int pe = 0; pe < getPdbCount(); pe++)
1094 boolean matches = false;
1095 addSequence(pe, getSequence()[pe]);
1096 if (fileName == null)
1099 // see JAL-623 - need method of matching pasted data up
1101 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1102 pdbfile, DataSourceType.PASTE,
1103 getIProgressIndicator());
1104 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1111 File fl = new File(getPdbEntry(pe).getFile());
1112 matches = fl.equals(new File(fileName));
1116 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1119 // to be tested. See mantis bug
1120 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1121 DataSourceType protocol = DataSourceType.URL;
1126 protocol = DataSourceType.FILE;
1128 } catch (Exception e)
1133 // Explicitly map to the filename used by Jmol ;
1134 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1135 fileName, protocol, getIProgressIndicator());
1136 // pdbentry[pe].getFile(), protocol);
1142 // add an entry for every chain in the model
1143 for (int i = 0; i < pdb.getChains().size(); i++)
1145 String chid = new String(
1146 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1147 chainFile.put(chid, fileName);
1148 chainNames.add(chid);
1150 notifyLoaded = true;
1154 if (!foundEntry && associateNewStructs)
1156 // this is a foreign pdb file that jalview doesn't know about - add
1157 // it to the dataset and try to find a home - either on a matching
1158 // sequence or as a new sequence.
1159 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1161 // parse pdb file into a chain, etc.
1162 // locate best match for pdb in associated views and add mapping to
1164 // if properly registered then
1165 notifyLoaded = true;
1170 // so finally, update the jmol bits and pieces
1171 // if (jmolpopup != null)
1173 // // potential for deadlock here:
1174 // // jmolpopup.updateComputedMenus();
1176 if (!isLoadingFromArchive())
1178 viewer.evalStringQuiet(
1179 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1181 // register ourselves as a listener and notify the gui that it needs to
1183 getSsm().addStructureViewerListener(this);
1186 FeatureRenderer fr = getFeatureRenderer(null);
1192 loadNotifiesHandled++;
1194 setLoadingFromArchive(false);
1197 protected IProgressIndicator getIProgressIndicator()
1202 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1204 notifyAtomPicked(iatom, strMeasure, null);
1207 public abstract void notifyScriptTermination(String strStatus,
1211 * display a message echoed from the jmol viewer
1215 public abstract void sendConsoleEcho(String strEcho); /*
1216 * { showConsole(true);
1218 * history.append("\n" +
1222 // /End JmolStatusListener
1223 // /////////////////////////////
1227 * status message - usually the response received after a script
1230 public abstract void sendConsoleMessage(String strStatus);
1233 public void setCallbackFunction(String callbackType,
1234 String callbackFunction)
1236 System.err.println("Ignoring set-callback request to associate "
1237 + callbackType + " with function " + callbackFunction);
1242 public void setJalviewColourScheme(ColourSchemeI cs)
1244 colourBySequence = false;
1252 StringBuilder command = new StringBuilder(128);
1253 command.append("select *;color white;");
1254 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1256 for (String resName : residueSet)
1258 char res = resName.length() == 3
1259 ? ResidueProperties.getSingleCharacterCode(resName)
1260 : resName.charAt(0);
1261 Color col = cs.findColour(res, 0, null, null, 0f);
1262 command.append("select " + resName + ";color[" + col.getRed() + ","
1263 + col.getGreen() + "," + col.getBlue() + "];");
1266 evalStateCommand(command.toString());
1270 public void showHelp()
1272 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1276 * open the URL somehow
1280 public abstract void showUrl(String url, String target);
1283 * called when the binding thinks the UI needs to be refreshed after a Jmol
1284 * state change. this could be because structures were loaded, or because an
1285 * error has occured.
1287 public abstract void refreshGUI();
1290 * called to show or hide the associated console window container.
1294 public abstract void showConsole(boolean show);
1297 * @param renderPanel
1299 * - when true will initialise jmol's file IO system (should be false
1300 * in applet context)
1302 * @param documentBase
1304 * @param commandOptions
1306 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1307 String htmlName, URL documentBase, URL codeBase,
1308 String commandOptions)
1310 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1311 codeBase, commandOptions, null, null);
1316 * @param renderPanel
1318 * - when true will initialise jmol's file IO system (should be false
1319 * in applet context)
1321 * @param documentBase
1323 * @param commandOptions
1324 * @param consolePanel
1325 * - panel to contain Jmol console
1326 * @param buttonsToShow
1327 * - buttons to show on the console, in ordr
1329 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1330 String htmlName, URL documentBase, URL codeBase,
1331 String commandOptions, final Container consolePanel,
1332 String buttonsToShow)
1334 if (commandOptions == null)
1336 commandOptions = "";
1338 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1339 (jmolfileio ? new SmarterJmolAdapter() : null),
1340 htmlName + ((Object) this).toString(), documentBase, codeBase,
1341 commandOptions, this);
1343 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1345 console = createJmolConsole(consolePanel, buttonsToShow);
1346 if (consolePanel != null)
1348 consolePanel.addComponentListener(this);
1354 protected abstract JmolAppConsoleInterface createJmolConsole(
1355 Container consolePanel, String buttonsToShow);
1357 protected org.jmol.api.JmolAppConsoleInterface console = null;
1360 public void setBackgroundColour(java.awt.Color col)
1363 viewer.evalStringQuiet("background [" + col.getRed() + ","
1364 + col.getGreen() + "," + col.getBlue() + "];");
1369 public int[] resizeInnerPanel(String data)
1371 // Jalview doesn't honour resize panel requests
1378 protected void closeConsole()
1380 if (console != null)
1384 console.setVisible(false);
1387 } catch (Exception x)
1396 * ComponentListener method
1399 public void componentMoved(ComponentEvent e)
1404 * ComponentListener method
1407 public void componentResized(ComponentEvent e)
1412 * ComponentListener method
1415 public void componentShown(ComponentEvent e)
1421 * ComponentListener method
1424 public void componentHidden(ComponentEvent e)
1430 public void showStructures(AlignViewportI av, boolean refocus)
1432 StringBuilder cmd = new StringBuilder(128);
1434 if (isShowAlignmentOnly())
1436 cmd.append("hide *;");
1438 AtomSpecModel model = getShownResidues(av);
1439 String atomSpec = JmolCommands.getAtomSpec(model);
1441 cmd.append("display ").append(atomSpec);
1445 cmd.append("display *");
1447 cmd.append("; cartoon");
1450 cmd.append("; zoom 0");
1452 evalStateCommand(cmd.toString());
1456 * Answers a Jmol syntax style structure model specification. Model number 0, 1,
1457 * 2... is formatted as "1.1", "2.1", "3.1" etc.
1460 public String getModelSpec(int model)
1462 return String.valueOf(model + 1) + ".1";