JAL-4159 fix sense of console/alignment output suppression flags and make sure all...
[jalview.git] / src / jalview / gui / PairwiseAlignPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import jalview.analysis.AlignSeq;
24 import jalview.datamodel.Alignment;
25 import jalview.datamodel.AlignmentView;
26 import jalview.datamodel.SequenceGroup;
27 import jalview.datamodel.SequenceI;
28 import jalview.jbgui.GPairwiseAlignPanel;
29 import jalview.util.MessageManager;
30 import jalview.viewmodel.AlignmentViewport;
31 import jalview.math.MiscMath;
32
33 import java.beans.PropertyChangeListener;
34 import java.awt.event.ActionEvent;
35 import java.util.Vector;
36 import javax.swing.event.SwingPropertyChangeSupport;
37
38 /**
39  * DOCUMENT ME!
40  * 
41  * @author $author$
42  * @version $Revision$
43  */
44 public class PairwiseAlignPanel extends GPairwiseAlignPanel
45 {
46
47   private static final String DASHES = "---------------------\n";
48
49   private float[][] scores;
50
51   private float[][] alignmentScores;    // scores used by PaSiMap
52
53   private int GAP_OPEN_COST;
54
55   private int GAP_EXTEND_COST;
56
57   AlignmentViewport av;
58
59   Vector<SequenceI> sequences;
60
61   private String alignmentOutput;
62
63   private boolean suppressTextbox;
64  
65   private boolean discardAlignments;
66
67   private boolean endGaps;
68
69   // for listening
70   public static final String TOTAL = "total";
71
72   public static final String PROGRESS = "progress";
73
74   private int total;
75
76   private int progress;
77
78   private SequenceGroup selection;
79   /**
80    * input sequences
81    */
82   private SequenceI[] seqs=null;
83
84   /**
85    * Creates a new PairwiseAlignPanel object.
86    * 
87    * @param viewport
88    *          DOCUMENT ME!
89    * @param endGaps ~ toggle gaps and the beginning and end of sequences
90    */
91   public PairwiseAlignPanel(AlignmentViewport viewport)
92   {
93     this(viewport, null, false, 120, 20, true); // default penalties used in AlignSeq
94   }
95   public PairwiseAlignPanel(AlignmentViewport viewport, boolean endGaps, int gapOpenCost, int gapExtendCost)
96   {
97     this(viewport, null, endGaps, gapOpenCost, gapExtendCost, true);
98   }
99
100   public PairwiseAlignPanel(AlignmentViewport viewport, SequenceGroup selection, boolean  endGaps,
101           int gapOpenCost, int gapExtendCost, boolean run)
102   {
103     super();
104     this.av = viewport;
105     this.GAP_OPEN_COST = gapOpenCost;
106     this.GAP_EXTEND_COST = gapExtendCost;
107     this.endGaps = endGaps;
108     this.selection = selection;
109     this.total = MiscMath.combinations(av.getAlignment().getHeight(), 2);
110
111     if (run)
112       calculate();
113     System.out.println("Creating pap");
114   }
115   
116   public void calculate()
117   {
118
119     StringBuilder sb = new StringBuilder(1024);
120
121     sequences = new Vector<SequenceI>();
122     String[] seqStrings;
123     seqs=null;
124
125     if (selection != null)
126     {
127       // given a set of sequences to compare
128       seqs = selection.getSelectionAsNewSequences(av.getAlignment());
129       seqStrings = new String[seqs.length];
130       int s = 0;
131       for (SequenceI seq : seqs)
132       {
133         seqStrings[s++] = seq.getSequenceAsString();
134       }
135     }
136     else
137     {
138       SequenceGroup selectionGroup = av.getSelectionGroup();
139       boolean isSelection = selectionGroup != null
140               && selectionGroup.getSize() > 0;
141       AlignmentView view = av.getAlignmentView(isSelection);
142       seqStrings = view.getSequenceStrings(av.getGapCharacter());
143       if (isSelection)
144       {
145         seqs = (SequenceI[]) view
146                 .getAlignmentAndHiddenColumns(av.getGapCharacter())[0];
147       }
148       else
149       {
150         seqs = av.getAlignment().getSequencesArray();
151       }
152     }
153     
154     String type = (av.getAlignment().isNucleotide()) ? AlignSeq.DNA
155             : AlignSeq.PEP;
156
157     float[][] scores = new float[seqs.length][seqs.length];
158     float[][] alignmentScores = new float[seqs.length][seqs.length];
159     double totscore = 0D;
160     int count = seqs.length;
161     suppressTextbox = count>10;
162     discardAlignments = count>15;
163     boolean first = true;
164
165     progress = 0;
166     firePropertyChange(TOTAL, 0, total);
167
168     for (int i = 1; i < count; i++)
169     {
170       // fill diagonal alignmentScores with Float.NaN
171       alignmentScores[i - 1][i - 1] = Float.NaN;
172       for (int j = 0; j < i; j++)
173       {
174         AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
175                 seqStrings[j], type, GAP_OPEN_COST, GAP_EXTEND_COST);
176
177         if (as.s1str.length() == 0 || as.s2str.length() == 0)
178         {
179           continue;
180         }
181
182         as.calcScoreMatrix();
183         if (endGaps)
184         {
185           as.traceAlignmentWithEndGaps();
186         }
187         else
188         {
189           as.traceAlignment();
190         }
191         as.scoreAlignment();
192
193         if (!first && !suppressTextbox)
194         {
195           jalview.bin.Console.outPrintln(DASHES);
196           textarea.append(DASHES);
197           sb.append(DASHES);
198         }
199         first = false;
200         if (!discardAlignments) {
201           as.printAlignment(System.out);
202         }
203         scores[i][j] = as.getMaxScore() / as.getASeq1().length;
204         alignmentScores[i][j] = as.getAlignmentScore();
205         totscore = totscore + scores[i][j];
206         if (!suppressTextbox)
207         {
208           textarea.append(as.getOutput());
209           sb.append(as.getOutput());
210         }
211         if (!discardAlignments)
212         {
213           sequences.add(as.getAlignedSeq1());
214           sequences.add(as.getAlignedSeq2());
215         }
216         firePropertyChange(PROGRESS, progress, ++progress);
217       }
218     }
219     alignmentScores[count - 1][count - 1] = Float.NaN;
220
221     this.scores = scores;
222     this.alignmentScores = alignmentScores;
223
224     if (count > 2)
225     {
226       printScoreMatrix(seqs, scores, totscore);
227     }
228
229     alignmentOutput = sb.toString();
230   }
231
232   public float[][] getScores()
233   {
234     return this.scores;
235   }
236
237   public float[][] getAlignmentScores()
238   {
239     return this.alignmentScores;
240   }
241
242   public String getAlignmentOutput()
243   {
244     return this.alignmentOutput;
245   }
246
247   /**
248    * Prints a matrix of seqi-seqj pairwise alignment scores to sysout
249    * 
250    * @param seqs
251    * @param scores
252    * @param totscore
253    */
254   protected void printScoreMatrix(SequenceI[] seqs, float[][] scores,
255           double totscore)
256   {
257     System.out
258             .println("Pairwise alignment scaled similarity score matrix\n");
259
260     for (int i = 0; i < seqs.length; i++)
261     {
262       jalview.bin.Console.outPrintln(
263               String.format("%3d %s", i + 1, seqs[i].getDisplayId(true)));
264     }
265
266     /*
267      * table heading columns for sequences 1, 2, 3...
268      */
269     System.out.print("\n ");
270     for (int i = 0; i < seqs.length; i++)
271     {
272       System.out.print(String.format("%7d", i + 1));
273     }
274     jalview.bin.Console.outPrintln();
275
276     for (int i = 0; i < seqs.length; i++)
277     {
278       System.out.print(String.format("%3d", i + 1));
279       for (int j = 0; j < i; j++)
280       {
281         /*
282          * as a fraction of tot score, outputs are 0 <= score <= 1
283          */
284         System.out.print(String.format("%7.3f", scores[i][j] / totscore));
285       }
286       jalview.bin.Console.outPrintln();
287     }
288
289     jalview.bin.Console.outPrintln("\n");
290   }
291
292   /**
293    * DOCUMENT ME!
294    * 
295    * @param e
296    *          DOCUMENT ME!
297    */
298   @Override
299   protected void viewInEditorButton_actionPerformed(ActionEvent e)
300   {
301     SequenceI[] seq = new SequenceI[sequences.size()];
302
303     for (int i = 0; i < sequences.size(); i++)
304     {
305       seq[i] = sequences.elementAt(i);
306     }
307
308     AlignFrame af = new AlignFrame(new Alignment(seq),
309             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
310
311     Desktop.addInternalFrame(af,
312             MessageManager.getString("label.pairwise_aligned_sequences"),
313             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
314   }
315
316   public long getTotal()
317   {
318     return total;
319   }
320
321   public long getProgress()
322   {
323     return progress;
324   }
325   public SequenceI[] getInputSequences()
326   {
327     return seqs;
328   }
329 }