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.viewer.Viewer;
64 public abstract class JalviewJmolBinding extends AAStructureBindingModel
65 implements JmolStatusListener, JmolSelectionListener,
68 private String lastMessage;
70 boolean allChainsSelected = false;
73 * when true, try to search the associated datamodel for sequences that are
74 * associated with any unknown structures in the Jmol view.
76 private boolean associateNewStructs = false;
78 Vector<String> atomsPicked = new Vector<>();
80 Hashtable<String, String> chainFile;
83 * the default or current model displayed if the model cannot be identified
84 * from the selection message
88 // protected JmolGenericPopup jmolpopup; // not used - remove?
94 StringBuffer resetLastRes = new StringBuffer();
98 public JalviewJmolBinding(StructureSelectionManager ssm,
99 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
100 DataSourceType protocol)
102 super(ssm, pdbentry, sequenceIs, protocol);
104 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
105 * "jalviewJmol", ap.av.applet .getDocumentBase(),
106 * ap.av.applet.getCodeBase(), "", this);
108 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
112 public JalviewJmolBinding(StructureSelectionManager ssm,
113 SequenceI[][] seqs, Viewer theViewer)
118 viewer.setJmolStatusListener(this);
119 viewer.addSelectionListener(this);
123 * construct a title string for the viewer window based on the data jalview
128 public String getViewerTitle()
130 return getViewerTitle("Jmol", true);
134 * prepare the view for a given set of models/chains. chainList contains strings
135 * of the form 'pdbfilename:Chaincode'
137 * @deprecated now only used by applet code
140 public void centerViewer()
142 StringBuilder cmd = new StringBuilder(128);
144 for (String lbl : chainsToShow)
150 mlength = lbl.indexOf(":", p);
151 } while (p < mlength && mlength < (lbl.length() - 2));
152 // TODO: lookup each pdb id and recover proper model number for it.
153 cmd.append(":" + lbl.substring(mlength + 1) + " /"
154 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
156 if (cmd.length() > 0)
158 cmd.setLength(cmd.length() - 4);
160 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
161 evalStateCommand(command);
164 public void closeViewer()
166 // remove listeners for all structures in viewer
167 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
171 releaseUIResources();
175 public void colourByChain()
177 colourBySequence = false;
178 // TODO: colour by chain should colour each chain distinctly across all
180 // TODO: http://issues.jalview.org/browse/JAL-628
181 evalStateCommand("select *;color chain");
185 public void colourByCharge()
187 colourBySequence = false;
188 evalStateCommand("select *;color white;select ASP,GLU;color red;"
189 + "select LYS,ARG;color blue;select CYS;color yellow");
193 * superpose the structures associated with sequences in the alignment
194 * according to their corresponding positions.
196 public void superposeStructures(AlignmentI alignment)
198 superposeStructures(alignment, -1, null);
202 * superpose the structures associated with sequences in the alignment
203 * according to their corresponding positions. ded)
205 * @param refStructure
206 * - select which pdb file to use as reference (default is -1 - the
207 * first structure in the alignment)
209 public void superposeStructures(AlignmentI alignment, int refStructure)
211 superposeStructures(alignment, refStructure, null);
215 * superpose the structures associated with sequences in the alignment
216 * according to their corresponding positions. ded)
218 * @param refStructure
219 * - select which pdb file to use as reference (default is -1 - the
220 * first structure in the alignment)
224 public void superposeStructures(AlignmentI alignment, int refStructure,
225 HiddenColumns hiddenCols)
227 superposeStructures(new AlignmentI[] { alignment },
229 { refStructure }, new HiddenColumns[] { hiddenCols });
236 public String superposeStructures(AlignmentI[] _alignment,
237 int[] _refStructure, HiddenColumns[] _hiddenCols)
239 while (viewer.isScriptExecuting())
244 } catch (InterruptedException i)
250 * get the distinct structure files modelled
251 * (a file with multiple chains may map to multiple sequences)
253 String[] files = getStructureFiles();
254 if (!waitForFileLoad(files))
259 StringBuilder selectioncom = new StringBuilder(256);
260 // In principle - nSeconds specifies the speed of animation for each
261 // superposition - but is seems to behave weirdly, so we don't specify it.
262 String nSeconds = " ";
263 if (files.length > 10)
265 nSeconds = " 0.005 ";
269 nSeconds = " " + (2.0 / files.length) + " ";
270 // if (nSeconds).substring(0,5)+" ";
273 // see JAL-1345 - should really automatically turn off the animation for
274 // large numbers of structures, but Jmol doesn't seem to allow that.
276 // union of all aligned positions are collected together.
277 for (int a = 0; a < _alignment.length; a++)
279 int refStructure = _refStructure[a];
280 AlignmentI alignment = _alignment[a];
281 HiddenColumns hiddenCols = _hiddenCols[a];
282 if (a > 0 && selectioncom.length() > 0 && !selectioncom
283 .substring(selectioncom.length() - 1).equals("|"))
285 selectioncom.append("|");
287 // process this alignment
288 if (refStructure >= files.length)
291 "Invalid reference structure value " + refStructure);
296 * 'matched' bit j will be set for visible alignment columns j where
297 * all sequences have a residue with a mapping to the PDB structure
299 BitSet matched = new BitSet();
300 for (int m = 0; m < alignment.getWidth(); m++)
302 if (hiddenCols == null || hiddenCols.isVisible(m))
308 SuperposeData[] structures = new SuperposeData[files.length];
309 for (int f = 0; f < files.length; f++)
311 structures[f] = new SuperposeData(alignment.getWidth());
315 * Calculate the superposable alignment columns ('matched'), and the
316 * corresponding structure residue positions (structures.pdbResNo)
318 int candidateRefStructure = findSuperposableResidues(alignment,
319 matched, structures);
320 if (refStructure < 0)
323 * If no reference structure was specified, pick the first one that has
324 * a mapping in the alignment
326 refStructure = candidateRefStructure;
329 String[] selcom = new String[files.length];
330 int nmatched = matched.cardinality();
333 return (MessageManager.formatMessage("label.insufficient_residues",
338 * generate select statements to select regions to superimpose structures
341 // TODO extract method to construct selection statements
342 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
344 String chainCd = ":" + structures[pdbfnum].chain;
347 StringBuilder molsel = new StringBuilder();
350 int nextColumnMatch = matched.nextSetBit(0);
351 while (nextColumnMatch != -1)
353 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
354 if (lpos != pdbResNo - 1)
360 molsel.append(chainCd);
367 // continuous run - and lpos >-1
370 // at the beginning, so add dash
377 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
380 * add final selection phrase
385 molsel.append(chainCd);
388 if (molsel.length() > 1)
390 selcom[pdbfnum] = molsel.toString();
391 selectioncom.append("((");
392 selectioncom.append(selcom[pdbfnum].substring(1,
393 selcom[pdbfnum].length() - 1));
394 selectioncom.append(" )& ");
395 selectioncom.append(pdbfnum + 1);
396 selectioncom.append(".1)");
397 if (pdbfnum < files.length - 1)
399 selectioncom.append("|");
404 selcom[pdbfnum] = null;
408 StringBuilder command = new StringBuilder(256);
409 // command.append("set spinFps 10;\n");
411 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
413 if (pdbfnum == refStructure || selcom[pdbfnum] == null
414 || selcom[refStructure] == null)
418 command.append("echo ");
419 command.append("\"Superposing (");
420 command.append(structures[pdbfnum].pdbId);
421 command.append(") against reference (");
422 command.append(structures[refStructure].pdbId);
423 command.append(")\";\ncompare " + nSeconds);
425 command.append(Integer.toString(1 + pdbfnum));
426 command.append(".1} {");
427 command.append(Integer.toString(1 + refStructure));
428 // conformation=1 excludes alternate locations for CA (JAL-1757)
430 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
432 // for (int s = 0; s < 2; s++)
434 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
436 command.append(selcom[pdbfnum]);
437 command.append(selcom[refStructure]);
438 command.append(" ROTATE TRANSLATE;\n");
440 if (selectioncom.length() > 0)
442 // TODO is performing selectioncom redundant here? is done later on
443 // System.out.println("Select regions:\n" + selectioncom.toString());
444 evalStateCommand("select *; cartoons off; backbone; select ("
445 + selectioncom.toString() + "); cartoons; ");
446 // selcom.append("; ribbons; ");
447 String cmdString = command.toString();
448 // System.out.println("Superimpose command(s):\n" + cmdString);
450 evalStateCommand(cmdString);
453 if (selectioncom.length() > 0)
454 {// finally, mark all regions that were superposed.
455 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
457 selectioncom.setLength(selectioncom.length() - 1);
459 // System.out.println("Select regions:\n" + selectioncom.toString());
460 evalStateCommand("select *; cartoons off; backbone; select ("
461 + selectioncom.toString() + "); cartoons; zoom 0");
462 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
463 // cartoons; center "+selcom.toString());
469 public void evalStateCommand(String command)
472 if (lastCommand == null || !lastCommand.equals(command))
474 viewer.evalStringQuiet(command + "\n");
477 lastCommand = command;
480 Thread colourby = null;
483 * Sends a set of colour commands to the structure viewer
488 protected void colourBySequence(AlignmentViewPanel viewPanel)
490 Map<Object, AtomSpecModel> map = StructureCommands.buildColoursMap(this,
493 String[] commands = JmolCommands.getColourBySequenceCommand(map);
495 if (colourby != null)
497 colourby.interrupt();
500 colourby = new Thread(new Runnable()
505 for (String cmd : commands)
507 executeWhenReady(cmd);
517 protected void executeWhenReady(String command)
519 evalStateCommand(command);
522 public void createImage(String file, String type, int quality)
524 System.out.println("JMOL CREATE IMAGE");
528 public String createImage(String fileName, String type,
529 Object textOrBytes, int quality)
531 System.out.println("JMOL CREATE IMAGE");
536 public String eval(String strEval)
538 // System.out.println(strEval);
539 // "# 'eval' is implemented only for the applet.";
543 // End StructureListener
544 // //////////////////////////
547 public float[][] functionXY(String functionName, int x, int y)
553 public float[][][] functionXYZ(String functionName, int nx, int ny,
556 // TODO Auto-generated method stub
561 * instruct the Jalview binding to update the pdbentries vector if necessary
562 * prior to matching the jmol view's contents to the list of structure files
563 * Jalview knows about.
565 public abstract void refreshPdbEntries();
567 private int getModelNum(String modelFileName)
569 String[] mfn = getStructureFiles();
574 for (int i = 0; i < mfn.length; i++)
576 if (mfn[i].equalsIgnoreCase(modelFileName))
585 * map between index of model filename returned from getPdbFile and the first
586 * index of models from this file in the viewer. Note - this is not trimmed -
587 * use getPdbFile to get number of unique models.
589 private int _modelFileNameMap[];
592 public synchronized String[] getStructureFiles()
596 return new String[0];
599 if (modelFileNames == null)
601 List<String> mset = new ArrayList<>();
602 int modelCount = viewer.ms.mc;
603 String filePath = null;
604 for (int i = 0; i < modelCount; ++i)
606 filePath = viewer.ms.getModelFileName(i);
607 if (!mset.contains(filePath))
612 modelFileNames = mset.toArray(new String[mset.size()]);
615 return modelFileNames;
619 * map from string to applet
622 public Map<String, Object> getRegistryInfo()
624 // TODO Auto-generated method stub
628 // ///////////////////////////////
629 // JmolStatusListener
631 public void handlePopupMenu(int x, int y)
633 // jmolpopup.show(x, y);
634 // jmolpopup.jpiShow(x, y);
638 * Highlight zero, one or more atoms on the structure
641 public void highlightAtoms(List<AtomSpec> atoms)
645 if (resetLastRes.length() > 0)
647 viewer.evalStringQuiet(resetLastRes.toString());
648 resetLastRes.setLength(0);
650 for (AtomSpec atom : atoms)
652 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
653 atom.getChain(), atom.getPdbFile());
659 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
662 if (modelFileNames == null)
667 // look up file model number for this pdbfile
669 // may need to adjust for URLencoding here - we don't worry about that yet.
670 while (mdlNum < modelFileNames.length
671 && !pdbfile.equals(modelFileNames[mdlNum]))
675 if (mdlNum == modelFileNames.length)
682 StringBuilder cmd = new StringBuilder(64);
683 cmd.append("select " + pdbResNum); // +modelNum
685 resetLastRes.append("select " + pdbResNum); // +modelNum
688 resetLastRes.append(":");
689 if (!chain.equals(" "))
692 resetLastRes.append(chain);
695 cmd.append(" /" + (mdlNum + 1));
696 resetLastRes.append("/" + (mdlNum + 1));
698 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
700 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
701 + " and not hetero; spacefill 0;");
703 cmd.append("spacefill 200;select none");
705 viewer.evalStringQuiet(cmd.toString());
710 boolean debug = true;
712 private void jmolHistory(boolean enable)
714 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
717 public void loadInline(String string)
721 // viewer.loadInline(strModel, isAppend);
723 // construct fake fullPathName and fileName so we can identify the file
725 // Then, construct pass a reader for the string to Jmol.
726 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
727 // fileName, null, reader, false, null, null, 0);
728 viewer.openStringInline(string);
731 protected void mouseOverStructure(int atomIndex, final String strInfo)
734 int alocsep = strInfo.indexOf("^");
735 int mdlSep = strInfo.indexOf("/");
736 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
738 if (chainSeparator == -1)
740 chainSeparator = strInfo.indexOf(".");
741 if (mdlSep > -1 && mdlSep < chainSeparator)
743 chainSeparator1 = chainSeparator;
744 chainSeparator = mdlSep;
747 // handle insertion codes
750 pdbResNum = Integer.parseInt(
751 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
756 pdbResNum = Integer.parseInt(
757 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
761 if (strInfo.indexOf(":") > -1)
763 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
764 strInfo.indexOf("."));
771 String pdbfilename = modelFileNames[frameNo]; // default is first or current
775 if (chainSeparator1 == -1)
777 chainSeparator1 = strInfo.indexOf(".", mdlSep);
779 String mdlId = (chainSeparator1 > -1)
780 ? strInfo.substring(mdlSep + 1, chainSeparator1)
781 : strInfo.substring(mdlSep + 1);
784 // recover PDB filename for the model hovered over.
785 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
786 if (_modelFileNameMap != null)
788 int _mp = _modelFileNameMap.length - 1;
790 while (mnumber < _modelFileNameMap[_mp])
794 pdbfilename = modelFileNames[_mp];
798 if (mnumber >= 0 && mnumber < modelFileNames.length)
800 pdbfilename = modelFileNames[mnumber];
803 if (pdbfilename == null)
805 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
809 } catch (Exception e)
815 * highlight position on alignment(s); if some text is returned,
816 * show this as a second line on the structure hover tooltip
818 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
822 // change comma to pipe separator (newline token for Jmol)
823 label = label.replace(',', '|');
824 StringTokenizer toks = new StringTokenizer(strInfo, " ");
825 StringBuilder sb = new StringBuilder();
826 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
827 .append(chainId).append("/1");
828 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
829 .append(toks.nextToken());
830 sb.append("|").append(label).append("\"");
831 evalStateCommand(sb.toString());
835 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
837 if (strInfo.equals(lastMessage))
841 lastMessage = strInfo;
844 System.err.println("Ignoring additional hover info: " + data
845 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
847 mouseOverStructure(atomIndex, strInfo);
851 * { if (history != null && strStatus != null &&
852 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
856 public void notifyAtomPicked(int atomIndex, String strInfo,
860 * this implements the toggle label behaviour copied from the original
861 * structure viewer, MCView
865 System.err.println("Ignoring additional pick data string " + strData);
867 int chainSeparator = strInfo.indexOf(":");
869 if (chainSeparator == -1)
871 chainSeparator = strInfo.indexOf(".");
874 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
876 String mdlString = "";
877 if ((p = strInfo.indexOf(":")) > -1)
879 picked += strInfo.substring(p, strInfo.indexOf("."));
882 if ((p = strInfo.indexOf("/")) > -1)
884 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
886 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
890 if (!atomsPicked.contains(picked))
892 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
893 atomsPicked.addElement(picked);
897 viewer.evalString("select " + picked + ";label off");
898 atomsPicked.removeElement(picked);
901 // TODO: in application this happens
903 // if (scriptWindow != null)
905 // scriptWindow.sendConsoleMessage(strInfo);
906 // scriptWindow.sendConsoleMessage("\n");
912 public void notifyCallback(CBK type, Object[] data)
919 notifyFileLoaded((String) data[1], (String) data[2],
920 (String) data[3], (String) data[4],
921 ((Integer) data[5]).intValue());
925 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
927 // also highlight in alignment
928 // deliberate fall through
930 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
934 notifyScriptTermination((String) data[2],
935 ((Integer) data[3]).intValue());
938 sendConsoleEcho((String) data[1]);
942 (data == null) ? ((String) null) : (String) data[1]);
945 // System.err.println("Ignoring error callback.");
956 "Unhandled callback " + type + " " + data[1].toString());
959 } catch (Exception e)
961 System.err.println("Squashed Jmol callback handler error:");
967 public boolean notifyEnabled(CBK callbackPick)
969 switch (callbackPick)
985 // incremented every time a load notification is successfully handled -
986 // lightweight mechanism for other threads to detect when they can start
987 // referrring to new structures.
988 private long loadNotifiesHandled = 0;
990 public long getLoadNotifiesHandled()
992 return loadNotifiesHandled;
995 public void notifyFileLoaded(String fullPathName, String fileName2,
996 String modelName, String errorMsg, int modelParts)
998 if (errorMsg != null)
1000 fileLoadingError = errorMsg;
1004 // TODO: deal sensibly with models loaded inLine:
1005 // modelName will be null, as will fullPathName.
1007 // the rest of this routine ignores the arguments, and simply interrogates
1008 // the Jmol view to find out what structures it contains, and adds them to
1009 // the structure selection manager.
1010 fileLoadingError = null;
1011 String[] oldmodels = modelFileNames;
1012 modelFileNames = null;
1013 chainNames = new ArrayList<>();
1014 chainFile = new Hashtable<>();
1015 boolean notifyLoaded = false;
1016 String[] modelfilenames = getStructureFiles();
1017 // first check if we've lost any structures
1018 if (oldmodels != null && oldmodels.length > 0)
1021 for (int i = 0; i < oldmodels.length; i++)
1023 for (int n = 0; n < modelfilenames.length; n++)
1025 if (modelfilenames[n] == oldmodels[i])
1027 oldmodels[i] = null;
1031 if (oldmodels[i] != null)
1038 String[] oldmfn = new String[oldm];
1040 for (int i = 0; i < oldmodels.length; i++)
1042 if (oldmodels[i] != null)
1044 oldmfn[oldm++] = oldmodels[i];
1047 // deregister the Jmol instance for these structures - we'll add
1048 // ourselves again at the end for the current structure set.
1049 getSsm().removeStructureViewerListener(this, oldmfn);
1052 refreshPdbEntries();
1053 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1055 String fileName = modelfilenames[modelnum];
1056 boolean foundEntry = false;
1057 StructureFile pdb = null;
1058 String pdbfile = null;
1059 // model was probably loaded inline - so check the pdb file hashcode
1062 // calculate essential attributes for the pdb data imported inline.
1063 // prolly need to resolve modelnumber properly - for now just use our
1065 pdbfile = viewer.getData(
1066 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1068 // search pdbentries and sequences to find correct pdbentry for this
1070 for (int pe = 0; pe < getPdbCount(); pe++)
1072 boolean matches = false;
1073 addSequence(pe, getSequence()[pe]);
1074 if (fileName == null)
1077 // see JAL-623 - need method of matching pasted data up
1079 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1080 pdbfile, DataSourceType.PASTE,
1081 getIProgressIndicator());
1082 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1089 File fl = new File(getPdbEntry(pe).getFile());
1090 matches = fl.equals(new File(fileName));
1094 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1097 // to be tested. See mantis bug
1098 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1099 DataSourceType protocol = DataSourceType.URL;
1104 protocol = DataSourceType.FILE;
1106 } catch (Exception e)
1111 // Explicitly map to the filename used by Jmol ;
1112 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1113 fileName, protocol, getIProgressIndicator());
1114 // pdbentry[pe].getFile(), protocol);
1120 // add an entry for every chain in the model
1121 for (int i = 0; i < pdb.getChains().size(); i++)
1123 String chid = new String(
1124 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1125 chainFile.put(chid, fileName);
1126 chainNames.add(chid);
1128 notifyLoaded = true;
1132 if (!foundEntry && associateNewStructs)
1134 // this is a foreign pdb file that jalview doesn't know about - add
1135 // it to the dataset and try to find a home - either on a matching
1136 // sequence or as a new sequence.
1137 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1139 // parse pdb file into a chain, etc.
1140 // locate best match for pdb in associated views and add mapping to
1142 // if properly registered then
1143 notifyLoaded = true;
1148 // so finally, update the jmol bits and pieces
1149 // if (jmolpopup != null)
1151 // // potential for deadlock here:
1152 // // jmolpopup.updateComputedMenus();
1154 if (!isLoadingFromArchive())
1156 viewer.evalStringQuiet(
1157 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1159 // register ourselves as a listener and notify the gui that it needs to
1161 getSsm().addStructureViewerListener(this);
1164 FeatureRenderer fr = getFeatureRenderer(null);
1170 loadNotifiesHandled++;
1172 setLoadingFromArchive(false);
1175 protected IProgressIndicator getIProgressIndicator()
1180 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1182 notifyAtomPicked(iatom, strMeasure, null);
1185 public abstract void notifyScriptTermination(String strStatus,
1189 * display a message echoed from the jmol viewer
1193 public abstract void sendConsoleEcho(String strEcho); /*
1194 * { showConsole(true);
1196 * history.append("\n" +
1200 // /End JmolStatusListener
1201 // /////////////////////////////
1205 * status message - usually the response received after a script
1208 public abstract void sendConsoleMessage(String strStatus);
1211 public void setCallbackFunction(String callbackType,
1212 String callbackFunction)
1214 System.err.println("Ignoring set-callback request to associate "
1215 + callbackType + " with function " + callbackFunction);
1220 public void setJalviewColourScheme(ColourSchemeI cs)
1222 colourBySequence = false;
1230 StringBuilder command = new StringBuilder(128);
1231 command.append("select *;color white;");
1232 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1234 for (String resName : residueSet)
1236 char res = resName.length() == 3
1237 ? ResidueProperties.getSingleCharacterCode(resName)
1238 : resName.charAt(0);
1239 Color col = cs.findColour(res, 0, null, null, 0f);
1240 command.append("select " + resName + ";color[" + col.getRed() + ","
1241 + col.getGreen() + "," + col.getBlue() + "];");
1244 evalStateCommand(command.toString());
1248 public void showHelp()
1250 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1254 * open the URL somehow
1258 public abstract void showUrl(String url, String target);
1261 * called when the binding thinks the UI needs to be refreshed after a Jmol
1262 * state change. this could be because structures were loaded, or because an
1263 * error has occured.
1265 public abstract void refreshGUI();
1268 * called to show or hide the associated console window container.
1272 public abstract void showConsole(boolean show);
1275 * @param renderPanel
1277 * - when true will initialise jmol's file IO system (should be false
1278 * in applet context)
1280 * @param documentBase
1282 * @param commandOptions
1284 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1285 String htmlName, URL documentBase, URL codeBase,
1286 String commandOptions)
1288 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1289 codeBase, commandOptions, null, null);
1294 * @param renderPanel
1296 * - when true will initialise jmol's file IO system (should be false
1297 * in applet context)
1299 * @param documentBase
1301 * @param commandOptions
1302 * @param consolePanel
1303 * - panel to contain Jmol console
1304 * @param buttonsToShow
1305 * - buttons to show on the console, in ordr
1307 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1308 String htmlName, URL documentBase, URL codeBase,
1309 String commandOptions, final Container consolePanel,
1310 String buttonsToShow)
1312 if (commandOptions == null)
1314 commandOptions = "";
1316 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1317 (jmolfileio ? new SmarterJmolAdapter() : null),
1318 htmlName + ((Object) this).toString(), documentBase, codeBase,
1319 commandOptions, this);
1321 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1323 console = createJmolConsole(consolePanel, buttonsToShow);
1324 if (consolePanel != null)
1326 consolePanel.addComponentListener(this);
1332 protected abstract JmolAppConsoleInterface createJmolConsole(
1333 Container consolePanel, String buttonsToShow);
1335 protected org.jmol.api.JmolAppConsoleInterface console = null;
1338 public void setBackgroundColour(java.awt.Color col)
1341 viewer.evalStringQuiet("background [" + col.getRed() + ","
1342 + col.getGreen() + "," + col.getBlue() + "];");
1347 public int[] resizeInnerPanel(String data)
1349 // Jalview doesn't honour resize panel requests
1356 protected void closeConsole()
1358 if (console != null)
1362 console.setVisible(false);
1365 } catch (Exception x)
1374 * ComponentListener method
1377 public void componentMoved(ComponentEvent e)
1382 * ComponentListener method
1385 public void componentResized(ComponentEvent e)
1390 * ComponentListener method
1393 public void componentShown(ComponentEvent e)
1399 * ComponentListener method
1402 public void componentHidden(ComponentEvent e)
1408 public void showStructures(AlignViewportI av, boolean refocus)
1410 StringBuilder cmd = new StringBuilder(128);
1411 if (isShowAlignmentOnly())
1413 AtomSpecModel model = getShownResidues(av);
1414 String atomSpec = JmolCommands.getAtomSpec(model);
1416 cmd.append("hide *;display ").append(atomSpec)
1417 .append("; select displayed");
1421 cmd.append(";display *");
1423 cmd.append("; cartoon only");
1426 cmd.append("; zoom 0");
1428 evalStateCommand(cmd.toString());
1432 * Answers a Jmol syntax style structure model specification. Model number 0, 1,
1433 * 2... is formatted as "1.1", "2.1", "3.1" etc.
1436 public String getModelSpec(int model)
1438 return String.valueOf(model + 1) + ".1";
1442 * Sends a command to recentre the display
1445 public void focusView()
1448 * don't use evalStateCommand because it ignores a command that is the same
1449 * as the last command (why?); but user may have adjusted the display since
1451 viewer.evalString("zoom 0");
1455 public int getModelForPdbFile(String fileName, int fileIndex)