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.AppletFormatAdapter;
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.Hashtable;
48 import java.util.List;
50 import java.util.Vector;
52 import javajs.awt.Dimension;
54 import org.jmol.adapter.smarter.SmarterJmolAdapter;
55 import org.jmol.api.JmolAppConsoleInterface;
56 import org.jmol.api.JmolSelectionListener;
57 import org.jmol.api.JmolStatusListener;
58 import org.jmol.api.JmolViewer;
59 import org.jmol.c.CBK;
60 import org.jmol.script.T;
61 import org.jmol.viewer.JC;
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<String>();
78 public Vector<String> chainNames;
80 Hashtable<String, String> chainFile;
82 public String fileLoadingError;
85 * the default or current model displayed if the model cannot be identified
86 * from the selection message
90 // protected JmolGenericPopup jmolpopup; // not used - remove?
99 * current set of model filenames loaded in the Jmol instance
101 String[] modelFileNames = null;
103 StringBuffer resetLastRes = new StringBuffer();
105 public Viewer viewer;
107 public JalviewJmolBinding(StructureSelectionManager ssm,
108 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
111 super(ssm, pdbentry, sequenceIs, chains, protocol);
113 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
114 * "jalviewJmol", ap.av.applet .getDocumentBase(),
115 * ap.av.applet.getCodeBase(), "", this);
117 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
121 public JalviewJmolBinding(StructureSelectionManager ssm,
122 SequenceI[][] seqs, Viewer theViewer)
127 viewer.setJmolStatusListener(this);
128 viewer.addSelectionListener(this);
132 * construct a title string for the viewer window based on the data jalview
137 public String getViewerTitle()
139 return getViewerTitle("Jmol", true);
143 * prepare the view for a given set of models/chains. chainList contains
144 * strings of the form 'pdbfilename:Chaincode'
147 * list of chains to make visible
149 public void centerViewer(Vector<String> chainList)
151 StringBuilder cmd = new StringBuilder(128);
153 for (String lbl : chainList)
159 mlength = lbl.indexOf(":", p);
160 } while (p < mlength && mlength < (lbl.length() - 2));
161 // TODO: lookup each pdb id and recover proper model number for it.
162 cmd.append(":" + lbl.substring(mlength + 1) + " /"
163 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
165 if (cmd.length() > 0)
167 cmd.setLength(cmd.length() - 4);
169 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
172 public void closeViewer()
174 viewer.acm.setModeMouse(JC.MOUSE_NONE);
175 // remove listeners for all structures in viewer
176 getSsm().removeStructureViewerListener(this, this.getPdbFile());
177 // and shut down jmol
178 viewer.evalStringQuiet("zap");
179 viewer.setJmolStatusListener(null);
182 releaseUIResources();
185 public void colourByChain()
187 colourBySequence = false;
188 // TODO: colour by chain should colour each chain distinctly across all
190 // TODO: http://issues.jalview.org/browse/JAL-628
191 evalStateCommand("select *;color chain");
194 public void colourByCharge()
196 colourBySequence = false;
197 evalStateCommand("select *;color white;select ASP,GLU;color red;"
198 + "select LYS,ARG;color blue;select CYS;color yellow");
202 * superpose the structures associated with sequences in the alignment
203 * according to their corresponding positions.
205 public void superposeStructures(AlignmentI alignment)
207 superposeStructures(alignment, -1, null);
211 * superpose the structures associated with sequences in the alignment
212 * according to their corresponding positions. ded)
214 * @param refStructure
215 * - select which pdb file to use as reference (default is -1 - the
216 * first structure in the alignment)
218 public void superposeStructures(AlignmentI alignment, int refStructure)
220 superposeStructures(alignment, refStructure, null);
224 * superpose the structures associated with sequences in the alignment
225 * according to their corresponding positions. ded)
227 * @param refStructure
228 * - select which pdb file to use as reference (default is -1 - the
229 * first structure in the alignment)
233 public void superposeStructures(AlignmentI alignment, int refStructure,
234 ColumnSelection hiddenCols)
236 superposeStructures(new AlignmentI[] { alignment },
237 new int[] { refStructure },
238 new ColumnSelection[] { hiddenCols });
242 * Construct and send a command to align structures against a reference
243 * structure, based on one or more sequence alignments
246 * an array of alignments to process
247 * @param _refStructure
248 * an array of corresponding reference structures (index into pdb
249 * file array); if a negative value is passed, the first PDB file
250 * mapped to an alignment sequence is used as the reference for
253 * an array of corresponding hidden columns for each alignment
255 public void superposeStructures(AlignmentI[] _alignment,
256 int[] _refStructure, ColumnSelection[] _hiddenCols)
258 while (viewer.isScriptExecuting())
263 } catch (InterruptedException i)
268 String[] files = getPdbFile();
269 if (!waitForFileLoad(files))
274 StringBuilder selectioncom = new StringBuilder(256);
275 // In principle - nSeconds specifies the speed of animation for each
276 // superposition - but is seems to behave weirdly, so we don't specify it.
277 String nSeconds = " ";
278 if (files.length > 10)
280 nSeconds = " 0.005 ";
284 nSeconds = " " + (2.0 / files.length) + " ";
285 // if (nSeconds).substring(0,5)+" ";
287 // see JAL-1345 - should really automatically turn off the animation for
288 // large numbers of structures, but Jmol doesn't seem to allow that.
290 // union of all aligned positions are collected together.
291 for (int a = 0; a < _alignment.length; a++)
293 int refStructure = _refStructure[a];
294 AlignmentI alignment = _alignment[a];
295 ColumnSelection hiddenCols = _hiddenCols[a];
297 && selectioncom.length() > 0
298 && !selectioncom.substring(selectioncom.length() - 1).equals(
301 selectioncom.append("|");
303 // process this alignment
304 if (refStructure >= files.length)
306 System.err.println("Invalid reference structure value "
312 * 'matched' array will hold 'true' for visible alignment columns where
313 * all sequences have a residue with a mapping to the PDB structure
315 boolean matched[] = new boolean[alignment.getWidth()];
316 for (int m = 0; m < matched.length; m++)
318 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
321 SuperposeData[] structures = new SuperposeData[files.length];
322 for (int f = 0; f < files.length; f++)
324 structures[f] = new SuperposeData(alignment.getWidth());
328 * Calculate the superposable alignment columns ('matched'), and the
329 * corresponding structure residue positions (structures.pdbResNo)
331 int candidateRefStructure = findSuperposableResidues(alignment,
332 matched, structures);
333 if (refStructure < 0)
336 * If no reference structure was specified, pick the first one that has
337 * a mapping in the alignment
339 refStructure = candidateRefStructure;
342 String[] selcom = new String[files.length];
344 for (boolean b : matched)
353 // TODO: bail out here because superposition illdefined?
357 * generate select statements to select regions to superimpose structures
360 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
362 String chainCd = ":" + structures[pdbfnum].chain;
365 StringBuilder molsel = new StringBuilder();
367 for (int r = 0; r < matched.length; r++)
371 int pdbResNo = structures[pdbfnum].pdbResNo[r];
372 if (lpos != pdbResNo - 1)
378 molsel.append(chainCd);
385 // continuous run - and lpos >-1
388 // at the beginning, so add dash
398 * add final selection phrase
403 molsel.append(chainCd);
406 if (molsel.length() > 1)
408 selcom[pdbfnum] = molsel.toString();
409 selectioncom.append("((");
410 selectioncom.append(selcom[pdbfnum].substring(1,
411 selcom[pdbfnum].length() - 1));
412 selectioncom.append(" )& ");
413 selectioncom.append(pdbfnum + 1);
414 selectioncom.append(".1)");
415 if (pdbfnum < files.length - 1)
417 selectioncom.append("|");
422 selcom[pdbfnum] = null;
426 StringBuilder command = new StringBuilder(256);
427 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
429 if (pdbfnum == refStructure || selcom[pdbfnum] == null
430 || selcom[refStructure] == null)
434 command.append("echo ");
435 command.append("\"Superposing (");
436 command.append(structures[pdbfnum].pdbId);
437 command.append(") against reference (");
438 command.append(structures[refStructure].pdbId);
439 command.append(")\";\ncompare " + nSeconds);
441 command.append(Integer.toString(1 + pdbfnum));
442 command.append(".1} {");
443 command.append(Integer.toString(1 + refStructure));
444 // conformation=1 excludes alternate locations for CA (JAL-1757)
445 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
447 // for (int s = 0; s < 2; s++)
449 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
451 command.append(selcom[pdbfnum]);
452 command.append(selcom[refStructure]);
453 command.append(" ROTATE TRANSLATE;\n");
455 if (selectioncom.length() > 0)
457 System.out.println("Select regions:\n" + selectioncom.toString());
458 evalStateCommand("select *; cartoons off; backbone; select ("
459 + selectioncom.toString() + "); cartoons; ");
460 // selcom.append("; ribbons; ");
461 String cmdString = command.toString();
462 System.out.println("Superimpose command(s):\n" + cmdString);
464 evalStateCommand(cmdString);
467 if (selectioncom.length() > 0)
468 {// finally, mark all regions that were superposed.
469 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
471 selectioncom.setLength(selectioncom.length() - 1);
473 System.out.println("Select regions:\n" + selectioncom.toString());
474 evalStateCommand("select *; cartoons off; backbone; select ("
475 + selectioncom.toString() + "); cartoons; ");
476 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
480 public void evalStateCommand(String command)
483 if (lastCommand == null || !lastCommand.equals(command))
485 viewer.evalStringQuiet(command + "\n");
488 lastCommand = command;
492 * colour any structures associated with sequences in the given alignment
493 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
494 * if colourBySequence is enabled.
496 public void colourBySequence(AlignmentViewPanel alignmentv)
498 boolean showFeatures = alignmentv.getAlignViewport()
499 .isShowSequenceFeatures();
500 if (!colourBySequence || !isLoadingFinished())
504 if (getSsm() == null)
508 String[] files = getPdbFile();
510 SequenceRenderer sr = getSequenceRenderer(alignmentv);
512 FeatureRenderer fr = null;
515 fr = getFeatureRenderer(alignmentv);
517 AlignmentI alignment = alignmentv.getAlignment();
519 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
520 files, sr, fr, alignment))
522 for (String cbyseq : cpdbbyseq.commands)
524 executeWhenReady(cbyseq);
536 protected StructureMappingcommandSet[] getColourBySequenceCommands(
537 String[] files, SequenceRenderer sr, FeatureRenderer fr,
538 AlignmentI alignment)
540 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
541 getSequence(), sr, fr, alignment);
547 protected void executeWhenReady(String command)
549 evalStateCommand(command);
552 public void createImage(String file, String type, int quality)
554 System.out.println("JMOL CREATE IMAGE");
558 public String createImage(String fileName, String type,
559 Object textOrBytes, int quality)
561 System.out.println("JMOL CREATE IMAGE");
566 public String eval(String strEval)
568 // System.out.println(strEval);
569 // "# 'eval' is implemented only for the applet.";
573 // End StructureListener
574 // //////////////////////////
577 public float[][] functionXY(String functionName, int x, int y)
583 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
585 // TODO Auto-generated method stub
589 public Color getColour(int atomIndex, int pdbResNum, String chain,
592 if (getModelNum(pdbfile) < 0)
596 // TODO: verify atomIndex is selecting correct model.
597 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
598 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
599 return new Color(colour);
603 * returns the current featureRenderer that should be used to colour the
610 public abstract FeatureRenderer getFeatureRenderer(
611 AlignmentViewPanel alignment);
614 * instruct the Jalview binding to update the pdbentries vector if necessary
615 * prior to matching the jmol view's contents to the list of structure files
616 * Jalview knows about.
618 public abstract void refreshPdbEntries();
620 private int getModelNum(String modelFileName)
622 String[] mfn = getPdbFile();
627 for (int i = 0; i < mfn.length; i++)
629 if (mfn[i].equalsIgnoreCase(modelFileName))
638 * map between index of model filename returned from getPdbFile and the first
639 * index of models from this file in the viewer. Note - this is not trimmed -
640 * use getPdbFile to get number of unique models.
642 private int _modelFileNameMap[];
644 // ////////////////////////////////
645 // /StructureListener
647 public synchronized String[] getPdbFile()
651 return new String[0];
653 if (modelFileNames == null)
655 String mset[] = new String[viewer.ms.mc];
656 _modelFileNameMap = new int[mset.length];
657 String m = viewer.ms.getModelFileName(0);
663 mset[0] = new File(m).getAbsolutePath();
664 } catch (AccessControlException x)
666 // usually not allowed to do this in applet
668 .println("jmolBinding: Using local file string from Jmol: "
671 if (mset[0].indexOf("/file:") != -1)
673 // 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 < mset.length; i++)
681 m = viewer.ms.getModelFileName(i);
687 mset[j] = 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);
694 _modelFileNameMap[j] = i; // record the model index for the filename
695 // skip any additional models in the same file (NMR structures)
696 if ((mset[j] == null ? mset[j] != mset[j - 1]
697 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
702 modelFileNames = new String[j];
703 System.arraycopy(mset, 0, modelFileNames, 0, j);
705 return modelFileNames;
709 * map from string to applet
712 public Map<String, Object> getRegistryInfo()
714 // TODO Auto-generated method stub
719 * returns the current sequenceRenderer that should be used to colour the
726 public abstract SequenceRenderer getSequenceRenderer(
727 AlignmentViewPanel alignment);
729 // ///////////////////////////////
730 // JmolStatusListener
732 public void handlePopupMenu(int x, int y)
734 // jmolpopup.show(x, y);
735 // jmolpopup.jpiShow(x, y);
739 * Highlight zero, one or more atoms on the structure
742 public void highlightAtoms(List<AtomSpec> atoms)
746 if (resetLastRes.length() > 0)
748 viewer.evalStringQuiet(resetLastRes.toString());
749 resetLastRes.setLength(0);
751 for (AtomSpec atom : atoms)
753 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
754 atom.getChain(), atom.getPdbFile());
760 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
763 if (modelFileNames == null)
768 // look up file model number for this pdbfile
770 // may need to adjust for URLencoding here - we don't worry about that yet.
771 while (mdlNum < modelFileNames.length
772 && !pdbfile.equals(modelFileNames[mdlNum]))
776 if (mdlNum == modelFileNames.length)
783 StringBuilder cmd = new StringBuilder(64);
784 cmd.append("select " + pdbResNum); // +modelNum
786 resetLastRes.append("select " + pdbResNum); // +modelNum
789 resetLastRes.append(":");
790 if (!chain.equals(" "))
793 resetLastRes.append(chain);
796 cmd.append(" /" + (mdlNum + 1));
797 resetLastRes.append("/" + (mdlNum + 1));
799 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
801 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
802 + " and not hetero; spacefill 0;");
804 cmd.append("spacefill 200;select none");
806 viewer.evalStringQuiet(cmd.toString());
811 boolean debug = true;
813 private void jmolHistory(boolean enable)
815 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
818 public void loadInline(String string)
822 // viewer.loadInline(strModel, isAppend);
824 // construct fake fullPathName and fileName so we can identify the file
826 // Then, construct pass a reader for the string to Jmol.
827 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
828 // fileName, null, reader, false, null, null, 0);
829 viewer.openStringInline(string);
832 public void mouseOverStructure(int atomIndex, String strInfo)
835 int alocsep = strInfo.indexOf("^");
836 int mdlSep = strInfo.indexOf("/");
837 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
839 if (chainSeparator == -1)
841 chainSeparator = strInfo.indexOf(".");
842 if (mdlSep > -1 && mdlSep < chainSeparator)
844 chainSeparator1 = chainSeparator;
845 chainSeparator = mdlSep;
848 // handle insertion codes
851 pdbResNum = Integer.parseInt(strInfo.substring(
852 strInfo.indexOf("]") + 1, alocsep));
857 pdbResNum = Integer.parseInt(strInfo.substring(
858 strInfo.indexOf("]") + 1, chainSeparator));
862 if (strInfo.indexOf(":") > -1)
864 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
865 strInfo.indexOf("."));
872 String pdbfilename = modelFileNames[frameNo]; // default is first or current
876 if (chainSeparator1 == -1)
878 chainSeparator1 = strInfo.indexOf(".", mdlSep);
880 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
881 chainSeparator1) : strInfo.substring(mdlSep + 1);
884 // recover PDB filename for the model hovered over.
885 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
887 while (mnumber < _modelFileNameMap[_mp])
891 pdbfilename = modelFileNames[_mp];
892 if (pdbfilename == null)
894 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
898 } catch (Exception e)
903 if (lastMessage == null || !lastMessage.equals(strInfo))
905 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
908 lastMessage = strInfo;
911 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
915 System.err.println("Ignoring additional hover info: " + data
916 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
918 mouseOverStructure(atomIndex, strInfo);
922 * { if (history != null && strStatus != null &&
923 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
927 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
930 * this implements the toggle label behaviour copied from the original
931 * structure viewer, MCView
935 System.err.println("Ignoring additional pick data string " + strData);
937 int chainSeparator = strInfo.indexOf(":");
939 if (chainSeparator == -1)
941 chainSeparator = strInfo.indexOf(".");
944 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
946 String mdlString = "";
947 if ((p = strInfo.indexOf(":")) > -1)
949 picked += strInfo.substring(p, strInfo.indexOf("."));
952 if ((p = strInfo.indexOf("/")) > -1)
954 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
956 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
960 if (!atomsPicked.contains(picked))
962 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
963 atomsPicked.addElement(picked);
967 viewer.evalString("select " + picked + ";label off");
968 atomsPicked.removeElement(picked);
971 // TODO: in application this happens
973 // if (scriptWindow != null)
975 // scriptWindow.sendConsoleMessage(strInfo);
976 // scriptWindow.sendConsoleMessage("\n");
982 public void notifyCallback(CBK type, Object[] data)
989 notifyFileLoaded((String) data[1], (String) data[2],
990 (String) data[3], (String) data[4],
991 ((Integer) data[5]).intValue());
995 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
997 // also highlight in alignment
999 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1003 notifyScriptTermination((String) data[2],
1004 ((Integer) data[3]).intValue());
1007 sendConsoleEcho((String) data[1]);
1010 sendConsoleMessage((data == null) ? ((String) null)
1011 : (String) data[1]);
1014 // System.err.println("Ignoring error callback.");
1024 System.err.println("Unhandled callback " + type + " "
1025 + data[1].toString());
1028 } catch (Exception e)
1030 System.err.println("Squashed Jmol callback handler error:");
1031 e.printStackTrace();
1036 public boolean notifyEnabled(CBK callbackPick)
1038 switch (callbackPick)
1054 // incremented every time a load notification is successfully handled -
1055 // lightweight mechanism for other threads to detect when they can start
1056 // referrring to new structures.
1057 private long loadNotifiesHandled = 0;
1059 public long getLoadNotifiesHandled()
1061 return loadNotifiesHandled;
1064 public void notifyFileLoaded(String fullPathName, String fileName2,
1065 String modelName, String errorMsg, int modelParts)
1067 if (errorMsg != null)
1069 fileLoadingError = errorMsg;
1073 // TODO: deal sensibly with models loaded inLine:
1074 // modelName will be null, as will fullPathName.
1076 // the rest of this routine ignores the arguments, and simply interrogates
1077 // the Jmol view to find out what structures it contains, and adds them to
1078 // the structure selection manager.
1079 fileLoadingError = null;
1080 String[] oldmodels = modelFileNames;
1081 modelFileNames = null;
1082 chainNames = new Vector<String>();
1083 chainFile = new Hashtable<String, String>();
1084 boolean notifyLoaded = false;
1085 String[] modelfilenames = getPdbFile();
1086 // first check if we've lost any structures
1087 if (oldmodels != null && oldmodels.length > 0)
1090 for (int i = 0; i < oldmodels.length; i++)
1092 for (int n = 0; n < modelfilenames.length; n++)
1094 if (modelfilenames[n] == oldmodels[i])
1096 oldmodels[i] = null;
1100 if (oldmodels[i] != null)
1107 String[] oldmfn = new String[oldm];
1109 for (int i = 0; i < oldmodels.length; i++)
1111 if (oldmodels[i] != null)
1113 oldmfn[oldm++] = oldmodels[i];
1116 // deregister the Jmol instance for these structures - we'll add
1117 // ourselves again at the end for the current structure set.
1118 getSsm().removeStructureViewerListener(this, oldmfn);
1121 refreshPdbEntries();
1122 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1124 String fileName = modelfilenames[modelnum];
1125 boolean foundEntry = false;
1126 StructureFile pdb = null;
1127 String pdbfile = null;
1128 // model was probably loaded inline - so check the pdb file hashcode
1131 // calculate essential attributes for the pdb data imported inline.
1132 // prolly need to resolve modelnumber properly - for now just use our
1134 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1137 // search pdbentries and sequences to find correct pdbentry for this
1139 for (int pe = 0; pe < getPdbCount(); pe++)
1141 boolean matches = false;
1142 if (fileName == null)
1145 // see JAL-623 - need method of matching pasted data up
1147 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1148 pdbfile, AppletFormatAdapter.PASTE,
1149 getIProgressIndicator());
1150 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1157 File fl = new File(getPdbEntry(pe).getFile());
1158 matches = fl.equals(new File(fileName));
1162 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1165 // to be tested. See mantis bug
1166 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1167 String protocol = AppletFormatAdapter.URL;
1172 protocol = AppletFormatAdapter.FILE;
1174 } catch (Exception e)
1179 // Explicitly map to the filename used by Jmol ;
1180 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1181 fileName, protocol, getIProgressIndicator());
1182 // pdbentry[pe].getFile(), protocol);
1188 // add an entry for every chain in the model
1189 for (int i = 0; i < pdb.getChains().size(); i++)
1191 String chid = new String(pdb.getId() + ":"
1192 + pdb.getChains().elementAt(i).id);
1193 chainFile.put(chid, fileName);
1194 chainNames.addElement(chid);
1196 notifyLoaded = true;
1200 if (!foundEntry && associateNewStructs)
1202 // this is a foreign pdb file that jalview doesn't know about - add
1203 // it to the dataset and try to find a home - either on a matching
1204 // sequence or as a new sequence.
1205 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1207 // parse pdb file into a chain, etc.
1208 // locate best match for pdb in associated views and add mapping to
1210 // if properly registered then
1211 notifyLoaded = true;
1216 // so finally, update the jmol bits and pieces
1217 // if (jmolpopup != null)
1219 // // potential for deadlock here:
1220 // // jmolpopup.updateComputedMenus();
1222 if (!isLoadingFromArchive())
1224 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1226 // register ourselves as a listener and notify the gui that it needs to
1228 getSsm().addStructureViewerListener(this);
1231 FeatureRenderer fr = getFeatureRenderer(null);
1237 loadNotifiesHandled++;
1239 setLoadingFromArchive(false);
1242 protected abstract IProgressIndicator getIProgressIndicator();
1244 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1246 notifyAtomPicked(iatom, strMeasure, null);
1249 public abstract void notifyScriptTermination(String strStatus,
1253 * display a message echoed from the jmol viewer
1257 public abstract void sendConsoleEcho(String strEcho); /*
1258 * { showConsole(true);
1260 * history.append("\n" +
1264 // /End JmolStatusListener
1265 // /////////////////////////////
1269 * status message - usually the response received after a script
1272 public abstract void sendConsoleMessage(String strStatus);
1275 public void setCallbackFunction(String callbackType,
1276 String callbackFunction)
1278 System.err.println("Ignoring set-callback request to associate "
1279 + callbackType + " with function " + callbackFunction);
1283 public void setJalviewColourScheme(ColourSchemeI cs)
1285 colourBySequence = false;
1293 StringBuilder command = new StringBuilder(128);
1294 command.append("select *;color white;");
1295 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1297 for (String res : residueSet)
1299 Color col = cs.findColour(res.charAt(0));
1300 command.append("select " + res + ";color[" + col.getRed() + ","
1301 + col.getGreen() + "," + col.getBlue() + "];");
1304 evalStateCommand(command.toString());
1308 public void showHelp()
1310 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1314 * open the URL somehow
1318 public abstract void showUrl(String url, String target);
1321 * called when the binding thinks the UI needs to be refreshed after a Jmol
1322 * state change. this could be because structures were loaded, or because an
1323 * error has occured.
1325 public abstract void refreshGUI();
1328 * called to show or hide the associated console window container.
1332 public abstract void showConsole(boolean show);
1335 * @param renderPanel
1337 * - when true will initialise jmol's file IO system (should be false
1338 * in applet context)
1340 * @param documentBase
1342 * @param commandOptions
1344 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1345 String htmlName, URL documentBase, URL codeBase,
1346 String commandOptions)
1348 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1349 codeBase, commandOptions, null, null);
1354 * @param renderPanel
1356 * - when true will initialise jmol's file IO system (should be false
1357 * in applet context)
1359 * @param documentBase
1361 * @param commandOptions
1362 * @param consolePanel
1363 * - panel to contain Jmol console
1364 * @param buttonsToShow
1365 * - buttons to show on the console, in ordr
1367 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1368 String htmlName, URL documentBase, URL codeBase,
1369 String commandOptions, final Container consolePanel,
1370 String buttonsToShow)
1372 if (commandOptions == null)
1374 commandOptions = "";
1376 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1377 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1378 + ((Object) this).toString(), documentBase, codeBase,
1379 commandOptions, this);
1381 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1383 console = createJmolConsole(consolePanel, buttonsToShow);
1384 if (consolePanel != null)
1386 consolePanel.addComponentListener(this);
1392 protected abstract JmolAppConsoleInterface createJmolConsole(
1393 Container consolePanel, String buttonsToShow);
1395 protected org.jmol.api.JmolAppConsoleInterface console = null;
1397 public void setBackgroundColour(java.awt.Color col)
1400 viewer.evalStringQuiet("background [" + col.getRed() + ","
1401 + col.getGreen() + "," + col.getBlue() + "];");
1406 public Dimension resizeInnerPanel(String data)
1408 // Jalview doesn't honour resize panel requests
1415 protected void closeConsole()
1417 if (console != null)
1421 console.setVisible(false);
1424 } catch (Exception x)
1433 * ComponentListener method
1436 public void componentMoved(ComponentEvent e)
1441 * ComponentListener method
1444 public void componentResized(ComponentEvent e)
1449 * ComponentListener method
1452 public void componentShown(ComponentEvent e)
1458 * ComponentListener method
1461 public void componentHidden(ComponentEvent e)