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