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