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;
022
023import java.awt.Dimension;
024import java.util.ArrayList;
025import java.util.List;
026
027import javax.swing.Box;
028import javax.swing.JFrame;
029import javax.swing.JMenuBar;
030import javax.swing.JScrollPane;
031
032import org.biojava.nbio.structure.Atom;
033import org.biojava.nbio.structure.Chain;
034import org.biojava.nbio.structure.Structure;
035import org.biojava.nbio.structure.StructureException;
036import org.biojava.nbio.structure.StructureImpl;
037import org.biojava.nbio.structure.align.gui.aligpanel.MultipleAligPanel;
038import org.biojava.nbio.structure.align.gui.aligpanel.MultipleStatusDisplay;
039import org.biojava.nbio.structure.align.gui.jmol.AbstractAlignmentJmol;
040import org.biojava.nbio.structure.align.gui.jmol.JmolTools;
041import org.biojava.nbio.structure.align.gui.jmol.MultipleAlignmentJmol;
042import org.biojava.nbio.structure.align.multiple.Block;
043import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
044import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentDisplay;
045import org.slf4j.Logger;
046import org.slf4j.LoggerFactory;
047
048/**
049 * Utility Class that provides helper methods for the visualization of
050 * {@link MultipleAlignment}s.
051 * <p>
052 * Currently supported: Alignment Panel Display, select aligned
053 * residues in Jmol by their PDB name, show a text Frame for any sequence
054 * alignment format, basic Jmol display from a MultipleAlignment, generate
055 * an artificial PDB structure with a new model for every aligned structure.
056 *
057 * @author Aleix Lafita
058 * @since 4.2.0
059 *
060 */
061public class MultipleAlignmentJmolDisplay  {
062
063        private static final Logger logger =
064                        LoggerFactory.getLogger(MultipleAlignmentJmolDisplay.class);
065
066        /**
067         * Utility method used in the {@link MultipleAlignmentJmol} Frame,
068         * when the aligned residues of a structure in the alignment have
069         * to be selected for formatting them (coloring and style).
070         *
071         * @param structNum the structure index (row) of the alignment
072         * @param multAln the MultipleAlignment that contains the equivalent
073         *                      positions
074         * @param ca the atom array of the structure specified
075         *                      (corresponding to the structure index)
076         * @return List of pdb Strings corresponding to the aligned positions
077         *                      of the structure.
078         */
079        public static List<String> getPDBresnum(int structNum,
080                        MultipleAlignment multAln, Atom[] ca){
081
082                List<String> lst = new ArrayList<String>();
083
084                for(Block block : multAln.getBlocks() ) {
085
086                        for (int i=0; i<block.length(); i++){
087                                Integer pos = block.getAlignRes().get(structNum).get(i);
088                                if (pos==null) continue; //gap
089                                else if (pos < ca.length) {
090                                        String pdbInfo = JmolTools.getPdbInfo(ca[pos]);
091                                        lst.add(pdbInfo);
092                                }
093                        }
094                }
095                return lst;
096        }
097
098        /**
099         * Creates a new Frame with the MultipleAlignment Sequence Panel.
100         * The panel can communicate with the Jmol 3D visualization by
101         * selecting the aligned residues of every structure.
102         *
103         * @param multAln
104         * @param jmol
105
106         * @throws StructureException
107         */
108        public static void showMultipleAligmentPanel(MultipleAlignment multAln,
109                        AbstractAlignmentJmol jmol) throws StructureException {
110
111                MultipleAligPanel me = new MultipleAligPanel(multAln, jmol);
112                JFrame frame = new JFrame();
113
114                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
115                frame.setTitle(jmol.getTitle());
116                me.setPreferredSize(new Dimension(
117                                me.getCoordManager().getPreferredWidth() ,
118                                me.getCoordManager().getPreferredHeight()));
119
120                JMenuBar menu = MenuCreator.getAlignmentPanelMenu(
121                                frame,me,null, multAln);
122                frame.setJMenuBar(menu);
123
124                JScrollPane scroll = new JScrollPane(me);
125                scroll.setAutoscrolls(true);
126
127                MultipleStatusDisplay status = new MultipleStatusDisplay(me);
128                me.addAlignmentPositionListener(status);
129
130                Box vBox = Box.createVerticalBox();
131                vBox.add(scroll);
132                vBox.add(status);
133                frame.getContentPane().add(vBox);
134
135                frame.pack();
136                frame.setVisible(true);
137
138                frame.addWindowListener(me);
139                frame.addWindowListener(status);
140        }
141
142        /**
143         * Creates a new Frame with the String output representation of the
144         * {@link MultipleAlignment}.
145         *
146         * @param multAln
147         * @param result String output
148         */
149        public static void showAlignmentImage(MultipleAlignment multAln,
150                        String result) {
151
152                JFrame frame = new JFrame();
153
154                String title = multAln.getEnsemble().getAlgorithmName() +
155                                " V."+multAln.getEnsemble().getVersion();
156                frame.setTitle(title);
157                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
158
159                AlignmentTextPanel txtPanel = new AlignmentTextPanel();
160                txtPanel.setText(result);
161
162                JMenuBar menu = MenuCreator.getAlignmentTextMenu(
163                                frame,txtPanel,null,multAln);
164
165                frame.setJMenuBar(menu);
166                JScrollPane js = new JScrollPane();
167                js.getViewport().add(txtPanel);
168                js.getViewport().setBorder(null);
169
170                frame.getContentPane().add(js);
171                frame.pack();
172                frame.setVisible(true);
173        }
174
175        /**
176         * Display a MultipleAlignment with a JmolPanel.
177         * New structures are downloaded if they were
178         * not cached in the alignment and they are entirely
179         * transformed here with the superposition information
180         * in the Multiple Alignment.
181         *
182         * @param multAln
183         * @return MultipleAlignmentJmol instance
184         * @throws StructureException
185         */
186        public static MultipleAlignmentJmol display(MultipleAlignment multAln)
187                        throws StructureException {
188
189                List<Atom[]> rotatedAtoms = MultipleAlignmentDisplay.getRotatedAtoms(multAln);
190
191                MultipleAlignmentJmol jmol =
192                                new MultipleAlignmentJmol(multAln, rotatedAtoms);
193
194                jmol.setTitle(jmol.getStructure().getPDBHeader().getTitle());
195                return jmol;
196        }
197
198        /**
199         * Get an artifical Structure containing a different model for every
200         * input structure, so that the alignment result can be viewed in Jmol.
201         * The Atoms have to be rotated beforehand.
202         *
203         * @param atomArrays an array of Atoms for every aligned structure
204         * @return a structure object containing a set of models,
205         *                      one for each input array of Atoms.
206         * @throws StructureException
207         */
208        public static final Structure getAlignedStructure(List<Atom[]> atomArrays)
209                        throws StructureException {
210
211                Structure s = new StructureImpl();
212                for (int i=0; i<atomArrays.size(); i++){
213                        List<Chain> model = DisplayAFP.getAlignedModel(atomArrays.get(i));
214                        s.addModel(model);
215                }
216                return s;
217        }
218
219}