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.SequenceRenderer;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.ColumnSelection;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.SequenceI;
30 import jalview.io.AppletFormatAdapter;
31 import jalview.schemes.ColourSchemeI;
32 import jalview.schemes.ResidueProperties;
33 import jalview.structure.AtomSpec;
34 import jalview.structure.StructureMappingcommandSet;
35 import jalview.structure.StructureSelectionManager;
36 import jalview.structures.models.AAStructureBindingModel;
38 import java.awt.Color;
39 import java.awt.Container;
40 import java.awt.event.ComponentEvent;
41 import java.awt.event.ComponentListener;
44 import java.security.AccessControlException;
45 import java.util.Hashtable;
46 import java.util.List;
48 import java.util.Vector;
50 import javajs.awt.Dimension;
52 import org.jmol.adapter.smarter.SmarterJmolAdapter;
53 import org.jmol.api.JmolAppConsoleInterface;
54 import org.jmol.api.JmolSelectionListener;
55 import org.jmol.api.JmolStatusListener;
56 import org.jmol.api.JmolViewer;
57 import org.jmol.c.CBK;
58 import org.jmol.script.T;
59 import org.jmol.viewer.JC;
60 import org.jmol.viewer.Viewer;
62 public abstract class JalviewJmolBinding extends AAStructureBindingModel
63 implements JmolStatusListener, JmolSelectionListener,
66 boolean allChainsSelected = false;
69 * when true, try to search the associated datamodel for sequences that are
70 * associated with any unknown structures in the Jmol view.
72 private boolean associateNewStructs = false;
74 Vector<String> atomsPicked = new Vector<String>();
76 public Vector<String> chainNames;
78 Hashtable<String, String> chainFile;
80 public String fileLoadingError;
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?
97 * current set of model filenames loaded in the Jmol instance
99 String[] modelFileNames = null;
101 StringBuffer resetLastRes = new StringBuffer();
103 public Viewer viewer;
105 public JalviewJmolBinding(StructureSelectionManager ssm,
106 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
109 super(ssm, pdbentry, sequenceIs, chains, protocol);
111 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
112 * "jalviewJmol", ap.av.applet .getDocumentBase(),
113 * ap.av.applet.getCodeBase(), "", this);
115 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
119 public JalviewJmolBinding(StructureSelectionManager ssm,
120 SequenceI[][] seqs, Viewer theViewer)
125 viewer.setJmolStatusListener(this);
126 viewer.addSelectionListener(this);
130 * construct a title string for the viewer window based on the data jalview
135 public String getViewerTitle()
137 return getViewerTitle("Jmol", true);
141 * prepare the view for a given set of models/chains. chainList contains
142 * strings of the form 'pdbfilename:Chaincode'
145 * list of chains to make visible
147 public void centerViewer(Vector<String> chainList)
149 StringBuilder cmd = new StringBuilder(128);
151 for (String lbl : chainList)
157 mlength = lbl.indexOf(":", p);
158 } while (p < mlength && mlength < (lbl.length() - 2));
159 // TODO: lookup each pdb id and recover proper model number for it.
160 cmd.append(":" + lbl.substring(mlength + 1) + " /"
161 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
163 if (cmd.length() > 0)
165 cmd.setLength(cmd.length() - 4);
167 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
170 public void closeViewer()
172 viewer.acm.setModeMouse(JC.MOUSE_NONE);
173 // remove listeners for all structures in viewer
174 getSsm().removeStructureViewerListener(this, this.getPdbFile());
175 // and shut down jmol
176 viewer.evalStringQuiet("zap");
177 viewer.setJmolStatusListener(null);
180 releaseUIResources();
183 public void colourByChain()
185 colourBySequence = false;
186 // TODO: colour by chain should colour each chain distinctly across all
188 // TODO: http://issues.jalview.org/browse/JAL-628
189 evalStateCommand("select *;color chain");
192 public void colourByCharge()
194 colourBySequence = false;
195 evalStateCommand("select *;color white;select ASP,GLU;color red;"
196 + "select LYS,ARG;color blue;select CYS;color yellow");
200 * superpose the structures associated with sequences in the alignment
201 * according to their corresponding positions.
203 public void superposeStructures(AlignmentI alignment)
205 superposeStructures(alignment, -1, null);
209 * superpose the structures associated with sequences in the alignment
210 * according to their corresponding positions. ded)
212 * @param refStructure
213 * - select which pdb file to use as reference (default is -1 - the
214 * first structure in the alignment)
216 public void superposeStructures(AlignmentI alignment, int refStructure)
218 superposeStructures(alignment, refStructure, null);
222 * superpose the structures associated with sequences in the alignment
223 * according to their corresponding positions. ded)
225 * @param refStructure
226 * - select which pdb file to use as reference (default is -1 - the
227 * first structure in the alignment)
231 public void superposeStructures(AlignmentI alignment, int refStructure,
232 ColumnSelection hiddenCols)
234 superposeStructures(new AlignmentI[] { alignment },
235 new int[] { refStructure },
236 new ColumnSelection[] { hiddenCols });
240 * Construct and send a command to align structures against a reference
241 * structure, based on one or more sequence alignments
244 * an array of alignments to process
245 * @param _refStructure
246 * an array of corresponding reference structures (index into pdb
247 * file array); if a negative value is passed, the first PDB file
248 * mapped to an alignment sequence is used as the reference for
251 * an array of corresponding hidden columns for each alignment
253 public void superposeStructures(AlignmentI[] _alignment,
254 int[] _refStructure, ColumnSelection[] _hiddenCols)
256 while (viewer.isScriptExecuting())
261 } catch (InterruptedException i)
266 String[] files = getPdbFile();
267 if (!waitForFileLoad(files))
272 StringBuilder selectioncom = new StringBuilder(256);
273 // In principle - nSeconds specifies the speed of animation for each
274 // superposition - but is seems to behave weirdly, so we don't specify it.
275 String nSeconds = " ";
276 if (files.length > 10)
278 nSeconds = " 0.005 ";
282 nSeconds = " " + (2.0 / files.length) + " ";
283 // if (nSeconds).substring(0,5)+" ";
285 // see JAL-1345 - should really automatically turn off the animation for
286 // large numbers of structures, but Jmol doesn't seem to allow that.
288 // union of all aligned positions are collected together.
289 for (int a = 0; a < _alignment.length; a++)
291 int refStructure = _refStructure[a];
292 AlignmentI alignment = _alignment[a];
293 ColumnSelection hiddenCols = _hiddenCols[a];
295 && selectioncom.length() > 0
296 && !selectioncom.substring(selectioncom.length() - 1).equals(
299 selectioncom.append("|");
301 // process this alignment
302 if (refStructure >= files.length)
304 System.err.println("Invalid reference structure value "
310 * 'matched' array will hold 'true' for visible alignment columns where
311 * all sequences have a residue with a mapping to the PDB structure
313 boolean matched[] = new boolean[alignment.getWidth()];
314 for (int m = 0; m < matched.length; m++)
316 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
319 SuperposeData[] structures = new SuperposeData[files.length];
320 for (int f = 0; f < files.length; f++)
322 structures[f] = new SuperposeData(alignment.getWidth());
326 * Calculate the superposable alignment columns ('matched'), and the
327 * corresponding structure residue positions (structures.pdbResNo)
329 int candidateRefStructure = findSuperposableResidues(alignment,
330 matched, structures);
331 if (refStructure < 0)
334 * If no reference structure was specified, pick the first one that has
335 * a mapping in the alignment
337 refStructure = candidateRefStructure;
340 String[] selcom = new String[files.length];
342 for (boolean b : matched)
351 // TODO: bail out here because superposition illdefined?
355 * generate select statements to select regions to superimpose structures
358 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
360 String chainCd = ":" + structures[pdbfnum].chain;
363 StringBuilder molsel = new StringBuilder();
365 for (int r = 0; r < matched.length; r++)
369 int pdbResNo = structures[pdbfnum].pdbResNo[r];
370 if (lpos != pdbResNo - 1)
376 molsel.append(chainCd);
383 // continuous run - and lpos >-1
386 // at the beginning, so add dash
396 * add final selection phrase
401 molsel.append(chainCd);
404 if (molsel.length() > 1)
406 selcom[pdbfnum] = molsel.toString();
407 selectioncom.append("((");
408 selectioncom.append(selcom[pdbfnum].substring(1,
409 selcom[pdbfnum].length() - 1));
410 selectioncom.append(" )& ");
411 selectioncom.append(pdbfnum + 1);
412 selectioncom.append(".1)");
413 if (pdbfnum < files.length - 1)
415 selectioncom.append("|");
420 selcom[pdbfnum] = null;
424 StringBuilder command = new StringBuilder(256);
425 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
427 if (pdbfnum == refStructure || selcom[pdbfnum] == null
428 || selcom[refStructure] == null)
432 command.append("echo ");
433 command.append("\"Superposing (");
434 command.append(structures[pdbfnum].pdbId);
435 command.append(") against reference (");
436 command.append(structures[refStructure].pdbId);
437 command.append(")\";\ncompare " + nSeconds);
439 command.append(Integer.toString(1 + pdbfnum));
440 command.append(".1} {");
441 command.append(Integer.toString(1 + refStructure));
442 // conformation=1 excludes alternate locations for CA (JAL-1757)
443 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
445 // for (int s = 0; s < 2; s++)
447 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
449 command.append(selcom[pdbfnum]);
450 command.append(selcom[refStructure]);
451 command.append(" ROTATE TRANSLATE;\n");
453 if (selectioncom.length() > 0)
455 System.out.println("Select regions:\n" + selectioncom.toString());
456 evalStateCommand("select *; cartoons off; backbone; select ("
457 + selectioncom.toString() + "); cartoons; ");
458 // selcom.append("; ribbons; ");
459 String cmdString = command.toString();
460 System.out.println("Superimpose command(s):\n" + cmdString);
462 evalStateCommand(cmdString);
465 if (selectioncom.length() > 0)
466 {// finally, mark all regions that were superposed.
467 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
469 selectioncom.setLength(selectioncom.length() - 1);
471 System.out.println("Select regions:\n" + selectioncom.toString());
472 evalStateCommand("select *; cartoons off; backbone; select ("
473 + selectioncom.toString() + "); cartoons; ");
474 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
478 public void evalStateCommand(String command)
481 if (lastCommand == null || !lastCommand.equals(command))
483 viewer.evalStringQuiet(command + "\n");
486 lastCommand = command;
490 * colour any structures associated with sequences in the given alignment
491 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
492 * if colourBySequence is enabled.
494 public void colourBySequence(AlignmentViewPanel alignmentv)
496 boolean showFeatures = alignmentv.getAlignViewport()
497 .isShowSequenceFeatures();
498 if (!colourBySequence || !isLoadingFinished())
502 if (getSsm() == null)
506 String[] files = getPdbFile();
508 SequenceRenderer sr = getSequenceRenderer(alignmentv);
510 FeatureRenderer fr = null;
513 fr = getFeatureRenderer(alignmentv);
515 AlignmentI alignment = alignmentv.getAlignment();
517 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
518 files, sr, fr, alignment))
520 for (String cbyseq : cpdbbyseq.commands)
522 executeWhenReady(cbyseq);
534 protected StructureMappingcommandSet[] getColourBySequenceCommands(
535 String[] files, SequenceRenderer sr, FeatureRenderer fr,
536 AlignmentI alignment)
538 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
539 getSequence(), sr, fr, alignment);
545 protected void executeWhenReady(String command)
547 evalStateCommand(command);
550 public void createImage(String file, String type, int quality)
552 System.out.println("JMOL CREATE IMAGE");
556 public String createImage(String fileName, String type,
557 Object textOrBytes, int quality)
559 System.out.println("JMOL CREATE IMAGE");
564 public String eval(String strEval)
566 // System.out.println(strEval);
567 // "# 'eval' is implemented only for the applet.";
571 // End StructureListener
572 // //////////////////////////
575 public float[][] functionXY(String functionName, int x, int y)
581 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
583 // TODO Auto-generated method stub
587 public Color getColour(int atomIndex, int pdbResNum, String chain,
590 if (getModelNum(pdbfile) < 0)
594 // TODO: verify atomIndex is selecting correct model.
595 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
596 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
597 return new Color(colour);
601 * returns the current featureRenderer that should be used to colour the
608 public abstract FeatureRenderer getFeatureRenderer(
609 AlignmentViewPanel alignment);
612 * instruct the Jalview binding to update the pdbentries vector if necessary
613 * prior to matching the jmol view's contents to the list of structure files
614 * Jalview knows about.
616 public abstract void refreshPdbEntries();
618 private int getModelNum(String modelFileName)
620 String[] mfn = getPdbFile();
625 for (int i = 0; i < mfn.length; i++)
627 if (mfn[i].equalsIgnoreCase(modelFileName))
636 * map between index of model filename returned from getPdbFile and the first
637 * index of models from this file in the viewer. Note - this is not trimmed -
638 * use getPdbFile to get number of unique models.
640 private int _modelFileNameMap[];
642 // ////////////////////////////////
643 // /StructureListener
645 public synchronized String[] getPdbFile()
649 return new String[0];
651 if (modelFileNames == null)
653 String mset[] = new String[viewer.ms.mc];
654 _modelFileNameMap = new int[mset.length];
655 String m = viewer.ms.getModelFileName(0);
661 mset[0] = new File(m).getAbsolutePath();
662 } catch (AccessControlException x)
664 // usually not allowed to do this in applet
666 .println("jmolBinding: Using local file string from Jmol: "
669 if (mset[0].indexOf("/file:") != -1)
671 // applet path with docroot - discard as format won't match pdbfile
674 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
677 for (int i = 1; i < mset.length; i++)
679 m = viewer.ms.getModelFileName(i);
685 mset[j] = new File(m).getAbsolutePath();
686 } catch (AccessControlException x)
688 // usually not allowed to do this in applet, so keep raw handle
689 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
692 _modelFileNameMap[j] = i; // record the model index for the filename
693 // skip any additional models in the same file (NMR structures)
694 if ((mset[j] == null ? mset[j] != mset[j - 1]
695 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
700 modelFileNames = new String[j];
701 System.arraycopy(mset, 0, modelFileNames, 0, j);
703 return modelFileNames;
707 * map from string to applet
710 public Map<String, Object> getRegistryInfo()
712 // TODO Auto-generated method stub
717 * returns the current sequenceRenderer that should be used to colour the
724 public abstract SequenceRenderer getSequenceRenderer(
725 AlignmentViewPanel alignment);
727 // ///////////////////////////////
728 // JmolStatusListener
730 public void handlePopupMenu(int x, int y)
732 // jmolpopup.show(x, y);
733 // jmolpopup.jpiShow(x, y);
737 * Highlight zero, one or more atoms on the structure
740 public void highlightAtoms(List<AtomSpec> atoms)
744 if (resetLastRes.length() > 0)
746 viewer.evalStringQuiet(resetLastRes.toString());
747 resetLastRes.setLength(0);
749 for (AtomSpec atom : atoms)
751 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
752 atom.getChain(), atom.getPdbFile());
758 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
761 if (modelFileNames == null)
766 // look up file model number for this pdbfile
768 // may need to adjust for URLencoding here - we don't worry about that yet.
769 while (mdlNum < modelFileNames.length
770 && !pdbfile.equals(modelFileNames[mdlNum]))
774 if (mdlNum == modelFileNames.length)
781 StringBuilder cmd = new StringBuilder(64);
782 cmd.append("select " + pdbResNum); // +modelNum
784 resetLastRes.append("select " + pdbResNum); // +modelNum
787 resetLastRes.append(":");
788 if (!chain.equals(" "))
791 resetLastRes.append(chain);
794 cmd.append(" /" + (mdlNum + 1));
795 resetLastRes.append("/" + (mdlNum + 1));
797 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
799 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
800 + " and not hetero; spacefill 0;");
802 cmd.append("spacefill 200;select none");
804 viewer.evalStringQuiet(cmd.toString());
809 boolean debug = true;
811 private void jmolHistory(boolean enable)
813 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
816 public void loadInline(String string)
820 // viewer.loadInline(strModel, isAppend);
822 // construct fake fullPathName and fileName so we can identify the file
824 // Then, construct pass a reader for the string to Jmol.
825 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
826 // fileName, null, reader, false, null, null, 0);
827 viewer.openStringInline(string);
830 public void mouseOverStructure(int atomIndex, String strInfo)
833 int alocsep = strInfo.indexOf("^");
834 int mdlSep = strInfo.indexOf("/");
835 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
837 if (chainSeparator == -1)
839 chainSeparator = strInfo.indexOf(".");
840 if (mdlSep > -1 && mdlSep < chainSeparator)
842 chainSeparator1 = chainSeparator;
843 chainSeparator = mdlSep;
846 // handle insertion codes
849 pdbResNum = Integer.parseInt(strInfo.substring(
850 strInfo.indexOf("]") + 1, alocsep));
855 pdbResNum = Integer.parseInt(strInfo.substring(
856 strInfo.indexOf("]") + 1, chainSeparator));
860 if (strInfo.indexOf(":") > -1)
862 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
863 strInfo.indexOf("."));
870 String pdbfilename = modelFileNames[frameNo]; // default is first or current
874 if (chainSeparator1 == -1)
876 chainSeparator1 = strInfo.indexOf(".", mdlSep);
878 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
879 chainSeparator1) : strInfo.substring(mdlSep + 1);
882 // recover PDB filename for the model hovered over.
883 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
885 while (mnumber < _modelFileNameMap[_mp])
889 pdbfilename = modelFileNames[_mp];
890 if (pdbfilename == null)
892 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
896 } catch (Exception e)
901 if (lastMessage == null || !lastMessage.equals(strInfo))
903 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
906 lastMessage = strInfo;
909 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
913 System.err.println("Ignoring additional hover info: " + data
914 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
916 mouseOverStructure(atomIndex, strInfo);
920 * { if (history != null && strStatus != null &&
921 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
925 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
928 * this implements the toggle label behaviour copied from the original
929 * structure viewer, MCView
933 System.err.println("Ignoring additional pick data string " + strData);
935 int chainSeparator = strInfo.indexOf(":");
937 if (chainSeparator == -1)
939 chainSeparator = strInfo.indexOf(".");
942 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
944 String mdlString = "";
945 if ((p = strInfo.indexOf(":")) > -1)
947 picked += strInfo.substring(p, strInfo.indexOf("."));
950 if ((p = strInfo.indexOf("/")) > -1)
952 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
954 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
958 if (!atomsPicked.contains(picked))
960 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
961 atomsPicked.addElement(picked);
965 viewer.evalString("select " + picked + ";label off");
966 atomsPicked.removeElement(picked);
969 // TODO: in application this happens
971 // if (scriptWindow != null)
973 // scriptWindow.sendConsoleMessage(strInfo);
974 // scriptWindow.sendConsoleMessage("\n");
980 public void notifyCallback(CBK type, Object[] data)
987 notifyFileLoaded((String) data[1], (String) data[2],
988 (String) data[3], (String) data[4],
989 ((Integer) data[5]).intValue());
993 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
995 // also highlight in alignment
997 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1001 notifyScriptTermination((String) data[2],
1002 ((Integer) data[3]).intValue());
1005 sendConsoleEcho((String) data[1]);
1008 sendConsoleMessage((data == null) ? ((String) null)
1009 : (String) data[1]);
1012 // System.err.println("Ignoring error callback.");
1022 System.err.println("Unhandled callback " + type + " "
1023 + data[1].toString());
1026 } catch (Exception e)
1028 System.err.println("Squashed Jmol callback handler error:");
1029 e.printStackTrace();
1034 public boolean notifyEnabled(CBK callbackPick)
1036 switch (callbackPick)
1052 // incremented every time a load notification is successfully handled -
1053 // lightweight mechanism for other threads to detect when they can start
1054 // referrring to new structures.
1055 private long loadNotifiesHandled = 0;
1057 public long getLoadNotifiesHandled()
1059 return loadNotifiesHandled;
1062 public void notifyFileLoaded(String fullPathName, String fileName2,
1063 String modelName, String errorMsg, int modelParts)
1065 if (errorMsg != null)
1067 fileLoadingError = errorMsg;
1071 // TODO: deal sensibly with models loaded inLine:
1072 // modelName will be null, as will fullPathName.
1074 // the rest of this routine ignores the arguments, and simply interrogates
1075 // the Jmol view to find out what structures it contains, and adds them to
1076 // the structure selection manager.
1077 fileLoadingError = null;
1078 String[] oldmodels = modelFileNames;
1079 modelFileNames = null;
1080 chainNames = new Vector<String>();
1081 chainFile = new Hashtable<String, String>();
1082 boolean notifyLoaded = false;
1083 String[] modelfilenames = getPdbFile();
1084 // first check if we've lost any structures
1085 if (oldmodels != null && oldmodels.length > 0)
1088 for (int i = 0; i < oldmodels.length; i++)
1090 for (int n = 0; n < modelfilenames.length; n++)
1092 if (modelfilenames[n] == oldmodels[i])
1094 oldmodels[i] = null;
1098 if (oldmodels[i] != null)
1105 String[] oldmfn = new String[oldm];
1107 for (int i = 0; i < oldmodels.length; i++)
1109 if (oldmodels[i] != null)
1111 oldmfn[oldm++] = oldmodels[i];
1114 // deregister the Jmol instance for these structures - we'll add
1115 // ourselves again at the end for the current structure set.
1116 getSsm().removeStructureViewerListener(this, oldmfn);
1119 refreshPdbEntries();
1120 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1122 String fileName = modelfilenames[modelnum];
1123 boolean foundEntry = false;
1124 MCview.PDBfile pdb = null;
1125 String pdbfile = null;
1126 // model was probably loaded inline - so check the pdb file hashcode
1129 // calculate essential attributes for the pdb data imported inline.
1130 // prolly need to resolve modelnumber properly - for now just use our
1132 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1135 // search pdbentries and sequences to find correct pdbentry for this
1137 for (int pe = 0; pe < getPdbCount(); pe++)
1139 boolean matches = false;
1140 if (fileName == null)
1143 // see JAL-623 - need method of matching pasted data up
1145 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1146 pdbfile, AppletFormatAdapter.PASTE);
1147 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1154 File fl = new File(getPdbEntry(pe).getFile());
1155 matches = fl.equals(new File(fileName));
1159 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1162 // to be tested. See mantis bug
1163 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1164 String protocol = AppletFormatAdapter.URL;
1169 protocol = AppletFormatAdapter.FILE;
1171 } catch (Exception e)
1176 // Explicitly map to the filename used by Jmol ;
1177 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1178 fileName, protocol);
1179 // pdbentry[pe].getFile(), protocol);
1185 // add an entry for every chain in the model
1186 for (int i = 0; i < pdb.chains.size(); i++)
1188 String chid = new String(pdb.id + ":"
1189 + pdb.chains.elementAt(i).id);
1190 chainFile.put(chid, fileName);
1191 chainNames.addElement(chid);
1193 notifyLoaded = true;
1197 if (!foundEntry && associateNewStructs)
1199 // this is a foreign pdb file that jalview doesn't know about - add
1200 // it to the dataset and try to find a home - either on a matching
1201 // sequence or as a new sequence.
1202 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1204 // parse pdb file into a chain, etc.
1205 // locate best match for pdb in associated views and add mapping to
1207 // if properly registered then
1208 notifyLoaded = true;
1213 // so finally, update the jmol bits and pieces
1214 // if (jmolpopup != null)
1216 // // potential for deadlock here:
1217 // // jmolpopup.updateComputedMenus();
1219 if (!isLoadingFromArchive())
1221 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1223 // register ourselves as a listener and notify the gui that it needs to
1225 getSsm().addStructureViewerListener(this);
1228 FeatureRenderer fr = getFeatureRenderer(null);
1234 loadNotifiesHandled++;
1236 setLoadingFromArchive(false);
1239 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1241 notifyAtomPicked(iatom, strMeasure, null);
1244 public abstract void notifyScriptTermination(String strStatus,
1248 * display a message echoed from the jmol viewer
1252 public abstract void sendConsoleEcho(String strEcho); /*
1253 * { showConsole(true);
1255 * history.append("\n" +
1259 // /End JmolStatusListener
1260 // /////////////////////////////
1264 * status message - usually the response received after a script
1267 public abstract void sendConsoleMessage(String strStatus);
1270 public void setCallbackFunction(String callbackType,
1271 String callbackFunction)
1273 System.err.println("Ignoring set-callback request to associate "
1274 + callbackType + " with function " + callbackFunction);
1278 public void setJalviewColourScheme(ColourSchemeI cs)
1280 colourBySequence = false;
1288 StringBuilder command = new StringBuilder(128);
1289 command.append("select *;color white;");
1290 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1292 for (String res : residueSet)
1294 Color col = cs.findColour(res.charAt(0));
1295 command.append("select " + res + ";color[" + col.getRed() + ","
1296 + col.getGreen() + "," + col.getBlue() + "];");
1299 evalStateCommand(command.toString());
1303 public void showHelp()
1305 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1309 * open the URL somehow
1313 public abstract void showUrl(String url, String target);
1316 * called when the binding thinks the UI needs to be refreshed after a Jmol
1317 * state change. this could be because structures were loaded, or because an
1318 * error has occured.
1320 public abstract void refreshGUI();
1323 * called to show or hide the associated console window container.
1327 public abstract void showConsole(boolean show);
1330 * @param renderPanel
1332 * - when true will initialise jmol's file IO system (should be false
1333 * in applet context)
1335 * @param documentBase
1337 * @param commandOptions
1339 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1340 String htmlName, URL documentBase, URL codeBase,
1341 String commandOptions)
1343 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1344 codeBase, commandOptions, null, null);
1349 * @param renderPanel
1351 * - when true will initialise jmol's file IO system (should be false
1352 * in applet context)
1354 * @param documentBase
1356 * @param commandOptions
1357 * @param consolePanel
1358 * - panel to contain Jmol console
1359 * @param buttonsToShow
1360 * - buttons to show on the console, in ordr
1362 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1363 String htmlName, URL documentBase, URL codeBase,
1364 String commandOptions, final Container consolePanel,
1365 String buttonsToShow)
1367 if (commandOptions == null)
1369 commandOptions = "";
1371 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1372 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1373 + ((Object) this).toString(), documentBase, codeBase,
1374 commandOptions, this);
1376 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1378 console = createJmolConsole(consolePanel, buttonsToShow);
1379 if (consolePanel != null)
1381 consolePanel.addComponentListener(this);
1387 protected abstract JmolAppConsoleInterface createJmolConsole(
1388 Container consolePanel, String buttonsToShow);
1390 protected org.jmol.api.JmolAppConsoleInterface console = null;
1392 public void setBackgroundColour(java.awt.Color col)
1395 viewer.evalStringQuiet("background [" + col.getRed() + ","
1396 + col.getGreen() + "," + col.getBlue() + "];");
1401 public Dimension resizeInnerPanel(String data)
1403 // Jalview doesn't honour resize panel requests
1410 protected void closeConsole()
1412 if (console != null)
1416 console.setVisible(false);
1419 } catch (Exception x)
1428 * ComponentListener method
1431 public void componentMoved(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentResized(ComponentEvent e)
1444 * ComponentListener method
1447 public void componentShown(ComponentEvent e)
1453 * ComponentListener method
1456 public void componentHidden(ComponentEvent e)