Use selection area with hidden columns in calculations
[jalview.git] / src / jalview / gui / RedundancyPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 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 jalview.datamodel.*;\r
22 \r
23 import jalview.jbgui.*;\r
24 \r
25 import java.awt.event.*;\r
26 \r
27 import java.util.*;\r
28 \r
29 import javax.swing.event.*;\r
30 import jalview.util.Comparison;\r
31 import javax.swing.*;\r
32 \r
33 \r
34 /**\r
35  * DOCUMENT ME!\r
36  *\r
37  * @author $author$\r
38  * @version $Revision$\r
39  */\r
40 public class RedundancyPanel extends GSliderPanel implements Runnable\r
41 {\r
42     AlignFrame af;\r
43     AlignmentPanel ap;\r
44     Stack historyList = new Stack(); // simpler than synching with alignFrame.\r
45     float [] redundancy;\r
46     SequenceI [] originalSequences;\r
47     Hashtable originalColours;\r
48     JInternalFrame frame;\r
49 \r
50     /**\r
51      * Creates a new RedundancyPanel object.\r
52      *\r
53      * @param ap DOCUMENT ME!\r
54      * @param af DOCUMENT ME!\r
55      */\r
56     public RedundancyPanel(AlignmentPanel ap, AlignFrame af)\r
57     {\r
58         this.ap = ap;\r
59         this.af = af;\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(60);\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                 resetColours();\r
88               }\r
89             }\r
90             );\r
91 \r
92     }\r
93 \r
94 \r
95     /**\r
96      * This is a copy of remove redundancy in jalivew.datamodel.Alignment\r
97      * except we dont want to remove redundancy, just calculate once\r
98      * so we can use the slider to dynamically hide redundant sequences\r
99      *\r
100      * @param threshold DOCUMENT ME!\r
101      * @param sel DOCUMENT ME!\r
102      *\r
103      * @return DOCUMENT ME!\r
104      */\r
105     public void run()\r
106     {\r
107         JProgressBar progress = new JProgressBar();\r
108         progress.setIndeterminate(true);\r
109         southPanel.add(progress, java.awt.BorderLayout.SOUTH);\r
110 \r
111         label.setText("Calculating....");\r
112 \r
113         slider.setVisible(false);\r
114         applyButton.setEnabled(false);\r
115         valueField.setVisible(false);\r
116 \r
117         validate();\r
118 \r
119         String[] omitHidden = null;\r
120 \r
121         SequenceGroup sg = ap.av.getSelectionGroup();\r
122         int height;\r
123 \r
124         originalColours = new Hashtable();\r
125         int start, end;\r
126 \r
127         if ( (sg != null) && (sg.getSize(false) >= 1))\r
128         {\r
129            originalSequences = sg.getSequencesInOrder(ap.av.alignment);\r
130            start = sg.getStartRes();\r
131            end = sg.getEndRes();\r
132         }\r
133         else\r
134         {\r
135           originalSequences = ap.av.alignment.getSequencesArray();\r
136           start = 0;\r
137           end = ap.av.alignment.getWidth();\r
138         }\r
139 \r
140         height = originalSequences.length;\r
141 \r
142         redundancy = new float[height];\r
143         for (int i = 0; i < height; i++)\r
144         {\r
145           redundancy[i] = 0f;\r
146         }\r
147 \r
148         if (ap.av.hasHiddenColumns)\r
149         {\r
150           omitHidden = ap.av.getSelectionAsString();\r
151         }\r
152 \r
153 \r
154        // long start = System.currentTimeMillis();\r
155 \r
156         float pid;\r
157         String seqi, seqj;\r
158         for (int i = 0; i < height; i++)\r
159         {\r
160             originalColours.put(originalSequences[i],\r
161                                originalSequences[i].getColor());\r
162 \r
163             for (int j = 0; j < i; j++)\r
164             {\r
165               if(i==j)\r
166                 continue;\r
167 \r
168               if(omitHidden==null)\r
169               {\r
170                 seqi = originalSequences[i].getSequence(start, end);\r
171                 seqj = originalSequences[j].getSequence(start, end);\r
172               }\r
173               else\r
174               {\r
175                 seqi = omitHidden[i];\r
176                 seqj = omitHidden[j];\r
177               }\r
178 \r
179               pid = Comparison.PID( seqi,  seqj );\r
180 \r
181               if(seqj.length() < seqi.length())\r
182                 redundancy[j] = Math.max(pid, redundancy[j]);\r
183               else\r
184                 redundancy[i] = Math.max(pid, redundancy[i]);\r
185 \r
186             }\r
187         }\r
188 \r
189         progress.setIndeterminate(false);\r
190         progress.setVisible(false);\r
191         progress = null;\r
192 \r
193         label.setText("Enter the redundancy threshold");\r
194         slider.setVisible(true);\r
195         applyButton.setEnabled(true);\r
196         valueField.setVisible(true);\r
197 \r
198         validate();\r
199        // System.out.println((System.currentTimeMillis()-start));\r
200     }\r
201 \r
202     void sliderValueChanged()\r
203     {\r
204       if(redundancy==null)\r
205         return;\r
206 \r
207       float value = slider.getValue();\r
208 \r
209       for(int i=0; i<redundancy.length; i++)\r
210       {\r
211         if (value > redundancy[i])\r
212            originalSequences[i].setColor(java.awt.Color.white);\r
213         else\r
214           originalSequences[i].setColor(java.awt.Color.red);\r
215       }\r
216 \r
217       PaintRefresher.Refresh(null,ap.av.alignment);\r
218 \r
219     }\r
220 \r
221     /**\r
222      * DOCUMENT ME!\r
223      *\r
224      * @param e DOCUMENT ME!\r
225      */\r
226     public void applyButton_actionPerformed(ActionEvent e)\r
227     {\r
228         historyList.push(new HistoryItem("Remove redundancy",\r
229                     ap.av.alignment, HistoryItem.HIDE));\r
230 \r
231         if ((historyList.size() == 1) ||\r
232                 !af.historyList.contains(historyList.firstElement()))\r
233         {\r
234             af.addHistoryItem((HistoryItem) historyList.firstElement());\r
235             af.updateEditMenuBar();\r
236         }\r
237 \r
238         Vector del = new Vector();\r
239 \r
240         undoButton.setEnabled(true);\r
241 \r
242         float value = slider.getValue();\r
243         SequenceGroup sg = ap.av.getSelectionGroup();\r
244 \r
245         for (int i = 0; i < redundancy.length; i++)\r
246         {\r
247           if (value <= redundancy[i])\r
248           {\r
249             SequenceI seq = originalSequences[i];\r
250             ap.av.alignment.deleteSequence(seq);\r
251             del.add(seq);\r
252             if (sg != null)\r
253             {\r
254               sg.deleteSequence(seq, false);\r
255             }\r
256           }\r
257         }\r
258 \r
259 \r
260         // This has to be done before the restoreHistoryItem method of alignFrame will\r
261         // actually restore these sequences.\r
262         if (del.size() > 0)\r
263         {\r
264             for (int i = 0, j = del.size(); i < j; i++)\r
265             {\r
266                 SequenceI sq = (SequenceI) del.elementAt(i);\r
267                 sq.deleteChars(0, sq.getLength());\r
268             }\r
269         }\r
270 \r
271         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences());\r
272         af.updateEditMenuBar();\r
273     }\r
274 \r
275     void resetColours()\r
276     {\r
277       for(int i=0; i<originalSequences.length; i++)\r
278       {\r
279         SequenceI seq = originalSequences[i];\r
280         seq.setColor( (java.awt.Color)originalColours.get(seq));\r
281       }\r
282 \r
283       PaintRefresher.Refresh(ap.av.alignment);\r
284     }\r
285 \r
286     /**\r
287      * DOCUMENT ME!\r
288      *\r
289      * @param e DOCUMENT ME!\r
290      */\r
291     public void undoButton_actionPerformed(ActionEvent e)\r
292     {\r
293       HistoryItem hi = (HistoryItem) historyList.pop();\r
294       af.restoreHistoryItem(hi);\r
295 \r
296       if (historyList.size() == 0)\r
297       {\r
298         undoButton.setEnabled(false);\r
299 \r
300         if (af.historyList.contains(hi))\r
301         {\r
302           af.historyList.remove(hi);\r
303           af.updateEditMenuBar();\r
304         }\r
305       }\r
306     }\r
307 \r
308     /**\r
309      * DOCUMENT ME!\r
310      *\r
311      * @param e DOCUMENT ME!\r
312      */\r
313     public void valueField_actionPerformed(ActionEvent e)\r
314     {\r
315         try\r
316         {\r
317             int i = Integer.parseInt(valueField.getText());\r
318             slider.setValue(i);\r
319         }\r
320         catch (Exception ex)\r
321         {\r
322             valueField.setText(slider.getValue() + "");\r
323         }\r
324     }\r
325 \r
326 \r
327 }\r