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.AlignmentViewPanel;
24 import jalview.api.FeatureRenderer;
25 import jalview.api.SequenceRenderer;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.HiddenColumns;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.SequenceI;
30 import jalview.gui.IProgressIndicator;
31 import jalview.io.DataSourceType;
32 import jalview.io.StructureFile;
33 import jalview.schemes.ColourSchemeI;
34 import jalview.schemes.ResidueProperties;
35 import jalview.structure.AtomSpec;
36 import jalview.structure.StructureMappingcommandSet;
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.Vector;
54 import org.jmol.adapter.smarter.SmarterJmolAdapter;
55 import org.jmol.api.JmolAppConsoleInterface;
56 import org.jmol.api.JmolSelectionListener;
57 import org.jmol.api.JmolStatusListener;
58 import org.jmol.api.JmolViewer;
59 import org.jmol.c.CBK;
60 import org.jmol.script.T;
61 import org.jmol.viewer.Viewer;
63 public abstract class JalviewJmolBinding extends AAStructureBindingModel
64 implements JmolStatusListener, JmolSelectionListener,
67 boolean allChainsSelected = false;
70 * when true, try to search the associated datamodel for sequences that are
71 * associated with any unknown structures in the Jmol view.
73 private boolean associateNewStructs = false;
75 Vector<String> atomsPicked = new Vector<>();
77 private List<String> chainNames;
79 Hashtable<String, String> chainFile;
82 * the default or current model displayed if the model cannot be identified
83 * from the selection message
87 // protected JmolGenericPopup jmolpopup; // not used - remove?
95 StringBuffer resetLastRes = new StringBuffer();
99 public JalviewJmolBinding(StructureSelectionManager ssm,
100 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
101 DataSourceType protocol)
103 super(ssm, pdbentry, sequenceIs, protocol);
105 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
106 * "jalviewJmol", ap.av.applet .getDocumentBase(),
107 * ap.av.applet.getCodeBase(), "", this);
109 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
113 public JalviewJmolBinding(StructureSelectionManager ssm,
114 SequenceI[][] seqs, Viewer theViewer)
119 viewer.setJmolStatusListener(this);
120 viewer.addSelectionListener(this);
124 * construct a title string for the viewer window based on the data jalview
129 public String getViewerTitle()
131 return getViewerTitle("Jmol", true);
135 * prepare the view for a given set of models/chains. chainList contains
136 * strings of the form 'pdbfilename:Chaincode'
139 * list of chains to make visible
141 public void centerViewer(Vector<String> chainList)
143 StringBuilder cmd = new StringBuilder(128);
145 for (String lbl : chainList)
151 mlength = lbl.indexOf(":", p);
152 } while (p < mlength && mlength < (lbl.length() - 2));
153 // TODO: lookup each pdb id and recover proper model number for it.
154 cmd.append(":" + lbl.substring(mlength + 1) + " /"
155 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
157 if (cmd.length() > 0)
159 cmd.setLength(cmd.length() - 4);
161 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
164 public void closeViewer()
166 // remove listeners for all structures in viewer
167 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
174 releaseUIResources();
178 public void colourByChain()
180 colourBySequence = false;
181 // TODO: colour by chain should colour each chain distinctly across all
183 // TODO: http://issues.jalview.org/browse/JAL-628
184 evalStateCommand("select *;color chain");
188 public void colourByCharge()
190 colourBySequence = false;
191 evalStateCommand("select *;color white;select ASP,GLU;color red;"
192 + "select LYS,ARG;color blue;select CYS;color yellow");
196 * superpose the structures associated with sequences in the alignment
197 * according to their corresponding positions.
199 public void superposeStructures(AlignmentI alignment)
201 superposeStructures(alignment, -1, null);
205 * superpose the structures associated with sequences in the alignment
206 * according to their corresponding positions. ded)
208 * @param refStructure
209 * - select which pdb file to use as reference (default is -1 - the
210 * first structure in the alignment)
212 public void superposeStructures(AlignmentI alignment, int refStructure)
214 superposeStructures(alignment, refStructure, null);
218 * superpose the structures associated with sequences in the alignment
219 * according to their corresponding positions. ded)
221 * @param refStructure
222 * - select which pdb file to use as reference (default is -1 - the
223 * first structure in the alignment)
227 public void superposeStructures(AlignmentI alignment, int refStructure,
228 HiddenColumns hiddenCols)
230 superposeStructures(new AlignmentI[] { alignment },
232 { refStructure }, new HiddenColumns[] { hiddenCols });
239 public String superposeStructures(AlignmentI[] _alignment,
240 int[] _refStructure, HiddenColumns[] _hiddenCols)
242 while (viewer.isScriptExecuting())
247 } catch (InterruptedException i)
253 * get the distinct structure files modelled
254 * (a file with multiple chains may map to multiple sequences)
256 String[] files = getStructureFiles();
257 if (!waitForFileLoad(files))
262 StringBuilder selectioncom = new StringBuilder(256);
263 // In principle - nSeconds specifies the speed of animation for each
264 // superposition - but is seems to behave weirdly, so we don't specify it.
265 String nSeconds = " ";
266 if (files.length > 10)
268 nSeconds = " 0.005 ";
272 nSeconds = " " + (2.0 / files.length) + " ";
273 // if (nSeconds).substring(0,5)+" ";
276 // see JAL-1345 - should really automatically turn off the animation for
277 // large numbers of structures, but Jmol doesn't seem to allow that.
279 // union of all aligned positions are collected together.
280 for (int a = 0; a < _alignment.length; a++)
282 int refStructure = _refStructure[a];
283 AlignmentI alignment = _alignment[a];
284 HiddenColumns hiddenCols = _hiddenCols[a];
285 if (a > 0 && selectioncom.length() > 0 && !selectioncom
286 .substring(selectioncom.length() - 1).equals("|"))
288 selectioncom.append("|");
290 // process this alignment
291 if (refStructure >= files.length)
294 "Invalid reference structure value " + refStructure);
299 * 'matched' bit j will be set for visible alignment columns j where
300 * all sequences have a residue with a mapping to the PDB structure
302 BitSet matched = new BitSet();
303 for (int m = 0; m < alignment.getWidth(); m++)
305 if (hiddenCols == null || hiddenCols.isVisible(m))
311 SuperposeData[] structures = new SuperposeData[files.length];
312 for (int f = 0; f < files.length; f++)
314 structures[f] = new SuperposeData(alignment.getWidth());
318 * Calculate the superposable alignment columns ('matched'), and the
319 * corresponding structure residue positions (structures.pdbResNo)
321 int candidateRefStructure = findSuperposableResidues(alignment,
322 matched, structures);
323 if (refStructure < 0)
326 * If no reference structure was specified, pick the first one that has
327 * a mapping in the alignment
329 refStructure = candidateRefStructure;
332 String[] selcom = new String[files.length];
333 int nmatched = matched.cardinality();
336 return (MessageManager.formatMessage("label.insufficient_residues",
341 * generate select statements to select regions to superimpose structures
344 // TODO extract method to construct selection statements
345 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
347 String chainCd = ":" + structures[pdbfnum].chain;
350 StringBuilder molsel = new StringBuilder();
353 int nextColumnMatch = matched.nextSetBit(0);
354 while (nextColumnMatch != -1)
356 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
357 if (lpos != pdbResNo - 1)
363 molsel.append(chainCd);
370 // continuous run - and lpos >-1
373 // at the beginning, so add dash
380 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
383 * add final selection phrase
388 molsel.append(chainCd);
391 if (molsel.length() > 1)
393 selcom[pdbfnum] = molsel.toString();
394 selectioncom.append("((");
395 selectioncom.append(selcom[pdbfnum].substring(1,
396 selcom[pdbfnum].length() - 1));
397 selectioncom.append(" )& ");
398 selectioncom.append(pdbfnum + 1);
399 selectioncom.append(".1)");
400 if (pdbfnum < files.length - 1)
402 selectioncom.append("|");
407 selcom[pdbfnum] = null;
411 StringBuilder command = new StringBuilder(256);
412 // command.append("set spinFps 10;\n");
414 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
416 if (pdbfnum == refStructure || selcom[pdbfnum] == null
417 || selcom[refStructure] == null)
421 command.append("echo ");
422 command.append("\"Superposing (");
423 command.append(structures[pdbfnum].pdbId);
424 command.append(") against reference (");
425 command.append(structures[refStructure].pdbId);
426 command.append(")\";\ncompare " + nSeconds);
428 command.append(Integer.toString(1 + pdbfnum));
429 command.append(".1} {");
430 command.append(Integer.toString(1 + refStructure));
431 // conformation=1 excludes alternate locations for CA (JAL-1757)
433 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
435 // for (int s = 0; s < 2; s++)
437 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
439 command.append(selcom[pdbfnum]);
440 command.append(selcom[refStructure]);
441 command.append(" ROTATE TRANSLATE;\n");
443 if (selectioncom.length() > 0)
445 // TODO is performing selectioncom redundant here? is done later on
446 // System.out.println("Select regions:\n" + selectioncom.toString());
447 evalStateCommand("select *; cartoons off; backbone; select ("
448 + selectioncom.toString() + "); cartoons; ");
449 // selcom.append("; ribbons; ");
450 String cmdString = command.toString();
451 // System.out.println("Superimpose command(s):\n" + cmdString);
453 evalStateCommand(cmdString);
456 if (selectioncom.length() > 0)
457 {// finally, mark all regions that were superposed.
458 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
460 selectioncom.setLength(selectioncom.length() - 1);
462 // System.out.println("Select regions:\n" + selectioncom.toString());
463 evalStateCommand("select *; cartoons off; backbone; select ("
464 + selectioncom.toString() + "); cartoons; ");
465 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
466 // cartoons; center "+selcom.toString());
472 public void evalStateCommand(String command)
475 if (lastCommand == null || !lastCommand.equals(command))
477 jmolScript(command + "\n");
480 lastCommand = command;
483 Thread colourby = null;
486 * Sends a set of colour commands to the structure viewer
488 * @param colourBySequenceCommands
491 protected void colourBySequence(
492 final StructureMappingcommandSet[] colourBySequenceCommands)
494 if (colourby != null)
496 colourby.interrupt();
499 Thread colourby = new Thread(new Runnable()
504 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
506 for (String cbyseq : cpdbbyseq.commands)
508 executeWhenReady(cbyseq);
514 this.colourby = colourby;
524 protected StructureMappingcommandSet[] getColourBySequenceCommands(
525 String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
527 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
528 getSequence(), sr, viewPanel);
534 protected void executeWhenReady(String command)
536 evalStateCommand(command);
539 public void createImage(String file, String type, int quality)
541 System.out.println("JMOL CREATE IMAGE");
545 public String createImage(String fileName, String type,
546 Object textOrBytes, int quality)
548 System.out.println("JMOL CREATE IMAGE");
553 public String eval(String strEval)
555 // System.out.println(strEval);
556 // "# 'eval' is implemented only for the applet.";
560 // End StructureListener
561 // //////////////////////////
564 public float[][] functionXY(String functionName, int x, int y)
570 public float[][][] functionXYZ(String functionName, int nx, int ny,
573 // TODO Auto-generated method stub
577 public Color getColour(int atomIndex, int pdbResNum, String chain,
580 if (getModelNum(pdbfile) < 0)
584 // TODO: verify atomIndex is selecting correct model.
585 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
586 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
587 return new Color(colour);
591 * instruct the Jalview binding to update the pdbentries vector if necessary
592 * prior to matching the jmol view's contents to the list of structure files
593 * Jalview knows about.
595 public abstract void refreshPdbEntries();
597 private int getModelNum(String modelFileName)
599 String[] mfn = getStructureFiles();
604 for (int i = 0; i < mfn.length; i++)
606 if (mfn[i].equalsIgnoreCase(modelFileName))
615 * map between index of model filename returned from getPdbFile and the first
616 * index of models from this file in the viewer. Note - this is not trimmed -
617 * use getPdbFile to get number of unique models.
619 private int _modelFileNameMap[];
622 public synchronized String[] getStructureFiles()
624 List<String> mset = new ArrayList<>();
627 return new String[0];
630 if (modelFileNames == null)
632 int modelCount = viewer.ms.mc;
633 String filePath = null;
634 for (int i = 0; i < modelCount; ++i)
636 filePath = viewer.ms.getModelFileName(i);
637 if (!mset.contains(filePath))
642 modelFileNames = mset.toArray(new String[mset.size()]);
645 return modelFileNames;
649 * map from string to applet
652 public Map<String, Object> getRegistryInfo()
654 // TODO Auto-generated method stub
658 // ///////////////////////////////
659 // JmolStatusListener
661 public void handlePopupMenu(int x, int y)
663 // jmolpopup.show(x, y);
664 // jmolpopup.jpiShow(x, y);
668 * Highlight zero, one or more atoms on the structure
671 public void highlightAtoms(List<AtomSpec> atoms)
675 if (resetLastRes.length() > 0)
677 jmolScript(resetLastRes.toString());
678 resetLastRes.setLength(0);
680 for (AtomSpec atom : atoms)
682 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
683 atom.getChain(), atom.getPdbFile());
689 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
692 if (modelFileNames == null)
697 // look up file model number for this pdbfile
699 // may need to adjust for URLencoding here - we don't worry about that yet.
700 while (mdlNum < modelFileNames.length
701 && !pdbfile.equals(modelFileNames[mdlNum]))
705 if (mdlNum == modelFileNames.length)
712 StringBuilder cmd = new StringBuilder(64);
713 cmd.append("select " + pdbResNum); // +modelNum
715 resetLastRes.append("select " + pdbResNum); // +modelNum
718 resetLastRes.append(":");
719 if (!chain.equals(" "))
722 resetLastRes.append(chain);
725 cmd.append(" /" + (mdlNum + 1));
726 resetLastRes.append("/" + (mdlNum + 1));
728 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
730 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
731 + " and not hetero; spacefill 0;");
733 cmd.append("spacefill 200;select none");
735 jmolScript(cmd.toString());
740 boolean debug = true;
742 private void jmolHistory(boolean enable)
744 jmolScript("History " + ((debug || enable) ? "on" : "off"));
747 public void loadInline(String string)
751 // viewer.loadInline(strModel, isAppend);
753 // construct fake fullPathName and fileName so we can identify the file
755 // Then, construct pass a reader for the string to Jmol.
756 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
757 // fileName, null, reader, false, null, null, 0);
758 viewer.openStringInline(string);
761 public void mouseOverStructure(int atomIndex, String strInfo)
764 int alocsep = strInfo.indexOf("^");
765 int mdlSep = strInfo.indexOf("/");
766 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
768 if (chainSeparator == -1)
770 chainSeparator = strInfo.indexOf(".");
771 if (mdlSep > -1 && mdlSep < chainSeparator)
773 chainSeparator1 = chainSeparator;
774 chainSeparator = mdlSep;
777 // handle insertion codes
780 pdbResNum = Integer.parseInt(
781 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
786 pdbResNum = Integer.parseInt(
787 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
791 if (strInfo.indexOf(":") > -1)
793 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
794 strInfo.indexOf("."));
801 String pdbfilename = modelFileNames[frameNo]; // default is first or current
805 if (chainSeparator1 == -1)
807 chainSeparator1 = strInfo.indexOf(".", mdlSep);
809 String mdlId = (chainSeparator1 > -1)
810 ? strInfo.substring(mdlSep + 1, chainSeparator1)
811 : strInfo.substring(mdlSep + 1);
814 // recover PDB filename for the model hovered over.
815 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
816 if (_modelFileNameMap != null)
818 int _mp = _modelFileNameMap.length - 1;
820 while (mnumber < _modelFileNameMap[_mp])
824 pdbfilename = modelFileNames[_mp];
828 if (mnumber >= 0 && mnumber < modelFileNames.length)
830 pdbfilename = modelFileNames[mnumber];
833 if (pdbfilename == null)
835 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
839 } catch (Exception e)
844 if (lastMessage == null || !lastMessage.equals(strInfo))
846 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
849 lastMessage = strInfo;
852 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
856 System.err.println("Ignoring additional hover info: " + data
857 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
859 mouseOverStructure(atomIndex, strInfo);
863 * { if (history != null && strStatus != null &&
864 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
868 public void notifyAtomPicked(int atomIndex, String strInfo,
872 * this implements the toggle label behaviour copied from the original
873 * structure viewer, mc_view
877 System.err.println("Ignoring additional pick data string " + strData);
879 int chainSeparator = strInfo.indexOf(":");
881 if (chainSeparator == -1)
883 chainSeparator = strInfo.indexOf(".");
886 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
888 String mdlString = "";
889 if ((p = strInfo.indexOf(":")) > -1)
891 picked += strInfo.substring(p, strInfo.indexOf("."));
894 if ((p = strInfo.indexOf("/")) > -1)
896 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
898 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
902 if (!atomsPicked.contains(picked))
904 jmolScript("select " + picked + ";label %n %r:%c");
905 atomsPicked.addElement(picked);
909 viewer.evalString("select " + picked + ";label off");
910 atomsPicked.removeElement(picked);
913 // TODO: in application this happens
915 // if (scriptWindow != null)
917 // scriptWindow.sendConsoleMessage(strInfo);
918 // scriptWindow.sendConsoleMessage("\n");
924 public void notifyCallback(CBK type, Object[] data)
931 notifyFileLoaded((String) data[1], (String) data[2],
932 (String) data[3], (String) data[4],
933 ((Integer) data[5]).intValue());
937 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
939 // also highlight in alignment
940 // deliberate fall through
942 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
946 notifyScriptTermination((String) data[2],
947 ((Integer) data[3]).intValue());
950 sendConsoleEcho((String) data[1]);
954 (data == null) ? ((String) null) : (String) data[1]);
957 // System.err.println("Ignoring error callback.");
968 "Unhandled callback " + type + " " + data[1].toString());
971 } catch (Exception e)
973 System.err.println("Squashed Jmol callback handler error:");
979 public boolean notifyEnabled(CBK callbackPick)
981 switch (callbackPick)
997 // incremented every time a load notification is successfully handled -
998 // lightweight mechanism for other threads to detect when they can start
999 // referrring to new structures.
1000 private long loadNotifiesHandled = 0;
1002 public long getLoadNotifiesHandled()
1004 return loadNotifiesHandled;
1007 public void notifyFileLoaded(String fullPathName, String fileName2,
1008 String modelName, String errorMsg, int modelParts)
1010 if (errorMsg != null)
1012 fileLoadingError = errorMsg;
1016 // TODO: deal sensibly with models loaded inLine:
1017 // modelName will be null, as will fullPathName.
1019 // the rest of this routine ignores the arguments, and simply interrogates
1020 // the Jmol view to find out what structures it contains, and adds them to
1021 // the structure selection manager.
1022 fileLoadingError = null;
1023 String[] oldmodels = modelFileNames;
1024 modelFileNames = null;
1025 chainNames = new ArrayList<>();
1026 chainFile = new Hashtable<>();
1027 boolean notifyLoaded = false;
1028 String[] modelfilenames = getStructureFiles();
1029 // first check if we've lost any structures
1030 if (oldmodels != null && oldmodels.length > 0)
1033 for (int i = 0; i < oldmodels.length; i++)
1035 for (int n = 0; n < modelfilenames.length; n++)
1037 if (modelfilenames[n] == oldmodels[i])
1039 oldmodels[i] = null;
1043 if (oldmodels[i] != null)
1050 String[] oldmfn = new String[oldm];
1052 for (int i = 0; i < oldmodels.length; i++)
1054 if (oldmodels[i] != null)
1056 oldmfn[oldm++] = oldmodels[i];
1059 // deregister the Jmol instance for these structures - we'll add
1060 // ourselves again at the end for the current structure set.
1061 getSsm().removeStructureViewerListener(this, oldmfn);
1064 refreshPdbEntries();
1065 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1067 String fileName = modelfilenames[modelnum];
1068 boolean foundEntry = false;
1069 StructureFile pdb = null;
1070 String pdbfile = null;
1071 // model was probably loaded inline - so check the pdb file hashcode
1074 // calculate essential attributes for the pdb data imported inline.
1075 // prolly need to resolve modelnumber properly - for now just use our
1077 pdbfile = viewer.getData(
1078 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1080 // search pdbentries and sequences to find correct pdbentry for this
1082 for (int pe = 0; pe < getPdbCount(); pe++)
1084 boolean matches = false;
1085 addSequence(pe, getSequence()[pe]);
1086 if (fileName == null)
1089 // see JAL-623 - need method of matching pasted data up
1091 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1092 pdbfile, DataSourceType.PASTE, getIProgressIndicator());
1093 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1100 File fl = new File(getPdbEntry(pe).getFile());
1101 matches = fl.equals(new File(fileName));
1105 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1108 // to be tested. See mantis bug
1109 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1110 DataSourceType protocol = DataSourceType.URL;
1115 protocol = DataSourceType.FILE;
1117 } catch (Exception e)
1122 // Explicitly map to the filename used by Jmol ;
1123 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1124 fileName, protocol, getIProgressIndicator());
1125 // pdbentry[pe].getFile(), protocol);
1131 // add an entry for every chain in the model
1132 for (int i = 0; i < pdb.getChains().size(); i++)
1134 String chid = new String(
1135 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1136 chainFile.put(chid, fileName);
1137 chainNames.add(chid);
1139 notifyLoaded = true;
1143 if (!foundEntry && associateNewStructs)
1145 // this is a foreign pdb file that jalview doesn't know about - add
1146 // it to the dataset and try to find a home - either on a matching
1147 // sequence or as a new sequence.
1148 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1150 // parse pdb file into a chain, etc.
1151 // locate best match for pdb in associated views and add mapping to
1153 // if properly registered then
1154 notifyLoaded = true;
1159 // so finally, update the jmol bits and pieces
1160 // if (jmolpopup != null)
1162 // // potential for deadlock here:
1163 // // jmolpopup.updateComputedMenus();
1165 if (!isLoadingFromArchive())
1168 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1170 // register ourselves as a listener and notify the gui that it needs to
1172 getSsm().addStructureViewerListener(this);
1175 FeatureRenderer fr = getFeatureRenderer(null);
1181 loadNotifiesHandled++;
1183 setLoadingFromArchive(false);
1187 public List<String> getChainNames()
1192 protected IProgressIndicator getIProgressIndicator()
1197 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1199 notifyAtomPicked(iatom, strMeasure, null);
1202 public abstract void notifyScriptTermination(String strStatus,
1206 * display a message echoed from the jmol viewer
1210 public abstract void sendConsoleEcho(String strEcho); /*
1211 * { showConsole(true);
1213 * history.append("\n" +
1217 // /End JmolStatusListener
1218 // /////////////////////////////
1222 * status message - usually the response received after a script
1225 public abstract void sendConsoleMessage(String strStatus);
1228 public void setCallbackFunction(String callbackType,
1229 String callbackFunction)
1231 System.err.println("Ignoring set-callback request to associate "
1232 + callbackType + " with function " + callbackFunction);
1237 public void setJalviewColourScheme(ColourSchemeI cs)
1239 colourBySequence = false;
1247 StringBuilder command = new StringBuilder(128);
1248 command.append("select *;color white;");
1249 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1251 for (String resName : residueSet)
1253 char res = resName.length() == 3
1254 ? ResidueProperties.getSingleCharacterCode(resName)
1255 : resName.charAt(0);
1256 Color col = cs.findColour(res, 0, null, null, 0f);
1257 command.append("select " + resName + ";color[" + col.getRed() + ","
1258 + col.getGreen() + "," + col.getBlue() + "];");
1261 evalStateCommand(command.toString());
1265 public void showHelp()
1267 showUrl("http://wiki.jmol.org"
1268 // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/"
1273 * open the URL somehow
1277 public abstract void showUrl(String url, String target);
1280 * called when the binding thinks the UI needs to be refreshed after a Jmol
1281 * state change. this could be because structures were loaded, or because an
1282 * error has occured.
1284 public abstract void refreshGUI();
1287 * called to show or hide the associated console window container.
1291 public abstract void showConsole(boolean show);
1293 public static Viewer getJmolData(JmolParser jmolParser)
1295 return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null,
1296 "-x -o -n", jmolParser);
1303 * @param renderPanel
1305 * - when true will initialise jmol's file IO system (should be false
1306 * in applet context)
1308 * @param documentBase
1310 * @param commandOptions
1312 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1313 String htmlName, URL documentBase, URL codeBase,
1314 String commandOptions)
1316 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1317 codeBase, commandOptions, null, null);
1322 * @param renderPanel
1324 * - when true will initialise jmol's file IO system (should be false
1325 * in applet context)
1327 * @param documentBase
1329 * @param commandOptions
1330 * @param consolePanel
1331 * - panel to contain Jmol console
1332 * @param buttonsToShow
1333 * - buttons to show on the console, in order
1335 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1336 String htmlName, URL documentBase, URL codeBase,
1337 String commandOptions, final Container consolePanel,
1338 String buttonsToShow)
1341 System.err.println("Allocating Jmol Viewer: " + commandOptions);
1343 if (commandOptions == null)
1345 commandOptions = "";
1347 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1348 (jmolfileio ? new SmarterJmolAdapter() : null),
1349 htmlName + ((Object) this).toString(), documentBase, codeBase,
1350 commandOptions, this);
1352 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1356 console = createJmolConsole(consolePanel, buttonsToShow);
1357 } catch (Throwable e)
1359 System.err.println("Could not create Jmol application console. "
1361 e.printStackTrace();
1363 if (consolePanel != null)
1365 consolePanel.addComponentListener(this);
1371 protected abstract JmolAppConsoleInterface createJmolConsole(
1372 Container consolePanel, String buttonsToShow);
1374 // BH 2018 -- Jmol console is not working due to problems with styled
1377 protected org.jmol.api.JmolAppConsoleInterface console = null;
1380 public void setBackgroundColour(java.awt.Color col)
1383 jmolScript("background [" + col.getRed() + "," + col.getGreen() + ","
1384 + col.getBlue() + "];");
1388 private String jmolScript(String script)
1391 System.err.println(">>Jmol>> " + script);
1393 String s = viewer.scriptWait(script);
1395 System.err.println("<<Jmol<< " + s);
1401 public int[] resizeInnerPanel(String data)
1403 // Jalview doesn't honour resize panel requests
1410 protected void closeConsole()
1412 if (console != null)
1416 console.setVisible(false);
1419 } catch (Exception x)
1428 * ComponentListener method
1431 public void componentMoved(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentResized(ComponentEvent e)
1444 * ComponentListener method
1447 public void componentShown(ComponentEvent e)
1453 * ComponentListener method
1456 public void componentHidden(ComponentEvent e)