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.gui.IProgressIndicator;
31 import jalview.io.DataSourceType;
32 import jalview.io.StructureFile;
33 import jalview.schemes.ColourSchemeI;
34 import jalview.schemes.ResidueProperties;
35 import jalview.structure.AtomSpec;
36 import jalview.structure.StructureMappingcommandSet;
37 import jalview.structure.StructureSelectionManager;
38 import jalview.structures.models.AAStructureBindingModel;
39 import jalview.util.MessageManager;
41 import java.awt.Color;
42 import java.awt.Container;
43 import java.awt.event.ComponentEvent;
44 import java.awt.event.ComponentListener;
47 import java.security.AccessControlException;
48 import java.util.ArrayList;
49 import java.util.BitSet;
50 import java.util.Hashtable;
51 import java.util.List;
53 import java.util.Vector;
55 import org.jmol.adapter.smarter.SmarterJmolAdapter;
56 import org.jmol.api.JmolAppConsoleInterface;
57 import org.jmol.api.JmolSelectionListener;
58 import org.jmol.api.JmolStatusListener;
59 import org.jmol.api.JmolViewer;
60 import org.jmol.c.CBK;
61 import org.jmol.script.T;
62 import org.jmol.viewer.Viewer;
64 public abstract class JalviewJmolBinding extends AAStructureBindingModel
65 implements JmolStatusListener, JmolSelectionListener,
68 boolean allChainsSelected = false;
71 * when true, try to search the associated datamodel for sequences that are
72 * associated with any unknown structures in the Jmol view.
74 private boolean associateNewStructs = false;
76 Vector<String> atomsPicked = new Vector<>();
78 private List<String> chainNames;
80 Hashtable<String, String> chainFile;
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?
96 StringBuffer resetLastRes = new StringBuffer();
100 public JalviewJmolBinding(StructureSelectionManager ssm,
101 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
102 DataSourceType protocol)
104 super(ssm, pdbentry, sequenceIs, protocol);
106 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
107 * "jalviewJmol", ap.av.applet .getDocumentBase(),
108 * ap.av.applet.getCodeBase(), "", this);
110 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
114 public JalviewJmolBinding(StructureSelectionManager ssm,
115 SequenceI[][] seqs, Viewer theViewer)
120 viewer.setJmolStatusListener(this);
121 viewer.addSelectionListener(this);
125 * construct a title string for the viewer window based on the data jalview
130 public String getViewerTitle()
132 return getViewerTitle("Jmol", true);
136 * prepare the view for a given set of models/chains. chainList contains
137 * strings of the form 'pdbfilename:Chaincode'
140 * list of chains to make visible
142 public void centerViewer(Vector<String> chainList)
144 StringBuilder cmd = new StringBuilder(128);
146 for (String lbl : chainList)
152 mlength = lbl.indexOf(":", p);
153 } while (p < mlength && mlength < (lbl.length() - 2));
154 // TODO: lookup each pdb id and recover proper model number for it.
155 cmd.append(":" + lbl.substring(mlength + 1) + " /"
156 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
158 if (cmd.length() > 0)
160 cmd.setLength(cmd.length() - 4);
162 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
165 public void closeViewer()
167 // remove listeners for all structures in viewer
168 getSsm().removeStructureViewerListener(this, this.getStructureFiles());
172 releaseUIResources();
176 public void colourByChain()
178 colourBySequence = false;
179 // TODO: colour by chain should colour each chain distinctly across all
181 // TODO: http://issues.jalview.org/browse/JAL-628
182 evalStateCommand("select *;color chain");
186 public void colourByCharge()
188 colourBySequence = false;
189 evalStateCommand("select *;color white;select ASP,GLU;color red;"
190 + "select LYS,ARG;color blue;select CYS;color yellow");
194 * superpose the structures associated with sequences in the alignment
195 * according to their corresponding positions.
197 public void superposeStructures(AlignmentI alignment)
199 superposeStructures(alignment, -1, null);
203 * superpose the structures associated with sequences in the alignment
204 * according to their corresponding positions. ded)
206 * @param refStructure
207 * - select which pdb file to use as reference (default is -1 - the
208 * first structure in the alignment)
210 public void superposeStructures(AlignmentI alignment, int refStructure)
212 superposeStructures(alignment, refStructure, null);
216 * superpose the structures associated with sequences in the alignment
217 * according to their corresponding positions. ded)
219 * @param refStructure
220 * - select which pdb file to use as reference (default is -1 - the
221 * first structure in the alignment)
225 public void superposeStructures(AlignmentI alignment, int refStructure,
226 HiddenColumns hiddenCols)
228 superposeStructures(new AlignmentI[] { alignment },
230 { refStructure }, new HiddenColumns[] { hiddenCols });
237 public String superposeStructures(AlignmentI[] _alignment,
238 int[] _refStructure, HiddenColumns[] _hiddenCols)
240 while (viewer.isScriptExecuting())
245 } catch (InterruptedException i)
251 * get the distinct structure files modelled
252 * (a file with multiple chains may map to multiple sequences)
254 String[] files = getStructureFiles();
255 if (!waitForFileLoad(files))
260 StringBuilder selectioncom = new StringBuilder(256);
261 // In principle - nSeconds specifies the speed of animation for each
262 // superposition - but is seems to behave weirdly, so we don't specify it.
263 String nSeconds = " ";
264 if (files.length > 10)
266 nSeconds = " 0.005 ";
270 nSeconds = " " + (2.0 / files.length) + " ";
271 // if (nSeconds).substring(0,5)+" ";
274 // see JAL-1345 - should really automatically turn off the animation for
275 // large numbers of structures, but Jmol doesn't seem to allow that.
277 // union of all aligned positions are collected together.
278 for (int a = 0; a < _alignment.length; a++)
280 int refStructure = _refStructure[a];
281 AlignmentI alignment = _alignment[a];
282 HiddenColumns hiddenCols = _hiddenCols[a];
283 if (a > 0 && selectioncom.length() > 0 && !selectioncom
284 .substring(selectioncom.length() - 1).equals("|"))
286 selectioncom.append("|");
288 // process this alignment
289 if (refStructure >= files.length)
292 "Invalid reference structure value " + refStructure);
297 * 'matched' bit j will be set for visible alignment columns j where
298 * all sequences have a residue with a mapping to the PDB structure
300 BitSet matched = new BitSet();
301 for (int m = 0; m < alignment.getWidth(); m++)
303 if (hiddenCols == null || hiddenCols.isVisible(m))
309 SuperposeData[] structures = new SuperposeData[files.length];
310 for (int f = 0; f < files.length; f++)
312 structures[f] = new SuperposeData(alignment.getWidth());
316 * Calculate the superposable alignment columns ('matched'), and the
317 * corresponding structure residue positions (structures.pdbResNo)
319 int candidateRefStructure = findSuperposableResidues(alignment,
320 matched, structures);
321 if (refStructure < 0)
324 * If no reference structure was specified, pick the first one that has
325 * a mapping in the alignment
327 refStructure = candidateRefStructure;
330 String[] selcom = new String[files.length];
331 int nmatched = matched.cardinality();
334 return (MessageManager.formatMessage("label.insufficient_residues",
339 * generate select statements to select regions to superimpose structures
342 // TODO extract method to construct selection statements
343 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
345 String chainCd = ":" + structures[pdbfnum].chain;
348 StringBuilder molsel = new StringBuilder();
351 int nextColumnMatch = matched.nextSetBit(0);
352 while (nextColumnMatch != -1)
354 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
355 if (lpos != pdbResNo - 1)
361 molsel.append(chainCd);
368 // continuous run - and lpos >-1
371 // at the beginning, so add dash
378 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
381 * add final selection phrase
386 molsel.append(chainCd);
389 if (molsel.length() > 1)
391 selcom[pdbfnum] = molsel.toString();
392 selectioncom.append("((");
393 selectioncom.append(selcom[pdbfnum].substring(1,
394 selcom[pdbfnum].length() - 1));
395 selectioncom.append(" )& ");
396 selectioncom.append(pdbfnum + 1);
397 selectioncom.append(".1)");
398 if (pdbfnum < files.length - 1)
400 selectioncom.append("|");
405 selcom[pdbfnum] = null;
409 StringBuilder command = new StringBuilder(256);
410 // command.append("set spinFps 10;\n");
412 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
414 if (pdbfnum == refStructure || selcom[pdbfnum] == null
415 || selcom[refStructure] == null)
419 command.append("echo ");
420 command.append("\"Superposing (");
421 command.append(structures[pdbfnum].pdbId);
422 command.append(") against reference (");
423 command.append(structures[refStructure].pdbId);
424 command.append(")\";\ncompare " + nSeconds);
426 command.append(Integer.toString(1 + pdbfnum));
427 command.append(".1} {");
428 command.append(Integer.toString(1 + refStructure));
429 // conformation=1 excludes alternate locations for CA (JAL-1757)
431 ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
433 // for (int s = 0; s < 2; s++)
435 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
437 command.append(selcom[pdbfnum]);
438 command.append(selcom[refStructure]);
439 command.append(" ROTATE TRANSLATE;\n");
441 if (selectioncom.length() > 0)
443 // TODO is performing selectioncom redundant here? is done later on
444 // System.out.println("Select regions:\n" + selectioncom.toString());
445 evalStateCommand("select *; cartoons off; backbone; select ("
446 + selectioncom.toString() + "); cartoons; ");
447 // selcom.append("; ribbons; ");
448 String cmdString = command.toString();
449 // System.out.println("Superimpose command(s):\n" + cmdString);
451 evalStateCommand(cmdString);
454 if (selectioncom.length() > 0)
455 {// finally, mark all regions that were superposed.
456 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
458 selectioncom.setLength(selectioncom.length() - 1);
460 // System.out.println("Select regions:\n" + selectioncom.toString());
461 evalStateCommand("select *; cartoons off; backbone; select ("
462 + selectioncom.toString() + "); cartoons; ");
463 // evalStateCommand("select *; backbone; select "+selcom.toString()+";
464 // 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,
555 // TODO Auto-generated method stub
559 public Color getColour(int atomIndex, int pdbResNum, String chain,
562 if (getModelNum(pdbfile) < 0)
566 // TODO: verify atomIndex is selecting correct model.
567 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
568 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
569 return new Color(colour);
573 * instruct the Jalview binding to update the pdbentries vector if necessary
574 * prior to matching the jmol view's contents to the list of structure files
575 * Jalview knows about.
577 public abstract void refreshPdbEntries();
579 private int getModelNum(String modelFileName)
581 String[] mfn = getStructureFiles();
586 for (int i = 0; i < mfn.length; i++)
588 if (mfn[i].equalsIgnoreCase(modelFileName))
597 * map between index of model filename returned from getPdbFile and the first
598 * index of models from this file in the viewer. Note - this is not trimmed -
599 * use getPdbFile to get number of unique models.
601 private int _modelFileNameMap[];
603 // ////////////////////////////////
604 // /StructureListener
606 public synchronized String[] getPdbFilex()
610 return new String[0];
612 if (modelFileNames == null)
614 List<String> mset = new ArrayList<>();
615 _modelFileNameMap = new int[viewer.ms.mc];
616 String m = viewer.ms.getModelFileName(0);
622 filePath = new File(m).getAbsolutePath();
623 } catch (AccessControlException x)
625 // usually not allowed to do this in applet
627 "jmolBinding: Using local file string from Jmol: " + m);
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
656 * add this model unless it is read from a structure file we have
657 * already seen (example: 2MJW is an NMR structure with 10 models)
659 if (!mset.contains(filePath))
662 _modelFileNameMap[j] = i; // record the model index for the filename
666 modelFileNames = mset.toArray(new String[mset.size()]);
668 return modelFileNames;
672 public synchronized String[] getStructureFiles()
674 List<String> mset = new ArrayList<>();
677 return new String[0];
680 if (modelFileNames == null)
682 int modelCount = viewer.ms.mc;
683 String filePath = null;
684 for (int i = 0; i < modelCount; ++i)
686 filePath = viewer.ms.getModelFileName(i);
687 if (!mset.contains(filePath))
692 modelFileNames = mset.toArray(new String[mset.size()]);
695 return modelFileNames;
699 * map from string to applet
702 public Map<String, Object> getRegistryInfo()
704 // 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(
831 strInfo.substring(strInfo.indexOf("]") + 1, alocsep));
836 pdbResNum = Integer.parseInt(
837 strInfo.substring(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)
860 ? strInfo.substring(mdlSep + 1, chainSeparator1)
861 : strInfo.substring(mdlSep + 1);
864 // recover PDB filename for the model hovered over.
865 int _mp = _modelFileNameMap.length - 1,
866 mnumber = new Integer(mdlId).intValue() - 1;
867 while (mnumber < _modelFileNameMap[_mp])
871 pdbfilename = modelFileNames[_mp];
872 if (pdbfilename == null)
874 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
878 } catch (Exception e)
883 if (lastMessage == null || !lastMessage.equals(strInfo))
885 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
888 lastMessage = strInfo;
891 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
895 System.err.println("Ignoring additional hover info: " + data
896 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
898 mouseOverStructure(atomIndex, strInfo);
902 * { if (history != null && strStatus != null &&
903 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
907 public void notifyAtomPicked(int atomIndex, String strInfo,
911 * this implements the toggle label behaviour copied from the original
912 * structure viewer, MCView
916 System.err.println("Ignoring additional pick data string " + strData);
918 int chainSeparator = strInfo.indexOf(":");
920 if (chainSeparator == -1)
922 chainSeparator = strInfo.indexOf(".");
925 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
927 String mdlString = "";
928 if ((p = strInfo.indexOf(":")) > -1)
930 picked += strInfo.substring(p, strInfo.indexOf("."));
933 if ((p = strInfo.indexOf("/")) > -1)
935 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
937 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
941 if (!atomsPicked.contains(picked))
943 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
944 atomsPicked.addElement(picked);
948 viewer.evalString("select " + picked + ";label off");
949 atomsPicked.removeElement(picked);
952 // TODO: in application this happens
954 // if (scriptWindow != null)
956 // scriptWindow.sendConsoleMessage(strInfo);
957 // scriptWindow.sendConsoleMessage("\n");
963 public void notifyCallback(CBK type, Object[] data)
970 notifyFileLoaded((String) data[1], (String) data[2],
971 (String) data[3], (String) data[4],
972 ((Integer) data[5]).intValue());
976 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
978 // also highlight in alignment
979 // deliberate fall through
981 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
985 notifyScriptTermination((String) data[2],
986 ((Integer) data[3]).intValue());
989 sendConsoleEcho((String) data[1]);
993 (data == null) ? ((String) null) : (String) data[1]);
996 // System.err.println("Ignoring error callback.");
1007 "Unhandled callback " + type + " " + data[1].toString());
1010 } catch (Exception e)
1012 System.err.println("Squashed Jmol callback handler error:");
1013 e.printStackTrace();
1018 public boolean notifyEnabled(CBK callbackPick)
1020 switch (callbackPick)
1036 // incremented every time a load notification is successfully handled -
1037 // lightweight mechanism for other threads to detect when they can start
1038 // referrring to new structures.
1039 private long loadNotifiesHandled = 0;
1041 public long getLoadNotifiesHandled()
1043 return loadNotifiesHandled;
1046 public void notifyFileLoaded(String fullPathName, String fileName2,
1047 String modelName, String errorMsg, int modelParts)
1049 if (errorMsg != null)
1051 fileLoadingError = errorMsg;
1055 // TODO: deal sensibly with models loaded inLine:
1056 // modelName will be null, as will fullPathName.
1058 // the rest of this routine ignores the arguments, and simply interrogates
1059 // the Jmol view to find out what structures it contains, and adds them to
1060 // the structure selection manager.
1061 fileLoadingError = null;
1062 String[] oldmodels = modelFileNames;
1063 modelFileNames = null;
1064 chainNames = new ArrayList<>();
1065 chainFile = new Hashtable<>();
1066 boolean notifyLoaded = false;
1067 String[] modelfilenames = getStructureFiles();
1068 // first check if we've lost any structures
1069 if (oldmodels != null && oldmodels.length > 0)
1072 for (int i = 0; i < oldmodels.length; i++)
1074 for (int n = 0; n < modelfilenames.length; n++)
1076 if (modelfilenames[n] == oldmodels[i])
1078 oldmodels[i] = null;
1082 if (oldmodels[i] != null)
1089 String[] oldmfn = new String[oldm];
1091 for (int i = 0; i < oldmodels.length; i++)
1093 if (oldmodels[i] != null)
1095 oldmfn[oldm++] = oldmodels[i];
1098 // deregister the Jmol instance for these structures - we'll add
1099 // ourselves again at the end for the current structure set.
1100 getSsm().removeStructureViewerListener(this, oldmfn);
1103 refreshPdbEntries();
1104 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1106 String fileName = modelfilenames[modelnum];
1107 boolean foundEntry = false;
1108 StructureFile pdb = null;
1109 String pdbfile = null;
1110 // model was probably loaded inline - so check the pdb file hashcode
1113 // calculate essential attributes for the pdb data imported inline.
1114 // prolly need to resolve modelnumber properly - for now just use our
1116 pdbfile = viewer.getData(
1117 "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB");
1119 // search pdbentries and sequences to find correct pdbentry for this
1121 for (int pe = 0; pe < getPdbCount(); pe++)
1123 boolean matches = false;
1124 addSequence(pe, getSequence()[pe]);
1125 if (fileName == null)
1128 // see JAL-623 - need method of matching pasted data up
1130 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1131 pdbfile, DataSourceType.PASTE,
1132 getIProgressIndicator());
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, getIProgressIndicator());
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 protected abstract IProgressIndicator getIProgressIndicator();
1234 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1236 notifyAtomPicked(iatom, strMeasure, null);
1239 public abstract void notifyScriptTermination(String strStatus,
1243 * display a message echoed from the jmol viewer
1247 public abstract void sendConsoleEcho(String strEcho); /*
1248 * { showConsole(true);
1250 * history.append("\n" +
1254 // /End JmolStatusListener
1255 // /////////////////////////////
1259 * status message - usually the response received after a script
1262 public abstract void sendConsoleMessage(String strStatus);
1265 public void setCallbackFunction(String callbackType,
1266 String callbackFunction)
1268 System.err.println("Ignoring set-callback request to associate "
1269 + callbackType + " with function " + callbackFunction);
1274 public void setJalviewColourScheme(ColourSchemeI cs)
1276 colourBySequence = false;
1284 StringBuilder command = new StringBuilder(128);
1285 command.append("select *;color white;");
1286 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1288 for (String resName : residueSet)
1290 char res = resName.length() == 3
1291 ? ResidueProperties.getSingleCharacterCode(resName)
1292 : resName.charAt(0);
1293 Color col = cs.findColour(res, 0, null, null, 0f);
1294 command.append("select " + resName + ";color[" + col.getRed() + ","
1295 + col.getGreen() + "," + col.getBlue() + "];");
1298 evalStateCommand(command.toString());
1302 public void showHelp()
1304 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1308 * open the URL somehow
1312 public abstract void showUrl(String url, String target);
1315 * called when the binding thinks the UI needs to be refreshed after a Jmol
1316 * state change. this could be because structures were loaded, or because an
1317 * error has occured.
1319 public abstract void refreshGUI();
1322 * called to show or hide the associated console window container.
1326 public abstract void showConsole(boolean show);
1329 * @param renderPanel
1331 * - when true will initialise jmol's file IO system (should be false
1332 * in applet context)
1334 * @param documentBase
1336 * @param commandOptions
1338 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1339 String htmlName, URL documentBase, URL codeBase,
1340 String commandOptions)
1342 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1343 codeBase, commandOptions, null, null);
1348 * @param renderPanel
1350 * - when true will initialise jmol's file IO system (should be false
1351 * in applet context)
1353 * @param documentBase
1355 * @param commandOptions
1356 * @param consolePanel
1357 * - panel to contain Jmol console
1358 * @param buttonsToShow
1359 * - buttons to show on the console, in ordr
1361 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1362 String htmlName, URL documentBase, URL codeBase,
1363 String commandOptions, final Container consolePanel,
1364 String buttonsToShow)
1366 if (commandOptions == null)
1368 commandOptions = "";
1370 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1371 (jmolfileio ? new SmarterJmolAdapter() : null),
1372 htmlName + ((Object) this).toString(), documentBase, codeBase,
1373 commandOptions, this);
1375 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1377 console = createJmolConsole(consolePanel, buttonsToShow);
1378 if (consolePanel != null)
1380 consolePanel.addComponentListener(this);
1386 protected abstract JmolAppConsoleInterface createJmolConsole(
1387 Container consolePanel, String buttonsToShow);
1389 protected org.jmol.api.JmolAppConsoleInterface console = null;
1392 public void setBackgroundColour(java.awt.Color col)
1395 viewer.evalStringQuiet("background [" + col.getRed() + ","
1396 + col.getGreen() + "," + col.getBlue() + "];");
1401 public int[] resizeInnerPanel(String data)
1403 // Jalview doesn't honour resize panel requests
1410 protected void closeConsole()
1412 if (console != null)
1416 console.setVisible(false);
1419 } catch (Exception x)
1428 * ComponentListener method
1431 public void componentMoved(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentResized(ComponentEvent e)
1444 * ComponentListener method
1447 public void componentShown(ComponentEvent e)
1453 * ComponentListener method
1456 public void componentHidden(ComponentEvent e)