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,
67 * state flag used to check if the Jmol viewer's paint method can be called
69 private boolean finishedInit = false;
71 boolean allChainsSelected = false;
74 * when true, try to search the associated datamodel for sequences that are
75 * associated with any unknown structures in the Jmol view.
77 private boolean associateNewStructs = false;
79 Vector<String> atomsPicked = new Vector<String>();
81 public Vector<String> chainNames;
83 Hashtable<String, String> chainFile;
85 public String fileLoadingError;
88 * the default or current model displayed if the model cannot be identified
89 * from the selection message
93 // protected JmolGenericPopup jmolpopup; // not used - remove?
102 * current set of model filenames loaded in the Jmol instance
104 String[] modelFileNames = null;
106 StringBuffer resetLastRes = new StringBuffer();
108 public Viewer viewer;
110 public JalviewJmolBinding(StructureSelectionManager ssm,
111 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
114 super(ssm, pdbentry, sequenceIs, chains, protocol);
116 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
117 * "jalviewJmol", ap.av.applet .getDocumentBase(),
118 * ap.av.applet.getCodeBase(), "", this);
120 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
124 public JalviewJmolBinding(StructureSelectionManager ssm,
125 SequenceI[][] seqs, Viewer theViewer)
130 viewer.setJmolStatusListener(this);
131 viewer.addSelectionListener(this);
135 * construct a title string for the viewer window based on the data jalview
140 public String getViewerTitle()
142 return getViewerTitle("Jmol", true);
146 * prepare the view for a given set of models/chains. chainList contains
147 * strings of the form 'pdbfilename:Chaincode'
150 * list of chains to make visible
152 public void centerViewer(Vector<String> chainList)
154 StringBuilder cmd = new StringBuilder(128);
156 for (String lbl : chainList)
162 mlength = lbl.indexOf(":", p);
163 } while (p < mlength && mlength < (lbl.length() - 2));
164 // TODO: lookup each pdb id and recover proper model number for it.
165 cmd.append(":" + lbl.substring(mlength + 1) + " /"
166 + (1 + getModelNum(chainFile.get(lbl))) + " or ");
168 if (cmd.length() > 0)
170 cmd.setLength(cmd.length() - 4);
172 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
175 public void closeViewer()
177 viewer.acm.setModeMouse(JC.MOUSE_NONE);
178 // remove listeners for all structures in viewer
179 getSsm().removeStructureViewerListener(this, this.getPdbFile());
180 // and shut down jmol
181 viewer.evalStringQuiet("zap");
182 viewer.setJmolStatusListener(null);
185 releaseUIResources();
188 public void colourByChain()
190 colourBySequence = false;
191 // TODO: colour by chain should colour each chain distinctly across all
193 // TODO: http://issues.jalview.org/browse/JAL-628
194 evalStateCommand("select *;color chain");
197 public void colourByCharge()
199 colourBySequence = false;
200 evalStateCommand("select *;color white;select ASP,GLU;color red;"
201 + "select LYS,ARG;color blue;select CYS;color yellow");
205 * superpose the structures associated with sequences in the alignment
206 * according to their corresponding positions.
208 public void superposeStructures(AlignmentI alignment)
210 superposeStructures(alignment, -1, null);
214 * superpose the structures associated with sequences in the alignment
215 * according to their corresponding positions. ded)
217 * @param refStructure
218 * - select which pdb file to use as reference (default is -1 - the
219 * first structure in the alignment)
221 public void superposeStructures(AlignmentI alignment, int refStructure)
223 superposeStructures(alignment, refStructure, null);
227 * superpose the structures associated with sequences in the alignment
228 * according to their corresponding positions. ded)
230 * @param refStructure
231 * - select which pdb file to use as reference (default is -1 - the
232 * first structure in the alignment)
236 public void superposeStructures(AlignmentI alignment, int refStructure,
237 ColumnSelection hiddenCols)
239 superposeStructures(new AlignmentI[]
240 { alignment }, new int[]
241 { refStructure }, new ColumnSelection[]
246 * Construct and send a command to align structures against a reference
247 * structure, based on one or more sequence alignments
250 * an array of alignments to process
251 * @param _refStructure
252 * an array of corresponding reference structures (index into pdb
253 * file array); if a negative value is passed, the first PDB file
254 * mapped to an alignment sequence is used as the reference for
257 * an array of corresponding hidden columns for each alignment
259 public void superposeStructures(AlignmentI[] _alignment,
260 int[] _refStructure, ColumnSelection[] _hiddenCols)
262 while (viewer.isScriptExecuting())
267 } catch (InterruptedException i)
272 String[] files = getPdbFile();
273 if (!waitForFileLoad(files))
278 StringBuilder selectioncom = new StringBuilder(256);
279 // In principle - nSeconds specifies the speed of animation for each
280 // superposition - but is seems to behave weirdly, so we don't specify it.
281 String nSeconds = " ";
282 if (files.length > 10)
284 nSeconds = " 0.00001 ";
288 nSeconds = " " + (2.0 / files.length) + " ";
289 // if (nSeconds).substring(0,5)+" ";
291 // see JAL-1345 - should really automatically turn off the animation for
292 // large numbers of structures, but Jmol doesn't seem to allow that.
294 // union of all aligned positions are collected together.
295 for (int a = 0; a < _alignment.length; a++)
297 int refStructure = _refStructure[a];
298 AlignmentI alignment = _alignment[a];
299 ColumnSelection hiddenCols = _hiddenCols[a];
301 && selectioncom.length() > 0
302 && !selectioncom.substring(selectioncom.length() - 1).equals(
305 selectioncom.append("|");
307 // process this alignment
308 if (refStructure >= files.length)
310 System.err.println("Invalid reference structure value "
316 * 'matched' array will hold 'true' for visible alignment columns where
317 * all sequences have a residue with a mapping to the PDB structure
319 boolean matched[] = new boolean[alignment.getWidth()];
320 for (int m = 0; m < matched.length; m++)
322 matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true;
325 SuperposeData[] structures = new SuperposeData[files.length];
326 for (int f = 0; f < files.length; f++)
328 structures[f] = new SuperposeData(alignment.getWidth());
332 * Calculate the superposable alignment columns ('matched'), and the
333 * corresponding structure residue positions (structures.pdbResNo)
335 int candidateRefStructure = findSuperposableResidues(alignment,
336 matched, structures);
337 if (refStructure < 0)
340 * If no reference structure was specified, pick the first one that has
341 * a mapping in the alignment
343 refStructure = candidateRefStructure;
346 String[] selcom = new String[files.length];
348 for (boolean b : matched)
357 // TODO: bail out here because superposition illdefined?
361 * generate select statements to select regions to superimpose structures
364 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
366 String chainCd = ":" + structures[pdbfnum].chain;
369 StringBuilder molsel = new StringBuilder();
371 for (int r = 0; r < matched.length; r++)
375 int pdbResNo = structures[pdbfnum].pdbResNo[r];
376 if (lpos != pdbResNo - 1)
382 molsel.append(chainCd);
389 // continuous run - and lpos >-1
392 // at the beginning, so add dash
402 * add final selection phrase
407 molsel.append(chainCd);
410 if (molsel.length() > 1)
412 selcom[pdbfnum] = molsel.toString();
413 selectioncom.append("((");
414 selectioncom.append(selcom[pdbfnum].substring(1,
415 selcom[pdbfnum].length() - 1));
416 selectioncom.append(" )& ");
417 selectioncom.append(pdbfnum + 1);
418 selectioncom.append(".1)");
419 if (pdbfnum < files.length - 1)
421 selectioncom.append("|");
426 selcom[pdbfnum] = null;
430 StringBuilder command = new StringBuilder(256);
431 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
433 if (pdbfnum == refStructure || selcom[pdbfnum] == null
434 || selcom[refStructure] == null)
438 command.append("echo ");
439 command.append("\"Superposing (");
440 command.append(structures[pdbfnum].pdbId);
441 command.append(") against reference (");
442 command.append(structures[refStructure].pdbId);
443 command.append(")\";\ncompare " + nSeconds);
445 command.append(Integer.toString(1 + pdbfnum));
446 command.append(".1} {");
447 command.append(Integer.toString(1 + refStructure));
448 // conformation=1 excludes alternate locations for CA (JAL-1757)
449 command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS ");
451 // for (int s = 0; s < 2; s++)
453 // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
455 command.append(selcom[pdbfnum]);
456 command.append(selcom[refStructure]);
457 command.append(" ROTATE TRANSLATE;\n");
459 if (selectioncom.length() > 0)
461 System.out.println("Select regions:\n" + selectioncom.toString());
462 evalStateCommand("select *; cartoons off; backbone; select ("
463 + selectioncom.toString() + "); cartoons; ");
464 // selcom.append("; ribbons; ");
465 String cmdString = command.toString();
467 .println("Superimpose command(s):\n" + cmdString);
469 evalStateCommand(cmdString);
472 if (selectioncom.length() > 0)
473 {// finally, mark all regions that were superposed.
474 if (selectioncom.substring(selectioncom.length() - 1).equals("|"))
476 selectioncom.setLength(selectioncom.length() - 1);
478 System.out.println("Select regions:\n" + selectioncom.toString());
479 evalStateCommand("select *; cartoons off; backbone; select ("
480 + selectioncom.toString() + "); cartoons; ");
481 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
485 public void evalStateCommand(String command)
488 if (lastCommand == null || !lastCommand.equals(command))
490 viewer.evalStringQuiet(command + "\n");
493 lastCommand = command;
497 * colour any structures associated with sequences in the given alignment
498 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
499 * if colourBySequence is enabled.
501 public void colourBySequence(AlignmentViewPanel alignmentv)
503 boolean showFeatures = alignmentv.getAlignViewport()
504 .isShowSequenceFeatures();
505 if (!colourBySequence || !isLoadingFinished())
509 if (getSsm() == null)
513 String[] files = getPdbFile();
515 SequenceRenderer sr = getSequenceRenderer(alignmentv);
517 FeatureRenderer fr = null;
520 fr = getFeatureRenderer(alignmentv);
522 AlignmentI alignment = alignmentv.getAlignment();
524 for (jalview.structure.StructureMappingcommandSet cpdbbyseq : getColourBySequenceCommands(files, sr, fr, alignment))
526 for (String cbyseq : cpdbbyseq.commands)
528 executeWhenReady(cbyseq);
540 protected StructureMappingcommandSet[] getColourBySequenceCommands(
541 String[] files, SequenceRenderer sr, FeatureRenderer fr,
542 AlignmentI alignment)
545 .getColourBySequenceCommand(getSsm(), files, getSequence(), sr,
553 protected void executeWhenReady(String command)
555 evalStateCommand(command);
558 public void createImage(String file, String type, int quality)
560 System.out.println("JMOL CREATE IMAGE");
563 public String createImage(String fileName, String type,
564 Object textOrBytes, int quality)
566 System.out.println("JMOL CREATE IMAGE");
570 public String eval(String strEval)
572 // System.out.println(strEval);
573 // "# 'eval' is implemented only for the applet.";
577 // End StructureListener
578 // //////////////////////////
580 public float[][] functionXY(String functionName, int x, int y)
585 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
587 // TODO Auto-generated method stub
591 public Color getColour(int atomIndex, int pdbResNum, String chain,
594 if (getModelNum(pdbfile) < 0)
598 // TODO: verify atomIndex is selecting correct model.
599 // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4
600 int colour = viewer.ms.at[atomIndex]
601 .atomPropertyInt(T.color);
602 return new Color(colour);
606 * returns the current featureRenderer that should be used to colour the
613 public abstract FeatureRenderer getFeatureRenderer(
614 AlignmentViewPanel alignment);
617 * instruct the Jalview binding to update the pdbentries vector if necessary
618 * prior to matching the jmol view's contents to the list of structure files
619 * Jalview knows about.
621 public abstract void refreshPdbEntries();
623 private int getModelNum(String modelFileName)
625 String[] mfn = getPdbFile();
630 for (int i = 0; i < mfn.length; i++)
632 if (mfn[i].equalsIgnoreCase(modelFileName))
641 * map between index of model filename returned from getPdbFile and the first
642 * index of models from this file in the viewer. Note - this is not trimmed -
643 * use getPdbFile to get number of unique models.
645 private int _modelFileNameMap[];
647 // ////////////////////////////////
648 // /StructureListener
650 public synchronized String[] getPdbFile()
654 return new String[0];
656 if (modelFileNames == null)
658 String mset[] = new String[viewer.ms.mc];
659 _modelFileNameMap = new int[mset.length];
660 String m = viewer.ms.getModelFileName(0);
666 mset[0] = new File(m).getAbsolutePath();
667 } catch (AccessControlException x)
669 // usually not allowed to do this in applet
671 .println("jmolBinding: Using local file string from Jmol: "
674 if (mset[0].indexOf("/file:") != -1)
676 // applet path with docroot - discard as format won't match pdbfile
681 for (int i = 1; i < mset.length; i++)
683 m = viewer.ms.getModelFileName(i);
689 mset[j] = new File(m).getAbsolutePath();
690 } catch (AccessControlException x)
692 // usually not allowed to do this in applet, so keep raw handle
693 // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
696 _modelFileNameMap[j] = i; // record the model index for the filename
697 // skip any additional models in the same file (NMR structures)
698 if ((mset[j] == null ? mset[j] != mset[j - 1]
699 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
704 modelFileNames = new String[j];
705 System.arraycopy(mset, 0, modelFileNames, 0, j);
707 return modelFileNames;
711 * map from string to applet
714 public Map<String, Object> getRegistryInfo()
716 // TODO Auto-generated method stub
721 * returns the current sequenceRenderer that should be used to colour the
728 public abstract SequenceRenderer getSequenceRenderer(
729 AlignmentViewPanel alignment);
731 // ///////////////////////////////
732 // JmolStatusListener
734 public void handlePopupMenu(int x, int y)
736 // jmolpopup.show(x, y);
737 // jmolpopup.jpiShow(x, y);
741 * Highlight zero, one or more atoms on the structure
744 public void highlightAtoms(List<AtomSpec> atoms)
748 for (AtomSpec atom : atoms)
750 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
751 atom.getChain(), atom.getPdbFile());
757 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
760 if (modelFileNames == null)
765 // look up file model number for this pdbfile
767 // may need to adjust for URLencoding here - we don't worry about that yet.
768 while (mdlNum < modelFileNames.length
769 && !pdbfile.equals(modelFileNames[mdlNum]))
773 if (mdlNum == modelFileNames.length)
779 // if (!pdbfile.equals(pdbentry.getFile()))
781 if (resetLastRes.length() > 0)
783 viewer.evalStringQuiet(resetLastRes.toString());
786 StringBuilder cmd = new StringBuilder(64);
787 cmd.append("select " + pdbResNum); // +modelNum
789 resetLastRes.setLength(0);
790 resetLastRes.append("select " + pdbResNum); // +modelNum
793 resetLastRes.append(":");
794 if (!chain.equals(" "))
797 resetLastRes.append(chain);
800 cmd.append(" /" + (mdlNum + 1));
801 resetLastRes.append("/" + (mdlNum + 1));
803 cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;");
805 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
806 + " and not hetero; spacefill 0;");
808 cmd.append("spacefill 200;select none");
810 viewer.evalStringQuiet(cmd.toString());
815 boolean debug = true;
817 private void jmolHistory(boolean enable)
819 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
822 public void loadInline(String string)
826 // viewer.loadInline(strModel, isAppend);
828 // construct fake fullPathName and fileName so we can identify the file
830 // Then, construct pass a reader for the string to Jmol.
831 // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName,
832 // fileName, null, reader, false, null, null, 0);
833 viewer.openStringInline(string);
836 public void mouseOverStructure(int atomIndex, String strInfo)
839 int alocsep = strInfo.indexOf("^");
840 int mdlSep = strInfo.indexOf("/");
841 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
843 if (chainSeparator == -1)
845 chainSeparator = strInfo.indexOf(".");
846 if (mdlSep > -1 && mdlSep < chainSeparator)
848 chainSeparator1 = chainSeparator;
849 chainSeparator = mdlSep;
852 // handle insertion codes
855 pdbResNum = Integer.parseInt(strInfo.substring(
856 strInfo.indexOf("]") + 1, alocsep));
861 pdbResNum = Integer.parseInt(strInfo.substring(
862 strInfo.indexOf("]") + 1, chainSeparator));
866 if (strInfo.indexOf(":") > -1)
868 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
869 strInfo.indexOf("."));
876 String pdbfilename = modelFileNames[frameNo]; // default is first or current
880 if (chainSeparator1 == -1)
882 chainSeparator1 = strInfo.indexOf(".", mdlSep);
884 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
885 chainSeparator1) : strInfo.substring(mdlSep + 1);
888 // recover PDB filename for the model hovered over.
889 int _mp = _modelFileNameMap.length - 1, mnumber = new Integer(mdlId)
891 while (mnumber < _modelFileNameMap[_mp])
895 pdbfilename = modelFileNames[_mp];
896 if (pdbfilename == null)
898 pdbfilename = new File(
899 viewer.ms.getModelFileName(mnumber))
903 } catch (Exception e)
908 if (lastMessage == null || !lastMessage.equals(strInfo))
910 getSsm().mouseOverStructure(pdbResNum, chainId, pdbfilename);
913 lastMessage = strInfo;
916 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
920 System.err.println("Ignoring additional hover info: " + data
921 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
923 mouseOverStructure(atomIndex, strInfo);
927 * { if (history != null && strStatus != null &&
928 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
932 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
935 * this implements the toggle label behaviour copied from the original
936 * structure viewer, MCView
940 System.err.println("Ignoring additional pick data string " + strData);
942 int chainSeparator = strInfo.indexOf(":");
944 if (chainSeparator == -1)
946 chainSeparator = strInfo.indexOf(".");
949 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
951 String mdlString = "";
952 if ((p = strInfo.indexOf(":")) > -1)
954 picked += strInfo.substring(p + 1, strInfo.indexOf("."));
957 if ((p = strInfo.indexOf("/")) > -1)
959 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
961 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
965 if (!atomsPicked.contains(picked))
967 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
968 atomsPicked.addElement(picked);
972 viewer.evalString("select " + picked + ";label off");
973 atomsPicked.removeElement(picked);
976 // TODO: in application this happens
978 // if (scriptWindow != null)
980 // scriptWindow.sendConsoleMessage(strInfo);
981 // scriptWindow.sendConsoleMessage("\n");
987 public void notifyCallback(CBK type, Object[] data)
994 notifyFileLoaded((String) data[1], (String) data[2],
995 (String) data[3], (String) data[4],
996 ((Integer) data[5]).intValue());
1000 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
1002 // also highlight in alignment
1004 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
1008 notifyScriptTermination((String) data[2],
1009 ((Integer) data[3]).intValue());
1012 sendConsoleEcho((String) data[1]);
1015 sendConsoleMessage((data == null) ? ((String) null)
1016 : (String) data[1]);
1019 // System.err.println("Ignoring error callback.");
1029 System.err.println("Unhandled callback " + type + " "
1030 + data[1].toString());
1033 } catch (Exception e)
1035 System.err.println("Squashed Jmol callback handler error:");
1036 e.printStackTrace();
1041 public boolean notifyEnabled(CBK callbackPick)
1043 switch (callbackPick)
1059 // incremented every time a load notification is successfully handled -
1060 // lightweight mechanism for other threads to detect when they can start
1061 // referrring to new structures.
1062 private long loadNotifiesHandled = 0;
1064 public long getLoadNotifiesHandled()
1066 return loadNotifiesHandled;
1069 public void notifyFileLoaded(String fullPathName, String fileName2,
1070 String modelName, String errorMsg, int modelParts)
1072 if (errorMsg != null)
1074 fileLoadingError = errorMsg;
1078 // TODO: deal sensibly with models loaded inLine:
1079 // modelName will be null, as will fullPathName.
1081 // the rest of this routine ignores the arguments, and simply interrogates
1082 // the Jmol view to find out what structures it contains, and adds them to
1083 // the structure selection manager.
1084 fileLoadingError = null;
1085 String[] oldmodels = modelFileNames;
1086 modelFileNames = null;
1087 chainNames = new Vector<String>();
1088 chainFile = new Hashtable<String, String>();
1089 boolean notifyLoaded = false;
1090 String[] modelfilenames = getPdbFile();
1091 // first check if we've lost any structures
1092 if (oldmodels != null && oldmodels.length > 0)
1095 for (int i = 0; i < oldmodels.length; i++)
1097 for (int n = 0; n < modelfilenames.length; n++)
1099 if (modelfilenames[n] == oldmodels[i])
1101 oldmodels[i] = null;
1105 if (oldmodels[i] != null)
1112 String[] oldmfn = new String[oldm];
1114 for (int i = 0; i < oldmodels.length; i++)
1116 if (oldmodels[i] != null)
1118 oldmfn[oldm++] = oldmodels[i];
1121 // deregister the Jmol instance for these structures - we'll add
1122 // ourselves again at the end for the current structure set.
1123 getSsm().removeStructureViewerListener(this, oldmfn);
1126 refreshPdbEntries();
1127 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1129 String fileName = modelfilenames[modelnum];
1130 boolean foundEntry = false;
1131 MCview.PDBfile pdb = null;
1132 String pdbfile = null;
1133 // model was probably loaded inline - so check the pdb file hashcode
1136 // calculate essential attributes for the pdb data imported inline.
1137 // prolly need to resolve modelnumber properly - for now just use our
1139 pdbfile = viewer.getData("" + (1 + _modelFileNameMap[modelnum])
1142 // search pdbentries and sequences to find correct pdbentry for this
1144 for (int pe = 0; pe < getPdbCount(); pe++)
1146 boolean matches = false;
1147 if (fileName == null)
1150 // see JAL-623 - need method of matching pasted data up
1152 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1153 pdbfile, AppletFormatAdapter.PASTE);
1154 getPdbEntry(modelnum).setFile("INLINE" + pdb.id);
1161 File fl = new File(getPdbEntry(pe).getFile());
1162 matches = fl.equals(new File(fileName));
1166 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1169 // to be tested. See mantis bug
1170 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1171 String protocol = AppletFormatAdapter.URL;
1176 protocol = AppletFormatAdapter.FILE;
1178 } catch (Exception e)
1183 // Explicitly map to the filename used by Jmol ;
1184 pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe],
1185 fileName, protocol);
1186 // pdbentry[pe].getFile(), protocol);
1192 // add an entry for every chain in the model
1193 for (int i = 0; i < pdb.chains.size(); i++)
1195 String chid = new String(pdb.id + ":"
1196 + pdb.chains.elementAt(i).id);
1197 chainFile.put(chid, fileName);
1198 chainNames.addElement(chid);
1200 notifyLoaded = true;
1204 if (!foundEntry && associateNewStructs)
1206 // this is a foreign pdb file that jalview doesn't know about - add
1207 // it to the dataset and try to find a home - either on a matching
1208 // sequence or as a new sequence.
1209 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1211 // parse pdb file into a chain, etc.
1212 // locate best match for pdb in associated views and add mapping to
1214 // if properly registered then
1215 notifyLoaded = true;
1220 // so finally, update the jmol bits and pieces
1221 // if (jmolpopup != null)
1223 // // potential for deadlock here:
1224 // // jmolpopup.updateComputedMenus();
1226 if (!isLoadingFromArchive())
1228 viewer.evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
1230 // register ourselves as a listener and notify the gui that it needs to
1232 getSsm().addStructureViewerListener(this);
1235 FeatureRenderer fr = getFeatureRenderer(null);
1241 loadNotifiesHandled++;
1243 setLoadingFromArchive(false);
1246 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1248 notifyAtomPicked(iatom, strMeasure, null);
1251 public abstract void notifyScriptTermination(String strStatus,
1255 * display a message echoed from the jmol viewer
1259 public abstract void sendConsoleEcho(String strEcho); /*
1260 * { showConsole(true);
1262 * history.append("\n" +
1266 // /End JmolStatusListener
1267 // /////////////////////////////
1271 * status message - usually the response received after a script
1274 public abstract void sendConsoleMessage(String strStatus);
1276 public void setCallbackFunction(String callbackType,
1277 String callbackFunction)
1279 System.err.println("Ignoring set-callback request to associate "
1280 + callbackType + " with function " + callbackFunction);
1284 public void setJalviewColourScheme(ColourSchemeI cs)
1286 colourBySequence = false;
1294 StringBuilder command = new StringBuilder(128);
1295 command.append("select *;color white;");
1296 List<String> residueSet = ResidueProperties.getResidues(isNucleotide(),
1298 for (String res : residueSet)
1300 Color col = cs.findColour(res.charAt(0));
1301 command.append("select " + res + ";color[" + col.getRed() + ","
1302 + col.getGreen() + "," + col.getBlue() + "];");
1305 evalStateCommand(command.toString());
1309 public void showHelp()
1311 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1315 * open the URL somehow
1319 public abstract void showUrl(String url, String target);
1322 * called when the binding thinks the UI needs to be refreshed after a Jmol
1323 * state change. this could be because structures were loaded, or because an
1324 * error has occured.
1326 public abstract void refreshGUI();
1329 * called to show or hide the associated console window container.
1333 public abstract void showConsole(boolean show);
1336 * @param renderPanel
1338 * - when true will initialise jmol's file IO system (should be false
1339 * in applet context)
1341 * @param documentBase
1343 * @param commandOptions
1345 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1346 String htmlName, URL documentBase, URL codeBase,
1347 String commandOptions)
1349 allocateViewer(renderPanel, jmolfileio, htmlName, documentBase,
1350 codeBase, commandOptions, null, null);
1355 * @param renderPanel
1357 * - when true will initialise jmol's file IO system (should be false
1358 * in applet context)
1360 * @param documentBase
1362 * @param commandOptions
1363 * @param consolePanel
1364 * - panel to contain Jmol console
1365 * @param buttonsToShow
1366 * - buttons to show on the console, in ordr
1368 public void allocateViewer(Container renderPanel, boolean jmolfileio,
1369 String htmlName, URL documentBase, URL codeBase,
1370 String commandOptions, final Container consolePanel,
1371 String buttonsToShow)
1373 if (commandOptions == null)
1375 commandOptions = "";
1377 viewer = (Viewer) JmolViewer.allocateViewer(renderPanel,
1378 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1379 + ((Object) this).toString(), documentBase, codeBase,
1380 commandOptions, this);
1382 viewer.setJmolStatusListener(this); // extends JmolCallbackListener
1384 console = createJmolConsole(consolePanel, buttonsToShow);
1385 if (consolePanel != null)
1387 consolePanel.addComponentListener(this);
1393 protected abstract JmolAppConsoleInterface createJmolConsole(
1394 Container consolePanel, String buttonsToShow);
1396 protected org.jmol.api.JmolAppConsoleInterface console = null;
1398 public void setBackgroundColour(java.awt.Color col)
1401 viewer.evalStringQuiet("background [" + col.getRed() + ","
1402 + col.getGreen() + "," + col.getBlue() + "];");
1407 public Dimension resizeInnerPanel(String data)
1409 // Jalview doesn't honour resize panel requests
1413 public boolean isFinishedInit()
1415 return finishedInit;
1418 public void setFinishedInit(boolean finishedInit)
1420 this.finishedInit = finishedInit;
1426 protected void closeConsole()
1428 if (console != null)
1432 console.setVisible(false);
1435 } catch (Exception x)
1444 * ComponentListener method
1447 public void componentMoved(ComponentEvent e)
1452 * ComponentListener method
1455 public void componentResized(ComponentEvent e)
1460 * ComponentListener method
1463 public void componentShown(ComponentEvent e)
1469 * ComponentListener method
1472 public void componentHidden(ComponentEvent e)