patch to fix occasional arrayoutofbounds exception when working with hidden columns...
[jalview.git] / src / jalview / appletgui / RedundancyPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.appletgui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25
26 import jalview.commands.*;
27 import jalview.datamodel.*;
28
29 public class RedundancyPanel extends SliderPanel implements Runnable,
30         WindowListener
31 {
32   AlignmentPanel ap;
33
34   Stack historyList = new Stack(); // simpler than synching with alignFrame.
35
36   float[] redundancy;
37
38   SequenceI[] originalSequences;
39
40   Frame frame;
41
42   Vector redundantSeqs;
43
44   public RedundancyPanel(AlignmentPanel ap)
45   {
46     super(ap, 0, false, null);
47
48     redundantSeqs = new Vector();
49     this.ap = ap;
50     undoButton.setVisible(true);
51     applyButton.setVisible(true);
52     allGroupsCheck.setVisible(false);
53
54     label.setText("Enter the redundancy threshold");
55     valueField.setText("100");
56
57     slider.setVisibleAmount(1);
58     slider.setMinimum(0);
59     slider.setMaximum(100 + slider.getVisibleAmount());
60     slider.setValue(100);
61
62     slider.addAdjustmentListener(new AdjustmentListener()
63     {
64       public void adjustmentValueChanged(AdjustmentEvent evt)
65       {
66         valueField.setText(slider.getValue() + "");
67         sliderValueChanged();
68       }
69     });
70
71     frame = new Frame();
72     frame.add(this);
73     jalview.bin.JalviewLite.addFrame(frame,
74             "Redundancy threshold selection", 400, 100);
75
76     frame.addWindowListener(this);
77
78     Thread worker = new Thread(this);
79     worker.start();
80   }
81
82   /**
83    * This is a copy of remove redundancy in jalivew.datamodel.Alignment except
84    * we dont want to remove redundancy, just calculate once so we can use the
85    * slider to dynamically hide redundant sequences
86    * 
87    * @param threshold
88    *                DOCUMENT ME!
89    * @param sel
90    *                DOCUMENT ME!
91    * 
92    * @return DOCUMENT ME!
93    */
94   public void run()
95   {
96     label.setText("Calculating....");
97
98     slider.setVisible(false);
99     applyButton.setEnabled(false);
100     valueField.setVisible(false);
101
102     validate();
103
104     String[] omitHidden = null;
105
106     SequenceGroup sg = ap.av.getSelectionGroup();
107     int height;
108
109     int start, end;
110
111     if ((sg != null) && (sg.getSize() >= 1))
112     {
113       originalSequences = sg.getSequencesInOrder(ap.av.alignment);
114       start = sg.getStartRes();
115       end = sg.getEndRes();
116     }
117     else
118     {
119       originalSequences = ap.av.alignment.getSequencesArray();
120       start = 0;
121       end = ap.av.alignment.getWidth();
122     }
123
124     height = originalSequences.length;
125
126     redundancy = new float[height];
127     for (int i = 0; i < height; i++)
128     {
129       redundancy[i] = 0f;
130     }
131
132     // if (ap.av.hasHiddenColumns)
133     {
134       // omitHidden = ap.av.getSelectionAsString();
135     }
136
137     // long start = System.currentTimeMillis();
138
139     float pid;
140     String seqi, seqj;
141     for (int i = 0; i < height; i++)
142     {
143       for (int j = 0; j < i; j++)
144       {
145         if (i == j)
146         {
147           continue;
148         }
149
150         if (omitHidden == null)
151         {
152           seqi = originalSequences[i].getSequenceAsString(start, end);
153           seqj = originalSequences[j].getSequenceAsString(start, end);
154         }
155         else
156         {
157           seqi = omitHidden[i];
158           seqj = omitHidden[j];
159         }
160
161         pid = jalview.util.Comparison.PID(seqi, seqj);
162
163         if (seqj.length() < seqi.length())
164         {
165           redundancy[j] = Math.max(pid, redundancy[j]);
166         }
167         else
168         {
169           redundancy[i] = Math.max(pid, redundancy[i]);
170         }
171
172       }
173     }
174
175     label.setText("Enter the redundancy threshold");
176     slider.setVisible(true);
177     applyButton.setEnabled(true);
178     valueField.setVisible(true);
179
180     validate();
181     // System.out.println("blob done "+ (System.currentTimeMillis()-start));
182   }
183
184   void sliderValueChanged()
185   {
186     if (redundancy == null)
187     {
188       return;
189     }
190
191     float value = slider.getValue();
192
193     for (int i = 0; i < redundancy.length; i++)
194     {
195       if (value > redundancy[i])
196       {
197         redundantSeqs.removeElement(originalSequences[i]);
198       }
199       else if (!redundantSeqs.contains(originalSequences[i]))
200       {
201         redundantSeqs.addElement(originalSequences[i]);
202       }
203     }
204
205     ap.idPanel.idCanvas.setHighlighted(redundantSeqs);
206     PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
207
208   }
209
210   public void applyButton_actionPerformed()
211   {
212     Vector del = new Vector();
213
214     undoButton.setEnabled(true);
215
216     float value = slider.getValue();
217     SequenceGroup sg = ap.av.getSelectionGroup();
218
219     for (int i = 0; i < redundancy.length; i++)
220     {
221       if (value <= redundancy[i])
222       {
223         del.addElement(originalSequences[i]);
224       }
225     }
226
227     // This has to be done before the restoreHistoryItem method of alignFrame
228     // will
229     // actually restore these sequences.
230     if (del.size() > 0)
231     {
232       SequenceI[] deleted = new SequenceI[del.size()];
233
234       int width = 0;
235       for (int i = 0; i < del.size(); i++)
236       {
237         deleted[i] = (SequenceI) del.elementAt(i);
238         if (deleted[i].getLength() > width)
239         {
240           width = deleted[i].getLength();
241         }
242       }
243
244       EditCommand cut = new EditCommand("Remove Redundancy",
245               EditCommand.CUT, deleted, 0, width, ap.av.alignment);
246
247       for (int i = 0; i < del.size(); i++)
248       {
249         ap.av.alignment.deleteSequence(deleted[i]);
250         PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
251         if (sg != null)
252         {
253           sg.deleteSequence(deleted[i], false);
254         }
255       }
256
257       historyList.push(cut);
258
259       ap.alignFrame.addHistoryItem(cut);
260
261       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
262               .getSequences());
263     }
264
265   }
266
267   public void undoButton_actionPerformed()
268   {
269     CommandI command = (CommandI) historyList.pop();
270     command.undoCommand(null);
271
272     if (ap.av.historyList.contains(command))
273     {
274       ap.av.historyList.removeElement(command);
275       ap.alignFrame.updateEditMenuBar();
276     }
277
278     ap.paintAlignment(true);
279
280     if (historyList.size() == 0)
281     {
282       undoButton.setEnabled(false);
283     }
284   }
285
286   public void valueField_actionPerformed(ActionEvent e)
287   {
288     try
289     {
290       int i = Integer.parseInt(valueField.getText());
291       slider.setValue(i);
292     } catch (Exception ex)
293     {
294       valueField.setText(slider.getValue() + "");
295     }
296   }
297
298   public void windowOpened(WindowEvent evt)
299   {
300   }
301
302   public void windowClosing(WindowEvent evt)
303   {
304     ap.idPanel.idCanvas.setHighlighted(null);
305   }
306
307   public void windowClosed(WindowEvent evt)
308   {
309   }
310
311   public void windowActivated(WindowEvent evt)
312   {
313   }
314
315   public void windowDeactivated(WindowEvent evt)
316   {
317   }
318
319   public void windowIconified(WindowEvent evt)
320   {
321   }
322
323   public void windowDeiconified(WindowEvent evt)
324   {
325   }
326 }