001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.gui.jmol;
022
023import java.awt.event.ActionEvent;
024import java.awt.event.ActionListener;
025import java.awt.event.MouseEvent;
026import java.awt.event.MouseListener;
027import java.awt.event.MouseMotionListener;
028import java.awt.event.WindowEvent;
029import java.awt.event.WindowListener;
030import java.util.List;
031
032import javax.swing.JFrame;
033import javax.swing.JTextField;
034
035import org.biojava.nbio.structure.Atom;
036import org.biojava.nbio.structure.Chain;
037import org.biojava.nbio.structure.ChainImpl;
038import org.biojava.nbio.structure.Structure;
039import org.biojava.nbio.structure.StructureImpl;
040import org.biojava.nbio.structure.align.util.ResourceManager;
041import org.biojava.nbio.structure.jama.Matrix;
042import org.jcolorbrewer.ColorBrewer;
043import org.jmol.api.JmolViewer;
044import org.jmol.viewer.Viewer;
045import org.slf4j.Logger;
046import org.slf4j.LoggerFactory;
047
048/**
049 * An Abstract Class to generalize the visualization of AFP and
050 * MultipleAlignment structure alignments in Jmol.
051 *
052 * @author Aleix Lafita
053 *
054 */
055public abstract class AbstractAlignmentJmol
056implements MouseMotionListener, MouseListener, WindowListener, ActionListener {
057
058        private static final Logger logger = LoggerFactory.getLogger(AbstractAlignmentJmol.class);
059        protected Structure structure;
060        protected ColorBrewer colorPalette = ColorBrewer.Spectral;
061
062        protected JmolPanel jmolPanel;
063        protected JFrame frame;
064        protected JTextField text ;
065        protected JTextField status;
066
067        protected static final String COMMAND_LINE_HELP =
068                        "enter Jmol scripting command...";
069
070        protected static final int DEFAULT_HEIGHT = 500;
071        protected static final int DEFAULT_WIDTH = 500;
072        protected static final String DEFAULT_SCRIPT =
073                        ResourceManager.getResourceManager("ce").
074                        getString("default.alignment.jmol.script");
075
076        protected static int nrOpenWindows = 0;
077
078        /**
079         * Display the structures after the variable initialization in the
080         * constructor.
081         */
082        protected abstract void initCoords();
083
084        /**
085         * Set all the member variables to null.
086         */
087        public void destroy(){
088                logger.debug("cleaning up AlignmentJmol window");
089                jmolPanel.removeMouseListener(this);
090                jmolPanel.removeMouseMotionListener(this);
091                jmolPanel.destroy();
092        }
093
094        /**
095         * Return to the initial state of the alignment visualization.
096         */
097        public abstract void resetDisplay();
098
099        /**
100         * Create and set a new structure from a given atom array.
101         * @param atoms
102         */
103        public void setAtoms(Atom[] atoms){
104                Structure s = new StructureImpl();
105                Chain c = new ChainImpl();
106                c.setId("A");
107                for (Atom a: atoms){
108                        c.addGroup(a.getGroup());
109                }
110                s.addChain(c);
111                setStructure(s);
112        }
113
114        /**
115         * Return the color pattelete of the AlignmentJmol instance.
116         */
117        public ColorBrewer getColorPalette() {
118                return colorPalette;
119        }
120
121        /**
122         * Return the jmolPanel instance of the AlignmentJmol.
123         */
124        public JmolPanel getJmolPanel() {
125                return jmolPanel;
126        }
127
128        /**
129         * Set the jmolPanel of the AlignmentJmol instance.
130         * @param jmolPanel
131         */
132        public void setJmolPanel(JmolPanel jmolPanel) {
133                this.jmolPanel = jmolPanel;
134        }
135
136        /**
137         * Execute a command String in the current Jmol panel.
138         * @param rasmolScript
139         */
140        public void evalString(String rasmolScript){
141                if ( jmolPanel == null ){
142                        logger.error("please install Jmol first");
143                        return;
144                }
145                jmolPanel.evalString(rasmolScript);
146        }
147
148        /**
149         * Set a new Structure to visualize in the AlignmentJmol window.
150         * @param s
151         */
152        public void setStructure(Structure s) {
153
154                if (jmolPanel == null){
155                        logger.error("please install Jmol first");
156                        return;
157                }
158                setTitle(s.getPDBCode());
159                jmolPanel.setStructure(s);
160
161                // actually this is very simple
162                // just convert the structure to a PDB file
163
164                //String pdb = s.toPDB();
165                //System.out.println(s.isNmr());
166
167                //System.out.println(pdb);
168                // Jmol could also read the file directly from your file system
169                //viewer.openFile("/Path/To/PDB/1tim.pdb");
170
171                //System.out.println(pdb);
172                //jmolPanel.openStringInline(pdb);
173
174                // send the PDB file to Jmol.
175                // there are also other ways to interact with Jmol,
176                // e.g make it directly
177                // access the biojava structure object, but they require more
178                // code. See the SPICE code repository for how to do this.
179
180                structure = s;
181        }
182
183        /**
184         * Return the current Structure in the AlignmentJmol instance.
185         */
186        public Structure getStructure(){
187                return structure;
188        }
189
190        /**
191         * Returns a List of internal Distance Matrices,
192         * one for each structure in the alignment.
193         * Returns null if no alignment is being displayed.
194         */
195        public abstract List<Matrix> getDistanceMatrices();
196
197        /**
198         * Set the title of the AlignmentJmol window.
199         * @param label
200         */
201        public void setTitle(String title){
202                frame.setTitle(title);
203                frame.repaint();
204        }
205
206        /**
207         * Return the title of the AlignmentJmol window.
208         */
209        public String getTitle(){
210                return frame.getTitle();
211        }
212
213        @Override
214        public void mouseDragged(MouseEvent e) {}
215
216        @Override
217        public void mouseMoved(MouseEvent e) {
218
219                JmolViewer viewer = jmolPanel.getViewer();
220                int pos = viewer.findNearestAtomIndex( e.getX(), e.getY() );
221                if ( pos == -1 ) { return ; }
222
223                String atomInfo = ((Viewer) viewer).getAtomInfo(pos);
224                text.setText(atomInfo);
225
226        }
227
228        @Override
229        public void mouseClicked(MouseEvent e) {}
230
231        @Override
232        public void mouseEntered(MouseEvent e) {}
233
234        @Override
235        public void mouseExited(MouseEvent e) {}
236
237        @Override
238        public void mousePressed(MouseEvent e) {}
239
240        @Override
241        public void mouseReleased(MouseEvent e) {
242
243                JmolViewer viewer = jmolPanel.getViewer();
244                int pos = viewer.findNearestAtomIndex(e.getX(), e.getY());
245                if (pos == -1) return;
246
247                String atomInfo = ((Viewer) viewer).getAtomInfo(pos);
248                status.setText("clicked: " + atomInfo);
249                AtomInfo ai = AtomInfoParser.parse(atomInfo);
250
251                String cmd = "select " + ai.getResidueNumber()+":"
252                                +ai.getChainId()+"/"+ai.getModelNumber()
253                                + "; set display selected;";
254                evalString(cmd);
255        }
256
257        @Override
258        public void windowActivated(WindowEvent e) {}
259
260        @Override
261        public void windowClosed(WindowEvent e) {}
262
263        @Override
264        public void windowClosing(WindowEvent e) {
265                destroy();
266        }
267
268        @Override
269        public void windowDeactivated(WindowEvent e) {}
270
271        @Override
272        public void windowDeiconified(WindowEvent e) {}
273
274        @Override
275        public void windowIconified(WindowEvent e) {}
276
277        @Override
278        public void windowOpened(WindowEvent e) {}
279
280        @Override
281        public abstract void actionPerformed(ActionEvent e);
282
283}