    001    /*
    002     * PairwiseAlignmentFrame.java
    003     *
    004     * Copyright 2003 Sergio Anibal de Carvalho Junior
    005     *
    006     * This file is part of NeoBio.
    007     *
    008     * NeoBio is free software; you can redistribute it and/or modify it under the terms of
    009     * the GNU General Public License as published by the Free Software Foundation; either
    010     * version 2 of the License, or (at your option) any later version.
    011     *
    012     * NeoBio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    013     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    014     * PURPOSE. See the GNU General Public License for more details.
    015     *
    016     * You should have received a copy of the GNU General Public License along with NeoBio;
    017     * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    018     * Boston, MA 02111-1307, USA.
    019     *
    020     * Proper attribution of the author as the source of the software would be appreciated.
    021     *
    022     * Sergio Anibal de Carvalho Junior             mailto:sergioanibaljr@users.sourceforge.net
    023     * Department of Computer Science               http://www.dcs.kcl.ac.uk
    024     * King's College London, UK                    http://www.kcl.ac.uk
    025     *
    026     * Please visit http://neobio.sourceforge.net
    027     *
    028     * This project was supervised by Professor Maxime Crochemore.
    029     *
    030     */
    031
    032    package neobio.gui;
    033
    034    import neobio.alignment.*;
    035
    036    import java.io.*;
    037    import java.awt.*;
    038    import java.awt.event.*;
    039    import javax.swing.*;
    040    import javax.swing.border.*;
    041    import javax.swing.event.*;
    042
    043    /**
    044     * This class is the internal frame of NeoBio's graphical interface for computing pairwise
    045     * sequence alignments using one of the the algorithms provided in the {@link
    046     * neobio.alignment} package.
    047     *
    048     * @author Sergio A. de Carvalho Jr.
    049     */
    050    public class PairwiseAlignmentFrame extends JInternalFrame
    051    {
    052            private static int              window_number = 1;
    053
    054            private Frame                   parent_frame;
    055
    056            private JPanel                  input_panel, scoring_panel, algorithm_panel, output_panel;
    057            private JPanel                  progress_tab_panel, output_tab_panel;
    058            private JTextField              seq1_field, seq2_field, matrix_field, output_field;
    059            private JTextField              match_field, mismatch_field, gap_field;
    060            private JTextArea               progress_area, output_area;
    061            private JButton                 find_seq1_button, find_seq2_button, find_output_button;
    062            private JButton                 find_matrix_button, run_button;
    063            private JComboBox               algorithm_combo;
    064            private JTabbedPane             output_tab;
    065            private JRadioButton    screen_button, file_button, basic_button, matrix_button;
    066            private ButtonGroup             scoring_group, output_group;
    067            private JLabel                  seq1_label, seq2_label;
    068            private JLabel                  match_label, mismatch_label, gap_label;
    069
    070            private JFileChooser    find_dialog;
    071
    072            private boolean                 output_to_file, basic_scheme;
    073
    074            private String[]                algorithm_name = {"Needleman & Wunsch (global alignment)",
    075                                                                    "Smith & Waterman (local alignment)",
    076                                                                    "Crochemore, Landau & Ziv-Ukelson for global alignment",
    077                                                                    "Crochemore, Landau & Ziv-Ukelson for local alignment"};
    078
    079            private PairwiseAlignmentAlgorithm[]    algorithm = {new NeedlemanWunsch(),
    080                                                                    new SmithWaterman(),
    081                                                                    new CrochemoreLandauZivUkelsonGlobalAlignment(),
    082                                                                    new CrochemoreLandauZivUkelsonLocalAlignment()};
    083
    084            /**
    085             * Creates a new instance of the internal frame.
    086             *
    087             * @param parent_frame the parent frame
    088             */
    089            public PairwiseAlignmentFrame (Frame parent_frame)
    090            {
    091                    this.parent_frame = parent_frame;
    092                    initComponents();
    093            }
    094
    095            private void initComponents()
    096            {
    097                    JComponent                      pane;
    098                    GridBagConstraints      c;
    099
    100                    setIconifiable(true);
    101                    setMaximizable(true);
    102                    setResizable(true);
    103                    setClosable(true);
    104                    setTitle("Pairwise Sequence Alignment " + window_number++);
    105                    setMinimumSize(new Dimension(500, 500));
    106
    107                    pane = (JComponent) getContentPane();
    108                    pane.setLayout(new GridBagLayout());
    109
    110                    c = new GridBagConstraints();
    111                    c.insets = new Insets (4, 4, 4, 4);
    112                    c.fill = GridBagConstraints.BOTH;
    113                    c.weightx = 1.0; c.weighty = 0;
    114
    115                    // input panel
    116                    input_panel = new JPanel ();
    117                    add (pane, input_panel, c, 0, 0);
    118
    119                    // scoring panel
    120                    scoring_panel = new JPanel ();
    121                    add (pane, scoring_panel, c, 0, 1);
    122
    123                    // output panel
    124                    output_panel = new JPanel ();
    125                    add (pane, output_panel, c, 0, 2);
    126
    127                    // algorithm panel
    128                    algorithm_panel = new JPanel ();
    129                    add (pane, algorithm_panel, c, 0, 3);
    130
    131                    c.weightx = 1.0; c.weighty = 1.0;
    132
    133                    // output tab
    134                    output_tab = new JTabbedPane();
    135                    add (pane, output_tab, c, 0, 4);
    136
    137                    find_dialog = new JFileChooser();
    138                    find_dialog.setDialogTitle("Find...");
    139                    find_dialog.setDialogType(JFileChooser.OPEN_DIALOG );
    140
    141                    // ***************** INPUT PANEL *****************
    142                    input_panel.setLayout(new GridBagLayout());
    143                    input_panel.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(
    144                                                                                                                    EtchedBorder.LOWERED), "Input"));
    145
    146                    seq1_label = new JLabel("Sequence 1:");
    147                    seq2_label = new JLabel("Sequence 2:");
    148
    149                    seq1_field = new JTextField();
    150                    seq1_field.addCaretListener (new CaretListener()
    151                            {
    152                                    public void caretUpdate (CaretEvent e)
    153                                    {
    154                                            checkRunButtonStatus ();
    155                                    }
    156                            });
    157
    158                    seq2_field = new JTextField();
    159                    seq2_field.addCaretListener (new CaretListener()
    160                            {
    161                                    public void caretUpdate (CaretEvent e)
    162                                    {
    163                                            checkRunButtonStatus ();
    164                                    }
    165                            });
    166
    167                    find_seq1_button = new JButton("Find...");
    168            find_seq1_button.addActionListener (new ActionListener()
    169                            {
    170                                    public void actionPerformed (ActionEvent e)
    171                                    {
    172                                            findSeq1ButtonActionPerformed();
    173                                    }
    174                            });
    175
    176                    find_seq2_button = new JButton("Find...");
    177            find_seq2_button.addActionListener (new ActionListener()
    178                            {
    179                                    public void actionPerformed (ActionEvent e)
    180                                    {
    181                                            findSeq2ButtonActionPerformed();
    182                                    }
    183                            });
    184
    185                    c.weightx = 0; c.weighty = 0; c.anchor = GridBagConstraints.EAST;
    186                    add (input_panel, seq1_label, c, 0, 0);
    187                    add (input_panel, seq2_label, c, 0, 1);
    188
    189                    c.anchor = GridBagConstraints.CENTER;
    190                    add (input_panel, find_seq1_button, c, 2, 0);
    191                    add (input_panel, find_seq2_button, c, 2, 1);
    192
    193                    c.weightx = 1.0; c.fill = GridBagConstraints.HORIZONTAL;
    194                    add (input_panel, seq1_field, c, 1, 0);
    195                    add (input_panel, seq2_field, c, 1, 1);
    196
    197                    // ***************** SCORING SCHEME PANEL *****************
    198                    scoring_panel.setLayout(new GridBagLayout());
    199                    scoring_panel.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(
    200                                                                                            EtchedBorder.LOWERED), "Scoring Scheme"));
    201
    202                    basic_scheme = true;
    203                    basic_button = new JRadioButton("Basic:");
    204                    basic_button.setSelected(true);
    205            basic_button.addItemListener (new ItemListener()
    206                            {
    207                                    public void itemStateChanged (ItemEvent e)
    208                                    {
    209                                            schemeOptionStateChanged();
    210                                    }
    211                            });
    212
    213                    matrix_button = new JRadioButton("Substitution Matrix:");
    214            matrix_button.addItemListener (new ItemListener()
    215                            {
    216                                    public void itemStateChanged (ItemEvent e)
    217                                    {
    218                                            schemeOptionStateChanged();
    219                                    }
    220                            });
    221
    222                    match_label = new JLabel("Match:");
    223                    mismatch_label = new JLabel ("Mismatch:");
    224                    gap_label = new JLabel ("Gap:");
    225
    226                    match_field = new JTextField("1", 2);
    227                    match_field.setHorizontalAlignment(JTextField.RIGHT);
    228                    match_field.addCaretListener (new CaretListener()
    229                            {
    230                                    public void caretUpdate (CaretEvent e)
    231                                    {
    232                                            checkRunButtonStatus ();
    233                                    }
    234                            });
    235
    236                    mismatch_field = new JTextField("-1", 2);
    237                    mismatch_field.setHorizontalAlignment(JTextField.RIGHT);
    238                    mismatch_field.addCaretListener (new CaretListener()
    239                            {
    240                                    public void caretUpdate (CaretEvent e)
    241                                    {
    242                                            checkRunButtonStatus ();
    243                                    }
    244                            });
    245
    246                    gap_field = new JTextField("-1", 2);
    247                    gap_field.setHorizontalAlignment(JTextField.RIGHT);
    248                    gap_field.addCaretListener (new CaretListener()
    249                            {
    250                                    public void caretUpdate (CaretEvent e)
    251                                    {
    252                                            checkRunButtonStatus ();
    253                                    }
    254                            });
    255
    256                    matrix_field = new JTextField();
    257                    matrix_field.setEnabled(false);
    258                    matrix_field.addCaretListener (new CaretListener()
    259                            {
    260                                    public void caretUpdate (CaretEvent e)
    261                                    {
    262                                            checkRunButtonStatus ();
    263                                    }
    264                            });
    265
    266                    find_matrix_button = new JButton("Find...");
    267                    find_matrix_button.setEnabled(false);
    268            find_matrix_button.addActionListener (new ActionListener()
    269                            {
    270                                    public void actionPerformed (ActionEvent e)
    271                                    {
    272                                            findMatrixButtonActionPerformed();
    273                                    }
    274                            });
    275
    276                    scoring_group = new ButtonGroup ();
    277                    scoring_group.add(basic_button);
    278                    scoring_group.add(matrix_button);
    279
    280                    c.weightx = 0; c.fill = GridBagConstraints.NONE;
    281                    c.anchor = GridBagConstraints.WEST;
    282                    add (scoring_panel, basic_button, c, 0, 0);
    283
    284                    c.anchor = GridBagConstraints.EAST;
    285                    add (scoring_panel, match_label, c, 1, 0);
    286                    add (scoring_panel, mismatch_label, c, 3, 0);
    287                    add (scoring_panel, gap_label, c, 5, 0);
    288
    289                    c.anchor = GridBagConstraints.WEST;
    290                    add (scoring_panel, matrix_button, c, 0, 1);
    291
    292                    c.anchor = GridBagConstraints.CENTER;
    293                    add (scoring_panel, find_matrix_button, c, 7, 1);
    294
    295                    c.weightx = 1.0 / 3; c.fill = GridBagConstraints.HORIZONTAL;
    296                    add (scoring_panel, match_field, c, 2, 0);
    297                    add (scoring_panel, mismatch_field, c, 4, 0);
    298                    add (scoring_panel, gap_field, c, 6, 0);
    299
    300                    c.weightx = 1.0; c.gridwidth = 6;
    301                    add (scoring_panel, matrix_field, c, 1, 1);
    302                    c.gridwidth = 1;
    303
    304                    // ***************** OUTPUT PANEL *****************
    305                    output_panel.setLayout(new GridBagLayout());
    306                    output_panel.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(
    307                                                                                                                    EtchedBorder.LOWERED), "Output"));
    308
    309                    screen_button = new JRadioButton("Screen");
    310                    screen_button.setSelected(true);
    311
    312                    output_to_file = false;
    313                    file_button = new JRadioButton("File:");
    314            file_button.addItemListener (new ItemListener()
    315                            {
    316                                    public void itemStateChanged (ItemEvent e)
    317                                    {
    318                                            outputOptionStateChanged();
    319                                    }
    320                            });
    321
    322                    output_field = new JTextField();
    323                    output_field.setEnabled(false);
    324                    output_field.addCaretListener (new CaretListener()
    325                            {
    326                                    public void caretUpdate (CaretEvent e)
    327                                    {
    328                                            checkRunButtonStatus ();
    329                                    }
    330                            });
    331
    332                    find_output_button = new JButton("Find...");
    333                    find_output_button.setEnabled(false);
    334            find_output_button.addActionListener (new ActionListener()
    335                            {
    336                                    public void actionPerformed (ActionEvent e)
    337                                    {
    338                                            findOutputButtonActionPerformed();
    339                                    }
    340                            });
    341
    342                    output_group = new ButtonGroup ();
    343                    output_group.add(screen_button);
    344                    output_group.add(file_button);
    345
    346                    c.weightx = 0; c.weighty = 0; c.fill = GridBagConstraints.NONE;
    347                    add (output_panel, screen_button, c, 0, 0);
    348                    add (output_panel, file_button, c, 1, 0);
    349                    add (output_panel, find_output_button, c, 3, 0);
    350
    351                    c.weightx = 1.0; c.weighty = 0; c.fill = GridBagConstraints.HORIZONTAL;
    352                    add (output_panel, output_field, c, 2, 0);
    353
    354                    // ***************** ALGORITHM PANEL *****************
    355                    algorithm_panel.setLayout(new GridBagLayout());
    356                    algorithm_panel.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(
    357                                                                    EtchedBorder.LOWERED), "Alignment Algorithm"));
    358
    359                    algorithm_combo = new JComboBox(algorithm_name);
    360
    361                    run_button = new JButton("Run");
    362                    run_button.setEnabled(false);
    363            run_button.addActionListener (new ActionListener()
    364                            {
    365                                    public void actionPerformed (ActionEvent e)
    366                                    {
    367                                            runButtonActionPerformed();
    368                                    }
    369                            });
    370
    371
    372                    c.weightx = 1.0; c.weighty = 0; c.fill = GridBagConstraints.HORIZONTAL;
    373                    add (algorithm_panel, algorithm_combo, c, 0, 0);
    374
    375                    c.weightx = 0; c.weighty = 0; c.fill = GridBagConstraints.NONE;
    376                    add (algorithm_panel, run_button, c, 1, 0);
    377
    378                    // ***************** OUTPUT TAB *****************
    379                    progress_area = new JTextArea ();
    380                    progress_area.setEditable (false);
    381                    progress_area.setBorder (BorderFactory.createBevelBorder(BevelBorder.LOWERED));
    382                    progress_tab_panel = new JPanel ();
    383                    progress_tab_panel.setLayout (new GridLayout());
    384                    progress_tab_panel.add (new JScrollPane (progress_area));
    385                    output_tab.addTab ("Progress", progress_tab_panel);
    386
    387                    output_area = new JTextArea ();
    388                    output_area.setEditable (false);
    389                    output_area.setBorder (BorderFactory.createBevelBorder(BevelBorder.LOWERED));
    390                    output_area.setFont (new Font("Monospaced", Font.PLAIN, 12));
    391                    output_tab_panel = new JPanel();
    392                    output_tab_panel.setLayout (new GridLayout());
    393                    output_tab_panel.add (new JScrollPane (output_area));
    394                    output_tab.addTab ("Output", output_tab_panel);
    395        }
    396
    397        private void add (JComponent a, JComponent b, GridBagConstraints c, int x, int y)
    398        {
    399                    c.gridx = x;
    400                    c.gridy = y;
    401                    a.add (b, c);
    402            }
    403
    404        private void findSeq1ButtonActionPerformed ()
    405            {
    406                int c = find_dialog.showOpenDialog (this);
    407
    408                if (c != JFileChooser.APPROVE_OPTION) return;
    409
    410                seq1_field.setText (find_dialog.getSelectedFile().getPath());
    411            }
    412
    413        private void findSeq2ButtonActionPerformed ()
    414            {
    415                int c = find_dialog.showOpenDialog (this);
    416
    417                if (c != JFileChooser.APPROVE_OPTION) return;
    418
    419                seq2_field.setText (find_dialog.getSelectedFile().getPath());
    420            }
    421
    422        private void findMatrixButtonActionPerformed ()
    423            {
    424                int c = find_dialog.showOpenDialog (this);
    425
    426                if (c != JFileChooser.APPROVE_OPTION) return;
    427
    428                matrix_field.setText (find_dialog.getSelectedFile().getPath());
    429            }
    430
    431        private void findOutputButtonActionPerformed ()
    432            {
    433                int c = find_dialog.showOpenDialog (this);
    434
    435                if (c != JFileChooser.APPROVE_OPTION) return;
    436
    437                output_field.setText (find_dialog.getSelectedFile().getPath());
    438            }
    439
    440            private void schemeOptionStateChanged ()
    441            {
    442                    basic_scheme = basic_button.isSelected();
    443
    444                    match_label.setEnabled(basic_scheme);
    445                    match_field.setEnabled(basic_scheme);
    446                    mismatch_label.setEnabled(basic_scheme);
    447                    mismatch_field.setEnabled(basic_scheme);
    448                    gap_label.setEnabled(basic_scheme);
    449                    gap_field.setEnabled(basic_scheme);
    450
    451                    matrix_field.setEnabled (!basic_scheme);
    452                    find_matrix_button.setEnabled (!basic_scheme);
    453
    454                    checkRunButtonStatus();
    455            }
    456
    457            private void outputOptionStateChanged ()
    458            {
    459                    output_to_file = file_button.isSelected();
    460
    461                    output_field.setEnabled (output_to_file);
    462                    find_output_button.setEnabled (output_to_file);
    463
    464                    checkRunButtonStatus();
    465            }
    466
    467            private void checkRunButtonStatus ()
    468            {
    469                    boolean run = true;
    470
    471                    if (seq1_field.getText().length() == 0 || seq2_field.getText().length() == 0)
    472                    {
    473                            run = false;
    474                    }
    475                    else
    476                    {
    477                            if (file_button.isSelected() && output_field.getText().length() == 0)
    478                            {
    479                                    run = false;
    480                            }
    481                            else
    482                            {
    483                                    if (matrix_button.isSelected())
    484                                    {
    485                                            if (matrix_field.getText().length() == 0)
    486                                            {
    487                                                    run = false;
    488                                            }
    489                                    }
    490                                    else
    491                                    {
    492                                            if (match_field.getText().length() == 0
    493                                                    || mismatch_field.getText().length() == 0
    494                                                    || gap_field.getText().length() == 0)
    495                                            {
    496                                                    run = false;
    497                                            }
    498                                    }
    499                            }
    500                    }
    501
    502                    if ((run_button.isEnabled() && !run) || (!run_button.isEnabled() && run))
    503                            run_button.setEnabled(run);
    504            }
    505
    506            private void runButtonActionPerformed ()
    507            {
    508                    ScoringScheme           scoring;
    509                    PairwiseAlignment       alignment;
    510                    FileReader                      seq1_file, seq2_file, matrix_file;
    511                    BufferedWriter          output_file;
    512                    String                          seq1_filename, seq2_filename;
    513                    String                          matrix_filename, output_filename, message;
    514                    int                                     alg, match, mismatch, gap;
    515                    long                            start, elapsed;
    516
    517                    alg = algorithm_combo.getSelectedIndex();
    518
    519                    output_tab.setSelectedIndex(0);
    520
    521                    output_area.setText ("");
    522
    523                    // ***************** SET SCORING SCHEME *****************
    524                    if (basic_scheme)
    525                    {
    526                            progress_area.setText ("Creating scoring scheme... ");
    527                            try
    528                            {
    529                                    match = Integer.parseInt (match_field.getText());
    530                                    mismatch = Integer.parseInt (mismatch_field.getText());
    531                                    gap = Integer.parseInt (gap_field.getText());
    532
    533                                    scoring = new BasicScoringScheme (match, mismatch, gap);
    534                                    algorithm[alg].setScoringScheme(scoring);
    535                                    progress_area.append ("OK");
    536                            }
    537                            catch (NumberFormatException e)
    538                            {
    539                                    message = "Invalid scoring arguments.";
    540                                    progress_area.append ("\n" + message);
    541                                    showError (message);
    542                                    return;
    543                            }
    544                    }
    545                    else
    546                    {
    547                            matrix_filename = matrix_field.getText  ();
    548                            progress_area.setText ("Loading matrix file... ");
    549                            try
    550                            {
    551                                    matrix_file = new FileReader (matrix_filename);
    552                            }
    553                            catch (FileNotFoundException e)
    554                            {
    555                                    message = "File \"" + matrix_filename + "\" not found.";
    556                                    progress_area.append("\n" + message);
    557                                    showError (message);
    558                                    return;
    559                            }
    560
    561                            try
    562                            {
    563                                    try
    564                                    {
    565                                            scoring = new ScoringMatrix (matrix_file);
    566                                            algorithm[alg].setScoringScheme(scoring);
    567                                            progress_area.append ("OK");
    568                                    }
    569                                    catch (InvalidScoringMatrixException e)
    570                                    {
    571                                            matrix_file.close();
    572                                            message = "Invalid matrix file \"" + matrix_filename + "\".";
    573                                            progress_area.append ("\n" + message);
    574                                            showError (message);
    575                                            return;
    576                                    }
    577                                    matrix_file.close();
    578                            }
    579                            catch (IOException e)
    580                            {
    581                                    message = "Error reading file.";
    582                                    progress_area.append("\n" + message);
    583                                    showError (message);
    584                                    return;
    585                            }
    586                    }
    587
    588                    // ***************** LOAD SEQUENCES *****************
    589                    progress_area.append ("\n\nLoading sequences... ");
    590
    591                    seq1_filename = seq1_field.getText ();
    592                    try
    593                    {
    594                            seq1_file = new FileReader (seq1_filename);
    595                    }
    596                    catch (FileNotFoundException e)
    597                    {
    598                            message = "File \"" +  seq1_filename +"\" not found.";
    599                            progress_area.append("\n" + message);
    600                            showError (message);
    601                            return;
    602                    }
    603
    604                    seq2_filename = seq2_field.getText ();
    605                    try
    606                    {
    607                            seq2_file = new FileReader (seq2_filename);
    608                    }
    609                    catch (FileNotFoundException e)
    610                    {
    611                            message = "File \"" +  seq2_filename +"\" not found.";
    612                            progress_area.append("\n" + message);
    613                            showError (message);
    614                            return;
    615                    }
    616
    617                    try
    618                    {
    619                            try
    620                            {
    621                                    start = System.currentTimeMillis();
    622                                    algorithm[alg].loadSequences (seq1_file, seq2_file);
    623                                    elapsed = System.currentTimeMillis() - start;
    624                                    progress_area.append ("OK");
    625                                    progress_area.append ("\n[ Elapsed time: " + elapsed + " milliseconds ]");
    626
    627                            }
    628                            catch (InvalidSequenceException e)
    629                            {
    630                                    seq1_file.close();
    631                                    seq2_file.close();
    632                                    message = "Invalid sequence files.";
    633                                    progress_area.append ("\n" + message);
    634                                    showError (message);
    635                                    return;
    636                            }
    637                            seq1_file.close();
    638                            seq2_file.close();
    639                    }
    640                    catch (IOException e)
    641                    {
    642                            message = "Error reading sequence files.";
    643                            progress_area.append("\n" + message);
    644                            showError (message);
    645                            return;
    646                    }
    647
    648                    // ***************** EXECUTE ALGORITHM *****************
    649                    progress_area.append("\n\nRunning " + algorithm_combo.getSelectedItem() + "... ");
    650                    try
    651                    {
    652                            start = System.currentTimeMillis();
    653                            alignment = algorithm[alg].getPairwiseAlignment();
    654                            elapsed = System.currentTimeMillis() - start;
    655                            progress_area.append ("OK");
    656                            progress_area.append ("\n[ Elapsed time: " + elapsed + " milliseconds ]");
    657                    }
    658                    catch (IncompatibleScoringSchemeException e)
    659                    {
    660                            message = "Scoring matrix is not compatible with loaded sequences.";
    661                            progress_area.append ("\n" + message);
    662                            showError (message);
    663                            return;
    664                    }
    665                    catch (OutOfMemoryError e)
    666                    {
    667                            message = "Insufficient memory to compute an alignment";
    668                            progress_area.append ("\n" + message);
    669                            showError (message);
    670                            return;
    671                    }
    672
    673                    // ***************** DISPLAY / SAVE OUTPUT *****************
    674                    if (output_to_file)
    675                    {
    676                            output_filename = output_field.getText ();
    677                            progress_area.append ("\n\nSaving alignment... ");
    678                            try
    679                            {
    680                                    int length = alignment.getGappedSequence1().length();
    681
    682                                    output_file = new BufferedWriter(new FileWriter (output_filename));
    683                                    output_file.write(alignment.getGappedSequence1(), 0, length);
    684                                    output_file.newLine();
    685                                    output_file.write(alignment.getScoreTagLine(), 0, length);
    686                                    output_file.newLine();
    687                                    output_file.write(alignment.getGappedSequence2(), 0, length);
    688                                    output_file.newLine();
    689                                    String tmp = "Score: " + alignment.getScore();
    690                                    output_file.write(tmp, 0, tmp.length());
    691                                    output_file.close();
    692                            }
    693                            catch (IOException e)
    694                            {
    695                                    message = "Error writing file \"" + output_filename +"\".";
    696                                    progress_area.append("\n" + message);
    697                                    showError (message);
    698                                    return;
    699                            }
    700                            progress_area.append ("OK");
    701                    }
    702                    else
    703                    {
    704                            output_area.setText (alignment.toString());
    705                            output_tab.setSelectedIndex(1);
    706                    }
    707            }
    708
    709            private void showError (String message)
    710            {
    711                    JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
    712            }
    713    }