0b4987c5eb112581a58f159c084893bff8ba3343
[jalview.git] / src / jalview / appletgui / RedundancyPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.appletgui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import jalview.commands.*;
26 import jalview.datamodel.*;
27
28 public class RedundancyPanel extends SliderPanel implements Runnable,
29         WindowListener
30 {
31   Stack historyList = new Stack(); // simpler than synching with alignFrame.
32
33   float[] redundancy;
34
35   SequenceI[] originalSequences;
36
37   Frame frame;
38
39   Vector redundantSeqs;
40
41   public RedundancyPanel(AlignmentPanel ap)
42   {
43     super(ap, 0, false, null);
44
45     redundantSeqs = new Vector();
46     this.ap = ap;
47     undoButton.setVisible(true);
48     applyButton.setVisible(true);
49     allGroupsCheck.setVisible(false);
50
51     label.setText("Enter the redundancy threshold");
52     valueField.setText("100");
53
54     slider.setVisibleAmount(1);
55     slider.setMinimum(0);
56     slider.setMaximum(100 + slider.getVisibleAmount());
57     slider.setValue(100);
58
59     slider.addAdjustmentListener(new AdjustmentListener()
60     {
61       public void adjustmentValueChanged(AdjustmentEvent evt)
62       {
63         valueField.setText(slider.getValue() + "");
64         sliderValueChanged();
65       }
66     });
67
68     frame = new Frame();
69     frame.add(this);
70     jalview.bin.JalviewLite.addFrame(frame,
71             "Redundancy threshold selection", 400, 100);
72
73     frame.addWindowListener(this);
74
75     Thread worker = new Thread(this);
76     worker.start();
77   }
78
79   /**
80    * This is a copy of remove redundancy in jalivew.datamodel.Alignment except
81    * we dont want to remove redundancy, just calculate once so we can use the
82    * slider to dynamically hide redundant sequences
83    * 
84    * @param threshold
85    *          DOCUMENT ME!
86    * @param sel
87    *          DOCUMENT ME!
88    * 
89    * @return DOCUMENT ME!
90    */
91   public void run()
92   {
93     label.setText("Calculating....");
94
95     slider.setVisible(false);
96     applyButton.setEnabled(false);
97     valueField.setVisible(false);
98
99     validate();
100
101     String[] omitHidden = null;
102
103     SequenceGroup sg = ap.av.getSelectionGroup();
104     int height;
105
106     int start, end;
107
108     if ((sg != null) && (sg.getSize() >= 1))
109     {
110       originalSequences = sg.getSequencesInOrder(ap.av.getAlignment());
111       start = sg.getStartRes();
112       end = sg.getEndRes();
113     }
114     else
115     {
116       originalSequences = ap.av.getAlignment().getSequencesArray();
117       start = 0;
118       end = ap.av.getAlignment().getWidth();
119     }
120
121     height = originalSequences.length;
122
123     redundancy = new float[height];
124     for (int i = 0; i < height; i++)
125     {
126       redundancy[i] = 0f;
127     }
128
129     // if (ap.av.hasHiddenColumns)
130     {
131       // omitHidden = ap.av.getSelectionAsString();
132     }
133
134     // long start = System.currentTimeMillis();
135
136     float pid;
137     String seqi, seqj;
138     for (int i = 0; i < height; i++)
139     {
140       for (int j = 0; j < i; j++)
141       {
142         if (i == j)
143         {
144           continue;
145         }
146
147         if (omitHidden == null)
148         {
149           seqi = originalSequences[i].getSequenceAsString(start, end);
150           seqj = originalSequences[j].getSequenceAsString(start, end);
151         }
152         else
153         {
154           seqi = omitHidden[i];
155           seqj = omitHidden[j];
156         }
157
158         pid = jalview.util.Comparison.PID(seqi, seqj);
159
160         if (seqj.length() < seqi.length())
161         {
162           redundancy[j] = Math.max(pid, redundancy[j]);
163         }
164         else
165         {
166           redundancy[i] = Math.max(pid, redundancy[i]);
167         }
168
169       }
170     }
171
172     label.setText("Enter the redundancy threshold");
173     slider.setVisible(true);
174     applyButton.setEnabled(true);
175     valueField.setVisible(true);
176
177     validate();
178     // System.out.println("blob done "+ (System.currentTimeMillis()-start));
179   }
180
181   void sliderValueChanged()
182   {
183     if (redundancy == null)
184     {
185       return;
186     }
187
188     float value = slider.getValue();
189
190     for (int i = 0; i < redundancy.length; i++)
191     {
192       if (value > redundancy[i])
193       {
194         redundantSeqs.removeElement(originalSequences[i]);
195       }
196       else if (!redundantSeqs.contains(originalSequences[i]))
197       {
198         redundantSeqs.addElement(originalSequences[i]);
199       }
200     }
201
202     ap.idPanel.idCanvas.setHighlighted(redundantSeqs);
203     PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
204
205   }
206
207   public void applyButton_actionPerformed()
208   {
209     Vector del = new Vector();
210
211     undoButton.setEnabled(true);
212
213     float value = slider.getValue();
214     SequenceGroup sg = ap.av.getSelectionGroup();
215
216     for (int i = 0; i < redundancy.length; i++)
217     {
218       if (value <= redundancy[i])
219       {
220         del.addElement(originalSequences[i]);
221       }
222     }
223
224     // This has to be done before the restoreHistoryItem method of alignFrame
225     // will
226     // actually restore these sequences.
227     if (del.size() > 0)
228     {
229       SequenceI[] deleted = new SequenceI[del.size()];
230
231       int width = 0;
232       for (int i = 0; i < del.size(); i++)
233       {
234         deleted[i] = (SequenceI) del.elementAt(i);
235         if (deleted[i].getLength() > width)
236         {
237           width = deleted[i].getLength();
238         }
239       }
240
241       EditCommand cut = new EditCommand("Remove Redundancy",
242               EditCommand.CUT, deleted, 0, width, ap.av.getAlignment());
243       AlignmentI alignment=ap.av.getAlignment();
244       for (int i = 0; i < del.size(); i++)
245       {
246         alignment.deleteSequence(deleted[i]);
247         PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
248         if (sg != null)
249         {
250           sg.deleteSequence(deleted[i], false);
251         }
252       }
253
254       historyList.push(cut);
255
256       ap.alignFrame.addHistoryItem(cut);
257
258       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
259               .getSequences());
260     }
261
262   }
263
264   public void undoButton_actionPerformed()
265   {
266     CommandI command = (CommandI) historyList.pop();
267     command.undoCommand(null);
268
269     if (ap.av.historyList.contains(command))
270     {
271       ap.av.historyList.removeElement(command);
272       ap.alignFrame.updateEditMenuBar();
273     }
274
275     ap.paintAlignment(true);
276
277     if (historyList.size() == 0)
278     {
279       undoButton.setEnabled(false);
280     }
281   }
282
283   public void valueField_actionPerformed(ActionEvent e)
284   {
285     try
286     {
287       int i = Integer.parseInt(valueField.getText());
288       slider.setValue(i);
289     } catch (Exception ex)
290     {
291       valueField.setText(slider.getValue() + "");
292     }
293   }
294
295   public void windowOpened(WindowEvent evt)
296   {
297   }
298
299   public void windowClosing(WindowEvent evt)
300   {
301     ap.idPanel.idCanvas.setHighlighted(null);
302   }
303
304   public void windowClosed(WindowEvent evt)
305   {
306   }
307
308   public void windowActivated(WindowEvent evt)
309   {
310   }
311
312   public void windowDeactivated(WindowEvent evt)
313   {
314   }
315
316   public void windowIconified(WindowEvent evt)
317   {
318   }
319
320   public void windowDeiconified(WindowEvent evt)
321   {
322   }
323 }