Multiple Views
[jalview.git] / src / jalview / gui / RedundancyPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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     JInternalFrame frame;\r
48     Vector redundantSeqs;\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(final AlignmentPanel ap, AlignFrame af)\r
57     {\r
58         this.ap = ap;\r
59         this.af = af;\r
60         redundantSeqs = new Vector();\r
61 \r
62         slider.addChangeListener(new ChangeListener()\r
63             {\r
64                 public void stateChanged(ChangeEvent evt)\r
65                 {\r
66                     valueField.setText(slider.getValue() + "");\r
67                     sliderValueChanged();\r
68                 }\r
69             });\r
70 \r
71         applyButton.setText("Remove");\r
72         allGroupsCheck.setVisible(false);\r
73         slider.setMinimum(0);\r
74         slider.setMaximum(100);\r
75         slider.setValue(100);\r
76 \r
77         Thread worker = new Thread(this);\r
78         worker.start();\r
79 \r
80         frame = new JInternalFrame();\r
81         frame.setContentPane(this);\r
82         Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400,\r
83                          100, false);\r
84         frame.addInternalFrameListener(new InternalFrameAdapter()\r
85             {\r
86               public void internalFrameClosing(InternalFrameEvent evt)\r
87               {\r
88                ap.idPanel.idCanvas.setHighlighted(null);\r
89               }\r
90             }\r
91             );\r
92 \r
93     }\r
94 \r
95 \r
96     /**\r
97      * This is a copy of remove redundancy in jalivew.datamodel.Alignment\r
98      * except we dont want to remove redundancy, just calculate once\r
99      * so we can use the slider to dynamically hide redundant sequences\r
100      *\r
101      * @param threshold DOCUMENT ME!\r
102      * @param sel DOCUMENT ME!\r
103      *\r
104      * @return DOCUMENT ME!\r
105      */\r
106     public void run()\r
107     {\r
108         JProgressBar progress = new JProgressBar();\r
109         progress.setIndeterminate(true);\r
110         southPanel.add(progress, java.awt.BorderLayout.SOUTH);\r
111 \r
112         label.setText("Calculating....");\r
113 \r
114         slider.setVisible(false);\r
115         applyButton.setEnabled(false);\r
116         valueField.setVisible(false);\r
117 \r
118         validate();\r
119 \r
120         String[] omitHidden = null;\r
121 \r
122         SequenceGroup sg = ap.av.getSelectionGroup();\r
123         int height;\r
124 \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.getViewAsString(sg!=null);\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 \r
161             for (int j = 0; j < i; j++)\r
162             {\r
163               if(i==j)\r
164                 continue;\r
165 \r
166               if(omitHidden==null)\r
167               {\r
168                 seqi = originalSequences[i].getSequence(start, end);\r
169                 seqj = originalSequences[j].getSequence(start, end);\r
170               }\r
171               else\r
172               {\r
173                 seqi = omitHidden[i];\r
174                 seqj = omitHidden[j];\r
175               }\r
176 \r
177               pid = Comparison.PID( seqi,  seqj );\r
178 \r
179               if(seqj.length() < seqi.length())\r
180                 redundancy[j] = Math.max(pid, redundancy[j]);\r
181               else\r
182                 redundancy[i] = Math.max(pid, redundancy[i]);\r
183 \r
184             }\r
185         }\r
186 \r
187         progress.setIndeterminate(false);\r
188         progress.setVisible(false);\r
189         progress = null;\r
190 \r
191         label.setText("Enter the redundancy threshold");\r
192         slider.setVisible(true);\r
193         applyButton.setEnabled(true);\r
194         valueField.setVisible(true);\r
195 \r
196         validate();\r
197        // System.out.println((System.currentTimeMillis()-start));\r
198     }\r
199 \r
200     void sliderValueChanged()\r
201     {\r
202       if(redundancy==null)\r
203         return;\r
204 \r
205       float value = slider.getValue();\r
206 \r
207       for(int i=0; i<redundancy.length; i++)\r
208       {\r
209         if (value > redundancy[i])\r
210           redundantSeqs.remove(originalSequences[i]);\r
211         else if(!redundantSeqs.contains(originalSequences[i]))\r
212           redundantSeqs.add(originalSequences[i]);\r
213 \r
214       }\r
215 \r
216       ap.idPanel.idCanvas.setHighlighted(redundantSeqs);\r
217     }\r
218 \r
219     /**\r
220      * DOCUMENT ME!\r
221      *\r
222      * @param e DOCUMENT ME!\r
223      */\r
224     public void applyButton_actionPerformed(ActionEvent e)\r
225     {\r
226         historyList.push(new HistoryItem("Remove redundancy",\r
227                     ap.av.alignment, HistoryItem.HIDE));\r
228 \r
229         if ((historyList.size() == 1) ||\r
230                 !af.historyList.contains(historyList.firstElement()))\r
231         {\r
232             af.addHistoryItem((HistoryItem) historyList.firstElement());\r
233             af.updateEditMenuBar();\r
234         }\r
235 \r
236         Vector del = new Vector();\r
237 \r
238         undoButton.setEnabled(true);\r
239 \r
240         float value = slider.getValue();\r
241         SequenceGroup sg = ap.av.getSelectionGroup();\r
242 \r
243         for (int i = 0; i < redundancy.length; i++)\r
244         {\r
245           if (value <= redundancy[i])\r
246           {\r
247             SequenceI seq = originalSequences[i];\r
248             ap.av.alignment.deleteSequence(seq);\r
249             PaintRefresher.Refresh(this,ap.av.getSequenceSetId(),seq,null);\r
250             del.add(seq);\r
251             if (sg != null)\r
252             {\r
253               sg.deleteSequence(seq, false);\r
254             }\r
255           }\r
256         }\r
257 \r
258 \r
259         // This has to be done before the restoreHistoryItem method of alignFrame will\r
260         // actually restore these sequences.\r
261         if (del.size() > 0)\r
262         {\r
263             for (int i = 0, j = del.size(); i < j; i++)\r
264             {\r
265                 SequenceI sq = (SequenceI) del.elementAt(i);\r
266                 sq.deleteChars(0, sq.getLength());\r
267             }\r
268         }\r
269 \r
270         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences());\r
271         af.updateEditMenuBar();\r
272     }\r
273 \r
274 \r
275     /**\r
276      * DOCUMENT ME!\r
277      *\r
278      * @param e DOCUMENT ME!\r
279      */\r
280     public void undoButton_actionPerformed(ActionEvent e)\r
281     {\r
282       HistoryItem hi = (HistoryItem) historyList.pop();\r
283       af.restoreHistoryItem(hi);\r
284 \r
285       if (historyList.size() == 0)\r
286       {\r
287         undoButton.setEnabled(false);\r
288 \r
289         if (af.historyList.contains(hi))\r
290         {\r
291           af.historyList.remove(hi);\r
292           af.updateEditMenuBar();\r
293         }\r
294       }\r
295     }\r
296 \r
297     /**\r
298      * DOCUMENT ME!\r
299      *\r
300      * @param e DOCUMENT ME!\r
301      */\r
302     public void valueField_actionPerformed(ActionEvent e)\r
303     {\r
304         try\r
305         {\r
306             int i = Integer.parseInt(valueField.getText());\r
307             slider.setValue(i);\r
308         }\r
309         catch (Exception ex)\r
310         {\r
311             valueField.setText(slider.getValue() + "");\r
312         }\r
313     }\r
314 \r
315 \r
316 }\r