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.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'
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;
480 * Sends a set of colour commands to the structure viewer
482 * @param colourBySequenceCommands
485 protected void colourBySequence(
486 final StructureMappingcommandSet[] colourBySequenceCommands)
488 if (colourby != null)
490 colourby.interrupt();
493 colourby = new Thread(new Runnable()
498 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
500 for (String cbyseq : cpdbbyseq.commands)
502 executeWhenReady(cbyseq);
516 protected StructureMappingcommandSet[] getColourBySequenceCommands(
517 String[] files, AlignmentViewPanel viewPanel)
519 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
526 protected void executeWhenReady(String command)
528 evalStateCommand(command);
531 public void createImage(String file, String type, int quality)
533 System.out.println("JMOL CREATE IMAGE");
537 public String createImage(String fileName, String type,
538 Object textOrBytes, int quality)
540 System.out.println("JMOL CREATE IMAGE");
545 public String eval(String strEval)
547 // System.out.println(strEval);
548 // "# 'eval' is implemented only for the applet.";
552 // End StructureListener
553 // //////////////////////////
556 public float[][] functionXY(String functionName, int x, int y)
562 public float[][][] functionXYZ(String functionName, int nx, int ny,
565 // TODO Auto-generated method stub
569 public Color getColour(int atomIndex, int pdbResNum, String chain,
572 if (getModelNum(pdbfile) < 0)
576 // TODO: verify atomIndex is selecting correct model.
577 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
578 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
579 return new Color(colour);
583 * instruct the Jalview binding to update the pdbentries vector if necessary
584 * prior to matching the jmol view's contents to the list of structure files
585 * Jalview knows about.
587 public abstract void refreshPdbEntries();
589 private int getModelNum(String modelFileName)
591 String[] mfn = getStructureFiles();
596 for (int i = 0; i < mfn.length; i++)
598 if (mfn[i].equalsIgnoreCase(modelFileName))
607 * map between index of model filename returned from getPdbFile and the first
608 * index of models from this file in the viewer. Note - this is not trimmed -
609 * use getPdbFile to get number of unique models.
611 private int _modelFileNameMap[];
614 public synchronized String[] getStructureFiles()
616 List<String> mset = new ArrayList<>();
619 return new String[0];
622 if (modelFileNames == null)
624 int modelCount = viewer.ms.mc;
625 String filePath = null;
626 for (int i = 0; i < modelCount; ++i)
628 filePath = viewer.ms.getModelFileName(i);
629 if (!mset.contains(filePath))
634 modelFileNames = mset.toArray(new String[mset.size()]);
637 return modelFileNames;
641 * map from string to applet
644 public Map<String, Object> getRegistryInfo()
646 // TODO Auto-generated method stub
650 // ///////////////////////////////
651 // JmolStatusListener
653 public void handlePopupMenu(int x, int y)
655 // jmolpopup.show(x, y);
656 // jmolpopup.jpiShow(x, y);
660 * Highlight zero, one or more atoms on the structure
663 public void highlightAtoms(List<AtomSpec> atoms)
667 if (resetLastRes.length() > 0)
669 viewer.evalStringQuiet(resetLastRes.toString());
670 resetLastRes.setLength(0);
672 for (AtomSpec atom : atoms)
674 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
675 atom.getChain(), atom.getPdbFile());
681 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
684 if (modelFileNames == null)
689 // look up file model number for this pdbfile
691 // may need to adjust for URLencoding here - we don't worry about that yet.
692 while (mdlNum < modelFileNames.length
693 && !pdbfile.equals(modelFileNames[mdlNum]))
697 if (mdlNum == modelFileNames.length)
704 StringBuilder cmd = new StringBuilder(64);
705 cmd.append("select " + pdbResNum); // +modelNum
707 resetLastRes.append("select " + pdbResNum); // +modelNum
710 resetLastRes.append(":");
711 if (!chain.equals(" "))
714 resetLastRes.append(chain);
717 cmd.append(" /" + (mdlNum + 1));
718 resetLastRes.append("/" + (mdlNum + 1));
720 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
722 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
723 + " and not hetero; spacefill 0;");
725 cmd.append("spacefill 200;select none");
727 viewer.evalStringQuiet(cmd.toString());
732 boolean debug = true;
734 private void jmolHistory(boolean enable)
736 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
739 public void loadInline(String string)
743 // viewer.loadInline(strModel, isAppend);
745 // construct fake fullPathName and fileName so we can identify the file
747 // Then, construct pass a reader for the string to Jmol.
748 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
749 // fileName, null, reader, false, null, null, 0);
750 viewer.openStringInline(string);
753 public void mouseOverStructure(int atomIndex, String strInfo)
756 int alocsep = strInfo.indexOf("^");
757 int mdlSep = strInfo.indexOf("/");
758 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
760 if (chainSeparator == -1)
762 chainSeparator = strInfo.indexOf(".");
763 if (mdlSep > -1 && mdlSep < chainSeparator)
765 chainSeparator1 = chainSeparator;
766 chainSeparator = mdlSep;
769 // handle insertion codes
772 pdbResNum = Integer.parseInt(
773 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
778 pdbResNum = Integer.parseInt(
779 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
783 if (strInfo.indexOf(":") > -1)
785 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
786 strInfo.indexOf("."));
793 String pdbfilename = modelFileNames[frameNo]; // default is first or current
797 if (chainSeparator1 == -1)
799 chainSeparator1 = strInfo.indexOf(".", mdlSep);
801 String mdlId = (chainSeparator1 > -1)
802 ? strInfo.substring(mdlSep + 1, chainSeparator1)
803 : strInfo.substring(mdlSep + 1);
806 // recover PDB filename for the model hovered over.
807 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
808 if (_modelFileNameMap != null)
810 int _mp = _modelFileNameMap.length - 1;
812 while (mnumber < _modelFileNameMap[_mp])
816 pdbfilename = modelFileNames[_mp];
820 if (mnumber >= 0 && mnumber < modelFileNames.length)
822 pdbfilename = modelFileNames[mnumber];
825 if (pdbfilename == null)
827 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
831 } catch (Exception e)
836 if (lastMessage == null || !lastMessage.equals(strInfo))
838 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
841 lastMessage = strInfo;
844 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
848 System.err.println("Ignoring additional hover info: " + data
849 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
851 mouseOverStructure(atomIndex, strInfo);
855 * { if (history != null && strStatus != null &&
856 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
860 public void notifyAtomPicked(int atomIndex, String strInfo,
864 * this implements the toggle label behaviour copied from the original
865 * structure viewer, MCView
869 System.err.println("Ignoring additional pick data string " + strData);
871 int chainSeparator = strInfo.indexOf(":");
873 if (chainSeparator == -1)
875 chainSeparator = strInfo.indexOf(".");
878 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
880 String mdlString = "";
881 if ((p = strInfo.indexOf(":")) > -1)
883 picked += strInfo.substring(p, strInfo.indexOf("."));
886 if ((p = strInfo.indexOf("/")) > -1)
888 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
890 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
894 if (!atomsPicked.contains(picked))
896 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
897 atomsPicked.addElement(picked);
901 viewer.evalString("select " + picked + ";label off");
902 atomsPicked.removeElement(picked);
905 // TODO: in application this happens
907 // if (scriptWindow != null)
909 // scriptWindow.sendConsoleMessage(strInfo);
910 // scriptWindow.sendConsoleMessage("\n");
916 public void notifyCallback(CBK type, Object[] data)
923 notifyFileLoaded((String) data[1], (String) data[2],
924 (String) data[3], (String) data[4],
925 ((Integer) data[5]).intValue());
929 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
931 // also highlight in alignment
932 // deliberate fall through
934 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
938 notifyScriptTermination((String) data[2],
939 ((Integer) data[3]).intValue());
942 sendConsoleEcho((String) data[1]);
946 (data == null) ? ((String) null) : (String) data[1]);
949 // System.err.println("Ignoring error callback.");
960 "Unhandled callback " + type + " " + data[1].toString());
963 } catch (Exception e)
965 System.err.println("Squashed Jmol callback handler error:");
971 public boolean notifyEnabled(CBK callbackPick)
973 switch (callbackPick)
989 // incremented every time a load notification is successfully handled -
990 // lightweight mechanism for other threads to detect when they can start
991 // referrring to new structures.
992 private long loadNotifiesHandled = 0;
994 public long getLoadNotifiesHandled()
996 return loadNotifiesHandled;
999 public void notifyFileLoaded(String fullPathName, String fileName2,
1000 String modelName, String errorMsg, int modelParts)
1002 if (errorMsg != null)
1004 fileLoadingError = errorMsg;
1008 // TODO: deal sensibly with models loaded inLine:
1009 // modelName will be null, as will fullPathName.
1011 // the rest of this routine ignores the arguments, and simply interrogates
1012 // the Jmol view to find out what structures it contains, and adds them to
1013 // the structure selection manager.
1014 fileLoadingError = null;
1015 String[] oldmodels = modelFileNames;
1016 modelFileNames = null;
1017 chainNames = new ArrayList<>();
1018 chainFile = new Hashtable<>();
1019 boolean notifyLoaded = false;
1020 String[] modelfilenames = getStructureFiles();
1021 // first check if we've lost any structures
1022 if (oldmodels != null && oldmodels.length > 0)
1025 for (int i = 0; i < oldmodels.length; i++)
1027 for (int n = 0; n < modelfilenames.length; n++)
1029 if (modelfilenames[n] == oldmodels[i])
1031 oldmodels[i] = null;
1035 if (oldmodels[i] != null)
1042 String[] oldmfn = new String[oldm];
1044 for (int i = 0; i < oldmodels.length; i++)
1046 if (oldmodels[i] != null)
1048 oldmfn[oldm++] = oldmodels[i];
1051 // deregister the Jmol instance for these structures - we'll add
1052 // ourselves again at the end for the current structure set.
1053 getSsm().removeStructureViewerListener(this, oldmfn);
1056 refreshPdbEntries();
1057 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1059 String fileName = modelfilenames[modelnum];
1060 boolean foundEntry = false;
1061 StructureFile pdb = null;
1062 String pdbfile = null;
1063 // model was probably loaded inline - so check the pdb file hashcode
1066 // calculate essential attributes for the pdb data imported inline.
1067 // prolly need to resolve modelnumber properly - for now just use our
1069 pdbfile = viewer.getData(
1070 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1072 // search pdbentries and sequences to find correct pdbentry for this
1074 for (int pe = 0; pe < getPdbCount(); pe++)
1076 boolean matches = false;
1077 addSequence(pe, getSequence()[pe]);
1078 if (fileName == null)
1081 // see JAL-623 - need method of matching pasted data up
1083 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1084 pdbfile, DataSourceType.PASTE,
1085 getIProgressIndicator());
1086 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1093 File fl = new File(getPdbEntry(pe).getFile());
1094 matches = fl.equals(new File(fileName));
1098 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1101 // to be tested. See mantis bug
1102 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1103 DataSourceType protocol = DataSourceType.URL;
1108 protocol = DataSourceType.FILE;
1110 } catch (Exception e)
1115 // Explicitly map to the filename used by Jmol ;
1116 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1117 fileName, protocol, getIProgressIndicator());
1118 // pdbentry[pe].getFile(), protocol);
1124 // add an entry for every chain in the model
1125 for (int i = 0; i < pdb.getChains().size(); i++)
1127 String chid = new String(
1128 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1129 chainFile.put(chid, fileName);
1130 chainNames.add(chid);
1132 notifyLoaded = true;
1136 if (!foundEntry && associateNewStructs)
1138 // this is a foreign pdb file that jalview doesn't know about - add
1139 // it to the dataset and try to find a home - either on a matching
1140 // sequence or as a new sequence.
1141 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1143 // parse pdb file into a chain, etc.
1144 // locate best match for pdb in associated views and add mapping to
1146 // if properly registered then
1147 notifyLoaded = true;
1152 // so finally, update the jmol bits and pieces
1153 // if (jmolpopup != null)
1155 // // potential for deadlock here:
1156 // // jmolpopup.updateComputedMenus();
1158 if (!isLoadingFromArchive())
1160 viewer.evalStringQuiet(
1161 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1163 // register ourselves as a listener and notify the gui that it needs to
1165 getSsm().addStructureViewerListener(this);
1168 FeatureRenderer fr = getFeatureRenderer(null);
1174 loadNotifiesHandled++;
1176 setLoadingFromArchive(false);
1180 public List<String> getChainNames()
1185 protected IProgressIndicator getIProgressIndicator()
1190 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1192 notifyAtomPicked(iatom, strMeasure, null);
1195 public abstract void notifyScriptTermination(String strStatus,
1199 * display a message echoed from the jmol viewer
1203 public abstract void sendConsoleEcho(String strEcho); /*
1204 * { showConsole(true);
1206 * history.append("\n" +
1210 // /End JmolStatusListener
1211 // /////////////////////////////
1215 * status message - usually the response received after a script
1218 public abstract void sendConsoleMessage(String strStatus);
1221 public void setCallbackFunction(String callbackType,
1222 String callbackFunction)
1224 System.err.println("Ignoring set-callback request to associate "
1225 + callbackType + " with function " + callbackFunction);
1230 public void setJalviewColourScheme(ColourSchemeI cs)
1232 colourBySequence = false;
1240 StringBuilder command = new StringBuilder(128);
1241 command.append("select *;color white;");
1242 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1244 for (String resName : residueSet)
1246 char res = resName.length() == 3
1247 ? ResidueProperties.getSingleCharacterCode(resName)
1248 : resName.charAt(0);
1249 Color col = cs.findColour(res, 0, null, null, 0f);
1250 command.append("select " + resName + ";color[" + col.getRed() + ","
1251 + col.getGreen() + "," + col.getBlue() + "];");
1254 evalStateCommand(command.toString());
1258 public void showHelp()
1260 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1264 * open the URL somehow
1268 public abstract void showUrl(String url, String target);
1271 * called when the binding thinks the UI needs to be refreshed after a Jmol
1272 * state change. this could be because structures were loaded, or because an
1273 * error has occured.
1275 public abstract void refreshGUI();
1278 * called to show or hide the associated console window container.
1282 public abstract void showConsole(boolean show);
1285 * @param renderPanel
1287 * - when true will initialise jmol's file IO system (should be false
1288 * in applet context)
1290 * @param documentBase
1292 * @param commandOptions
1294 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1295 String htmlName, URL documentBase, URL codeBase,
1296 String commandOptions)
1298 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1299 codeBase, commandOptions, null, null);
1304 * @param renderPanel
1306 * - when true will initialise jmol's file IO system (should be false
1307 * in applet context)
1309 * @param documentBase
1311 * @param commandOptions
1312 * @param consolePanel
1313 * - panel to contain Jmol console
1314 * @param buttonsToShow
1315 * - buttons to show on the console, in ordr
1317 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1318 String htmlName, URL documentBase, URL codeBase,
1319 String commandOptions, final Container consolePanel,
1320 String buttonsToShow)
1322 if (commandOptions == null)
1324 commandOptions = "";
1326 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1327 (jmolfileio ? new SmarterJmolAdapter() : null),
1328 htmlName + ((Object) this).toString(), documentBase, codeBase,
1329 commandOptions, this);
1331 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1333 console = createJmolConsole(consolePanel, buttonsToShow);
1334 if (consolePanel != null)
1336 consolePanel.addComponentListener(this);
1342 protected abstract JmolAppConsoleInterface createJmolConsole(
1343 Container consolePanel, String buttonsToShow);
1345 protected org.jmol.api.JmolAppConsoleInterface console = null;
1348 public void setBackgroundColour(java.awt.Color col)
1351 viewer.evalStringQuiet("background [" + col.getRed() + ","
1352 + col.getGreen() + "," + col.getBlue() + "];");
1357 public int[] resizeInnerPanel(String data)
1359 // Jalview doesn't honour resize panel requests
1366 protected void closeConsole()
1368 if (console != null)
1372 console.setVisible(false);
1375 } catch (Exception x)
1384 * ComponentListener method
1387 public void componentMoved(ComponentEvent e)
1392 * ComponentListener method
1395 public void componentResized(ComponentEvent e)
1400 * ComponentListener method
1403 public void componentShown(ComponentEvent e)
1409 * ComponentListener method
1412 public void componentHidden(ComponentEvent e)
1418 public void showStructures(AlignViewportI av, boolean refocus)
1420 // TODO show Jmol structure optionally restricted to visible alignment
1421 // and/or selected chains