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.AlignmentViewPanel;
24 import jalview.api.FeatureRenderer;
25 import jalview.api.FeatureSettingsModelI;
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.AppJmol;
32 import jalview.gui.IProgressIndicator;
33 import jalview.io.DataSourceType;
34 import jalview.io.StructureFile;
35 import jalview.schemes.ColourSchemeI;
36 import jalview.schemes.ResidueProperties;
37 import jalview.structure.AtomSpec;
38 import jalview.structure.StructureMappingcommandSet;
39 import jalview.structure.StructureSelectionManager;
40 import jalview.structures.models.AAStructureBindingModel;
41 import jalview.util.MessageManager;
42 import jalview.ws.dbsources.Pdb;
44 import java.awt.Color;
45 import java.awt.Container;
46 import java.awt.event.ComponentEvent;
47 import java.awt.event.ComponentListener;
50 import java.util.ArrayList;
51 import java.util.BitSet;
52 import java.util.Hashtable;
53 import java.util.List;
55 import java.util.StringTokenizer;
56 import java.util.Vector;
58 import org.jmol.adapter.smarter.SmarterJmolAdapter;
59 import org.jmol.api.JmolAppConsoleInterface;
60 import org.jmol.api.JmolSelectionListener;
61 import org.jmol.api.JmolStatusListener;
62 import org.jmol.api.JmolViewer;
63 import org.jmol.c.CBK;
64 import org.jmol.script.T;
65 import org.jmol.viewer.Viewer;
67 public abstract class JalviewJmolBinding extends AAStructureBindingModel
68 implements JmolStatusListener, JmolSelectionListener,
71 private String lastMessage;
73 boolean allChainsSelected = false;
76 * when true, try to search the associated datamodel for sequences that are
77 * associated with any unknown structures in the Jmol view.
79 private boolean associateNewStructs = false;
81 Vector<String> atomsPicked = new Vector<>();
83 private List<String> chainNames;
85 Hashtable<String, String> chainFile;
88 * the default or current model displayed if the model cannot be identified
89 * from the selection message
93 // protected JmolGenericPopup jmolpopup; // not used - remove?
99 StringBuffer resetLastRes = new StringBuffer();
101 public Viewer viewer;
103 public JalviewJmolBinding(StructureSelectionManager ssm,
104 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
105 DataSourceType protocol)
107 super(ssm, pdbentry, sequenceIs, protocol);
109 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
110 * "jalviewJmol", ap.av.applet .getDocumentBase(),
111 * ap.av.applet.getCodeBase(), "", this);
113 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
117 public JalviewJmolBinding(StructureSelectionManager ssm,
118 SequenceI[][] seqs, Viewer theViewer)
123 viewer.setJmolStatusListener(this);
124 viewer.addSelectionListener(this);
128 * construct a title string for the viewer window based on the data jalview
133 public String getViewerTitle()
135 return getViewerTitle("Jmol", true);
139 * prepare the view for a given set of models/chains. chainList contains
140 * strings of the form 'pdbfilename:Chaincode'
143 * list of chains to make visible
145 public void centerViewer(Vector<String> chainList)
147 StringBuilder cmd = new StringBuilder(128);
149 for (String lbl : chainList)
155 mlength = lbl.indexOf(":", p);
156 } while (p < mlength && mlength < (lbl.length() - 2));
157 // TODO: lookup each pdb id and recover proper model number for it.
158 cmd.append(":" + lbl.substring(mlength + 1) + " /"
159 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
161 if (cmd.length() > 0)
163 cmd.setLength(cmd.length() - 4);
165 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
168 public void closeViewer()
170 // remove listeners for all structures in viewer
171 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
175 releaseUIResources();
179 public void colourByChain()
181 colourBySequence = false;
182 // TODO: colour by chain should colour each chain distinctly across all
184 // TODO: http://issues.jalview.org/browse/JAL-628
185 evalStateCommand("select *;color chain");
189 public void colourByCharge()
191 colourBySequence = false;
192 evalStateCommand("select *;color white;select ASP,GLU;color red;"
193 + "select LYS,ARG;color blue;select CYS;color yellow");
197 * superpose the structures associated with sequences in the alignment
198 * according to their corresponding positions.
200 public void superposeStructures(AlignmentI alignment)
202 superposeStructures(alignment, -1, null);
206 * superpose the structures associated with sequences in the alignment
207 * according to their corresponding positions. ded)
209 * @param refStructure
210 * - select which pdb file to use as reference (default is -1 - the
211 * first structure in the alignment)
213 public void superposeStructures(AlignmentI alignment, int refStructure)
215 superposeStructures(alignment, refStructure, null);
219 * superpose the structures associated with sequences in the alignment
220 * according to their corresponding positions. ded)
222 * @param refStructure
223 * - select which pdb file to use as reference (default is -1 - the
224 * first structure in the alignment)
228 public void superposeStructures(AlignmentI alignment, int refStructure,
229 HiddenColumns hiddenCols)
231 superposeStructures(new AlignmentI[] { alignment },
233 { refStructure }, new HiddenColumns[] { hiddenCols });
240 public String superposeStructures(AlignmentI[] _alignment,
241 int[] _refStructure, HiddenColumns[] _hiddenCols)
243 while (viewer.isScriptExecuting())
248 } catch (InterruptedException i)
254 * get the distinct structure files modelled
255 * (a file with multiple chains may map to multiple sequences)
257 String[] files = getStructureFiles();
258 if (!waitForFileLoad(files))
263 StringBuilder selectioncom = new StringBuilder(256);
264 // In principle - nSeconds specifies the speed of animation for each
265 // superposition - but is seems to behave weirdly, so we don't specify it.
266 String nSeconds = " ";
267 if (files.length > 10)
269 nSeconds = " 0.005 ";
273 nSeconds = " " + (2.0 / files.length) + " ";
274 // if (nSeconds).substring(0,5)+" ";
277 // see JAL-1345 - should really automatically turn off the animation for
278 // large numbers of structures, but Jmol doesn't seem to allow that.
280 // union of all aligned positions are collected together.
281 for (int a = 0; a < _alignment.length; a++)
283 int refStructure = _refStructure[a];
284 AlignmentI alignment = _alignment[a];
285 HiddenColumns hiddenCols = _hiddenCols[a];
286 if (a > 0 && selectioncom.length() > 0 && !selectioncom
287 .substring(selectioncom.length() - 1).equals("|"))
289 selectioncom.append("|");
291 // process this alignment
292 if (refStructure >= files.length)
295 "Invalid reference structure value " + refStructure);
300 * 'matched' bit j will be set for visible alignment columns j where
301 * all sequences have a residue with a mapping to the PDB structure
303 BitSet matched = new BitSet();
304 for (int m = 0; m < alignment.getWidth(); m++)
306 if (hiddenCols == null || hiddenCols.isVisible(m))
312 SuperposeData[] structures = new SuperposeData[files.length];
313 for (int f = 0; f < files.length; f++)
315 structures[f] = new SuperposeData(alignment.getWidth());
319 * Calculate the superposable alignment columns ('matched'), and the
320 * corresponding structure residue positions (structures.pdbResNo)
322 int candidateRefStructure = findSuperposableResidues(alignment,
323 matched, structures);
324 if (refStructure < 0)
327 * If no reference structure was specified, pick the first one that has
328 * a mapping in the alignment
330 refStructure = candidateRefStructure;
333 String[] selcom = new String[files.length];
334 int nmatched = matched.cardinality();
337 return (MessageManager.formatMessage("label.insufficient_residues",
342 * generate select statements to select regions to superimpose structures
345 // TODO extract method to construct selection statements
346 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
348 String chainCd = ":" + structures[pdbfnum].chain;
351 StringBuilder molsel = new StringBuilder();
354 int nextColumnMatch = matched.nextSetBit(0);
355 while (nextColumnMatch != -1)
357 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
358 if (lpos != pdbResNo - 1)
364 molsel.append(chainCd);
371 // continuous run - and lpos >-1
374 // at the beginning, so add dash
381 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
384 * add final selection phrase
389 molsel.append(chainCd);
392 if (molsel.length() > 1)
394 selcom[pdbfnum] = molsel.toString();
395 selectioncom.append("((");
396 selectioncom.append(selcom[pdbfnum].substring(1,
397 selcom[pdbfnum].length() - 1));
398 selectioncom.append(" )& ");
399 selectioncom.append(pdbfnum + 1);
400 selectioncom.append(".1)");
401 if (pdbfnum < files.length - 1)
403 selectioncom.append("|");
408 selcom[pdbfnum] = null;
412 StringBuilder command = new StringBuilder(256);
413 // command.append("set spinFps 10;\n");
415 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
417 if (pdbfnum == refStructure || selcom[pdbfnum] == null
418 || selcom[refStructure] == null)
422 command.append("echo ");
423 command.append("\"Superposing (");
424 command.append(structures[pdbfnum].pdbId);
425 command.append(") against reference (");
426 command.append(structures[refStructure].pdbId);
427 command.append(")\";\ncompare " + nSeconds);
429 command.append(Integer.toString(1 + pdbfnum));
430 command.append(".1} {");
431 command.append(Integer.toString(1 + refStructure));
432 // conformation=1 excludes alternate locations for CA (JAL-1757)
434 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
436 // for (int s = 0; s < 2; s++)
438 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
440 command.append(selcom[pdbfnum]);
441 command.append(selcom[refStructure]);
442 command.append(" ROTATE TRANSLATE;\n");
444 if (selectioncom.length() > 0)
446 // TODO is performing selectioncom redundant here? is done later on
447 // System.out.println("Select regions:\n" + selectioncom.toString());
448 evalStateCommand("select *; cartoons off; backbone; select ("
449 + selectioncom.toString() + "); cartoons; ");
450 // selcom.append("; ribbons; ");
451 String cmdString = command.toString();
452 // System.out.println("Superimpose command(s):\n" + cmdString);
454 evalStateCommand(cmdString);
457 if (selectioncom.length() > 0)
458 {// finally, mark all regions that were superposed.
459 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
461 selectioncom.setLength(selectioncom.length() - 1);
463 // System.out.println("Select regions:\n" + selectioncom.toString());
464 evalStateCommand("select *; cartoons off; backbone; select ("
465 + selectioncom.toString() + "); cartoons; ");
466 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
467 // cartoons; center "+selcom.toString());
473 public void evalStateCommand(String command)
476 if (lastCommand == null || !lastCommand.equals(command))
478 viewer.evalStringQuiet(command + "\n");
481 lastCommand = command;
484 Thread colourby = null;
486 * Sends a set of colour commands to the structure viewer
488 * @param colourBySequenceCommands
491 protected void colourBySequence(
492 final StructureMappingcommandSet[] colourBySequenceCommands)
494 if (colourby != null)
496 colourby.interrupt();
499 colourby = new Thread(new Runnable()
504 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
506 for (String cbyseq : cpdbbyseq.commands)
508 executeWhenReady(cbyseq);
523 protected StructureMappingcommandSet[] getColourBySequenceCommands(
524 String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
526 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
527 getSequence(), sr, viewPanel);
533 protected void executeWhenReady(String command)
535 evalStateCommand(command);
538 public void createImage(String file, String type, int quality)
540 System.out.println("JMOL CREATE IMAGE");
544 public String createImage(String fileName, String type,
545 Object textOrBytes, int quality)
547 System.out.println("JMOL CREATE IMAGE");
552 public String eval(String strEval)
554 // System.out.println(strEval);
555 // "# 'eval' is implemented only for the applet.";
559 // End StructureListener
560 // //////////////////////////
563 public float[][] functionXY(String functionName, int x, int y)
569 public float[][][] functionXYZ(String functionName, int nx, int ny,
572 // TODO Auto-generated method stub
576 public Color getColour(int atomIndex, int pdbResNum, String chain,
579 if (getModelNum(pdbfile) < 0)
583 // TODO: verify atomIndex is selecting correct model.
584 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
585 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
586 return new Color(colour);
590 * instruct the Jalview binding to update the pdbentries vector if necessary
591 * prior to matching the jmol view's contents to the list of structure files
592 * Jalview knows about.
594 public abstract void refreshPdbEntries();
596 private int getModelNum(String modelFileName)
598 String[] mfn = getStructureFiles();
603 for (int i = 0; i < mfn.length; i++)
605 if (mfn[i].equalsIgnoreCase(modelFileName))
614 * map between index of model filename returned from getPdbFile and the first
615 * index of models from this file in the viewer. Note - this is not trimmed -
616 * use getPdbFile to get number of unique models.
618 private int _modelFileNameMap[];
621 public synchronized String[] getStructureFiles()
623 List<String> mset = new ArrayList<>();
626 return new String[0];
629 if (modelFileNames == null)
631 int modelCount = viewer.ms.mc;
632 String filePath = null;
633 for (int i = 0; i < modelCount; ++i)
635 filePath = viewer.ms.getModelFileName(i);
636 if (!mset.contains(filePath))
641 modelFileNames = mset.toArray(new String[mset.size()]);
644 return modelFileNames;
648 * map from string to applet
651 public Map<String, Object> getRegistryInfo()
653 // TODO Auto-generated method stub
657 // ///////////////////////////////
658 // JmolStatusListener
660 public void handlePopupMenu(int x, int y)
662 // jmolpopup.show(x, y);
663 // jmolpopup.jpiShow(x, y);
667 * Highlight zero, one or more atoms on the structure
670 public void highlightAtoms(List<AtomSpec> atoms)
674 if (resetLastRes.length() > 0)
676 viewer.evalStringQuiet(resetLastRes.toString());
677 resetLastRes.setLength(0);
679 for (AtomSpec atom : atoms)
681 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
682 atom.getChain(), atom.getPdbFile());
688 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
691 if (modelFileNames == null)
696 // look up file model number for this pdbfile
698 // may need to adjust for URLencoding here - we don't worry about that yet.
699 while (mdlNum < modelFileNames.length
700 && !pdbfile.equals(modelFileNames[mdlNum]))
704 if (mdlNum == modelFileNames.length)
711 StringBuilder cmd = new StringBuilder(64);
712 cmd.append("select " + pdbResNum); // +modelNum
714 resetLastRes.append("select " + pdbResNum); // +modelNum
717 resetLastRes.append(":");
718 if (!chain.equals(" "))
721 resetLastRes.append(chain);
724 cmd.append(" /" + (mdlNum + 1));
725 resetLastRes.append("/" + (mdlNum + 1));
727 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
729 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
730 + " and not hetero; spacefill 0;");
732 cmd.append("spacefill 200;select none");
734 viewer.evalStringQuiet(cmd.toString());
739 boolean debug = true;
741 private void jmolHistory(boolean enable)
743 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
746 public void loadInline(String string)
750 // viewer.loadInline(strModel, isAppend);
752 // construct fake fullPathName and fileName so we can identify the file
754 // Then, construct pass a reader for the string to Jmol.
755 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
756 // fileName, null, reader, false, null, null, 0);
757 viewer.openStringInline(string);
760 protected void mouseOverStructure(int atomIndex, final String strInfo)
763 int alocsep = strInfo.indexOf("^");
764 int mdlSep = strInfo.indexOf("/");
765 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
767 if (chainSeparator == -1)
769 chainSeparator = strInfo.indexOf(".");
770 if (mdlSep > -1 && mdlSep < chainSeparator)
772 chainSeparator1 = chainSeparator;
773 chainSeparator = mdlSep;
776 // handle insertion codes
779 pdbResNum = Integer.parseInt(
780 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
785 pdbResNum = Integer.parseInt(
786 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
790 if (strInfo.indexOf(":") > -1)
792 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
793 strInfo.indexOf("."));
800 String pdbfilename = modelFileNames[frameNo]; // default is first or current
804 if (chainSeparator1 == -1)
806 chainSeparator1 = strInfo.indexOf(".", mdlSep);
808 String mdlId = (chainSeparator1 > -1)
809 ? strInfo.substring(mdlSep + 1, chainSeparator1)
810 : strInfo.substring(mdlSep + 1);
813 // recover PDB filename for the model hovered over.
814 int mnumber = Integer.valueOf(mdlId).intValue() - 1;
815 if (_modelFileNameMap != null)
817 int _mp = _modelFileNameMap.length - 1;
819 while (mnumber < _modelFileNameMap[_mp])
823 pdbfilename = modelFileNames[_mp];
827 if (mnumber >= 0 && mnumber < modelFileNames.length)
829 pdbfilename = modelFileNames[mnumber];
832 if (pdbfilename == null)
834 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
838 } catch (Exception e)
844 * highlight position on alignment(s); if some text is returned,
845 * show this as a second line on the structure hover tooltip
847 String label = getSsm().mouseOverStructure(pdbResNum, chainId,
851 // change comma to pipe separator (newline token for Jmol)
852 label = label.replace(',', '|');
853 StringTokenizer toks = new StringTokenizer(strInfo, " ");
854 StringBuilder sb = new StringBuilder();
855 sb.append("select ").append(String.valueOf(pdbResNum)).append(":")
856 .append(chainId).append("/1");
857 sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ")
858 .append(toks.nextToken());
859 sb.append("|").append(label).append("\"");
860 evalStateCommand(sb.toString());
864 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
866 if (strInfo.equals(lastMessage))
870 lastMessage = strInfo;
873 System.err.println("Ignoring additional hover info: " + data
874 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
876 mouseOverStructure(atomIndex, strInfo);
880 * { if (history != null && strStatus != null &&
881 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
885 public void notifyAtomPicked(int atomIndex, String strInfo,
889 * this implements the toggle label behaviour copied from the original
890 * structure viewer, MCView
894 System.err.println("Ignoring additional pick data string " + strData);
896 int chainSeparator = strInfo.indexOf(":");
898 if (chainSeparator == -1)
900 chainSeparator = strInfo.indexOf(".");
903 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
905 String mdlString = "";
906 if ((p = strInfo.indexOf(":")) > -1)
908 picked += strInfo.substring(p, strInfo.indexOf("."));
911 if ((p = strInfo.indexOf("/")) > -1)
913 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
915 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
919 if (!atomsPicked.contains(picked))
921 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
922 atomsPicked.addElement(picked);
926 viewer.evalString("select " + picked + ";label off");
927 atomsPicked.removeElement(picked);
930 // TODO: in application this happens
932 // if (scriptWindow != null)
934 // scriptWindow.sendConsoleMessage(strInfo);
935 // scriptWindow.sendConsoleMessage("\n");
941 public void notifyCallback(CBK type, Object[] data)
948 notifyFileLoaded((String) data[1], (String) data[2],
949 (String) data[3], (String) data[4],
950 ((Integer) data[5]).intValue());
954 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
956 // also highlight in alignment
957 // deliberate fall through
959 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
963 notifyScriptTermination((String) data[2],
964 ((Integer) data[3]).intValue());
967 sendConsoleEcho((String) data[1]);
971 (data == null) ? ((String) null) : (String) data[1]);
974 // System.err.println("Ignoring error callback.");
985 "Unhandled callback " + type + " " + data[1].toString());
988 } catch (Exception e)
990 System.err.println("Squashed Jmol callback handler error:");
996 public boolean notifyEnabled(CBK callbackPick)
998 switch (callbackPick)
1014 // incremented every time a load notification is successfully handled -
1015 // lightweight mechanism for other threads to detect when they can start
1016 // referrring to new structures.
1017 private long loadNotifiesHandled = 0;
1019 public long getLoadNotifiesHandled()
1021 return loadNotifiesHandled;
1024 public void notifyFileLoaded(String fullPathName, String fileName2,
1025 String modelName, String errorMsg, int modelParts)
1027 if (errorMsg != null)
1029 fileLoadingError = errorMsg;
1033 // TODO: deal sensibly with models loaded inLine:
1034 // modelName will be null, as will fullPathName.
1036 // the rest of this routine ignores the arguments, and simply interrogates
1037 // the Jmol view to find out what structures it contains, and adds them to
1038 // the structure selection manager.
1039 fileLoadingError = null;
1040 String[] oldmodels = modelFileNames;
1041 modelFileNames = null;
1042 chainNames = new ArrayList<>();
1043 chainFile = new Hashtable<>();
1044 boolean notifyLoaded = false;
1045 String[] modelfilenames = getStructureFiles();
1046 // first check if we've lost any structures
1047 if (oldmodels != null && oldmodels.length > 0)
1050 for (int i = 0; i < oldmodels.length; i++)
1052 for (int n = 0; n < modelfilenames.length; n++)
1054 if (modelfilenames[n] == oldmodels[i])
1056 oldmodels[i] = null;
1060 if (oldmodels[i] != null)
1067 String[] oldmfn = new String[oldm];
1069 for (int i = 0; i < oldmodels.length; i++)
1071 if (oldmodels[i] != null)
1073 oldmfn[oldm++] = oldmodels[i];
1076 // deregister the Jmol instance for these structures - we'll add
1077 // ourselves again at the end for the current structure set.
1078 getSsm().removeStructureViewerListener(this, oldmfn);
1081 refreshPdbEntries();
1082 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1084 String fileName = modelfilenames[modelnum];
1085 boolean foundEntry = false;
1086 StructureFile pdb = null;
1087 String pdbfile = null;
1088 // model was probably loaded inline - so check the pdb file hashcode
1091 // calculate essential attributes for the pdb data imported inline.
1092 // prolly need to resolve modelnumber properly - for now just use our
1094 pdbfile = viewer.getData(
1095 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1097 // search pdbentries and sequences to find correct pdbentry for this
1099 for (int pe = 0; pe < getPdbCount(); pe++)
1101 boolean matches = false;
1102 addSequence(pe, getSequence()[pe]);
1103 if (fileName == null)
1106 // see JAL-623 - need method of matching pasted data up
1108 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1109 pdbfile, DataSourceType.PASTE,
1110 getIProgressIndicator());
1111 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1118 File fl = new File(getPdbEntry(pe).getFile());
1119 matches = fl.equals(new File(fileName));
1123 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1126 // to be tested. See mantis bug
1127 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1128 DataSourceType protocol = DataSourceType.URL;
1133 protocol = DataSourceType.FILE;
1135 } catch (Exception e)
1140 // Explicitly map to the filename used by Jmol ;
1141 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1142 fileName, protocol, getIProgressIndicator());
1143 // pdbentry[pe].getFile(), protocol);
1149 // add an entry for every chain in the model
1150 for (int i = 0; i < pdb.getChains().size(); i++)
1152 String chid = new String(
1153 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1154 chainFile.put(chid, fileName);
1155 chainNames.add(chid);
1157 notifyLoaded = true;
1161 if (!foundEntry && associateNewStructs)
1163 // this is a foreign pdb file that jalview doesn't know about - add
1164 // it to the dataset and try to find a home - either on a matching
1165 // sequence or as a new sequence.
1166 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1168 // parse pdb file into a chain, etc.
1169 // locate best match for pdb in associated views and add mapping to
1171 // if properly registered then
1172 notifyLoaded = true;
1177 // so finally, update the jmol bits and pieces
1178 // if (jmolpopup != null)
1180 // // potential for deadlock here:
1181 // // jmolpopup.updateComputedMenus();
1183 if (!isLoadingFromArchive())
1185 viewer.evalStringQuiet(
1186 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1188 // register ourselves as a listener and notify the gui that it needs to
1190 getSsm().addStructureViewerListener(this);
1193 FeatureRenderer fr = getFeatureRenderer(null);
1196 FeatureSettingsModelI colours = new Pdb().getFeatureColourScheme();
1197 ((AppJmol) getViewer()).getAlignmentPanel().av
1198 .applyFeaturesStyle(colours);
1201 loadNotifiesHandled++;
1203 setLoadingFromArchive(false);
1207 public List<String> getChainNames()
1212 protected IProgressIndicator getIProgressIndicator()
1217 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1219 notifyAtomPicked(iatom, strMeasure, null);
1222 public abstract void notifyScriptTermination(String strStatus,
1226 * display a message echoed from the jmol viewer
1230 public abstract void sendConsoleEcho(String strEcho); /*
1231 * { showConsole(true);
1233 * history.append("\n" +
1237 // /End JmolStatusListener
1238 // /////////////////////////////
1242 * status message - usually the response received after a script
1245 public abstract void sendConsoleMessage(String strStatus);
1248 public void setCallbackFunction(String callbackType,
1249 String callbackFunction)
1251 System.err.println("Ignoring set-callback request to associate "
1252 + callbackType + " with function " + callbackFunction);
1257 public void setJalviewColourScheme(ColourSchemeI cs)
1259 colourBySequence = false;
1267 StringBuilder command = new StringBuilder(128);
1268 command.append("select *;color white;");
1269 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1271 for (String resName : residueSet)
1273 char res = resName.length() == 3
1274 ? ResidueProperties.getSingleCharacterCode(resName)
1275 : resName.charAt(0);
1276 Color col = cs.findColour(res, 0, null, null, 0f);
1277 command.append("select " + resName + ";color[" + col.getRed() + ","
1278 + col.getGreen() + "," + col.getBlue() + "];");
1281 evalStateCommand(command.toString());
1285 public void showHelp()
1287 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1291 * open the URL somehow
1295 public abstract void showUrl(String url, String target);
1298 * called when the binding thinks the UI needs to be refreshed after a Jmol
1299 * state change. this could be because structures were loaded, or because an
1300 * error has occured.
1302 public abstract void refreshGUI();
1305 * called to show or hide the associated console window container.
1309 public abstract void showConsole(boolean show);
1312 * @param renderPanel
1314 * - when true will initialise jmol's file IO system (should be false
1315 * in applet context)
1317 * @param documentBase
1319 * @param commandOptions
1321 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1322 String htmlName, URL documentBase, URL codeBase,
1323 String commandOptions)
1325 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1326 codeBase, commandOptions, null, null);
1331 * @param renderPanel
1333 * - when true will initialise jmol's file IO system (should be false
1334 * in applet context)
1336 * @param documentBase
1338 * @param commandOptions
1339 * @param consolePanel
1340 * - panel to contain Jmol console
1341 * @param buttonsToShow
1342 * - buttons to show on the console, in ordr
1344 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1345 String htmlName, URL documentBase, URL codeBase,
1346 String commandOptions, final Container consolePanel,
1347 String buttonsToShow)
1349 if (commandOptions == null)
1351 commandOptions = "";
1353 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1354 (jmolfileio ? new SmarterJmolAdapter() : null),
1355 htmlName + ((Object) this).toString(), documentBase, codeBase,
1356 commandOptions, this);
1358 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1360 console = createJmolConsole(consolePanel, buttonsToShow);
1361 if (consolePanel != null)
1363 consolePanel.addComponentListener(this);
1369 protected abstract JmolAppConsoleInterface createJmolConsole(
1370 Container consolePanel, String buttonsToShow);
1372 protected org.jmol.api.JmolAppConsoleInterface console = null;
1375 public void setBackgroundColour(java.awt.Color col)
1378 viewer.evalStringQuiet("background [" + col.getRed() + ","
1379 + col.getGreen() + "," + col.getBlue() + "];");
1384 public int[] resizeInnerPanel(String data)
1386 // Jalview doesn't honour resize panel requests
1393 protected void closeConsole()
1395 if (console != null)
1399 console.setVisible(false);
1402 } catch (Exception x)
1411 * ComponentListener method
1414 public void componentMoved(ComponentEvent e)
1419 * ComponentListener method
1422 public void componentResized(ComponentEvent e)
1427 * ComponentListener method
1430 public void componentShown(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentHidden(ComponentEvent e)