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