Merge branch 'test/progressBar' into feature/JAL-4159_pasimap
[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   /**
79    * Creates a new PairwiseAlignPanel object.
80    * 
81    * @param viewport
82    *          DOCUMENT ME!
83    * @param endGaps ~ toggle gaps and the beginning and end of sequences
84    */
85   public PairwiseAlignPanel(AlignmentViewport viewport)
86   {
87     this(viewport, false, 120, 20, true);       // default penalties used in AlignSeq
88   }
89   public PairwiseAlignPanel(AlignmentViewport viewport, boolean endGaps, int gapOpenCost, int gapExtendCost)
90   {
91     this(viewport, endGaps, gapOpenCost, gapExtendCost, true);
92   }
93   public PairwiseAlignPanel(AlignmentViewport viewport, boolean endGaps, int gapOpenCost, int gapExtendCost, boolean run)
94   {
95     super();
96     this.av = viewport;
97     this.GAP_OPEN_COST = gapOpenCost;
98     this.GAP_EXTEND_COST = gapExtendCost;
99     this.endGaps = endGaps;
100     this.total = MiscMath.combinations(av.getAlignment().getHeight(), 2);
101     
102     if (run)
103       calculate();
104 System.out.println("Creating pap");
105   }
106
107   public void calculate()
108   {
109
110     SequenceGroup selectionGroup = av.getSelectionGroup();
111     StringBuilder sb = new StringBuilder(1024);
112
113     sequences = new Vector<SequenceI>();
114
115     boolean isSelection = selectionGroup != null
116             && selectionGroup.getSize() > 0;
117     AlignmentView view = av.getAlignmentView(isSelection);
118     // String[] seqStrings = av.getViewAsString(true);
119     String[] seqStrings = view
120             .getSequenceStrings(av.getGapCharacter());
121
122     SequenceI[] seqs;
123     if (isSelection)
124     {
125       seqs = (SequenceI[]) view
126               .getAlignmentAndHiddenColumns(av.getGapCharacter())[0];
127     }
128     else
129     {
130       seqs = av.getAlignment().getSequencesArray();
131     }
132
133     String type = (av.getAlignment().isNucleotide()) ? AlignSeq.DNA
134             : AlignSeq.PEP;
135
136     float[][] scores = new float[seqs.length][seqs.length];
137     float[][] alignmentScores = new float[seqs.length][seqs.length];
138     double totscore = 0D;
139     int count = seqs.length;
140     boolean first = true;
141
142     progress = 0;
143     firePropertyChange(TOTAL, 0, total);
144
145     suppressTextbox = count<10;
146     discardAlignments = count<15;
147
148     for (int i = 1; i < count; i++)
149     {
150       // fill diagonal alignmentScores with Float.NaN
151       alignmentScores[i - 1][i - 1] = Float.NaN;
152       for (int j = 0; j < i; j++)
153       {
154         AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
155                 seqStrings[j], type, GAP_OPEN_COST, GAP_EXTEND_COST);
156
157         if (as.s1str.length() == 0 || as.s2str.length() == 0)
158         {
159           continue;
160         }
161
162         as.calcScoreMatrix();
163         if (endGaps)
164         {
165           as.traceAlignmentWithEndGaps();
166         } else {
167           as.traceAlignment();
168         }
169         as.scoreAlignment();
170
171         if (!first)
172         {
173           System.out.println(DASHES);
174           textarea.append(DASHES);
175           sb.append(DASHES);
176         }
177         first = false;
178         if (discardAlignments) {
179           as.printAlignment(System.out);
180         }
181         scores[i][j] = as.getMaxScore() / as.getASeq1().length;
182         alignmentScores[i][j] = as.getAlignmentScore();
183         totscore = totscore + scores[i][j];
184
185         if (suppressTextbox)
186         {
187           textarea.append(as.getOutput());
188           sb.append(as.getOutput());
189         }
190         if (discardAlignments)
191         {
192           sequences.add(as.getAlignedSeq1());
193           sequences.add(as.getAlignedSeq2());
194         }
195
196         firePropertyChange(PROGRESS, progress, ++progress);
197       }
198     }
199     alignmentScores[count - 1][count - 1] = Float.NaN;
200
201     this.scores = scores;
202     this.alignmentScores = alignmentScores;
203
204     if (count > 2)
205     {
206       printScoreMatrix(seqs, scores, totscore);
207     }
208
209     alignmentOutput = sb.toString();
210   }
211
212   public float[][] getScores()
213   {
214     return this.scores;
215   }
216
217   public float[][] getAlignmentScores()
218   {
219     return this.alignmentScores;
220   }
221
222   public String getAlignmentOutput()
223   {
224     return this.alignmentOutput;
225   }
226
227   /**
228    * Prints a matrix of seqi-seqj pairwise alignment scores to sysout
229    * 
230    * @param seqs
231    * @param scores
232    * @param totscore
233    */
234   protected void printScoreMatrix(SequenceI[] seqs, float[][] scores,
235           double totscore)
236   {
237     System.out
238             .println("Pairwise alignment scaled similarity score matrix\n");
239
240     for (int i = 0; i < seqs.length; i++)
241     {
242       System.out.println(
243               String.format("%3d %s", i + 1, seqs[i].getDisplayId(true)));
244     }
245
246     /*
247      * table heading columns for sequences 1, 2, 3...
248      */
249     System.out.print("\n ");
250     for (int i = 0; i < seqs.length; i++)
251     {
252       System.out.print(String.format("%7d", i + 1));
253     }
254     System.out.println();
255
256     for (int i = 0; i < seqs.length; i++)
257     {
258       System.out.print(String.format("%3d", i + 1));
259       for (int j = 0; j < i; j++)
260       {
261         /*
262          * as a fraction of tot score, outputs are 0 <= score <= 1
263          */
264         System.out.print(String.format("%7.3f", scores[i][j] / totscore));
265       }
266       System.out.println();
267     }
268
269     System.out.println("\n");
270   }
271
272   /**
273    * DOCUMENT ME!
274    * 
275    * @param e
276    *          DOCUMENT ME!
277    */
278   @Override
279   protected void viewInEditorButton_actionPerformed(ActionEvent e)
280   {
281     SequenceI[] seq = new SequenceI[sequences.size()];
282
283     for (int i = 0; i < sequences.size(); i++)
284     {
285       seq[i] = sequences.elementAt(i);
286     }
287
288     AlignFrame af = new AlignFrame(new Alignment(seq),
289             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
290
291     Desktop.addInternalFrame(af,
292             MessageManager.getString("label.pairwise_aligned_sequences"),
293             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
294   }
295
296   public long getTotal()
297   {
298     return total;
299   }
300
301   public long getProgress()
302   {
303     return progress;
304   }
305 }