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,
66 boolean allChainsSelected = false;
69 * when true, try to search the associated datamodel for sequences that are
70 * associated with any unknown structures in the Jmol view.
72 private boolean associateNewStructs = false;
74 Vector<String> atomsPicked = new Vector<String>();
76 public Vector<String> chainNames;
78 Hashtable<String, String> chainFile;
80 public String fileLoadingError;
83 * the default or current model displayed if the model cannot be identified
84 * from the selection message
88 // protected JmolGenericPopup jmolpopup; // not used - remove?
97 * current set of model filenames loaded in the Jmol instance
99 String[] modelFileNames = null;
101 StringBuffer resetLastRes = new StringBuffer();
103 public Viewer viewer;
105 public JalviewJmolBinding(StructureSelectionManager ssm,
106 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
109 super(ssm, pdbentry, sequenceIs, chains, protocol);
111 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
112 * "jalviewJmol", ap.av.applet .getDocumentBase(),
113 * ap.av.applet.getCodeBase(), "", this);
115 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
119 public JalviewJmolBinding(StructureSelectionManager ssm,
120 SequenceI[][] seqs, Viewer theViewer)
125 viewer.setJmolStatusListener(this);
126 viewer.addSelectionListener(this);
130 * construct a title string for the viewer window based on the data jalview
135 public String getViewerTitle()
137 return getViewerTitle("Jmol", true);
141 * prepare the view for a given set of models/chains. chainList contains
142 * strings of the form 'pdbfilename:Chaincode'
145 * list of chains to make visible
147 public void centerViewer(Vector<String> chainList)
149 StringBuilder cmd = new StringBuilder(128);
151 for (String lbl : chainList)
157 mlength = lbl.indexOf(":", p);
158 } while (p < mlength && mlength < (lbl.length() - 2));
159 // TODO: lookup each pdb id and recover proper model number for it.
160 cmd.append(":" + lbl.substring(mlength + 1) + " /"
161 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
163 if (cmd.length() > 0)
165 cmd.setLength(cmd.length() - 4);
167 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
170 public void closeViewer()
172 viewer.acm.setModeMouse(JC.MOUSE_NONE);
173 // remove listeners for all structures in viewer
174 getSsm().removeStructureViewerListener(this, this.getPdbFile());
175 // and shut down jmol
176 viewer.evalStringQuiet("zap");
177 viewer.setJmolStatusListener(null);
180 releaseUIResources();
183 public void colourByChain()
185 colourBySequence = false;
186 // TODO: colour by chain should colour each chain distinctly across all
188 // TODO: http://issues.jalview.org/browse/JAL-628
189 evalStateCommand("select *;color chain");
192 public void colourByCharge()
194 colourBySequence = false;
195 evalStateCommand("select *;color white;select ASP,GLU;color red;"
196 + "select LYS,ARG;color blue;select CYS;color yellow");
200 * superpose the structures associated with sequences in the alignment
201 * according to their corresponding positions.
203 public void superposeStructures(AlignmentI alignment)
205 superposeStructures(alignment, -1, null);
209 * superpose the structures associated with sequences in the alignment
210 * according to their corresponding positions. ded)
212 * @param refStructure
213 * - select which pdb file to use as reference (default is -1 - the
214 * first structure in the alignment)
216 public void superposeStructures(AlignmentI alignment, int refStructure)
218 superposeStructures(alignment, refStructure, null);
222 * superpose the structures associated with sequences in the alignment
223 * according to their corresponding positions. ded)
225 * @param refStructure
226 * - select which pdb file to use as reference (default is -1 - the
227 * first structure in the alignment)
231 public void superposeStructures(AlignmentI alignment, int refStructure,
232 ColumnSelection hiddenCols)
234 superposeStructures(new AlignmentI[] { alignment },
235 new int[] { refStructure },
236 new ColumnSelection[] { hiddenCols });
240 * Construct and send a command to align structures against a reference
241 * structure, based on one or more sequence alignments
244 * an array of alignments to process
245 * @param _refStructure
246 * an array of corresponding reference structures (index into pdb
247 * file array); if a negative value is passed, the first PDB file
248 * mapped to an alignment sequence is used as the reference for
251 * an array of corresponding hidden columns for each alignment
253 public void superposeStructures(AlignmentI[] _alignment,
254 int[] _refStructure, ColumnSelection[] _hiddenCols)
256 while (viewer.isScriptExecuting())
261 } catch (InterruptedException i)
266 String[] files = getPdbFile();
267 if (!waitForFileLoad(files))
272 StringBuilder selectioncom = new StringBuilder(256);
273 // In principle - nSeconds specifies the speed of animation for each
274 // superposition - but is seems to behave weirdly, so we don't specify it.
275 String nSeconds = " ";
276 if (files.length > 10)
278 nSeconds = " 0.005 ";
282 nSeconds = " " + (2.0 / files.length) + " ";
283 // if (nSeconds).substring(0,5)+" ";
285 // see JAL-1345 - should really automatically turn off the animation for
286 // large numbers of structures, but Jmol doesn't seem to allow that.
288 // union of all aligned positions are collected together.
289 for (int a = 0; a < _alignment.length; a++)
291 int refStructure = _refStructure[a];
292 AlignmentI alignment = _alignment[a];
293 ColumnSelection hiddenCols = _hiddenCols[a];
295 && selectioncom.length() > 0
296 && !selectioncom.substring(selectioncom.length() - 1).equals(
299 selectioncom.append("|");
301 // process this alignment
302 if (refStructure >= files.length)
304 System.err.println("Invalid reference structure value "
310 * 'matched' array will hold 'true' for visible alignment columns where
311 * all sequences have a residue with a mapping to the PDB structure
313 boolean matched[] = new boolean[alignment.getWidth()];
314 for (int m = 0; m < matched.length; m++)
316 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
319 SuperposeData[] structures = new SuperposeData[files.length];
320 for (int f = 0; f < files.length; f++)
322 structures[f] = new SuperposeData(alignment.getWidth());
326 * Calculate the superposable alignment columns ('matched'), and the
327 * corresponding structure residue positions (structures.pdbResNo)
329 int candidateRefStructure = findSuperposableResidues(alignment,
330 matched, structures);
331 if (refStructure < 0)
334 * If no reference structure was specified, pick the first one that has
335 * a mapping in the alignment
337 refStructure = candidateRefStructure;
340 String[] selcom = new String[files.length];
342 for (boolean b : matched)
351 // TODO: bail out here because superposition illdefined?
355 * generate select statements to select regions to superimpose structures
358 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
360 String chainCd = ":" + structures[pdbfnum].chain;
363 StringBuilder molsel = new StringBuilder();
365 for (int r = 0; r < matched.length; r++)
369 int pdbResNo = structures[pdbfnum].pdbResNo[r];
370 if (lpos != pdbResNo - 1)
376 molsel.append(chainCd);
383 // continuous run - and lpos >-1
386 // at the beginning, so add dash
396 * add final selection phrase
401 molsel.append(chainCd);
404 if (molsel.length() > 1)
406 selcom[pdbfnum] = molsel.toString();
407 selectioncom.append("((");
408 selectioncom.append(selcom[pdbfnum].substring(1,
409 selcom[pdbfnum].length() - 1));
410 selectioncom.append(" )& ");
411 selectioncom.append(pdbfnum + 1);
412 selectioncom.append(".1)");
413 if (pdbfnum < files.length - 1)
415 selectioncom.append("|");
420 selcom[pdbfnum] = null;
424 StringBuilder command = new StringBuilder(256);
425 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
427 if (pdbfnum == refStructure || selcom[pdbfnum] == null
428 || selcom[refStructure] == null)
432 command.append("echo ");
433 command.append("\"Superposing (");
434 command.append(structures[pdbfnum].pdbId);
435 command.append(") against reference (");
436 command.append(structures[refStructure].pdbId);
437 command.append(")\";\ncompare " + nSeconds);
439 command.append(Integer.toString(1 + pdbfnum));
440 command.append(".1} {");
441 command.append(Integer.toString(1 + refStructure));
442 // conformation=1 excludes alternate locations for CA (JAL-1757)
443 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
445 // for (int s = 0; s < 2; s++)
447 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
449 command.append(selcom[pdbfnum]);
450 command.append(selcom[refStructure]);
451 command.append(" ROTATE TRANSLATE;\n");
453 if (selectioncom.length() > 0)
455 System.out.println("Select regions:\n" + selectioncom.toString());
456 evalStateCommand("select *; cartoons off; backbone; select ("
457 + selectioncom.toString() + "); cartoons; ");
458 // selcom.append("; ribbons; ");
459 String cmdString = command.toString();
460 System.out.println("Superimpose command(s):\n" + cmdString);
462 evalStateCommand(cmdString);
465 if (selectioncom.length() > 0)
466 {// finally, mark all regions that were superposed.
467 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
469 selectioncom.setLength(selectioncom.length() - 1);
471 System.out.println("Select regions:\n" + selectioncom.toString());
472 evalStateCommand("select *; cartoons off; backbone; select ("
473 + selectioncom.toString() + "); cartoons; ");
474 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
478 public void evalStateCommand(String command)
481 if (lastCommand == null || !lastCommand.equals(command))
483 viewer.evalStringQuiet(command + "\n");
486 lastCommand = command;
490 * colour any structures associated with sequences in the given alignment
491 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
492 * if colourBySequence is enabled.
494 public void colourBySequence(AlignmentViewPanel alignmentv)
496 boolean showFeatures = alignmentv.getAlignViewport()
497 .isShowSequenceFeatures();
498 if (!colourBySequence || !isLoadingFinished())
502 if (getSsm() == null)
506 String[] files = getPdbFile();
508 SequenceRenderer sr = getSequenceRenderer(alignmentv);
510 FeatureRenderer fr = null;
513 fr = getFeatureRenderer(alignmentv);
515 AlignmentI alignment = alignmentv.getAlignment();
517 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
518 files, sr, fr, alignment))
520 for (String cbyseq : cpdbbyseq.commands)
522 executeWhenReady(cbyseq);
534 protected StructureMappingcommandSet[] getColourBySequenceCommands(
535 String[] files, SequenceRenderer sr, FeatureRenderer fr,
536 AlignmentI alignment)
538 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
539 getSequence(), sr, fr, alignment);
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].atomPropertyInt(T.color);
593 return new Color(colour);
597 * returns the current featureRenderer that should be used to colour the
604 public abstract FeatureRenderer getFeatureRenderer(
605 AlignmentViewPanel alignment);
608 * instruct the Jalview binding to update the pdbentries vector if necessary
609 * prior to matching the jmol view's contents to the list of structure files
610 * Jalview knows about.
612 public abstract void refreshPdbEntries();
614 private int getModelNum(String modelFileName)
616 String[] mfn = getPdbFile();
621 for (int i = 0; i < mfn.length; i++)
623 if (mfn[i].equalsIgnoreCase(modelFileName))
632 * map between index of model filename returned from getPdbFile and the first
633 * index of models from this file in the viewer. Note - this is not trimmed -
634 * use getPdbFile to get number of unique models.
636 private int _modelFileNameMap[];
638 // ////////////////////////////////
639 // /StructureListener
641 public synchronized String[] getPdbFile()
645 return new String[0];
647 if (modelFileNames == null)
649 String mset[] = new String[viewer.ms.mc];
650 _modelFileNameMap = new int[mset.length];
651 String m = viewer.ms.getModelFileName(0);
657 mset[0] = new File(m).getAbsolutePath();
658 } catch (AccessControlException x)
660 // usually not allowed to do this in applet
662 .println("jmolBinding: Using local file string from Jmol: "
665 if (mset[0].indexOf("/file:") != -1)
667 // applet path with docroot - discard as format won't match pdbfile
670 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
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(viewer.ms.getModelFileName(mnumber))
894 } catch (Exception e)
899 if (lastMessage == null || !lastMessage.equals(strInfo))
901 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
904 lastMessage = strInfo;
907 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
911 System.err.println("Ignoring additional hover info: " + data
912 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
914 mouseOverStructure(atomIndex, strInfo);
918 * { if (history != null && strStatus != null &&
919 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
923 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
926 * this implements the toggle label behaviour copied from the original
927 * structure viewer, MCView
931 System.err.println("Ignoring additional pick data string " + strData);
933 int chainSeparator = strInfo.indexOf(":");
935 if (chainSeparator == -1)
937 chainSeparator = strInfo.indexOf(".");
940 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
942 String mdlString = "";
943 if ((p = strInfo.indexOf(":")) > -1)
945 picked += strInfo.substring(p, strInfo.indexOf("."));
948 if ((p = strInfo.indexOf("/")) > -1)
950 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
952 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
956 if (!atomsPicked.contains(picked))
958 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
959 atomsPicked.addElement(picked);
963 viewer.evalString("select " + picked + ";label off");
964 atomsPicked.removeElement(picked);
967 // TODO: in application this happens
969 // if (scriptWindow != null)
971 // scriptWindow.sendConsoleMessage(strInfo);
972 // scriptWindow.sendConsoleMessage("\n");
978 public void notifyCallback(CBK type, Object[] data)
985 notifyFileLoaded((String) data[1], (String) data[2],
986 (String) data[3], (String) data[4],
987 ((Integer) data[5]).intValue());
991 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
993 // also highlight in alignment
995 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
999 notifyScriptTermination((String) data[2],
1000 ((Integer) data[3]).intValue());
1003 sendConsoleEcho((String) data[1]);
1006 sendConsoleMessage((data == null) ? ((String) null)
1007 : (String) data[1]);
1010 // System.err.println("Ignoring error callback.");
1020 System.err.println("Unhandled callback " + type + " "
1021 + data[1].toString());
1024 } catch (Exception e)
1026 System.err.println("Squashed Jmol callback handler error:");
1027 e.printStackTrace();
1032 public boolean notifyEnabled(CBK callbackPick)
1034 switch (callbackPick)
1050 // incremented every time a load notification is successfully handled -
1051 // lightweight mechanism for other threads to detect when they can start
1052 // referrring to new structures.
1053 private long loadNotifiesHandled = 0;
1055 public long getLoadNotifiesHandled()
1057 return loadNotifiesHandled;
1060 public void notifyFileLoaded(String fullPathName, String fileName2,
1061 String modelName, String errorMsg, int modelParts)
1063 if (errorMsg != null)
1065 fileLoadingError = errorMsg;
1069 // TODO: deal sensibly with models loaded inLine:
1070 // modelName will be null, as will fullPathName.
1072 // the rest of this routine ignores the arguments, and simply interrogates
1073 // the Jmol view to find out what structures it contains, and adds them to
1074 // the structure selection manager.
1075 fileLoadingError = null;
1076 String[] oldmodels = modelFileNames;
1077 modelFileNames = null;
1078 chainNames = new Vector<String>();
1079 chainFile = new Hashtable<String, String>();
1080 boolean notifyLoaded = false;
1081 String[] modelfilenames = getPdbFile();
1082 // first check if we've lost any structures
1083 if (oldmodels != null && oldmodels.length > 0)
1086 for (int i = 0; i < oldmodels.length; i++)
1088 for (int n = 0; n < modelfilenames.length; n++)
1090 if (modelfilenames[n] == oldmodels[i])
1092 oldmodels[i] = null;
1096 if (oldmodels[i] != null)
1103 String[] oldmfn = new String[oldm];
1105 for (int i = 0; i < oldmodels.length; i++)
1107 if (oldmodels[i] != null)
1109 oldmfn[oldm++] = oldmodels[i];
1112 // deregister the Jmol instance for these structures - we'll add
1113 // ourselves again at the end for the current structure set.
1114 getSsm().removeStructureViewerListener(this, oldmfn);
1117 refreshPdbEntries();
1118 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1120 String fileName = modelfilenames[modelnum];
1121 boolean foundEntry = false;
1122 MCview.PDBfile pdb = null;
1123 String pdbfile = null;
1124 // model was probably loaded inline - so check the pdb file hashcode
1127 // calculate essential attributes for the pdb data imported inline.
1128 // prolly need to resolve modelnumber properly - for now just use our
1130 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1133 // search pdbentries and sequences to find correct pdbentry for this
1135 for (int pe = 0; pe < getPdbCount(); pe++)
1137 boolean matches = false;
1138 if (fileName == null)
1141 // see JAL-623 - need method of matching pasted data up
1143 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1144 pdbfile, AppletFormatAdapter.PASTE);
1145 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1152 File fl = new File(getPdbEntry(pe).getFile());
1153 matches = fl.equals(new File(fileName));
1157 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1160 // to be tested. See mantis bug
1161 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1162 String protocol = AppletFormatAdapter.URL;
1167 protocol = AppletFormatAdapter.FILE;
1169 } catch (Exception e)
1174 // Explicitly map to the filename used by Jmol ;
1175 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1176 fileName, protocol);
1177 // pdbentry[pe].getFile(), protocol);
1183 // add an entry for every chain in the model
1184 for (int i = 0; i < pdb.chains.size(); i++)
1186 String chid = new String(pdb.id + ":"
1187 + pdb.chains.elementAt(i).id);
1188 chainFile.put(chid, fileName);
1189 chainNames.addElement(chid);
1191 notifyLoaded = true;
1195 if (!foundEntry && associateNewStructs)
1197 // this is a foreign pdb file that jalview doesn't know about - add
1198 // it to the dataset and try to find a home - either on a matching
1199 // sequence or as a new sequence.
1200 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1202 // parse pdb file into a chain, etc.
1203 // locate best match for pdb in associated views and add mapping to
1205 // if properly registered then
1206 notifyLoaded = true;
1211 // so finally, update the jmol bits and pieces
1212 // if (jmolpopup != null)
1214 // // potential for deadlock here:
1215 // // jmolpopup.updateComputedMenus();
1217 if (!isLoadingFromArchive())
1219 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1221 // register ourselves as a listener and notify the gui that it needs to
1223 getSsm().addStructureViewerListener(this);
1226 FeatureRenderer fr = getFeatureRenderer(null);
1232 loadNotifiesHandled++;
1234 setLoadingFromArchive(false);
1237 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1239 notifyAtomPicked(iatom, strMeasure, null);
1242 public abstract void notifyScriptTermination(String strStatus,
1246 * display a message echoed from the jmol viewer
1250 public abstract void sendConsoleEcho(String strEcho); /*
1251 * { showConsole(true);
1253 * history.append("\n" +
1257 // /End JmolStatusListener
1258 // /////////////////////////////
1262 * status message - usually the response received after a script
1265 public abstract void sendConsoleMessage(String strStatus);
1267 public void setCallbackFunction(String callbackType,
1268 String callbackFunction)
1270 System.err.println("Ignoring set-callback request to associate "
1271 + callbackType + " with function " + callbackFunction);
1275 public void setJalviewColourScheme(ColourSchemeI cs)
1277 colourBySequence = false;
1285 StringBuilder command = new StringBuilder(128);
1286 command.append("select *;color white;");
1287 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1289 for (String res : residueSet)
1291 Color col = cs.findColour(res.charAt(0));
1292 command.append("select " + res + ";color[" + col.getRed() + ","
1293 + col.getGreen() + "," + col.getBlue() + "];");
1296 evalStateCommand(command.toString());
1300 public void showHelp()
1302 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1306 * open the URL somehow
1310 public abstract void showUrl(String url, String target);
1313 * called when the binding thinks the UI needs to be refreshed after a Jmol
1314 * state change. this could be because structures were loaded, or because an
1315 * error has occured.
1317 public abstract void refreshGUI();
1320 * called to show or hide the associated console window container.
1324 public abstract void showConsole(boolean show);
1327 * @param renderPanel
1329 * - when true will initialise jmol's file IO system (should be false
1330 * in applet context)
1332 * @param documentBase
1334 * @param commandOptions
1336 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1337 String htmlName, URL documentBase, URL codeBase,
1338 String commandOptions)
1340 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1341 codeBase, commandOptions, null, null);
1346 * @param renderPanel
1348 * - when true will initialise jmol's file IO system (should be false
1349 * in applet context)
1351 * @param documentBase
1353 * @param commandOptions
1354 * @param consolePanel
1355 * - panel to contain Jmol console
1356 * @param buttonsToShow
1357 * - buttons to show on the console, in ordr
1359 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1360 String htmlName, URL documentBase, URL codeBase,
1361 String commandOptions, final Container consolePanel,
1362 String buttonsToShow)
1364 if (commandOptions == null)
1366 commandOptions = "";
1368 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1369 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1370 + ((Object) this).toString(), documentBase, codeBase,
1371 commandOptions, this);
1373 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1375 console = createJmolConsole(consolePanel, buttonsToShow);
1376 if (consolePanel != null)
1378 consolePanel.addComponentListener(this);
1384 protected abstract JmolAppConsoleInterface createJmolConsole(
1385 Container consolePanel, String buttonsToShow);
1387 protected org.jmol.api.JmolAppConsoleInterface console = null;
1389 public void setBackgroundColour(java.awt.Color col)
1392 viewer.evalStringQuiet("background [" + col.getRed() + ","
1393 + col.getGreen() + "," + col.getBlue() + "];");
1398 public Dimension resizeInnerPanel(String data)
1400 // Jalview doesn't honour resize panel requests
1407 protected void closeConsole()
1409 if (console != null)
1413 console.setVisible(false);
1416 } catch (Exception x)
1425 * ComponentListener method
1428 public void componentMoved(ComponentEvent e)
1433 * ComponentListener method
1436 public void componentResized(ComponentEvent e)
1441 * ComponentListener method
1444 public void componentShown(ComponentEvent e)
1450 * ComponentListener method
1453 public void componentHidden(ComponentEvent e)