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.io.AppletFormatAdapter;
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.Hashtable;
46 import java.util.List;
48 import java.util.Vector;
50 import javajs.awt.Dimension;
52 import org.jmol.adapter.smarter.SmarterJmolAdapter;
53 import org.jmol.api.JmolAppConsoleInterface;
54 import org.jmol.api.JmolSelectionListener;
55 import org.jmol.api.JmolStatusListener;
56 import org.jmol.api.JmolViewer;
57 import org.jmol.c.CBK;
58 import org.jmol.popup.JmolGenericPopup;
59 import org.jmol.script.T;
60 import org.jmol.viewer.JC;
61 import org.jmol.viewer.Viewer;
63 public abstract class JalviewJmolBinding extends AAStructureBindingModel
64 implements JmolStatusListener, JmolSelectionListener,
68 * state flag used to check if the Jmol viewer's paint method can be called
70 private boolean finishedInit = false;
72 boolean allChainsSelected = false;
75 * when true, try to search the associated datamodel for sequences that are
76 * associated with any unknown structures in the Jmol view.
78 private boolean associateNewStructs = false;
80 Vector atomsPicked = new Vector();
82 public Vector chainNames;
86 StringBuffer eval = new StringBuffer();
88 public String fileLoadingError;
91 * the default or current model displayed if the model cannot be identified
92 * from the selection message
96 protected JmolGenericPopup jmolpopup;
102 boolean loadedInline;
105 * current set of model filenames loaded in the Jmol instance
107 String[] modelFileNames = null;
109 StringBuffer resetLastRes = new StringBuffer();
111 public Viewer viewer;
113 public JalviewJmolBinding(StructureSelectionManager ssm,
114 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
117 super(ssm, pdbentry, sequenceIs, chains, protocol);
119 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
120 * "jalviewJmol", ap.av.applet .getDocumentBase(),
121 * ap.av.applet.getCodeBase(), "", this);
123 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
127 public JalviewJmolBinding(StructureSelectionManager ssm,
128 SequenceI[][] seqs, Viewer theViewer)
133 viewer.setJmolStatusListener(this);
134 viewer.addSelectionListener(this);
138 * construct a title string for the viewer window based on the data jalview
143 public String getViewerTitle()
145 return getViewerTitle("Jmol", true);
149 * prepare the view for a given set of models/chains. chainList contains
150 * strings of the form 'pdbfilename:Chaincode'
153 * list of chains to make visible
155 public void centerViewer(Vector chainList)
157 StringBuffer cmd = new StringBuffer();
160 for (int i = 0, iSize = chainList.size(); i < iSize; i++)
163 lbl = (String) chainList.elementAt(i);
167 mlength = lbl.indexOf(":", p);
168 } while (p < mlength && mlength < (lbl.length() - 2));
169 // TODO: lookup each pdb id and recover proper model number for it.
170 cmd.append(":" + lbl.substring(mlength + 1) + " /"
171 + (1 + getModelNum((String) chainFile.get(lbl))) + " or ");
173 if (cmd.length() > 0)
175 cmd.setLength(cmd.length() - 4);
177 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
180 public void closeViewer()
182 viewer.acm.setModeMouse(JC.MOUSE_NONE);
183 // remove listeners for all structures in viewer
184 getSsm().removeStructureViewerListener(this, this.getPdbFile());
185 // and shut down jmol
186 viewer.evalStringQuiet("zap");
187 viewer.setJmolStatusListener(null);
190 releaseUIResources();
193 public void colourByChain()
195 colourBySequence = false;
196 // TODO: colour by chain should colour each chain distinctly across all
198 // TODO: http://issues.jalview.org/browse/JAL-628
199 evalStateCommand("select *;color chain");
202 public void colourByCharge()
204 colourBySequence = false;
205 evalStateCommand("select *;color white;select ASP,GLU;color red;"
206 + "select LYS,ARG;color blue;select CYS;color yellow");
210 * superpose the structures associated with sequences in the alignment
211 * according to their corresponding positions.
213 public void superposeStructures(AlignmentI alignment)
215 superposeStructures(alignment, -1, null);
219 * superpose the structures associated with sequences in the alignment
220 * according to their corresponding positions. ded)
222 * @param refStructure
223 * - select which pdb file to use as reference (default is -1 - the
224 * first structure in the alignment)
226 public void superposeStructures(AlignmentI alignment, int refStructure)
228 superposeStructures(alignment, refStructure, null);
232 * superpose the structures associated with sequences in the alignment
233 * according to their corresponding positions. ded)
235 * @param refStructure
236 * - select which pdb file to use as reference (default is -1 - the
237 * first structure in the alignment)
241 public void superposeStructures(AlignmentI alignment, int refStructure,
242 ColumnSelection hiddenCols)
244 superposeStructures(new AlignmentI[]
245 { alignment }, new int[]
246 { refStructure }, new ColumnSelection[]
251 * Construct and send a command to align structures against a reference
252 * structure, based on one or more sequence alignments
255 * an array of alignments to process
256 * @param _refStructure
257 * an array of corresponding reference structures (index into pdb
258 * file array); if a negative value is passed, the first PDB file
259 * mapped to an alignment sequence is used as the reference for
262 * an array of corresponding hidden columns for each alignment
264 public void superposeStructures(AlignmentI[] _alignment,
265 int[] _refStructure, ColumnSelection[] _hiddenCols)
267 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.00001 ";
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();
463 .println("Superimpose command(s):\n" + cmdString);
465 evalStateCommand(cmdString);
468 if (selectioncom.length() > 0)
469 {// finally, mark all regions that were superposed.
470 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
472 selectioncom.setLength(selectioncom.length() - 1);
474 System.out.println("Select regions:\n" + selectioncom.toString());
475 evalStateCommand("select *; cartoons off; backbone; select ("
476 + selectioncom.toString() + "); cartoons; ");
477 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
481 public void evalStateCommand(String command)
484 if (lastCommand == null || !lastCommand.equals(command))
486 viewer.evalStringQuiet(command + "\n");
489 lastCommand = command;
493 * colour any structures associated with sequences in the given alignment
494 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
495 * if colourBySequence is enabled.
497 public void colourBySequence(boolean showFeatures,
498 jalview.api.AlignmentViewPanel alignmentv)
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(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)
540 .getColourBySequenceCommand(getSsm(), files, getSequence(), sr,
548 protected void executeWhenReady(String command)
550 evalStateCommand(command);
553 public void createImage(String file, String type, int quality)
555 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");
565 public String eval(String strEval)
567 // System.out.println(strEval);
568 // "# 'eval' is implemented only for the applet.";
572 // End StructureListener
573 // //////////////////////////
575 public float[][] functionXY(String functionName, int x, int y)
580 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
582 // TODO Auto-generated method stub
586 public Color getColour(int atomIndex, int pdbResNum, String chain,
589 if (getModelNum(pdbfile) < 0)
593 // TODO: verify atomIndex is selecting correct model.
594 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
595 int colour = viewer.ms.at[atomIndex]
596 .atomPropertyInt(T.color);
597 return new Color(colour);
601 * returns the current featureRenderer that should be used to colour the
608 public abstract FeatureRenderer getFeatureRenderer(
609 AlignmentViewPanel alignment);
612 * instruct the Jalview binding to update the pdbentries vector if necessary
613 * prior to matching the jmol view's contents to the list of structure files
614 * Jalview knows about.
616 public abstract void refreshPdbEntries();
618 private int getModelNum(String modelFileName)
620 String[] mfn = getPdbFile();
625 for (int i = 0; i < mfn.length; i++)
627 if (mfn[i].equalsIgnoreCase(modelFileName))
636 * map between index of model filename returned from getPdbFile and the first
637 * index of models from this file in the viewer. Note - this is not trimmed -
638 * use getPdbFile to get number of unique models.
640 private int _modelFileNameMap[];
642 // ////////////////////////////////
643 // /StructureListener
645 public synchronized String[] getPdbFile()
649 return new String[0];
651 if (modelFileNames == null)
653 String mset[] = new String[viewer.ms.mc];
654 _modelFileNameMap = new int[mset.length];
655 String m = viewer.ms.getModelFileName(0);
661 mset[0] = new File(m).getAbsolutePath();
662 } catch (AccessControlException x)
664 // usually not allowed to do this in applet
666 .println("jmolBinding: Using local file string from Jmol: "
669 if (mset[0].indexOf("/file:") != -1)
671 // applet path with docroot - discard as format won't match pdbfile
676 for (int i = 1; i < mset.length; i++)
678 m = viewer.ms.getModelFileName(i);
684 mset[j] = new File(m).getAbsolutePath();
685 } catch (AccessControlException x)
687 // usually not allowed to do this in applet, so keep raw handle
688 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
691 _modelFileNameMap[j] = i; // record the model index for the filename
692 // skip any additional models in the same file (NMR structures)
693 if ((mset[j] == null ? mset[j] != mset[j - 1]
694 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
699 modelFileNames = new String[j];
700 System.arraycopy(mset, 0, modelFileNames, 0, j);
702 return modelFileNames;
706 * map from string to applet
709 public Map<String, Object> getRegistryInfo()
711 // TODO Auto-generated method stub
716 * returns the current sequenceRenderer that should be used to colour the
723 public abstract SequenceRenderer getSequenceRenderer(
724 AlignmentViewPanel alignment);
726 // ///////////////////////////////
727 // JmolStatusListener
729 public void handlePopupMenu(int x, int y)
731 // jmolpopup.show(x, y);
732 jmolpopup.jpiShow(x, y);
736 * Highlight zero, one or more atoms on the structure
739 public void highlightAtoms(List<AtomSpec> atoms)
743 for (AtomSpec atom : atoms)
745 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
746 atom.getChain(), atom.getPdbFile());
752 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
755 if (modelFileNames == null)
760 // look up file model number for this pdbfile
763 // may need to adjust for URLencoding here - we don't worry about that yet.
764 while (mdlNum < modelFileNames.length
765 && !pdbfile.equals(modelFileNames[mdlNum]))
767 // System.out.println("nomatch:"+pdbfile+"\nmodelfn:"+fn);
770 if (mdlNum == modelFileNames.length)
776 // if (!pdbfile.equals(pdbentry.getFile()))
778 if (resetLastRes.length() > 0)
780 viewer.evalStringQuiet(resetLastRes.toString());
784 eval.append("select " + pdbResNum); // +modelNum
786 resetLastRes.setLength(0);
787 resetLastRes.append("select " + pdbResNum); // +modelNum
790 resetLastRes.append(":");
791 if (!chain.equals(" "))
794 resetLastRes.append(chain);
797 eval.append(" /" + (mdlNum + 1));
798 resetLastRes.append("/" + (mdlNum + 1));
800 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
802 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
803 + " and not hetero; spacefill 0;");
805 eval.append("spacefill 200;select none");
807 viewer.evalStringQuiet(eval.toString());
812 boolean debug = true;
814 private void jmolHistory(boolean enable)
816 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
819 public void loadInline(String string)
823 // viewer.loadInline(strModel, isAppend);
825 // construct fake fullPathName and fileName so we can identify the file
827 // Then, construct pass a reader for the string to Jmol.
828 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
829 // fileName, null, reader, false, null, null, 0);
830 viewer.openStringInline(string);
833 public void mouseOverStructure(int atomIndex, String strInfo)
836 int alocsep = strInfo.indexOf("^");
837 int mdlSep = strInfo.indexOf("/");
838 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
840 if (chainSeparator == -1)
842 chainSeparator = strInfo.indexOf(".");
843 if (mdlSep > -1 && mdlSep < chainSeparator)
845 chainSeparator1 = chainSeparator;
846 chainSeparator = mdlSep;
849 // handle insertion codes
852 pdbResNum = Integer.parseInt(strInfo.substring(
853 strInfo.indexOf("]") + 1, alocsep));
858 pdbResNum = Integer.parseInt(strInfo.substring(
859 strInfo.indexOf("]") + 1, chainSeparator));
863 if (strInfo.indexOf(":") > -1)
865 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
866 strInfo.indexOf("."));
873 String pdbfilename = modelFileNames[frameNo]; // default is first or current
877 if (chainSeparator1 == -1)
879 chainSeparator1 = strInfo.indexOf(".", mdlSep);
881 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
882 chainSeparator1) : strInfo.substring(mdlSep + 1);
885 // recover PDB filename for the model hovered over.
886 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
888 while (mnumber < _modelFileNameMap[_mp])
892 pdbfilename = modelFileNames[_mp];
893 if (pdbfilename == null)
895 pdbfilename = new File(
896 viewer.ms.getModelFileName(mnumber))
900 } catch (Exception e)
905 if (lastMessage == null || !lastMessage.equals(strInfo))
907 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
910 lastMessage = strInfo;
913 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
917 System.err.println("Ignoring additional hover info: " + data
918 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
920 mouseOverStructure(atomIndex, strInfo);
924 * { if (history != null && strStatus != null &&
925 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
929 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
932 * this implements the toggle label behaviour copied from the original
933 * structure viewer, MCView
937 System.err.println("Ignoring additional pick data string " + strData);
939 int chainSeparator = strInfo.indexOf(":");
941 if (chainSeparator == -1)
943 chainSeparator = strInfo.indexOf(".");
946 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
948 String mdlString = "";
949 if ((p = strInfo.indexOf(":")) > -1)
951 picked += strInfo.substring(p + 1, strInfo.indexOf("."));
954 if ((p = strInfo.indexOf("/")) > -1)
956 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
958 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
962 if (!atomsPicked.contains(picked))
964 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
965 atomsPicked.addElement(picked);
969 viewer.evalString("select " + picked + ";label off");
970 atomsPicked.removeElement(picked);
973 // TODO: in application this happens
975 // if (scriptWindow != null)
977 // scriptWindow.sendConsoleMessage(strInfo);
978 // scriptWindow.sendConsoleMessage("\n");
984 public void notifyCallback(CBK type, Object[] data)
991 notifyFileLoaded((String) data[1], (String) data[2],
992 (String) data[3], (String) data[4],
993 ((Integer) data[5]).intValue());
997 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
999 // also highlight in alignment
1001 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1005 notifyScriptTermination((String) data[2],
1006 ((Integer) data[3]).intValue());
1009 sendConsoleEcho((String) data[1]);
1012 sendConsoleMessage((data == null) ? ((String) null)
1013 : (String) data[1]);
1016 // System.err.println("Ignoring error callback.");
1026 System.err.println("Unhandled callback " + type + " "
1027 + data[1].toString());
1030 } catch (Exception e)
1032 System.err.println("Squashed Jmol callback handler error:");
1033 e.printStackTrace();
1038 public boolean notifyEnabled(CBK callbackPick)
1040 switch (callbackPick)
1056 // incremented every time a load notification is successfully handled -
1057 // lightweight mechanism for other threads to detect when they can start
1058 // referrring to new structures.
1059 private long loadNotifiesHandled = 0;
1061 public long getLoadNotifiesHandled()
1063 return loadNotifiesHandled;
1066 public void notifyFileLoaded(String fullPathName, String fileName2,
1067 String modelName, String errorMsg, int modelParts)
1069 if (errorMsg != null)
1071 fileLoadingError = errorMsg;
1075 // TODO: deal sensibly with models loaded inLine:
1076 // modelName will be null, as will fullPathName.
1078 // the rest of this routine ignores the arguments, and simply interrogates
1079 // the Jmol view to find out what structures it contains, and adds them to
1080 // the structure selection manager.
1081 fileLoadingError = null;
1082 String[] oldmodels = modelFileNames;
1083 modelFileNames = null;
1084 chainNames = new Vector();
1085 chainFile = new Hashtable();
1086 boolean notifyLoaded = false;
1087 String[] modelfilenames = getPdbFile();
1088 // first check if we've lost any structures
1089 if (oldmodels != null && oldmodels.length > 0)
1092 for (int i = 0; i < oldmodels.length; i++)
1094 for (int n = 0; n < modelfilenames.length; n++)
1096 if (modelfilenames[n] == oldmodels[i])
1098 oldmodels[i] = null;
1102 if (oldmodels[i] != null)
1109 String[] oldmfn = new String[oldm];
1111 for (int i = 0; i < oldmodels.length; i++)
1113 if (oldmodels[i] != null)
1115 oldmfn[oldm++] = oldmodels[i];
1118 // deregister the Jmol instance for these structures - we'll add
1119 // ourselves again at the end for the current structure set.
1120 getSsm().removeStructureViewerListener(this, oldmfn);
1123 refreshPdbEntries();
1124 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1126 String fileName = modelfilenames[modelnum];
1127 boolean foundEntry = false;
1128 MCview.PDBfile pdb = null;
1129 String pdbfile = null, pdbfhash = null;
1130 // model was probably loaded inline - so check the pdb file hashcode
1133 // calculate essential attributes for the pdb data imported inline.
1134 // prolly need to resolve modelnumber properly - for now just use our
1136 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1138 pdbfhash = "" + pdbfile.hashCode();
1140 // search pdbentries and sequences to find correct pdbentry for this
1142 for (int pe = 0; pe < getPdbCount(); pe++)
1144 boolean matches = false;
1145 if (fileName == null)
1148 // see JAL-623 - need method of matching pasted data up
1150 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1151 pdbfile, AppletFormatAdapter.PASTE);
1152 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1159 File fl = new File(getPdbEntry(pe).getFile());
1160 matches = fl.equals(new File(fileName));
1164 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1167 // to be tested. See mantis bug
1168 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1169 String protocol = AppletFormatAdapter.URL;
1174 protocol = AppletFormatAdapter.FILE;
1176 } catch (Exception e)
1181 // Explicitly map to the filename used by Jmol ;
1182 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1183 fileName, protocol);
1184 // pdbentry[pe].getFile(), protocol);
1190 // add an entry for every chain in the model
1191 for (int i = 0; i < pdb.chains.size(); i++)
1193 String chid = new String(pdb.id + ":"
1194 + pdb.chains.elementAt(i).id);
1195 chainFile.put(chid, fileName);
1196 chainNames.addElement(chid);
1198 notifyLoaded = true;
1202 if (!foundEntry && associateNewStructs)
1204 // this is a foreign pdb file that jalview doesn't know about - add
1205 // it to the dataset and try to find a home - either on a matching
1206 // sequence or as a new sequence.
1207 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1209 // parse pdb file into a chain, etc.
1210 // locate best match for pdb in associated views and add mapping to
1212 // if properly registered then
1213 notifyLoaded = true;
1218 // so finally, update the jmol bits and pieces
1219 if (jmolpopup != null)
1221 // potential for deadlock here:
1222 // jmolpopup.updateComputedMenus();
1224 if (!isLoadingFromArchive())
1226 viewer.evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
1228 // register ourselves as a listener and notify the gui that it needs to
1230 getSsm().addStructureViewerListener(this);
1233 FeatureRenderer fr = getFeatureRenderer(null);
1239 loadNotifiesHandled++;
1241 setLoadingFromArchive(false);
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);
1274 public void setCallbackFunction(String callbackType,
1275 String callbackFunction)
1277 System.err.println("Ignoring set-callback request to associate "
1278 + callbackType + " with function " + callbackFunction);
1282 public void setJalviewColourScheme(ColourSchemeI cs)
1284 colourBySequence = false;
1292 StringBuilder command = new StringBuilder(128);
1293 command.append("select *;color white;");
1294 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1296 for (String res : residueSet)
1298 Color col = cs.findColour(res.charAt(0));
1299 command.append("select " + res + ";color[" + col.getRed() + ","
1300 + col.getGreen() + "," + col.getBlue() + "];");
1303 evalStateCommand(command.toString());
1307 public void showHelp()
1309 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1313 * open the URL somehow
1317 public abstract void showUrl(String url, String target);
1320 * called when the binding thinks the UI needs to be refreshed after a Jmol
1321 * state change. this could be because structures were loaded, or because an
1322 * error has occured.
1324 public abstract void refreshGUI();
1327 * called to show or hide the associated console window container.
1331 public abstract void showConsole(boolean show);
1334 * @param renderPanel
1336 * - when true will initialise jmol's file IO system (should be false
1337 * in applet context)
1339 * @param documentBase
1341 * @param commandOptions
1343 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1344 String htmlName, URL documentBase, URL codeBase,
1345 String commandOptions)
1347 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1348 codeBase, commandOptions, null, null);
1353 * @param renderPanel
1355 * - when true will initialise jmol's file IO system (should be false
1356 * in applet context)
1358 * @param documentBase
1360 * @param commandOptions
1361 * @param consolePanel
1362 * - panel to contain Jmol console
1363 * @param buttonsToShow
1364 * - buttons to show on the console, in ordr
1366 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1367 String htmlName, URL documentBase, URL codeBase,
1368 String commandOptions, final Container consolePanel,
1369 String buttonsToShow)
1371 if (commandOptions == null)
1373 commandOptions = "";
1375 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1376 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1377 + ((Object) this).toString(), documentBase, codeBase,
1378 commandOptions, this);
1380 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1382 console = createJmolConsole(consolePanel, buttonsToShow);
1383 if (consolePanel != null)
1385 consolePanel.addComponentListener(this);
1391 protected abstract JmolAppConsoleInterface createJmolConsole(
1392 Container consolePanel, String buttonsToShow);
1394 protected org.jmol.api.JmolAppConsoleInterface console = null;
1396 public void setBackgroundColour(java.awt.Color col)
1399 viewer.evalStringQuiet("background [" + col.getRed() + ","
1400 + col.getGreen() + "," + col.getBlue() + "];");
1405 public Dimension resizeInnerPanel(String data)
1407 // Jalview doesn't honour resize panel requests
1411 public boolean isFinishedInit()
1413 return finishedInit;
1416 public void setFinishedInit(boolean finishedInit)
1418 this.finishedInit = finishedInit;
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)