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.api.SequenceRenderer;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.HiddenColumns;
29 import jalview.datamodel.PDBEntry;
30 import jalview.datamodel.SequenceI;
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.StructureMappingcommandSet;
38 import jalview.structure.StructureSelectionManager;
39 import jalview.structures.models.AAStructureBindingModel;
40 import jalview.util.MessageManager;
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.Vector;
55 import org.jmol.adapter.smarter.SmarterJmolAdapter;
56 import org.jmol.api.JmolAppConsoleInterface;
57 import org.jmol.api.JmolSelectionListener;
58 import org.jmol.api.JmolStatusListener;
59 import org.jmol.api.JmolViewer;
60 import org.jmol.c.CBK;
61 import org.jmol.script.T;
62 import org.jmol.viewer.Viewer;
64 public abstract class JalviewJmolBinding extends AAStructureBindingModel
65 implements JmolStatusListener, JmolSelectionListener,
68 boolean allChainsSelected = false;
71 * when true, try to search the associated datamodel for sequences that are
72 * associated with any unknown structures in the Jmol view.
74 private boolean associateNewStructs = false;
76 Vector<String> atomsPicked = new Vector<>();
78 private List<String> chainNames;
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?
96 StringBuffer resetLastRes = new StringBuffer();
100 public JalviewJmolBinding(StructureSelectionManager ssm,
101 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
102 DataSourceType protocol)
104 super(ssm, pdbentry, sequenceIs, protocol);
106 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
107 * "jalviewJmol", ap.av.applet .getDocumentBase(),
108 * ap.av.applet.getCodeBase(), "", this);
110 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
114 public JalviewJmolBinding(StructureSelectionManager ssm,
115 SequenceI[][] seqs, Viewer theViewer)
120 viewer.setJmolStatusListener(this);
121 viewer.addSelectionListener(this);
125 * construct a title string for the viewer window based on the data jalview
130 public String getViewerTitle()
132 return getViewerTitle("Jmol", true);
136 * prepare the view for a given set of models/chains. chainList contains
137 * strings of the form 'pdbfilename:Chaincode'
139 public void centerViewer()
141 StringBuilder cmd = new StringBuilder(128);
143 for (String lbl : chainsToShow)
149 mlength = lbl.indexOf(":", p);
150 } while (p < mlength && mlength < (lbl.length() - 2));
151 // TODO: lookup each pdb id and recover proper model number for it.
152 cmd.append(":" + lbl.substring(mlength + 1) + " /"
153 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
155 if (cmd.length() > 0)
157 cmd.setLength(cmd.length() - 4);
159 String command = "select *;restrict " + cmd + ";cartoon;center " + cmd;
160 evalStateCommand(command);
163 public void closeViewer()
165 // remove listeners for all structures in viewer
166 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
170 releaseUIResources();
174 public void colourByChain()
176 colourBySequence = false;
177 // TODO: colour by chain should colour each chain distinctly across all
179 // TODO: http://issues.jalview.org/browse/JAL-628
180 evalStateCommand("select *;color chain");
184 public void colourByCharge()
186 colourBySequence = false;
187 evalStateCommand("select *;color white;select ASP,GLU;color red;"
188 + "select LYS,ARG;color blue;select CYS;color yellow");
192 * superpose the structures associated with sequences in the alignment
193 * according to their corresponding positions.
195 public void superposeStructures(AlignmentI alignment)
197 superposeStructures(alignment, -1, null);
201 * superpose the structures associated with sequences in the alignment
202 * according to their corresponding positions. ded)
204 * @param refStructure
205 * - select which pdb file to use as reference (default is -1 - the
206 * first structure in the alignment)
208 public void superposeStructures(AlignmentI alignment, int refStructure)
210 superposeStructures(alignment, refStructure, null);
214 * superpose the structures associated with sequences in the alignment
215 * according to their corresponding positions. ded)
217 * @param refStructure
218 * - select which pdb file to use as reference (default is -1 - the
219 * first structure in the alignment)
223 public void superposeStructures(AlignmentI alignment, int refStructure,
224 HiddenColumns hiddenCols)
226 superposeStructures(new AlignmentI[] { alignment },
228 { refStructure }, new HiddenColumns[] { hiddenCols });
235 public String superposeStructures(AlignmentI[] _alignment,
236 int[] _refStructure, HiddenColumns[] _hiddenCols)
238 while (viewer.isScriptExecuting())
243 } catch (InterruptedException i)
249 * get the distinct structure files modelled
250 * (a file with multiple chains may map to multiple sequences)
252 String[] files = getStructureFiles();
253 if (!waitForFileLoad(files))
258 StringBuilder selectioncom = new StringBuilder(256);
259 // In principle - nSeconds specifies the speed of animation for each
260 // superposition - but is seems to behave weirdly, so we don't specify it.
261 String nSeconds = " ";
262 if (files.length > 10)
264 nSeconds = " 0.005 ";
268 nSeconds = " " + (2.0 / files.length) + " ";
269 // if (nSeconds).substring(0,5)+" ";
272 // see JAL-1345 - should really automatically turn off the animation for
273 // large numbers of structures, but Jmol doesn't seem to allow that.
275 // union of all aligned positions are collected together.
276 for (int a = 0; a < _alignment.length; a++)
278 int refStructure = _refStructure[a];
279 AlignmentI alignment = _alignment[a];
280 HiddenColumns hiddenCols = _hiddenCols[a];
281 if (a > 0 && selectioncom.length() > 0 && !selectioncom
282 .substring(selectioncom.length() - 1).equals("|"))
284 selectioncom.append("|");
286 // process this alignment
287 if (refStructure >= files.length)
290 "Invalid reference structure value " + refStructure);
295 * 'matched' bit j will be set for visible alignment columns j where
296 * all sequences have a residue with a mapping to the PDB structure
298 BitSet matched = new BitSet();
299 for (int m = 0; m < alignment.getWidth(); m++)
301 if (hiddenCols == null || hiddenCols.isVisible(m))
307 SuperposeData[] structures = new SuperposeData[files.length];
308 for (int f = 0; f < files.length; f++)
310 structures[f] = new SuperposeData(alignment.getWidth());
314 * Calculate the superposable alignment columns ('matched'), and the
315 * corresponding structure residue positions (structures.pdbResNo)
317 int candidateRefStructure = findSuperposableResidues(alignment,
318 matched, structures);
319 if (refStructure < 0)
322 * If no reference structure was specified, pick the first one that has
323 * a mapping in the alignment
325 refStructure = candidateRefStructure;
328 String[] selcom = new String[files.length];
329 int nmatched = matched.cardinality();
332 return (MessageManager.formatMessage("label.insufficient_residues",
337 * generate select statements to select regions to superimpose structures
340 // TODO extract method to construct selection statements
341 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
343 String chainCd = ":" + structures[pdbfnum].chain;
346 StringBuilder molsel = new StringBuilder();
349 int nextColumnMatch = matched.nextSetBit(0);
350 while (nextColumnMatch != -1)
352 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
353 if (lpos != pdbResNo - 1)
359 molsel.append(chainCd);
366 // continuous run - and lpos >-1
369 // at the beginning, so add dash
376 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
379 * add final selection phrase
384 molsel.append(chainCd);
387 if (molsel.length() > 1)
389 selcom[pdbfnum] = molsel.toString();
390 selectioncom.append("((");
391 selectioncom.append(selcom[pdbfnum].substring(1,
392 selcom[pdbfnum].length() - 1));
393 selectioncom.append(" )& ");
394 selectioncom.append(pdbfnum + 1);
395 selectioncom.append(".1)");
396 if (pdbfnum < files.length - 1)
398 selectioncom.append("|");
403 selcom[pdbfnum] = null;
407 StringBuilder command = new StringBuilder(256);
408 // command.append("set spinFps 10;\n");
410 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
412 if (pdbfnum == refStructure || selcom[pdbfnum] == null
413 || selcom[refStructure] == null)
417 command.append("echo ");
418 command.append("\"Superposing (");
419 command.append(structures[pdbfnum].pdbId);
420 command.append(") against reference (");
421 command.append(structures[refStructure].pdbId);
422 command.append(")\";\ncompare " + nSeconds);
424 command.append(Integer.toString(1 + pdbfnum));
425 command.append(".1} {");
426 command.append(Integer.toString(1 + refStructure));
427 // conformation=1 excludes alternate locations for CA (JAL-1757)
429 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
431 // for (int s = 0; s < 2; s++)
433 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
435 command.append(selcom[pdbfnum]);
436 command.append(selcom[refStructure]);
437 command.append(" ROTATE TRANSLATE;\n");
439 if (selectioncom.length() > 0)
441 // TODO is performing selectioncom redundant here? is done later on
442 // System.out.println("Select regions:\n" + selectioncom.toString());
443 evalStateCommand("select *; cartoons off; backbone; select ("
444 + selectioncom.toString() + "); cartoons; ");
445 // selcom.append("; ribbons; ");
446 String cmdString = command.toString();
447 // System.out.println("Superimpose command(s):\n" + cmdString);
449 evalStateCommand(cmdString);
452 if (selectioncom.length() > 0)
453 {// finally, mark all regions that were superposed.
454 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
456 selectioncom.setLength(selectioncom.length() - 1);
458 // System.out.println("Select regions:\n" + selectioncom.toString());
459 evalStateCommand("select *; cartoons off; backbone; select ("
460 + selectioncom.toString() + "); cartoons; ");
461 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
462 // cartoons; center "+selcom.toString());
468 public void evalStateCommand(String command)
471 if (lastCommand == null || !lastCommand.equals(command))
473 viewer.evalStringQuiet(command + "\n");
476 lastCommand = command;
479 Thread colourby = null;
481 * Sends a set of colour commands to the structure viewer
483 * @param colourBySequenceCommands
486 protected void colourBySequence(
487 final StructureMappingcommandSet[] colourBySequenceCommands)
489 if (colourby != null)
491 colourby.interrupt();
494 colourby = new Thread(new Runnable()
499 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
501 for (String cbyseq : cpdbbyseq.commands)
503 executeWhenReady(cbyseq);
518 protected StructureMappingcommandSet[] getColourBySequenceCommands(
519 String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
521 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
522 getSequence(), sr, viewPanel);
528 protected void executeWhenReady(String command)
530 evalStateCommand(command);
533 public void createImage(String file, String type, int quality)
535 System.out.println("JMOL CREATE IMAGE");
539 public String createImage(String fileName, String type,
540 Object textOrBytes, int quality)
542 System.out.println("JMOL CREATE IMAGE");
547 public String eval(String strEval)
549 // System.out.println(strEval);
550 // "# 'eval' is implemented only for the applet.";
554 // End StructureListener
555 // //////////////////////////
558 public float[][] functionXY(String functionName, int x, int y)
564 public float[][][] functionXYZ(String functionName, int nx, int ny,
567 // TODO Auto-generated method stub
571 public Color getColour(int atomIndex, int pdbResNum, String chain,
574 if (getModelNum(pdbfile) < 0)
578 // TODO: verify atomIndex is selecting correct model.
579 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
580 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
581 return new Color(colour);
585 * instruct the Jalview binding to update the pdbentries vector if necessary
586 * prior to matching the jmol view's contents to the list of structure files
587 * Jalview knows about.
589 public abstract void refreshPdbEntries();
591 private int getModelNum(String modelFileName)
593 String[] mfn = getStructureFiles();
598 for (int i = 0; i < mfn.length; i++)
600 if (mfn[i].equalsIgnoreCase(modelFileName))
609 * map between index of model filename returned from getPdbFile and the first
610 * index of models from this file in the viewer. Note - this is not trimmed -
611 * use getPdbFile to get number of unique models.
613 private int _modelFileNameMap[];
616 public synchronized String[] getStructureFiles()
618 List<String> mset = new ArrayList<>();
621 return new String[0];
624 if (modelFileNames == null)
626 int modelCount = viewer.ms.mc;
627 String filePath = null;
628 for (int i = 0; i < modelCount; ++i)
630 filePath = viewer.ms.getModelFileName(i);
631 if (!mset.contains(filePath))
636 modelFileNames = mset.toArray(new String[mset.size()]);
639 return modelFileNames;
643 * map from string to applet
646 public Map<String, Object> getRegistryInfo()
648 // TODO Auto-generated method stub
652 // ///////////////////////////////
653 // JmolStatusListener
655 public void handlePopupMenu(int x, int y)
657 // jmolpopup.show(x, y);
658 // jmolpopup.jpiShow(x, y);
662 * Highlight zero, one or more atoms on the structure
665 public void highlightAtoms(List<AtomSpec> atoms)
669 if (resetLastRes.length() > 0)
671 viewer.evalStringQuiet(resetLastRes.toString());
672 resetLastRes.setLength(0);
674 for (AtomSpec atom : atoms)
676 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
677 atom.getChain(), atom.getPdbFile());
683 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
686 if (modelFileNames == null)
691 // look up file model number for this pdbfile
693 // may need to adjust for URLencoding here - we don't worry about that yet.
694 while (mdlNum < modelFileNames.length
695 && !pdbfile.equals(modelFileNames[mdlNum]))
699 if (mdlNum == modelFileNames.length)
706 StringBuilder cmd = new StringBuilder(64);
707 cmd.append("select " + pdbResNum); // +modelNum
709 resetLastRes.append("select " + pdbResNum); // +modelNum
712 resetLastRes.append(":");
713 if (!chain.equals(" "))
716 resetLastRes.append(chain);
719 cmd.append(" /" + (mdlNum + 1));
720 resetLastRes.append("/" + (mdlNum + 1));
722 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
724 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
725 + " and not hetero; spacefill 0;");
727 cmd.append("spacefill 200;select none");
729 viewer.evalStringQuiet(cmd.toString());
734 boolean debug = true;
736 private void jmolHistory(boolean enable)
738 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
741 public void loadInline(String string)
745 // viewer.loadInline(strModel, isAppend);
747 // construct fake fullPathName and fileName so we can identify the file
749 // Then, construct pass a reader for the string to Jmol.
750 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
751 // fileName, null, reader, false, null, null, 0);
752 viewer.openStringInline(string);
755 public void mouseOverStructure(int atomIndex, String strInfo)
758 int alocsep = strInfo.indexOf("^");
759 int mdlSep = strInfo.indexOf("/");
760 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
762 if (chainSeparator == -1)
764 chainSeparator = strInfo.indexOf(".");
765 if (mdlSep > -1 && mdlSep < chainSeparator)
767 chainSeparator1 = chainSeparator;
768 chainSeparator = mdlSep;
771 // handle insertion codes
774 pdbResNum = Integer.parseInt(
775 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
780 pdbResNum = Integer.parseInt(
781 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
785 if (strInfo.indexOf(":") > -1)
787 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
788 strInfo.indexOf("."));
795 String pdbfilename = modelFileNames[frameNo]; // default is first or current
799 if (chainSeparator1 == -1)
801 chainSeparator1 = strInfo.indexOf(".", mdlSep);
803 String mdlId = (chainSeparator1 > -1)
804 ? strInfo.substring(mdlSep + 1, chainSeparator1)
805 : strInfo.substring(mdlSep + 1);
808 // recover PDB filename for the model hovered over.
809 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
810 if (_modelFileNameMap != null)
812 int _mp = _modelFileNameMap.length - 1;
814 while (mnumber < _modelFileNameMap[_mp])
818 pdbfilename = modelFileNames[_mp];
822 if (mnumber >= 0 && mnumber < modelFileNames.length)
824 pdbfilename = modelFileNames[mnumber];
827 if (pdbfilename == null)
829 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
833 } catch (Exception e)
838 if (lastMessage == null || !lastMessage.equals(strInfo))
840 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
843 lastMessage = strInfo;
846 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
850 System.err.println("Ignoring additional hover info: " + data
851 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
853 mouseOverStructure(atomIndex, strInfo);
857 * { if (history != null && strStatus != null &&
858 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
862 public void notifyAtomPicked(int atomIndex, String strInfo,
866 * this implements the toggle label behaviour copied from the original
867 * structure viewer, MCView
871 System.err.println("Ignoring additional pick data string " + strData);
873 int chainSeparator = strInfo.indexOf(":");
875 if (chainSeparator == -1)
877 chainSeparator = strInfo.indexOf(".");
880 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
882 String mdlString = "";
883 if ((p = strInfo.indexOf(":")) > -1)
885 picked += strInfo.substring(p, strInfo.indexOf("."));
888 if ((p = strInfo.indexOf("/")) > -1)
890 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
892 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
896 if (!atomsPicked.contains(picked))
898 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
899 atomsPicked.addElement(picked);
903 viewer.evalString("select " + picked + ";label off");
904 atomsPicked.removeElement(picked);
907 // TODO: in application this happens
909 // if (scriptWindow != null)
911 // scriptWindow.sendConsoleMessage(strInfo);
912 // scriptWindow.sendConsoleMessage("\n");
918 public void notifyCallback(CBK type, Object[] data)
925 notifyFileLoaded((String) data[1], (String) data[2],
926 (String) data[3], (String) data[4],
927 ((Integer) data[5]).intValue());
931 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
933 // also highlight in alignment
934 // deliberate fall through
936 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
940 notifyScriptTermination((String) data[2],
941 ((Integer) data[3]).intValue());
944 sendConsoleEcho((String) data[1]);
948 (data == null) ? ((String) null) : (String) data[1]);
951 // System.err.println("Ignoring error callback.");
962 "Unhandled callback " + type + " " + data[1].toString());
965 } catch (Exception e)
967 System.err.println("Squashed Jmol callback handler error:");
973 public boolean notifyEnabled(CBK callbackPick)
975 switch (callbackPick)
991 // incremented every time a load notification is successfully handled -
992 // lightweight mechanism for other threads to detect when they can start
993 // referrring to new structures.
994 private long loadNotifiesHandled = 0;
996 public long getLoadNotifiesHandled()
998 return loadNotifiesHandled;
1001 public void notifyFileLoaded(String fullPathName, String fileName2,
1002 String modelName, String errorMsg, int modelParts)
1004 if (errorMsg != null)
1006 fileLoadingError = errorMsg;
1010 // TODO: deal sensibly with models loaded inLine:
1011 // modelName will be null, as will fullPathName.
1013 // the rest of this routine ignores the arguments, and simply interrogates
1014 // the Jmol view to find out what structures it contains, and adds them to
1015 // the structure selection manager.
1016 fileLoadingError = null;
1017 String[] oldmodels = modelFileNames;
1018 modelFileNames = null;
1019 chainNames = new ArrayList<>();
1020 chainFile = new Hashtable<>();
1021 boolean notifyLoaded = false;
1022 String[] modelfilenames = getStructureFiles();
1023 // first check if we've lost any structures
1024 if (oldmodels != null && oldmodels.length > 0)
1027 for (int i = 0; i < oldmodels.length; i++)
1029 for (int n = 0; n < modelfilenames.length; n++)
1031 if (modelfilenames[n] == oldmodels[i])
1033 oldmodels[i] = null;
1037 if (oldmodels[i] != null)
1044 String[] oldmfn = new String[oldm];
1046 for (int i = 0; i < oldmodels.length; i++)
1048 if (oldmodels[i] != null)
1050 oldmfn[oldm++] = oldmodels[i];
1053 // deregister the Jmol instance for these structures - we'll add
1054 // ourselves again at the end for the current structure set.
1055 getSsm().removeStructureViewerListener(this, oldmfn);
1058 refreshPdbEntries();
1059 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1061 String fileName = modelfilenames[modelnum];
1062 boolean foundEntry = false;
1063 StructureFile pdb = null;
1064 String pdbfile = null;
1065 // model was probably loaded inline - so check the pdb file hashcode
1068 // calculate essential attributes for the pdb data imported inline.
1069 // prolly need to resolve modelnumber properly - for now just use our
1071 pdbfile = viewer.getData(
1072 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1074 // search pdbentries and sequences to find correct pdbentry for this
1076 for (int pe = 0; pe < getPdbCount(); pe++)
1078 boolean matches = false;
1079 addSequence(pe, getSequence()[pe]);
1080 if (fileName == null)
1083 // see JAL-623 - need method of matching pasted data up
1085 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1086 pdbfile, DataSourceType.PASTE,
1087 getIProgressIndicator());
1088 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1095 File fl = new File(getPdbEntry(pe).getFile());
1096 matches = fl.equals(new File(fileName));
1100 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1103 // to be tested. See mantis bug
1104 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1105 DataSourceType protocol = DataSourceType.URL;
1110 protocol = DataSourceType.FILE;
1112 } catch (Exception e)
1117 // Explicitly map to the filename used by Jmol ;
1118 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1119 fileName, protocol, getIProgressIndicator());
1120 // pdbentry[pe].getFile(), protocol);
1126 // add an entry for every chain in the model
1127 for (int i = 0; i < pdb.getChains().size(); i++)
1129 String chid = new String(
1130 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1131 chainFile.put(chid, fileName);
1132 chainNames.add(chid);
1134 notifyLoaded = true;
1138 if (!foundEntry && associateNewStructs)
1140 // this is a foreign pdb file that jalview doesn't know about - add
1141 // it to the dataset and try to find a home - either on a matching
1142 // sequence or as a new sequence.
1143 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1145 // parse pdb file into a chain, etc.
1146 // locate best match for pdb in associated views and add mapping to
1148 // if properly registered then
1149 notifyLoaded = true;
1154 // so finally, update the jmol bits and pieces
1155 // if (jmolpopup != null)
1157 // // potential for deadlock here:
1158 // // jmolpopup.updateComputedMenus();
1160 if (!isLoadingFromArchive())
1162 viewer.evalStringQuiet(
1163 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1165 // register ourselves as a listener and notify the gui that it needs to
1167 getSsm().addStructureViewerListener(this);
1170 FeatureRenderer fr = getFeatureRenderer(null);
1176 loadNotifiesHandled++;
1178 setLoadingFromArchive(false);
1182 public List<String> getChainNames()
1187 protected IProgressIndicator getIProgressIndicator()
1192 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1194 notifyAtomPicked(iatom, strMeasure, null);
1197 public abstract void notifyScriptTermination(String strStatus,
1201 * display a message echoed from the jmol viewer
1205 public abstract void sendConsoleEcho(String strEcho); /*
1206 * { showConsole(true);
1208 * history.append("\n" +
1212 // /End JmolStatusListener
1213 // /////////////////////////////
1217 * status message - usually the response received after a script
1220 public abstract void sendConsoleMessage(String strStatus);
1223 public void setCallbackFunction(String callbackType,
1224 String callbackFunction)
1226 System.err.println("Ignoring set-callback request to associate "
1227 + callbackType + " with function " + callbackFunction);
1232 public void setJalviewColourScheme(ColourSchemeI cs)
1234 colourBySequence = false;
1242 StringBuilder command = new StringBuilder(128);
1243 command.append("select *;color white;");
1244 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1246 for (String resName : residueSet)
1248 char res = resName.length() == 3
1249 ? ResidueProperties.getSingleCharacterCode(resName)
1250 : resName.charAt(0);
1251 Color col = cs.findColour(res, 0, null, null, 0f);
1252 command.append("select " + resName + ";color[" + col.getRed() + ","
1253 + col.getGreen() + "," + col.getBlue() + "];");
1256 evalStateCommand(command.toString());
1260 public void showHelp()
1262 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1266 * open the URL somehow
1270 public abstract void showUrl(String url, String target);
1273 * called when the binding thinks the UI needs to be refreshed after a Jmol
1274 * state change. this could be because structures were loaded, or because an
1275 * error has occured.
1277 public abstract void refreshGUI();
1280 * called to show or hide the associated console window container.
1284 public abstract void showConsole(boolean show);
1287 * @param renderPanel
1289 * - when true will initialise jmol's file IO system (should be false
1290 * in applet context)
1292 * @param documentBase
1294 * @param commandOptions
1296 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1297 String htmlName, URL documentBase, URL codeBase,
1298 String commandOptions)
1300 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1301 codeBase, commandOptions, null, null);
1306 * @param renderPanel
1308 * - when true will initialise jmol's file IO system (should be false
1309 * in applet context)
1311 * @param documentBase
1313 * @param commandOptions
1314 * @param consolePanel
1315 * - panel to contain Jmol console
1316 * @param buttonsToShow
1317 * - buttons to show on the console, in ordr
1319 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1320 String htmlName, URL documentBase, URL codeBase,
1321 String commandOptions, final Container consolePanel,
1322 String buttonsToShow)
1324 if (commandOptions == null)
1326 commandOptions = "";
1328 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1329 (jmolfileio ? new SmarterJmolAdapter() : null),
1330 htmlName + ((Object) this).toString(), documentBase, codeBase,
1331 commandOptions, this);
1333 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1335 console = createJmolConsole(consolePanel, buttonsToShow);
1336 if (consolePanel != null)
1338 consolePanel.addComponentListener(this);
1344 protected abstract JmolAppConsoleInterface createJmolConsole(
1345 Container consolePanel, String buttonsToShow);
1347 protected org.jmol.api.JmolAppConsoleInterface console = null;
1350 public void setBackgroundColour(java.awt.Color col)
1353 viewer.evalStringQuiet("background [" + col.getRed() + ","
1354 + col.getGreen() + "," + col.getBlue() + "];");
1359 public int[] resizeInnerPanel(String data)
1361 // Jalview doesn't honour resize panel requests
1368 protected void closeConsole()
1370 if (console != null)
1374 console.setVisible(false);
1377 } catch (Exception x)
1386 * ComponentListener method
1389 public void componentMoved(ComponentEvent e)
1394 * ComponentListener method
1397 public void componentResized(ComponentEvent e)
1402 * ComponentListener method
1405 public void componentShown(ComponentEvent e)
1411 * ComponentListener method
1414 public void componentHidden(ComponentEvent e)
1420 public void showStructures(AlignViewportI av, boolean refocus)
1422 // TODO show Jmol structure optionally restricted to visible alignment
1423 // and/or selected chains