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