Merge branch 'feature/JAL-4159_pasimap' into spike/JAL-4159_pasimap_2113_series
[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     suppressTextbox = count<10;
141     discardAlignments = count<15;
142     boolean first = true;
143
144     progress = 0;
145     firePropertyChange(TOTAL, 0, total);
146
147     suppressTextbox = count<10;
148     discardAlignments = count<15;
149
150     for (int i = 1; i < count; i++)
151     {
152       // fill diagonal alignmentScores with Float.NaN
153       alignmentScores[i - 1][i - 1] = Float.NaN;
154       for (int j = 0; j < i; j++)
155       {
156         AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
157                 seqStrings[j], type, GAP_OPEN_COST, GAP_EXTEND_COST);
158
159         if (as.s1str.length() == 0 || as.s2str.length() == 0)
160         {
161           continue;
162         }
163
164         as.calcScoreMatrix();
165         if (endGaps)
166         {
167           as.traceAlignmentWithEndGaps();
168         }
169         else
170         {
171           as.traceAlignment();
172         }
173         as.scoreAlignment();
174
175         if (!first)
176         {
177           jalview.bin.Console.outPrintln(DASHES);
178           textarea.append(DASHES);
179           sb.append(DASHES);
180         }
181         first = false;
182         if (discardAlignments) {
183           as.printAlignment(System.out);
184         }
185         scores[i][j] = as.getMaxScore() / as.getASeq1().length;
186         alignmentScores[i][j] = as.getAlignmentScore();
187         totscore = totscore + scores[i][j];
188         if (suppressTextbox)
189         {
190           textarea.append(as.getOutput());
191           sb.append(as.getOutput());
192         }
193         if (discardAlignments)
194         {
195           sequences.add(as.getAlignedSeq1());
196           sequences.add(as.getAlignedSeq2());
197         }
198         firePropertyChange(PROGRESS, progress, ++progress);
199       }
200     }
201     alignmentScores[count - 1][count - 1] = Float.NaN;
202
203     this.scores = scores;
204     this.alignmentScores = alignmentScores;
205
206     if (count > 2)
207     {
208       printScoreMatrix(seqs, scores, totscore);
209     }
210
211     alignmentOutput = sb.toString();
212   }
213
214   public float[][] getScores()
215   {
216     return this.scores;
217   }
218
219   public float[][] getAlignmentScores()
220   {
221     return this.alignmentScores;
222   }
223
224   public String getAlignmentOutput()
225   {
226     return this.alignmentOutput;
227   }
228
229   /**
230    * Prints a matrix of seqi-seqj pairwise alignment scores to sysout
231    * 
232    * @param seqs
233    * @param scores
234    * @param totscore
235    */
236   protected void printScoreMatrix(SequenceI[] seqs, float[][] scores,
237           double totscore)
238   {
239     System.out
240             .println("Pairwise alignment scaled similarity score matrix\n");
241
242     for (int i = 0; i < seqs.length; i++)
243     {
244       jalview.bin.Console.outPrintln(
245               String.format("%3d %s", i + 1, seqs[i].getDisplayId(true)));
246     }
247
248     /*
249      * table heading columns for sequences 1, 2, 3...
250      */
251     System.out.print("\n ");
252     for (int i = 0; i < seqs.length; i++)
253     {
254       System.out.print(String.format("%7d", i + 1));
255     }
256     jalview.bin.Console.outPrintln();
257
258     for (int i = 0; i < seqs.length; i++)
259     {
260       System.out.print(String.format("%3d", i + 1));
261       for (int j = 0; j < i; j++)
262       {
263         /*
264          * as a fraction of tot score, outputs are 0 <= score <= 1
265          */
266         System.out.print(String.format("%7.3f", scores[i][j] / totscore));
267       }
268       jalview.bin.Console.outPrintln();
269     }
270
271     jalview.bin.Console.outPrintln("\n");
272   }
273
274   /**
275    * DOCUMENT ME!
276    * 
277    * @param e
278    *          DOCUMENT ME!
279    */
280   @Override
281   protected void viewInEditorButton_actionPerformed(ActionEvent e)
282   {
283     SequenceI[] seq = new SequenceI[sequences.size()];
284
285     for (int i = 0; i < sequences.size(); i++)
286     {
287       seq[i] = sequences.elementAt(i);
288     }
289
290     AlignFrame af = new AlignFrame(new Alignment(seq),
291             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
292
293     Desktop.addInternalFrame(af,
294             MessageManager.getString("label.pairwise_aligned_sequences"),
295             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
296   }
297
298   public long getTotal()
299   {
300     return total;
301   }
302
303   public long getProgress()
304   {
305     return progress;
306   }
307 }