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.script.T;
59 import org.jmol.viewer.JC;
60 import org.jmol.viewer.Viewer;
62 public abstract class JalviewJmolBinding extends AAStructureBindingModel
63 implements JmolStatusListener, JmolSelectionListener,
67 * state flag used to check if the Jmol viewer's paint method can be called
69 private boolean finishedInit = false;
71 boolean allChainsSelected = false;
74 * when true, try to search the associated datamodel for sequences that are
75 * associated with any unknown structures in the Jmol view.
77 private boolean associateNewStructs = false;
79 Vector<String> atomsPicked = new Vector<String>();
81 public Vector<String> chainNames;
83 Hashtable<String, String> chainFile;
85 public String fileLoadingError;
88 * the default or current model displayed if the model cannot be identified
89 * from the selection message
93 // protected JmolGenericPopup jmolpopup; // not used - remove?
102 * current set of model filenames loaded in the Jmol instance
104 String[] modelFileNames = null;
106 StringBuffer resetLastRes = new StringBuffer();
108 public Viewer viewer;
110 public JalviewJmolBinding(StructureSelectionManager ssm,
111 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
114 super(ssm, pdbentry, sequenceIs, chains, protocol);
116 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
117 * "jalviewJmol", ap.av.applet .getDocumentBase(),
118 * ap.av.applet.getCodeBase(), "", this);
120 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
124 public JalviewJmolBinding(StructureSelectionManager ssm,
125 SequenceI[][] seqs, Viewer theViewer)
130 viewer.setJmolStatusListener(this);
131 viewer.addSelectionListener(this);
135 * construct a title string for the viewer window based on the data jalview
140 public String getViewerTitle()
142 return getViewerTitle("Jmol", true);
146 * prepare the view for a given set of models/chains. chainList contains
147 * strings of the form 'pdbfilename:Chaincode'
150 * list of chains to make visible
152 public void centerViewer(Vector<String> chainList)
154 StringBuilder cmd = new StringBuilder(128);
156 for (String lbl : chainList)
162 mlength = lbl.indexOf(":", p);
163 } while (p < mlength && mlength < (lbl.length() - 2));
164 // TODO: lookup each pdb id and recover proper model number for it.
165 cmd.append(":" + lbl.substring(mlength + 1) + " /"
166 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
168 if (cmd.length() > 0)
170 cmd.setLength(cmd.length() - 4);
172 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
175 public void closeViewer()
177 viewer.acm.setModeMouse(JC.MOUSE_NONE);
178 // remove listeners for all structures in viewer
179 getSsm().removeStructureViewerListener(this, this.getPdbFile());
180 // and shut down jmol
181 viewer.evalStringQuiet("zap");
182 viewer.setJmolStatusListener(null);
185 releaseUIResources();
188 public void colourByChain()
190 colourBySequence = false;
191 // TODO: colour by chain should colour each chain distinctly across all
193 // TODO: http://issues.jalview.org/browse/JAL-628
194 evalStateCommand("select *;color chain");
197 public void colourByCharge()
199 colourBySequence = false;
200 evalStateCommand("select *;color white;select ASP,GLU;color red;"
201 + "select LYS,ARG;color blue;select CYS;color yellow");
205 * superpose the structures associated with sequences in the alignment
206 * according to their corresponding positions.
208 public void superposeStructures(AlignmentI alignment)
210 superposeStructures(alignment, -1, 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)
221 public void superposeStructures(AlignmentI alignment, int refStructure)
223 superposeStructures(alignment, refStructure, null);
227 * superpose the structures associated with sequences in the alignment
228 * according to their corresponding positions. ded)
230 * @param refStructure
231 * - select which pdb file to use as reference (default is -1 - the
232 * first structure in the alignment)
236 public void superposeStructures(AlignmentI alignment, int refStructure,
237 ColumnSelection hiddenCols)
239 superposeStructures(new AlignmentI[]
240 { alignment }, new int[]
241 { refStructure }, new ColumnSelection[]
246 * Construct and send a command to align structures against a reference
247 * structure, based on one or more sequence alignments
250 * an array of alignments to process
251 * @param _refStructure
252 * an array of corresponding reference structures (index into pdb
253 * file array); if a negative value is passed, the first PDB file
254 * mapped to an alignment sequence is used as the reference for
257 * an array of corresponding hidden columns for each alignment
259 public void superposeStructures(AlignmentI[] _alignment,
260 int[] _refStructure, ColumnSelection[] _hiddenCols)
262 String[] files = getPdbFile();
264 if (!waitForFileLoad(files))
269 StringBuilder selectioncom = new StringBuilder(256);
270 // In principle - nSeconds specifies the speed of animation for each
271 // superposition - but is seems to behave weirdly, so we don't specify it.
272 String nSeconds = " ";
273 if (files.length > 10)
275 nSeconds = " 0.00001 ";
279 nSeconds = " " + (2.0 / files.length) + " ";
280 // if (nSeconds).substring(0,5)+" ";
282 // see JAL-1345 - should really automatically turn off the animation for
283 // large numbers of structures, but Jmol doesn't seem to allow that.
285 // union of all aligned positions are collected together.
286 for (int a = 0; a < _alignment.length; a++)
288 int refStructure = _refStructure[a];
289 AlignmentI alignment = _alignment[a];
290 ColumnSelection hiddenCols = _hiddenCols[a];
292 && selectioncom.length() > 0
293 && !selectioncom.substring(selectioncom.length() - 1).equals(
296 selectioncom.append("|");
298 // process this alignment
299 if (refStructure >= files.length)
301 System.err.println("Invalid reference structure value "
307 * 'matched' array will hold 'true' for visible alignment columns where
308 * all sequences have a residue with a mapping to the PDB structure
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 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
357 String chainCd = ":" + structures[pdbfnum].chain;
360 StringBuilder molsel = new StringBuilder();
362 for (int r = 0; r < matched.length; r++)
366 int pdbResNo = structures[pdbfnum].pdbResNo[r];
367 if (lpos != pdbResNo - 1)
373 molsel.append(chainCd);
380 // continuous run - and lpos >-1
383 // at the beginning, so add dash
393 * add final selection phrase
398 molsel.append(chainCd);
401 if (molsel.length() > 1)
403 selcom[pdbfnum] = molsel.toString();
404 selectioncom.append("((");
405 selectioncom.append(selcom[pdbfnum].substring(1,
406 selcom[pdbfnum].length() - 1));
407 selectioncom.append(" )& ");
408 selectioncom.append(pdbfnum + 1);
409 selectioncom.append(".1)");
410 if (pdbfnum < files.length - 1)
412 selectioncom.append("|");
417 selcom[pdbfnum] = null;
421 StringBuilder command = new StringBuilder(256);
422 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
424 if (pdbfnum == refStructure || selcom[pdbfnum] == null
425 || selcom[refStructure] == null)
429 command.append("echo ");
430 command.append("\"Superposing (");
431 command.append(structures[pdbfnum].pdbId);
432 command.append(") against reference (");
433 command.append(structures[refStructure].pdbId);
434 command.append(")\";\ncompare " + nSeconds);
436 command.append(Integer.toString(1 + pdbfnum));
437 command.append(".1} {");
438 command.append(Integer.toString(1 + refStructure));
439 // conformation=1 excludes alternate locations for CA (JAL-1757)
440 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
442 // for (int s = 0; s < 2; s++)
444 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
446 command.append(selcom[pdbfnum]);
447 command.append(selcom[refStructure]);
448 command.append(" ROTATE TRANSLATE;\n");
450 if (selectioncom.length() > 0)
452 System.out.println("Select regions:\n" + selectioncom.toString());
453 evalStateCommand("select *; cartoons off; backbone; select ("
454 + selectioncom.toString() + "); cartoons; ");
455 // selcom.append("; ribbons; ");
456 String cmdString = command.toString();
458 .println("Superimpose command(s):\n" + cmdString);
460 evalStateCommand(cmdString);
463 if (selectioncom.length() > 0)
464 {// finally, mark all regions that were superposed.
465 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
467 selectioncom.setLength(selectioncom.length() - 1);
469 System.out.println("Select regions:\n" + selectioncom.toString());
470 evalStateCommand("select *; cartoons off; backbone; select ("
471 + selectioncom.toString() + "); cartoons; ");
472 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
476 public void evalStateCommand(String command)
479 if (lastCommand == null || !lastCommand.equals(command))
481 System.out.println(command);
482 viewer.evalStringQuiet(command + "\n");
485 lastCommand = command;
489 * colour any structures associated with sequences in the given alignment
490 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
491 * if colourBySequence is enabled.
493 public void colourBySequence(AlignmentViewPanel alignmentv)
495 boolean showFeatures = alignmentv.getAlignViewport()
496 .isShowSequenceFeatures();
497 if (!colourBySequence || !isLoadingFinished())
501 if (getSsm() == null)
505 String[] files = getPdbFile();
507 SequenceRenderer sr = getSequenceRenderer(alignmentv);
509 FeatureRenderer fr = null;
512 fr = getFeatureRenderer(alignmentv);
514 AlignmentI alignment = alignmentv.getAlignment();
516 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(files, sr, fr, alignment))
518 for (String cbyseq : cpdbbyseq.commands)
520 executeWhenReady(cbyseq);
532 protected StructureMappingcommandSet[] getColourBySequenceCommands(
533 String[] files, SequenceRenderer sr, FeatureRenderer fr,
534 AlignmentI alignment)
537 .getColourBySequenceCommand(getSsm(), files, getSequence(), sr,
545 protected void executeWhenReady(String command)
547 evalStateCommand(command);
550 public void createImage(String file, String type, int quality)
552 System.out.println("JMOL CREATE IMAGE");
555 public String createImage(String fileName, String type,
556 Object textOrBytes, int quality)
558 System.out.println("JMOL CREATE IMAGE");
562 public String eval(String strEval)
564 // System.out.println(strEval);
565 // "# 'eval' is implemented only for the applet.";
569 // End StructureListener
570 // //////////////////////////
572 public float[][] functionXY(String functionName, int x, int y)
577 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
579 // TODO Auto-generated method stub
583 public Color getColour(int atomIndex, int pdbResNum, String chain,
586 if (getModelNum(pdbfile) < 0)
590 // TODO: verify atomIndex is selecting correct model.
591 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
592 int colour = viewer.ms.at[atomIndex]
593 .atomPropertyInt(T.color);
594 return new Color(colour);
598 * returns the current featureRenderer that should be used to colour the
605 public abstract FeatureRenderer getFeatureRenderer(
606 AlignmentViewPanel alignment);
609 * instruct the Jalview binding to update the pdbentries vector if necessary
610 * prior to matching the jmol view's contents to the list of structure files
611 * Jalview knows about.
613 public abstract void refreshPdbEntries();
615 private int getModelNum(String modelFileName)
617 String[] mfn = getPdbFile();
622 for (int i = 0; i < mfn.length; i++)
624 if (mfn[i].equalsIgnoreCase(modelFileName))
633 * map between index of model filename returned from getPdbFile and the first
634 * index of models from this file in the viewer. Note - this is not trimmed -
635 * use getPdbFile to get number of unique models.
637 private int _modelFileNameMap[];
639 // ////////////////////////////////
640 // /StructureListener
642 public synchronized String[] getPdbFile()
646 return new String[0];
648 if (modelFileNames == null)
650 String mset[] = new String[viewer.ms.mc];
651 _modelFileNameMap = new int[mset.length];
652 String m = viewer.ms.getModelFileName(0);
658 mset[0] = new File(m).getAbsolutePath();
659 } catch (AccessControlException x)
661 // usually not allowed to do this in applet
663 .println("jmolBinding: Using local file string from Jmol: "
666 if (mset[0].indexOf("/file:") != -1)
668 // applet path with docroot - discard as format won't match pdbfile
673 for (int i = 1; i < mset.length; i++)
675 m = viewer.ms.getModelFileName(i);
681 mset[j] = new File(m).getAbsolutePath();
682 } catch (AccessControlException x)
684 // usually not allowed to do this in applet, so keep raw handle
685 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
688 _modelFileNameMap[j] = i; // record the model index for the filename
689 // skip any additional models in the same file (NMR structures)
690 if ((mset[j] == null ? mset[j] != mset[j - 1]
691 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
696 modelFileNames = new String[j];
697 System.arraycopy(mset, 0, modelFileNames, 0, j);
699 return modelFileNames;
703 * map from string to applet
706 public Map<String, Object> getRegistryInfo()
708 // TODO Auto-generated method stub
713 * returns the current sequenceRenderer that should be used to colour the
720 public abstract SequenceRenderer getSequenceRenderer(
721 AlignmentViewPanel alignment);
723 // ///////////////////////////////
724 // JmolStatusListener
726 public void handlePopupMenu(int x, int y)
728 // jmolpopup.show(x, y);
729 // jmolpopup.jpiShow(x, y);
733 * Highlight zero, one or more atoms on the structure
736 public void highlightAtoms(List<AtomSpec> atoms)
740 for (AtomSpec atom : atoms)
742 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
743 atom.getChain(), atom.getPdbFile());
749 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
752 if (modelFileNames == null)
757 // look up file model number for this pdbfile
759 // may need to adjust for URLencoding here - we don't worry about that yet.
760 while (mdlNum < modelFileNames.length
761 && !pdbfile.equals(modelFileNames[mdlNum]))
765 if (mdlNum == modelFileNames.length)
771 // if (!pdbfile.equals(pdbentry.getFile()))
773 if (resetLastRes.length() > 0)
775 viewer.evalStringQuiet(resetLastRes.toString());
778 StringBuilder cmd = new StringBuilder(64);
779 cmd.append("select " + pdbResNum); // +modelNum
781 resetLastRes.setLength(0);
782 resetLastRes.append("select " + pdbResNum); // +modelNum
785 resetLastRes.append(":");
786 if (!chain.equals(" "))
789 resetLastRes.append(chain);
792 cmd.append(" /" + (mdlNum + 1));
793 resetLastRes.append("/" + (mdlNum + 1));
795 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
797 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
798 + " and not hetero; spacefill 0;");
800 cmd.append("spacefill 200;select none");
802 viewer.evalStringQuiet(cmd.toString());
807 boolean debug = true;
809 private void jmolHistory(boolean enable)
811 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
814 public void loadInline(String string)
818 // viewer.loadInline(strModel, isAppend);
820 // construct fake fullPathName and fileName so we can identify the file
822 // Then, construct pass a reader for the string to Jmol.
823 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
824 // fileName, null, reader, false, null, null, 0);
825 viewer.openStringInline(string);
828 public void mouseOverStructure(int atomIndex, String strInfo)
831 int alocsep = strInfo.indexOf("^");
832 int mdlSep = strInfo.indexOf("/");
833 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
835 if (chainSeparator == -1)
837 chainSeparator = strInfo.indexOf(".");
838 if (mdlSep > -1 && mdlSep < chainSeparator)
840 chainSeparator1 = chainSeparator;
841 chainSeparator = mdlSep;
844 // handle insertion codes
847 pdbResNum = Integer.parseInt(strInfo.substring(
848 strInfo.indexOf("]") + 1, alocsep));
853 pdbResNum = Integer.parseInt(strInfo.substring(
854 strInfo.indexOf("]") + 1, chainSeparator));
858 if (strInfo.indexOf(":") > -1)
860 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
861 strInfo.indexOf("."));
868 String pdbfilename = modelFileNames[frameNo]; // default is first or current
872 if (chainSeparator1 == -1)
874 chainSeparator1 = strInfo.indexOf(".", mdlSep);
876 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
877 chainSeparator1) : strInfo.substring(mdlSep + 1);
880 // recover PDB filename for the model hovered over.
881 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
883 while (mnumber < _modelFileNameMap[_mp])
887 pdbfilename = modelFileNames[_mp];
888 if (pdbfilename == null)
890 pdbfilename = new File(
891 viewer.ms.getModelFileName(mnumber))
895 } catch (Exception e)
900 if (lastMessage == null || !lastMessage.equals(strInfo))
902 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
905 lastMessage = strInfo;
908 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
912 System.err.println("Ignoring additional hover info: " + data
913 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
915 mouseOverStructure(atomIndex, strInfo);
919 * { if (history != null && strStatus != null &&
920 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
924 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
927 * this implements the toggle label behaviour copied from the original
928 * structure viewer, MCView
932 System.err.println("Ignoring additional pick data string " + strData);
934 int chainSeparator = strInfo.indexOf(":");
936 if (chainSeparator == -1)
938 chainSeparator = strInfo.indexOf(".");
941 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
943 String mdlString = "";
944 if ((p = strInfo.indexOf(":")) > -1)
946 picked += strInfo.substring(p + 1, strInfo.indexOf("."));
949 if ((p = strInfo.indexOf("/")) > -1)
951 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
953 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
957 if (!atomsPicked.contains(picked))
959 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
960 atomsPicked.addElement(picked);
964 viewer.evalString("select " + picked + ";label off");
965 atomsPicked.removeElement(picked);
968 // TODO: in application this happens
970 // if (scriptWindow != null)
972 // scriptWindow.sendConsoleMessage(strInfo);
973 // scriptWindow.sendConsoleMessage("\n");
979 public void notifyCallback(CBK type, Object[] data)
986 notifyFileLoaded((String) data[1], (String) data[2],
987 (String) data[3], (String) data[4],
988 ((Integer) data[5]).intValue());
992 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
994 // also highlight in alignment
996 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1000 notifyScriptTermination((String) data[2],
1001 ((Integer) data[3]).intValue());
1004 sendConsoleEcho((String) data[1]);
1007 sendConsoleMessage((data == null) ? ((String) null)
1008 : (String) data[1]);
1011 // System.err.println("Ignoring error callback.");
1021 System.err.println("Unhandled callback " + type + " "
1022 + data[1].toString());
1025 } catch (Exception e)
1027 System.err.println("Squashed Jmol callback handler error:");
1028 e.printStackTrace();
1033 public boolean notifyEnabled(CBK callbackPick)
1035 switch (callbackPick)
1051 // incremented every time a load notification is successfully handled -
1052 // lightweight mechanism for other threads to detect when they can start
1053 // referrring to new structures.
1054 private long loadNotifiesHandled = 0;
1056 public long getLoadNotifiesHandled()
1058 return loadNotifiesHandled;
1061 public void notifyFileLoaded(String fullPathName, String fileName2,
1062 String modelName, String errorMsg, int modelParts)
1064 if (errorMsg != null)
1066 fileLoadingError = errorMsg;
1070 // TODO: deal sensibly with models loaded inLine:
1071 // modelName will be null, as will fullPathName.
1073 // the rest of this routine ignores the arguments, and simply interrogates
1074 // the Jmol view to find out what structures it contains, and adds them to
1075 // the structure selection manager.
1076 fileLoadingError = null;
1077 String[] oldmodels = modelFileNames;
1078 modelFileNames = null;
1079 chainNames = new Vector<String>();
1080 chainFile = new Hashtable<String, String>();
1081 boolean notifyLoaded = false;
1082 String[] modelfilenames = getPdbFile();
1083 // first check if we've lost any structures
1084 if (oldmodels != null && oldmodels.length > 0)
1087 for (int i = 0; i < oldmodels.length; i++)
1089 for (int n = 0; n < modelfilenames.length; n++)
1091 if (modelfilenames[n] == oldmodels[i])
1093 oldmodels[i] = null;
1097 if (oldmodels[i] != null)
1104 String[] oldmfn = new String[oldm];
1106 for (int i = 0; i < oldmodels.length; i++)
1108 if (oldmodels[i] != null)
1110 oldmfn[oldm++] = oldmodels[i];
1113 // deregister the Jmol instance for these structures - we'll add
1114 // ourselves again at the end for the current structure set.
1115 getSsm().removeStructureViewerListener(this, oldmfn);
1118 refreshPdbEntries();
1119 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1121 String fileName = modelfilenames[modelnum];
1122 boolean foundEntry = false;
1123 MCview.PDBfile pdb = null;
1124 String pdbfile = null;
1125 // model was probably loaded inline - so check the pdb file hashcode
1128 // calculate essential attributes for the pdb data imported inline.
1129 // prolly need to resolve modelnumber properly - for now just use our
1131 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1134 // search pdbentries and sequences to find correct pdbentry for this
1136 for (int pe = 0; pe < getPdbCount(); pe++)
1138 boolean matches = false;
1139 if (fileName == null)
1142 // see JAL-623 - need method of matching pasted data up
1144 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1145 pdbfile, AppletFormatAdapter.PASTE);
1146 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1153 File fl = new File(getPdbEntry(pe).getFile());
1154 matches = fl.equals(new File(fileName));
1158 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1161 // to be tested. See mantis bug
1162 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1163 String protocol = AppletFormatAdapter.URL;
1168 protocol = AppletFormatAdapter.FILE;
1170 } catch (Exception e)
1175 // Explicitly map to the filename used by Jmol ;
1176 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1177 fileName, protocol);
1178 // pdbentry[pe].getFile(), protocol);
1184 // add an entry for every chain in the model
1185 for (int i = 0; i < pdb.chains.size(); i++)
1187 String chid = new String(pdb.id + ":"
1188 + pdb.chains.elementAt(i).id);
1189 chainFile.put(chid, fileName);
1190 chainNames.addElement(chid);
1192 notifyLoaded = true;
1196 if (!foundEntry && associateNewStructs)
1198 // this is a foreign pdb file that jalview doesn't know about - add
1199 // it to the dataset and try to find a home - either on a matching
1200 // sequence or as a new sequence.
1201 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1203 // parse pdb file into a chain, etc.
1204 // locate best match for pdb in associated views and add mapping to
1206 // if properly registered then
1207 notifyLoaded = true;
1212 // so finally, update the jmol bits and pieces
1213 // if (jmolpopup != null)
1215 // // potential for deadlock here:
1216 // // jmolpopup.updateComputedMenus();
1218 if (!isLoadingFromArchive())
1220 viewer.evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
1222 // register ourselves as a listener and notify the gui that it needs to
1224 getSsm().addStructureViewerListener(this);
1227 FeatureRenderer fr = getFeatureRenderer(null);
1233 loadNotifiesHandled++;
1235 setLoadingFromArchive(false);
1238 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1240 notifyAtomPicked(iatom, strMeasure, null);
1243 public abstract void notifyScriptTermination(String strStatus,
1247 * display a message echoed from the jmol viewer
1251 public abstract void sendConsoleEcho(String strEcho); /*
1252 * { showConsole(true);
1254 * history.append("\n" +
1258 // /End JmolStatusListener
1259 // /////////////////////////////
1263 * status message - usually the response received after a script
1266 public abstract void sendConsoleMessage(String strStatus);
1268 public void setCallbackFunction(String callbackType,
1269 String callbackFunction)
1271 System.err.println("Ignoring set-callback request to associate "
1272 + callbackType + " with function " + callbackFunction);
1276 public void setJalviewColourScheme(ColourSchemeI cs)
1278 colourBySequence = false;
1286 StringBuilder command = new StringBuilder(128);
1287 command.append("select *;color white;");
1288 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1290 for (String res : residueSet)
1292 Color col = cs.findColour(res.charAt(0));
1293 command.append("select " + res + ";color[" + col.getRed() + ","
1294 + col.getGreen() + "," + col.getBlue() + "];");
1297 evalStateCommand(command.toString());
1301 public void showHelp()
1303 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1307 * open the URL somehow
1311 public abstract void showUrl(String url, String target);
1314 * called when the binding thinks the UI needs to be refreshed after a Jmol
1315 * state change. this could be because structures were loaded, or because an
1316 * error has occured.
1318 public abstract void refreshGUI();
1321 * called to show or hide the associated console window container.
1325 public abstract void showConsole(boolean show);
1328 * @param renderPanel
1330 * - when true will initialise jmol's file IO system (should be false
1331 * in applet context)
1333 * @param documentBase
1335 * @param commandOptions
1337 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1338 String htmlName, URL documentBase, URL codeBase,
1339 String commandOptions)
1341 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1342 codeBase, commandOptions, null, null);
1347 * @param renderPanel
1349 * - when true will initialise jmol's file IO system (should be false
1350 * in applet context)
1352 * @param documentBase
1354 * @param commandOptions
1355 * @param consolePanel
1356 * - panel to contain Jmol console
1357 * @param buttonsToShow
1358 * - buttons to show on the console, in ordr
1360 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1361 String htmlName, URL documentBase, URL codeBase,
1362 String commandOptions, final Container consolePanel,
1363 String buttonsToShow)
1365 if (commandOptions == null)
1367 commandOptions = "";
1369 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1370 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1371 + ((Object) this).toString(), documentBase, codeBase,
1372 commandOptions, this);
1374 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1376 console = createJmolConsole(consolePanel, buttonsToShow);
1377 if (consolePanel != null)
1379 consolePanel.addComponentListener(this);
1385 protected abstract JmolAppConsoleInterface createJmolConsole(
1386 Container consolePanel, String buttonsToShow);
1388 protected org.jmol.api.JmolAppConsoleInterface console = null;
1390 public void setBackgroundColour(java.awt.Color col)
1393 viewer.evalStringQuiet("background [" + col.getRed() + ","
1394 + col.getGreen() + "," + col.getBlue() + "];");
1399 public Dimension resizeInnerPanel(String data)
1401 // Jalview doesn't honour resize panel requests
1405 public boolean isFinishedInit()
1407 return finishedInit;
1410 public void setFinishedInit(boolean finishedInit)
1412 this.finishedInit = finishedInit;
1418 protected void closeConsole()
1420 if (console != null)
1424 console.setVisible(false);
1427 } catch (Exception x)
1436 * ComponentListener method
1439 public void componentMoved(ComponentEvent e)
1444 * ComponentListener method
1447 public void componentResized(ComponentEvent e)
1452 * ComponentListener method
1455 public void componentShown(ComponentEvent e)
1461 * ComponentListener method
1464 public void componentHidden(ComponentEvent e)