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