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 },
228 new int[] { refStructure },
229 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];
283 && selectioncom.length() > 0
284 && !selectioncom.substring(selectioncom.length() - 1).equals(
287 selectioncom.append("|");
289 // process this alignment
290 if (refStructure >= files.length)
292 System.err.println("Invalid reference structure value "
298 * 'matched' bit j will be set for visible alignment columns j where
299 * all sequences have a residue with a mapping to the PDB structure
301 BitSet matched = new BitSet();
302 for (int m = 0; m < alignment.getWidth(); m++)
304 if (hiddenCols == null || hiddenCols.isVisible(m))
310 SuperposeData[] structures = new SuperposeData[files.length];
311 for (int f = 0; f < files.length; f++)
313 structures[f] = new SuperposeData(alignment.getWidth());
317 * Calculate the superposable alignment columns ('matched'), and the
318 * corresponding structure residue positions (structures.pdbResNo)
320 int candidateRefStructure = findSuperposableResidues(alignment,
321 matched, structures);
322 if (refStructure < 0)
325 * If no reference structure was specified, pick the first one that has
326 * a mapping in the alignment
328 refStructure = candidateRefStructure;
331 String[] selcom = new String[files.length];
332 int nmatched = matched.cardinality();
335 return (MessageManager.formatMessage(
336 "label.insufficient_residues",
341 * generate select statements to select regions to superimpose structures
344 // TODO extract method to construct selection statements
345 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
347 String chainCd = ":" + structures[pdbfnum].chain;
350 StringBuilder molsel = new StringBuilder();
353 int nextColumnMatch = matched.nextSetBit(0);
354 while (nextColumnMatch != -1)
356 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
357 if (lpos != pdbResNo - 1)
363 molsel.append(chainCd);
370 // continuous run - and lpos >-1
373 // at the beginning, so add dash
380 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
383 * add final selection phrase
388 molsel.append(chainCd);
391 if (molsel.length() > 1)
393 selcom[pdbfnum] = molsel.toString();
394 selectioncom.append("((");
395 selectioncom.append(selcom[pdbfnum].substring(1,
396 selcom[pdbfnum].length() - 1));
397 selectioncom.append(" )& ");
398 selectioncom.append(pdbfnum + 1);
399 selectioncom.append(".1)");
400 if (pdbfnum < files.length - 1)
402 selectioncom.append("|");
407 selcom[pdbfnum] = null;
411 StringBuilder command = new StringBuilder(256);
412 // command.append("set spinFps 10;\n");
414 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
416 if (pdbfnum == refStructure || selcom[pdbfnum] == null
417 || selcom[refStructure] == null)
421 command.append("echo ");
422 command.append("\"Superposing (");
423 command.append(structures[pdbfnum].pdbId);
424 command.append(") against reference (");
425 command.append(structures[refStructure].pdbId);
426 command.append(")\";\ncompare " + nSeconds);
428 command.append(Integer.toString(1 + pdbfnum));
429 command.append(".1} {");
430 command.append(Integer.toString(1 + refStructure));
431 // conformation=1 excludes alternate locations for CA (JAL-1757)
432 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
434 // for (int s = 0; s < 2; s++)
436 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
438 command.append(selcom[pdbfnum]);
439 command.append(selcom[refStructure]);
440 command.append(" ROTATE TRANSLATE;\n");
442 if (selectioncom.length() > 0)
444 // TODO is performing selectioncom redundant here? is done later on
445 // System.out.println("Select regions:\n" + selectioncom.toString());
446 evalStateCommand("select *; cartoons off; backbone; select ("
447 + selectioncom.toString() + "); cartoons; ");
448 // selcom.append("; ribbons; ");
449 String cmdString = command.toString();
450 // System.out.println("Superimpose command(s):\n" + cmdString);
452 evalStateCommand(cmdString);
455 if (selectioncom.length() > 0)
456 {// finally, mark all regions that were superposed.
457 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
459 selectioncom.setLength(selectioncom.length() - 1);
461 // System.out.println("Select regions:\n" + selectioncom.toString());
462 evalStateCommand("select *; cartoons off; backbone; select ("
463 + selectioncom.toString() + "); cartoons; ");
464 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
470 public void evalStateCommand(String command)
473 if (lastCommand == null || !lastCommand.equals(command))
475 viewer.evalStringQuiet(command + "\n");
478 lastCommand = command;
482 * Sends a set of colour commands to the structure viewer
484 * @param colourBySequenceCommands
487 protected void colourBySequence(
488 StructureMappingcommandSet[] colourBySequenceCommands)
490 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
492 for (String cbyseq : cpdbbyseq.commands)
494 executeWhenReady(cbyseq);
506 protected StructureMappingcommandSet[] getColourBySequenceCommands(
507 String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
509 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
510 getSequence(), sr, viewPanel);
516 protected void executeWhenReady(String command)
518 evalStateCommand(command);
521 public void createImage(String file, String type, int quality)
523 System.out.println("JMOL CREATE IMAGE");
527 public String createImage(String fileName, String type,
528 Object textOrBytes, int quality)
530 System.out.println("JMOL CREATE IMAGE");
535 public String eval(String strEval)
537 // System.out.println(strEval);
538 // "# 'eval' is implemented only for the applet.";
542 // End StructureListener
543 // //////////////////////////
546 public float[][] functionXY(String functionName, int x, int y)
552 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
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 .println("jmolBinding: Using local file string from Jmol: "
629 if (filePath.indexOf("/file:") != -1)
631 // applet path with docroot - discard as format won't match pdbfile
635 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
638 for (int i = 1; i < viewer.ms.mc; i++)
640 m = viewer.ms.getModelFileName(i);
646 filePath = new File(m).getAbsolutePath();
647 } catch (AccessControlException x)
649 // usually not allowed to do this in applet, so keep raw handle
650 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
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;
697 * map from string to applet
700 public Map<String, Object> getRegistryInfo()
702 // TODO Auto-generated method stub
708 // ///////////////////////////////
709 // JmolStatusListener
711 public void handlePopupMenu(int x, int y)
713 // jmolpopup.show(x, y);
714 // jmolpopup.jpiShow(x, y);
718 * Highlight zero, one or more atoms on the structure
721 public void highlightAtoms(List<AtomSpec> atoms)
725 if (resetLastRes.length() > 0)
727 viewer.evalStringQuiet(resetLastRes.toString());
728 resetLastRes.setLength(0);
730 for (AtomSpec atom : atoms)
732 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
733 atom.getChain(), atom.getPdbFile());
739 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
742 if (modelFileNames == null)
747 // look up file model number for this pdbfile
749 // may need to adjust for URLencoding here - we don't worry about that yet.
750 while (mdlNum < modelFileNames.length
751 && !pdbfile.equals(modelFileNames[mdlNum]))
755 if (mdlNum == modelFileNames.length)
762 StringBuilder cmd = new StringBuilder(64);
763 cmd.append("select " + pdbResNum); // +modelNum
765 resetLastRes.append("select " + pdbResNum); // +modelNum
768 resetLastRes.append(":");
769 if (!chain.equals(" "))
772 resetLastRes.append(chain);
775 cmd.append(" /" + (mdlNum + 1));
776 resetLastRes.append("/" + (mdlNum + 1));
778 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
780 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
781 + " and not hetero; spacefill 0;");
783 cmd.append("spacefill 200;select none");
785 viewer.evalStringQuiet(cmd.toString());
790 boolean debug = true;
792 private void jmolHistory(boolean enable)
794 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
797 public void loadInline(String string)
801 // viewer.loadInline(strModel, isAppend);
803 // construct fake fullPathName and fileName so we can identify the file
805 // Then, construct pass a reader for the string to Jmol.
806 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
807 // fileName, null, reader, false, null, null, 0);
808 viewer.openStringInline(string);
811 public void mouseOverStructure(int atomIndex, String strInfo)
814 int alocsep = strInfo.indexOf("^");
815 int mdlSep = strInfo.indexOf("/");
816 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
818 if (chainSeparator == -1)
820 chainSeparator = strInfo.indexOf(".");
821 if (mdlSep > -1 && mdlSep < chainSeparator)
823 chainSeparator1 = chainSeparator;
824 chainSeparator = mdlSep;
827 // handle insertion codes
830 pdbResNum = Integer.parseInt(strInfo.substring(
831 strInfo.indexOf("]") + 1, alocsep));
836 pdbResNum = Integer.parseInt(strInfo.substring(
837 strInfo.indexOf("]") + 1, chainSeparator));
841 if (strInfo.indexOf(":") > -1)
843 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
844 strInfo.indexOf("."));
851 String pdbfilename = modelFileNames[frameNo]; // default is first or current
855 if (chainSeparator1 == -1)
857 chainSeparator1 = strInfo.indexOf(".", mdlSep);
859 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
860 chainSeparator1) : strInfo.substring(mdlSep + 1);
863 // recover PDB filename for the model hovered over.
864 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
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, String strData)
909 * this implements the toggle label behaviour copied from the original
910 * structure viewer, MCView
914 System.err.println("Ignoring additional pick data string " + strData);
916 int chainSeparator = strInfo.indexOf(":");
918 if (chainSeparator == -1)
920 chainSeparator = strInfo.indexOf(".");
923 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
925 String mdlString = "";
926 if ((p = strInfo.indexOf(":")) > -1)
928 picked += strInfo.substring(p, strInfo.indexOf("."));
931 if ((p = strInfo.indexOf("/")) > -1)
933 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
935 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
939 if (!atomsPicked.contains(picked))
941 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
942 atomsPicked.addElement(picked);
946 viewer.evalString("select " + picked + ";label off");
947 atomsPicked.removeElement(picked);
950 // TODO: in application this happens
952 // if (scriptWindow != null)
954 // scriptWindow.sendConsoleMessage(strInfo);
955 // scriptWindow.sendConsoleMessage("\n");
961 public void notifyCallback(CBK type, Object[] data)
968 notifyFileLoaded((String) data[1], (String) data[2],
969 (String) data[3], (String) data[4],
970 ((Integer) data[5]).intValue());
974 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
976 // also highlight in alignment
978 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
982 notifyScriptTermination((String) data[2],
983 ((Integer) data[3]).intValue());
986 sendConsoleEcho((String) data[1]);
989 sendConsoleMessage((data == null) ? ((String) null)
993 // System.err.println("Ignoring error callback.");
1003 System.err.println("Unhandled callback " + type + " "
1004 + data[1].toString());
1007 } catch (Exception e)
1009 System.err.println("Squashed Jmol callback handler error:");
1010 e.printStackTrace();
1015 public boolean notifyEnabled(CBK callbackPick)
1017 switch (callbackPick)
1033 // incremented every time a load notification is successfully handled -
1034 // lightweight mechanism for other threads to detect when they can start
1035 // referrring to new structures.
1036 private long loadNotifiesHandled = 0;
1038 public long getLoadNotifiesHandled()
1040 return loadNotifiesHandled;
1043 public void notifyFileLoaded(String fullPathName, String fileName2,
1044 String modelName, String errorMsg, int modelParts)
1046 if (errorMsg != null)
1048 fileLoadingError = errorMsg;
1052 // TODO: deal sensibly with models loaded inLine:
1053 // modelName will be null, as will fullPathName.
1055 // the rest of this routine ignores the arguments, and simply interrogates
1056 // the Jmol view to find out what structures it contains, and adds them to
1057 // the structure selection manager.
1058 fileLoadingError = null;
1059 String[] oldmodels = modelFileNames;
1060 modelFileNames = null;
1061 chainNames = new ArrayList<String>();
1062 chainFile = new Hashtable<String, String>();
1063 boolean notifyLoaded = false;
1064 String[] modelfilenames = getStructureFiles();
1065 // first check if we've lost any structures
1066 if (oldmodels != null && oldmodels.length > 0)
1069 for (int i = 0; i < oldmodels.length; i++)
1071 for (int n = 0; n < modelfilenames.length; n++)
1073 if (modelfilenames[n] == oldmodels[i])
1075 oldmodels[i] = null;
1079 if (oldmodels[i] != null)
1086 String[] oldmfn = new String[oldm];
1088 for (int i = 0; i < oldmodels.length; i++)
1090 if (oldmodels[i] != null)
1092 oldmfn[oldm++] = oldmodels[i];
1095 // deregister the Jmol instance for these structures - we'll add
1096 // ourselves again at the end for the current structure set.
1097 getSsm().removeStructureViewerListener(this, oldmfn);
1100 refreshPdbEntries();
1101 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1103 String fileName = modelfilenames[modelnum];
1104 boolean foundEntry = false;
1105 StructureFile pdb = null;
1106 String pdbfile = null;
1107 // model was probably loaded inline - so check the pdb file hashcode
1110 // calculate essential attributes for the pdb data imported inline.
1111 // prolly need to resolve modelnumber properly - for now just use our
1113 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1116 // search pdbentries and sequences to find correct pdbentry for this
1118 for (int pe = 0; pe < getPdbCount(); pe++)
1120 boolean matches = false;
1121 addSequence(pe, getSequence()[pe]);
1122 if (fileName == null)
1125 // see JAL-623 - need method of matching pasted data up
1127 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1128 pdbfile, DataSourceType.PASTE);
1129 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1136 File fl = new File(getPdbEntry(pe).getFile());
1137 matches = fl.equals(new File(fileName));
1141 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1144 // to be tested. See mantis bug
1145 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1146 DataSourceType protocol = DataSourceType.URL;
1151 protocol = DataSourceType.FILE;
1153 } catch (Exception e)
1158 // Explicitly map to the filename used by Jmol ;
1159 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1160 fileName, protocol);
1161 // pdbentry[pe].getFile(), protocol);
1167 // add an entry for every chain in the model
1168 for (int i = 0; i < pdb.getChains().size(); i++)
1170 String chid = new String(pdb.getId() + ":"
1171 + pdb.getChains().elementAt(i).id);
1172 chainFile.put(chid, fileName);
1173 chainNames.add(chid);
1175 notifyLoaded = true;
1179 if (!foundEntry && associateNewStructs)
1181 // this is a foreign pdb file that jalview doesn't know about - add
1182 // it to the dataset and try to find a home - either on a matching
1183 // sequence or as a new sequence.
1184 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1186 // parse pdb file into a chain, etc.
1187 // locate best match for pdb in associated views and add mapping to
1189 // if properly registered then
1190 notifyLoaded = true;
1195 // so finally, update the jmol bits and pieces
1196 // if (jmolpopup != null)
1198 // // potential for deadlock here:
1199 // // jmolpopup.updateComputedMenus();
1201 if (!isLoadingFromArchive())
1203 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1205 // register ourselves as a listener and notify the gui that it needs to
1207 getSsm().addStructureViewerListener(this);
1210 FeatureRenderer fr = getFeatureRenderer(null);
1216 loadNotifiesHandled++;
1218 setLoadingFromArchive(false);
1222 public List<String> getChainNames()
1227 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1229 notifyAtomPicked(iatom, strMeasure, null);
1232 public abstract void notifyScriptTermination(String strStatus,
1236 * display a message echoed from the jmol viewer
1240 public abstract void sendConsoleEcho(String strEcho); /*
1241 * { showConsole(true);
1243 * history.append("\n" +
1247 // /End JmolStatusListener
1248 // /////////////////////////////
1252 * status message - usually the response received after a script
1255 public abstract void sendConsoleMessage(String strStatus);
1258 public void setCallbackFunction(String callbackType,
1259 String callbackFunction)
1261 System.err.println("Ignoring set-callback request to associate "
1262 + callbackType + " with function " + callbackFunction);
1267 public void setJalviewColourScheme(ColourSchemeI cs)
1269 colourBySequence = false;
1277 StringBuilder command = new StringBuilder(128);
1278 command.append("select *;color white;");
1279 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1281 for (String resName : residueSet)
1283 char res = resName.length() == 3 ? ResidueProperties
1284 .getSingleCharacterCode(resName) : resName.charAt(0);
1285 Color col = cs.findColour(res, 0, null, null, 0f);
1286 command.append("select " + resName + ";color[" + col.getRed() + ","
1287 + col.getGreen() + "," + col.getBlue() + "];");
1290 evalStateCommand(command.toString());
1294 public void showHelp()
1296 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1300 * open the URL somehow
1304 public abstract void showUrl(String url, String target);
1307 * called when the binding thinks the UI needs to be refreshed after a Jmol
1308 * state change. this could be because structures were loaded, or because an
1309 * error has occured.
1311 public abstract void refreshGUI();
1314 * called to show or hide the associated console window container.
1318 public abstract void showConsole(boolean show);
1321 * @param renderPanel
1323 * - when true will initialise jmol's file IO system (should be false
1324 * in applet context)
1326 * @param documentBase
1328 * @param commandOptions
1330 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1331 String htmlName, URL documentBase, URL codeBase,
1332 String commandOptions)
1334 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1335 codeBase, commandOptions, null, null);
1340 * @param renderPanel
1342 * - when true will initialise jmol's file IO system (should be false
1343 * in applet context)
1345 * @param documentBase
1347 * @param commandOptions
1348 * @param consolePanel
1349 * - panel to contain Jmol console
1350 * @param buttonsToShow
1351 * - buttons to show on the console, in ordr
1353 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1354 String htmlName, URL documentBase, URL codeBase,
1355 String commandOptions, final Container consolePanel,
1356 String buttonsToShow)
1358 if (commandOptions == null)
1360 commandOptions = "";
1362 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1363 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1364 + ((Object) this).toString(), documentBase, codeBase,
1365 commandOptions, this);
1367 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1369 console = createJmolConsole(consolePanel, buttonsToShow);
1370 if (consolePanel != null)
1372 consolePanel.addComponentListener(this);
1378 protected abstract JmolAppConsoleInterface createJmolConsole(
1379 Container consolePanel, String buttonsToShow);
1381 protected org.jmol.api.JmolAppConsoleInterface console = null;
1384 public void setBackgroundColour(java.awt.Color col)
1387 viewer.evalStringQuiet("background [" + col.getRed() + ","
1388 + col.getGreen() + "," + col.getBlue() + "];");
1393 public int[] resizeInnerPanel(String data)
1395 // Jalview doesn't honour resize panel requests
1402 protected void closeConsole()
1404 if (console != null)
1408 console.setVisible(false);
1411 } catch (Exception x)
1420 * ComponentListener method
1423 public void componentMoved(ComponentEvent e)
1428 * ComponentListener method
1431 public void componentResized(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentShown(ComponentEvent e)
1445 * ComponentListener method
1448 public void componentHidden(ComponentEvent e)