Must set alignIndex before delete takes place
[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 import jalview.jbgui.*;\r
23 import jalview.util.Comparison;\r
24 import jalview.commands.*;\r
25 \r
26 import java.awt.event.*;\r
27 \r
28 import java.util.*;\r
29 \r
30 import javax.swing.event.*;\r
31 \r
32 import javax.swing.*;\r
33 \r
34 \r
35 /**\r
36  * DOCUMENT ME!\r
37  *\r
38  * @author $author$\r
39  * @version $Revision$\r
40  */\r
41 public class RedundancyPanel extends GSliderPanel implements Runnable\r
42 {\r
43     AlignFrame af;\r
44     AlignmentPanel ap;\r
45     Stack historyList = new Stack(); // simpler than synching with alignFrame.\r
46     float [] redundancy;\r
47     SequenceI [] originalSequences;\r
48     JInternalFrame frame;\r
49     Vector redundantSeqs;\r
50 \r
51     /**\r
52      * Creates a new RedundancyPanel object.\r
53      *\r
54      * @param ap DOCUMENT ME!\r
55      * @param af DOCUMENT ME!\r
56      */\r
57     public RedundancyPanel(final AlignmentPanel ap, AlignFrame af)\r
58     {\r
59         this.ap = ap;\r
60         this.af = af;\r
61         redundantSeqs = new Vector();\r
62 \r
63         slider.addChangeListener(new ChangeListener()\r
64             {\r
65                 public void stateChanged(ChangeEvent evt)\r
66                 {\r
67                     valueField.setText(slider.getValue() + "");\r
68                     sliderValueChanged();\r
69                 }\r
70             });\r
71 \r
72         applyButton.setText("Remove");\r
73         allGroupsCheck.setVisible(false);\r
74         slider.setMinimum(0);\r
75         slider.setMaximum(100);\r
76         slider.setValue(100);\r
77 \r
78         Thread worker = new Thread(this);\r
79         worker.start();\r
80 \r
81         frame = new JInternalFrame();\r
82         frame.setContentPane(this);\r
83         Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400,\r
84                          100, false);\r
85         frame.addInternalFrameListener(new InternalFrameAdapter()\r
86             {\r
87               public void internalFrameClosing(InternalFrameEvent evt)\r
88               {\r
89                ap.idPanel.idCanvas.setHighlighted(null);\r
90               }\r
91             }\r
92             );\r
93 \r
94     }\r
95 \r
96 \r
97     /**\r
98      * This is a copy of remove redundancy in jalivew.datamodel.Alignment\r
99      * except we dont want to remove redundancy, just calculate once\r
100      * so we can use the slider to dynamically hide redundant sequences\r
101      *\r
102      * @param threshold DOCUMENT ME!\r
103      * @param sel DOCUMENT ME!\r
104      *\r
105      * @return DOCUMENT ME!\r
106      */\r
107     public void run()\r
108     {\r
109         JProgressBar progress = new JProgressBar();\r
110         progress.setIndeterminate(true);\r
111         southPanel.add(progress, java.awt.BorderLayout.SOUTH);\r
112 \r
113         label.setText("Calculating....");\r
114 \r
115         slider.setVisible(false);\r
116         applyButton.setEnabled(false);\r
117         valueField.setVisible(false);\r
118 \r
119         validate();\r
120 \r
121         String[] omitHidden = null;\r
122 \r
123         SequenceGroup sg = ap.av.getSelectionGroup();\r
124         int height;\r
125 \r
126         int start, end;\r
127 \r
128         if ( (sg != null) && (sg.getSize(false) >= 1))\r
129         {\r
130            originalSequences = sg.getSequencesInOrder(ap.av.alignment);\r
131            start = sg.getStartRes();\r
132            end = sg.getEndRes();\r
133         }\r
134         else\r
135         {\r
136           originalSequences = ap.av.alignment.getSequencesArray();\r
137           start = 0;\r
138           end = ap.av.alignment.getWidth();\r
139         }\r
140 \r
141         height = originalSequences.length;\r
142 \r
143         redundancy = new float[height];\r
144         for (int i = 0; i < height; i++)\r
145         {\r
146           redundancy[i] = 0f;\r
147         }\r
148 \r
149         if (ap.av.hasHiddenColumns)\r
150         {\r
151           omitHidden = ap.av.getViewAsString(sg!=null);\r
152         }\r
153 \r
154 \r
155        // long start = System.currentTimeMillis();\r
156 \r
157         float pid;\r
158         String seqi, seqj;\r
159         for (int i = 0; i < height; i++)\r
160         {\r
161 \r
162             for (int j = 0; j < i; j++)\r
163             {\r
164               if(i==j)\r
165                 continue;\r
166 \r
167               if(omitHidden==null)\r
168               {\r
169                 seqi = originalSequences[i].getSequence(start, end);\r
170                 seqj = originalSequences[j].getSequence(start, end);\r
171               }\r
172               else\r
173               {\r
174                 seqi = omitHidden[i];\r
175                 seqj = omitHidden[j];\r
176               }\r
177 \r
178               pid = Comparison.PID( seqi,  seqj );\r
179 \r
180               if(seqj.length() < seqi.length())\r
181                 redundancy[j] = Math.max(pid, redundancy[j]);\r
182               else\r
183                 redundancy[i] = Math.max(pid, redundancy[i]);\r
184 \r
185             }\r
186         }\r
187 \r
188         progress.setIndeterminate(false);\r
189         progress.setVisible(false);\r
190         progress = null;\r
191 \r
192         label.setText("Enter the redundancy threshold");\r
193         slider.setVisible(true);\r
194         applyButton.setEnabled(true);\r
195         valueField.setVisible(true);\r
196 \r
197         validate();\r
198        // System.out.println((System.currentTimeMillis()-start));\r
199     }\r
200 \r
201     void sliderValueChanged()\r
202     {\r
203       if(redundancy==null)\r
204         return;\r
205 \r
206       float value = slider.getValue();\r
207 \r
208       for(int i=0; i<redundancy.length; i++)\r
209       {\r
210         if (value > redundancy[i])\r
211           redundantSeqs.remove(originalSequences[i]);\r
212         else if(!redundantSeqs.contains(originalSequences[i]))\r
213           redundantSeqs.add(originalSequences[i]);\r
214 \r
215       }\r
216 \r
217       ap.idPanel.idCanvas.setHighlighted(redundantSeqs);\r
218     }\r
219 \r
220     /**\r
221      * DOCUMENT ME!\r
222      *\r
223      * @param e DOCUMENT ME!\r
224      */\r
225     public void applyButton_actionPerformed(ActionEvent e)\r
226     {\r
227         Vector del = new Vector();\r
228 \r
229         undoButton.setEnabled(true);\r
230 \r
231         float value = slider.getValue();\r
232         SequenceGroup sg = ap.av.getSelectionGroup();\r
233 \r
234         for (int i = 0; i < redundancy.length; i++)\r
235         {\r
236           if (value <= redundancy[i])\r
237           {\r
238             del.addElement(originalSequences[i]);\r
239           }\r
240         }\r
241 \r
242 \r
243         // This has to be done before the restoreHistoryItem method of alignFrame will\r
244         // actually restore these sequences.\r
245         if (del.size() > 0)\r
246         {\r
247           SequenceI [] deleted = new SequenceI[del.size()];\r
248 \r
249           int width = 0;\r
250           for (int i = 0; i < del.size(); i++)\r
251           {\r
252             deleted[i] = (SequenceI)del.elementAt(i);\r
253             if(deleted[i].getLength()>width)\r
254               width = deleted[i].getLength();\r
255           }\r
256 \r
257           EditCommand cut = new EditCommand("Remove Redundancy",\r
258               EditCommand.CUT, deleted,0,width,ap.av.alignment);\r
259 \r
260           for (int i = 0; i < del.size(); i++)\r
261           {\r
262             ap.av.alignment.deleteSequence( deleted[i] );\r
263             PaintRefresher.Refresh(this,\r
264                                    ap.av.getSequenceSetId(),\r
265                                    deleted[i], null);\r
266             if (sg != null)\r
267             {\r
268               sg.deleteSequence(deleted[i], false);\r
269             }\r
270           }\r
271 \r
272           historyList.push(cut);\r
273 \r
274           ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences());\r
275         }\r
276 \r
277 \r
278     }\r
279 \r
280 \r
281     /**\r
282      * DOCUMENT ME!\r
283      *\r
284      * @param e DOCUMENT ME!\r
285      */\r
286     public void undoButton_actionPerformed(ActionEvent e)\r
287     {\r
288       CommandI command = (CommandI) historyList.pop();\r
289       command.undoCommand();\r
290 \r
291       ap.repaint();\r
292 \r
293       if (historyList.size() == 0)\r
294       {\r
295         undoButton.setEnabled(false);\r
296       }\r
297     }\r
298 \r
299     /**\r
300      * DOCUMENT ME!\r
301      *\r
302      * @param e DOCUMENT ME!\r
303      */\r
304     public void valueField_actionPerformed(ActionEvent e)\r
305     {\r
306         try\r
307         {\r
308             int i = Integer.parseInt(valueField.getText());\r
309             slider.setValue(i);\r
310         }\r
311         catch (Exception ex)\r
312         {\r
313             valueField.setText(slider.getValue() + "");\r
314         }\r
315     }\r
316 \r
317 \r
318 }\r