2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.ext.jmol;
23 import jalview.api.AlignmentViewPanel;
24 import jalview.api.FeatureRenderer;
25 import jalview.api.SequenceRenderer;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.ColumnSelection;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.SequenceI;
30 import jalview.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;
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.Hashtable;
49 import java.util.List;
51 import java.util.Vector;
53 import org.jmol.adapter.smarter.SmarterJmolAdapter;
54 import org.jmol.api.JmolAppConsoleInterface;
55 import org.jmol.api.JmolSelectionListener;
56 import org.jmol.api.JmolStatusListener;
57 import org.jmol.api.JmolViewer;
58 import org.jmol.c.CBK;
59 import org.jmol.script.T;
60 import org.jmol.viewer.Viewer;
62 public abstract class JalviewJmolBinding extends AAStructureBindingModel
63 implements JmolStatusListener, JmolSelectionListener,
66 boolean allChainsSelected = false;
69 * when true, try to search the associated datamodel for sequences that are
70 * associated with any unknown structures in the Jmol view.
72 private boolean associateNewStructs = false;
74 Vector<String> atomsPicked = new Vector<String>();
76 private List<String> chainNames;
78 Hashtable<String, String> chainFile;
80 public String fileLoadingError;
83 * the default or current model displayed if the model cannot be identified
84 * from the selection message
88 // protected JmolGenericPopup jmolpopup; // not used - remove?
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.getPdbFile());
172 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");
184 public void colourByCharge()
186 colourBySequence = false;
187 evalStateCommand("select *;color white;select ASP,GLU;color red;"
188 + "select LYS,ARG;color blue;select CYS;color yellow");
192 * superpose the structures associated with sequences in the alignment
193 * according to their corresponding positions.
195 public void superposeStructures(AlignmentI alignment)
197 superposeStructures(alignment, -1, null);
201 * superpose the structures associated with sequences in the alignment
202 * according to their corresponding positions. ded)
204 * @param refStructure
205 * - select which pdb file to use as reference (default is -1 - the
206 * first structure in the alignment)
208 public void superposeStructures(AlignmentI alignment, int refStructure)
210 superposeStructures(alignment, refStructure, null);
214 * superpose the structures associated with sequences in the alignment
215 * according to their corresponding positions. ded)
217 * @param refStructure
218 * - select which pdb file to use as reference (default is -1 - the
219 * first structure in the alignment)
223 public void superposeStructures(AlignmentI alignment, int refStructure,
224 ColumnSelection hiddenCols)
226 superposeStructures(new AlignmentI[] { alignment },
227 new int[] { refStructure },
228 new ColumnSelection[] { hiddenCols });
232 * Construct and send a command to align structures against a reference
233 * structure, based on one or more sequence alignments
236 * an array of alignments to process
237 * @param _refStructure
238 * an array of corresponding reference structures (index into pdb
239 * file array); if a negative value is passed, the first PDB file
240 * mapped to an alignment sequence is used as the reference for
243 * an array of corresponding hidden columns for each alignment
245 public void superposeStructures(AlignmentI[] _alignment,
246 int[] _refStructure, ColumnSelection[] _hiddenCols)
248 while (viewer.isScriptExecuting())
253 } catch (InterruptedException i)
259 * get the distinct structure files modelled
260 * (a file with multiple chains may map to multiple sequences)
262 String[] files = getPdbFile();
263 if (!waitForFileLoad(files))
268 StringBuilder selectioncom = new StringBuilder(256);
269 // In principle - nSeconds specifies the speed of animation for each
270 // superposition - but is seems to behave weirdly, so we don't specify it.
271 String nSeconds = " ";
272 if (files.length > 10)
274 nSeconds = " 0.005 ";
278 nSeconds = " " + (2.0 / files.length) + " ";
279 // if (nSeconds).substring(0,5)+" ";
281 // see JAL-1345 - should really automatically turn off the animation for
282 // large numbers of structures, but Jmol doesn't seem to allow that.
284 // union of all aligned positions are collected together.
285 for (int a = 0; a < _alignment.length; a++)
287 int refStructure = _refStructure[a];
288 AlignmentI alignment = _alignment[a];
289 ColumnSelection hiddenCols = _hiddenCols[a];
291 && selectioncom.length() > 0
292 && !selectioncom.substring(selectioncom.length() - 1).equals(
295 selectioncom.append("|");
297 // process this alignment
298 if (refStructure >= files.length)
300 System.err.println("Invalid reference structure value "
306 * 'matched' array will hold 'true' for visible alignment columns where
307 * all sequences have a residue with a mapping to the PDB structure
309 // TODO could use a BitSet for matched
310 boolean matched[] = new boolean[alignment.getWidth()];
311 for (int m = 0; m < matched.length; m++)
313 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
316 SuperposeData[] structures = new SuperposeData[files.length];
317 for (int f = 0; f < files.length; f++)
319 structures[f] = new SuperposeData(alignment.getWidth());
323 * Calculate the superposable alignment columns ('matched'), and the
324 * corresponding structure residue positions (structures.pdbResNo)
326 int candidateRefStructure = findSuperposableResidues(alignment,
327 matched, structures);
328 if (refStructure < 0)
331 * If no reference structure was specified, pick the first one that has
332 * a mapping in the alignment
334 refStructure = candidateRefStructure;
337 String[] selcom = new String[files.length];
339 for (boolean b : matched)
348 // TODO: bail out here because superposition illdefined?
352 * generate select statements to select regions to superimpose structures
355 // TODO extract method to construct selection statements
356 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
358 String chainCd = ":" + structures[pdbfnum].chain;
361 StringBuilder molsel = new StringBuilder();
363 for (int r = 0; r < matched.length; r++)
367 int pdbResNo = structures[pdbfnum].pdbResNo[r];
368 if (lpos != pdbResNo - 1)
374 molsel.append(chainCd);
381 // continuous run - and lpos >-1
384 // at the beginning, so add dash
394 * add final selection phrase
399 molsel.append(chainCd);
402 if (molsel.length() > 1)
404 selcom[pdbfnum] = molsel.toString();
405 selectioncom.append("((");
406 selectioncom.append(selcom[pdbfnum].substring(1,
407 selcom[pdbfnum].length() - 1));
408 selectioncom.append(" )& ");
409 selectioncom.append(pdbfnum + 1);
410 selectioncom.append(".1)");
411 if (pdbfnum < files.length - 1)
413 selectioncom.append("|");
418 selcom[pdbfnum] = null;
422 StringBuilder command = new StringBuilder(256);
423 // command.append("set spinFps 10;\n");
425 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
427 if (pdbfnum == refStructure || selcom[pdbfnum] == null
428 || selcom[refStructure] == null)
432 command.append("echo ");
433 command.append("\"Superposing (");
434 command.append(structures[pdbfnum].pdbId);
435 command.append(") against reference (");
436 command.append(structures[refStructure].pdbId);
437 command.append(")\";\ncompare " + nSeconds);
439 command.append(Integer.toString(1 + pdbfnum));
440 command.append(".1} {");
441 command.append(Integer.toString(1 + refStructure));
442 // conformation=1 excludes alternate locations for CA (JAL-1757)
443 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
445 // for (int s = 0; s < 2; s++)
447 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
449 command.append(selcom[pdbfnum]);
450 command.append(selcom[refStructure]);
451 command.append(" ROTATE TRANSLATE;\n");
453 if (selectioncom.length() > 0)
455 // TODO is performing selectioncom redundant here? is done later on
456 // System.out.println("Select regions:\n" + selectioncom.toString());
457 evalStateCommand("select *; cartoons off; backbone; select ("
458 + selectioncom.toString() + "); cartoons; ");
459 // selcom.append("; ribbons; ");
460 String cmdString = command.toString();
461 // System.out.println("Superimpose command(s):\n" + cmdString);
463 evalStateCommand(cmdString);
466 if (selectioncom.length() > 0)
467 {// finally, mark all regions that were superposed.
468 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
470 selectioncom.setLength(selectioncom.length() - 1);
472 // System.out.println("Select regions:\n" + selectioncom.toString());
473 evalStateCommand("select *; cartoons off; backbone; select ("
474 + selectioncom.toString() + "); cartoons; ");
475 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
479 public void evalStateCommand(String command)
482 if (lastCommand == null || !lastCommand.equals(command))
484 viewer.evalStringQuiet(command + "\n");
487 lastCommand = command;
491 * colour any structures associated with sequences in the given alignment
492 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
493 * if colourBySequence is enabled.
495 public void colourBySequence(AlignmentViewPanel alignmentv)
497 boolean showFeatures = alignmentv.getAlignViewport()
498 .isShowSequenceFeatures();
499 if (!colourBySequence || !isLoadingFinished())
503 if (getSsm() == null)
507 String[] files = getPdbFile();
509 SequenceRenderer sr = getSequenceRenderer(alignmentv);
511 FeatureRenderer fr = null;
514 fr = getFeatureRenderer(alignmentv);
516 AlignmentI alignment = alignmentv.getAlignment();
518 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
519 files, sr, fr, alignment))
521 for (String cbyseq : cpdbbyseq.commands)
523 executeWhenReady(cbyseq);
535 protected StructureMappingcommandSet[] getColourBySequenceCommands(
536 String[] files, SequenceRenderer sr, FeatureRenderer fr,
537 AlignmentI alignment)
539 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
540 getSequence(), sr, fr, alignment);
546 protected void executeWhenReady(String command)
548 evalStateCommand(command);
551 public void createImage(String file, String type, int quality)
553 System.out.println("JMOL CREATE IMAGE");
557 public String createImage(String fileName, String type,
558 Object textOrBytes, int quality)
560 System.out.println("JMOL CREATE IMAGE");
565 public String eval(String strEval)
567 // System.out.println(strEval);
568 // "# 'eval' is implemented only for the applet.";
572 // End StructureListener
573 // //////////////////////////
576 public float[][] functionXY(String functionName, int x, int y)
582 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
584 // TODO Auto-generated method stub
588 public Color getColour(int atomIndex, int pdbResNum, String chain,
591 if (getModelNum(pdbfile) < 0)
595 // TODO: verify atomIndex is selecting correct model.
596 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
597 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
598 return new Color(colour);
602 * returns the current featureRenderer that should be used to colour the
609 public abstract FeatureRenderer getFeatureRenderer(
610 AlignmentViewPanel alignment);
613 * instruct the Jalview binding to update the pdbentries vector if necessary
614 * prior to matching the jmol view's contents to the list of structure files
615 * Jalview knows about.
617 public abstract void refreshPdbEntries();
619 private int getModelNum(String modelFileName)
621 String[] mfn = getPdbFile();
626 for (int i = 0; i < mfn.length; i++)
628 if (mfn[i].equalsIgnoreCase(modelFileName))
637 * map between index of model filename returned from getPdbFile and the first
638 * index of models from this file in the viewer. Note - this is not trimmed -
639 * use getPdbFile to get number of unique models.
641 private int _modelFileNameMap[];
643 // ////////////////////////////////
644 // /StructureListener
646 public synchronized String[] getPdbFile()
650 return new String[0];
652 if (modelFileNames == null)
654 List<String> mset = new ArrayList<String>();
655 _modelFileNameMap = new int[viewer.ms.mc];
656 String m = viewer.ms.getModelFileName(0);
662 filePath = new File(m).getAbsolutePath();
663 } catch (AccessControlException x)
665 // usually not allowed to do this in applet
667 .println("jmolBinding: Using local file string from Jmol: "
670 if (filePath.indexOf("/file:") != -1)
672 // applet path with docroot - discard as format won't match pdbfile
676 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
679 for (int i = 1; i < viewer.ms.mc; i++)
681 m = viewer.ms.getModelFileName(i);
687 filePath = new File(m).getAbsolutePath();
688 } catch (AccessControlException x)
690 // usually not allowed to do this in applet, so keep raw handle
691 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
696 * add this model unless it is read from a structure file we have
697 * already seen (example: 2MJW is an NMR structure with 10 models)
699 if (!mset.contains(filePath))
702 _modelFileNameMap[j] = i; // record the model index for the filename
706 modelFileNames = mset.toArray(new String[mset.size()]);
708 return modelFileNames;
712 * map from string to applet
715 public Map<String, Object> getRegistryInfo()
717 // TODO Auto-generated method stub
722 * returns the current sequenceRenderer that should be used to colour the
729 public abstract SequenceRenderer getSequenceRenderer(
730 AlignmentViewPanel alignment);
732 // ///////////////////////////////
733 // JmolStatusListener
735 public void handlePopupMenu(int x, int y)
737 // jmolpopup.show(x, y);
738 // jmolpopup.jpiShow(x, y);
742 * Highlight zero, one or more atoms on the structure
745 public void highlightAtoms(List<AtomSpec> atoms)
749 if (resetLastRes.length() > 0)
751 viewer.evalStringQuiet(resetLastRes.toString());
752 resetLastRes.setLength(0);
754 for (AtomSpec atom : atoms)
756 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
757 atom.getChain(), atom.getPdbFile());
763 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
766 if (modelFileNames == null)
771 // look up file model number for this pdbfile
773 // may need to adjust for URLencoding here - we don't worry about that yet.
774 while (mdlNum < modelFileNames.length
775 && !pdbfile.equals(modelFileNames[mdlNum]))
779 if (mdlNum == modelFileNames.length)
786 StringBuilder cmd = new StringBuilder(64);
787 cmd.append("select " + pdbResNum); // +modelNum
789 resetLastRes.append("select " + pdbResNum); // +modelNum
792 resetLastRes.append(":");
793 if (!chain.equals(" "))
796 resetLastRes.append(chain);
799 cmd.append(" /" + (mdlNum + 1));
800 resetLastRes.append("/" + (mdlNum + 1));
802 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
804 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
805 + " and not hetero; spacefill 0;");
807 cmd.append("spacefill 200;select none");
809 viewer.evalStringQuiet(cmd.toString());
814 boolean debug = true;
816 private void jmolHistory(boolean enable)
818 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
821 public void loadInline(String string)
825 // viewer.loadInline(strModel, isAppend);
827 // construct fake fullPathName and fileName so we can identify the file
829 // Then, construct pass a reader for the string to Jmol.
830 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
831 // fileName, null, reader, false, null, null, 0);
832 viewer.openStringInline(string);
835 public void mouseOverStructure(int atomIndex, String strInfo)
838 int alocsep = strInfo.indexOf("^");
839 int mdlSep = strInfo.indexOf("/");
840 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
842 if (chainSeparator == -1)
844 chainSeparator = strInfo.indexOf(".");
845 if (mdlSep > -1 && mdlSep < chainSeparator)
847 chainSeparator1 = chainSeparator;
848 chainSeparator = mdlSep;
851 // handle insertion codes
854 pdbResNum = Integer.parseInt(strInfo.substring(
855 strInfo.indexOf("]") + 1, alocsep));
860 pdbResNum = Integer.parseInt(strInfo.substring(
861 strInfo.indexOf("]") + 1, chainSeparator));
865 if (strInfo.indexOf(":") > -1)
867 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
868 strInfo.indexOf("."));
875 String pdbfilename = modelFileNames[frameNo]; // default is first or current
879 if (chainSeparator1 == -1)
881 chainSeparator1 = strInfo.indexOf(".", mdlSep);
883 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
884 chainSeparator1) : strInfo.substring(mdlSep + 1);
887 // recover PDB filename for the model hovered over.
888 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
890 while (mnumber < _modelFileNameMap[_mp])
894 pdbfilename = modelFileNames[_mp];
895 if (pdbfilename == null)
897 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
901 } catch (Exception e)
906 if (lastMessage == null || !lastMessage.equals(strInfo))
908 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
911 lastMessage = strInfo;
914 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
918 System.err.println("Ignoring additional hover info: " + data
919 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
921 mouseOverStructure(atomIndex, strInfo);
925 * { if (history != null && strStatus != null &&
926 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
930 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
933 * this implements the toggle label behaviour copied from the original
934 * structure viewer, MCView
938 System.err.println("Ignoring additional pick data string " + strData);
940 int chainSeparator = strInfo.indexOf(":");
942 if (chainSeparator == -1)
944 chainSeparator = strInfo.indexOf(".");
947 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
949 String mdlString = "";
950 if ((p = strInfo.indexOf(":")) > -1)
952 picked += strInfo.substring(p, strInfo.indexOf("."));
955 if ((p = strInfo.indexOf("/")) > -1)
957 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
959 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
963 if (!atomsPicked.contains(picked))
965 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
966 atomsPicked.addElement(picked);
970 viewer.evalString("select " + picked + ";label off");
971 atomsPicked.removeElement(picked);
974 // TODO: in application this happens
976 // if (scriptWindow != null)
978 // scriptWindow.sendConsoleMessage(strInfo);
979 // scriptWindow.sendConsoleMessage("\n");
985 public void notifyCallback(CBK type, Object[] data)
992 notifyFileLoaded((String) data[1], (String) data[2],
993 (String) data[3], (String) data[4],
994 ((Integer) data[5]).intValue());
998 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
1000 // also highlight in alignment
1002 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1006 notifyScriptTermination((String) data[2],
1007 ((Integer) data[3]).intValue());
1010 sendConsoleEcho((String) data[1]);
1013 sendConsoleMessage((data == null) ? ((String) null)
1014 : (String) data[1]);
1017 // System.err.println("Ignoring error callback.");
1027 System.err.println("Unhandled callback " + type + " "
1028 + data[1].toString());
1031 } catch (Exception e)
1033 System.err.println("Squashed Jmol callback handler error:");
1034 e.printStackTrace();
1039 public boolean notifyEnabled(CBK callbackPick)
1041 switch (callbackPick)
1057 // incremented every time a load notification is successfully handled -
1058 // lightweight mechanism for other threads to detect when they can start
1059 // referrring to new structures.
1060 private long loadNotifiesHandled = 0;
1062 public long getLoadNotifiesHandled()
1064 return loadNotifiesHandled;
1067 public void notifyFileLoaded(String fullPathName, String fileName2,
1068 String modelName, String errorMsg, int modelParts)
1070 if (errorMsg != null)
1072 fileLoadingError = errorMsg;
1076 // TODO: deal sensibly with models loaded inLine:
1077 // modelName will be null, as will fullPathName.
1079 // the rest of this routine ignores the arguments, and simply interrogates
1080 // the Jmol view to find out what structures it contains, and adds them to
1081 // the structure selection manager.
1082 fileLoadingError = null;
1083 String[] oldmodels = modelFileNames;
1084 modelFileNames = null;
1085 chainNames = new ArrayList<String>();
1086 chainFile = new Hashtable<String, String>();
1087 boolean notifyLoaded = false;
1088 String[] modelfilenames = getPdbFile();
1089 // first check if we've lost any structures
1090 if (oldmodels != null && oldmodels.length > 0)
1093 for (int i = 0; i < oldmodels.length; i++)
1095 for (int n = 0; n < modelfilenames.length; n++)
1097 if (modelfilenames[n] == oldmodels[i])
1099 oldmodels[i] = null;
1103 if (oldmodels[i] != null)
1110 String[] oldmfn = new String[oldm];
1112 for (int i = 0; i < oldmodels.length; i++)
1114 if (oldmodels[i] != null)
1116 oldmfn[oldm++] = oldmodels[i];
1119 // deregister the Jmol instance for these structures - we'll add
1120 // ourselves again at the end for the current structure set.
1121 getSsm().removeStructureViewerListener(this, oldmfn);
1124 refreshPdbEntries();
1125 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1127 String fileName = modelfilenames[modelnum];
1128 boolean foundEntry = false;
1129 StructureFile pdb = null;
1130 String pdbfile = null;
1131 // model was probably loaded inline - so check the pdb file hashcode
1134 // calculate essential attributes for the pdb data imported inline.
1135 // prolly need to resolve modelnumber properly - for now just use our
1137 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1140 // search pdbentries and sequences to find correct pdbentry for this
1142 for (int pe = 0; pe < getPdbCount(); pe++)
1144 boolean matches = false;
1145 addSequence(pe, getSequence()[pe]);
1146 if (fileName == null)
1149 // see JAL-623 - need method of matching pasted data up
1151 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1152 pdbfile, DataSourceType.PASTE, getIProgressIndicator());
1153 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1160 File fl = new File(getPdbEntry(pe).getFile());
1161 matches = fl.equals(new File(fileName));
1165 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1168 // to be tested. See mantis bug
1169 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1170 DataSourceType protocol = DataSourceType.URL;
1175 protocol = DataSourceType.FILE;
1177 } catch (Exception e)
1182 // Explicitly map to the filename used by Jmol ;
1183 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1184 fileName, protocol, getIProgressIndicator());
1185 // pdbentry[pe].getFile(), protocol);
1191 // add an entry for every chain in the model
1192 for (int i = 0; i < pdb.getChains().size(); i++)
1194 String chid = new String(pdb.getId() + ":"
1195 + pdb.getChains().elementAt(i).id);
1196 chainFile.put(chid, fileName);
1197 chainNames.add(chid);
1199 notifyLoaded = true;
1203 if (!foundEntry && associateNewStructs)
1205 // this is a foreign pdb file that jalview doesn't know about - add
1206 // it to the dataset and try to find a home - either on a matching
1207 // sequence or as a new sequence.
1208 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1210 // parse pdb file into a chain, etc.
1211 // locate best match for pdb in associated views and add mapping to
1213 // if properly registered then
1214 notifyLoaded = true;
1219 // so finally, update the jmol bits and pieces
1220 // if (jmolpopup != null)
1222 // // potential for deadlock here:
1223 // // jmolpopup.updateComputedMenus();
1225 if (!isLoadingFromArchive())
1227 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1229 // register ourselves as a listener and notify the gui that it needs to
1231 getSsm().addStructureViewerListener(this);
1234 FeatureRenderer fr = getFeatureRenderer(null);
1240 loadNotifiesHandled++;
1242 setLoadingFromArchive(false);
1246 public List<String> getChainNames()
1251 protected abstract IProgressIndicator getIProgressIndicator();
1253 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1255 notifyAtomPicked(iatom, strMeasure, null);
1258 public abstract void notifyScriptTermination(String strStatus,
1262 * display a message echoed from the jmol viewer
1266 public abstract void sendConsoleEcho(String strEcho); /*
1267 * { showConsole(true);
1269 * history.append("\n" +
1273 // /End JmolStatusListener
1274 // /////////////////////////////
1278 * status message - usually the response received after a script
1281 public abstract void sendConsoleMessage(String strStatus);
1284 public void setCallbackFunction(String callbackType,
1285 String callbackFunction)
1287 System.err.println("Ignoring set-callback request to associate "
1288 + callbackType + " with function " + callbackFunction);
1292 public void setJalviewColourScheme(ColourSchemeI cs)
1294 colourBySequence = false;
1302 StringBuilder command = new StringBuilder(128);
1303 command.append("select *;color white;");
1304 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1306 for (String res : residueSet)
1308 Color col = cs.findColour(res.charAt(0));
1309 command.append("select " + res + ";color[" + col.getRed() + ","
1310 + col.getGreen() + "," + col.getBlue() + "];");
1313 evalStateCommand(command.toString());
1317 public void showHelp()
1319 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1323 * open the URL somehow
1327 public abstract void showUrl(String url, String target);
1330 * called when the binding thinks the UI needs to be refreshed after a Jmol
1331 * state change. this could be because structures were loaded, or because an
1332 * error has occured.
1334 public abstract void refreshGUI();
1337 * called to show or hide the associated console window container.
1341 public abstract void showConsole(boolean show);
1344 * @param renderPanel
1346 * - when true will initialise jmol's file IO system (should be false
1347 * in applet context)
1349 * @param documentBase
1351 * @param commandOptions
1353 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1354 String htmlName, URL documentBase, URL codeBase,
1355 String commandOptions)
1357 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1358 codeBase, commandOptions, null, null);
1363 * @param renderPanel
1365 * - when true will initialise jmol's file IO system (should be false
1366 * in applet context)
1368 * @param documentBase
1370 * @param commandOptions
1371 * @param consolePanel
1372 * - panel to contain Jmol console
1373 * @param buttonsToShow
1374 * - buttons to show on the console, in ordr
1376 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1377 String htmlName, URL documentBase, URL codeBase,
1378 String commandOptions, final Container consolePanel,
1379 String buttonsToShow)
1381 if (commandOptions == null)
1383 commandOptions = "";
1385 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1386 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1387 + ((Object) this).toString(), documentBase, codeBase,
1388 commandOptions, this);
1390 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1392 console = createJmolConsole(consolePanel, buttonsToShow);
1393 if (consolePanel != null)
1395 consolePanel.addComponentListener(this);
1401 protected abstract JmolAppConsoleInterface createJmolConsole(
1402 Container consolePanel, String buttonsToShow);
1404 protected org.jmol.api.JmolAppConsoleInterface console = null;
1406 public void setBackgroundColour(java.awt.Color col)
1409 viewer.evalStringQuiet("background [" + col.getRed() + ","
1410 + col.getGreen() + "," + col.getBlue() + "];");
1415 public int[] resizeInnerPanel(String data)
1417 // Jalview doesn't honour resize panel requests
1424 protected void closeConsole()
1426 if (console != null)
1430 console.setVisible(false);
1433 } catch (Exception x)
1442 * ComponentListener method
1445 public void componentMoved(ComponentEvent e)
1450 * ComponentListener method
1453 public void componentResized(ComponentEvent e)
1458 * ComponentListener method
1461 public void componentShown(ComponentEvent e)
1467 * ComponentListener method
1470 public void componentHidden(ComponentEvent e)