2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
18 package jalview.ext.jmol;
23 import java.applet.Applet;
25 import java.awt.event.*;
27 import jalview.api.FeatureRenderer;
28 import jalview.api.SequenceRenderer;
29 import jalview.api.SequenceStructureBinding;
30 import jalview.datamodel.*;
31 import jalview.structure.*;
34 import org.jmol.api.*;
35 import org.jmol.adapter.smarter.SmarterJmolAdapter;
37 import org.jmol.popup.*;
38 import org.jmol.viewer.JmolConstants;
40 import jalview.schemes.*;
42 public abstract class JalviewJmolBinding implements StructureListener,
43 JmolStatusListener, SequenceStructureBinding, JmolSelectionListener
47 * set if Jmol state is being restored from some source - instructs binding
48 * not to apply default display style when structure set is updated for first
51 private boolean loadingFromArchive = false;
54 * state flag used to check if the Jmol viewer's paint method can be called
56 private boolean finishedInit = false;
58 public boolean isFinishedInit()
63 public void setFinishedInit(boolean finishedInit)
65 this.finishedInit = finishedInit;
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 atomsPicked = new Vector();
78 public Vector chainNames;
81 * array of target chains for seuqences - tied to pdbentry and sequence[]
83 protected String[][] chains;
85 boolean colourBySequence = true;
87 StringBuffer eval = new StringBuffer();
89 public String fileLoadingError;
92 * the default or current model displayed if the model cannot be identified
93 * from the selection message
97 protected JmolPopup jmolpopup;
103 boolean loadedInline;
106 * current set of model filenames loaded in the Jmol instance
108 String[] modelFileNames = null;
110 public PDBEntry[] pdbentry;
113 * datasource protocol for access to PDBEntry
115 String protocol = null;
117 StringBuffer resetLastRes = new StringBuffer();
120 * sequences mapped to each pdbentry
122 public SequenceI[][] sequence;
124 StructureSelectionManager ssm;
126 public JmolViewer viewer;
128 public JalviewJmolBinding(PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
129 String[][] chains, String protocol)
131 this.sequence = sequenceIs;
132 this.chains = chains;
133 this.pdbentry = pdbentry;
134 this.protocol = protocol;
137 this.chains = new String[pdbentry.length][];
140 * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
141 * "jalviewJmol", ap.av.applet .getDocumentBase(),
142 * ap.av.applet.getCodeBase(), "", this);
144 * jmolpopup = JmolPopup.newJmolPopup(viewer, true, "Jmol", true);
148 public JalviewJmolBinding(JmolViewer viewer2)
151 viewer.setJmolStatusListener(this);
152 viewer.addSelectionListener(this);
156 * construct a title string for the viewer window based on the data jalview
161 public String getViewerTitle()
163 if (sequence == null || pdbentry == null || sequence.length < 1
164 || pdbentry.length < 1)
166 return ("Jalview Jmol Window");
168 StringBuffer title = new StringBuffer(sequence[0][0].getName() + ":"
169 + pdbentry[0].getId());
171 if (pdbentry[0].getProperty() != null)
173 if (pdbentry[0].getProperty().get("method") != null)
175 title.append(" Method: ");
176 title.append(pdbentry[0].getProperty().get("method"));
178 if (pdbentry[0].getProperty().get("chains") != null)
180 title.append(" Chain:");
181 title.append(pdbentry[0].getProperty().get("chains"));
184 return title.toString();
188 * prepare the view for a given set of models/chains. chainList contains
189 * strings of the form 'pdbfilename:Chaincode'
192 * list of chains to make visible
194 public void centerViewer(Vector chainList)
196 StringBuffer cmd = new StringBuffer();
199 for (int i = 0, iSize = chainList.size(); i < iSize; i++)
202 lbl = (String) chainList.elementAt(i);
206 mlength = lbl.indexOf(":", p);
207 } while (p < mlength && mlength < (lbl.length() - 2));
208 cmd.append(":" + lbl.substring(mlength + 1) + " /"
209 + getModelNum(lbl.substring(0, mlength)) + " or ");
211 if (cmd.length() > 0)
212 cmd.setLength(cmd.length() - 4);
213 evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd);
216 public void closeViewer()
218 viewer.setModeMouse(org.jmol.viewer.JmolConstants.MOUSE_NONE);
219 // remove listeners for all structures in viewer
220 StructureSelectionManager.getStructureSelectionManager()
221 .removeStructureViewerListener(this, this.getPdbFile());
222 // and shut down jmol
223 viewer.evalStringQuiet("zap");
224 viewer.setJmolStatusListener(null);
229 public void colourByChain()
231 colourBySequence = false;
232 // TODO: colour by chain should colour each chain distinctly across all visible models
233 // TODO: http://issues.jalview.org/browse/JAL-628
234 evalStateCommand("select *;color chain");
237 public void colourByCharge()
239 colourBySequence = false;
240 evalStateCommand("select *;color white;select ASP,GLU;color red;"
241 + "select LYS,ARG;color blue;select CYS;color yellow");
245 * superpose the structures associated with sequences in the alignment
246 * according to their corresponding positions.
248 public void superposeStructures(AlignmentI alignment)
250 superposeStructures(alignment, -1, null);
254 * superpose the structures associated with sequences in the alignment
255 * according to their corresponding positions. ded)
257 * @param refStructure
258 * - select which pdb file to use as reference (default is -1 - the
259 * first structure in the alignment)
261 public void superposeStructures(AlignmentI alignment, int refStructure)
263 superposeStructures(alignment, refStructure, null);
267 * superpose the structures associated with sequences in the alignment
268 * according to their corresponding positions. ded)
269 * @param refStructure
270 * - select which pdb file to use as reference (default is -1 - the
271 * first structure in the alignment)
272 * @param hiddenCols TODO
274 public void superposeStructures(AlignmentI alignment, int refStructure, ColumnSelection hiddenCols)
276 String[] files = getPdbFile();
277 if (refStructure>=files.length)
279 System.err.println("Invalid reference structure value "+refStructure);
286 StringBuffer command = new StringBuffer(), selectioncom = new StringBuffer();
288 boolean matched[] = new boolean[alignment.getWidth()];
289 for (int m = 0; m < matched.length; m++)
292 matched[m] = (hiddenCols!=null) ? hiddenCols.isVisible(m) : true;
295 int commonrpositions[][] = new int[files.length][alignment.getWidth()];
296 String isel[] = new String[files.length];
297 // reference structure - all others are superposed in it
298 String[] targetC = new String[files.length];
299 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
301 StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
303 if (mapping == null || mapping.length < 1)
307 for (int s = 0; s < sequence[pdbfnum].length; s++)
309 for (int sp, m = 0; m < mapping.length; m++)
311 if (mapping[m].getSequence() == sequence[pdbfnum][s]
312 && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
314 if (refStructure == -1)
316 refStructure = pdbfnum;
318 SequenceI asp = alignment.getSequenceAt(sp);
319 for (int r = 0; r < matched.length; r++)
325 matched[r] = false; // assume this is not a good site
326 if (r >= asp.getLength())
331 if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
333 // no mapping to gaps in sequence
336 int t = asp.findPosition(r); // sequence position
337 int apos = mapping[m].getAtomNum(t);
338 int pos = mapping[m].getPDBResNum(t);
340 if (pos < 1 || pos == lastPos)
342 // can't align unmapped sequence
345 matched[r] = true; // this is a good ite
347 // just record this residue position
348 commonrpositions[pdbfnum][r] = pos;
350 // create model selection suffix
351 isel[pdbfnum] = "/" + (pdbfnum + 1) + ".1";
352 if (mapping[m].getChain() == null
353 || mapping[m].getChain().trim().length() == 0)
355 targetC[pdbfnum] = "";
359 targetC[pdbfnum] = ":" + mapping[m].getChain();
361 // move on to next pdb file
362 s = sequence[pdbfnum].length;
368 String[] selcom = new String[files.length];
369 // generate select statements to select regions to superimpose structures
371 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
373 String chainCd = targetC[pdbfnum];
376 StringBuffer molsel = new StringBuffer();
378 for (int r = 0; r < matched.length; r++)
383 if (lpos != commonrpositions[pdbfnum][r] - 1)
389 molsel.append(chainCd);
390 // molsel.append("} {");
396 // continuous run - and lpos >-1
399 // at the beginning, so add dash
405 lpos = commonrpositions[pdbfnum][r];
406 // molsel.append(lpos);
409 // add final selection phrase
413 molsel.append(chainCd);
416 selcom[pdbfnum] = molsel.toString();
417 selectioncom.append("((");
418 selectioncom.append(selcom[pdbfnum].substring(1, selcom[pdbfnum].length()-1));
419 selectioncom.append(" )& ");
420 selectioncom.append(pdbfnum+1);
421 selectioncom.append(".1)");
422 if (pdbfnum<files.length-1)
424 selectioncom.append("|");
429 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
431 if (pdbfnum == refStructure)
435 command.append("compare ");
437 command.append(1 + pdbfnum);
438 command.append(".1} {");
439 command.append(1 + refStructure);
440 command.append(".1} SUBSET {*.CA | *.P} ATOMS ");
442 // form the matched pair strings
444 for (int s = 0; s < 2; s++)
446 command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
448 command.append(" ROTATE TRANSLATE;\n");
450 System.out.println("Select regions:\n" + selectioncom.toString());
451 evalStateCommand("select *; cartoons off; backbone; select ("+selectioncom.toString()+"); cartoons; ");
452 // selcom.append("; ribbons; ");
453 System.out.println("Superimpose command(s):\n" + command.toString());
455 evalStateCommand(command.toString());
457 // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
460 public void evalStateCommand(String command)
463 if (lastCommand == null || !lastCommand.equals(command))
465 viewer.evalStringQuiet(command + "\n");
468 lastCommand = command;
472 * colour any structures associated with sequences in the given alignment
473 * using the getFeatureRenderer() and getSequenceRenderer() renderers but only
474 * if colourBySequence is enabled.
476 public void colourBySequence(boolean showFeatures, AlignmentI alignment)
478 if (!colourBySequence)
484 String[] files = getPdbFile();
485 SequenceRenderer sr = getSequenceRenderer();
487 FeatureRenderer fr = null;
490 fr = getFeatureRenderer();
493 StringBuffer command = new StringBuffer();
495 for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
497 StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
499 if (mapping == null || mapping.length < 1)
503 for (int s = 0; s < sequence[pdbfnum].length; s++)
505 for (int sp, m = 0; m < mapping.length; m++)
507 if (mapping[m].getSequence() == sequence[pdbfnum][s]
508 && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
510 SequenceI asp = alignment.getSequenceAt(sp);
511 for (int r = 0; r < asp.getLength(); r++)
513 // no mapping to gaps in sequence
514 if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
518 int pos = mapping[m].getPDBResNum(asp.findPosition(r));
520 if (pos < 1 || pos == lastPos)
525 Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
528 col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
529 String newSelcom = (mapping[m].getChain() != " " ? ":"
530 + mapping[m].getChain() : "")
539 + col.getBlue() + "]";
540 if (command.toString().endsWith(newSelcom))
542 command = condenseCommand(command.toString(), pos);
545 // TODO: deal with case when buffer is too large for Jmol to parse
546 // - execute command and flush
548 command.append(";select " + pos);
549 command.append(newSelcom);
556 evalStateCommand(command.toString());
559 public boolean isColourBySequence()
561 return colourBySequence;
564 public void setColourBySequence(boolean colourBySequence)
566 this.colourBySequence = colourBySequence;
569 StringBuffer condenseCommand(String command, int pos)
572 StringBuffer sb = new StringBuffer(command.substring(0,
573 command.lastIndexOf("select") + 7));
575 command = command.substring(sb.length());
579 if (command.indexOf("-") > -1)
581 start = command.substring(0, command.indexOf("-"));
585 start = command.substring(0, command.indexOf(":"));
588 sb.append(start + "-" + pos + command.substring(command.indexOf(":")));
593 public void createImage(String file, String type, int quality)
595 System.out.println("JMOL CREATE IMAGE");
598 public String createImage(String fileName, String type,
599 Object textOrBytes, int quality)
601 System.out.println("JMOL CREATE IMAGE");
605 public String eval(String strEval)
607 // System.out.println(strEval);
608 // "# 'eval' is implemented only for the applet.";
612 // End StructureListener
613 // //////////////////////////
615 public float[][] functionXY(String functionName, int x, int y)
620 public float[][][] functionXYZ(String functionName, int nx, int ny, int nz)
622 // TODO Auto-generated method stub
626 public Color getColour(int atomIndex, int pdbResNum, String chain,
629 if (getModelNum(pdbfile) < 0)
631 // TODO: verify atomIndex is selecting correct model.
632 return new Color(viewer.getAtomArgb(atomIndex));
636 * returns the current featureRenderer that should be used to colour the
641 public abstract FeatureRenderer getFeatureRenderer();
644 * instruct the Jalview binding to update the pdbentries vector if necessary
645 * prior to matching the jmol view's contents to the list of structure files
646 * Jalview knows about.
648 public abstract void refreshPdbEntries();
650 private int getModelNum(String modelFileName)
652 String[] mfn = getPdbFile();
657 for (int i = 0; i < mfn.length; i++)
659 if (mfn[i].equalsIgnoreCase(modelFileName))
665 // ////////////////////////////////
666 // /StructureListener
667 public synchronized String[] getPdbFile()
669 if (modelFileNames == null)
671 String mset[] = new String[viewer.getModelCount()];
673 mset[0] = viewer.getModelFileName(0);
674 for (int i = 1; i < mset.length; i++)
676 // skip any additional models in the same file (NMR structures)
677 if (!(mset[j] = viewer.getModelFileName(i)).equals(mset[j-1]))
682 modelFileNames = new String[j];
683 System.arraycopy(mset, 0, modelFileNames, 0, j);
685 return modelFileNames;
689 * map from string to applet
691 public Map getRegistryInfo()
693 // TODO Auto-generated method stub
698 * returns the current sequenceRenderer that should be used to colour the
703 public abstract SequenceRenderer getSequenceRenderer();
705 // ///////////////////////////////
706 // JmolStatusListener
708 public void handlePopupMenu(int x, int y)
710 jmolpopup.show(x, y);
714 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
717 if (modelFileNames == null)
722 // look up file model number for this pdbfile
725 // may need to adjust for URLencoding here - we don't worry about that yet.
726 while (mdlNum < modelFileNames.length
727 && !pdbfile.equals(modelFileNames[mdlNum]))
729 // System.out.println("nomatch:"+pdbfile+"\nmodelfn:"+fn);
732 if (mdlNum == modelFileNames.length)
738 // if (!pdbfile.equals(pdbentry.getFile()))
740 if (resetLastRes.length() > 0)
742 viewer.evalStringQuiet(resetLastRes.toString());
746 eval.append("select " + pdbResNum); // +modelNum
748 resetLastRes.setLength(0);
749 resetLastRes.append("select " + pdbResNum); // +modelNum
752 resetLastRes.append(":");
753 if (!chain.equals(" "))
756 resetLastRes.append(chain);
759 eval.append(" /" + (mdlNum + 1));
760 resetLastRes.append("/" + (mdlNum + 1));
762 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
764 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
765 + " and not hetero; spacefill 0;");
767 eval.append("spacefill 200;select none");
769 viewer.evalStringQuiet(eval.toString());
774 boolean debug = true;
776 private void jmolHistory(boolean enable)
778 viewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off"));
781 public void loadInline(String string)
784 viewer.openStringInline(string);
787 public void mouseOverStructure(int atomIndex, String strInfo)
790 int mdlSep = strInfo.indexOf("/");
791 int chainSeparator = strInfo.indexOf(":"), chainSeparator1 = -1;
793 if (chainSeparator == -1)
795 chainSeparator = strInfo.indexOf(".");
796 if (mdlSep > -1 && mdlSep < chainSeparator)
798 chainSeparator1 = chainSeparator;
799 chainSeparator = mdlSep;
802 pdbResNum = Integer.parseInt(strInfo.substring(
803 strInfo.indexOf("]") + 1, chainSeparator));
807 if (strInfo.indexOf(":") > -1)
808 chainId = strInfo.substring(strInfo.indexOf(":") + 1,
809 strInfo.indexOf("."));
815 String pdbfilename = modelFileNames[frameNo]; // default is first or current
819 if (chainSeparator1 == -1)
821 chainSeparator1 = strInfo.indexOf(".", mdlSep);
823 String mdlId = (chainSeparator1 > -1) ? strInfo.substring(mdlSep + 1,
824 chainSeparator1) : strInfo.substring(mdlSep + 1);
827 // recover PDB filename for the model hovered over.
829 .getModelFileName(new Integer(mdlId).intValue() - 1);
830 } catch (Exception e)
835 if (lastMessage == null || !lastMessage.equals(strInfo))
836 ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename);
838 lastMessage = strInfo;
841 public void notifyAtomHovered(int atomIndex, String strInfo, String data)
845 System.err.println("Ignoring additional hover info: " + data
846 + " (other info: '" + strInfo + "' pos " + atomIndex + ")");
848 mouseOverStructure(atomIndex, strInfo);
852 * { if (history != null && strStatus != null &&
853 * !strStatus.equals("Script completed")) { history.append("\n" + strStatus);
857 public void notifyAtomPicked(int atomIndex, String strInfo, String strData)
860 * this implements the toggle label behaviour copied from the original
861 * structure viewer, MCView
865 System.err.println("Ignoring additional pick data string " + strData);
867 int chainSeparator = strInfo.indexOf(":");
869 if (chainSeparator == -1)
870 chainSeparator = strInfo.indexOf(".");
872 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
874 String mdlString = "";
875 if ((p = strInfo.indexOf(":")) > -1)
876 picked += strInfo.substring(p + 1, strInfo.indexOf("."));
878 if ((p = strInfo.indexOf("/")) > -1)
880 mdlString += strInfo.substring(p, strInfo.indexOf(" #"));
882 picked = "((" + picked + ".CA" + mdlString + ")|(" + picked + ".P"
886 if (!atomsPicked.contains(picked))
888 viewer.evalStringQuiet("select " + picked + ";label %n %r:%c");
889 atomsPicked.addElement(picked);
893 viewer.evalString("select " + picked + ";label off");
894 atomsPicked.removeElement(picked);
897 // TODO: in application this happens
899 // if (scriptWindow != null)
901 // scriptWindow.sendConsoleMessage(strInfo);
902 // scriptWindow.sendConsoleMessage("\n");
907 public void notifyCallback(int type, Object[] data)
913 case JmolConstants.CALLBACK_LOADSTRUCT:
914 notifyFileLoaded((String) data[1], (String) data[2],
915 (String) data[3], (String) data[4],
916 ((Integer) data[5]).intValue());
919 case JmolConstants.CALLBACK_PICK:
920 notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
922 // also highlight in alignment
923 case JmolConstants.CALLBACK_HOVER:
924 notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
927 case JmolConstants.CALLBACK_SCRIPT:
928 notifyScriptTermination((String) data[2],
929 ((Integer) data[3]).intValue());
931 case JmolConstants.CALLBACK_ECHO:
932 sendConsoleEcho((String) data[1]);
934 case JmolConstants.CALLBACK_MESSAGE:
935 sendConsoleMessage((data == null) ? ((String) null)
938 case JmolConstants.CALLBACK_ERROR:
939 // System.err.println("Ignoring error callback.");
941 case JmolConstants.CALLBACK_SYNC:
942 case JmolConstants.CALLBACK_RESIZE:
945 case JmolConstants.CALLBACK_MEASURE:
947 case JmolConstants.CALLBACK_CLICK:
950 System.err.println("Unhandled callback " + type + " "
951 + data[1].toString());
954 } catch (Exception e)
956 System.err.println("Squashed Jmol callback handler error:");
961 public boolean notifyEnabled(int callbackPick)
963 switch (callbackPick)
965 case JmolConstants.CALLBACK_ECHO:
966 case JmolConstants.CALLBACK_LOADSTRUCT:
967 case JmolConstants.CALLBACK_MEASURE:
968 case JmolConstants.CALLBACK_MESSAGE:
969 case JmolConstants.CALLBACK_PICK:
970 case JmolConstants.CALLBACK_SCRIPT:
971 case JmolConstants.CALLBACK_HOVER:
972 case JmolConstants.CALLBACK_ERROR:
974 case JmolConstants.CALLBACK_RESIZE:
975 case JmolConstants.CALLBACK_SYNC:
976 case JmolConstants.CALLBACK_CLICK:
977 case JmolConstants.CALLBACK_ANIMFRAME:
978 case JmolConstants.CALLBACK_MINIMIZATION:
983 public void notifyFileLoaded(String fullPathName, String fileName2,
984 String modelName, String errorMsg, int modelParts)
986 if (errorMsg != null)
988 fileLoadingError = errorMsg;
992 // the rest of this routine ignores the arguments, and simply interrogates
993 // the Jmol view to find out what structures it contains, and adds them to
994 // the structure selection manager.
995 fileLoadingError = null;
996 String[] oldmodels = modelFileNames;
997 modelFileNames = null;
998 chainNames = new Vector();
999 boolean notifyLoaded = false;
1000 String[] modelfilenames = getPdbFile();
1001 ssm = StructureSelectionManager.getStructureSelectionManager();
1002 // first check if we've lost any structures
1003 if (oldmodels != null && oldmodels.length > 0)
1006 for (int i = 0; i < oldmodels.length; i++)
1008 for (int n = 0; n < modelfilenames.length; n++)
1010 if (modelfilenames[n] == oldmodels[i])
1012 oldmodels[i] = null;
1016 if (oldmodels[i] != null)
1023 String[] oldmfn = new String[oldm];
1025 for (int i = 0; i < oldmodels.length; i++)
1027 if (oldmodels[i] != null)
1029 oldmfn[oldm++] = oldmodels[i];
1032 // deregister the Jmol instance for these structures - we'll add
1033 // ourselves again at the end for the current structure set.
1034 ssm.removeStructureViewerListener(this, oldmfn);
1037 refreshPdbEntries();
1038 for (int modelnum = 0; modelnum < modelfilenames.length; modelnum++)
1040 String fileName = modelfilenames[modelnum];
1041 if (fileName != null)
1043 boolean foundEntry = false;
1044 // search pdbentries and sequences to find correct pdbentry and
1045 // sequence[] pair for this filename
1046 if (pdbentry != null)
1048 for (int pe = 0; pe < pdbentry.length; pe++)
1050 if (pdbentry[pe].getFile().equals(fileName))
1056 // TODO: replace with getData ?
1057 pdb = ssm.setMapping(sequence[pe], chains[pe],
1058 pdbentry[pe].getFile(), AppletFormatAdapter.PASTE);
1059 pdbentry[pe].setFile("INLINE" + pdb.id);
1063 // TODO: Jmol can in principle retrieve from CLASSLOADER but
1066 // to be tested. See mantis bug
1067 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
1068 String protocol = AppletFormatAdapter.URL;
1071 File fl = new java.io.File(pdbentry[pe].getFile());
1074 protocol = AppletFormatAdapter.FILE;
1076 } catch (Exception e)
1082 pdb = ssm.setMapping(sequence[pe], chains[pe],
1083 pdbentry[pe].getFile(), protocol);
1087 pdbentry[pe].setId(pdb.id);
1089 for (int i = 0; i < pdb.chains.size(); i++)
1091 chainNames.addElement(new String(pdb.id + ":"
1092 + ((MCview.PDBChain) pdb.chains.elementAt(i)).id));
1094 notifyLoaded = true;
1098 if (!foundEntry && associateNewStructs)
1100 // this is a foreign pdb file that jalview doesn't know about - add
1101 // it to the dataset and try to find a home - either on a matching
1102 // sequence or as a new sequence.
1103 String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1",
1105 // parse pdb file into a chain, etc.
1106 // locate best match for pdb in associated views and add mapping to
1108 // if properly registered then
1109 notifyLoaded = true;
1115 // so finally, update the jmol bits and pieces
1116 if (jmolpopup != null)
1118 jmolpopup.updateComputedMenus();
1120 if (!isLoadingFromArchive())
1122 viewer.evalStringQuiet("model 0; select backbone;restrict;cartoon;wireframe off;spacefill off");
1124 setLoadingFromArchive(false);
1125 // register ourselves as a listener and notify the gui that it needs to
1127 ssm.addStructureViewerListener(this);
1130 FeatureRenderer fr = getFeatureRenderer();
1139 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
1141 notifyAtomPicked(iatom, strMeasure, null);
1144 public abstract void notifyScriptTermination(String strStatus,
1148 * display a message echoed from the jmol viewer
1152 public abstract void sendConsoleEcho(String strEcho); /*
1153 * { showConsole(true);
1155 * history.append("\n" +
1159 // /End JmolStatusListener
1160 // /////////////////////////////
1164 * status message - usually the response received after a script
1167 public abstract void sendConsoleMessage(String strStatus);
1169 public void setCallbackFunction(String callbackType,
1170 String callbackFunction)
1172 System.err.println("Ignoring set-callback request to associate "
1173 + callbackType + " with function " + callbackFunction);
1177 public void setJalviewColourScheme(ColourSchemeI cs)
1179 colourBySequence = false;
1188 // TODO: Switch between nucleotide or aa selection expressions
1189 Enumeration en = ResidueProperties.aa3Hash.keys();
1190 StringBuffer command = new StringBuffer("select *;color white;");
1191 while (en.hasMoreElements())
1193 res = en.nextElement().toString();
1194 index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
1198 col = cs.findColour(ResidueProperties.aa[index].charAt(0));
1200 command.append("select " + res + ";color[" + col.getRed() + ","
1201 + col.getGreen() + "," + col.getBlue() + "];");
1204 evalStateCommand(command.toString());
1208 public void showHelp()
1210 showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp");
1214 * open the URL somehow
1218 public abstract void showUrl(String url, String target);
1221 * called when the binding thinks the UI needs to be refreshed after a Jmol
1222 * state change. this could be because structures were loaded, or because an
1223 * error has occured.
1225 public abstract void refreshGUI();
1228 * @param renderPanel
1230 * - when true will initialise jmol's file IO system (should be false
1231 * in applet context)
1233 * @param documentBase
1235 * @param commandOptions
1237 public void allocateViewer(Component renderPanel, boolean jmolfileio,
1238 String htmlName, URL documentBase, URL codeBase,
1239 String commandOptions)
1241 viewer = JmolViewer.allocateViewer(renderPanel,
1242 (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
1243 + ((Object) this).toString(), documentBase, codeBase,
1244 commandOptions, this);
1247 public void setLoadingFromArchive(boolean loadingFromArchive)
1249 this.loadingFromArchive = loadingFromArchive;
1252 public boolean isLoadingFromArchive()
1254 return loadingFromArchive;
1257 public void setBackgroundColour(java.awt.Color col)
1260 viewer.evalStringQuiet("background [" + col.getRed() + ","
1261 + col.getGreen() + "," + col.getBlue() + "];");
1266 * add structures and any known sequence associations
1268 * @returns the pdb entries added to the current set.
1270 public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
1274 Vector v = new Vector();
1275 Vector rtn = new Vector();
1276 for (int i = 0; i < pdbentry.length; i++)
1278 v.addElement(pdbentry[i]);
1280 for (int i = 0; i < pdbe.length; i++)
1282 int r = v.indexOf(pdbe[i]);
1283 if (r == -1 || r >= pdbentry.length)
1285 rtn.addElement(new int[]
1287 v.addElement(pdbe[i]);
1291 // just make sure the sequence/chain entries are all up to date
1292 addSequenceAndChain(r, seq[i], chns[i]);
1295 pdbe = new PDBEntry[v.size()];
1300 // expand the tied seuqence[] and string[] arrays
1301 SequenceI[][] sqs = new SequenceI[pdbentry.length][];
1302 String[][] sch = new String[pdbentry.length][];
1303 System.arraycopy(sequence, 0, sqs, 0, sequence.length);
1304 System.arraycopy(chains, 0, sch, 0, this.chains.length);
1307 pdbe = new PDBEntry[rtn.size()];
1308 for (int r = 0; r < pdbe.length; r++)
1310 int[] stri = ((int[]) rtn.elementAt(r));
1311 // record the pdb file as a new addition
1312 pdbe[r] = pdbentry[stri[0]];
1313 // and add the new sequence/chain entries
1314 addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
1324 public void addSequence(int pe, SequenceI[] seq)
1326 // add sequences to the pe'th pdbentry's seuqence set.
1327 addSequenceAndChain(pe, seq, null);
1330 private void addSequenceAndChain(int pe, SequenceI[] seq, String[] tchain)
1332 if (pe < 0 || pe >= pdbentry.length)
1335 "Implementation error - no corresponding pdbentry (for index "
1336 + pe + ") to add sequences mappings to");
1338 final String nullChain = "TheNullChain";
1339 Vector s = new Vector();
1340 Vector c = new Vector();
1343 chains = new String[pdbentry.length][];
1345 if (sequence[pe] != null)
1347 for (int i = 0; i < sequence[pe].length; i++)
1349 s.addElement(sequence[pe][i]);
1350 if (chains[pe] != null)
1352 if (i < chains[pe].length)
1354 c.addElement(chains[pe][i]);
1358 c.addElement(nullChain);
1363 if (tchain != null && tchain.length > 0)
1365 c.addElement(nullChain);
1370 for (int i = 0; i < seq.length; i++)
1372 if (!s.contains(seq[i]))
1374 s.addElement(seq[i]);
1375 if (tchain != null && i < tchain.length)
1377 c.addElement(tchain[i] == null ? nullChain : tchain[i]);
1381 SequenceI[] tmp = new SequenceI[s.size()];
1386 String[] tch = new String[c.size()];
1388 for (int i = 0; i < tch.length; i++)
1390 if (tch[i] == nullChain)