History is per viewport
[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         // This has to be done before the restoreHistoryItem method of alignFrame will\r
243         // actually restore these sequences.\r
244         if (del.size() > 0)\r
245         {\r
246           SequenceI [] deleted = new SequenceI[del.size()];\r
247 \r
248           int width = 0;\r
249           for (int i = 0; i < del.size(); i++)\r
250           {\r
251             deleted[i] = (SequenceI)del.elementAt(i);\r
252             if(deleted[i].getLength()>width)\r
253               width = deleted[i].getLength();\r
254           }\r
255 \r
256           EditCommand cut = new EditCommand("Remove Redundancy",\r
257               EditCommand.CUT, deleted,0,width,ap.av.alignment);\r
258 \r
259           for (int i = 0; i < del.size(); i++)\r
260           {\r
261             ap.av.alignment.deleteSequence( deleted[i] );\r
262             PaintRefresher.Refresh(this,\r
263                                    ap.av.getSequenceSetId(),\r
264                                    true,\r
265                                    true);\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.alignFrame.addHistoryItem(cut);\r
275 \r
276           ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences());\r
277         }\r
278 \r
279 \r
280     }\r
281 \r
282 \r
283     /**\r
284      * DOCUMENT ME!\r
285      *\r
286      * @param e DOCUMENT ME!\r
287      */\r
288     public void undoButton_actionPerformed(ActionEvent e)\r
289     {\r
290       CommandI command = (CommandI) historyList.pop();\r
291       command.undoCommand();\r
292 \r
293       if (ap.av.historyList.contains(command))\r
294       {\r
295         ap.av.historyList.remove(command);\r
296         af.updateEditMenuBar();\r
297       }\r
298 \r
299       ap.repaint();\r
300 \r
301       if (historyList.size() == 0)\r
302       {\r
303         undoButton.setEnabled(false);\r
304       }\r
305     }\r
306 \r
307     /**\r
308      * DOCUMENT ME!\r
309      *\r
310      * @param e DOCUMENT ME!\r
311      */\r
312     public void valueField_actionPerformed(ActionEvent e)\r
313     {\r
314         try\r
315         {\r
316             int i = Integer.parseInt(valueField.getText());\r
317             slider.setValue(i);\r
318         }\r
319         catch (Exception ex)\r
320         {\r
321             valueField.setText(slider.getValue() + "");\r
322         }\r
323     }\r
324 \r
325 \r
326 }\r