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 java.awt.Color;
24 import java.awt.Container;
25 import java.awt.event.ComponentEvent;
26 import java.awt.event.ComponentListener;
29 import java.security.AccessControlException;
30 import java.util.Hashtable;
31 import java.util.List;
33 import java.util.Vector;
35 import org.jmol.adapter.smarter.SmarterJmolAdapter;
36 import org.jmol.api.JmolAppConsoleInterface;
37 import org.jmol.api.JmolSelectionListener;
38 import org.jmol.api.JmolStatusListener;
39 import org.jmol.api.JmolViewer;
40 import org.jmol.constant.EnumCallback;
41 import org.jmol.popup.JmolPopup;
43 import jalview.api.AlignmentViewPanel;
44 import jalview.api.FeatureRenderer;
45 import jalview.api.SequenceRenderer;
46 import jalview.datamodel.AlignmentI;
47 import jalview.datamodel.ColumnSelection;
48 import jalview.datamodel.PDBEntry;
49 import jalview.datamodel.SequenceI;
50 import jalview.io.AppletFormatAdapter;
51 import jalview.schemes.ColourSchemeI;
52 import jalview.schemes.ResidueProperties;
53 import jalview.structure.AtomSpec;
54 import jalview.structure.StructureMappingcommandSet;
55 import jalview.structure.StructureSelectionManager;
56 import jalview.structures.models.AAStructureBindingModel;
58 public abstract class JalviewJmolBinding extends AAStructureBindingModel
59 implements JmolStatusListener, JmolSelectionListener,
63 * state flag used to check if the Jmol viewer's paint method can be called
65 private boolean finishedInit = false;
67 boolean allChainsSelected = false;
70 * when true, try to search the associated datamodel for sequences that are
71 * associated with any unknown structures in the Jmol view.
73 private boolean associateNewStructs = false;
75 Vector atomsPicked = new Vector();
77 public Vector chainNames;
81 StringBuffer eval = new StringBuffer();
83 public String fileLoadingError;
86 * the default or current model displayed if the model cannot be identified
87 * from the selection message
91 protected JmolPopup jmolpopup;
100 * current set of model filenames loaded in the Jmol instance
102 String[] modelFileNames = null;
104 StringBuffer resetLastRes = new StringBuffer();
106 public JmolViewer viewer;
108 public JalviewJmolBinding(StructureSelectionManager ssm,
109 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
112 super(ssm, pdbentry, sequenceIs, chains, protocol);
114 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
115 * "jalviewJmol", ap.av.applet .getDocumentBase(),
116 * ap.av.applet.getCodeBase(), "", this);
118 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
122 public JalviewJmolBinding(StructureSelectionManager ssm,
123 SequenceI[][] seqs, JmolViewer theViewer)
128 viewer.setJmolStatusListener(this);
129 viewer.addSelectionListener(this);
133 * construct a title string for the viewer window based on the data jalview
138 public String getViewerTitle()
140 return getViewerTitle("JMol", true);
144 * prepare the view for a given set of models/chains. chainList contains
145 * strings of the form 'pdbfilename:Chaincode'
148 * list of chains to make visible
150 public void centerViewer(Vector chainList)
152 StringBuffer cmd = new StringBuffer();
155 for (int i = 0, iSize = chainList.size(); i < iSize; i++)
158 lbl = (String) chainList.elementAt(i);
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((String) 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.setModeMouse(org.jmol.viewer.JmolConstants.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 viewer.evalStringQuiet(command + "\n");
484 lastCommand = command;
488 * colour any structures associated with sequences in the given alignment
489 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
490 * if colourBySequence is enabled.
492 public void colourBySequence(boolean showFeatures,
493 jalview.api.AlignmentViewPanel alignmentv)
495 if (!colourBySequence || !isLoadingFinished())
499 if (getSsm() == null)
503 String[] files = getPdbFile();
505 SequenceRenderer sr = getSequenceRenderer(alignmentv);
507 FeatureRenderer fr = null;
510 fr = getFeatureRenderer(alignmentv);
512 AlignmentI alignment = alignmentv.getAlignment();
514 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(files, sr, fr, alignment))
516 for (String cbyseq : cpdbbyseq.commands)
518 executeWhenReady(cbyseq);
530 protected StructureMappingcommandSet[] getColourBySequenceCommands(
531 String[] files, SequenceRenderer sr, FeatureRenderer fr,
532 AlignmentI alignment)
535 .getColourBySequenceCommand(getSsm(), files, getSequence(), sr,
543 protected void executeWhenReady(String command)
545 evalStateCommand(command);
548 public void createImage(String file, String type, int quality)
550 System.out.println("JMOL CREATE IMAGE");
553 public String createImage(String fileName, String type,
554 Object textOrBytes, int quality)
556 System.out.println("JMOL CREATE IMAGE");
560 public String eval(String strEval)
562 // System.out.println(strEval);
563 // "# 'eval' is implemented only for the applet.";
567 // End StructureListener
568 // //////////////////////////
570 public float[][] functionXY(String functionName, int x, int y)
575 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
577 // TODO Auto-generated method stub
581 public Color getColour(int atomIndex, int pdbResNum, String chain,
584 if (getModelNum(pdbfile) < 0)
588 // TODO: verify atomIndex is selecting correct model.
589 return new Color(viewer.getAtomArgb(atomIndex));
593 * returns the current featureRenderer that should be used to colour the
600 public abstract FeatureRenderer getFeatureRenderer(
601 AlignmentViewPanel alignment);
604 * instruct the Jalview binding to update the pdbentries vector if necessary
605 * prior to matching the jmol view's contents to the list of structure files
606 * Jalview knows about.
608 public abstract void refreshPdbEntries();
610 private int getModelNum(String modelFileName)
612 String[] mfn = getPdbFile();
617 for (int i = 0; i < mfn.length; i++)
619 if (mfn[i].equalsIgnoreCase(modelFileName))
628 * map between index of model filename returned from getPdbFile and the first
629 * index of models from this file in the viewer. Note - this is not trimmed -
630 * use getPdbFile to get number of unique models.
632 private int _modelFileNameMap[];
634 // ////////////////////////////////
635 // /StructureListener
637 public synchronized String[] getPdbFile()
641 return new String[0];
643 if (modelFileNames == null)
646 String mset[] = new String[viewer.getModelCount()];
647 _modelFileNameMap = new int[mset.length];
649 String m = viewer.getModelFileName(0);
654 mset[0] = new File(m).getAbsolutePath();
655 } catch (AccessControlException x)
657 // usually not allowed to do this in applet, so keep raw handle
659 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
662 for (int i = 1; i < mset.length; i++)
664 m = viewer.getModelFileName(i);
669 mset[j] = new File(m).getAbsolutePath();
670 } catch (AccessControlException x)
672 // usually not allowed to do this in applet, so keep raw handle
674 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
677 _modelFileNameMap[j] = i; // record the model index for the filename
678 // skip any additional models in the same file (NMR structures)
679 if ((mset[j] == null ? mset[j] != mset[j - 1]
680 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
685 modelFileNames = new String[j];
686 System.arraycopy(mset, 0, modelFileNames, 0, j);
688 return modelFileNames;
692 * map from string to applet
695 public Map<String, Object> getRegistryInfo()
697 // TODO Auto-generated method stub
702 * returns the current sequenceRenderer that should be used to colour the
709 public abstract SequenceRenderer getSequenceRenderer(
710 AlignmentViewPanel alignment);
712 // ///////////////////////////////
713 // JmolStatusListener
715 public void handlePopupMenu(int x, int y)
717 jmolpopup.show(x, y);
721 * Highlight zero, one or more atoms on the structure
724 public void highlightAtoms(List<AtomSpec> atoms)
728 for (AtomSpec atom : atoms)
730 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
731 atom.getChain(), atom.getPdbFile());
737 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
740 if (modelFileNames == null)
745 // look up file model number for this pdbfile
748 // may need to adjust for URLencoding here - we don't worry about that yet.
749 while (mdlNum < modelFileNames.length
750 && !pdbfile.equals(modelFileNames[mdlNum]))
752 // System.out.println("nomatch:"+pdbfile+"\nmodelfn:"+fn);
755 if (mdlNum == modelFileNames.length)
761 // if (!pdbfile.equals(pdbentry.getFile()))
763 if (resetLastRes.length() > 0)
765 viewer.evalStringQuiet(resetLastRes.toString());
769 eval.append("select " + pdbResNum); // +modelNum
771 resetLastRes.setLength(0);
772 resetLastRes.append("select " + pdbResNum); // +modelNum
775 resetLastRes.append(":");
776 if (!chain.equals(" "))
779 resetLastRes.append(chain);
782 eval.append(" /" + (mdlNum + 1));
783 resetLastRes.append("/" + (mdlNum + 1));
785 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
787 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
788 + " and not hetero; spacefill 0;");
790 eval.append("spacefill 200;select none");
792 viewer.evalStringQuiet(eval.toString());
797 boolean debug = true;
799 private void jmolHistory(boolean enable)
801 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
804 public void loadInline(String string)
808 // viewer.loadInline(strModel, isAppend);
810 // construct fake fullPathName and fileName so we can identify the file
812 // Then, construct pass a reader for the string to Jmol.
813 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
814 // fileName, null, reader, false, null, null, 0);
815 viewer.openStringInline(string);
818 public void mouseOverStructure(int atomIndex, String strInfo)
821 int alocsep = strInfo.indexOf("^");
822 int mdlSep = strInfo.indexOf("/");
823 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
825 if (chainSeparator == -1)
827 chainSeparator = strInfo.indexOf(".");
828 if (mdlSep > -1 && mdlSep < chainSeparator)
830 chainSeparator1 = chainSeparator;
831 chainSeparator = mdlSep;
834 // handle insertion codes
837 pdbResNum = Integer.parseInt(strInfo.substring(
838 strInfo.indexOf("]") + 1, alocsep));
843 pdbResNum = Integer.parseInt(strInfo.substring(
844 strInfo.indexOf("]") + 1, chainSeparator));
848 if (strInfo.indexOf(":") > -1)
850 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
851 strInfo.indexOf("."));
858 String pdbfilename = modelFileNames[frameNo]; // default is first or current
862 if (chainSeparator1 == -1)
864 chainSeparator1 = strInfo.indexOf(".", mdlSep);
866 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
867 chainSeparator1) : strInfo.substring(mdlSep + 1);
870 // recover PDB filename for the model hovered over.
871 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
873 while (mnumber < _modelFileNameMap[_mp])
877 pdbfilename = modelFileNames[_mp];
878 if (pdbfilename == null)
880 pdbfilename = new File(viewer.getModelFileName(mnumber))
884 } catch (Exception e)
889 if (lastMessage == null || !lastMessage.equals(strInfo))
891 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
894 lastMessage = strInfo;
897 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
901 System.err.println("Ignoring additional hover info: " + data
902 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
904 mouseOverStructure(atomIndex, strInfo);
908 * { if (history != null && strStatus != null &&
909 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
913 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
916 * this implements the toggle label behaviour copied from the original
917 * structure viewer, MCView
921 System.err.println("Ignoring additional pick data string " + strData);
923 int chainSeparator = strInfo.indexOf(":");
925 if (chainSeparator == -1)
927 chainSeparator = strInfo.indexOf(".");
930 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
932 String mdlString = "";
933 if ((p = strInfo.indexOf(":")) > -1)
935 picked += strInfo.substring(p + 1, strInfo.indexOf("."));
938 if ((p = strInfo.indexOf("/")) > -1)
940 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
942 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
946 if (!atomsPicked.contains(picked))
948 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
949 atomsPicked.addElement(picked);
953 viewer.evalString("select " + picked + ";label off");
954 atomsPicked.removeElement(picked);
957 // TODO: in application this happens
959 // if (scriptWindow != null)
961 // scriptWindow.sendConsoleMessage(strInfo);
962 // scriptWindow.sendConsoleMessage("\n");
968 public void notifyCallback(EnumCallback type, Object[] data)
975 notifyFileLoaded((String) data[1], (String) data[2],
976 (String) data[3], (String) data[4],
977 ((Integer) data[5]).intValue());
981 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
983 // also highlight in alignment
985 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
989 notifyScriptTermination((String) data[2],
990 ((Integer) data[3]).intValue());
993 sendConsoleEcho((String) data[1]);
996 sendConsoleMessage((data == null) ? ((String) null)
1000 // System.err.println("Ignoring error callback.");
1010 System.err.println("Unhandled callback " + type + " "
1011 + data[1].toString());
1014 } catch (Exception e)
1016 System.err.println("Squashed Jmol callback handler error:");
1017 e.printStackTrace();
1022 public boolean notifyEnabled(EnumCallback callbackPick)
1024 switch (callbackPick)
1044 // incremented every time a load notification is successfully handled -
1045 // lightweight mechanism for other threads to detect when they can start
1046 // referrring to new structures.
1047 private long loadNotifiesHandled = 0;
1049 public long getLoadNotifiesHandled()
1051 return loadNotifiesHandled;
1054 public void notifyFileLoaded(String fullPathName, String fileName2,
1055 String modelName, String errorMsg, int modelParts)
1057 if (errorMsg != null)
1059 fileLoadingError = errorMsg;
1063 // TODO: deal sensibly with models loaded inLine:
1064 // modelName will be null, as will fullPathName.
1066 // the rest of this routine ignores the arguments, and simply interrogates
1067 // the Jmol view to find out what structures it contains, and adds them to
1068 // the structure selection manager.
1069 fileLoadingError = null;
1070 String[] oldmodels = modelFileNames;
1071 modelFileNames = null;
1072 chainNames = new Vector();
1073 chainFile = new Hashtable();
1074 boolean notifyLoaded = false;
1075 String[] modelfilenames = getPdbFile();
1076 // first check if we've lost any structures
1077 if (oldmodels != null && oldmodels.length > 0)
1080 for (int i = 0; i < oldmodels.length; i++)
1082 for (int n = 0; n < modelfilenames.length; n++)
1084 if (modelfilenames[n] == oldmodels[i])
1086 oldmodels[i] = null;
1090 if (oldmodels[i] != null)
1097 String[] oldmfn = new String[oldm];
1099 for (int i = 0; i < oldmodels.length; i++)
1101 if (oldmodels[i] != null)
1103 oldmfn[oldm++] = oldmodels[i];
1106 // deregister the Jmol instance for these structures - we'll add
1107 // ourselves again at the end for the current structure set.
1108 getSsm().removeStructureViewerListener(this, oldmfn);
1111 refreshPdbEntries();
1112 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1114 String fileName = modelfilenames[modelnum];
1115 boolean foundEntry = false;
1116 MCview.PDBfile pdb = null;
1117 String pdbfile = null, pdbfhash = null;
1118 // model was probably loaded inline - so check the pdb file hashcode
1121 // calculate essential attributes for the pdb data imported inline.
1122 // prolly need to resolve modelnumber properly - for now just use our
1124 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1126 pdbfhash = "" + pdbfile.hashCode();
1128 // search pdbentries and sequences to find correct pdbentry for this
1130 for (int pe = 0; pe < getPdbCount(); pe++)
1132 boolean matches = false;
1133 if (fileName == null)
1136 // see JAL-623 - need method of matching pasted data up
1138 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1139 pdbfile, AppletFormatAdapter.PASTE);
1140 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1148 if (matches = (fl = new File(getPdbEntry(pe).getFile()))
1149 .equals(new File(fileName)))
1152 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1155 // to be tested. See mantis bug
1156 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1157 String protocol = AppletFormatAdapter.URL;
1162 protocol = AppletFormatAdapter.FILE;
1164 } catch (Exception e)
1169 // Explicitly map to the filename used by Jmol ;
1170 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1171 fileName, protocol);
1172 // pdbentry[pe].getFile(), protocol);
1178 // add an entry for every chain in the model
1179 for (int i = 0; i < pdb.chains.size(); i++)
1181 String chid = new String(pdb.id + ":"
1182 + pdb.chains.elementAt(i).id);
1183 chainFile.put(chid, fileName);
1184 chainNames.addElement(chid);
1186 notifyLoaded = true;
1190 if (!foundEntry && associateNewStructs)
1192 // this is a foreign pdb file that jalview doesn't know about - add
1193 // it to the dataset and try to find a home - either on a matching
1194 // sequence or as a new sequence.
1195 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1197 // parse pdb file into a chain, etc.
1198 // locate best match for pdb in associated views and add mapping to
1200 // if properly registered then
1201 notifyLoaded = true;
1206 // so finally, update the jmol bits and pieces
1207 if (jmolpopup != null)
1209 // potential for deadlock here:
1210 // jmolpopup.updateComputedMenus();
1212 if (!isLoadingFromArchive())
1214 viewer.evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
1216 // register ourselves as a listener and notify the gui that it needs to
1218 getSsm().addStructureViewerListener(this);
1221 FeatureRenderer fr = getFeatureRenderer(null);
1227 loadNotifiesHandled++;
1229 setLoadingFromArchive(false);
1232 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1234 notifyAtomPicked(iatom, strMeasure, null);
1237 public abstract void notifyScriptTermination(String strStatus,
1241 * display a message echoed from the jmol viewer
1245 public abstract void sendConsoleEcho(String strEcho); /*
1246 * { showConsole(true);
1248 * history.append("\n" +
1252 // /End JmolStatusListener
1253 // /////////////////////////////
1257 * status message - usually the response received after a script
1260 public abstract void sendConsoleMessage(String strStatus);
1262 public void setCallbackFunction(String callbackType,
1263 String callbackFunction)
1265 System.err.println("Ignoring set-callback request to associate "
1266 + callbackType + " with function " + callbackFunction);
1270 public void setJalviewColourScheme(ColourSchemeI cs)
1272 colourBySequence = false;
1280 StringBuilder command = new StringBuilder(128);
1281 command.append("select *;color white;");
1282 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1284 for (String res : residueSet)
1286 Color col = cs.findColour(res.charAt(0));
1287 command.append("select " + res + ";color[" + col.getRed() + ","
1288 + col.getGreen() + "," + col.getBlue() + "];");
1291 evalStateCommand(command.toString());
1295 public void showHelp()
1297 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1301 * open the URL somehow
1305 public abstract void showUrl(String url, String target);
1308 * called when the binding thinks the UI needs to be refreshed after a Jmol
1309 * state change. this could be because structures were loaded, or because an
1310 * error has occured.
1312 public abstract void refreshGUI();
1315 * called to show or hide the associated console window container.
1319 public abstract void showConsole(boolean show);
1322 * @param renderPanel
1324 * - when true will initialise jmol's file IO system (should be false
1325 * in applet context)
1327 * @param documentBase
1329 * @param commandOptions
1331 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1332 String htmlName, URL documentBase, URL codeBase,
1333 String commandOptions)
1335 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1336 codeBase, commandOptions, null, null);
1341 * @param renderPanel
1343 * - when true will initialise jmol's file IO system (should be false
1344 * in applet context)
1346 * @param documentBase
1348 * @param commandOptions
1349 * @param consolePanel
1350 * - panel to contain Jmol console
1351 * @param buttonsToShow
1352 * - buttons to show on the console, in ordr
1354 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1355 String htmlName, URL documentBase, URL codeBase,
1356 String commandOptions, final Container consolePanel,
1357 String buttonsToShow)
1359 if (commandOptions == null)
1361 commandOptions = "";
1363 viewer = JmolViewer.allocateViewer(renderPanel,
1364 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1365 + ((Object) this).toString(), documentBase, codeBase,
1366 commandOptions, this);
1368 console = createJmolConsole(viewer, consolePanel, buttonsToShow);
1369 if (consolePanel != null)
1371 consolePanel.addComponentListener(this);
1377 protected abstract JmolAppConsoleInterface createJmolConsole(
1378 JmolViewer viewer2, Container consolePanel, String buttonsToShow);
1380 protected org.jmol.api.JmolAppConsoleInterface console = null;
1382 public void setBackgroundColour(java.awt.Color col)
1385 viewer.evalStringQuiet("background [" + col.getRed() + ","
1386 + col.getGreen() + "," + col.getBlue() + "];");
1391 public void resizeInnerPanel(String data)
1393 // Jalview doesn't honour resize panel requests
1397 public boolean isFinishedInit()
1399 return finishedInit;
1402 public void setFinishedInit(boolean finishedInit)
1404 this.finishedInit = finishedInit;
1410 protected void closeConsole()
1412 if (console != null)
1416 console.setVisible(false);
1419 } catch (Exception x)
1428 * ComponentListener method
1431 public void componentMoved(ComponentEvent e)
1436 * ComponentListener method
1439 public void componentResized(ComponentEvent e)
1444 * ComponentListener method
1447 public void componentShown(ComponentEvent e)
1453 * ComponentListener method
1456 public void componentHidden(ComponentEvent e)