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;
40 import jalview.util.StructureCommands;
42 import java.awt.Color;
43 import java.awt.Container;
44 import java.awt.event.ComponentEvent;
45 import java.awt.event.ComponentListener;
48 import java.util.ArrayList;
49 import java.util.BitSet;
50 import java.util.Hashtable;
51 import java.util.List;
53 import java.util.StringTokenizer;
54 import java.util.Vector;
56 import org.jmol.adapter.smarter.SmarterJmolAdapter;
57 import org.jmol.api.JmolAppConsoleInterface;
58 import org.jmol.api.JmolSelectionListener;
59 import org.jmol.api.JmolStatusListener;
60 import org.jmol.api.JmolViewer;
61 import org.jmol.c.CBK;
62 import org.jmol.script.T;
63 import org.jmol.viewer.Viewer;
65 public abstract class JalviewJmolBinding extends AAStructureBindingModel
66 implements JmolStatusListener, JmolSelectionListener,
69 private String lastMessage;
71 boolean allChainsSelected = false;
74 * when true, try to search the associated datamodel for sequences that are
75 * associated with any unknown structures in the Jmol view.
77 private boolean associateNewStructs = false;
79 Vector<String> atomsPicked = new Vector<>();
81 Hashtable<String, String> chainFile;
84 * the default or current model displayed if the model cannot be identified
85 * from the selection message
89 // 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 strings
136 * of the form 'pdbfilename:Chaincode'
138 * @deprecated now only used by applet code
141 public void centerViewer()
143 StringBuilder cmd = new StringBuilder(128);
145 for (String lbl : chainsToShow)
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 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
162 evalStateCommand(command);
165 public void closeViewer()
167 // remove listeners for all structures in viewer
168 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
172 releaseUIResources();
176 public void colourByChain()
178 colourBySequence = false;
179 // TODO: colour by chain should colour each chain distinctly across all
181 // TODO: http://issues.jalview.org/browse/JAL-628
182 evalStateCommand("select *;color chain");
186 public void colourByCharge()
188 colourBySequence = false;
189 evalStateCommand("select *;color white;select ASP,GLU;color red;"
190 + "select LYS,ARG;color blue;select CYS;color yellow");
194 * superpose the structures associated with sequences in the alignment
195 * according to their corresponding positions.
197 public void superposeStructures(AlignmentI alignment)
199 superposeStructures(alignment, -1, null);
203 * superpose the structures associated with sequences in the alignment
204 * according to their corresponding positions. ded)
206 * @param refStructure
207 * - select which pdb file to use as reference (default is -1 - the
208 * first structure in the alignment)
210 public void superposeStructures(AlignmentI alignment, int refStructure)
212 superposeStructures(alignment, refStructure, null);
216 * superpose the structures associated with sequences in the alignment
217 * according to their corresponding positions. ded)
219 * @param refStructure
220 * - select which pdb file to use as reference (default is -1 - the
221 * first structure in the alignment)
225 public void superposeStructures(AlignmentI alignment, int refStructure,
226 HiddenColumns hiddenCols)
228 superposeStructures(new AlignmentI[] { alignment },
230 { refStructure }, new HiddenColumns[] { hiddenCols });
237 public String superposeStructures(AlignmentI[] _alignment,
238 int[] _refStructure, HiddenColumns[] _hiddenCols)
240 while (viewer.isScriptExecuting())
245 } catch (InterruptedException i)
251 * get the distinct structure files modelled
252 * (a file with multiple chains may map to multiple sequences)
254 String[] files = getStructureFiles();
255 if (!waitForFileLoad(files))
260 StringBuilder selectioncom = new StringBuilder(256);
261 // In principle - nSeconds specifies the speed of animation for each
262 // superposition - but is seems to behave weirdly, so we don't specify it.
263 String nSeconds = " ";
264 if (files.length > 10)
266 nSeconds = " 0.005 ";
270 nSeconds = " " + (2.0 / files.length) + " ";
271 // if (nSeconds).substring(0,5)+" ";
274 // see JAL-1345 - should really automatically turn off the animation for
275 // large numbers of structures, but Jmol doesn't seem to allow that.
277 // union of all aligned positions are collected together.
278 for (int a = 0; a < _alignment.length; a++)
280 int refStructure = _refStructure[a];
281 AlignmentI alignment = _alignment[a];
282 HiddenColumns hiddenCols = _hiddenCols[a];
283 if (a > 0 && selectioncom.length() > 0 && !selectioncom
284 .substring(selectioncom.length() - 1).equals("|"))
286 selectioncom.append("|");
288 // process this alignment
289 if (refStructure >= files.length)
292 "Invalid reference structure value " + refStructure);
297 * 'matched' bit j will be set for visible alignment columns j where
298 * all sequences have a residue with a mapping to the PDB structure
300 BitSet matched = new BitSet();
301 for (int m = 0; m < alignment.getWidth(); m++)
303 if (hiddenCols == null || hiddenCols.isVisible(m))
309 SuperposeData[] structures = new SuperposeData[files.length];
310 for (int f = 0; f < files.length; f++)
312 structures[f] = new SuperposeData(alignment.getWidth());
316 * Calculate the superposable alignment columns ('matched'), and the
317 * corresponding structure residue positions (structures.pdbResNo)
319 int candidateRefStructure = findSuperposableResidues(alignment,
320 matched, structures);
321 if (refStructure < 0)
324 * If no reference structure was specified, pick the first one that has
325 * a mapping in the alignment
327 refStructure = candidateRefStructure;
330 String[] selcom = new String[files.length];
331 int nmatched = matched.cardinality();
334 return (MessageManager.formatMessage("label.insufficient_residues",
339 * generate select statements to select regions to superimpose structures
342 // TODO extract method to construct selection statements
343 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
345 String chainCd = ":" + structures[pdbfnum].chain;
348 StringBuilder molsel = new StringBuilder();
351 int nextColumnMatch = matched.nextSetBit(0);
352 while (nextColumnMatch != -1)
354 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
355 if (lpos != pdbResNo - 1)
361 molsel.append(chainCd);
368 // continuous run - and lpos >-1
371 // at the beginning, so add dash
378 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
381 * add final selection phrase
386 molsel.append(chainCd);
389 if (molsel.length() > 1)
391 selcom[pdbfnum] = molsel.toString();
392 selectioncom.append("((");
393 selectioncom.append(selcom[pdbfnum].substring(1,
394 selcom[pdbfnum].length() - 1));
395 selectioncom.append(" )& ");
396 selectioncom.append(pdbfnum + 1);
397 selectioncom.append(".1)");
398 if (pdbfnum < files.length - 1)
400 selectioncom.append("|");
405 selcom[pdbfnum] = null;
409 StringBuilder command = new StringBuilder(256);
410 // command.append("set spinFps 10;\n");
412 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
414 if (pdbfnum == refStructure || selcom[pdbfnum] == null
415 || selcom[refStructure] == null)
419 command.append("echo ");
420 command.append("\"Superposing (");
421 command.append(structures[pdbfnum].pdbId);
422 command.append(") against reference (");
423 command.append(structures[refStructure].pdbId);
424 command.append(")\";\ncompare " + nSeconds);
426 command.append(Integer.toString(1 + pdbfnum));
427 command.append(".1} {");
428 command.append(Integer.toString(1 + refStructure));
429 // conformation=1 excludes alternate locations for CA (JAL-1757)
431 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
433 // for (int s = 0; s < 2; s++)
435 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
437 command.append(selcom[pdbfnum]);
438 command.append(selcom[refStructure]);
439 command.append(" ROTATE TRANSLATE;\n");
441 if (selectioncom.length() > 0)
443 // TODO is performing selectioncom redundant here? is done later on
444 // System.out.println("Select regions:\n" + selectioncom.toString());
445 evalStateCommand("select *; cartoons off; backbone; select ("
446 + selectioncom.toString() + "); cartoons; ");
447 // selcom.append("; ribbons; ");
448 String cmdString = command.toString();
449 // System.out.println("Superimpose command(s):\n" + cmdString);
451 evalStateCommand(cmdString);
454 if (selectioncom.length() > 0)
455 {// finally, mark all regions that were superposed.
456 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
458 selectioncom.setLength(selectioncom.length() - 1);
460 // System.out.println("Select regions:\n" + selectioncom.toString());
461 evalStateCommand("select *; cartoons off; backbone; select ("
462 + selectioncom.toString() + "); cartoons; zoom 0");
463 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
464 // cartoons; center "+selcom.toString());
470 public void evalStateCommand(String command)
473 if (lastCommand == null || !lastCommand.equals(command))
475 viewer.evalStringQuiet(command + "\n");
478 lastCommand = command;
481 Thread colourby = null;
484 * Sends a set of colour commands to the structure viewer
489 protected void colourBySequence(final String[] commands)
491 if (colourby != null)
493 colourby.interrupt();
496 colourby = new Thread(new Runnable()
501 for (String cmd : commands)
503 executeWhenReady(cmd);
516 protected String[] getColourBySequenceCommands(
517 String[] files, AlignmentViewPanel viewPanel)
519 Map<Object, AtomSpecModel> map = StructureCommands.buildColoursMap(this, viewPanel);
521 return JmolCommands.getColourBySequenceCommand(map);
527 protected void executeWhenReady(String command)
529 evalStateCommand(command);
532 public void createImage(String file, String type, int quality)
534 System.out.println("JMOL CREATE IMAGE");
538 public String createImage(String fileName, String type,
539 Object textOrBytes, int quality)
541 System.out.println("JMOL CREATE IMAGE");
546 public String eval(String strEval)
548 // System.out.println(strEval);
549 // "# 'eval' is implemented only for the applet.";
553 // End StructureListener
554 // //////////////////////////
557 public float[][] functionXY(String functionName, int x, int y)
563 public float[][][] functionXYZ(String functionName, int nx, int ny,
566 // TODO Auto-generated method stub
570 public Color getColour(int atomIndex, int pdbResNum, String chain,
573 if (getModelNum(pdbfile) < 0)
577 // TODO: verify atomIndex is selecting correct model.
578 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
579 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
580 return new Color(colour);
584 * instruct the Jalview binding to update the pdbentries vector if necessary
585 * prior to matching the jmol view's contents to the list of structure files
586 * Jalview knows about.
588 public abstract void refreshPdbEntries();
590 private int getModelNum(String modelFileName)
592 String[] mfn = getStructureFiles();
597 for (int i = 0; i < mfn.length; i++)
599 if (mfn[i].equalsIgnoreCase(modelFileName))
608 * map between index of model filename returned from getPdbFile and the first
609 * index of models from this file in the viewer. Note - this is not trimmed -
610 * use getPdbFile to get number of unique models.
612 private int _modelFileNameMap[];
615 public synchronized String[] getStructureFiles()
617 List<String> mset = new ArrayList<>();
620 return new String[0];
623 if (modelFileNames == null)
625 int modelCount = viewer.ms.mc;
626 String filePath = null;
627 for (int i = 0; i < modelCount; ++i)
629 filePath = viewer.ms.getModelFileName(i);
630 if (!mset.contains(filePath))
635 modelFileNames = mset.toArray(new String[mset.size()]);
638 return modelFileNames;
642 * map from string to applet
645 public Map<String, Object> getRegistryInfo()
647 // TODO Auto-generated method stub
651 // ///////////////////////////////
652 // JmolStatusListener
654 public void handlePopupMenu(int x, int y)
656 // jmolpopup.show(x, y);
657 // jmolpopup.jpiShow(x, y);
661 * Highlight zero, one or more atoms on the structure
664 public void highlightAtoms(List<AtomSpec> atoms)
668 if (resetLastRes.length() > 0)
670 viewer.evalStringQuiet(resetLastRes.toString());
671 resetLastRes.setLength(0);
673 for (AtomSpec atom : atoms)
675 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
676 atom.getChain(), atom.getPdbFile());
682 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
685 if (modelFileNames == null)
690 // look up file model number for this pdbfile
692 // may need to adjust for URLencoding here - we don't worry about that yet.
693 while (mdlNum < modelFileNames.length
694 && !pdbfile.equals(modelFileNames[mdlNum]))
698 if (mdlNum == modelFileNames.length)
705 StringBuilder cmd = new StringBuilder(64);
706 cmd.append("select " + pdbResNum); // +modelNum
708 resetLastRes.append("select " + pdbResNum); // +modelNum
711 resetLastRes.append(":");
712 if (!chain.equals(" "))
715 resetLastRes.append(chain);
718 cmd.append(" /" + (mdlNum + 1));
719 resetLastRes.append("/" + (mdlNum + 1));
721 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
723 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
724 + " and not hetero; spacefill 0;");
726 cmd.append("spacefill 200;select none");
728 viewer.evalStringQuiet(cmd.toString());
733 boolean debug = true;
735 private void jmolHistory(boolean enable)
737 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
740 public void loadInline(String string)
744 // viewer.loadInline(strModel, isAppend);
746 // construct fake fullPathName and fileName so we can identify the file
748 // Then, construct pass a reader for the string to Jmol.
749 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
750 // fileName, null, reader, false, null, null, 0);
751 viewer.openStringInline(string);
754 protected void mouseOverStructure(int atomIndex, final String strInfo)
757 int alocsep = strInfo.indexOf("^");
758 int mdlSep = strInfo.indexOf("/");
759 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
761 if (chainSeparator == -1)
763 chainSeparator = strInfo.indexOf(".");
764 if (mdlSep > -1 && mdlSep < chainSeparator)
766 chainSeparator1 = chainSeparator;
767 chainSeparator = mdlSep;
770 // handle insertion codes
773 pdbResNum = Integer.parseInt(
774 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
779 pdbResNum = Integer.parseInt(
780 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
784 if (strInfo.indexOf(":") > -1)
786 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
787 strInfo.indexOf("."));
794 String pdbfilename = modelFileNames[frameNo]; // default is first or current
798 if (chainSeparator1 == -1)
800 chainSeparator1 = strInfo.indexOf(".", mdlSep);
802 String mdlId = (chainSeparator1 > -1)
803 ? strInfo.substring(mdlSep + 1, chainSeparator1)
804 : strInfo.substring(mdlSep + 1);
807 // recover PDB filename for the model hovered over.
808 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
809 if (_modelFileNameMap != null)
811 int _mp = _modelFileNameMap.length - 1;
813 while (mnumber < _modelFileNameMap[_mp])
817 pdbfilename = modelFileNames[_mp];
821 if (mnumber >= 0 && mnumber < modelFileNames.length)
823 pdbfilename = modelFileNames[mnumber];
826 if (pdbfilename == null)
828 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
832 } catch (Exception e)
838 * highlight position on alignment(s); if some text is returned,
839 * show this as a second line on the structure hover tooltip
841 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
845 // change comma to pipe separator (newline token for Jmol)
846 label = label.replace(',', '|');
847 StringTokenizer toks = new StringTokenizer(strInfo, " ");
848 StringBuilder sb = new StringBuilder();
849 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
850 .append(chainId).append("/1");
851 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
852 .append(toks.nextToken());
853 sb.append("|").append(label).append("\"");
854 evalStateCommand(sb.toString());
858 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
860 if (strInfo.equals(lastMessage))
864 lastMessage = strInfo;
867 System.err.println("Ignoring additional hover info: " + data
868 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
870 mouseOverStructure(atomIndex, strInfo);
874 * { if (history != null && strStatus != null &&
875 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
879 public void notifyAtomPicked(int atomIndex, String strInfo,
883 * this implements the toggle label behaviour copied from the original
884 * structure viewer, MCView
888 System.err.println("Ignoring additional pick data string " + strData);
890 int chainSeparator = strInfo.indexOf(":");
892 if (chainSeparator == -1)
894 chainSeparator = strInfo.indexOf(".");
897 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
899 String mdlString = "";
900 if ((p = strInfo.indexOf(":")) > -1)
902 picked += strInfo.substring(p, strInfo.indexOf("."));
905 if ((p = strInfo.indexOf("/")) > -1)
907 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
909 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
913 if (!atomsPicked.contains(picked))
915 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
916 atomsPicked.addElement(picked);
920 viewer.evalString("select " + picked + ";label off");
921 atomsPicked.removeElement(picked);
924 // TODO: in application this happens
926 // if (scriptWindow != null)
928 // scriptWindow.sendConsoleMessage(strInfo);
929 // scriptWindow.sendConsoleMessage("\n");
935 public void notifyCallback(CBK type, Object[] data)
942 notifyFileLoaded((String) data[1], (String) data[2],
943 (String) data[3], (String) data[4],
944 ((Integer) data[5]).intValue());
948 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
950 // also highlight in alignment
951 // deliberate fall through
953 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
957 notifyScriptTermination((String) data[2],
958 ((Integer) data[3]).intValue());
961 sendConsoleEcho((String) data[1]);
965 (data == null) ? ((String) null) : (String) data[1]);
968 // System.err.println("Ignoring error callback.");
979 "Unhandled callback " + type + " " + data[1].toString());
982 } catch (Exception e)
984 System.err.println("Squashed Jmol callback handler error:");
990 public boolean notifyEnabled(CBK callbackPick)
992 switch (callbackPick)
1008 // incremented every time a load notification is successfully handled -
1009 // lightweight mechanism for other threads to detect when they can start
1010 // referrring to new structures.
1011 private long loadNotifiesHandled = 0;
1013 public long getLoadNotifiesHandled()
1015 return loadNotifiesHandled;
1018 public void notifyFileLoaded(String fullPathName, String fileName2,
1019 String modelName, String errorMsg, int modelParts)
1021 if (errorMsg != null)
1023 fileLoadingError = errorMsg;
1027 // TODO: deal sensibly with models loaded inLine:
1028 // modelName will be null, as will fullPathName.
1030 // the rest of this routine ignores the arguments, and simply interrogates
1031 // the Jmol view to find out what structures it contains, and adds them to
1032 // the structure selection manager.
1033 fileLoadingError = null;
1034 String[] oldmodels = modelFileNames;
1035 modelFileNames = null;
1036 chainNames = new ArrayList<>();
1037 chainFile = new Hashtable<>();
1038 boolean notifyLoaded = false;
1039 String[] modelfilenames = getStructureFiles();
1040 // first check if we've lost any structures
1041 if (oldmodels != null && oldmodels.length > 0)
1044 for (int i = 0; i < oldmodels.length; i++)
1046 for (int n = 0; n < modelfilenames.length; n++)
1048 if (modelfilenames[n] == oldmodels[i])
1050 oldmodels[i] = null;
1054 if (oldmodels[i] != null)
1061 String[] oldmfn = new String[oldm];
1063 for (int i = 0; i < oldmodels.length; i++)
1065 if (oldmodels[i] != null)
1067 oldmfn[oldm++] = oldmodels[i];
1070 // deregister the Jmol instance for these structures - we'll add
1071 // ourselves again at the end for the current structure set.
1072 getSsm().removeStructureViewerListener(this, oldmfn);
1075 refreshPdbEntries();
1076 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1078 String fileName = modelfilenames[modelnum];
1079 boolean foundEntry = false;
1080 StructureFile pdb = null;
1081 String pdbfile = null;
1082 // model was probably loaded inline - so check the pdb file hashcode
1085 // calculate essential attributes for the pdb data imported inline.
1086 // prolly need to resolve modelnumber properly - for now just use our
1088 pdbfile = viewer.getData(
1089 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1091 // search pdbentries and sequences to find correct pdbentry for this
1093 for (int pe = 0; pe < getPdbCount(); pe++)
1095 boolean matches = false;
1096 addSequence(pe, getSequence()[pe]);
1097 if (fileName == null)
1100 // see JAL-623 - need method of matching pasted data up
1102 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1103 pdbfile, DataSourceType.PASTE,
1104 getIProgressIndicator());
1105 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1112 File fl = new File(getPdbEntry(pe).getFile());
1113 matches = fl.equals(new File(fileName));
1117 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1120 // to be tested. See mantis bug
1121 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1122 DataSourceType protocol = DataSourceType.URL;
1127 protocol = DataSourceType.FILE;
1129 } catch (Exception e)
1134 // Explicitly map to the filename used by Jmol ;
1135 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1136 fileName, protocol, getIProgressIndicator());
1137 // pdbentry[pe].getFile(), protocol);
1143 // add an entry for every chain in the model
1144 for (int i = 0; i < pdb.getChains().size(); i++)
1146 String chid = new String(
1147 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1148 chainFile.put(chid, fileName);
1149 chainNames.add(chid);
1151 notifyLoaded = true;
1155 if (!foundEntry && associateNewStructs)
1157 // this is a foreign pdb file that jalview doesn't know about - add
1158 // it to the dataset and try to find a home - either on a matching
1159 // sequence or as a new sequence.
1160 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1162 // parse pdb file into a chain, etc.
1163 // locate best match for pdb in associated views and add mapping to
1165 // if properly registered then
1166 notifyLoaded = true;
1171 // so finally, update the jmol bits and pieces
1172 // if (jmolpopup != null)
1174 // // potential for deadlock here:
1175 // // jmolpopup.updateComputedMenus();
1177 if (!isLoadingFromArchive())
1179 viewer.evalStringQuiet(
1180 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1182 // register ourselves as a listener and notify the gui that it needs to
1184 getSsm().addStructureViewerListener(this);
1187 FeatureRenderer fr = getFeatureRenderer(null);
1193 loadNotifiesHandled++;
1195 setLoadingFromArchive(false);
1198 protected IProgressIndicator getIProgressIndicator()
1203 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1205 notifyAtomPicked(iatom, strMeasure, null);
1208 public abstract void notifyScriptTermination(String strStatus,
1212 * display a message echoed from the jmol viewer
1216 public abstract void sendConsoleEcho(String strEcho); /*
1217 * { showConsole(true);
1219 * history.append("\n" +
1223 // /End JmolStatusListener
1224 // /////////////////////////////
1228 * status message - usually the response received after a script
1231 public abstract void sendConsoleMessage(String strStatus);
1234 public void setCallbackFunction(String callbackType,
1235 String callbackFunction)
1237 System.err.println("Ignoring set-callback request to associate "
1238 + callbackType + " with function " + callbackFunction);
1243 public void setJalviewColourScheme(ColourSchemeI cs)
1245 colourBySequence = false;
1253 StringBuilder command = new StringBuilder(128);
1254 command.append("select *;color white;");
1255 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1257 for (String resName : residueSet)
1259 char res = resName.length() == 3
1260 ? ResidueProperties.getSingleCharacterCode(resName)
1261 : resName.charAt(0);
1262 Color col = cs.findColour(res, 0, null, null, 0f);
1263 command.append("select " + resName + ";color[" + col.getRed() + ","
1264 + col.getGreen() + "," + col.getBlue() + "];");
1267 evalStateCommand(command.toString());
1271 public void showHelp()
1273 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1277 * open the URL somehow
1281 public abstract void showUrl(String url, String target);
1284 * called when the binding thinks the UI needs to be refreshed after a Jmol
1285 * state change. this could be because structures were loaded, or because an
1286 * error has occured.
1288 public abstract void refreshGUI();
1291 * called to show or hide the associated console window container.
1295 public abstract void showConsole(boolean show);
1298 * @param renderPanel
1300 * - when true will initialise jmol's file IO system (should be false
1301 * in applet context)
1303 * @param documentBase
1305 * @param commandOptions
1307 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1308 String htmlName, URL documentBase, URL codeBase,
1309 String commandOptions)
1311 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1312 codeBase, commandOptions, null, null);
1317 * @param renderPanel
1319 * - when true will initialise jmol's file IO system (should be false
1320 * in applet context)
1322 * @param documentBase
1324 * @param commandOptions
1325 * @param consolePanel
1326 * - panel to contain Jmol console
1327 * @param buttonsToShow
1328 * - buttons to show on the console, in ordr
1330 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1331 String htmlName, URL documentBase, URL codeBase,
1332 String commandOptions, final Container consolePanel,
1333 String buttonsToShow)
1335 if (commandOptions == null)
1337 commandOptions = "";
1339 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1340 (jmolfileio ? new SmarterJmolAdapter() : null),
1341 htmlName + ((Object) this).toString(), documentBase, codeBase,
1342 commandOptions, this);
1344 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1346 console = createJmolConsole(consolePanel, buttonsToShow);
1347 if (consolePanel != null)
1349 consolePanel.addComponentListener(this);
1355 protected abstract JmolAppConsoleInterface createJmolConsole(
1356 Container consolePanel, String buttonsToShow);
1358 protected org.jmol.api.JmolAppConsoleInterface console = null;
1361 public void setBackgroundColour(java.awt.Color col)
1364 viewer.evalStringQuiet("background [" + col.getRed() + ","
1365 + col.getGreen() + "," + col.getBlue() + "];");
1370 public int[] resizeInnerPanel(String data)
1372 // Jalview doesn't honour resize panel requests
1379 protected void closeConsole()
1381 if (console != null)
1385 console.setVisible(false);
1388 } catch (Exception x)
1397 * ComponentListener method
1400 public void componentMoved(ComponentEvent e)
1405 * ComponentListener method
1408 public void componentResized(ComponentEvent e)
1413 * ComponentListener method
1416 public void componentShown(ComponentEvent e)
1422 * ComponentListener method
1425 public void componentHidden(ComponentEvent e)
1431 public void showStructures(AlignViewportI av, boolean refocus)
1433 StringBuilder cmd = new StringBuilder(128);
1434 if (isShowAlignmentOnly())
1436 AtomSpecModel model = getShownResidues(av);
1437 String atomSpec = JmolCommands.getAtomSpec(model);
1439 cmd.append("hide *;display ").append(atomSpec)
1440 .append("; select displayed");
1444 cmd.append(";display *");
1446 cmd.append("; cartoon only");
1449 cmd.append("; zoom 0");
1451 evalStateCommand(cmd.toString());
1455 * Answers a Jmol syntax style structure model specification. Model number 0, 1,
1456 * 2... is formatted as "1.1", "2.1", "3.1" etc.
1459 public String getModelSpec(int model)
1461 return String.valueOf(model + 1) + ".1";
1465 * Sends a command to recentre the display
1468 public void focusView()
1471 * don't use evalStateCommand because it ignores a command that is the same
1472 * as the last command (why?); but user may have adjusted the display since
1474 viewer.evalString("zoom 0");