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/>.
20 import java.util.regex.*;
24 import javax.swing.event.*;
25 import java.awt.event.*;
28 import jalview.jbgui.GStructureViewer;
29 import jalview.datamodel.*;
31 import jalview.structure.*;
32 import jalview.datamodel.PDBEntry;
34 import jalview.schemes.*;
35 import jalview.ws.ebi.EBIFetchClient;
37 import org.jmol.api.*;
38 import org.jmol.adapter.smarter.SmarterJmolAdapter;
39 import org.jmol.popup.*;
41 public class AppJmol extends GStructureViewer implements StructureListener,
42 JmolStatusListener, Runnable
49 ScriptWindow scriptWindow;
57 StructureSelectionManager ssm;
61 RenderPanel renderPanel;
65 String fileLoadingError;
67 boolean colourBySequence = true;
69 boolean loadingFromArchive = false;
71 Vector atomsPicked = new Vector();
73 public AppJmol(String file, String id, SequenceI[] seq,
74 AlignmentPanel ap, String loadStatus, Rectangle bounds)
76 this(file, id, seq, ap, loadStatus, bounds, null);
79 public AppJmol(String file, String id, SequenceI[] seq,
80 AlignmentPanel ap, String loadStatus, Rectangle bounds,
83 loadingFromArchive = true;
84 pdbentry = new PDBEntry();
85 pdbentry.setFile(file);
90 this.setBounds(bounds);
91 colourBySequence = false;
92 seqColour.setSelected(false);
94 // jalview.gui.Desktop.addInternalFrame(this, "Loading File",
95 // bounds.width,bounds.height);
99 this.addInternalFrameListener(new InternalFrameAdapter()
101 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
108 public synchronized void addSequence(SequenceI[] seq)
110 Vector v = new Vector();
111 for (int i = 0; i < sequence.length; i++)
112 v.addElement(sequence[i]);
114 for (int i = 0; i < seq.length; i++)
115 if (!v.contains(seq[i]))
116 v.addElement(seq[i]);
118 SequenceI[] tmp = new SequenceI[v.size()];
123 public AppJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
126 // ////////////////////////////////
127 // Is the pdb file already loaded?
128 String alreadyMapped = StructureSelectionManager
129 .getStructureSelectionManager().alreadyMappedToFile(
132 if (alreadyMapped != null)
134 int option = JOptionPane
135 .showInternalConfirmDialog(
138 + " is already displayed."
139 + "\nDo you want to map sequences to the visible structure?",
140 "Map Sequences to Visible Window: "
141 + pdbentry.getId(), JOptionPane.YES_NO_OPTION);
143 if (option == JOptionPane.YES_OPTION)
145 StructureSelectionManager.getStructureSelectionManager()
146 .setMapping(seq, chains, alreadyMapped,
147 AppletFormatAdapter.FILE);
148 if (ap.seqPanel.seqCanvas.fr != null)
150 ap.seqPanel.seqCanvas.fr.featuresAdded();
151 ap.paintAlignment(true);
154 // Now this AppJmol is mapped to new sequences. We must add them to
155 // the exisiting array
156 JInternalFrame[] frames = Desktop.instance.getAllFrames();
158 for (int i = 0; i < frames.length; i++)
160 if (frames[i] instanceof AppJmol)
162 AppJmol topJmol = ((AppJmol) frames[i]);
163 if (topJmol.pdbentry.getFile().equals(alreadyMapped))
165 topJmol.addSequence(seq);
174 // /////////////////////////////////
177 this.pdbentry = pdbentry;
179 this.setSize(400, 400);
180 // jalview.gui.Desktop.addInternalFrame(this, "Jmol
181 // View"+(pdbentry.getId()!=null ? "for "+pdbentry.getId()
184 if (pdbentry.getFile() != null)
186 initJmol("load \"" + pdbentry.getFile() + "\"");
190 Thread worker = new Thread(this);
194 this.addInternalFrameListener(new InternalFrameAdapter()
196 public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
203 void initJmol(String command)
205 renderPanel = new RenderPanel();
207 this.getContentPane().add(renderPanel, java.awt.BorderLayout.CENTER);
209 StringBuffer title = new StringBuffer(sequence[0].getName() + ":"
212 if (pdbentry.getProperty() != null)
214 if (pdbentry.getProperty().get("method") != null)
216 title.append(" Method: ");
217 title.append(pdbentry.getProperty().get("method"));
219 if (pdbentry.getProperty().get("chains") != null)
221 title.append(" Chain:");
222 title.append(pdbentry.getProperty().get("chains"));
226 this.setTitle(title.toString());
227 jalview.gui.Desktop.addInternalFrame(this, title.toString(),
228 getBounds().width, getBounds().height);
230 viewer = org.jmol.api.JmolViewer.allocateViewer(renderPanel,
231 new SmarterJmolAdapter());
233 viewer.setAppletContext("", null, null, "");
235 viewer.setJmolStatusListener(this);
237 jmolpopup = JmolPopup.newJmolPopup(viewer);
239 viewer.evalStringQuiet(command);
242 void setChainMenuItems(Vector chains)
244 chainMenu.removeAll();
246 JMenuItem menuItem = new JMenuItem("All");
247 menuItem.addActionListener(new ActionListener()
249 public void actionPerformed(ActionEvent evt)
251 allChainsSelected = true;
252 for (int i = 0; i < chainMenu.getItemCount(); i++)
254 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
255 ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
258 allChainsSelected = false;
262 chainMenu.add(menuItem);
264 for (int c = 0; c < chains.size(); c++)
266 menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true);
267 menuItem.addItemListener(new ItemListener()
269 public void itemStateChanged(ItemEvent evt)
271 if (!allChainsSelected)
276 chainMenu.add(menuItem);
280 boolean allChainsSelected = false;
284 StringBuffer cmd = new StringBuffer();
285 for (int i = 0; i < chainMenu.getItemCount(); i++)
287 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
289 JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
290 if (item.isSelected())
291 cmd.append(":" + item.getText() + " or ");
295 if (cmd.length() > 0)
296 cmd.setLength(cmd.length() - 4);
298 viewer.evalStringQuiet("select *;restrict " + cmd + ";cartoon;center "
304 viewer.setModeMouse(org.jmol.viewer.JmolConstants.MOUSE_NONE);
305 viewer.evalStringQuiet("zap");
306 viewer.setJmolStatusListener(null);
309 // We'll need to find out what other
310 // listeners need to be shut down in Jmol
311 StructureSelectionManager.getStructureSelectionManager()
312 .removeStructureViewerListener(this, pdbentry.getFile());
319 // TODO: replace with reference fetching/transfer code (validate PDBentry
321 jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb();
323 if ((pdbseq = pdbclient.getSequenceRecords(pdbentry.getId())) != null)
325 // just transfer the file name from the first seuqence's first PDBEntry
326 pdbentry.setFile(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId()
327 .elementAt(0)).getFile());
328 initJmol("load " + pdbentry.getFile());
333 .showInternalMessageDialog(
336 + " could not be retrieved. Please try downloading the file manually.",
337 "Couldn't load file", JOptionPane.ERROR_MESSAGE);
340 } catch (OutOfMemoryError oomerror)
342 new OOMWarning("Retrieving PDB id " + pdbentry.getId() + " from MSD",
344 } catch (Exception ex)
346 ex.printStackTrace();
350 public void pdbFile_actionPerformed(ActionEvent actionEvent)
352 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
353 .getProperty("LAST_DIRECTORY"));
355 chooser.setFileView(new JalviewFileView());
356 chooser.setDialogTitle("Save PDB File");
357 chooser.setToolTipText("Save");
359 int value = chooser.showSaveDialog(this);
361 if (value == JalviewFileChooser.APPROVE_OPTION)
365 BufferedReader in = new BufferedReader(new FileReader(pdbentry
367 File outFile = chooser.getSelectedFile();
369 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
371 while ((data = in.readLine()) != null)
373 if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
379 } catch (Exception ex)
381 ex.printStackTrace();
386 public void viewMapping_actionPerformed(ActionEvent actionEvent)
388 jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
389 jalview.gui.Desktop.addInternalFrame(cap, "PDB - Sequence Mapping",
391 cap.setText(StructureSelectionManager.getStructureSelectionManager()
392 .printMapping(pdbentry.getFile()));
401 public void eps_actionPerformed(ActionEvent e)
403 makePDBImage(jalview.util.ImageMaker.EPS);
412 public void png_actionPerformed(ActionEvent e)
414 makePDBImage(jalview.util.ImageMaker.PNG);
417 void makePDBImage(int type)
419 int width = getWidth();
420 int height = getHeight();
422 jalview.util.ImageMaker im;
424 if (type == jalview.util.ImageMaker.PNG)
426 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
427 "Make PNG image from view", width, height, null, null);
431 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
432 "Make EPS file from view", width, height, null, this
436 if (im.getGraphics() != null)
438 Rectangle rect = new Rectangle(width, height);
439 viewer.renderScreenImage(im.getGraphics(), rect.getSize(), rect);
444 public void seqColour_actionPerformed(ActionEvent actionEvent)
447 colourBySequence = seqColour.isSelected();
448 colourBySequence(ap.alignFrame.alignPanel);
451 public void chainColour_actionPerformed(ActionEvent actionEvent)
453 colourBySequence = false;
454 seqColour.setSelected(false);
455 viewer.evalStringQuiet("select *;color chain");
458 public void chargeColour_actionPerformed(ActionEvent actionEvent)
460 colourBySequence = false;
461 seqColour.setSelected(false);
462 viewer.evalStringQuiet("select *;color white;select ASP,GLU;color red;"
463 + "select LYS,ARG;color blue;select CYS;color yellow");
466 public void zappoColour_actionPerformed(ActionEvent actionEvent)
468 setJalviewColourScheme(new ZappoColourScheme());
471 public void taylorColour_actionPerformed(ActionEvent actionEvent)
473 setJalviewColourScheme(new TaylorColourScheme());
476 public void hydroColour_actionPerformed(ActionEvent actionEvent)
478 setJalviewColourScheme(new HydrophobicColourScheme());
481 public void helixColour_actionPerformed(ActionEvent actionEvent)
483 setJalviewColourScheme(new HelixColourScheme());
486 public void strandColour_actionPerformed(ActionEvent actionEvent)
488 setJalviewColourScheme(new StrandColourScheme());
491 public void turnColour_actionPerformed(ActionEvent actionEvent)
493 setJalviewColourScheme(new TurnColourScheme());
496 public void buriedColour_actionPerformed(ActionEvent actionEvent)
498 setJalviewColourScheme(new BuriedColourScheme());
501 public void setJalviewColourScheme(ColourSchemeI cs)
503 colourBySequence = false;
504 seqColour.setSelected(false);
513 Enumeration en = ResidueProperties.aa3Hash.keys();
514 StringBuffer command = new StringBuffer("select *;color white;");
515 while (en.hasMoreElements())
517 res = en.nextElement().toString();
518 index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
522 col = cs.findColour(ResidueProperties.aa[index].charAt(0));
524 command.append("select " + res + ";color[" + col.getRed() + ","
525 + col.getGreen() + "," + col.getBlue() + "];");
528 viewer.evalStringQuiet(command.toString());
531 public void userColour_actionPerformed(ActionEvent actionEvent)
533 new UserDefinedColours(this, null);
536 public void backGround_actionPerformed(ActionEvent actionEvent)
538 java.awt.Color col = JColorChooser.showDialog(this,
539 "Select Background Colour", null);
543 viewer.evalStringQuiet("background [" + col.getRed() + ","
544 + col.getGreen() + "," + col.getBlue() + "];");
548 public void jmolHelp_actionPerformed(ActionEvent actionEvent)
552 jalview.util.BrowserLauncher
553 .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/");
554 } catch (Exception ex)
559 // ////////////////////////////////
560 // /StructureListener
561 public String getPdbFile()
563 return pdbentry.getFile();
566 Pattern pattern = Pattern
567 .compile("\\[(.*)\\]([0-9]+)(:[a-zA-Z]*)?\\.([a-zA-Z]+)(/[0-9]*)?");
571 public void mouseOverStructure(int atomIndex, String strInfo)
573 Matcher matcher = pattern.matcher(strInfo);
576 int pdbResNum = Integer.parseInt(matcher.group(2));
577 String chainId = matcher.group(3);
580 chainId = chainId.substring(1, chainId.length());
586 if (lastMessage == null || !lastMessage.equals(strInfo))
588 ssm.mouseOverStructure(pdbResNum, chainId, pdbentry.getFile());
590 lastMessage = strInfo;
593 StringBuffer resetLastRes = new StringBuffer();
595 StringBuffer eval = new StringBuffer();
597 public void highlightAtom(int atomIndex, int pdbResNum, String chain,
600 // TODO: rna: remove CA dependency in select string
601 if (!pdbfile.equals(pdbentry.getFile()))
604 if (resetLastRes.length() > 0)
606 viewer.evalStringQuiet(resetLastRes.toString());
610 eval.append("select " + pdbResNum);
612 resetLastRes.setLength(0);
613 resetLastRes.append("select " + pdbResNum);
616 resetLastRes.append(":");
617 if (!chain.equals(" "))
620 resetLastRes.append(chain);
623 eval.append(";wireframe 100;" + eval.toString() + " and not hetero;"); // ".*;");
625 resetLastRes.append(";wireframe 0;" + resetLastRes.toString()
626 // + ".*;spacefill 0;");
627 + " and not hetero;spacefill 0;");
629 eval.append("spacefill 200;select none");
630 // System.out.println("jmol:\n"+eval+"\n");
631 viewer.evalStringQuiet(eval.toString());
634 public Color getColour(int atomIndex, int pdbResNum, String chain,
637 if (!pdbfile.equals(pdbentry.getFile()))
640 return new Color(viewer.getAtomArgb(atomIndex));
643 public void updateColours(Object source)
645 colourBySequence((AlignmentPanel) source);
648 // End StructureListener
649 // //////////////////////////
653 FeatureRenderer fr = null;
655 public void colourBySequence(AlignmentPanel sourceap)
659 if (!colourBySequence || ap.alignFrame.getCurrentView() != ap.av)
662 StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile());
664 if (mapping.length < 1)
667 SequenceRenderer sr = new SequenceRenderer(ap.av);
669 boolean showFeatures = false;
671 if (ap.av.showSequenceFeatures)
676 fr = new jalview.gui.FeatureRenderer(ap);
679 fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
682 StringBuffer command = new StringBuffer();
685 for (int sp, s = 0; s < sequence.length; s++)
687 for (int m = 0; m < mapping.length; m++)
689 if (mapping[m].getSequence() == sequence[s]
690 && (sp = ap.av.alignment.findIndex(sequence[s])) > -1)
692 SequenceI asp = ap.av.alignment.getSequenceAt(sp);
693 for (int r = 0; r < asp.getLength(); r++)
695 // No mapping to gaps in sequence.
696 if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
700 int pos = mapping[m].getPDBResNum(asp.findPosition(r));
702 if (pos < 1 || pos == lastPos)
707 Color col = sr.getResidueBoxColour(asp, r);
710 col = fr.findFeatureColour(col, asp, r);
712 if (command.toString().endsWith(
713 ":" + mapping[m].getChain() + ";color[" + col.getRed()
714 + "," + col.getGreen() + "," + col.getBlue()
717 command = condenseCommand(command, pos);
721 command.append(";select " + pos);
723 if (!mapping[m].getChain().equals(" "))
725 command.append(":" + mapping[m].getChain());
728 command.append(";color[" + col.getRed() + "," + col.getGreen()
729 + "," + col.getBlue() + "]");
737 if (lastCommand == null || !lastCommand.equals(command.toString()))
739 viewer.evalStringQuiet(command.toString());
741 lastCommand = command.toString();
744 StringBuffer condenseCommand(StringBuffer command, int pos)
746 StringBuffer sb = new StringBuffer(command.substring(0, command
747 .lastIndexOf("select") + 7));
749 command.delete(0, sb.length());
753 if (command.indexOf("-") > -1)
755 start = command.substring(0, command.indexOf("-"));
759 start = command.substring(0, command.indexOf(":"));
762 sb.append(start + "-" + pos + command.substring(command.indexOf(":")));
767 // ///////////////////////////////
768 // JmolStatusListener
770 public String eval(String strEval)
772 // System.out.println(strEval);
773 // "# 'eval' is implemented only for the applet.";
777 public void createImage(String file, String type, int quality)
779 System.out.println("JMOL CREATE IMAGE");
782 public void setCallbackFunction(String callbackType,
783 String callbackFunction)
787 public void notifyFileLoaded(String fullPathName, String fileName,
788 String modelName, Object clientFile, String errorMsg)
790 if (errorMsg != null)
792 fileLoadingError = errorMsg;
797 fileLoadingError = null;
799 if (fileName != null)
803 ssm = StructureSelectionManager.getStructureSelectionManager();
804 MCview.PDBfile pdbFile = ssm.setMapping(sequence, chains, pdbentry
805 .getFile(), AppletFormatAdapter.FILE);
806 ssm.addStructureViewerListener(this);
807 Vector chains = new Vector();
808 for (int i = 0; i < pdbFile.chains.size(); i++)
811 .addElement(((MCview.PDBChain) pdbFile.chains.elementAt(i)).id);
813 setChainMenuItems(chains);
815 jmolpopup.updateComputedMenus();
817 if (!loadingFromArchive)
820 .evalStringQuiet("select backbone;restrict;cartoon;wireframe off;spacefill off");
822 colourBySequence(ap);
827 loadingFromArchive = false;
833 public void notifyFrameChanged(int frameNo)
835 boolean isAnimationRunning = (frameNo <= -2);
838 public void notifyScriptStart(String statusMessage, String additionalInfo)
842 public void sendConsoleEcho(String strEcho)
844 if (scriptWindow != null)
845 scriptWindow.sendConsoleEcho(strEcho);
848 public void sendConsoleMessage(String strStatus)
850 if (scriptWindow != null)
851 scriptWindow.sendConsoleMessage(strStatus);
854 public void notifyScriptTermination(String strStatus, int msWalltime)
856 if (scriptWindow != null)
857 scriptWindow.notifyScriptTermination(strStatus, msWalltime);
860 public void handlePopupMenu(int x, int y)
862 jmolpopup.show(x, y);
865 public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
867 notifyAtomPicked(iatom, strMeasure);
870 public void notifyNewDefaultModeMeasurement(int count, String strInfo)
874 public void notifyAtomPicked(int atomIndex, String strInfo)
876 Matcher matcher = pattern.matcher(strInfo);
880 String resnum = new String(matcher.group(2));
881 String chainId = matcher.group(3);
883 String picked = resnum;
886 picked += (":" + chainId.substring(1, chainId.length()));
890 if (!atomsPicked.contains(picked))
893 viewer.evalString("select " + picked + ";label %n %r:%c");
895 viewer.evalString("select " + picked + ";label %n %r");
896 atomsPicked.addElement(picked);
900 viewer.evalString("select " + picked + ";label off");
901 atomsPicked.removeElement(picked);
904 if (scriptWindow != null)
906 scriptWindow.sendConsoleMessage(strInfo);
907 scriptWindow.sendConsoleMessage("\n");
911 public void notifyAtomHovered(int atomIndex, String strInfo)
913 mouseOverStructure(atomIndex, strInfo);
916 public void sendSyncScript(String script, String appletName)
920 public void showUrl(String url)
924 public void showConsole(boolean showConsole)
926 if (scriptWindow == null)
927 scriptWindow = new ScriptWindow(this);
931 if (splitPane == null)
933 splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
934 splitPane.setTopComponent(renderPanel);
935 splitPane.setBottomComponent(scriptWindow);
936 this.getContentPane().add(splitPane, BorderLayout.CENTER);
939 splitPane.setDividerLocation(getHeight() - 200);
940 splitPane.validate();
944 if (splitPane != null)
945 splitPane.setVisible(false);
949 this.getContentPane().add(renderPanel, BorderLayout.CENTER);
955 public float functionXY(String functionName, int x, int y)
960 // /End JmolStatusListener
961 // /////////////////////////////
963 class RenderPanel extends JPanel
965 final Dimension currentSize = new Dimension();
967 final Rectangle rectClip = new Rectangle();
969 public void paintComponent(Graphics g)
971 getSize(currentSize);
972 g.getClipBounds(rectClip);
976 g.setColor(Color.black);
977 g.fillRect(0, 0, currentSize.width, currentSize.height);
978 g.setColor(Color.white);
979 g.setFont(new Font("Verdana", Font.BOLD, 14));
980 g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
982 else if (fileLoadingError != null)
984 g.setColor(Color.black);
985 g.fillRect(0, 0, currentSize.width, currentSize.height);
986 g.setColor(Color.white);
987 g.setFont(new Font("Verdana", Font.BOLD, 14));
988 g.drawString("Error loading file..." + pdbentry.getId(), 20,
989 currentSize.height / 2);
993 viewer.renderScreenImage(g, currentSize, rectClip);
998 String viewId = null;
1000 public String getViewId()
1004 viewId = System.currentTimeMillis() + "." + this.hashCode();