2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.analysis.AlignSeq;
24 import jalview.commands.CommandI;
25 import jalview.commands.EditCommand;
26 import jalview.commands.EditCommand.Action;
27 import jalview.datamodel.SequenceGroup;
28 import jalview.datamodel.SequenceI;
29 import jalview.jbgui.GSliderPanel;
30 import jalview.util.MessageManager;
32 import java.awt.Color;
33 import java.awt.event.ActionEvent;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Stack;
38 import java.util.Vector;
40 import javax.swing.JInternalFrame;
41 import javax.swing.JProgressBar;
42 import javax.swing.event.ChangeEvent;
43 import javax.swing.event.ChangeListener;
44 import javax.swing.event.InternalFrameAdapter;
45 import javax.swing.event.InternalFrameEvent;
53 public class RedundancyPanel extends GSliderPanel implements Runnable
59 Stack<CommandI> historyList = new Stack<CommandI>();
61 // simpler than synching with alignFrame.
65 SequenceI[] originalSequences;
71 private SequenceI[] redreps;
74 * Creates a new RedundancyPanel object.
81 public RedundancyPanel(final AlignmentPanel ap, AlignFrame af)
85 redundantSeqs = new Vector();
87 slider.addChangeListener(new ChangeListener()
90 public void stateChanged(ChangeEvent evt)
92 valueField.setText(slider.getValue() + "");
97 applyButton.setText(MessageManager.getString("action.hide"));
98 allGroupsCheck.setVisible(false);
100 slider.setMaximum(100);
101 slider.setValue(100);
103 Thread worker = new Thread(this);
106 frame = new JInternalFrame();
107 frame.setContentPane(this);
108 Desktop.addInternalFrame(frame, MessageManager
109 .getString("label.redundancy_threshold_selection"), 400, 100,
111 frame.addInternalFrameListener(new InternalFrameAdapter()
114 public void internalFrameClosing(InternalFrameEvent evt)
116 ap.getIdPanel().getIdCanvas().setHighlighted(null);
123 * This is a copy of remove redundancy in jalivew.datamodel.Alignment except
124 * we dont want to remove redundancy, just calculate once so we can use the
125 * slider to dynamically hide redundant sequences
132 * @return DOCUMENT ME!
137 JProgressBar progress = new JProgressBar();
138 progress.setIndeterminate(true);
139 southPanel.add(progress, java.awt.BorderLayout.SOUTH);
141 label.setText(MessageManager.getString("label.calculating"));
143 slider.setVisible(false);
144 applyButton.setEnabled(false);
145 valueField.setVisible(false);
149 String[] omitHidden = null;
151 SequenceGroup sg = ap.av.getSelectionGroup();
156 if ((sg != null) && (sg.getSize() >= 1))
158 originalSequences = sg.getSequencesInOrder(ap.av.getAlignment());
159 start = sg.getStartRes();
160 end = sg.getEndRes();
164 originalSequences = ap.av.getAlignment().getSequencesArray();
166 end = ap.av.getAlignment().getWidth();
169 height = originalSequences.length;
170 if (ap.av.hasHiddenColumns())
172 omitHidden = ap.av.getViewAsString(sg != null);
174 Object rr[] = AlignSeq.computeRedundancyMatrixWithRep(
176 omitHidden, start, end, false);
178 redundancy = (float[]) rr[0];
179 redreps = (SequenceI[]) rr[1];
181 progress.setIndeterminate(false);
182 progress.setVisible(false);
185 label.setText(MessageManager
186 .getString("label.enter_redundancy_thereshold"));
187 slider.setVisible(true);
188 applyButton.setEnabled(true);
189 valueField.setVisible(true);
192 sliderValueChanged();
193 // System.out.println((System.currentTimeMillis()-start));
196 void sliderValueChanged()
198 if (redundancy == null)
203 float value = slider.getValue();
204 List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
205 for (int i = 0; i < redundancy.length; i++)
207 if (value <= redundancy[i])
209 redundantSequences.add(originalSequences[i]);
212 ap.getIdPanel().getIdCanvas().setHighlighted(redundantSequences);
222 public void applyButton_actionPerformed(ActionEvent e)
225 undoButton.setEnabled(true);
227 float value = slider.getValue();
228 SequenceGroup sg = ap.av.getSelectionGroup();
229 // delete_seqs(value, sg);
230 hide_seqs(value, sg);
232 private void hide_seqs(float value, SequenceGroup sg)
235 * hash to look up the representative for a sequence
237 HashMap<SequenceI, SequenceI> rep = new HashMap<SequenceI, SequenceI>();
239 * hash to collect lists of sequences represented by a sequence
241 HashMap<SequenceI, SequenceGroup> reps = new HashMap<SequenceI, SequenceGroup>();
242 for (int i = 0; i < redundancy.length; i++)
244 if (value <= redundancy[i])
246 // does this sequence represent other sequences ?
247 SequenceGroup repset;
248 // is the representative also redundant ?
249 SequenceI repForI = rep.get(redreps[i]);
251 // the representative is still in the alignment.
252 // is it representing anything already ?
253 repset = reps.get(redreps[i]);
256 repset = new SequenceGroup();
258 repset.addSequence(originalSequences[i], false);
259 rep.put(originalSequences[i], redreps[i]);
260 reps.put(redreps[i], repset);
261 // and save the representative sequence for originalSeq
262 repForI = redreps[i];
264 // already hidden the representative for this sequence, so look up its redundant peers
265 repset = reps.get(repForI);
268 throw new Error("Implementation failure for redundancy set creation");
270 // add the sequence to the peerset, and mark sequence's representative in hash
271 repset.addSequence(originalSequences[i], false);
272 rep.put(originalSequences[i], repForI);
274 // merge any sequences represented by this with its new containing group
275 SequenceGroup existingreps = reps.remove(originalSequences[i]);
276 if (existingreps!=null)
278 for (SequenceI sq:existingreps.getSequences())
280 rep.put(sq, repForI);
281 repset.addSequence(sq, false);
286 int s = 0, e = ap.av.getAlignment().getWidth();
289 s = sg.getStartRes();
292 List<SequenceGroup> sgs = new ArrayList<SequenceGroup>();
293 for (SequenceI repseq: reps.keySet())
295 sg = reps.get(repseq);
296 sg.addSequence(repseq, false);
297 sg.setSeqrep(repseq);
302 ap.alignFrame.avc.showRandomColoursForGroups(sgs);
303 for (SequenceI repseq : reps.keySet())
305 sg = reps.get(repseq);
306 ap.av.hideRepSequences(repseq, sg);
310 private void delete_seqs(float value, SequenceGroup sg)
312 ArrayList<SequenceI> del = new ArrayList<SequenceI>();
314 for (int i = 0; i < redundancy.length; i++)
316 if (value <= redundancy[i])
318 del.add(originalSequences[i]);
321 // This has to be done before the restoreHistoryItem method of alignFrame
323 // actually restore these sequences.
326 SequenceI[] deleted = new SequenceI[del.size()];
329 for (int i = 0; i < del.size(); i++)
331 deleted[i] = del.get(i);
332 if (deleted[i].getLength() > width)
334 width = deleted[i].getLength();
338 EditCommand cut = new EditCommand(
339 MessageManager.getString("action.remove_redundancy"),
340 Action.CUT, deleted, 0, width, ap.av.getAlignment());
342 for (int i = 0; i < del.size(); i++)
344 ap.av.getAlignment().deleteSequence(deleted[i]);
347 sg.deleteSequence(deleted[i], false);
351 historyList.push(cut);
353 ap.alignFrame.addHistoryItem(cut);
355 PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
356 ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
369 public void undoButton_actionPerformed(ActionEvent e)
371 if (historyList == null || historyList.isEmpty())
373 undoButton.setEnabled(false);
377 CommandI command = historyList.pop();
378 if (ap.av.getHistoryList().contains(command))
380 command.undoCommand(af.getViewAlignments());
381 ap.av.getHistoryList().remove(command);
382 ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
384 af.updateEditMenuBar();
387 ap.paintAlignment(true);
389 if (historyList.size() == 0)
391 undoButton.setEnabled(false);
402 public void valueField_actionPerformed(ActionEvent e)
406 int i = Integer.parseInt(valueField.getText());
408 } catch (Exception ex)
410 valueField.setText(slider.getValue() + "");