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.io.StructureFile;
32 import jalview.schemes.ColourSchemeI;
33 import jalview.schemes.ResidueProperties;
34 import jalview.structure.AtomSpec;
35 import jalview.structure.StructureMappingcommandSet;
36 import jalview.structure.StructureSelectionManager;
37 import jalview.structures.models.AAStructureBindingModel;
39 import java.awt.Color;
40 import java.awt.Container;
41 import java.awt.event.ComponentEvent;
42 import java.awt.event.ComponentListener;
45 import java.security.AccessControlException;
46 import java.util.Hashtable;
47 import java.util.List;
49 import java.util.Vector;
51 import javajs.awt.Dimension;
53 import org.jmol.adapter.smarter.SmarterJmolAdapter;
54 import org.jmol.api.JmolAppConsoleInterface;
55 import org.jmol.api.JmolSelectionListener;
56 import org.jmol.api.JmolStatusListener;
57 import org.jmol.api.JmolViewer;
58 import org.jmol.c.CBK;
59 import org.jmol.script.T;
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 // remove listeners for all structures in viewer
173 getSsm().removeStructureViewerListener(this, this.getPdbFile());
177 releaseUIResources();
180 public void colourByChain()
182 colourBySequence = false;
183 // TODO: colour by chain should colour each chain distinctly across all
185 // TODO: http://issues.jalview.org/browse/JAL-628
186 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 ColumnSelection hiddenCols)
231 superposeStructures(new AlignmentI[] { alignment },
232 new int[] { refStructure },
233 new ColumnSelection[] { hiddenCols });
237 * Construct and send a command to align structures against a reference
238 * structure, based on one or more sequence alignments
241 * an array of alignments to process
242 * @param _refStructure
243 * an array of corresponding reference structures (index into pdb
244 * file array); if a negative value is passed, the first PDB file
245 * mapped to an alignment sequence is used as the reference for
248 * an array of corresponding hidden columns for each alignment
250 public void superposeStructures(AlignmentI[] _alignment,
251 int[] _refStructure, ColumnSelection[] _hiddenCols)
253 while (viewer.isScriptExecuting())
258 } catch (InterruptedException i)
263 String[] files = getPdbFile();
264 if (!waitForFileLoad(files))
269 StringBuilder selectioncom = new StringBuilder(256);
270 // In principle - nSeconds specifies the speed of animation for each
271 // superposition - but is seems to behave weirdly, so we don't specify it.
272 String nSeconds = " ";
273 if (files.length > 10)
275 nSeconds = " 0.005 ";
279 nSeconds = " " + (2.0 / files.length) + " ";
280 // if (nSeconds).substring(0,5)+" ";
282 // see JAL-1345 - should really automatically turn off the animation for
283 // large numbers of structures, but Jmol doesn't seem to allow that.
285 // union of all aligned positions are collected together.
286 for (int a = 0; a < _alignment.length; a++)
288 int refStructure = _refStructure[a];
289 AlignmentI alignment = _alignment[a];
290 ColumnSelection hiddenCols = _hiddenCols[a];
292 && selectioncom.length() > 0
293 && !selectioncom.substring(selectioncom.length() - 1).equals(
296 selectioncom.append("|");
298 // process this alignment
299 if (refStructure >= files.length)
301 System.err.println("Invalid reference structure value "
307 * 'matched' array will hold 'true' for visible alignment columns where
308 * all sequences have a residue with a mapping to the PDB structure
310 boolean matched[] = new boolean[alignment.getWidth()];
311 for (int m = 0; m < matched.length; m++)
313 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
316 SuperposeData[] structures = new SuperposeData[files.length];
317 for (int f = 0; f < files.length; f++)
319 structures[f] = new SuperposeData(alignment.getWidth());
323 * Calculate the superposable alignment columns ('matched'), and the
324 * corresponding structure residue positions (structures.pdbResNo)
326 int candidateRefStructure = findSuperposableResidues(alignment,
327 matched, structures);
328 if (refStructure < 0)
331 * If no reference structure was specified, pick the first one that has
332 * a mapping in the alignment
334 refStructure = candidateRefStructure;
337 String[] selcom = new String[files.length];
339 for (boolean b : matched)
348 // TODO: bail out here because superposition illdefined?
352 * generate select statements to select regions to superimpose structures
355 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
357 String chainCd = ":" + structures[pdbfnum].chain;
360 StringBuilder molsel = new StringBuilder();
362 for (int r = 0; r < matched.length; r++)
366 int pdbResNo = structures[pdbfnum].pdbResNo[r];
367 if (lpos != pdbResNo - 1)
373 molsel.append(chainCd);
380 // continuous run - and lpos >-1
383 // at the beginning, so add dash
393 * add final selection phrase
398 molsel.append(chainCd);
401 if (molsel.length() > 1)
403 selcom[pdbfnum] = molsel.toString();
404 selectioncom.append("((");
405 selectioncom.append(selcom[pdbfnum].substring(1,
406 selcom[pdbfnum].length() - 1));
407 selectioncom.append(" )& ");
408 selectioncom.append(pdbfnum + 1);
409 selectioncom.append(".1)");
410 if (pdbfnum < files.length - 1)
412 selectioncom.append("|");
417 selcom[pdbfnum] = null;
421 StringBuilder command = new StringBuilder(256);
422 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
424 if (pdbfnum == refStructure || selcom[pdbfnum] == null
425 || selcom[refStructure] == null)
429 command.append("echo ");
430 command.append("\"Superposing (");
431 command.append(structures[pdbfnum].pdbId);
432 command.append(") against reference (");
433 command.append(structures[refStructure].pdbId);
434 command.append(")\";\ncompare " + nSeconds);
436 command.append(Integer.toString(1 + pdbfnum));
437 command.append(".1} {");
438 command.append(Integer.toString(1 + refStructure));
439 // conformation=1 excludes alternate locations for CA (JAL-1757)
440 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
442 // for (int s = 0; s < 2; s++)
444 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
446 command.append(selcom[pdbfnum]);
447 command.append(selcom[refStructure]);
448 command.append(" ROTATE TRANSLATE;\n");
450 if (selectioncom.length() > 0)
452 System.out.println("Select regions:\n" + selectioncom.toString());
453 evalStateCommand("select *; cartoons off; backbone; select ("
454 + selectioncom.toString() + "); cartoons; ");
455 // selcom.append("; ribbons; ");
456 String cmdString = command.toString();
457 System.out.println("Superimpose command(s):\n" + cmdString);
459 evalStateCommand(cmdString);
462 if (selectioncom.length() > 0)
463 {// finally, mark all regions that were superposed.
464 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
466 selectioncom.setLength(selectioncom.length() - 1);
468 System.out.println("Select regions:\n" + selectioncom.toString());
469 evalStateCommand("select *; cartoons off; backbone; select ("
470 + selectioncom.toString() + "); cartoons; ");
471 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
475 public void evalStateCommand(String command)
478 if (lastCommand == null || !lastCommand.equals(command))
480 viewer.evalStringQuiet(command + "\n");
483 lastCommand = command;
487 * colour any structures associated with sequences in the given alignment
488 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
489 * if colourBySequence is enabled.
491 public void colourBySequence(AlignmentViewPanel alignmentv)
493 boolean showFeatures = alignmentv.getAlignViewport()
494 .isShowSequenceFeatures();
495 if (!colourBySequence || !isLoadingFinished())
499 if (getSsm() == null)
503 String[] files = getPdbFile();
505 SequenceRenderer sr = getSequenceRenderer(alignmentv);
507 FeatureRenderer fr = null;
510 fr = getFeatureRenderer(alignmentv);
512 AlignmentI alignment = alignmentv.getAlignment();
514 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
515 files, sr, fr, alignment))
517 for (String cbyseq : cpdbbyseq.commands)
519 executeWhenReady(cbyseq);
531 protected StructureMappingcommandSet[] getColourBySequenceCommands(
532 String[] files, SequenceRenderer sr, FeatureRenderer fr,
533 AlignmentI alignment)
535 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
536 getSequence(), sr, fr, alignment);
542 protected void executeWhenReady(String command)
544 evalStateCommand(command);
547 public void createImage(String file, String type, int quality)
549 System.out.println("JMOL CREATE IMAGE");
553 public String createImage(String fileName, String type,
554 Object textOrBytes, int quality)
556 System.out.println("JMOL CREATE IMAGE");
561 public String eval(String strEval)
563 // System.out.println(strEval);
564 // "# 'eval' is implemented only for the applet.";
568 // End StructureListener
569 // //////////////////////////
572 public float[][] functionXY(String functionName, int x, int y)
578 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
580 // TODO Auto-generated method stub
584 public Color getColour(int atomIndex, int pdbResNum, String chain,
587 if (getModelNum(pdbfile) < 0)
591 // TODO: verify atomIndex is selecting correct model.
592 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
593 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
594 return new Color(colour);
598 * returns the current featureRenderer that should be used to colour the
605 public abstract FeatureRenderer getFeatureRenderer(
606 AlignmentViewPanel alignment);
609 * instruct the Jalview binding to update the pdbentries vector if necessary
610 * prior to matching the jmol view's contents to the list of structure files
611 * Jalview knows about.
613 public abstract void refreshPdbEntries();
615 private int getModelNum(String modelFileName)
617 String[] mfn = getPdbFile();
622 for (int i = 0; i < mfn.length; i++)
624 if (mfn[i].equalsIgnoreCase(modelFileName))
633 * map between index of model filename returned from getPdbFile and the first
634 * index of models from this file in the viewer. Note - this is not trimmed -
635 * use getPdbFile to get number of unique models.
637 private int _modelFileNameMap[];
639 // ////////////////////////////////
640 // /StructureListener
642 public synchronized String[] getPdbFile()
646 return new String[0];
648 if (modelFileNames == null)
650 String mset[] = new String[viewer.ms.mc];
651 _modelFileNameMap = new int[mset.length];
652 String m = viewer.ms.getModelFileName(0);
658 mset[0] = new File(m).getAbsolutePath();
659 } catch (AccessControlException x)
661 // usually not allowed to do this in applet
663 .println("jmolBinding: Using local file string from Jmol: "
666 if (mset[0].indexOf("/file:") != -1)
668 // applet path with docroot - discard as format won't match pdbfile
671 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
674 for (int i = 1; i < mset.length; i++)
676 m = viewer.ms.getModelFileName(i);
682 mset[j] = new File(m).getAbsolutePath();
683 } catch (AccessControlException x)
685 // usually not allowed to do this in applet, so keep raw handle
686 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
689 _modelFileNameMap[j] = i; // record the model index for the filename
690 // skip any additional models in the same file (NMR structures)
691 if ((mset[j] == null ? mset[j] != mset[j - 1]
692 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
697 modelFileNames = new String[j];
698 System.arraycopy(mset, 0, modelFileNames, 0, j);
700 return modelFileNames;
704 * map from string to applet
707 public Map<String, Object> getRegistryInfo()
709 // TODO Auto-generated method stub
714 * returns the current sequenceRenderer that should be used to colour the
721 public abstract SequenceRenderer getSequenceRenderer(
722 AlignmentViewPanel alignment);
724 // ///////////////////////////////
725 // JmolStatusListener
727 public void handlePopupMenu(int x, int y)
729 // jmolpopup.show(x, y);
730 // jmolpopup.jpiShow(x, y);
734 * Highlight zero, one or more atoms on the structure
737 public void highlightAtoms(List<AtomSpec> atoms)
741 if (resetLastRes.length() > 0)
743 viewer.evalStringQuiet(resetLastRes.toString());
744 resetLastRes.setLength(0);
746 for (AtomSpec atom : atoms)
748 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
749 atom.getChain(), atom.getPdbFile());
755 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
758 if (modelFileNames == null)
763 // look up file model number for this pdbfile
765 // may need to adjust for URLencoding here - we don't worry about that yet.
766 while (mdlNum < modelFileNames.length
767 && !pdbfile.equals(modelFileNames[mdlNum]))
771 if (mdlNum == modelFileNames.length)
778 StringBuilder cmd = new StringBuilder(64);
779 cmd.append("select " + pdbResNum); // +modelNum
781 resetLastRes.append("select " + pdbResNum); // +modelNum
784 resetLastRes.append(":");
785 if (!chain.equals(" "))
788 resetLastRes.append(chain);
791 cmd.append(" /" + (mdlNum + 1));
792 resetLastRes.append("/" + (mdlNum + 1));
794 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
796 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
797 + " and not hetero; spacefill 0;");
799 cmd.append("spacefill 200;select none");
801 viewer.evalStringQuiet(cmd.toString());
806 boolean debug = true;
808 private void jmolHistory(boolean enable)
810 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
813 public void loadInline(String string)
817 // viewer.loadInline(strModel, isAppend);
819 // construct fake fullPathName and fileName so we can identify the file
821 // Then, construct pass a reader for the string to Jmol.
822 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
823 // fileName, null, reader, false, null, null, 0);
824 viewer.openStringInline(string);
827 public void mouseOverStructure(int atomIndex, String strInfo)
830 int alocsep = strInfo.indexOf("^");
831 int mdlSep = strInfo.indexOf("/");
832 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
834 if (chainSeparator == -1)
836 chainSeparator = strInfo.indexOf(".");
837 if (mdlSep > -1 && mdlSep < chainSeparator)
839 chainSeparator1 = chainSeparator;
840 chainSeparator = mdlSep;
843 // handle insertion codes
846 pdbResNum = Integer.parseInt(strInfo.substring(
847 strInfo.indexOf("]") + 1, alocsep));
852 pdbResNum = Integer.parseInt(strInfo.substring(
853 strInfo.indexOf("]") + 1, chainSeparator));
857 if (strInfo.indexOf(":") > -1)
859 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
860 strInfo.indexOf("."));
867 String pdbfilename = modelFileNames[frameNo]; // default is first or current
871 if (chainSeparator1 == -1)
873 chainSeparator1 = strInfo.indexOf(".", mdlSep);
875 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
876 chainSeparator1) : strInfo.substring(mdlSep + 1);
879 // recover PDB filename for the model hovered over.
880 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
882 while (mnumber < _modelFileNameMap[_mp])
886 pdbfilename = modelFileNames[_mp];
887 if (pdbfilename == null)
889 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
893 } catch (Exception e)
898 if (lastMessage == null || !lastMessage.equals(strInfo))
900 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
903 lastMessage = strInfo;
906 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
910 System.err.println("Ignoring additional hover info: " + data
911 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
913 mouseOverStructure(atomIndex, strInfo);
917 * { if (history != null && strStatus != null &&
918 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
922 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
925 * this implements the toggle label behaviour copied from the original
926 * structure viewer, MCView
930 System.err.println("Ignoring additional pick data string " + strData);
932 int chainSeparator = strInfo.indexOf(":");
934 if (chainSeparator == -1)
936 chainSeparator = strInfo.indexOf(".");
939 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
941 String mdlString = "";
942 if ((p = strInfo.indexOf(":")) > -1)
944 picked += strInfo.substring(p, strInfo.indexOf("."));
947 if ((p = strInfo.indexOf("/")) > -1)
949 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
951 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
955 if (!atomsPicked.contains(picked))
957 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
958 atomsPicked.addElement(picked);
962 viewer.evalString("select " + picked + ";label off");
963 atomsPicked.removeElement(picked);
966 // TODO: in application this happens
968 // if (scriptWindow != null)
970 // scriptWindow.sendConsoleMessage(strInfo);
971 // scriptWindow.sendConsoleMessage("\n");
977 public void notifyCallback(CBK type, Object[] data)
984 notifyFileLoaded((String) data[1], (String) data[2],
985 (String) data[3], (String) data[4],
986 ((Integer) data[5]).intValue());
990 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
992 // also highlight in alignment
994 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
998 notifyScriptTermination((String) data[2],
999 ((Integer) data[3]).intValue());
1002 sendConsoleEcho((String) data[1]);
1005 sendConsoleMessage((data == null) ? ((String) null)
1006 : (String) data[1]);
1009 // System.err.println("Ignoring error callback.");
1019 System.err.println("Unhandled callback " + type + " "
1020 + data[1].toString());
1023 } catch (Exception e)
1025 System.err.println("Squashed Jmol callback handler error:");
1026 e.printStackTrace();
1031 public boolean notifyEnabled(CBK callbackPick)
1033 switch (callbackPick)
1049 // incremented every time a load notification is successfully handled -
1050 // lightweight mechanism for other threads to detect when they can start
1051 // referrring to new structures.
1052 private long loadNotifiesHandled = 0;
1054 public long getLoadNotifiesHandled()
1056 return loadNotifiesHandled;
1059 public void notifyFileLoaded(String fullPathName, String fileName2,
1060 String modelName, String errorMsg, int modelParts)
1062 if (errorMsg != null)
1064 fileLoadingError = errorMsg;
1068 // TODO: deal sensibly with models loaded inLine:
1069 // modelName will be null, as will fullPathName.
1071 // the rest of this routine ignores the arguments, and simply interrogates
1072 // the Jmol view to find out what structures it contains, and adds them to
1073 // the structure selection manager.
1074 fileLoadingError = null;
1075 String[] oldmodels = modelFileNames;
1076 modelFileNames = null;
1077 chainNames = new Vector<String>();
1078 chainFile = new Hashtable<String, String>();
1079 boolean notifyLoaded = false;
1080 String[] modelfilenames = getPdbFile();
1081 // first check if we've lost any structures
1082 if (oldmodels != null && oldmodels.length > 0)
1085 for (int i = 0; i < oldmodels.length; i++)
1087 for (int n = 0; n < modelfilenames.length; n++)
1089 if (modelfilenames[n] == oldmodels[i])
1091 oldmodels[i] = null;
1095 if (oldmodels[i] != null)
1102 String[] oldmfn = new String[oldm];
1104 for (int i = 0; i < oldmodels.length; i++)
1106 if (oldmodels[i] != null)
1108 oldmfn[oldm++] = oldmodels[i];
1111 // deregister the Jmol instance for these structures - we'll add
1112 // ourselves again at the end for the current structure set.
1113 getSsm().removeStructureViewerListener(this, oldmfn);
1116 refreshPdbEntries();
1117 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1119 String fileName = modelfilenames[modelnum];
1120 boolean foundEntry = false;
1121 StructureFile pdb = null;
1122 String pdbfile = null;
1123 // model was probably loaded inline - so check the pdb file hashcode
1126 // calculate essential attributes for the pdb data imported inline.
1127 // prolly need to resolve modelnumber properly - for now just use our
1129 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1132 // search pdbentries and sequences to find correct pdbentry for this
1134 for (int pe = 0; pe < getPdbCount(); pe++)
1136 boolean matches = false;
1137 if (fileName == null)
1140 // see JAL-623 - need method of matching pasted data up
1142 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1143 pdbfile, AppletFormatAdapter.PASTE);
1144 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1151 File fl = new File(getPdbEntry(pe).getFile());
1152 matches = fl.equals(new File(fileName));
1156 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1159 // to be tested. See mantis bug
1160 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1161 String protocol = AppletFormatAdapter.URL;
1166 protocol = AppletFormatAdapter.FILE;
1168 } catch (Exception e)
1173 // Explicitly map to the filename used by Jmol ;
1174 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1175 fileName, protocol);
1176 // pdbentry[pe].getFile(), protocol);
1182 // add an entry for every chain in the model
1183 for (int i = 0; i < pdb.getChains().size(); i++)
1185 String chid = new String(pdb.getId() + ":"
1186 + pdb.getChains().elementAt(i).id);
1187 chainFile.put(chid, fileName);
1188 chainNames.addElement(chid);
1190 notifyLoaded = true;
1194 if (!foundEntry && associateNewStructs)
1196 // this is a foreign pdb file that jalview doesn't know about - add
1197 // it to the dataset and try to find a home - either on a matching
1198 // sequence or as a new sequence.
1199 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1201 // parse pdb file into a chain, etc.
1202 // locate best match for pdb in associated views and add mapping to
1204 // if properly registered then
1205 notifyLoaded = true;
1210 // so finally, update the jmol bits and pieces
1211 // if (jmolpopup != null)
1213 // // potential for deadlock here:
1214 // // jmolpopup.updateComputedMenus();
1216 if (!isLoadingFromArchive())
1218 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1220 // register ourselves as a listener and notify the gui that it needs to
1222 getSsm().addStructureViewerListener(this);
1225 FeatureRenderer fr = getFeatureRenderer(null);
1231 loadNotifiesHandled++;
1233 setLoadingFromArchive(false);
1236 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1238 notifyAtomPicked(iatom, strMeasure, null);
1241 public abstract void notifyScriptTermination(String strStatus,
1245 * display a message echoed from the jmol viewer
1249 public abstract void sendConsoleEcho(String strEcho); /*
1250 * { showConsole(true);
1252 * history.append("\n" +
1256 // /End JmolStatusListener
1257 // /////////////////////////////
1261 * status message - usually the response received after a script
1264 public abstract void sendConsoleMessage(String strStatus);
1267 public void setCallbackFunction(String callbackType,
1268 String callbackFunction)
1270 System.err.println("Ignoring set-callback request to associate "
1271 + callbackType + " with function " + callbackFunction);
1275 public void setJalviewColourScheme(ColourSchemeI cs)
1277 colourBySequence = false;
1285 StringBuilder command = new StringBuilder(128);
1286 command.append("select *;color white;");
1287 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1289 for (String res : residueSet)
1291 Color col = cs.findColour(res.charAt(0));
1292 command.append("select " + res + ";color[" + col.getRed() + ","
1293 + col.getGreen() + "," + col.getBlue() + "];");
1296 evalStateCommand(command.toString());
1300 public void showHelp()
1302 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1306 * open the URL somehow
1310 public abstract void showUrl(String url, String target);
1313 * called when the binding thinks the UI needs to be refreshed after a Jmol
1314 * state change. this could be because structures were loaded, or because an
1315 * error has occured.
1317 public abstract void refreshGUI();
1320 * called to show or hide the associated console window container.
1324 public abstract void showConsole(boolean show);
1327 * @param renderPanel
1329 * - when true will initialise jmol's file IO system (should be false
1330 * in applet context)
1332 * @param documentBase
1334 * @param commandOptions
1336 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1337 String htmlName, URL documentBase, URL codeBase,
1338 String commandOptions)
1340 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1341 codeBase, commandOptions, null, null);
1346 * @param renderPanel
1348 * - when true will initialise jmol's file IO system (should be false
1349 * in applet context)
1351 * @param documentBase
1353 * @param commandOptions
1354 * @param consolePanel
1355 * - panel to contain Jmol console
1356 * @param buttonsToShow
1357 * - buttons to show on the console, in ordr
1359 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1360 String htmlName, URL documentBase, URL codeBase,
1361 String commandOptions, final Container consolePanel,
1362 String buttonsToShow)
1364 if (commandOptions == null)
1366 commandOptions = "";
1368 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1369 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1370 + ((Object) this).toString(), documentBase, codeBase,
1371 commandOptions, this);
1373 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1375 console = createJmolConsole(consolePanel, buttonsToShow);
1376 if (consolePanel != null)
1378 consolePanel.addComponentListener(this);
1384 protected abstract JmolAppConsoleInterface createJmolConsole(
1385 Container consolePanel, String buttonsToShow);
1387 protected org.jmol.api.JmolAppConsoleInterface console = null;
1389 public void setBackgroundColour(java.awt.Color col)
1392 viewer.evalStringQuiet("background [" + col.getRed() + ","
1393 + col.getGreen() + "," + col.getBlue() + "];");
1398 public Dimension resizeInnerPanel(String data)
1400 // Jalview doesn't honour resize panel requests
1407 protected void closeConsole()
1409 if (console != null)
1413 console.setVisible(false);
1416 } catch (Exception x)
1425 * ComponentListener method
1428 public void componentMoved(ComponentEvent e)
1433 * ComponentListener method
1436 public void componentResized(ComponentEvent e)
1441 * ComponentListener method
1444 public void componentShown(ComponentEvent e)
1450 * ComponentListener method
1453 public void componentHidden(ComponentEvent e)