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.FeatureRenderer;
24 import jalview.api.SequenceRenderer;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.ColumnSelection;
27 import jalview.datamodel.PDBEntry;
28 import jalview.datamodel.SequenceI;
29 import jalview.io.DataSourceType;
30 import jalview.io.StructureFile;
31 import jalview.schemes.ColourSchemeI;
32 import jalview.schemes.ResidueProperties;
33 import jalview.structure.AtomSpec;
34 import jalview.structure.StructureMappingcommandSet;
35 import jalview.structure.StructureSelectionManager;
36 import jalview.structures.models.AAStructureBindingModel;
38 import java.awt.Color;
39 import java.awt.Container;
40 import java.awt.event.ComponentEvent;
41 import java.awt.event.ComponentListener;
44 import java.security.AccessControlException;
45 import java.util.ArrayList;
46 import java.util.Hashtable;
47 import java.util.List;
49 import java.util.Vector;
51 import org.jmol.adapter.smarter.SmarterJmolAdapter;
52 import org.jmol.api.JmolAppConsoleInterface;
53 import org.jmol.api.JmolSelectionListener;
54 import org.jmol.api.JmolStatusListener;
55 import org.jmol.api.JmolViewer;
56 import org.jmol.c.CBK;
57 import org.jmol.script.T;
58 import org.jmol.viewer.Viewer;
60 public abstract class JalviewJmolBinding extends AAStructureBindingModel
61 implements JmolStatusListener, JmolSelectionListener,
64 boolean allChainsSelected = false;
67 * when true, try to search the associated datamodel for sequences that are
68 * associated with any unknown structures in the Jmol view.
70 private boolean associateNewStructs = false;
72 Vector<String> atomsPicked = new Vector<String>();
74 private List<String> chainNames;
76 Hashtable<String, String> chainFile;
79 * the default or current model displayed if the model cannot be identified
80 * from the selection message
84 // protected JmolGenericPopup jmolpopup; // not used - remove?
92 StringBuffer resetLastRes = new StringBuffer();
96 public JalviewJmolBinding(StructureSelectionManager ssm,
97 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
98 DataSourceType protocol)
100 super(ssm, pdbentry, sequenceIs, protocol);
102 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
103 * "jalviewJmol", ap.av.applet .getDocumentBase(),
104 * ap.av.applet.getCodeBase(), "", this);
106 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
110 public JalviewJmolBinding(StructureSelectionManager ssm,
111 SequenceI[][] seqs, Viewer theViewer)
116 viewer.setJmolStatusListener(this);
117 viewer.addSelectionListener(this);
121 * construct a title string for the viewer window based on the data jalview
126 public String getViewerTitle()
128 return getViewerTitle("Jmol", true);
132 * prepare the view for a given set of models/chains. chainList contains
133 * strings of the form 'pdbfilename:Chaincode'
136 * list of chains to make visible
138 public void centerViewer(Vector<String> chainList)
140 StringBuilder cmd = new StringBuilder(128);
142 for (String lbl : chainList)
148 mlength = lbl.indexOf(":", p);
149 } while (p < mlength && mlength < (lbl.length() - 2));
150 // TODO: lookup each pdb id and recover proper model number for it.
151 cmd.append(":" + lbl.substring(mlength + 1) + " /"
152 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
154 if (cmd.length() > 0)
156 cmd.setLength(cmd.length() - 4);
158 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
161 public void closeViewer()
163 // remove listeners for all structures in viewer
164 getSsm().removeStructureViewerListener(this, this.getPdbFile());
168 releaseUIResources();
172 public void colourByChain()
174 colourBySequence = false;
175 // TODO: colour by chain should colour each chain distinctly across all
177 // TODO: http://issues.jalview.org/browse/JAL-628
178 evalStateCommand("select *;color chain");
182 public void colourByCharge()
184 colourBySequence = false;
185 evalStateCommand("select *;color white;select ASP,GLU;color red;"
186 + "select LYS,ARG;color blue;select CYS;color yellow");
190 * superpose the structures associated with sequences in the alignment
191 * according to their corresponding positions.
193 public void superposeStructures(AlignmentI alignment)
195 superposeStructures(alignment, -1, null);
199 * superpose the structures associated with sequences in the alignment
200 * according to their corresponding positions. ded)
202 * @param refStructure
203 * - select which pdb file to use as reference (default is -1 - the
204 * first structure in the alignment)
206 public void superposeStructures(AlignmentI alignment, int refStructure)
208 superposeStructures(alignment, refStructure, null);
212 * superpose the structures associated with sequences in the alignment
213 * according to their corresponding positions. ded)
215 * @param refStructure
216 * - select which pdb file to use as reference (default is -1 - the
217 * first structure in the alignment)
221 public void superposeStructures(AlignmentI alignment, int refStructure,
222 ColumnSelection hiddenCols)
224 superposeStructures(new AlignmentI[] { alignment },
225 new int[] { refStructure },
226 new ColumnSelection[] { hiddenCols });
230 * Construct and send a command to align structures against a reference
231 * structure, based on one or more sequence alignments
234 * an array of alignments to process
235 * @param _refStructure
236 * an array of corresponding reference structures (index into pdb
237 * file array); if a negative value is passed, the first PDB file
238 * mapped to an alignment sequence is used as the reference for
241 * an array of corresponding hidden columns for each alignment
244 public void superposeStructures(AlignmentI[] _alignment,
245 int[] _refStructure, ColumnSelection[] _hiddenCols)
247 while (viewer.isScriptExecuting())
252 } catch (InterruptedException i)
258 * get the distinct structure files modelled
259 * (a file with multiple chains may map to multiple sequences)
261 String[] files = getPdbFile();
262 if (!waitForFileLoad(files))
267 StringBuilder selectioncom = new StringBuilder(256);
268 // In principle - nSeconds specifies the speed of animation for each
269 // superposition - but is seems to behave weirdly, so we don't specify it.
270 String nSeconds = " ";
271 if (files.length > 10)
273 nSeconds = " 0.005 ";
277 nSeconds = " " + (2.0 / files.length) + " ";
278 // if (nSeconds).substring(0,5)+" ";
280 // see JAL-1345 - should really automatically turn off the animation for
281 // large numbers of structures, but Jmol doesn't seem to allow that.
283 // union of all aligned positions are collected together.
284 for (int a = 0; a < _alignment.length; a++)
286 int refStructure = _refStructure[a];
287 AlignmentI alignment = _alignment[a];
288 ColumnSelection hiddenCols = _hiddenCols[a];
290 && selectioncom.length() > 0
291 && !selectioncom.substring(selectioncom.length() - 1).equals(
294 selectioncom.append("|");
296 // process this alignment
297 if (refStructure >= files.length)
299 System.err.println("Invalid reference structure value "
305 * 'matched' array will hold 'true' for visible alignment columns where
306 * all sequences have a residue with a mapping to the PDB structure
308 // TODO could use a BitSet for matched
309 boolean matched[] = new boolean[alignment.getWidth()];
310 for (int m = 0; m < matched.length; m++)
312 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
315 SuperposeData[] structures = new SuperposeData[files.length];
316 for (int f = 0; f < files.length; f++)
318 structures[f] = new SuperposeData(alignment.getWidth());
322 * Calculate the superposable alignment columns ('matched'), and the
323 * corresponding structure residue positions (structures.pdbResNo)
325 int candidateRefStructure = findSuperposableResidues(alignment,
326 matched, structures);
327 if (refStructure < 0)
330 * If no reference structure was specified, pick the first one that has
331 * a mapping in the alignment
333 refStructure = candidateRefStructure;
336 String[] selcom = new String[files.length];
338 for (boolean b : matched)
347 // TODO: bail out here because superposition illdefined?
351 * generate select statements to select regions to superimpose structures
354 // TODO extract method to construct selection statements
355 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
357 String chainCd = ":" + structures[pdbfnum].chain;
360 StringBuilder molsel = new StringBuilder();
362 for (int r = 0; r < matched.length; r++)
366 int pdbResNo = structures[pdbfnum].pdbResNo[r];
367 if (lpos != pdbResNo - 1)
373 molsel.append(chainCd);
380 // continuous run - and lpos >-1
383 // at the beginning, so add dash
393 * add final selection phrase
398 molsel.append(chainCd);
401 if (molsel.length() > 1)
403 selcom[pdbfnum] = molsel.toString();
404 selectioncom.append("((");
405 selectioncom.append(selcom[pdbfnum].substring(1,
406 selcom[pdbfnum].length() - 1));
407 selectioncom.append(" )& ");
408 selectioncom.append(pdbfnum + 1);
409 selectioncom.append(".1)");
410 if (pdbfnum < files.length - 1)
412 selectioncom.append("|");
417 selcom[pdbfnum] = null;
421 StringBuilder command = new StringBuilder(256);
422 // command.append("set spinFps 10;\n");
424 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
426 if (pdbfnum == refStructure || selcom[pdbfnum] == null
427 || selcom[refStructure] == null)
431 command.append("echo ");
432 command.append("\"Superposing (");
433 command.append(structures[pdbfnum].pdbId);
434 command.append(") against reference (");
435 command.append(structures[refStructure].pdbId);
436 command.append(")\";\ncompare " + nSeconds);
438 command.append(Integer.toString(1 + pdbfnum));
439 command.append(".1} {");
440 command.append(Integer.toString(1 + refStructure));
441 // conformation=1 excludes alternate locations for CA (JAL-1757)
442 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
444 // for (int s = 0; s < 2; s++)
446 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
448 command.append(selcom[pdbfnum]);
449 command.append(selcom[refStructure]);
450 command.append(" ROTATE TRANSLATE;\n");
452 if (selectioncom.length() > 0)
454 // TODO is performing selectioncom redundant here? is done later on
455 // System.out.println("Select regions:\n" + selectioncom.toString());
456 evalStateCommand("select *; cartoons off; backbone; select ("
457 + selectioncom.toString() + "); cartoons; ");
458 // selcom.append("; ribbons; ");
459 String cmdString = command.toString();
460 // System.out.println("Superimpose command(s):\n" + cmdString);
462 evalStateCommand(cmdString);
465 if (selectioncom.length() > 0)
466 {// finally, mark all regions that were superposed.
467 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
469 selectioncom.setLength(selectioncom.length() - 1);
471 // System.out.println("Select regions:\n" + selectioncom.toString());
472 evalStateCommand("select *; cartoons off; backbone; select ("
473 + selectioncom.toString() + "); cartoons; ");
474 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
478 public void evalStateCommand(String command)
481 if (lastCommand == null || !lastCommand.equals(command))
483 viewer.evalStringQuiet(command + "\n");
486 lastCommand = command;
490 * Sends a set of colour commands to the structure viewer
492 * @param colourBySequenceCommands
495 protected void colourBySequence(
496 StructureMappingcommandSet[] colourBySequenceCommands)
498 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
500 for (String cbyseq : cpdbbyseq.commands)
502 executeWhenReady(cbyseq);
515 protected StructureMappingcommandSet[] getColourBySequenceCommands(
516 String[] files, SequenceRenderer sr, FeatureRenderer fr,
517 AlignmentI alignment)
519 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
520 getSequence(), sr, fr, alignment);
526 protected void executeWhenReady(String command)
528 evalStateCommand(command);
531 public void createImage(String file, String type, int quality)
533 System.out.println("JMOL CREATE IMAGE");
537 public String createImage(String fileName, String type,
538 Object textOrBytes, int quality)
540 System.out.println("JMOL CREATE IMAGE");
545 public String eval(String strEval)
547 // System.out.println(strEval);
548 // "# 'eval' is implemented only for the applet.";
552 // End StructureListener
553 // //////////////////////////
556 public float[][] functionXY(String functionName, int x, int y)
562 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
564 // TODO Auto-generated method stub
568 public Color getColour(int atomIndex, int pdbResNum, String chain,
571 if (getModelNum(pdbfile) < 0)
575 // TODO: verify atomIndex is selecting correct model.
576 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
577 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
578 return new Color(colour);
582 * instruct the Jalview binding to update the pdbentries vector if necessary
583 * prior to matching the jmol view's contents to the list of structure files
584 * Jalview knows about.
586 public abstract void refreshPdbEntries();
588 private int getModelNum(String modelFileName)
590 String[] mfn = getPdbFile();
595 for (int i = 0; i < mfn.length; i++)
597 if (mfn[i].equalsIgnoreCase(modelFileName))
606 * map between index of model filename returned from getPdbFile and the first
607 * index of models from this file in the viewer. Note - this is not trimmed -
608 * use getPdbFile to get number of unique models.
610 private int _modelFileNameMap[];
612 // ////////////////////////////////
613 // /StructureListener
615 public synchronized String[] getPdbFile()
619 return new String[0];
621 if (modelFileNames == null)
623 List<String> mset = new ArrayList<String>();
624 _modelFileNameMap = new int[viewer.ms.mc];
625 String m = viewer.ms.getModelFileName(0);
631 filePath = new File(m).getAbsolutePath();
632 } catch (AccessControlException x)
634 // usually not allowed to do this in applet
636 .println("jmolBinding: Using local file string from Jmol: "
639 if (filePath.indexOf("/file:") != -1)
641 // applet path with docroot - discard as format won't match pdbfile
645 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
648 for (int i = 1; i < viewer.ms.mc; i++)
650 m = viewer.ms.getModelFileName(i);
656 filePath = new File(m).getAbsolutePath();
657 } catch (AccessControlException x)
659 // usually not allowed to do this in applet, so keep raw handle
660 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
665 * add this model unless it is read from a structure file we have
666 * already seen (example: 2MJW is an NMR structure with 10 models)
668 if (!mset.contains(filePath))
671 _modelFileNameMap[j] = i; // record the model index for the filename
675 modelFileNames = mset.toArray(new String[mset.size()]);
677 return modelFileNames;
681 * map from string to applet
684 public Map<String, Object> getRegistryInfo()
686 // TODO Auto-generated method stub
692 // ///////////////////////////////
693 // JmolStatusListener
695 public void handlePopupMenu(int x, int y)
697 // jmolpopup.show(x, y);
698 // jmolpopup.jpiShow(x, y);
702 * Highlight zero, one or more atoms on the structure
705 public void highlightAtoms(List<AtomSpec> atoms)
709 if (resetLastRes.length() > 0)
711 viewer.evalStringQuiet(resetLastRes.toString());
712 resetLastRes.setLength(0);
714 for (AtomSpec atom : atoms)
716 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
717 atom.getChain(), atom.getPdbFile());
723 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
726 if (modelFileNames == null)
731 // look up file model number for this pdbfile
733 // may need to adjust for URLencoding here - we don't worry about that yet.
734 while (mdlNum < modelFileNames.length
735 && !pdbfile.equals(modelFileNames[mdlNum]))
739 if (mdlNum == modelFileNames.length)
746 StringBuilder cmd = new StringBuilder(64);
747 cmd.append("select " + pdbResNum); // +modelNum
749 resetLastRes.append("select " + pdbResNum); // +modelNum
752 resetLastRes.append(":");
753 if (!chain.equals(" "))
756 resetLastRes.append(chain);
759 cmd.append(" /" + (mdlNum + 1));
760 resetLastRes.append("/" + (mdlNum + 1));
762 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
764 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
765 + " and not hetero; spacefill 0;");
767 cmd.append("spacefill 200;select none");
769 viewer.evalStringQuiet(cmd.toString());
774 boolean debug = true;
776 private void jmolHistory(boolean enable)
778 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
781 public void loadInline(String string)
785 // viewer.loadInline(strModel, isAppend);
787 // construct fake fullPathName and fileName so we can identify the file
789 // Then, construct pass a reader for the string to Jmol.
790 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
791 // fileName, null, reader, false, null, null, 0);
792 viewer.openStringInline(string);
795 public void mouseOverStructure(int atomIndex, String strInfo)
798 int alocsep = strInfo.indexOf("^");
799 int mdlSep = strInfo.indexOf("/");
800 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
802 if (chainSeparator == -1)
804 chainSeparator = strInfo.indexOf(".");
805 if (mdlSep > -1 && mdlSep < chainSeparator)
807 chainSeparator1 = chainSeparator;
808 chainSeparator = mdlSep;
811 // handle insertion codes
814 pdbResNum = Integer.parseInt(strInfo.substring(
815 strInfo.indexOf("]") + 1, alocsep));
820 pdbResNum = Integer.parseInt(strInfo.substring(
821 strInfo.indexOf("]") + 1, chainSeparator));
825 if (strInfo.indexOf(":") > -1)
827 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
828 strInfo.indexOf("."));
835 String pdbfilename = modelFileNames[frameNo]; // default is first or current
839 if (chainSeparator1 == -1)
841 chainSeparator1 = strInfo.indexOf(".", mdlSep);
843 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
844 chainSeparator1) : strInfo.substring(mdlSep + 1);
847 // recover PDB filename for the model hovered over.
848 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
850 while (mnumber < _modelFileNameMap[_mp])
854 pdbfilename = modelFileNames[_mp];
855 if (pdbfilename == null)
857 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
861 } catch (Exception e)
866 if (lastMessage == null || !lastMessage.equals(strInfo))
868 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
871 lastMessage = strInfo;
874 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
878 System.err.println("Ignoring additional hover info: " + data
879 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
881 mouseOverStructure(atomIndex, strInfo);
885 * { if (history != null && strStatus != null &&
886 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
890 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
893 * this implements the toggle label behaviour copied from the original
894 * structure viewer, MCView
898 System.err.println("Ignoring additional pick data string " + strData);
900 int chainSeparator = strInfo.indexOf(":");
902 if (chainSeparator == -1)
904 chainSeparator = strInfo.indexOf(".");
907 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
909 String mdlString = "";
910 if ((p = strInfo.indexOf(":")) > -1)
912 picked += strInfo.substring(p, strInfo.indexOf("."));
915 if ((p = strInfo.indexOf("/")) > -1)
917 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
919 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
923 if (!atomsPicked.contains(picked))
925 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
926 atomsPicked.addElement(picked);
930 viewer.evalString("select " + picked + ";label off");
931 atomsPicked.removeElement(picked);
934 // TODO: in application this happens
936 // if (scriptWindow != null)
938 // scriptWindow.sendConsoleMessage(strInfo);
939 // scriptWindow.sendConsoleMessage("\n");
945 public void notifyCallback(CBK type, Object[] data)
952 notifyFileLoaded((String) data[1], (String) data[2],
953 (String) data[3], (String) data[4],
954 ((Integer) data[5]).intValue());
958 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
960 // also highlight in alignment
962 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
966 notifyScriptTermination((String) data[2],
967 ((Integer) data[3]).intValue());
970 sendConsoleEcho((String) data[1]);
973 sendConsoleMessage((data == null) ? ((String) null)
977 // System.err.println("Ignoring error callback.");
987 System.err.println("Unhandled callback " + type + " "
988 + data[1].toString());
991 } catch (Exception e)
993 System.err.println("Squashed Jmol callback handler error:");
999 public boolean notifyEnabled(CBK callbackPick)
1001 switch (callbackPick)
1017 // incremented every time a load notification is successfully handled -
1018 // lightweight mechanism for other threads to detect when they can start
1019 // referrring to new structures.
1020 private long loadNotifiesHandled = 0;
1022 public long getLoadNotifiesHandled()
1024 return loadNotifiesHandled;
1027 public void notifyFileLoaded(String fullPathName, String fileName2,
1028 String modelName, String errorMsg, int modelParts)
1030 if (errorMsg != null)
1032 fileLoadingError = errorMsg;
1036 // TODO: deal sensibly with models loaded inLine:
1037 // modelName will be null, as will fullPathName.
1039 // the rest of this routine ignores the arguments, and simply interrogates
1040 // the Jmol view to find out what structures it contains, and adds them to
1041 // the structure selection manager.
1042 fileLoadingError = null;
1043 String[] oldmodels = modelFileNames;
1044 modelFileNames = null;
1045 chainNames = new ArrayList<String>();
1046 chainFile = new Hashtable<String, String>();
1047 boolean notifyLoaded = false;
1048 String[] modelfilenames = getPdbFile();
1049 // first check if we've lost any structures
1050 if (oldmodels != null && oldmodels.length > 0)
1053 for (int i = 0; i < oldmodels.length; i++)
1055 for (int n = 0; n < modelfilenames.length; n++)
1057 if (modelfilenames[n] == oldmodels[i])
1059 oldmodels[i] = null;
1063 if (oldmodels[i] != null)
1070 String[] oldmfn = new String[oldm];
1072 for (int i = 0; i < oldmodels.length; i++)
1074 if (oldmodels[i] != null)
1076 oldmfn[oldm++] = oldmodels[i];
1079 // deregister the Jmol instance for these structures - we'll add
1080 // ourselves again at the end for the current structure set.
1081 getSsm().removeStructureViewerListener(this, oldmfn);
1084 refreshPdbEntries();
1085 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1087 String fileName = modelfilenames[modelnum];
1088 boolean foundEntry = false;
1089 StructureFile pdb = null;
1090 String pdbfile = null;
1091 // model was probably loaded inline - so check the pdb file hashcode
1094 // calculate essential attributes for the pdb data imported inline.
1095 // prolly need to resolve modelnumber properly - for now just use our
1097 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1100 // search pdbentries and sequences to find correct pdbentry for this
1102 for (int pe = 0; pe < getPdbCount(); pe++)
1104 boolean matches = false;
1105 addSequence(pe, getSequence()[pe]);
1106 if (fileName == null)
1109 // see JAL-623 - need method of matching pasted data up
1111 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1112 pdbfile, DataSourceType.PASTE);
1113 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1120 File fl = new File(getPdbEntry(pe).getFile());
1121 matches = fl.equals(new File(fileName));
1125 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1128 // to be tested. See mantis bug
1129 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1130 DataSourceType protocol = DataSourceType.URL;
1135 protocol = DataSourceType.FILE;
1137 } catch (Exception e)
1142 // Explicitly map to the filename used by Jmol ;
1143 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1144 fileName, protocol);
1145 // pdbentry[pe].getFile(), protocol);
1151 // add an entry for every chain in the model
1152 for (int i = 0; i < pdb.getChains().size(); i++)
1154 String chid = new String(pdb.getId() + ":"
1155 + pdb.getChains().elementAt(i).id);
1156 chainFile.put(chid, fileName);
1157 chainNames.add(chid);
1159 notifyLoaded = true;
1163 if (!foundEntry && associateNewStructs)
1165 // this is a foreign pdb file that jalview doesn't know about - add
1166 // it to the dataset and try to find a home - either on a matching
1167 // sequence or as a new sequence.
1168 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1170 // parse pdb file into a chain, etc.
1171 // locate best match for pdb in associated views and add mapping to
1173 // if properly registered then
1174 notifyLoaded = true;
1179 // so finally, update the jmol bits and pieces
1180 // if (jmolpopup != null)
1182 // // potential for deadlock here:
1183 // // jmolpopup.updateComputedMenus();
1185 if (!isLoadingFromArchive())
1187 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1189 // register ourselves as a listener and notify the gui that it needs to
1191 getSsm().addStructureViewerListener(this);
1194 FeatureRenderer fr = getFeatureRenderer(null);
1200 loadNotifiesHandled++;
1202 setLoadingFromArchive(false);
1206 public List<String> getChainNames()
1211 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1213 notifyAtomPicked(iatom, strMeasure, null);
1216 public abstract void notifyScriptTermination(String strStatus,
1220 * display a message echoed from the jmol viewer
1224 public abstract void sendConsoleEcho(String strEcho); /*
1225 * { showConsole(true);
1227 * history.append("\n" +
1231 // /End JmolStatusListener
1232 // /////////////////////////////
1236 * status message - usually the response received after a script
1239 public abstract void sendConsoleMessage(String strStatus);
1242 public void setCallbackFunction(String callbackType,
1243 String callbackFunction)
1245 System.err.println("Ignoring set-callback request to associate "
1246 + callbackType + " with function " + callbackFunction);
1251 public void setJalviewColourScheme(ColourSchemeI cs)
1253 colourBySequence = false;
1261 StringBuilder command = new StringBuilder(128);
1262 command.append("select *;color white;");
1263 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1265 for (String resName : residueSet)
1267 char res = resName.length() == 3 ? ResidueProperties
1268 .getSingleCharacterCode(resName) : resName.charAt(0);
1269 Color col = cs.findColour(res, 0, null, null, 0f);
1270 command.append("select " + resName + ";color[" + col.getRed() + ","
1271 + col.getGreen() + "," + col.getBlue() + "];");
1274 evalStateCommand(command.toString());
1278 public void showHelp()
1280 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1284 * open the URL somehow
1288 public abstract void showUrl(String url, String target);
1291 * called when the binding thinks the UI needs to be refreshed after a Jmol
1292 * state change. this could be because structures were loaded, or because an
1293 * error has occured.
1295 public abstract void refreshGUI();
1298 * called to show or hide the associated console window container.
1302 public abstract void showConsole(boolean show);
1305 * @param renderPanel
1307 * - when true will initialise jmol's file IO system (should be false
1308 * in applet context)
1310 * @param documentBase
1312 * @param commandOptions
1314 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1315 String htmlName, URL documentBase, URL codeBase,
1316 String commandOptions)
1318 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1319 codeBase, commandOptions, null, null);
1324 * @param renderPanel
1326 * - when true will initialise jmol's file IO system (should be false
1327 * in applet context)
1329 * @param documentBase
1331 * @param commandOptions
1332 * @param consolePanel
1333 * - panel to contain Jmol console
1334 * @param buttonsToShow
1335 * - buttons to show on the console, in ordr
1337 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1338 String htmlName, URL documentBase, URL codeBase,
1339 String commandOptions, final Container consolePanel,
1340 String buttonsToShow)
1342 if (commandOptions == null)
1344 commandOptions = "";
1346 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1347 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1348 + ((Object) this).toString(), documentBase, codeBase,
1349 commandOptions, this);
1351 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1353 console = createJmolConsole(consolePanel, buttonsToShow);
1354 if (consolePanel != null)
1356 consolePanel.addComponentListener(this);
1362 protected abstract JmolAppConsoleInterface createJmolConsole(
1363 Container consolePanel, String buttonsToShow);
1365 protected org.jmol.api.JmolAppConsoleInterface console = null;
1368 public void setBackgroundColour(java.awt.Color col)
1371 viewer.evalStringQuiet("background [" + col.getRed() + ","
1372 + col.getGreen() + "," + col.getBlue() + "];");
1377 public int[] resizeInnerPanel(String data)
1379 // Jalview doesn't honour resize panel requests
1386 protected void closeConsole()
1388 if (console != null)
1392 console.setVisible(false);
1395 } catch (Exception x)
1404 * ComponentListener method
1407 public void componentMoved(ComponentEvent e)
1412 * ComponentListener method
1415 public void componentResized(ComponentEvent e)
1420 * ComponentListener method
1423 public void componentShown(ComponentEvent e)
1429 * ComponentListener method
1432 public void componentHidden(ComponentEvent e)