2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5.1)
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.appletgui;
22 import java.awt.event.*;
24 import jalview.datamodel.*;
25 import jalview.structure.*;
28 import org.jmol.api.*;
29 import org.jmol.adapter.smarter.SmarterJmolAdapter;
31 import org.jmol.popup.*;
32 import jalview.schemes.*;
34 public class AppletJmol extends EmbmenuFrame implements StructureListener,
35 JmolStatusListener, KeyListener, ActionListener, ItemListener
38 Menu fileMenu = new Menu("File");
40 Menu viewMenu = new Menu("View");
42 Menu coloursMenu = new Menu("Colours");
44 Menu chainMenu = new Menu("Show Chain");
46 Menu helpMenu = new Menu("Help");
48 MenuItem mappingMenuItem = new MenuItem("View Mapping");
50 CheckboxMenuItem seqColour = new CheckboxMenuItem("By Sequence", true);
52 MenuItem chain = new MenuItem("By Chain");
54 MenuItem charge = new MenuItem("Charge & Cysteine");
56 MenuItem zappo = new MenuItem("Zappo");
58 MenuItem taylor = new MenuItem("Taylor");
60 MenuItem hydro = new MenuItem("Hydrophobicity");
62 MenuItem helix = new MenuItem("Helix Propensity");
64 MenuItem strand = new MenuItem("Strand Propensity");
66 MenuItem turn = new MenuItem("Turn Propensity");
68 MenuItem buried = new MenuItem("Buried Index");
70 MenuItem user = new MenuItem("User Defined Colours");
72 MenuItem jmolHelp = new MenuItem("Jmol Help");
88 StructureSelectionManager ssm;
90 RenderPanel renderPanel;
94 String fileLoadingError;
100 boolean colourBySequence = true;
102 Vector atomsPicked = new Vector();
105 * datasource protocol for access to PDBEntry
107 String protocol = null;
109 public AppletJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
110 AlignmentPanel ap, String protocol)
114 this.chains = chains;
115 this.pdbentry = pdbentry;
116 this.protocol = protocol;
117 if (pdbentry.getId() == null || pdbentry.getId().length() < 1)
119 if (protocol.equals(AppletFormatAdapter.PASTE))
121 pdbentry.setId("PASTED PDB"
122 + (chains == null ? "_" : chains.toString()));
126 pdbentry.setId(pdbentry.getFile());
130 if (jalview.bin.JalviewLite.debug)
133 .println("AppletJmol: PDB ID is '" + pdbentry.getId() + "'");
136 String alreadyMapped = StructureSelectionManager
137 .getStructureSelectionManager().alreadyMappedToFile(
139 MCview.PDBfile reader = null;
140 if (alreadyMapped != null)
142 reader = StructureSelectionManager.getStructureSelectionManager()
143 .setMapping(seq, chains, pdbentry.getFile(), protocol);
144 // PROMPT USER HERE TO ADD TO NEW OR EXISTING VIEW?
145 // FOR NOW, LETS JUST OPEN A NEW WINDOW
147 MenuBar menuBar = new MenuBar();
148 menuBar.add(fileMenu);
149 fileMenu.add(mappingMenuItem);
150 menuBar.add(viewMenu);
151 mappingMenuItem.addActionListener(this);
152 viewMenu.add(chainMenu);
153 menuBar.add(coloursMenu);
154 menuBar.add(helpMenu);
156 charge.addActionListener(this);
157 hydro.addActionListener(this);
158 chain.addActionListener(this);
159 seqColour.addItemListener(this);
160 zappo.addActionListener(this);
161 taylor.addActionListener(this);
162 helix.addActionListener(this);
163 strand.addActionListener(this);
164 turn.addActionListener(this);
165 buried.addActionListener(this);
166 user.addActionListener(this);
168 jmolHelp.addActionListener(this);
170 coloursMenu.add(seqColour);
171 coloursMenu.add(chain);
172 coloursMenu.add(charge);
173 coloursMenu.add(zappo);
174 coloursMenu.add(taylor);
175 coloursMenu.add(hydro);
176 coloursMenu.add(helix);
177 coloursMenu.add(strand);
178 coloursMenu.add(turn);
179 coloursMenu.add(buried);
180 coloursMenu.add(user);
182 helpMenu.add(jmolHelp);
186 renderPanel = new RenderPanel();
187 embedMenuIfNeeded(renderPanel);
188 this.add(renderPanel, BorderLayout.CENTER);
189 viewer = JmolViewer.allocateViewer(renderPanel,
190 new SmarterJmolAdapter());
192 viewer.setAppletContext("jalview", ap.av.applet.getDocumentBase(),
193 ap.av.applet.getCodeBase(), null);
195 viewer.setJmolStatusListener(this);
197 jmolpopup = JmolPopup.newJmolPopup(viewer);
199 this.addWindowListener(new WindowAdapter()
201 public void windowClosing(WindowEvent evt)
207 if (pdbentry.getFile() != null)
209 // import structure data from pdbentry.getFile based on given protocol
210 if (protocol.equals(AppletFormatAdapter.PASTE))
212 loadInline(pdbentry.getFile());
214 else if (protocol.equals(AppletFormatAdapter.FILE)
215 || protocol.equals(AppletFormatAdapter.URL))
217 viewer.openFile(pdbentry.getFile());
221 // probably CLASSLOADER based datasource..
222 // Try and get a reader on the datasource, and pass that to Jmol
225 java.io.Reader freader = null;
228 if (jalview.bin.JalviewLite.debug)
231 .println("AppletJmol:Trying to reuse existing PDBfile IO parser.");
233 // re-use the one we opened earlier
234 freader = reader.getReader();
238 if (jalview.bin.JalviewLite.debug)
241 .println("AppletJmol:Creating new PDBfile IO parser.");
243 FileParse fp = new FileParse(pdbentry.getFile(), protocol);
245 // reader = new MCview.PDBfile(fp);
246 // could set ID, etc.
247 // if (!reader.isValid())
249 // throw new Exception("Invalid datasource.
250 // "+reader.getWarningMessage());
253 freader = fp.getReader();
258 "Invalid datasource. Could not obtain Reader.");
260 viewer.openReader(pdbentry.getFile(), pdbentry.getId(), freader);
261 } catch (Exception e)
264 System.err.println("Couldn't access pdbentry id="
265 + pdbentry.getId() + " and file=" + pdbentry.getFile()
266 + " using protocol=" + protocol);
272 jalview.bin.JalviewLite.addFrame(this, "Jmol", 400, 400);
275 public void loadInline(String string)
278 viewer.openStringInline(string);
281 void setChainMenuItems(Vector chains)
283 chainMenu.removeAll();
285 MenuItem menuItem = new MenuItem("All");
286 menuItem.addActionListener(this);
288 chainMenu.add(menuItem);
290 CheckboxMenuItem menuItemCB;
291 for (int c = 0; c < chains.size(); c++)
293 menuItemCB = new CheckboxMenuItem(chains.elementAt(c).toString(),
295 menuItemCB.addItemListener(this);
296 chainMenu.add(menuItemCB);
300 boolean allChainsSelected = false;
304 StringBuffer cmd = new StringBuffer();
305 for (int i = 0; i < chainMenu.getItemCount(); i++)
307 if (chainMenu.getItem(i) instanceof CheckboxMenuItem)
309 CheckboxMenuItem item = (CheckboxMenuItem) chainMenu.getItem(i);
311 cmd.append(":" + item.getLabel() + " or ");
315 if (cmd.length() > 0)
316 cmd.setLength(cmd.length() - 4);
319 .evalString("select *;restrict " + cmd + ";cartoon;center "
325 viewer.setModeMouse(org.jmol.viewer.JmolConstants.MOUSE_NONE);
326 viewer.evalStringQuiet("zap");
327 viewer.setJmolStatusListener(null);
330 // We'll need to find out what other
331 // listeners need to be shut down in Jmol
332 StructureSelectionManager.getStructureSelectionManager()
333 .removeStructureViewerListener(this, pdbentry.getId());
335 this.setVisible(false);
338 public void actionPerformed(ActionEvent evt)
340 if (evt.getSource() == mappingMenuItem)
342 jalview.appletgui.CutAndPasteTransfer cap = new jalview.appletgui.CutAndPasteTransfer(
344 Frame frame = new Frame();
347 jalview.bin.JalviewLite.addFrame(frame, "PDB - Sequence Mapping",
349 cap.setText(StructureSelectionManager.getStructureSelectionManager()
350 .printMapping(pdbentry.getFile()));
352 else if (evt.getSource() == charge)
354 colourBySequence = false;
355 seqColour.setState(false);
357 .evalStringQuiet("select *;color white;select ASP,GLU;color red;"
358 + "select LYS,ARG;color blue;select CYS;color yellow");
361 else if (evt.getSource() == chain)
363 colourBySequence = false;
364 seqColour.setState(false);
365 viewer.evalStringQuiet("select *;color chain");
367 else if (evt.getSource() == zappo)
369 setJalviewColourScheme(new ZappoColourScheme());
371 else if (evt.getSource() == taylor)
373 setJalviewColourScheme(new TaylorColourScheme());
375 else if (evt.getSource() == hydro)
377 setJalviewColourScheme(new HydrophobicColourScheme());
379 else if (evt.getSource() == helix)
381 setJalviewColourScheme(new HelixColourScheme());
383 else if (evt.getSource() == strand)
385 setJalviewColourScheme(new StrandColourScheme());
387 else if (evt.getSource() == turn)
389 setJalviewColourScheme(new TurnColourScheme());
391 else if (evt.getSource() == buried)
393 setJalviewColourScheme(new BuriedColourScheme());
395 else if (evt.getSource() == user)
397 new UserDefinedColours(this);
399 else if (evt.getSource() == jmolHelp)
403 ap.av.applet.getAppletContext().showDocument(
405 "http://jmol.sourceforge.net/docs/JmolUserGuide/"),
407 } catch (java.net.MalformedURLException ex)
413 allChainsSelected = true;
414 for (int i = 0; i < chainMenu.getItemCount(); i++)
416 if (chainMenu.getItem(i) instanceof CheckboxMenuItem)
417 ((CheckboxMenuItem) chainMenu.getItem(i)).setState(true);
420 allChainsSelected = false;
424 public void setJalviewColourScheme(ColourSchemeI cs)
426 colourBySequence = false;
427 seqColour.setState(false);
436 Enumeration en = ResidueProperties.aa3Hash.keys();
437 StringBuffer command = new StringBuffer("select *;color white;");
438 while (en.hasMoreElements())
440 res = en.nextElement().toString();
441 index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
445 col = cs.findColour(ResidueProperties.aa[index].charAt(0));
447 command.append("select " + res + ";color[" + col.getRed() + ","
448 + col.getGreen() + "," + col.getBlue() + "];");
451 viewer.evalStringQuiet(command.toString());
454 public void itemStateChanged(ItemEvent evt)
456 if (evt.getSource() == seqColour)
459 colourBySequence = seqColour.getState();
460 colourBySequence(ap);
462 else if (!allChainsSelected)
466 public void keyPressed(KeyEvent evt)
468 if (evt.getKeyCode() == KeyEvent.VK_ENTER && scriptWindow.isVisible())
470 viewer.evalString(inputLine.getText());
471 history.append("\n$ " + inputLine.getText());
472 inputLine.setText("");
477 public void keyTyped(KeyEvent evt)
481 public void keyReleased(KeyEvent evt)
485 // ////////////////////////////////
486 // /StructureListener
487 public String getPdbFile()
494 public void mouseOverStructure(int atomIndex, String strInfo)
498 int chainSeparator = strInfo.indexOf(":");
500 if (chainSeparator == -1)
501 chainSeparator = strInfo.indexOf(".");
503 pdbResNum = Integer.parseInt(strInfo.substring(
504 strInfo.indexOf("]") + 1, chainSeparator));
508 if (strInfo.indexOf(":") > -1)
509 chainId = strInfo.substring(strInfo.indexOf(":") + 1, strInfo
516 if (lastMessage == null || !lastMessage.equals(strInfo))
517 ssm.mouseOverStructure(pdbResNum, chainId, pdbentry.getFile());
519 lastMessage = strInfo;
522 StringBuffer resetLastRes = new StringBuffer();
524 StringBuffer eval = new StringBuffer();
526 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
529 if (!pdbfile.equals(pdbentry.getFile()))
532 if (resetLastRes.length() > 0)
534 viewer.evalStringQuiet(resetLastRes.toString());
538 eval.append("select " + pdbResNum);
540 resetLastRes.setLength(0);
541 resetLastRes.append("select " + pdbResNum);
544 resetLastRes.append(":");
545 if (!chain.equals(" "))
548 resetLastRes.append(chain);
551 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;");
553 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
554 + " and not hetero; spacefill 0;");
556 eval.append("spacefill 200;select none");
558 viewer.evalStringQuiet(eval.toString());
562 public void updateColours(Object source)
564 colourBySequence((AlignmentPanel) source);
567 // End StructureListener
568 // //////////////////////////
570 public Color getColour(int atomIndex, int pdbResNum, String chain,
573 if (!pdbfile.equals(pdbentry.getFile()))
576 return new Color(viewer.getAtomArgb(atomIndex));
581 FeatureRenderer fr = null;
583 public void colourBySequence(AlignmentPanel sourceap)
587 if (!colourBySequence)
590 StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile());
592 if (mapping.length < 1)
595 SequenceRenderer sr = new SequenceRenderer(ap.av);
597 boolean showFeatures = false;
599 if (ap.av.showSequenceFeatures)
604 fr = new jalview.appletgui.FeatureRenderer(ap.av);
607 fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
610 StringBuffer command = new StringBuffer();
613 for (int s = 0; s < sequence.length; s++)
615 for (int sp, m = 0; m < mapping.length; m++)
617 if (mapping[m].getSequence() == sequence[s]
618 && (sp = ap.av.alignment.findIndex(sequence[s])) > -1)
620 SequenceI asp = ap.av.alignment.getSequenceAt(sp);
621 for (int r = 0; r < asp.getLength(); r++)
623 // no mapping to gaps in sequence
624 if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
628 int pos = mapping[m].getPDBResNum(asp.findPosition(r));
630 if (pos < 1 || pos == lastPos)
635 Color col = sr.getResidueBoxColour(sequence[s], r);
638 col = fr.findFeatureColour(col, sequence[s], r);
640 if (command.toString().endsWith(
641 ":" + mapping[m].getChain() + ";color[" + col.getRed()
642 + "," + col.getGreen() + "," + col.getBlue()
645 command = condenseCommand(command.toString(), pos);
649 command.append(";select " + pos);
651 if (!mapping[m].getChain().equals(" "))
653 command.append(":" + mapping[m].getChain());
656 command.append(";color[" + col.getRed() + "," + col.getGreen()
657 + "," + col.getBlue() + "]");
664 if (lastCommand == null || !lastCommand.equals(command.toString()))
666 viewer.evalStringQuiet(command.toString());
668 lastCommand = command.toString();
671 StringBuffer condenseCommand(String command, int pos)
674 StringBuffer sb = new StringBuffer(command.substring(0, command
675 .lastIndexOf("select") + 7));
677 command = command.substring(sb.length());
681 if (command.indexOf("-") > -1)
683 start = command.substring(0, command.indexOf("-"));
687 start = command.substring(0, command.indexOf(":"));
690 sb.append(start + "-" + pos + command.substring(command.indexOf(":")));
695 // ///////////////////////////////
696 // JmolStatusListener
698 public String eval(String strEval)
700 // System.out.println(strEval);
701 // "# 'eval' is implemented only for the applet.";
705 public void createImage(String file, String type, int quality)
709 public void setCallbackFunction(String callbackType,
710 String callbackFunction)
714 public void notifyFileLoaded(String fullPathName, String fileName,
715 String modelName, Object clientFile, String errorMsg)
717 if (errorMsg != null)
719 fileLoadingError = errorMsg;
724 fileLoadingError = null;
726 if (fileName != null)
729 jmolpopup.updateComputedMenus();
731 .evalStringQuiet("select backbone;restrict;cartoon;wireframe off;spacefill off");
733 ssm = StructureSelectionManager.getStructureSelectionManager();
737 pdb = ssm.setMapping(sequence, chains, pdbentry.getFile(),
738 AppletFormatAdapter.PASTE);
739 pdbentry.setFile("INLINE" + pdb.id);
743 // TODO: Jmol can in principle retrieve from CLASSLOADER but this needs
744 // to be tested. See mantis bug
745 // https://mantis.lifesci.dundee.ac.uk/view.php?id=36605
747 pdb = ssm.setMapping(sequence, chains, pdbentry.getFile(),
748 AppletFormatAdapter.URL);
752 pdbentry.setId(pdb.id);
754 ssm.addStructureViewerListener(this);
756 Vector chains = new Vector();
757 for (int i = 0; i < pdb.chains.size(); i++)
759 chains.addElement(((MCview.PDBChain) pdb.chains.elementAt(i)).id);
761 setChainMenuItems(chains);
763 colourBySequence(ap);
765 StringBuffer title = new StringBuffer(sequence[0].getName() + ":"
768 if (pdbentry.getProperty() != null)
770 if (pdbentry.getProperty().get("method") != null)
772 title.append(" Method: ");
773 title.append(pdbentry.getProperty().get("method"));
775 if (pdbentry.getProperty().get("chains") != null)
777 title.append(" Chain:");
778 title.append(pdbentry.getProperty().get("chains"));
782 this.setTitle(title.toString());
789 public void notifyFrameChanged(int frameNo)
791 boolean isAnimationRunning = (frameNo <= -2);
794 public void notifyScriptStart(String statusMessage, String additionalInfo)
798 public void sendConsoleEcho(String strEcho)
800 if (scriptWindow == null)
803 history.append("\n" + strEcho);
806 public void sendConsoleMessage(String strStatus)
808 if (history != null && strStatus != null
809 && !strStatus.equals("Script completed"))
811 history.append("\n" + strStatus);
815 public void notifyScriptTermination(String strStatus, int msWalltime)
819 public void handlePopupMenu(int x, int y)
821 jmolpopup.show(x, y);
824 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
826 notifyAtomPicked(iatom, strMeasure);
829 public void notifyNewDefaultModeMeasurement(int count, String strInfo)
833 public void notifyAtomPicked(int atomIndex, String strInfo)
836 int chainSeparator = strInfo.indexOf(":");
838 if (chainSeparator == -1)
839 chainSeparator = strInfo.indexOf(".");
841 String picked = strInfo.substring(strInfo.indexOf("]") + 1,
844 if (strInfo.indexOf(":") > -1)
845 picked += strInfo.substring(strInfo.indexOf(":") + 1, strInfo
850 if (!atomsPicked.contains(picked))
852 viewer.evalString("select " + picked + ";label %n %r:%c");
853 atomsPicked.addElement(picked);
857 viewer.evalString("select " + picked + ";label off");
858 atomsPicked.removeElement(picked);
862 public void notifyAtomHovered(int atomIndex, String strInfo)
864 mouseOverStructure(atomIndex, strInfo);
867 public void sendSyncScript(String script, String appletName)
871 public void showUrl(String url)
875 ap.av.applet.getAppletContext().showDocument(new java.net.URL(url),
877 } catch (java.net.MalformedURLException ex)
882 public void showConsole(boolean showConsole)
884 if (scriptWindow == null)
886 scriptWindow = new Panel(new BorderLayout());
887 inputLine = new TextField();
888 history = new TextArea(5, 40);
889 scriptWindow.add(history, BorderLayout.CENTER);
890 scriptWindow.add(inputLine, BorderLayout.SOUTH);
891 add(scriptWindow, BorderLayout.SOUTH);
892 scriptWindow.setVisible(false);
893 history.setEditable(false);
894 inputLine.addKeyListener(this);
897 scriptWindow.setVisible(!scriptWindow.isVisible());
901 public float functionXY(String functionName, int x, int y)
906 // /End JmolStatusListener
907 // /////////////////////////////
909 class RenderPanel extends Panel
911 Dimension currentSize = new Dimension();
913 Rectangle rectClip = new Rectangle();
915 public void update(Graphics g)
920 public void paint(Graphics g)
922 currentSize = this.getSize();
923 rectClip = g.getClipBounds();
927 g.setColor(Color.black);
928 g.fillRect(0, 0, currentSize.width, currentSize.height);
929 g.setColor(Color.white);
930 g.setFont(new Font("Verdana", Font.BOLD, 14));
931 g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
935 viewer.renderScreenImage(g, currentSize, rectClip);