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.io.StructureFile;
32 import jalview.schemes.ColourSchemeI;
33 import jalview.schemes.ResidueProperties;
34 import jalview.structure.AtomSpec;
35 import jalview.structure.StructureMappingcommandSet;
36 import jalview.structure.StructureSelectionManager;
37 import jalview.structures.models.AAStructureBindingModel;
39 import java.awt.Color;
40 import java.awt.Container;
41 import java.awt.event.ComponentEvent;
42 import java.awt.event.ComponentListener;
45 import java.security.AccessControlException;
46 import java.util.Hashtable;
47 import java.util.List;
49 import java.util.Vector;
51 import javajs.awt.Dimension;
53 import org.jmol.adapter.smarter.SmarterJmolAdapter;
54 import org.jmol.api.JmolAppConsoleInterface;
55 import org.jmol.api.JmolSelectionListener;
56 import org.jmol.api.JmolStatusListener;
57 import org.jmol.api.JmolViewer;
58 import org.jmol.c.CBK;
59 import org.jmol.script.T;
60 import org.jmol.viewer.JC;
61 import org.jmol.viewer.Viewer;
63 public abstract class JalviewJmolBinding extends AAStructureBindingModel
64 implements JmolStatusListener, JmolSelectionListener,
67 boolean allChainsSelected = false;
70 * when true, try to search the associated datamodel for sequences that are
71 * associated with any unknown structures in the Jmol view.
73 private boolean associateNewStructs = false;
75 Vector<String> atomsPicked = new Vector<String>();
77 public Vector<String> chainNames;
79 Hashtable<String, String> chainFile;
81 public String fileLoadingError;
84 * the default or current model displayed if the model cannot be identified
85 * from the selection message
89 // protected JmolGenericPopup jmolpopup; // not used - remove?
98 * current set of model filenames loaded in the Jmol instance
100 String[] modelFileNames = null;
102 StringBuffer resetLastRes = new StringBuffer();
104 public Viewer viewer;
106 public JalviewJmolBinding(StructureSelectionManager ssm,
107 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
110 super(ssm, pdbentry, sequenceIs, chains, protocol);
112 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
113 * "jalviewJmol", ap.av.applet .getDocumentBase(),
114 * ap.av.applet.getCodeBase(), "", this);
116 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
120 public JalviewJmolBinding(StructureSelectionManager ssm,
121 SequenceI[][] seqs, Viewer theViewer)
126 viewer.setJmolStatusListener(this);
127 viewer.addSelectionListener(this);
131 * construct a title string for the viewer window based on the data jalview
136 public String getViewerTitle()
138 return getViewerTitle("Jmol", true);
142 * prepare the view for a given set of models/chains. chainList contains
143 * strings of the form 'pdbfilename:Chaincode'
146 * list of chains to make visible
148 public void centerViewer(Vector<String> chainList)
150 StringBuilder cmd = new StringBuilder(128);
152 for (String lbl : chainList)
158 mlength = lbl.indexOf(":", p);
159 } while (p < mlength && mlength < (lbl.length() - 2));
160 // TODO: lookup each pdb id and recover proper model number for it.
161 cmd.append(":" + lbl.substring(mlength + 1) + " /"
162 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
164 if (cmd.length() > 0)
166 cmd.setLength(cmd.length() - 4);
168 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
171 public void closeViewer()
173 viewer.acm.setModeMouse(JC.MOUSE_NONE);
174 // remove listeners for all structures in viewer
175 getSsm().removeStructureViewerListener(this, this.getPdbFile());
176 // and shut down jmol
177 viewer.evalStringQuiet("zap");
178 viewer.setJmolStatusListener(null);
181 releaseUIResources();
184 public void colourByChain()
186 colourBySequence = false;
187 // TODO: colour by chain should colour each chain distinctly across all
189 // TODO: http://issues.jalview.org/browse/JAL-628
190 evalStateCommand("select *;color chain");
193 public void colourByCharge()
195 colourBySequence = false;
196 evalStateCommand("select *;color white;select ASP,GLU;color red;"
197 + "select LYS,ARG;color blue;select CYS;color yellow");
201 * superpose the structures associated with sequences in the alignment
202 * according to their corresponding positions.
204 public void superposeStructures(AlignmentI alignment)
206 superposeStructures(alignment, -1, null);
210 * superpose the structures associated with sequences in the alignment
211 * according to their corresponding positions. ded)
213 * @param refStructure
214 * - select which pdb file to use as reference (default is -1 - the
215 * first structure in the alignment)
217 public void superposeStructures(AlignmentI alignment, int refStructure)
219 superposeStructures(alignment, refStructure, null);
223 * superpose the structures associated with sequences in the alignment
224 * according to their corresponding positions. ded)
226 * @param refStructure
227 * - select which pdb file to use as reference (default is -1 - the
228 * first structure in the alignment)
232 public void superposeStructures(AlignmentI alignment, int refStructure,
233 ColumnSelection hiddenCols)
235 superposeStructures(new AlignmentI[] { alignment },
236 new int[] { refStructure },
237 new ColumnSelection[] { hiddenCols });
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();
461 System.out.println("Superimpose command(s):\n" + cmdString);
463 evalStateCommand(cmdString);
466 if (selectioncom.length() > 0)
467 {// finally, mark all regions that were superposed.
468 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
470 selectioncom.setLength(selectioncom.length() - 1);
472 System.out.println("Select regions:\n" + selectioncom.toString());
473 evalStateCommand("select *; cartoons off; backbone; select ("
474 + selectioncom.toString() + "); cartoons; ");
475 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
479 public void evalStateCommand(String command)
482 if (lastCommand == null || !lastCommand.equals(command))
484 viewer.evalStringQuiet(command + "\n");
487 lastCommand = command;
491 * colour any structures associated with sequences in the given alignment
492 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
493 * if colourBySequence is enabled.
495 public void colourBySequence(AlignmentViewPanel alignmentv)
497 boolean showFeatures = alignmentv.getAlignViewport()
498 .isShowSequenceFeatures();
499 if (!colourBySequence || !isLoadingFinished())
503 if (getSsm() == null)
507 String[] files = getPdbFile();
509 SequenceRenderer sr = getSequenceRenderer(alignmentv);
511 FeatureRenderer fr = null;
514 fr = getFeatureRenderer(alignmentv);
516 AlignmentI alignment = alignmentv.getAlignment();
518 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(
519 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)
539 return JmolCommands.getColourBySequenceCommand(getSsm(), files,
540 getSequence(), sr, fr, alignment);
546 protected void executeWhenReady(String command)
548 evalStateCommand(command);
551 public void createImage(String file, String type, int quality)
553 System.out.println("JMOL CREATE IMAGE");
557 public String createImage(String fileName, String type,
558 Object textOrBytes, int quality)
560 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 // //////////////////////////
576 public float[][] functionXY(String functionName, int x, int y)
582 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
584 // TODO Auto-generated method stub
588 public Color getColour(int atomIndex, int pdbResNum, String chain,
591 if (getModelNum(pdbfile) < 0)
595 // TODO: verify atomIndex is selecting correct model.
596 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
597 int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color);
598 return new Color(colour);
602 * returns the current featureRenderer that should be used to colour the
609 public abstract FeatureRenderer getFeatureRenderer(
610 AlignmentViewPanel alignment);
613 * instruct the Jalview binding to update the pdbentries vector if necessary
614 * prior to matching the jmol view's contents to the list of structure files
615 * Jalview knows about.
617 public abstract void refreshPdbEntries();
619 private int getModelNum(String modelFileName)
621 String[] mfn = getPdbFile();
626 for (int i = 0; i < mfn.length; i++)
628 if (mfn[i].equalsIgnoreCase(modelFileName))
637 * map between index of model filename returned from getPdbFile and the first
638 * index of models from this file in the viewer. Note - this is not trimmed -
639 * use getPdbFile to get number of unique models.
641 private int _modelFileNameMap[];
643 // ////////////////////////////////
644 // /StructureListener
646 public synchronized String[] getPdbFile()
650 return new String[0];
652 if (modelFileNames == null)
654 String mset[] = new String[viewer.ms.mc];
655 _modelFileNameMap = new int[mset.length];
656 String m = viewer.ms.getModelFileName(0);
662 mset[0] = new File(m).getAbsolutePath();
663 } catch (AccessControlException x)
665 // usually not allowed to do this in applet
667 .println("jmolBinding: Using local file string from Jmol: "
670 if (mset[0].indexOf("/file:") != -1)
672 // applet path with docroot - discard as format won't match pdbfile
675 _modelFileNameMap[0] = 0; // filename index for first model is always 0.
678 for (int i = 1; i < mset.length; i++)
680 m = viewer.ms.getModelFileName(i);
686 mset[j] = new File(m).getAbsolutePath();
687 } catch (AccessControlException x)
689 // usually not allowed to do this in applet, so keep raw handle
690 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
693 _modelFileNameMap[j] = i; // record the model index for the filename
694 // skip any additional models in the same file (NMR structures)
695 if ((mset[j] == null ? mset[j] != mset[j - 1]
696 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
701 modelFileNames = new String[j];
702 System.arraycopy(mset, 0, modelFileNames, 0, j);
704 return modelFileNames;
708 * map from string to applet
711 public Map<String, Object> getRegistryInfo()
713 // TODO Auto-generated method stub
718 * returns the current sequenceRenderer that should be used to colour the
725 public abstract SequenceRenderer getSequenceRenderer(
726 AlignmentViewPanel alignment);
728 // ///////////////////////////////
729 // JmolStatusListener
731 public void handlePopupMenu(int x, int y)
733 // jmolpopup.show(x, y);
734 // jmolpopup.jpiShow(x, y);
738 * Highlight zero, one or more atoms on the structure
741 public void highlightAtoms(List<AtomSpec> atoms)
745 if (resetLastRes.length() > 0)
747 viewer.evalStringQuiet(resetLastRes.toString());
748 resetLastRes.setLength(0);
750 for (AtomSpec atom : atoms)
752 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
753 atom.getChain(), atom.getPdbFile());
759 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
762 if (modelFileNames == null)
767 // look up file model number for this pdbfile
769 // may need to adjust for URLencoding here - we don't worry about that yet.
770 while (mdlNum < modelFileNames.length
771 && !pdbfile.equals(modelFileNames[mdlNum]))
775 if (mdlNum == modelFileNames.length)
782 StringBuilder cmd = new StringBuilder(64);
783 cmd.append("select " + pdbResNum); // +modelNum
785 resetLastRes.append("select " + pdbResNum); // +modelNum
788 resetLastRes.append(":");
789 if (!chain.equals(" "))
792 resetLastRes.append(chain);
795 cmd.append(" /" + (mdlNum + 1));
796 resetLastRes.append("/" + (mdlNum + 1));
798 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
800 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
801 + " and not hetero; spacefill 0;");
803 cmd.append("spacefill 200;select none");
805 viewer.evalStringQuiet(cmd.toString());
810 boolean debug = true;
812 private void jmolHistory(boolean enable)
814 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
817 public void loadInline(String string)
821 // viewer.loadInline(strModel, isAppend);
823 // construct fake fullPathName and fileName so we can identify the file
825 // Then, construct pass a reader for the string to Jmol.
826 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
827 // fileName, null, reader, false, null, null, 0);
828 viewer.openStringInline(string);
831 public void mouseOverStructure(int atomIndex, String strInfo)
834 int alocsep = strInfo.indexOf("^");
835 int mdlSep = strInfo.indexOf("/");
836 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
838 if (chainSeparator == -1)
840 chainSeparator = strInfo.indexOf(".");
841 if (mdlSep > -1 && mdlSep < chainSeparator)
843 chainSeparator1 = chainSeparator;
844 chainSeparator = mdlSep;
847 // handle insertion codes
850 pdbResNum = Integer.parseInt(strInfo.substring(
851 strInfo.indexOf("]") + 1, alocsep));
856 pdbResNum = Integer.parseInt(strInfo.substring(
857 strInfo.indexOf("]") + 1, chainSeparator));
861 if (strInfo.indexOf(":") > -1)
863 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
864 strInfo.indexOf("."));
871 String pdbfilename = modelFileNames[frameNo]; // default is first or current
875 if (chainSeparator1 == -1)
877 chainSeparator1 = strInfo.indexOf(".", mdlSep);
879 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
880 chainSeparator1) : strInfo.substring(mdlSep + 1);
883 // recover PDB filename for the model hovered over.
884 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
886 while (mnumber < _modelFileNameMap[_mp])
890 pdbfilename = modelFileNames[_mp];
891 if (pdbfilename == null)
893 pdbfilename = new File(viewer.ms.getModelFileName(mnumber))
897 } catch (Exception e)
902 if (lastMessage == null || !lastMessage.equals(strInfo))
904 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
907 lastMessage = strInfo;
910 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
914 System.err.println("Ignoring additional hover info: " + data
915 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
917 mouseOverStructure(atomIndex, strInfo);
921 * { if (history != null && strStatus != null &&
922 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
926 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
929 * this implements the toggle label behaviour copied from the original
930 * structure viewer, MCView
934 System.err.println("Ignoring additional pick data string " + strData);
936 int chainSeparator = strInfo.indexOf(":");
938 if (chainSeparator == -1)
940 chainSeparator = strInfo.indexOf(".");
943 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
945 String mdlString = "";
946 if ((p = strInfo.indexOf(":")) > -1)
948 picked += strInfo.substring(p, strInfo.indexOf("."));
951 if ((p = strInfo.indexOf("/")) > -1)
953 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
955 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
959 if (!atomsPicked.contains(picked))
961 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
962 atomsPicked.addElement(picked);
966 viewer.evalString("select " + picked + ";label off");
967 atomsPicked.removeElement(picked);
970 // TODO: in application this happens
972 // if (scriptWindow != null)
974 // scriptWindow.sendConsoleMessage(strInfo);
975 // scriptWindow.sendConsoleMessage("\n");
981 public void notifyCallback(CBK type, Object[] data)
988 notifyFileLoaded((String) data[1], (String) data[2],
989 (String) data[3], (String) data[4],
990 ((Integer) data[5]).intValue());
994 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
996 // also highlight in alignment
998 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1002 notifyScriptTermination((String) data[2],
1003 ((Integer) data[3]).intValue());
1006 sendConsoleEcho((String) data[1]);
1009 sendConsoleMessage((data == null) ? ((String) null)
1010 : (String) data[1]);
1013 // System.err.println("Ignoring error callback.");
1023 System.err.println("Unhandled callback " + type + " "
1024 + data[1].toString());
1027 } catch (Exception e)
1029 System.err.println("Squashed Jmol callback handler error:");
1030 e.printStackTrace();
1035 public boolean notifyEnabled(CBK callbackPick)
1037 switch (callbackPick)
1053 // incremented every time a load notification is successfully handled -
1054 // lightweight mechanism for other threads to detect when they can start
1055 // referrring to new structures.
1056 private long loadNotifiesHandled = 0;
1058 public long getLoadNotifiesHandled()
1060 return loadNotifiesHandled;
1063 public void notifyFileLoaded(String fullPathName, String fileName2,
1064 String modelName, String errorMsg, int modelParts)
1066 if (errorMsg != null)
1068 fileLoadingError = errorMsg;
1072 // TODO: deal sensibly with models loaded inLine:
1073 // modelName will be null, as will fullPathName.
1075 // the rest of this routine ignores the arguments, and simply interrogates
1076 // the Jmol view to find out what structures it contains, and adds them to
1077 // the structure selection manager.
1078 fileLoadingError = null;
1079 String[] oldmodels = modelFileNames;
1080 modelFileNames = null;
1081 chainNames = new Vector<String>();
1082 chainFile = new Hashtable<String, String>();
1083 boolean notifyLoaded = false;
1084 String[] modelfilenames = getPdbFile();
1085 // first check if we've lost any structures
1086 if (oldmodels != null && oldmodels.length > 0)
1089 for (int i = 0; i < oldmodels.length; i++)
1091 for (int n = 0; n < modelfilenames.length; n++)
1093 if (modelfilenames[n] == oldmodels[i])
1095 oldmodels[i] = null;
1099 if (oldmodels[i] != null)
1106 String[] oldmfn = new String[oldm];
1108 for (int i = 0; i < oldmodels.length; i++)
1110 if (oldmodels[i] != null)
1112 oldmfn[oldm++] = oldmodels[i];
1115 // deregister the Jmol instance for these structures - we'll add
1116 // ourselves again at the end for the current structure set.
1117 getSsm().removeStructureViewerListener(this, oldmfn);
1120 refreshPdbEntries();
1121 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1123 String fileName = modelfilenames[modelnum];
1124 boolean foundEntry = false;
1125 StructureFile pdb = null;
1126 String pdbfile = null;
1127 // model was probably loaded inline - so check the pdb file hashcode
1130 // calculate essential attributes for the pdb data imported inline.
1131 // prolly need to resolve modelnumber properly - for now just use our
1133 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1136 // search pdbentries and sequences to find correct pdbentry for this
1138 for (int pe = 0; pe < getPdbCount(); pe++)
1140 boolean matches = false;
1141 if (fileName == null)
1144 // see JAL-623 - need method of matching pasted data up
1146 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1147 pdbfile, AppletFormatAdapter.PASTE);
1148 getPdbEntry(modelnum).setFile("INLINE" + pdb.getId());
1155 File fl = new File(getPdbEntry(pe).getFile());
1156 matches = fl.equals(new File(fileName));
1160 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1163 // to be tested. See mantis bug
1164 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1165 String protocol = AppletFormatAdapter.URL;
1170 protocol = AppletFormatAdapter.FILE;
1172 } catch (Exception e)
1177 // Explicitly map to the filename used by Jmol ;
1178 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1179 fileName, protocol);
1180 // pdbentry[pe].getFile(), protocol);
1186 // add an entry for every chain in the model
1187 for (int i = 0; i < pdb.getChains().size(); i++)
1189 String chid = new String(pdb.getId() + ":"
1190 + pdb.getChains().elementAt(i).id);
1191 chainFile.put(chid, fileName);
1192 chainNames.addElement(chid);
1194 notifyLoaded = true;
1198 if (!foundEntry && associateNewStructs)
1200 // this is a foreign pdb file that jalview doesn't know about - add
1201 // it to the dataset and try to find a home - either on a matching
1202 // sequence or as a new sequence.
1203 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1205 // parse pdb file into a chain, etc.
1206 // locate best match for pdb in associated views and add mapping to
1208 // if properly registered then
1209 notifyLoaded = true;
1214 // so finally, update the jmol bits and pieces
1215 // if (jmolpopup != null)
1217 // // potential for deadlock here:
1218 // // jmolpopup.updateComputedMenus();
1220 if (!isLoadingFromArchive())
1222 viewer.evalStringQuiet("model *; select backbone;restrict;cartoon;wireframe off;spacefill off");
1224 // register ourselves as a listener and notify the gui that it needs to
1226 getSsm().addStructureViewerListener(this);
1229 FeatureRenderer fr = getFeatureRenderer(null);
1235 loadNotifiesHandled++;
1237 setLoadingFromArchive(false);
1240 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1242 notifyAtomPicked(iatom, strMeasure, null);
1245 public abstract void notifyScriptTermination(String strStatus,
1249 * display a message echoed from the jmol viewer
1253 public abstract void sendConsoleEcho(String strEcho); /*
1254 * { showConsole(true);
1256 * history.append("\n" +
1260 // /End JmolStatusListener
1261 // /////////////////////////////
1265 * status message - usually the response received after a script
1268 public abstract void sendConsoleMessage(String strStatus);
1271 public void setCallbackFunction(String callbackType,
1272 String callbackFunction)
1274 System.err.println("Ignoring set-callback request to associate "
1275 + callbackType + " with function " + callbackFunction);
1279 public void setJalviewColourScheme(ColourSchemeI cs)
1281 colourBySequence = false;
1289 StringBuilder command = new StringBuilder(128);
1290 command.append("select *;color white;");
1291 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1293 for (String res : residueSet)
1295 Color col = cs.findColour(res.charAt(0));
1296 command.append("select " + res + ";color[" + col.getRed() + ","
1297 + col.getGreen() + "," + col.getBlue() + "];");
1300 evalStateCommand(command.toString());
1304 public void showHelp()
1306 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1310 * open the URL somehow
1314 public abstract void showUrl(String url, String target);
1317 * called when the binding thinks the UI needs to be refreshed after a Jmol
1318 * state change. this could be because structures were loaded, or because an
1319 * error has occured.
1321 public abstract void refreshGUI();
1324 * called to show or hide the associated console window container.
1328 public abstract void showConsole(boolean show);
1331 * @param renderPanel
1333 * - when true will initialise jmol's file IO system (should be false
1334 * in applet context)
1336 * @param documentBase
1338 * @param commandOptions
1340 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1341 String htmlName, URL documentBase, URL codeBase,
1342 String commandOptions)
1344 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1345 codeBase, commandOptions, null, null);
1350 * @param renderPanel
1352 * - when true will initialise jmol's file IO system (should be false
1353 * in applet context)
1355 * @param documentBase
1357 * @param commandOptions
1358 * @param consolePanel
1359 * - panel to contain Jmol console
1360 * @param buttonsToShow
1361 * - buttons to show on the console, in ordr
1363 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1364 String htmlName, URL documentBase, URL codeBase,
1365 String commandOptions, final Container consolePanel,
1366 String buttonsToShow)
1368 if (commandOptions == null)
1370 commandOptions = "";
1372 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1373 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1374 + ((Object) this).toString(), documentBase, codeBase,
1375 commandOptions, this);
1377 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1379 console = createJmolConsole(consolePanel, buttonsToShow);
1380 if (consolePanel != null)
1382 consolePanel.addComponentListener(this);
1388 protected abstract JmolAppConsoleInterface createJmolConsole(
1389 Container consolePanel, String buttonsToShow);
1391 protected org.jmol.api.JmolAppConsoleInterface console = null;
1393 public void setBackgroundColour(java.awt.Color col)
1396 viewer.evalStringQuiet("background [" + col.getRed() + ","
1397 + col.getGreen() + "," + col.getBlue() + "];");
1402 public Dimension resizeInnerPanel(String data)
1404 // Jalview doesn't honour resize panel requests
1411 protected void closeConsole()
1413 if (console != null)
1417 console.setVisible(false);
1420 } catch (Exception x)
1429 * ComponentListener method
1432 public void componentMoved(ComponentEvent e)
1437 * ComponentListener method
1440 public void componentResized(ComponentEvent e)
1445 * ComponentListener method
1448 public void componentShown(ComponentEvent e)
1454 * ComponentListener method
1457 public void componentHidden(ComponentEvent e)