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 * Created on Jul 16, 2006
021 *
022 */
023package org.biojava.nbio.structure.align.gui;
024
025import java.awt.Dimension;
026import java.awt.event.ActionEvent;
027import java.util.List;
028
029import javax.swing.AbstractAction;
030import javax.swing.Action;
031import javax.swing.Box;
032import javax.swing.JButton;
033import javax.swing.JComboBox;
034import javax.swing.JFrame;
035import javax.swing.JLabel;
036import javax.swing.JMenuBar;
037import javax.swing.JOptionPane;
038import javax.swing.JProgressBar;
039import javax.swing.JTabbedPane;
040
041import org.biojava.nbio.structure.Structure;
042import org.biojava.nbio.structure.StructureException;
043import org.biojava.nbio.structure.StructureIdentifier;
044import org.biojava.nbio.structure.align.MultipleStructureAligner;
045import org.biojava.nbio.structure.align.StructureAlignment;
046import org.biojava.nbio.structure.align.StructureAlignmentFactory;
047import org.biojava.nbio.structure.align.ce.AbstractUserArgumentProcessor;
048import org.biojava.nbio.structure.align.ce.ConfigStrucAligParams;
049import org.biojava.nbio.structure.align.multiple.mc.MultipleMcMain;
050import org.biojava.nbio.structure.align.webstart.AligUIManager;
051import org.biojava.nbio.structure.gui.util.SelectMultiplePanel;
052
053/**
054 * A JFrame that allows to trigger a multiple structure alignment,
055 * either from files in a directory or after manual upload.
056 * <p>
057 * The current version allows to select the parameters of
058 * the pairwise alignment algorithm and the parameters of
059 * the multiple alignment algorithm.
060 *
061 * @author Aleix Lafita
062 * @since 4.2.0
063 *
064 */
065public class MultipleAlignmentGUI extends JFrame {
066
067        private final static long serialVersionUID =0l;
068        private final static String version = "1.0";
069
070        private MultipleStructureAligner multiple;
071        private StructureAlignment pairwise;
072
073        private SelectMultiplePanel tab;
074        private JTabbedPane tabPane;
075
076        private Thread thread;
077        private AlignmentCalculationRunnable alicalc;
078        private JProgressBar progress;
079        private JButton abortB;
080
081        private static final String MAIN_TITLE =
082                        "Multiple Structure Alignment - Main - V." + version;
083
084        private static final MultipleAlignmentGUI me =
085                        new MultipleAlignmentGUI();
086
087        public static void main(String[] args){
088                MultipleAlignmentGUI.getInstance();
089        }
090
091        public static MultipleAlignmentGUI getInstance(){
092
093                //TODO change about me
094                AbstractUserArgumentProcessor.printAboutMe();
095                AligUIManager.setLookAndFeel();
096
097                if (!me.isVisible()) me.setVisible(true);
098                if (!me.isActive()) me.requestFocus();
099
100                return me;
101        }
102
103        public static MultipleAlignmentGUI getInstanceNoVisibilityChange(){
104                return me;
105        }
106
107        protected MultipleAlignmentGUI() {
108                super();
109
110                thread = null;
111                JMenuBar menu = MenuCreator.initAlignmentGUIMenu(this);
112
113                this.setJMenuBar(menu);
114                this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
115                this.setTitle(MAIN_TITLE);
116
117                tab = new SelectMultiplePanel();
118
119                // setup tabPane
120                tabPane = new JTabbedPane();
121                tabPane.addTab("Select Structures", null,
122                                tab, "Input Structure identifiers");
123
124                Box hBoxPair = setupPairwiseAlgorithm();
125                Box hBoxMult = setupMultipleAlgorithm();
126                Box vBox = Box.createVerticalBox();
127
128                vBox.add(tabPane);
129                vBox.add(Box.createGlue());
130
131                Box vBoxMain = Box.createVerticalBox();
132                vBoxMain.add(hBoxPair);
133                vBoxMain.add(hBoxMult);
134                vBoxMain.add(tabPane);
135
136                vBoxMain.add(initButtons());
137                this.getContentPane().add(vBoxMain);
138
139                this.pack();
140                this.setVisible(true);
141        }
142
143        private Box setupPairwiseAlgorithm() {
144
145                String[] pairAlgo = StructureAlignmentFactory.getAllAlgorithmNames();
146                try {
147                        pairwise = StructureAlignmentFactory.getAlgorithm(pairAlgo[0]);
148                } catch (StructureException e){
149                        e.printStackTrace();
150                }
151                JLabel algoLabel = new JLabel("Select pairwise aligner: ");
152
153                JComboBox algorithmList = new JComboBox(pairAlgo);
154                algorithmList.setSelectedIndex(0);
155
156                Action actionAlgorithm = new AbstractAction("Algorithm") {
157                        public static final long serialVersionUID = 0l;
158                        @Override
159                        public void actionPerformed(ActionEvent evt) {
160                                JComboBox cb = (JComboBox)evt.getSource();
161                                String algorithmName = (String)cb.getSelectedItem();
162                                updatePairwiseAlgorithm(algorithmName);
163                        }
164                };
165                algorithmList.addActionListener(actionAlgorithm);
166
167                Action paramAction = new AbstractAction("Parameters") {
168                        public static final long serialVersionUID = 0l;
169                        @Override
170                        public void actionPerformed(ActionEvent evt) {
171                                StructureAlignment p = getPairwiseStructureAligner();
172                                ConfigStrucAligParams params = p.getParameters();
173                                new ParameterGUI(params, p.getAlgorithmName());
174                        }
175                };
176                JButton parameterButton = new JButton(paramAction);
177
178                Box hBoxAlgoPair = Box.createHorizontalBox();
179                hBoxAlgoPair.add(Box.createGlue());
180                hBoxAlgoPair.add(algoLabel);
181                hBoxAlgoPair.add(algorithmList);
182                hBoxAlgoPair.add(Box.createGlue());
183                hBoxAlgoPair.add(parameterButton);
184                hBoxAlgoPair.add(Box.createGlue());
185
186                return hBoxAlgoPair;
187        }
188
189        private Box setupMultipleAlgorithm() {
190
191                //TODO change in the future when more multiple algorithms are added
192                String[] multAlgo = {MultipleMcMain.algorithmName};
193                multiple = new MultipleMcMain(pairwise);
194
195                JLabel multLabel = new JLabel("Select multiple aligner: ");
196                JComboBox multList = new JComboBox(multAlgo);
197                multList.setSelectedIndex(0);
198
199                Action actionMultiple = new AbstractAction("Algorithm") {
200                        public static final long serialVersionUID = 0l;
201                        @Override
202                        public void actionPerformed(ActionEvent evt) {
203                                updateMultipleAlgorithm();
204                        }
205                };
206                multList.addActionListener(actionMultiple);
207
208                Action paramAction = new AbstractAction("Parameters") {
209                        public static final long serialVersionUID = 0l;
210                        @Override
211                        public void actionPerformed(ActionEvent evt) {
212                                MultipleStructureAligner m = getMultipleStructureAligner();
213                                ConfigStrucAligParams params = m.getParameters();
214                                new ParameterGUI(params, m.getAlgorithmName());
215                        }
216                };
217                JButton parameterButton = new JButton(paramAction);
218
219                Box hBoxAlgo = Box.createHorizontalBox();
220                hBoxAlgo.add(Box.createGlue());
221                hBoxAlgo.add(multLabel);
222                hBoxAlgo.add(multList);
223                hBoxAlgo.add(Box.createGlue());
224                hBoxAlgo.add(parameterButton);
225                hBoxAlgo.add(Box.createGlue());
226
227                return hBoxAlgo;
228        }
229
230        private Box initButtons(){
231
232                //Progress Bar
233                progress = new JProgressBar();
234                progress.setIndeterminate(false);
235                progress.setMaximumSize(new Dimension(10,100));
236                progress.setVisible(false);
237
238                Action action1 = new AbstractAction("Align") {
239                        public static final long serialVersionUID = 0l;
240                        // This method is called when the button is pressed
241                        @Override
242                        public void actionPerformed(ActionEvent evt) {
243                                calcAlignment();
244                        }
245                };
246                JButton submitB = new JButton(action1);
247
248                Action action3 = new AbstractAction("Abort") {
249                        public static final long serialVersionUID = 0l;
250                        // This method is called when the button is pressed
251                        @Override
252                        public void actionPerformed(ActionEvent evt) {
253                                abortCalc();
254                        }
255                };
256                abortB = new JButton(action3);
257                abortB.setEnabled(false);
258
259                Action action2 = new AbstractAction("Exit") {
260                        public static final long serialVersionUID = 0l;
261                        // This method is called when the button is pressed
262                        @Override
263                        public void actionPerformed(ActionEvent evt) {
264                                abortCalc();
265                                dispose();
266                                System.exit(0);
267                        }
268                };
269                JButton closeB = new JButton(action2);
270
271                Box hBox = Box.createHorizontalBox();
272                hBox.add(closeB);
273                hBox.add(Box.createGlue());
274                hBox.add(progress);
275                hBox.add(abortB);
276                hBox.add(submitB);
277
278                return hBox;
279        }
280
281        public void cleanUp() {
282                if (alicalc != null) alicalc.cleanup();
283        }
284
285        private void calcAlignment() {
286
287                try {
288                        List<Structure> structures = tab.getStructures();
289
290                        if ( structures.size() < 2) {
291                                System.err.println("please input more than 1 structure");
292                                return;
293                        }
294
295                        List<StructureIdentifier> names = tab.getNames();
296
297                        String message = "aligning: ";
298                        for (StructureIdentifier name:names){
299                                message += name.getIdentifier() + " ";
300                        }
301                        System.out.println(message);
302
303                        alicalc = new MultipleAlignmentCalc(this, structures, names);
304
305                        thread = new Thread(alicalc);
306                        thread.start();
307                        abortB.setEnabled(true);
308                        progress.setIndeterminate(true);
309                        ProgressThreadDrawer drawer = new ProgressThreadDrawer(progress);
310                        drawer.start();
311
312                } catch (StructureException e){
313                        JOptionPane.showMessageDialog(null,"Could not align structures. "
314                                        + "Exception: " + e.getMessage());
315                }
316
317        }
318
319        public void notifyCalcFinished(){
320                abortB.setEnabled(false);
321                thread = null;
322                progress.setIndeterminate(false);
323                this.repaint();
324        }
325
326        private void abortCalc(){
327                System.err.println("Interrupting alignment ...");
328                if (alicalc != null) alicalc.interrupt();
329                notifyCalcFinished();
330        }
331
332
333        public MultipleStructureAligner getMultipleStructureAligner() {
334                return multiple;
335        }
336
337        public StructureAlignment getPairwiseStructureAligner() {
338                return pairwise;
339        }
340
341        private void updatePairwiseAlgorithm(String algorithmName) {
342                try {
343                        pairwise = StructureAlignmentFactory.getAlgorithm(algorithmName);
344                        //Update also the multiple structure algorithm
345                        ConfigStrucAligParams params = multiple.getParameters();
346                        updateMultipleAlgorithm();
347                        multiple.setParameters(params);
348
349                } catch (StructureException ex){
350                        ex.printStackTrace();
351                }
352        }
353
354        private void updateMultipleAlgorithm() {
355                //TODO a factory would be needed to select the MultipleAligner
356                multiple = new MultipleMcMain(pairwise);
357        }
358}