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,
110 .getString("label.redundancy_threshold_selection"),
112 frame.addInternalFrameListener(new InternalFrameAdapter()
115 public void internalFrameClosing(InternalFrameEvent evt)
117 ap.getIdPanel().getIdCanvas().setHighlighted(null);
124 * This is a copy of remove redundancy in jalivew.datamodel.Alignment except
125 * we dont want to remove redundancy, just calculate once so we can use the
126 * slider to dynamically hide redundant sequences
133 * @return DOCUMENT ME!
138 JProgressBar progress = new JProgressBar();
139 progress.setIndeterminate(true);
140 southPanel.add(progress, java.awt.BorderLayout.SOUTH);
142 label.setText(MessageManager.getString("label.calculating"));
144 slider.setVisible(false);
145 applyButton.setEnabled(false);
146 valueField.setVisible(false);
150 String[] omitHidden = null;
152 SequenceGroup sg = ap.av.getSelectionGroup();
157 if ((sg != null) && (sg.getSize() >= 1))
159 originalSequences = sg.getSequencesInOrder(ap.av.getAlignment());
160 start = sg.getStartRes();
161 end = sg.getEndRes();
165 originalSequences = ap.av.getAlignment().getSequencesArray();
167 end = ap.av.getAlignment().getWidth();
170 height = originalSequences.length;
171 if (ap.av.hasHiddenColumns())
173 omitHidden = ap.av.getViewAsString(sg != null);
175 Object rr[] = AlignSeq.computeRedundancyMatrixWithRep(
177 omitHidden, start, end, false);
179 redundancy = (float[]) rr[0];
180 redreps = (SequenceI[]) rr[1];
182 progress.setIndeterminate(false);
183 progress.setVisible(false);
187 MessageManager.getString("label.enter_redundancy_threshold"));
188 slider.setVisible(true);
189 applyButton.setEnabled(true);
190 valueField.setVisible(true);
193 sliderValueChanged();
194 // System.out.println((System.currentTimeMillis()-start));
197 void sliderValueChanged()
199 if (redundancy == null)
204 float value = slider.getValue();
205 List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
206 for (int i = 0; i < redundancy.length; i++)
208 if (value <= redundancy[i])
210 redundantSequences.add(originalSequences[i]);
213 ap.getIdPanel().getIdCanvas().setHighlighted(redundantSequences);
223 public void applyButton_actionPerformed(ActionEvent e)
226 undoButton.setEnabled(true);
228 float value = slider.getValue();
229 SequenceGroup sg = ap.av.getSelectionGroup();
230 // delete_seqs(value, sg);
231 hide_seqs(value, sg);
233 private void hide_seqs(float value, SequenceGroup sg)
236 * hash to look up the representative for a sequence
238 HashMap<SequenceI, SequenceI> rep = new HashMap<SequenceI, SequenceI>();
240 * hash to collect lists of sequences represented by a sequence
242 HashMap<SequenceI, SequenceGroup> reps = new HashMap<SequenceI, SequenceGroup>();
243 for (int i = 0; i < redundancy.length; i++)
245 if (value <= redundancy[i])
247 // does this sequence represent other sequences ?
248 SequenceGroup repset;
249 // is the representative also redundant ?
250 SequenceI repForI = rep.get(redreps[i]);
252 // the representative is still in the alignment.
253 // is it representing anything already ?
254 repset = reps.get(redreps[i]);
257 repset = new SequenceGroup();
259 repset.addSequence(originalSequences[i], false);
260 rep.put(originalSequences[i], redreps[i]);
261 reps.put(redreps[i], repset);
262 // and save the representative sequence for originalSeq
263 repForI = redreps[i];
265 // already hidden the representative for this sequence, so look up its redundant peers
266 repset = reps.get(repForI);
269 throw new Error("Implementation failure for redundancy set creation");
271 // add the sequence to the peerset, and mark sequence's representative in hash
272 repset.addSequence(originalSequences[i], false);
273 rep.put(originalSequences[i], repForI);
275 // merge any sequences represented by this with its new containing group
276 SequenceGroup existingreps = reps.remove(originalSequences[i]);
277 if (existingreps!=null)
279 for (SequenceI sq:existingreps.getSequences())
281 rep.put(sq, repForI);
282 repset.addSequence(sq, false);
287 int s = 0, e = ap.av.getAlignment().getWidth();
290 s = sg.getStartRes();
293 List<SequenceGroup> sgs = new ArrayList<SequenceGroup>();
294 for (SequenceI repseq: reps.keySet())
296 sg = reps.get(repseq);
297 sg.addSequence(repseq, false);
298 sg.setSeqrep(repseq);
303 ap.alignFrame.avc.showRandomColoursForGroups(sgs);
304 for (SequenceI repseq : reps.keySet())
306 sg = reps.get(repseq);
307 ap.av.hideRepSequences(repseq, sg);
311 private void delete_seqs(float value, SequenceGroup sg)
313 ArrayList<SequenceI> del = new ArrayList<SequenceI>();
315 for (int i = 0; i < redundancy.length; i++)
317 if (value <= redundancy[i])
319 del.add(originalSequences[i]);
322 // This has to be done before the restoreHistoryItem method of alignFrame
324 // actually restore these sequences.
327 SequenceI[] deleted = new SequenceI[del.size()];
330 for (int i = 0; i < del.size(); i++)
332 deleted[i] = del.get(i);
333 if (deleted[i].getLength() > width)
335 width = deleted[i].getLength();
339 EditCommand cut = new EditCommand(
340 MessageManager.getString("action.remove_redundancy"),
341 Action.CUT, deleted, 0, width, ap.av.getAlignment());
343 for (int i = 0; i < del.size(); i++)
345 ap.av.getAlignment().deleteSequence(deleted[i]);
348 sg.deleteSequence(deleted[i], false);
352 historyList.push(cut);
354 ap.alignFrame.addHistoryItem(cut);
356 PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
357 ap.av.firePropertyChange("alignment", null,
358 ap.av.getAlignment().getSequences());
370 public void undoButton_actionPerformed(ActionEvent e)
372 if (historyList == null || historyList.isEmpty())
374 undoButton.setEnabled(false);
378 CommandI command = historyList.pop();
379 if (ap.av.getHistoryList().contains(command))
381 command.undoCommand(af.getViewAlignments());
382 ap.av.getHistoryList().remove(command);
383 ap.av.firePropertyChange("alignment", null,
384 ap.av.getAlignment().getSequences());
385 af.updateEditMenuBar();
388 ap.paintAlignment(true);
390 if (historyList.size() == 0)
392 undoButton.setEnabled(false);
403 public void valueField_actionPerformed(ActionEvent e)
407 int i = Integer.parseInt(valueField.getText());
409 } catch (Exception ex)
411 valueField.setText(slider.getValue() + "");