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[]
235 { alignment }, new int[]
236 { refStructure }, new ColumnSelection[]
241 * Construct and send a command to align structures against a reference
242 * structure, based on one or more sequence alignments
245 * an array of alignments to process
246 * @param _refStructure
247 * an array of corresponding reference structures (index into pdb
248 * file array); if a negative value is passed, the first PDB file
249 * mapped to an alignment sequence is used as the reference for
252 * an array of corresponding hidden columns for each alignment
254 public void superposeStructures(AlignmentI[] _alignment,
255 int[] _refStructure, ColumnSelection[] _hiddenCols)
257 while (viewer.isScriptExecuting())
262 } catch (InterruptedException i)
267 String[] files = getPdbFile();
268 if (!waitForFileLoad(files))
273 StringBuilder selectioncom = new StringBuilder(256);
274 // In principle - nSeconds specifies the speed of animation for each
275 // superposition - but is seems to behave weirdly, so we don't specify it.
276 String nSeconds = " ";
277 if (files.length > 10)
279 nSeconds = " 0.005 ";
283 nSeconds = " " + (2.0 / files.length) + " ";
284 // if (nSeconds).substring(0,5)+" ";
286 // see JAL-1345 - should really automatically turn off the animation for
287 // large numbers of structures, but Jmol doesn't seem to allow that.
289 // union of all aligned positions are collected together.
290 for (int a = 0; a < _alignment.length; a++)
292 int refStructure = _refStructure[a];
293 AlignmentI alignment = _alignment[a];
294 ColumnSelection hiddenCols = _hiddenCols[a];
296 && selectioncom.length() > 0
297 && !selectioncom.substring(selectioncom.length() - 1).equals(
300 selectioncom.append("|");
302 // process this alignment
303 if (refStructure >= files.length)
305 System.err.println("Invalid reference structure value "
311 * 'matched' array will hold 'true' for visible alignment columns where
312 * all sequences have a residue with a mapping to the PDB structure
314 boolean matched[] = new boolean[alignment.getWidth()];
315 for (int m = 0; m < matched.length; m++)
317 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
320 SuperposeData[] structures = new SuperposeData[files.length];
321 for (int f = 0; f < files.length; f++)
323 structures[f] = new SuperposeData(alignment.getWidth());
327 * Calculate the superposable alignment columns ('matched'), and the
328 * corresponding structure residue positions (structures.pdbResNo)
330 int candidateRefStructure = findSuperposableResidues(alignment,
331 matched, structures);
332 if (refStructure < 0)
335 * If no reference structure was specified, pick the first one that has
336 * a mapping in the alignment
338 refStructure = candidateRefStructure;
341 String[] selcom = new String[files.length];
343 for (boolean b : matched)
352 // TODO: bail out here because superposition illdefined?
356 * generate select statements to select regions to superimpose structures
359 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
361 String chainCd = ":" + structures[pdbfnum].chain;
364 StringBuilder molsel = new StringBuilder();
366 for (int r = 0; r < matched.length; r++)
370 int pdbResNo = structures[pdbfnum].pdbResNo[r];
371 if (lpos != pdbResNo - 1)
377 molsel.append(chainCd);
384 // continuous run - and lpos >-1
387 // at the beginning, so add dash
397 * add final selection phrase
402 molsel.append(chainCd);
405 if (molsel.length() > 1)
407 selcom[pdbfnum] = molsel.toString();
408 selectioncom.append("((");
409 selectioncom.append(selcom[pdbfnum].substring(1,
410 selcom[pdbfnum].length() - 1));
411 selectioncom.append(" )& ");
412 selectioncom.append(pdbfnum + 1);
413 selectioncom.append(".1)");
414 if (pdbfnum < files.length - 1)
416 selectioncom.append("|");
421 selcom[pdbfnum] = null;
425 StringBuilder command = new StringBuilder(256);
426 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
428 if (pdbfnum == refStructure || selcom[pdbfnum] == null
429 || selcom[refStructure] == null)
433 command.append("echo ");
434 command.append("\"Superposing (");
435 command.append(structures[pdbfnum].pdbId);
436 command.append(") against reference (");
437 command.append(structures[refStructure].pdbId);
438 command.append(")\";\ncompare " + nSeconds);
440 command.append(Integer.toString(1 + pdbfnum));
441 command.append(".1} {");
442 command.append(Integer.toString(1 + refStructure));
443 // conformation=1 excludes alternate locations for CA (JAL-1757)
444 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
446 // for (int s = 0; s < 2; s++)
448 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
450 command.append(selcom[pdbfnum]);
451 command.append(selcom[refStructure]);
452 command.append(" ROTATE TRANSLATE;\n");
454 if (selectioncom.length() > 0)
456 System.out.println("Select regions:\n" + selectioncom.toString());
457 evalStateCommand("select *; cartoons off; backbone; select ("
458 + selectioncom.toString() + "); cartoons; ");
459 // selcom.append("; ribbons; ");
460 String cmdString = command.toString();
462 .println("Superimpose command(s):\n" + cmdString);
464 evalStateCommand(cmdString);
467 if (selectioncom.length() > 0)
468 {// finally, mark all regions that were superposed.
469 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
471 selectioncom.setLength(selectioncom.length() - 1);
473 System.out.println("Select regions:\n" + selectioncom.toString());
474 evalStateCommand("select *; cartoons off; backbone; select ("
475 + selectioncom.toString() + "); cartoons; ");
476 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
480 public void evalStateCommand(String command)
483 if (lastCommand == null || !lastCommand.equals(command))
485 viewer.evalStringQuiet(command + "\n");
488 lastCommand = command;
492 * colour any structures associated with sequences in the given alignment
493 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
494 * if colourBySequence is enabled.
496 public void colourBySequence(AlignmentViewPanel alignmentv)
498 boolean showFeatures = alignmentv.getAlignViewport()
499 .isShowSequenceFeatures();
500 if (!colourBySequence || !isLoadingFinished())
504 if (getSsm() == null)
508 String[] files = getPdbFile();
510 SequenceRenderer sr = getSequenceRenderer(alignmentv);
512 FeatureRenderer fr = null;
515 fr = getFeatureRenderer(alignmentv);
517 AlignmentI alignment = alignmentv.getAlignment();
519 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(files, sr, fr, alignment))
521 for (String cbyseq : cpdbbyseq.commands)
523 executeWhenReady(cbyseq);
535 protected StructureMappingcommandSet[] getColourBySequenceCommands(
536 String[] files, SequenceRenderer sr, FeatureRenderer fr,
537 AlignmentI alignment)
540 .getColourBySequenceCommand(getSsm(), files, getSequence(), sr,
548 protected void executeWhenReady(String command)
550 evalStateCommand(command);
553 public void createImage(String file, String type, int quality)
555 System.out.println("JMOL CREATE IMAGE");
558 public String createImage(String fileName, String type,
559 Object textOrBytes, int quality)
561 System.out.println("JMOL CREATE IMAGE");
565 public String eval(String strEval)
567 // System.out.println(strEval);
568 // "# 'eval' is implemented only for the applet.";
572 // End StructureListener
573 // //////////////////////////
575 public float[][] functionXY(String functionName, int x, int y)
580 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
582 // TODO Auto-generated method stub
586 public Color getColour(int atomIndex, int pdbResNum, String chain,
589 if (getModelNum(pdbfile) < 0)
593 // TODO: verify atomIndex is selecting correct model.
594 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
595 int colour = viewer.ms.at[atomIndex]
596 .atomPropertyInt(T.color);
597 return new Color(colour);
601 * returns the current featureRenderer that should be used to colour the
608 public abstract FeatureRenderer getFeatureRenderer(
609 AlignmentViewPanel alignment);
612 * instruct the Jalview binding to update the pdbentries vector if necessary
613 * prior to matching the jmol view's contents to the list of structure files
614 * Jalview knows about.
616 public abstract void refreshPdbEntries();
618 private int getModelNum(String modelFileName)
620 String[] mfn = getPdbFile();
625 for (int i = 0; i < mfn.length; i++)
627 if (mfn[i].equalsIgnoreCase(modelFileName))
636 * map between index of model filename returned from getPdbFile and the first
637 * index of models from this file in the viewer. Note - this is not trimmed -
638 * use getPdbFile to get number of unique models.
640 private int _modelFileNameMap[];
642 // ////////////////////////////////
643 // /StructureListener
645 public synchronized String[] getPdbFile()
649 return new String[0];
651 if (modelFileNames == null)
653 String mset[] = new String[viewer.ms.mc];
654 _modelFileNameMap = new int[mset.length];
655 String m = viewer.ms.getModelFileName(0);
661 mset[0] = new File(m).getAbsolutePath();
662 } catch (AccessControlException x)
664 // usually not allowed to do this in applet
666 .println("jmolBinding: Using local file string from Jmol: "
669 if (mset[0].indexOf("/file:") != -1)
671 // applet path with docroot - discard as format won't match pdbfile
674 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
677 for (int i = 1; i < mset.length; i++)
679 m = viewer.ms.getModelFileName(i);
685 mset[j] = new File(m).getAbsolutePath();
686 } catch (AccessControlException x)
688 // usually not allowed to do this in applet, so keep raw handle
689 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
692 _modelFileNameMap[j] = i; // record the model index for the filename
693 // skip any additional models in the same file (NMR structures)
694 if ((mset[j] == null ? mset[j] != mset[j - 1]
695 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
700 modelFileNames = new String[j];
701 System.arraycopy(mset, 0, modelFileNames, 0, j);
703 return modelFileNames;
707 * map from string to applet
710 public Map<String, Object> getRegistryInfo()
712 // TODO Auto-generated method stub
717 * returns the current sequenceRenderer that should be used to colour the
724 public abstract SequenceRenderer getSequenceRenderer(
725 AlignmentViewPanel alignment);
727 // ///////////////////////////////
728 // JmolStatusListener
730 public void handlePopupMenu(int x, int y)
732 // jmolpopup.show(x, y);
733 // jmolpopup.jpiShow(x, y);
737 * Highlight zero, one or more atoms on the structure
740 public void highlightAtoms(List<AtomSpec> atoms)
744 for (AtomSpec atom : atoms)
746 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
747 atom.getChain(), atom.getPdbFile());
753 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
756 if (modelFileNames == null)
761 // look up file model number for this pdbfile
763 // may need to adjust for URLencoding here - we don't worry about that yet.
764 while (mdlNum < modelFileNames.length
765 && !pdbfile.equals(modelFileNames[mdlNum]))
769 if (mdlNum == modelFileNames.length)
775 // if (!pdbfile.equals(pdbentry.getFile()))
777 if (resetLastRes.length() > 0)
779 viewer.evalStringQuiet(resetLastRes.toString());
782 StringBuilder cmd = new StringBuilder(64);
783 cmd.append("select " + pdbResNum); // +modelNum
785 resetLastRes.setLength(0);
786 resetLastRes.append("select " + pdbResNum); // +modelNum
789 resetLastRes.append(":");
790 if (!chain.equals(" "))
793 resetLastRes.append(chain);
796 cmd.append(" /" + (mdlNum + 1));
797 resetLastRes.append("/" + (mdlNum + 1));
799 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
801 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
802 + " and not hetero; spacefill 0;");
804 cmd.append("spacefill 200;select none");
806 viewer.evalStringQuiet(cmd.toString());
811 boolean debug = true;
813 private void jmolHistory(boolean enable)
815 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
818 public void loadInline(String string)
822 // viewer.loadInline(strModel, isAppend);
824 // construct fake fullPathName and fileName so we can identify the file
826 // Then, construct pass a reader for the string to Jmol.
827 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
828 // fileName, null, reader, false, null, null, 0);
829 viewer.openStringInline(string);
832 public void mouseOverStructure(int atomIndex, String strInfo)
835 int alocsep = strInfo.indexOf("^");
836 int mdlSep = strInfo.indexOf("/");
837 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
839 if (chainSeparator == -1)
841 chainSeparator = strInfo.indexOf(".");
842 if (mdlSep > -1 && mdlSep < chainSeparator)
844 chainSeparator1 = chainSeparator;
845 chainSeparator = mdlSep;
848 // handle insertion codes
851 pdbResNum = Integer.parseInt(strInfo.substring(
852 strInfo.indexOf("]") + 1, alocsep));
857 pdbResNum = Integer.parseInt(strInfo.substring(
858 strInfo.indexOf("]") + 1, chainSeparator));
862 if (strInfo.indexOf(":") > -1)
864 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
865 strInfo.indexOf("."));
872 String pdbfilename = modelFileNames[frameNo]; // default is first or current
876 if (chainSeparator1 == -1)
878 chainSeparator1 = strInfo.indexOf(".", mdlSep);
880 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
881 chainSeparator1) : strInfo.substring(mdlSep + 1);
884 // recover PDB filename for the model hovered over.
885 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
887 while (mnumber < _modelFileNameMap[_mp])
891 pdbfilename = modelFileNames[_mp];
892 if (pdbfilename == null)
894 pdbfilename = new File(
895 viewer.ms.getModelFileName(mnumber))
899 } catch (Exception e)
904 if (lastMessage == null || !lastMessage.equals(strInfo))
906 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
909 lastMessage = strInfo;
912 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
916 System.err.println("Ignoring additional hover info: " + data
917 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
919 mouseOverStructure(atomIndex, strInfo);
923 * { if (history != null && strStatus != null &&
924 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
928 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
931 * this implements the toggle label behaviour copied from the original
932 * structure viewer, MCView
936 System.err.println("Ignoring additional pick data string " + strData);
938 int chainSeparator = strInfo.indexOf(":");
940 if (chainSeparator == -1)
942 chainSeparator = strInfo.indexOf(".");
945 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
947 String mdlString = "";
948 if ((p = strInfo.indexOf(":")) > -1)
950 picked += strInfo.substring(p, strInfo.indexOf("."));
953 if ((p = strInfo.indexOf("/")) > -1)
955 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
957 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
961 if (!atomsPicked.contains(picked))
963 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
964 atomsPicked.addElement(picked);
968 viewer.evalString("select " + picked + ";label off");
969 atomsPicked.removeElement(picked);
972 // TODO: in application this happens
974 // if (scriptWindow != null)
976 // scriptWindow.sendConsoleMessage(strInfo);
977 // scriptWindow.sendConsoleMessage("\n");
983 public void notifyCallback(CBK type, Object[] data)
990 notifyFileLoaded((String) data[1], (String) data[2],
991 (String) data[3], (String) data[4],
992 ((Integer) data[5]).intValue());
996 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
998 // also highlight in alignment
1000 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1004 notifyScriptTermination((String) data[2],
1005 ((Integer) data[3]).intValue());
1008 sendConsoleEcho((String) data[1]);
1011 sendConsoleMessage((data == null) ? ((String) null)
1012 : (String) data[1]);
1015 // System.err.println("Ignoring error callback.");
1025 System.err.println("Unhandled callback " + type + " "
1026 + data[1].toString());
1029 } catch (Exception e)
1031 System.err.println("Squashed Jmol callback handler error:");
1032 e.printStackTrace();
1037 public boolean notifyEnabled(CBK callbackPick)
1039 switch (callbackPick)
1055 // incremented every time a load notification is successfully handled -
1056 // lightweight mechanism for other threads to detect when they can start
1057 // referrring to new structures.
1058 private long loadNotifiesHandled = 0;
1060 public long getLoadNotifiesHandled()
1062 return loadNotifiesHandled;
1065 public void notifyFileLoaded(String fullPathName, String fileName2,
1066 String modelName, String errorMsg, int modelParts)
1068 if (errorMsg != null)
1070 fileLoadingError = errorMsg;
1074 // TODO: deal sensibly with models loaded inLine:
1075 // modelName will be null, as will fullPathName.
1077 // the rest of this routine ignores the arguments, and simply interrogates
1078 // the Jmol view to find out what structures it contains, and adds them to
1079 // the structure selection manager.
1080 fileLoadingError = null;
1081 String[] oldmodels = modelFileNames;
1082 modelFileNames = null;
1083 chainNames = new Vector<String>();
1084 chainFile = new Hashtable<String, String>();
1085 boolean notifyLoaded = false;
1086 String[] modelfilenames = getPdbFile();
1087 // first check if we've lost any structures
1088 if (oldmodels != null && oldmodels.length > 0)
1091 for (int i = 0; i < oldmodels.length; i++)
1093 for (int n = 0; n < modelfilenames.length; n++)
1095 if (modelfilenames[n] == oldmodels[i])
1097 oldmodels[i] = null;
1101 if (oldmodels[i] != null)
1108 String[] oldmfn = new String[oldm];
1110 for (int i = 0; i < oldmodels.length; i++)
1112 if (oldmodels[i] != null)
1114 oldmfn[oldm++] = oldmodels[i];
1117 // deregister the Jmol instance for these structures - we'll add
1118 // ourselves again at the end for the current structure set.
1119 getSsm().removeStructureViewerListener(this, oldmfn);
1122 refreshPdbEntries();
1123 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1125 String fileName = modelfilenames[modelnum];
1126 boolean foundEntry = false;
1127 MCview.PDBfile pdb = null;
1128 String pdbfile = null;
1129 // model was probably loaded inline - so check the pdb file hashcode
1132 // calculate essential attributes for the pdb data imported inline.
1133 // prolly need to resolve modelnumber properly - for now just use our
1135 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1138 // search pdbentries and sequences to find correct pdbentry for this
1140 for (int pe = 0; pe < getPdbCount(); pe++)
1142 boolean matches = false;
1143 if (fileName == null)
1146 // see JAL-623 - need method of matching pasted data up
1148 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1149 pdbfile, AppletFormatAdapter.PASTE);
1150 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1157 File fl = new File(getPdbEntry(pe).getFile());
1158 matches = fl.equals(new File(fileName));
1162 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1165 // to be tested. See mantis bug
1166 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1167 String protocol = AppletFormatAdapter.URL;
1172 protocol = AppletFormatAdapter.FILE;
1174 } catch (Exception e)
1179 // Explicitly map to the filename used by Jmol ;
1180 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1181 fileName, protocol);
1182 // pdbentry[pe].getFile(), protocol);
1188 // add an entry for every chain in the model
1189 for (int i = 0; i < pdb.chains.size(); i++)
1191 String chid = new String(pdb.id + ":"
1192 + pdb.chains.elementAt(i).id);
1193 chainFile.put(chid, fileName);
1194 chainNames.addElement(chid);
1196 notifyLoaded = true;
1200 if (!foundEntry && associateNewStructs)
1202 // this is a foreign pdb file that jalview doesn't know about - add
1203 // it to the dataset and try to find a home - either on a matching
1204 // sequence or as a new sequence.
1205 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1207 // parse pdb file into a chain, etc.
1208 // locate best match for pdb in associated views and add mapping to
1210 // if properly registered then
1211 notifyLoaded = true;
1216 // so finally, update the jmol bits and pieces
1217 // if (jmolpopup != null)
1219 // // potential for deadlock here:
1220 // // jmolpopup.updateComputedMenus();
1222 if (!isLoadingFromArchive())
1224 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1226 // register ourselves as a listener and notify the gui that it needs to
1228 getSsm().addStructureViewerListener(this);
1231 FeatureRenderer fr = getFeatureRenderer(null);
1237 loadNotifiesHandled++;
1239 setLoadingFromArchive(false);
1242 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1244 notifyAtomPicked(iatom, strMeasure, null);
1247 public abstract void notifyScriptTermination(String strStatus,
1251 * display a message echoed from the jmol viewer
1255 public abstract void sendConsoleEcho(String strEcho); /*
1256 * { showConsole(true);
1258 * history.append("\n" +
1262 // /End JmolStatusListener
1263 // /////////////////////////////
1267 * status message - usually the response received after a script
1270 public abstract void sendConsoleMessage(String strStatus);
1272 public void setCallbackFunction(String callbackType,
1273 String callbackFunction)
1275 System.err.println("Ignoring set-callback request to associate "
1276 + callbackType + " with function " + callbackFunction);
1280 public void setJalviewColourScheme(ColourSchemeI cs)
1282 colourBySequence = false;
1290 StringBuilder command = new StringBuilder(128);
1291 command.append("select *;color white;");
1292 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1294 for (String res : residueSet)
1296 Color col = cs.findColour(res.charAt(0));
1297 command.append("select " + res + ";color[" + col.getRed() + ","
1298 + col.getGreen() + "," + col.getBlue() + "];");
1301 evalStateCommand(command.toString());
1305 public void showHelp()
1307 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1311 * open the URL somehow
1315 public abstract void showUrl(String url, String target);
1318 * called when the binding thinks the UI needs to be refreshed after a Jmol
1319 * state change. this could be because structures were loaded, or because an
1320 * error has occured.
1322 public abstract void refreshGUI();
1325 * called to show or hide the associated console window container.
1329 public abstract void showConsole(boolean show);
1332 * @param renderPanel
1334 * - when true will initialise jmol's file IO system (should be false
1335 * in applet context)
1337 * @param documentBase
1339 * @param commandOptions
1341 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1342 String htmlName, URL documentBase, URL codeBase,
1343 String commandOptions)
1345 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1346 codeBase, commandOptions, null, null);
1351 * @param renderPanel
1353 * - when true will initialise jmol's file IO system (should be false
1354 * in applet context)
1356 * @param documentBase
1358 * @param commandOptions
1359 * @param consolePanel
1360 * - panel to contain Jmol console
1361 * @param buttonsToShow
1362 * - buttons to show on the console, in ordr
1364 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1365 String htmlName, URL documentBase, URL codeBase,
1366 String commandOptions, final Container consolePanel,
1367 String buttonsToShow)
1369 if (commandOptions == null)
1371 commandOptions = "";
1373 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1374 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1375 + ((Object) this).toString(), documentBase, codeBase,
1376 commandOptions, this);
1378 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1380 console = createJmolConsole(consolePanel, buttonsToShow);
1381 if (consolePanel != null)
1383 consolePanel.addComponentListener(this);
1389 protected abstract JmolAppConsoleInterface createJmolConsole(
1390 Container consolePanel, String buttonsToShow);
1392 protected org.jmol.api.JmolAppConsoleInterface console = null;
1394 public void setBackgroundColour(java.awt.Color col)
1397 viewer.evalStringQuiet("background [" + col.getRed() + ","
1398 + col.getGreen() + "," + col.getBlue() + "];");
1403 public Dimension resizeInnerPanel(String data)
1405 // Jalview doesn't honour resize panel requests
1412 protected void closeConsole()
1414 if (console != null)
1418 console.setVisible(false);
1421 } catch (Exception x)
1430 * ComponentListener method
1433 public void componentMoved(ComponentEvent e)
1438 * ComponentListener method
1441 public void componentResized(ComponentEvent e)
1446 * ComponentListener method
1449 public void componentShown(ComponentEvent e)
1455 * ComponentListener method
1458 public void componentHidden(ComponentEvent e)