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.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'
138 public void centerViewer()
140 StringBuilder cmd = new StringBuilder(128);
142 for (String lbl : chainsToShow)
148 mlength = lbl.indexOf(":", p);
149 } while (p < mlength && mlength < (lbl.length() - 2));
150 // TODO: lookup each pdb id and recover proper model number for it.
151 cmd.append(":" + lbl.substring(mlength + 1) + " /"
152 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
154 if (cmd.length() > 0)
156 cmd.setLength(cmd.length() - 4);
158 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
159 evalStateCommand(command);
162 public void closeViewer()
164 // remove listeners for all structures in viewer
165 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
169 releaseUIResources();
173 public void colourByChain()
175 colourBySequence = false;
176 // TODO: colour by chain should colour each chain distinctly across all
178 // TODO: http://issues.jalview.org/browse/JAL-628
179 evalStateCommand("select *;color chain");
183 public void colourByCharge()
185 colourBySequence = false;
186 evalStateCommand("select *;color white;select ASP,GLU;color red;"
187 + "select LYS,ARG;color blue;select CYS;color yellow");
191 * superpose the structures associated with sequences in the alignment
192 * according to their corresponding positions.
194 public void superposeStructures(AlignmentI alignment)
196 superposeStructures(alignment, -1, null);
200 * superpose the structures associated with sequences in the alignment
201 * according to their corresponding positions. ded)
203 * @param refStructure
204 * - select which pdb file to use as reference (default is -1 - the
205 * first structure in the alignment)
207 public void superposeStructures(AlignmentI alignment, int refStructure)
209 superposeStructures(alignment, refStructure, null);
213 * superpose the structures associated with sequences in the alignment
214 * according to their corresponding positions. ded)
216 * @param refStructure
217 * - select which pdb file to use as reference (default is -1 - the
218 * first structure in the alignment)
222 public void superposeStructures(AlignmentI alignment, int refStructure,
223 HiddenColumns hiddenCols)
225 superposeStructures(new AlignmentI[] { alignment },
227 { refStructure }, new HiddenColumns[] { hiddenCols });
234 public String superposeStructures(AlignmentI[] _alignment,
235 int[] _refStructure, HiddenColumns[] _hiddenCols)
237 while (viewer.isScriptExecuting())
242 } catch (InterruptedException i)
248 * get the distinct structure files modelled
249 * (a file with multiple chains may map to multiple sequences)
251 String[] files = getStructureFiles();
252 if (!waitForFileLoad(files))
257 StringBuilder selectioncom = new StringBuilder(256);
258 // In principle - nSeconds specifies the speed of animation for each
259 // superposition - but is seems to behave weirdly, so we don't specify it.
260 String nSeconds = " ";
261 if (files.length > 10)
263 nSeconds = " 0.005 ";
267 nSeconds = " " + (2.0 / files.length) + " ";
268 // if (nSeconds).substring(0,5)+" ";
271 // see JAL-1345 - should really automatically turn off the animation for
272 // large numbers of structures, but Jmol doesn't seem to allow that.
274 // union of all aligned positions are collected together.
275 for (int a = 0; a < _alignment.length; a++)
277 int refStructure = _refStructure[a];
278 AlignmentI alignment = _alignment[a];
279 HiddenColumns hiddenCols = _hiddenCols[a];
280 if (a > 0 && selectioncom.length() > 0 && !selectioncom
281 .substring(selectioncom.length() - 1).equals("|"))
283 selectioncom.append("|");
285 // process this alignment
286 if (refStructure >= files.length)
289 "Invalid reference structure value " + refStructure);
294 * 'matched' bit j will be set for visible alignment columns j where
295 * all sequences have a residue with a mapping to the PDB structure
297 BitSet matched = new BitSet();
298 for (int m = 0; m < alignment.getWidth(); m++)
300 if (hiddenCols == null || hiddenCols.isVisible(m))
306 SuperposeData[] structures = new SuperposeData[files.length];
307 for (int f = 0; f < files.length; f++)
309 structures[f] = new SuperposeData(alignment.getWidth());
313 * Calculate the superposable alignment columns ('matched'), and the
314 * corresponding structure residue positions (structures.pdbResNo)
316 int candidateRefStructure = findSuperposableResidues(alignment,
317 matched, structures);
318 if (refStructure < 0)
321 * If no reference structure was specified, pick the first one that has
322 * a mapping in the alignment
324 refStructure = candidateRefStructure;
327 String[] selcom = new String[files.length];
328 int nmatched = matched.cardinality();
331 return (MessageManager.formatMessage("label.insufficient_residues",
336 * generate select statements to select regions to superimpose structures
339 // TODO extract method to construct selection statements
340 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
342 String chainCd = ":" + structures[pdbfnum].chain;
345 StringBuilder molsel = new StringBuilder();
348 int nextColumnMatch = matched.nextSetBit(0);
349 while (nextColumnMatch != -1)
351 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
352 if (lpos != pdbResNo - 1)
358 molsel.append(chainCd);
365 // continuous run - and lpos >-1
368 // at the beginning, so add dash
375 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
378 * add final selection phrase
383 molsel.append(chainCd);
386 if (molsel.length() > 1)
388 selcom[pdbfnum] = molsel.toString();
389 selectioncom.append("((");
390 selectioncom.append(selcom[pdbfnum].substring(1,
391 selcom[pdbfnum].length() - 1));
392 selectioncom.append(" )& ");
393 selectioncom.append(pdbfnum + 1);
394 selectioncom.append(".1)");
395 if (pdbfnum < files.length - 1)
397 selectioncom.append("|");
402 selcom[pdbfnum] = null;
406 StringBuilder command = new StringBuilder(256);
407 // command.append("set spinFps 10;\n");
409 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
411 if (pdbfnum == refStructure || selcom[pdbfnum] == null
412 || selcom[refStructure] == null)
416 command.append("echo ");
417 command.append("\"Superposing (");
418 command.append(structures[pdbfnum].pdbId);
419 command.append(") against reference (");
420 command.append(structures[refStructure].pdbId);
421 command.append(")\";\ncompare " + nSeconds);
423 command.append(Integer.toString(1 + pdbfnum));
424 command.append(".1} {");
425 command.append(Integer.toString(1 + refStructure));
426 // conformation=1 excludes alternate locations for CA (JAL-1757)
428 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
430 // for (int s = 0; s < 2; s++)
432 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
434 command.append(selcom[pdbfnum]);
435 command.append(selcom[refStructure]);
436 command.append(" ROTATE TRANSLATE;\n");
438 if (selectioncom.length() > 0)
440 // TODO is performing selectioncom redundant here? is done later on
441 // System.out.println("Select regions:\n" + selectioncom.toString());
442 evalStateCommand("select *; cartoons off; backbone; select ("
443 + selectioncom.toString() + "); cartoons; ");
444 // selcom.append("; ribbons; ");
445 String cmdString = command.toString();
446 // System.out.println("Superimpose command(s):\n" + cmdString);
448 evalStateCommand(cmdString);
451 if (selectioncom.length() > 0)
452 {// finally, mark all regions that were superposed.
453 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
455 selectioncom.setLength(selectioncom.length() - 1);
457 // System.out.println("Select regions:\n" + selectioncom.toString());
458 evalStateCommand("select *; cartoons off; backbone; select ("
459 + selectioncom.toString() + "); cartoons; ");
460 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
461 // cartoons; center "+selcom.toString());
467 public void evalStateCommand(String command)
470 if (lastCommand == null || !lastCommand.equals(command))
472 viewer.evalStringQuiet(command + "\n");
475 lastCommand = command;
478 Thread colourby = null;
481 * Sends a set of colour commands to the structure viewer
486 protected void colourBySequence(final String[] commands)
488 if (colourby != null)
490 colourby.interrupt();
493 colourby = new Thread(new Runnable()
498 for (String cmd : commands)
500 executeWhenReady(cmd);
513 protected String[] getColourBySequenceCommands(
514 String[] files, AlignmentViewPanel viewPanel)
516 Map<Object, AtomSpecModel> map = buildColoursMap(viewPanel);
518 return JmolCommands.getColourBySequenceCommand(map);
524 protected void executeWhenReady(String command)
526 evalStateCommand(command);
529 public void createImage(String file, String type, int quality)
531 System.out.println("JMOL CREATE IMAGE");
535 public String createImage(String fileName, String type,
536 Object textOrBytes, int quality)
538 System.out.println("JMOL CREATE IMAGE");
543 public String eval(String strEval)
545 // System.out.println(strEval);
546 // "# 'eval' is implemented only for the applet.";
550 // End StructureListener
551 // //////////////////////////
554 public float[][] functionXY(String functionName, int x, int y)
560 public float[][][] functionXYZ(String functionName, int nx, int ny,
563 // TODO Auto-generated method stub
567 public Color getColour(int atomIndex, int pdbResNum, String chain,
570 if (getModelNum(pdbfile) < 0)
574 // TODO: verify atomIndex is selecting correct model.
575 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
576 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
577 return new Color(colour);
581 * instruct the Jalview binding to update the pdbentries vector if necessary
582 * prior to matching the jmol view's contents to the list of structure files
583 * Jalview knows about.
585 public abstract void refreshPdbEntries();
587 private int getModelNum(String modelFileName)
589 String[] mfn = getStructureFiles();
594 for (int i = 0; i < mfn.length; i++)
596 if (mfn[i].equalsIgnoreCase(modelFileName))
605 * map between index of model filename returned from getPdbFile and the first
606 * index of models from this file in the viewer. Note - this is not trimmed -
607 * use getPdbFile to get number of unique models.
609 private int _modelFileNameMap[];
612 public synchronized String[] getStructureFiles()
614 List<String> mset = new ArrayList<>();
617 return new String[0];
620 if (modelFileNames == null)
622 int modelCount = viewer.ms.mc;
623 String filePath = null;
624 for (int i = 0; i < modelCount; ++i)
626 filePath = viewer.ms.getModelFileName(i);
627 if (!mset.contains(filePath))
632 modelFileNames = mset.toArray(new String[mset.size()]);
635 return modelFileNames;
639 * map from string to applet
642 public Map<String, Object> getRegistryInfo()
644 // TODO Auto-generated method stub
648 // ///////////////////////////////
649 // JmolStatusListener
651 public void handlePopupMenu(int x, int y)
653 // jmolpopup.show(x, y);
654 // jmolpopup.jpiShow(x, y);
658 * Highlight zero, one or more atoms on the structure
661 public void highlightAtoms(List<AtomSpec> atoms)
665 if (resetLastRes.length() > 0)
667 viewer.evalStringQuiet(resetLastRes.toString());
668 resetLastRes.setLength(0);
670 for (AtomSpec atom : atoms)
672 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
673 atom.getChain(), atom.getPdbFile());
679 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
682 if (modelFileNames == null)
687 // look up file model number for this pdbfile
689 // may need to adjust for URLencoding here - we don't worry about that yet.
690 while (mdlNum < modelFileNames.length
691 && !pdbfile.equals(modelFileNames[mdlNum]))
695 if (mdlNum == modelFileNames.length)
702 StringBuilder cmd = new StringBuilder(64);
703 cmd.append("select " + pdbResNum); // +modelNum
705 resetLastRes.append("select " + pdbResNum); // +modelNum
708 resetLastRes.append(":");
709 if (!chain.equals(" "))
712 resetLastRes.append(chain);
715 cmd.append(" /" + (mdlNum + 1));
716 resetLastRes.append("/" + (mdlNum + 1));
718 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
720 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
721 + " and not hetero; spacefill 0;");
723 cmd.append("spacefill 200;select none");
725 viewer.evalStringQuiet(cmd.toString());
730 boolean debug = true;
732 private void jmolHistory(boolean enable)
734 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
737 public void loadInline(String string)
741 // viewer.loadInline(strModel, isAppend);
743 // construct fake fullPathName and fileName so we can identify the file
745 // Then, construct pass a reader for the string to Jmol.
746 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
747 // fileName, null, reader, false, null, null, 0);
748 viewer.openStringInline(string);
751 public void mouseOverStructure(int atomIndex, String strInfo)
754 int alocsep = strInfo.indexOf("^");
755 int mdlSep = strInfo.indexOf("/");
756 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
758 if (chainSeparator == -1)
760 chainSeparator = strInfo.indexOf(".");
761 if (mdlSep > -1 && mdlSep < chainSeparator)
763 chainSeparator1 = chainSeparator;
764 chainSeparator = mdlSep;
767 // handle insertion codes
770 pdbResNum = Integer.parseInt(
771 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
776 pdbResNum = Integer.parseInt(
777 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
781 if (strInfo.indexOf(":") > -1)
783 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
784 strInfo.indexOf("."));
791 String pdbfilename = modelFileNames[frameNo]; // default is first or current
795 if (chainSeparator1 == -1)
797 chainSeparator1 = strInfo.indexOf(".", mdlSep);
799 String mdlId = (chainSeparator1 > -1)
800 ? strInfo.substring(mdlSep + 1, chainSeparator1)
801 : strInfo.substring(mdlSep + 1);
804 // recover PDB filename for the model hovered over.
805 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
806 if (_modelFileNameMap != null)
808 int _mp = _modelFileNameMap.length - 1;
810 while (mnumber < _modelFileNameMap[_mp])
814 pdbfilename = modelFileNames[_mp];
818 if (mnumber >= 0 && mnumber < modelFileNames.length)
820 pdbfilename = modelFileNames[mnumber];
823 if (pdbfilename == null)
825 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
829 } catch (Exception e)
834 if (lastMessage == null || !lastMessage.equals(strInfo))
836 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
839 lastMessage = strInfo;
842 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
846 System.err.println("Ignoring additional hover info: " + data
847 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
849 mouseOverStructure(atomIndex, strInfo);
853 * { if (history != null && strStatus != null &&
854 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
858 public void notifyAtomPicked(int atomIndex, String strInfo,
862 * this implements the toggle label behaviour copied from the original
863 * structure viewer, MCView
867 System.err.println("Ignoring additional pick data string " + strData);
869 int chainSeparator = strInfo.indexOf(":");
871 if (chainSeparator == -1)
873 chainSeparator = strInfo.indexOf(".");
876 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
878 String mdlString = "";
879 if ((p = strInfo.indexOf(":")) > -1)
881 picked += strInfo.substring(p, strInfo.indexOf("."));
884 if ((p = strInfo.indexOf("/")) > -1)
886 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
888 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
892 if (!atomsPicked.contains(picked))
894 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
895 atomsPicked.addElement(picked);
899 viewer.evalString("select " + picked + ";label off");
900 atomsPicked.removeElement(picked);
903 // TODO: in application this happens
905 // if (scriptWindow != null)
907 // scriptWindow.sendConsoleMessage(strInfo);
908 // scriptWindow.sendConsoleMessage("\n");
914 public void notifyCallback(CBK type, Object[] data)
921 notifyFileLoaded((String) data[1], (String) data[2],
922 (String) data[3], (String) data[4],
923 ((Integer) data[5]).intValue());
927 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
929 // also highlight in alignment
930 // deliberate fall through
932 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
936 notifyScriptTermination((String) data[2],
937 ((Integer) data[3]).intValue());
940 sendConsoleEcho((String) data[1]);
944 (data == null) ? ((String) null) : (String) data[1]);
947 // System.err.println("Ignoring error callback.");
958 "Unhandled callback " + type + " " + data[1].toString());
961 } catch (Exception e)
963 System.err.println("Squashed Jmol callback handler error:");
969 public boolean notifyEnabled(CBK callbackPick)
971 switch (callbackPick)
987 // incremented every time a load notification is successfully handled -
988 // lightweight mechanism for other threads to detect when they can start
989 // referrring to new structures.
990 private long loadNotifiesHandled = 0;
992 public long getLoadNotifiesHandled()
994 return loadNotifiesHandled;
997 public void notifyFileLoaded(String fullPathName, String fileName2,
998 String modelName, String errorMsg, int modelParts)
1000 if (errorMsg != null)
1002 fileLoadingError = errorMsg;
1006 // TODO: deal sensibly with models loaded inLine:
1007 // modelName will be null, as will fullPathName.
1009 // the rest of this routine ignores the arguments, and simply interrogates
1010 // the Jmol view to find out what structures it contains, and adds them to
1011 // the structure selection manager.
1012 fileLoadingError = null;
1013 String[] oldmodels = modelFileNames;
1014 modelFileNames = null;
1015 chainNames = new ArrayList<>();
1016 chainFile = new Hashtable<>();
1017 boolean notifyLoaded = false;
1018 String[] modelfilenames = getStructureFiles();
1019 // first check if we've lost any structures
1020 if (oldmodels != null && oldmodels.length > 0)
1023 for (int i = 0; i < oldmodels.length; i++)
1025 for (int n = 0; n < modelfilenames.length; n++)
1027 if (modelfilenames[n] == oldmodels[i])
1029 oldmodels[i] = null;
1033 if (oldmodels[i] != null)
1040 String[] oldmfn = new String[oldm];
1042 for (int i = 0; i < oldmodels.length; i++)
1044 if (oldmodels[i] != null)
1046 oldmfn[oldm++] = oldmodels[i];
1049 // deregister the Jmol instance for these structures - we'll add
1050 // ourselves again at the end for the current structure set.
1051 getSsm().removeStructureViewerListener(this, oldmfn);
1054 refreshPdbEntries();
1055 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1057 String fileName = modelfilenames[modelnum];
1058 boolean foundEntry = false;
1059 StructureFile pdb = null;
1060 String pdbfile = null;
1061 // model was probably loaded inline - so check the pdb file hashcode
1064 // calculate essential attributes for the pdb data imported inline.
1065 // prolly need to resolve modelnumber properly - for now just use our
1067 pdbfile = viewer.getData(
1068 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1070 // search pdbentries and sequences to find correct pdbentry for this
1072 for (int pe = 0; pe < getPdbCount(); pe++)
1074 boolean matches = false;
1075 addSequence(pe, getSequence()[pe]);
1076 if (fileName == null)
1079 // see JAL-623 - need method of matching pasted data up
1081 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1082 pdbfile, DataSourceType.PASTE,
1083 getIProgressIndicator());
1084 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1091 File fl = new File(getPdbEntry(pe).getFile());
1092 matches = fl.equals(new File(fileName));
1096 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1099 // to be tested. See mantis bug
1100 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1101 DataSourceType protocol = DataSourceType.URL;
1106 protocol = DataSourceType.FILE;
1108 } catch (Exception e)
1113 // Explicitly map to the filename used by Jmol ;
1114 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1115 fileName, protocol, getIProgressIndicator());
1116 // pdbentry[pe].getFile(), protocol);
1122 // add an entry for every chain in the model
1123 for (int i = 0; i < pdb.getChains().size(); i++)
1125 String chid = new String(
1126 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1127 chainFile.put(chid, fileName);
1128 chainNames.add(chid);
1130 notifyLoaded = true;
1134 if (!foundEntry && associateNewStructs)
1136 // this is a foreign pdb file that jalview doesn't know about - add
1137 // it to the dataset and try to find a home - either on a matching
1138 // sequence or as a new sequence.
1139 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1141 // parse pdb file into a chain, etc.
1142 // locate best match for pdb in associated views and add mapping to
1144 // if properly registered then
1145 notifyLoaded = true;
1150 // so finally, update the jmol bits and pieces
1151 // if (jmolpopup != null)
1153 // // potential for deadlock here:
1154 // // jmolpopup.updateComputedMenus();
1156 if (!isLoadingFromArchive())
1158 viewer.evalStringQuiet(
1159 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1161 // register ourselves as a listener and notify the gui that it needs to
1163 getSsm().addStructureViewerListener(this);
1166 FeatureRenderer fr = getFeatureRenderer(null);
1172 loadNotifiesHandled++;
1174 setLoadingFromArchive(false);
1178 public List<String> getChainNames()
1183 protected IProgressIndicator getIProgressIndicator()
1188 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1190 notifyAtomPicked(iatom, strMeasure, null);
1193 public abstract void notifyScriptTermination(String strStatus,
1197 * display a message echoed from the jmol viewer
1201 public abstract void sendConsoleEcho(String strEcho); /*
1202 * { showConsole(true);
1204 * history.append("\n" +
1208 // /End JmolStatusListener
1209 // /////////////////////////////
1213 * status message - usually the response received after a script
1216 public abstract void sendConsoleMessage(String strStatus);
1219 public void setCallbackFunction(String callbackType,
1220 String callbackFunction)
1222 System.err.println("Ignoring set-callback request to associate "
1223 + callbackType + " with function " + callbackFunction);
1228 public void setJalviewColourScheme(ColourSchemeI cs)
1230 colourBySequence = false;
1238 StringBuilder command = new StringBuilder(128);
1239 command.append("select *;color white;");
1240 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1242 for (String resName : residueSet)
1244 char res = resName.length() == 3
1245 ? ResidueProperties.getSingleCharacterCode(resName)
1246 : resName.charAt(0);
1247 Color col = cs.findColour(res, 0, null, null, 0f);
1248 command.append("select " + resName + ";color[" + col.getRed() + ","
1249 + col.getGreen() + "," + col.getBlue() + "];");
1252 evalStateCommand(command.toString());
1256 public void showHelp()
1258 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1262 * open the URL somehow
1266 public abstract void showUrl(String url, String target);
1269 * called when the binding thinks the UI needs to be refreshed after a Jmol
1270 * state change. this could be because structures were loaded, or because an
1271 * error has occured.
1273 public abstract void refreshGUI();
1276 * called to show or hide the associated console window container.
1280 public abstract void showConsole(boolean show);
1283 * @param renderPanel
1285 * - when true will initialise jmol's file IO system (should be false
1286 * in applet context)
1288 * @param documentBase
1290 * @param commandOptions
1292 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1293 String htmlName, URL documentBase, URL codeBase,
1294 String commandOptions)
1296 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1297 codeBase, commandOptions, null, null);
1302 * @param renderPanel
1304 * - when true will initialise jmol's file IO system (should be false
1305 * in applet context)
1307 * @param documentBase
1309 * @param commandOptions
1310 * @param consolePanel
1311 * - panel to contain Jmol console
1312 * @param buttonsToShow
1313 * - buttons to show on the console, in ordr
1315 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1316 String htmlName, URL documentBase, URL codeBase,
1317 String commandOptions, final Container consolePanel,
1318 String buttonsToShow)
1320 if (commandOptions == null)
1322 commandOptions = "";
1324 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1325 (jmolfileio ? new SmarterJmolAdapter() : null),
1326 htmlName + ((Object) this).toString(), documentBase, codeBase,
1327 commandOptions, this);
1329 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1331 console = createJmolConsole(consolePanel, buttonsToShow);
1332 if (consolePanel != null)
1334 consolePanel.addComponentListener(this);
1340 protected abstract JmolAppConsoleInterface createJmolConsole(
1341 Container consolePanel, String buttonsToShow);
1343 protected org.jmol.api.JmolAppConsoleInterface console = null;
1346 public void setBackgroundColour(java.awt.Color col)
1349 viewer.evalStringQuiet("background [" + col.getRed() + ","
1350 + col.getGreen() + "," + col.getBlue() + "];");
1355 public int[] resizeInnerPanel(String data)
1357 // Jalview doesn't honour resize panel requests
1364 protected void closeConsole()
1366 if (console != null)
1370 console.setVisible(false);
1373 } catch (Exception x)
1382 * ComponentListener method
1385 public void componentMoved(ComponentEvent e)
1390 * ComponentListener method
1393 public void componentResized(ComponentEvent e)
1398 * ComponentListener method
1401 public void componentShown(ComponentEvent e)
1407 * ComponentListener method
1410 public void componentHidden(ComponentEvent e)
1416 public void showStructures(AlignViewportI av, boolean refocus)
1418 StringBuilder cmd = new StringBuilder(128);
1420 if (isShowAlignmentOnly())
1422 cmd.append("hide *;");
1424 AtomSpecModel model = getShownResidues(av);
1425 String atomSpec = JmolCommands.getAtomSpec(model);
1427 cmd.append("display ").append(atomSpec);
1431 cmd.append("display *");
1433 cmd.append("; cartoon");
1436 cmd.append("; zoom 100");
1438 evalStateCommand(cmd.toString());
1442 * Answers a Jmol syntax style structure model specification. Model number 0, 1,
1443 * 2... is formatted as "1.1", "2.1", "3.1" etc.
1446 public String getModelSpec(int model)
1448 return String.valueOf(model + 1) + ".1";