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.HiddenColumns;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.SequenceI;
30 import jalview.io.DataSourceType;
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;
38 import jalview.util.MessageManager;
40 import java.awt.Color;
41 import java.awt.Container;
42 import java.awt.event.ComponentEvent;
43 import java.awt.event.ComponentListener;
46 import java.security.AccessControlException;
47 import java.util.ArrayList;
48 import java.util.BitSet;
49 import java.util.Hashtable;
50 import java.util.List;
52 import java.util.Vector;
54 import org.jmol.adapter.smarter.SmarterJmolAdapter;
55 import org.jmol.api.JmolAppConsoleInterface;
56 import org.jmol.api.JmolSelectionListener;
57 import org.jmol.api.JmolStatusListener;
58 import org.jmol.api.JmolViewer;
59 import org.jmol.c.CBK;
60 import org.jmol.script.T;
61 import org.jmol.viewer.Viewer;
63 public abstract class JalviewJmolBinding extends AAStructureBindingModel
64 implements JmolStatusListener, JmolSelectionListener,
67 boolean allChainsSelected = false;
70 * when true, try to search the associated datamodel for sequences that are
71 * associated with any unknown structures in the Jmol view.
73 private boolean associateNewStructs = false;
75 Vector<String> atomsPicked = new Vector<String>();
77 private List<String> chainNames;
79 Hashtable<String, String> chainFile;
82 * the default or current model displayed if the model cannot be identified
83 * from the selection message
87 // protected JmolGenericPopup jmolpopup; // not used - remove?
95 StringBuffer resetLastRes = new StringBuffer();
99 public JalviewJmolBinding(StructureSelectionManager ssm,
100 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
101 DataSourceType protocol)
103 super(ssm, pdbentry, sequenceIs, protocol);
105 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
106 * "jalviewJmol", ap.av.applet .getDocumentBase(),
107 * ap.av.applet.getCodeBase(), "", this);
109 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
113 public JalviewJmolBinding(StructureSelectionManager ssm,
114 SequenceI[][] seqs, Viewer theViewer)
119 viewer.setJmolStatusListener(this);
120 viewer.addSelectionListener(this);
124 * construct a title string for the viewer window based on the data jalview
129 public String getViewerTitle()
131 return getViewerTitle("Jmol", true);
135 * prepare the view for a given set of models/chains. chainList contains
136 * strings of the form 'pdbfilename:Chaincode'
139 * list of chains to make visible
141 public void centerViewer(Vector<String> chainList)
143 StringBuilder cmd = new StringBuilder(128);
145 for (String lbl : chainList)
151 mlength = lbl.indexOf(":", p);
152 } while (p < mlength && mlength < (lbl.length() - 2));
153 // TODO: lookup each pdb id and recover proper model number for it.
154 cmd.append(":" + lbl.substring(mlength + 1) + " /"
155 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
157 if (cmd.length() > 0)
159 cmd.setLength(cmd.length() - 4);
161 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
164 public void closeViewer()
166 // remove listeners for all structures in viewer
167 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
171 releaseUIResources();
175 public void colourByChain()
177 colourBySequence = false;
178 // TODO: colour by chain should colour each chain distinctly across all
180 // TODO: http://issues.jalview.org/browse/JAL-628
181 evalStateCommand("select *;color chain");
185 public void colourByCharge()
187 colourBySequence = false;
188 evalStateCommand("select *;color white;select ASP,GLU;color red;"
189 + "select LYS,ARG;color blue;select CYS;color yellow");
193 * superpose the structures associated with sequences in the alignment
194 * according to their corresponding positions.
196 public void superposeStructures(AlignmentI alignment)
198 superposeStructures(alignment, -1, null);
202 * superpose the structures associated with sequences in the alignment
203 * according to their corresponding positions. ded)
205 * @param refStructure
206 * - select which pdb file to use as reference (default is -1 - the
207 * first structure in the alignment)
209 public void superposeStructures(AlignmentI alignment, int refStructure)
211 superposeStructures(alignment, refStructure, null);
215 * superpose the structures associated with sequences in the alignment
216 * according to their corresponding positions. ded)
218 * @param refStructure
219 * - select which pdb file to use as reference (default is -1 - the
220 * first structure in the alignment)
224 public void superposeStructures(AlignmentI alignment, int refStructure,
225 HiddenColumns hiddenCols)
227 superposeStructures(new AlignmentI[] { alignment },
229 { refStructure }, new HiddenColumns[] { hiddenCols });
236 public String superposeStructures(AlignmentI[] _alignment,
237 int[] _refStructure, HiddenColumns[] _hiddenCols)
239 while (viewer.isScriptExecuting())
244 } catch (InterruptedException i)
250 * get the distinct structure files modelled
251 * (a file with multiple chains may map to multiple sequences)
253 String[] files = getStructureFiles();
254 if (!waitForFileLoad(files))
259 StringBuilder selectioncom = new StringBuilder(256);
260 // In principle - nSeconds specifies the speed of animation for each
261 // superposition - but is seems to behave weirdly, so we don't specify it.
262 String nSeconds = " ";
263 if (files.length > 10)
265 nSeconds = " 0.005 ";
269 nSeconds = " " + (2.0 / files.length) + " ";
270 // if (nSeconds).substring(0,5)+" ";
273 // see JAL-1345 - should really automatically turn off the animation for
274 // large numbers of structures, but Jmol doesn't seem to allow that.
276 // union of all aligned positions are collected together.
277 for (int a = 0; a < _alignment.length; a++)
279 int refStructure = _refStructure[a];
280 AlignmentI alignment = _alignment[a];
281 HiddenColumns hiddenCols = _hiddenCols[a];
282 if (a > 0 && selectioncom.length() > 0 && !selectioncom
283 .substring(selectioncom.length() - 1).equals("|"))
285 selectioncom.append("|");
287 // process this alignment
288 if (refStructure >= files.length)
291 "Invalid reference structure value " + refStructure);
296 * 'matched' bit j will be set for visible alignment columns j where
297 * all sequences have a residue with a mapping to the PDB structure
299 BitSet matched = new BitSet();
300 for (int m = 0; m < alignment.getWidth(); m++)
302 if (hiddenCols == null || hiddenCols.isVisible(m))
308 SuperposeData[] structures = new SuperposeData[files.length];
309 for (int f = 0; f < files.length; f++)
311 structures[f] = new SuperposeData(alignment.getWidth());
315 * Calculate the superposable alignment columns ('matched'), and the
316 * corresponding structure residue positions (structures.pdbResNo)
318 int candidateRefStructure = findSuperposableResidues(alignment,
319 matched, structures);
320 if (refStructure < 0)
323 * If no reference structure was specified, pick the first one that has
324 * a mapping in the alignment
326 refStructure = candidateRefStructure;
329 String[] selcom = new String[files.length];
330 int nmatched = matched.cardinality();
333 return (MessageManager.formatMessage("label.insufficient_residues",
338 * generate select statements to select regions to superimpose structures
341 // TODO extract method to construct selection statements
342 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
344 String chainCd = ":" + structures[pdbfnum].chain;
347 StringBuilder molsel = new StringBuilder();
350 int nextColumnMatch = matched.nextSetBit(0);
351 while (nextColumnMatch != -1)
353 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
354 if (lpos != pdbResNo - 1)
360 molsel.append(chainCd);
367 // continuous run - and lpos >-1
370 // at the beginning, so add dash
377 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
380 * add final selection phrase
385 molsel.append(chainCd);
388 if (molsel.length() > 1)
390 selcom[pdbfnum] = molsel.toString();
391 selectioncom.append("((");
392 selectioncom.append(selcom[pdbfnum].substring(1,
393 selcom[pdbfnum].length() - 1));
394 selectioncom.append(" )& ");
395 selectioncom.append(pdbfnum + 1);
396 selectioncom.append(".1)");
397 if (pdbfnum < files.length - 1)
399 selectioncom.append("|");
404 selcom[pdbfnum] = null;
408 StringBuilder command = new StringBuilder(256);
409 // command.append("set spinFps 10;\n");
411 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
413 if (pdbfnum == refStructure || selcom[pdbfnum] == null
414 || selcom[refStructure] == null)
418 command.append("echo ");
419 command.append("\"Superposing (");
420 command.append(structures[pdbfnum].pdbId);
421 command.append(") against reference (");
422 command.append(structures[refStructure].pdbId);
423 command.append(")\";\ncompare " + nSeconds);
425 command.append(Integer.toString(1 + pdbfnum));
426 command.append(".1} {");
427 command.append(Integer.toString(1 + refStructure));
428 // conformation=1 excludes alternate locations for CA (JAL-1757)
430 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
432 // for (int s = 0; s < 2; s++)
434 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
436 command.append(selcom[pdbfnum]);
437 command.append(selcom[refStructure]);
438 command.append(" ROTATE TRANSLATE;\n");
440 if (selectioncom.length() > 0)
442 // TODO is performing selectioncom redundant here? is done later on
443 // System.out.println("Select regions:\n" + selectioncom.toString());
444 evalStateCommand("select *; cartoons off; backbone; select ("
445 + selectioncom.toString() + "); cartoons; ");
446 // selcom.append("; ribbons; ");
447 String cmdString = command.toString();
448 // System.out.println("Superimpose command(s):\n" + cmdString);
450 evalStateCommand(cmdString);
453 if (selectioncom.length() > 0)
454 {// finally, mark all regions that were superposed.
455 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
457 selectioncom.setLength(selectioncom.length() - 1);
459 // System.out.println("Select regions:\n" + selectioncom.toString());
460 evalStateCommand("select *; cartoons off; backbone; select ("
461 + selectioncom.toString() + "); cartoons; ");
462 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
463 // cartoons; center "+selcom.toString());
469 public void evalStateCommand(String command)
472 if (lastCommand == null || !lastCommand.equals(command))
474 viewer.evalStringQuiet(command + "\n");
477 lastCommand = command;
481 * Sends a set of colour commands to the structure viewer
483 * @param colourBySequenceCommands
486 protected void colourBySequence(
487 StructureMappingcommandSet[] colourBySequenceCommands)
489 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
491 for (String cbyseq : cpdbbyseq.commands)
493 executeWhenReady(cbyseq);
505 protected StructureMappingcommandSet[] getColourBySequenceCommands(
506 String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
508 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
509 getSequence(), sr, viewPanel);
515 protected void executeWhenReady(String command)
517 evalStateCommand(command);
520 public void createImage(String file, String type, int quality)
522 System.out.println("JMOL CREATE IMAGE");
526 public String createImage(String fileName, String type,
527 Object textOrBytes, int quality)
529 System.out.println("JMOL CREATE IMAGE");
534 public String eval(String strEval)
536 // System.out.println(strEval);
537 // "# 'eval' is implemented only for the applet.";
541 // End StructureListener
542 // //////////////////////////
545 public float[][] functionXY(String functionName, int x, int y)
551 public float[][][] functionXYZ(String functionName, int nx, int ny,
554 // TODO Auto-generated method stub
558 public Color getColour(int atomIndex, int pdbResNum, String chain,
561 if (getModelNum(pdbfile) < 0)
565 // TODO: verify atomIndex is selecting correct model.
566 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
567 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
568 return new Color(colour);
572 * instruct the Jalview binding to update the pdbentries vector if necessary
573 * prior to matching the jmol view's contents to the list of structure files
574 * Jalview knows about.
576 public abstract void refreshPdbEntries();
578 private int getModelNum(String modelFileName)
580 String[] mfn = getStructureFiles();
585 for (int i = 0; i < mfn.length; i++)
587 if (mfn[i].equalsIgnoreCase(modelFileName))
596 * map between index of model filename returned from getPdbFile and the first
597 * index of models from this file in the viewer. Note - this is not trimmed -
598 * use getPdbFile to get number of unique models.
600 private int _modelFileNameMap[];
602 // ////////////////////////////////
603 // /StructureListener
605 public synchronized String[] getPdbFilex()
609 return new String[0];
611 if (modelFileNames == null)
613 List<String> mset = new ArrayList<String>();
614 _modelFileNameMap = new int[viewer.ms.mc];
615 String m = viewer.ms.getModelFileName(0);
621 filePath = new File(m).getAbsolutePath();
622 } catch (AccessControlException x)
624 // usually not allowed to do this in applet
626 "jmolBinding: Using local file string from Jmol: " + m);
628 if (filePath.indexOf("/file:") != -1)
630 // applet path with docroot - discard as format won't match pdbfile
634 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
637 for (int i = 1; i < viewer.ms.mc; i++)
639 m = viewer.ms.getModelFileName(i);
645 filePath = new File(m).getAbsolutePath();
646 } catch (AccessControlException x)
648 // usually not allowed to do this in applet, so keep raw handle
649 // System.err.println("jmolBinding: Using local file string from
655 * add this model unless it is read from a structure file we have
656 * already seen (example: 2MJW is an NMR structure with 10 models)
658 if (!mset.contains(filePath))
661 _modelFileNameMap[j] = i; // record the model index for the filename
665 modelFileNames = mset.toArray(new String[mset.size()]);
667 return modelFileNames;
671 public synchronized String[] getStructureFiles()
673 List<String> mset = new ArrayList<String>();
676 return new String[0];
679 if (modelFileNames == null)
681 int modelCount = viewer.ms.mc;
682 String filePath = null;
683 for (int i = 0; i < modelCount; ++i)
685 filePath = viewer.ms.getModelFileName(i);
686 if (!mset.contains(filePath))
691 modelFileNames = mset.toArray(new String[mset.size()]);
694 return modelFileNames;
698 * map from string to applet
701 public Map<String, Object> getRegistryInfo()
703 // TODO Auto-generated method stub
707 // ///////////////////////////////
708 // JmolStatusListener
710 public void handlePopupMenu(int x, int y)
712 // jmolpopup.show(x, y);
713 // jmolpopup.jpiShow(x, y);
717 * Highlight zero, one or more atoms on the structure
720 public void highlightAtoms(List<AtomSpec> atoms)
724 if (resetLastRes.length() > 0)
726 viewer.evalStringQuiet(resetLastRes.toString());
727 resetLastRes.setLength(0);
729 for (AtomSpec atom : atoms)
731 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
732 atom.getChain(), atom.getPdbFile());
738 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
741 if (modelFileNames == null)
746 // look up file model number for this pdbfile
748 // may need to adjust for URLencoding here - we don't worry about that yet.
749 while (mdlNum < modelFileNames.length
750 && !pdbfile.equals(modelFileNames[mdlNum]))
754 if (mdlNum == modelFileNames.length)
761 StringBuilder cmd = new StringBuilder(64);
762 cmd.append("select " + pdbResNum); // +modelNum
764 resetLastRes.append("select " + pdbResNum); // +modelNum
767 resetLastRes.append(":");
768 if (!chain.equals(" "))
771 resetLastRes.append(chain);
774 cmd.append(" /" + (mdlNum + 1));
775 resetLastRes.append("/" + (mdlNum + 1));
777 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
779 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
780 + " and not hetero; spacefill 0;");
782 cmd.append("spacefill 200;select none");
784 viewer.evalStringQuiet(cmd.toString());
789 boolean debug = true;
791 private void jmolHistory(boolean enable)
793 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
796 public void loadInline(String string)
800 // viewer.loadInline(strModel, isAppend);
802 // construct fake fullPathName and fileName so we can identify the file
804 // Then, construct pass a reader for the string to Jmol.
805 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
806 // fileName, null, reader, false, null, null, 0);
807 viewer.openStringInline(string);
810 public void mouseOverStructure(int atomIndex, String strInfo)
813 int alocsep = strInfo.indexOf("^");
814 int mdlSep = strInfo.indexOf("/");
815 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
817 if (chainSeparator == -1)
819 chainSeparator = strInfo.indexOf(".");
820 if (mdlSep > -1 && mdlSep < chainSeparator)
822 chainSeparator1 = chainSeparator;
823 chainSeparator = mdlSep;
826 // handle insertion codes
829 pdbResNum = Integer.parseInt(
830 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
835 pdbResNum = Integer.parseInt(
836 strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator));
840 if (strInfo.indexOf(":") > -1)
842 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
843 strInfo.indexOf("."));
850 String pdbfilename = modelFileNames[frameNo]; // default is first or current
854 if (chainSeparator1 == -1)
856 chainSeparator1 = strInfo.indexOf(".", mdlSep);
858 String mdlId = (chainSeparator1 > -1)
859 ? strInfo.substring(mdlSep + 1, chainSeparator1)
860 : strInfo.substring(mdlSep + 1);
863 // recover PDB filename for the model hovered over.
864 int _mp = _modelFileNameMap.length - 1,
865 mnumber = new Integer(mdlId).intValue() - 1;
866 while (mnumber < _modelFileNameMap[_mp])
870 pdbfilename = modelFileNames[_mp];
871 if (pdbfilename == null)
873 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
877 } catch (Exception e)
882 if (lastMessage == null || !lastMessage.equals(strInfo))
884 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
887 lastMessage = strInfo;
890 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
894 System.err.println("Ignoring additional hover info: " + data
895 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
897 mouseOverStructure(atomIndex, strInfo);
901 * { if (history != null && strStatus != null &&
902 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
906 public void notifyAtomPicked(int atomIndex, String strInfo,
910 * this implements the toggle label behaviour copied from the original
911 * structure viewer, MCView
915 System.err.println("Ignoring additional pick data string " + strData);
917 int chainSeparator = strInfo.indexOf(":");
919 if (chainSeparator == -1)
921 chainSeparator = strInfo.indexOf(".");
924 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
926 String mdlString = "";
927 if ((p = strInfo.indexOf(":")) > -1)
929 picked += strInfo.substring(p, strInfo.indexOf("."));
932 if ((p = strInfo.indexOf("/")) > -1)
934 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
936 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
940 if (!atomsPicked.contains(picked))
942 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
943 atomsPicked.addElement(picked);
947 viewer.evalString("select " + picked + ";label off");
948 atomsPicked.removeElement(picked);
951 // TODO: in application this happens
953 // if (scriptWindow != null)
955 // scriptWindow.sendConsoleMessage(strInfo);
956 // scriptWindow.sendConsoleMessage("\n");
962 public void notifyCallback(CBK type, Object[] data)
969 notifyFileLoaded((String) data[1], (String) data[2],
970 (String) data[3], (String) data[4],
971 ((Integer) data[5]).intValue());
975 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
977 // also highlight in alignment
978 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
982 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
986 notifyScriptTermination((String) data[2],
987 ((Integer) data[3]).intValue());
990 sendConsoleEcho((String) data[1]);
994 (data == null) ? ((String) null) : (String) data[1]);
997 // System.err.println("Ignoring error callback.");
1008 "Unhandled callback " + type + " " + data[1].toString());
1011 } catch (Exception e)
1013 System.err.println("Squashed Jmol callback handler error:");
1014 e.printStackTrace();
1019 public boolean notifyEnabled(CBK callbackPick)
1021 switch (callbackPick)
1037 // incremented every time a load notification is successfully handled -
1038 // lightweight mechanism for other threads to detect when they can start
1039 // referrring to new structures.
1040 private long loadNotifiesHandled = 0;
1042 public long getLoadNotifiesHandled()
1044 return loadNotifiesHandled;
1047 public void notifyFileLoaded(String fullPathName, String fileName2,
1048 String modelName, String errorMsg, int modelParts)
1050 if (errorMsg != null)
1052 fileLoadingError = errorMsg;
1056 // TODO: deal sensibly with models loaded inLine:
1057 // modelName will be null, as will fullPathName.
1059 // the rest of this routine ignores the arguments, and simply interrogates
1060 // the Jmol view to find out what structures it contains, and adds them to
1061 // the structure selection manager.
1062 fileLoadingError = null;
1063 String[] oldmodels = modelFileNames;
1064 modelFileNames = null;
1065 chainNames = new ArrayList<String>();
1066 chainFile = new Hashtable<String, String>();
1067 boolean notifyLoaded = false;
1068 String[] modelfilenames = getStructureFiles();
1069 // first check if we've lost any structures
1070 if (oldmodels != null && oldmodels.length > 0)
1073 for (int i = 0; i < oldmodels.length; i++)
1075 for (int n = 0; n < modelfilenames.length; n++)
1077 if (modelfilenames[n] == oldmodels[i])
1079 oldmodels[i] = null;
1083 if (oldmodels[i] != null)
1090 String[] oldmfn = new String[oldm];
1092 for (int i = 0; i < oldmodels.length; i++)
1094 if (oldmodels[i] != null)
1096 oldmfn[oldm++] = oldmodels[i];
1099 // deregister the Jmol instance for these structures - we'll add
1100 // ourselves again at the end for the current structure set.
1101 getSsm().removeStructureViewerListener(this, oldmfn);
1104 refreshPdbEntries();
1105 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1107 String fileName = modelfilenames[modelnum];
1108 boolean foundEntry = false;
1109 StructureFile pdb = null;
1110 String pdbfile = null;
1111 // model was probably loaded inline - so check the pdb file hashcode
1114 // calculate essential attributes for the pdb data imported inline.
1115 // prolly need to resolve modelnumber properly - for now just use our
1117 pdbfile = viewer.getData(
1118 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1120 // search pdbentries and sequences to find correct pdbentry for this
1122 for (int pe = 0; pe < getPdbCount(); pe++)
1124 boolean matches = false;
1125 addSequence(pe, getSequence()[pe]);
1126 if (fileName == null)
1129 // see JAL-623 - need method of matching pasted data up
1131 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1132 pdbfile, DataSourceType.PASTE);
1133 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1140 File fl = new File(getPdbEntry(pe).getFile());
1141 matches = fl.equals(new File(fileName));
1145 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1148 // to be tested. See mantis bug
1149 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1150 DataSourceType protocol = DataSourceType.URL;
1155 protocol = DataSourceType.FILE;
1157 } catch (Exception e)
1162 // Explicitly map to the filename used by Jmol ;
1163 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1164 fileName, protocol);
1165 // pdbentry[pe].getFile(), protocol);
1171 // add an entry for every chain in the model
1172 for (int i = 0; i < pdb.getChains().size(); i++)
1174 String chid = new String(
1175 pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
1176 chainFile.put(chid, fileName);
1177 chainNames.add(chid);
1179 notifyLoaded = true;
1183 if (!foundEntry && associateNewStructs)
1185 // this is a foreign pdb file that jalview doesn't know about - add
1186 // it to the dataset and try to find a home - either on a matching
1187 // sequence or as a new sequence.
1188 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1190 // parse pdb file into a chain, etc.
1191 // locate best match for pdb in associated views and add mapping to
1193 // if properly registered then
1194 notifyLoaded = true;
1199 // so finally, update the jmol bits and pieces
1200 // if (jmolpopup != null)
1202 // // potential for deadlock here:
1203 // // jmolpopup.updateComputedMenus();
1205 if (!isLoadingFromArchive())
1207 viewer.evalStringQuiet(
1208 "model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1210 // register ourselves as a listener and notify the gui that it needs to
1212 getSsm().addStructureViewerListener(this);
1215 FeatureRenderer fr = getFeatureRenderer(null);
1221 loadNotifiesHandled++;
1223 setLoadingFromArchive(false);
1227 public List<String> getChainNames()
1232 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1234 notifyAtomPicked(iatom, strMeasure, null);
1237 public abstract void notifyScriptTermination(String strStatus,
1241 * display a message echoed from the jmol viewer
1245 public abstract void sendConsoleEcho(String strEcho); /*
1246 * { showConsole(true);
1248 * history.append("\n" +
1252 // /End JmolStatusListener
1253 // /////////////////////////////
1257 * status message - usually the response received after a script
1260 public abstract void sendConsoleMessage(String strStatus);
1263 public void setCallbackFunction(String callbackType,
1264 String callbackFunction)
1266 System.err.println("Ignoring set-callback request to associate "
1267 + callbackType + " with function " + callbackFunction);
1272 public void setJalviewColourScheme(ColourSchemeI cs)
1274 colourBySequence = false;
1282 StringBuilder command = new StringBuilder(128);
1283 command.append("select *;color white;");
1284 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1286 for (String resName : residueSet)
1288 char res = resName.length() == 3
1289 ? ResidueProperties.getSingleCharacterCode(resName)
1290 : resName.charAt(0);
1291 Color col = cs.findColour(res, 0, null, null, 0f);
1292 command.append("select " + resName + ";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),
1370 htmlName + ((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;
1390 public void setBackgroundColour(java.awt.Color col)
1393 viewer.evalStringQuiet("background [" + col.getRed() + ","
1394 + col.getGreen() + "," + col.getBlue() + "];");
1399 public int[] resizeInnerPanel(String data)
1401 // Jalview doesn't honour resize panel requests
1408 protected void closeConsole()
1410 if (console != null)
1414 console.setVisible(false);
1417 } catch (Exception x)
1426 * ComponentListener method
1429 public void componentMoved(ComponentEvent e)
1434 * ComponentListener method
1437 public void componentResized(ComponentEvent e)
1442 * ComponentListener method
1445 public void componentShown(ComponentEvent e)
1451 * ComponentListener method
1454 public void componentHidden(ComponentEvent e)