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.AlignViewportI;
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.gui.IProgressIndicator;
31 import jalview.io.DataSourceType;
32 import jalview.io.StructureFile;
33 import jalview.schemes.ColourSchemeI;
34 import jalview.schemes.ResidueProperties;
35 import jalview.structure.AtomSpec;
36 import jalview.structure.StructureMappingcommandSet;
37 import jalview.structure.StructureSelectionManager;
38 import jalview.structures.models.AAStructureBindingModel;
39 import jalview.util.MessageManager;
41 import java.awt.Color;
42 import java.awt.Container;
43 import java.awt.event.ComponentEvent;
44 import java.awt.event.ComponentListener;
47 import java.security.AccessControlException;
48 import java.util.ArrayList;
49 import java.util.BitSet;
50 import java.util.Hashtable;
51 import java.util.List;
53 import java.util.Vector;
55 import org.jmol.adapter.smarter.SmarterJmolAdapter;
56 import org.jmol.api.JmolAppConsoleInterface;
57 import org.jmol.api.JmolSelectionListener;
58 import org.jmol.api.JmolStatusListener;
59 import org.jmol.api.JmolViewer;
60 import org.jmol.c.CBK;
61 import org.jmol.script.T;
62 import org.jmol.viewer.Viewer;
64 public abstract class JalviewJmolBinding extends AAStructureBindingModel
65 implements JmolStatusListener, JmolSelectionListener,
68 boolean allChainsSelected = false;
71 * when true, try to search the associated datamodel for sequences that are
72 * associated with any unknown structures in the Jmol view.
74 private boolean associateNewStructs = false;
76 Vector<String> atomsPicked = new Vector<String>();
78 private List<String> chainNames;
80 Hashtable<String, String> chainFile;
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?
96 StringBuffer resetLastRes = new StringBuffer();
100 public JalviewJmolBinding(StructureSelectionManager ssm,
101 PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
102 DataSourceType protocol)
104 super(ssm, pdbentry, sequenceIs, protocol);
106 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
107 * "jalviewJmol", ap.av.applet .getDocumentBase(),
108 * ap.av.applet.getCodeBase(), "", this);
110 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
114 public JalviewJmolBinding(StructureSelectionManager ssm,
115 SequenceI[][] seqs, Viewer theViewer)
120 viewer.setJmolStatusListener(this);
121 viewer.addSelectionListener(this);
125 * construct a title string for the viewer window based on the data jalview
130 public String getViewerTitle()
132 return getViewerTitle("Jmol", true);
136 * prepare the view for a given set of models/chains. chainList contains
137 * strings of the form 'pdbfilename:Chaincode'
140 * list of chains to make visible
142 public void centerViewer(Vector<String> chainList)
144 StringBuilder cmd = new StringBuilder(128);
146 for (String lbl : chainList)
152 mlength = lbl.indexOf(":", p);
153 } while (p < mlength && mlength < (lbl.length() - 2));
154 // TODO: lookup each pdb id and recover proper model number for it.
155 cmd.append(":" + lbl.substring(mlength + 1) + " /"
156 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
158 if (cmd.length() > 0)
160 cmd.setLength(cmd.length() - 4);
162 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
165 public void closeViewer()
167 // remove listeners for all structures in viewer
168 getSsm().removeStructureViewerListener(this, this.getPdbFile());
172 releaseUIResources();
176 public void colourByChain()
178 colourBySequence = false;
179 // TODO: colour by chain should colour each chain distinctly across all
181 // TODO: http://issues.jalview.org/browse/JAL-628
182 evalStateCommand("select *;color chain");
186 public void colourByCharge()
188 colourBySequence = false;
189 evalStateCommand("select *;color white;select ASP,GLU;color red;"
190 + "select LYS,ARG;color blue;select CYS;color yellow");
194 * superpose the structures associated with sequences in the alignment
195 * according to their corresponding positions.
197 public void superposeStructures(AlignmentI alignment)
199 superposeStructures(alignment, -1, null);
203 * superpose the structures associated with sequences in the alignment
204 * according to their corresponding positions. ded)
206 * @param refStructure
207 * - select which pdb file to use as reference (default is -1 - the
208 * first structure in the alignment)
210 public void superposeStructures(AlignmentI alignment, int refStructure)
212 superposeStructures(alignment, refStructure, null);
216 * superpose the structures associated with sequences in the alignment
217 * according to their corresponding positions. ded)
219 * @param refStructure
220 * - select which pdb file to use as reference (default is -1 - the
221 * first structure in the alignment)
225 public void superposeStructures(AlignmentI alignment, int refStructure,
226 ColumnSelection hiddenCols)
228 superposeStructures(new AlignmentI[] { alignment },
229 new int[] { refStructure },
230 new ColumnSelection[] { hiddenCols });
237 public String superposeStructures(AlignmentI[] _alignment,
238 int[] _refStructure, ColumnSelection[] _hiddenCols)
240 while (viewer.isScriptExecuting())
245 } catch (InterruptedException i)
251 * get the distinct structure files modelled
252 * (a file with multiple chains may map to multiple sequences)
254 String[] files = getPdbFile();
255 if (!waitForFileLoad(files))
260 StringBuilder selectioncom = new StringBuilder(256);
261 // In principle - nSeconds specifies the speed of animation for each
262 // superposition - but is seems to behave weirdly, so we don't specify it.
263 String nSeconds = " ";
264 if (files.length > 10)
266 nSeconds = " 0.005 ";
270 nSeconds = " " + (2.0 / files.length) + " ";
271 // if (nSeconds).substring(0,5)+" ";
274 // see JAL-1345 - should really automatically turn off the animation for
275 // large numbers of structures, but Jmol doesn't seem to allow that.
277 // union of all aligned positions are collected together.
278 for (int a = 0; a < _alignment.length; a++)
280 int refStructure = _refStructure[a];
281 AlignmentI alignment = _alignment[a];
282 ColumnSelection hiddenCols = _hiddenCols[a];
284 && selectioncom.length() > 0
285 && !selectioncom.substring(selectioncom.length() - 1).equals(
288 selectioncom.append("|");
290 // process this alignment
291 if (refStructure >= files.length)
293 System.err.println("Invalid reference structure value "
299 * 'matched' bit j will be set for visible alignment columns j where
300 * all sequences have a residue with a mapping to the PDB structure
302 BitSet matched = new BitSet();
303 for (int m = 0; m < alignment.getWidth(); m++)
305 if (hiddenCols == null || hiddenCols.isVisible(m))
311 SuperposeData[] structures = new SuperposeData[files.length];
312 for (int f = 0; f < files.length; f++)
314 structures[f] = new SuperposeData(alignment.getWidth());
318 * Calculate the superposable alignment columns ('matched'), and the
319 * corresponding structure residue positions (structures.pdbResNo)
321 int candidateRefStructure = findSuperposableResidues(alignment,
322 matched, structures);
323 if (refStructure < 0)
326 * If no reference structure was specified, pick the first one that has
327 * a mapping in the alignment
329 refStructure = candidateRefStructure;
332 String[] selcom = new String[files.length];
333 int nmatched = matched.cardinality();
336 return (MessageManager.formatMessage(
337 "label.insufficient_residues",
342 * generate select statements to select regions to superimpose structures
345 // TODO extract method to construct selection statements
346 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
348 String chainCd = ":" + structures[pdbfnum].chain;
351 StringBuilder molsel = new StringBuilder();
354 int nextColumnMatch = matched.nextSetBit(0);
355 while (nextColumnMatch != -1)
357 int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch];
358 if (lpos != pdbResNo - 1)
364 molsel.append(chainCd);
371 // continuous run - and lpos >-1
374 // at the beginning, so add dash
381 nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1);
384 * add final selection phrase
389 molsel.append(chainCd);
392 if (molsel.length() > 1)
394 selcom[pdbfnum] = molsel.toString();
395 selectioncom.append("((");
396 selectioncom.append(selcom[pdbfnum].substring(1,
397 selcom[pdbfnum].length() - 1));
398 selectioncom.append(" )& ");
399 selectioncom.append(pdbfnum + 1);
400 selectioncom.append(".1)");
401 if (pdbfnum < files.length - 1)
403 selectioncom.append("|");
408 selcom[pdbfnum] = null;
412 StringBuilder command = new StringBuilder(256);
413 // command.append("set spinFps 10;\n");
415 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
417 if (pdbfnum == refStructure || selcom[pdbfnum] == null
418 || selcom[refStructure] == null)
422 command.append("echo ");
423 command.append("\"Superposing (");
424 command.append(structures[pdbfnum].pdbId);
425 command.append(") against reference (");
426 command.append(structures[refStructure].pdbId);
427 command.append(")\";\ncompare " + nSeconds);
429 command.append(Integer.toString(1 + pdbfnum));
430 command.append(".1} {");
431 command.append(Integer.toString(1 + refStructure));
432 // conformation=1 excludes alternate locations for CA (JAL-1757)
433 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
435 // for (int s = 0; s < 2; s++)
437 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
439 command.append(selcom[pdbfnum]);
440 command.append(selcom[refStructure]);
441 command.append(" ROTATE TRANSLATE;\n");
443 if (selectioncom.length() > 0)
445 // TODO is performing selectioncom redundant here? is done later on
446 // System.out.println("Select regions:\n" + selectioncom.toString());
447 evalStateCommand("select *; cartoons off; backbone; select ("
448 + selectioncom.toString() + "); cartoons; ");
449 // selcom.append("; ribbons; ");
450 String cmdString = command.toString();
451 // System.out.println("Superimpose command(s):\n" + cmdString);
453 evalStateCommand(cmdString);
456 if (selectioncom.length() > 0)
457 {// finally, mark all regions that were superposed.
458 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
460 selectioncom.setLength(selectioncom.length() - 1);
462 // System.out.println("Select regions:\n" + selectioncom.toString());
463 evalStateCommand("select *; cartoons off; backbone; select ("
464 + selectioncom.toString() + "); cartoons; ");
465 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
471 public void evalStateCommand(String command)
474 if (lastCommand == null || !lastCommand.equals(command))
476 viewer.evalStringQuiet(command + "\n");
479 lastCommand = command;
483 * Sends a set of colour commands to the structure viewer
485 * @param colourBySequenceCommands
488 protected void colourBySequence(
489 StructureMappingcommandSet[] colourBySequenceCommands)
491 for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands)
493 for (String cbyseq : cpdbbyseq.commands)
495 executeWhenReady(cbyseq);
508 protected StructureMappingcommandSet[] getColourBySequenceCommands(
509 String[] files, SequenceRenderer sr, FeatureRenderer fr,
510 AlignViewportI viewport)
512 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
513 getSequence(), sr, fr, viewport);
519 protected void executeWhenReady(String command)
521 evalStateCommand(command);
524 public void createImage(String file, String type, int quality)
526 System.out.println("JMOL CREATE IMAGE");
530 public String createImage(String fileName, String type,
531 Object textOrBytes, int quality)
533 System.out.println("JMOL CREATE IMAGE");
538 public String eval(String strEval)
540 // System.out.println(strEval);
541 // "# 'eval' is implemented only for the applet.";
545 // End StructureListener
546 // //////////////////////////
549 public float[][] functionXY(String functionName, int x, int y)
555 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
557 // TODO Auto-generated method stub
561 public Color getColour(int atomIndex, int pdbResNum, String chain,
564 if (getModelNum(pdbfile) < 0)
568 // TODO: verify atomIndex is selecting correct model.
569 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
570 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
571 return new Color(colour);
575 * instruct the Jalview binding to update the pdbentries vector if necessary
576 * prior to matching the jmol view's contents to the list of structure files
577 * Jalview knows about.
579 public abstract void refreshPdbEntries();
581 private int getModelNum(String modelFileName)
583 String[] mfn = getPdbFile();
588 for (int i = 0; i < mfn.length; i++)
590 if (mfn[i].equalsIgnoreCase(modelFileName))
599 * map between index of model filename returned from getPdbFile and the first
600 * index of models from this file in the viewer. Note - this is not trimmed -
601 * use getPdbFile to get number of unique models.
603 private int _modelFileNameMap[];
605 // ////////////////////////////////
606 // /StructureListener
608 public synchronized String[] getPdbFile()
612 return new String[0];
614 if (modelFileNames == null)
616 List<String> mset = new ArrayList<String>();
617 _modelFileNameMap = new int[viewer.ms.mc];
618 String m = viewer.ms.getModelFileName(0);
624 filePath = new File(m).getAbsolutePath();
625 } catch (AccessControlException x)
627 // usually not allowed to do this in applet
629 .println("jmolBinding: Using local file string from Jmol: "
632 if (filePath.indexOf("/file:") != -1)
634 // applet path with docroot - discard as format won't match pdbfile
638 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
641 for (int i = 1; i < viewer.ms.mc; i++)
643 m = viewer.ms.getModelFileName(i);
649 filePath = new File(m).getAbsolutePath();
650 } catch (AccessControlException x)
652 // usually not allowed to do this in applet, so keep raw handle
653 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
658 * add this model unless it is read from a structure file we have
659 * already seen (example: 2MJW is an NMR structure with 10 models)
661 if (!mset.contains(filePath))
664 _modelFileNameMap[j] = i; // record the model index for the filename
668 modelFileNames = mset.toArray(new String[mset.size()]);
670 return modelFileNames;
674 * map from string to applet
677 public Map<String, Object> getRegistryInfo()
679 // TODO Auto-generated method stub
685 // ///////////////////////////////
686 // JmolStatusListener
688 public void handlePopupMenu(int x, int y)
690 // jmolpopup.show(x, y);
691 // jmolpopup.jpiShow(x, y);
695 * Highlight zero, one or more atoms on the structure
698 public void highlightAtoms(List<AtomSpec> atoms)
702 if (resetLastRes.length() > 0)
704 viewer.evalStringQuiet(resetLastRes.toString());
705 resetLastRes.setLength(0);
707 for (AtomSpec atom : atoms)
709 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
710 atom.getChain(), atom.getPdbFile());
716 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
719 if (modelFileNames == null)
724 // look up file model number for this pdbfile
726 // may need to adjust for URLencoding here - we don't worry about that yet.
727 while (mdlNum < modelFileNames.length
728 && !pdbfile.equals(modelFileNames[mdlNum]))
732 if (mdlNum == modelFileNames.length)
739 StringBuilder cmd = new StringBuilder(64);
740 cmd.append("select " + pdbResNum); // +modelNum
742 resetLastRes.append("select " + pdbResNum); // +modelNum
745 resetLastRes.append(":");
746 if (!chain.equals(" "))
749 resetLastRes.append(chain);
752 cmd.append(" /" + (mdlNum + 1));
753 resetLastRes.append("/" + (mdlNum + 1));
755 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
757 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
758 + " and not hetero; spacefill 0;");
760 cmd.append("spacefill 200;select none");
762 viewer.evalStringQuiet(cmd.toString());
767 boolean debug = true;
769 private void jmolHistory(boolean enable)
771 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
774 public void loadInline(String string)
778 // viewer.loadInline(strModel, isAppend);
780 // construct fake fullPathName and fileName so we can identify the file
782 // Then, construct pass a reader for the string to Jmol.
783 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
784 // fileName, null, reader, false, null, null, 0);
785 viewer.openStringInline(string);
788 public void mouseOverStructure(int atomIndex, String strInfo)
791 int alocsep = strInfo.indexOf("^");
792 int mdlSep = strInfo.indexOf("/");
793 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
795 if (chainSeparator == -1)
797 chainSeparator = strInfo.indexOf(".");
798 if (mdlSep > -1 && mdlSep < chainSeparator)
800 chainSeparator1 = chainSeparator;
801 chainSeparator = mdlSep;
804 // handle insertion codes
807 pdbResNum = Integer.parseInt(strInfo.substring(
808 strInfo.indexOf("]") + 1, alocsep));
813 pdbResNum = Integer.parseInt(strInfo.substring(
814 strInfo.indexOf("]") + 1, chainSeparator));
818 if (strInfo.indexOf(":") > -1)
820 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
821 strInfo.indexOf("."));
828 String pdbfilename = modelFileNames[frameNo]; // default is first or current
832 if (chainSeparator1 == -1)
834 chainSeparator1 = strInfo.indexOf(".", mdlSep);
836 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
837 chainSeparator1) : strInfo.substring(mdlSep + 1);
840 // recover PDB filename for the model hovered over.
841 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
843 while (mnumber < _modelFileNameMap[_mp])
847 pdbfilename = modelFileNames[_mp];
848 if (pdbfilename == null)
850 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
854 } catch (Exception e)
859 if (lastMessage == null || !lastMessage.equals(strInfo))
861 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
864 lastMessage = strInfo;
867 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
871 System.err.println("Ignoring additional hover info: " + data
872 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
874 mouseOverStructure(atomIndex, strInfo);
878 * { if (history != null && strStatus != null &&
879 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
883 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
886 * this implements the toggle label behaviour copied from the original
887 * structure viewer, MCView
891 System.err.println("Ignoring additional pick data string " + strData);
893 int chainSeparator = strInfo.indexOf(":");
895 if (chainSeparator == -1)
897 chainSeparator = strInfo.indexOf(".");
900 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
902 String mdlString = "";
903 if ((p = strInfo.indexOf(":")) > -1)
905 picked += strInfo.substring(p, strInfo.indexOf("."));
908 if ((p = strInfo.indexOf("/")) > -1)
910 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
912 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
916 if (!atomsPicked.contains(picked))
918 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
919 atomsPicked.addElement(picked);
923 viewer.evalString("select " + picked + ";label off");
924 atomsPicked.removeElement(picked);
927 // TODO: in application this happens
929 // if (scriptWindow != null)
931 // scriptWindow.sendConsoleMessage(strInfo);
932 // scriptWindow.sendConsoleMessage("\n");
938 public void notifyCallback(CBK type, Object[] data)
945 notifyFileLoaded((String) data[1], (String) data[2],
946 (String) data[3], (String) data[4],
947 ((Integer) data[5]).intValue());
951 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
953 // also highlight in alignment
955 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
959 notifyScriptTermination((String) data[2],
960 ((Integer) data[3]).intValue());
963 sendConsoleEcho((String) data[1]);
966 sendConsoleMessage((data == null) ? ((String) null)
970 // System.err.println("Ignoring error callback.");
980 System.err.println("Unhandled callback " + type + " "
981 + data[1].toString());
984 } catch (Exception e)
986 System.err.println("Squashed Jmol callback handler error:");
992 public boolean notifyEnabled(CBK callbackPick)
994 switch (callbackPick)
1010 // incremented every time a load notification is successfully handled -
1011 // lightweight mechanism for other threads to detect when they can start
1012 // referrring to new structures.
1013 private long loadNotifiesHandled = 0;
1015 public long getLoadNotifiesHandled()
1017 return loadNotifiesHandled;
1020 public void notifyFileLoaded(String fullPathName, String fileName2,
1021 String modelName, String errorMsg, int modelParts)
1023 if (errorMsg != null)
1025 fileLoadingError = errorMsg;
1029 // TODO: deal sensibly with models loaded inLine:
1030 // modelName will be null, as will fullPathName.
1032 // the rest of this routine ignores the arguments, and simply interrogates
1033 // the Jmol view to find out what structures it contains, and adds them to
1034 // the structure selection manager.
1035 fileLoadingError = null;
1036 String[] oldmodels = modelFileNames;
1037 modelFileNames = null;
1038 chainNames = new ArrayList<String>();
1039 chainFile = new Hashtable<String, String>();
1040 boolean notifyLoaded = false;
1041 String[] modelfilenames = getPdbFile();
1042 // first check if we've lost any structures
1043 if (oldmodels != null && oldmodels.length > 0)
1046 for (int i = 0; i < oldmodels.length; i++)
1048 for (int n = 0; n < modelfilenames.length; n++)
1050 if (modelfilenames[n] == oldmodels[i])
1052 oldmodels[i] = null;
1056 if (oldmodels[i] != null)
1063 String[] oldmfn = new String[oldm];
1065 for (int i = 0; i < oldmodels.length; i++)
1067 if (oldmodels[i] != null)
1069 oldmfn[oldm++] = oldmodels[i];
1072 // deregister the Jmol instance for these structures - we'll add
1073 // ourselves again at the end for the current structure set.
1074 getSsm().removeStructureViewerListener(this, oldmfn);
1077 refreshPdbEntries();
1078 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1080 String fileName = modelfilenames[modelnum];
1081 boolean foundEntry = false;
1082 StructureFile pdb = null;
1083 String pdbfile = null;
1084 // model was probably loaded inline - so check the pdb file hashcode
1087 // calculate essential attributes for the pdb data imported inline.
1088 // prolly need to resolve modelnumber properly - for now just use our
1090 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1093 // search pdbentries and sequences to find correct pdbentry for this
1095 for (int pe = 0; pe < getPdbCount(); pe++)
1097 boolean matches = false;
1098 addSequence(pe, getSequence()[pe]);
1099 if (fileName == null)
1102 // see JAL-623 - need method of matching pasted data up
1104 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1105 pdbfile, DataSourceType.PASTE, getIProgressIndicator());
1106 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1113 File fl = new File(getPdbEntry(pe).getFile());
1114 matches = fl.equals(new File(fileName));
1118 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1121 // to be tested. See mantis bug
1122 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1123 DataSourceType protocol = DataSourceType.URL;
1128 protocol = DataSourceType.FILE;
1130 } catch (Exception e)
1135 // Explicitly map to the filename used by Jmol ;
1136 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1137 fileName, protocol, getIProgressIndicator());
1138 // pdbentry[pe].getFile(), protocol);
1144 // add an entry for every chain in the model
1145 for (int i = 0; i < pdb.getChains().size(); i++)
1147 String chid = new String(pdb.getId() + ":"
1148 + pdb.getChains().elementAt(i).id);
1149 chainFile.put(chid, fileName);
1150 chainNames.add(chid);
1152 notifyLoaded = true;
1156 if (!foundEntry && associateNewStructs)
1158 // this is a foreign pdb file that jalview doesn't know about - add
1159 // it to the dataset and try to find a home - either on a matching
1160 // sequence or as a new sequence.
1161 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1163 // parse pdb file into a chain, etc.
1164 // locate best match for pdb in associated views and add mapping to
1166 // if properly registered then
1167 notifyLoaded = true;
1172 // so finally, update the jmol bits and pieces
1173 // if (jmolpopup != null)
1175 // // potential for deadlock here:
1176 // // jmolpopup.updateComputedMenus();
1178 if (!isLoadingFromArchive())
1180 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1182 // register ourselves as a listener and notify the gui that it needs to
1184 getSsm().addStructureViewerListener(this);
1187 FeatureRenderer fr = getFeatureRenderer(null);
1193 loadNotifiesHandled++;
1195 setLoadingFromArchive(false);
1199 public List<String> getChainNames()
1204 protected abstract IProgressIndicator getIProgressIndicator();
1206 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1208 notifyAtomPicked(iatom, strMeasure, null);
1211 public abstract void notifyScriptTermination(String strStatus,
1215 * display a message echoed from the jmol viewer
1219 public abstract void sendConsoleEcho(String strEcho); /*
1220 * { showConsole(true);
1222 * history.append("\n" +
1226 // /End JmolStatusListener
1227 // /////////////////////////////
1231 * status message - usually the response received after a script
1234 public abstract void sendConsoleMessage(String strStatus);
1237 public void setCallbackFunction(String callbackType,
1238 String callbackFunction)
1240 System.err.println("Ignoring set-callback request to associate "
1241 + callbackType + " with function " + callbackFunction);
1246 public void setJalviewColourScheme(ColourSchemeI cs)
1248 colourBySequence = false;
1256 StringBuilder command = new StringBuilder(128);
1257 command.append("select *;color white;");
1258 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1260 for (String resName : residueSet)
1262 char res = resName.length() == 3 ? ResidueProperties
1263 .getSingleCharacterCode(resName) : resName.charAt(0);
1264 Color col = cs.findColour(res, 0, null, null, 0f);
1265 command.append("select " + resName + ";color[" + col.getRed() + ","
1266 + col.getGreen() + "," + col.getBlue() + "];");
1269 evalStateCommand(command.toString());
1273 public void showHelp()
1275 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1279 * open the URL somehow
1283 public abstract void showUrl(String url, String target);
1286 * called when the binding thinks the UI needs to be refreshed after a Jmol
1287 * state change. this could be because structures were loaded, or because an
1288 * error has occured.
1290 public abstract void refreshGUI();
1293 * called to show or hide the associated console window container.
1297 public abstract void showConsole(boolean show);
1300 * @param renderPanel
1302 * - when true will initialise jmol's file IO system (should be false
1303 * in applet context)
1305 * @param documentBase
1307 * @param commandOptions
1309 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1310 String htmlName, URL documentBase, URL codeBase,
1311 String commandOptions)
1313 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1314 codeBase, commandOptions, null, null);
1319 * @param renderPanel
1321 * - when true will initialise jmol's file IO system (should be false
1322 * in applet context)
1324 * @param documentBase
1326 * @param commandOptions
1327 * @param consolePanel
1328 * - panel to contain Jmol console
1329 * @param buttonsToShow
1330 * - buttons to show on the console, in ordr
1332 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1333 String htmlName, URL documentBase, URL codeBase,
1334 String commandOptions, final Container consolePanel,
1335 String buttonsToShow)
1337 if (commandOptions == null)
1339 commandOptions = "";
1341 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1342 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1343 + ((Object) this).toString(), documentBase, codeBase,
1344 commandOptions, this);
1346 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1348 console = createJmolConsole(consolePanel, buttonsToShow);
1349 if (consolePanel != null)
1351 consolePanel.addComponentListener(this);
1357 protected abstract JmolAppConsoleInterface createJmolConsole(
1358 Container consolePanel, String buttonsToShow);
1360 protected org.jmol.api.JmolAppConsoleInterface console = null;
1363 public void setBackgroundColour(java.awt.Color col)
1366 viewer.evalStringQuiet("background [" + col.getRed() + ","
1367 + col.getGreen() + "," + col.getBlue() + "];");
1372 public int[] resizeInnerPanel(String data)
1374 // Jalview doesn't honour resize panel requests
1381 protected void closeConsole()
1383 if (console != null)
1387 console.setVisible(false);
1390 } catch (Exception x)
1399 * ComponentListener method
1402 public void componentMoved(ComponentEvent e)
1407 * ComponentListener method
1410 public void componentResized(ComponentEvent e)
1415 * ComponentListener method
1418 public void componentShown(ComponentEvent e)
1424 * ComponentListener method
1427 public void componentHidden(ComponentEvent e)