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.event.ActionEvent;
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Stack;
37 import java.util.Vector;
39 import javax.swing.JInternalFrame;
40 import javax.swing.JProgressBar;
41 import javax.swing.event.ChangeEvent;
42 import javax.swing.event.ChangeListener;
43 import javax.swing.event.InternalFrameAdapter;
44 import javax.swing.event.InternalFrameEvent;
52 public class RedundancyPanel extends GSliderPanel implements Runnable
58 Stack<CommandI> historyList = new Stack<CommandI>();
60 // simpler than synching with alignFrame.
64 SequenceI[] originalSequences;
70 private SequenceI[] redreps;
73 * Creates a new RedundancyPanel object.
80 public RedundancyPanel(final AlignmentPanel ap, AlignFrame af)
84 redundantSeqs = new Vector();
86 slider.addChangeListener(new ChangeListener()
89 public void stateChanged(ChangeEvent evt)
91 valueField.setText(slider.getValue() + "");
96 applyButton.setText(MessageManager.getString("action.hide"));
97 allGroupsCheck.setVisible(false);
99 slider.setMaximum(100);
100 slider.setValue(100);
102 Thread worker = new Thread(this);
105 frame = new JInternalFrame();
106 frame.setContentPane(this);
107 Desktop.addInternalFrame(frame, MessageManager
108 .getString("label.redundancy_threshold_selection"), 400, 100,
110 frame.addInternalFrameListener(new InternalFrameAdapter()
113 public void internalFrameClosing(InternalFrameEvent evt)
115 ap.getIdPanel().getIdCanvas().setHighlighted(null);
122 * This is a copy of remove redundancy in jalivew.datamodel.Alignment except
123 * we dont want to remove redundancy, just calculate once so we can use the
124 * slider to dynamically hide redundant sequences
131 * @return DOCUMENT ME!
136 JProgressBar progress = new JProgressBar();
137 progress.setIndeterminate(true);
138 southPanel.add(progress, java.awt.BorderLayout.SOUTH);
140 label.setText(MessageManager.getString("label.calculating"));
142 slider.setVisible(false);
143 applyButton.setEnabled(false);
144 valueField.setVisible(false);
148 String[] omitHidden = null;
150 SequenceGroup sg = ap.av.getSelectionGroup();
155 if ((sg != null) && (sg.getSize() >= 1))
157 originalSequences = sg.getSequencesInOrder(ap.av.getAlignment());
158 start = sg.getStartRes();
159 end = sg.getEndRes();
163 originalSequences = ap.av.getAlignment().getSequencesArray();
165 end = ap.av.getAlignment().getWidth();
168 height = originalSequences.length;
169 if (ap.av.hasHiddenColumns())
171 omitHidden = ap.av.getViewAsString(sg != null);
173 Object rr[] = AlignSeq.computeRedundancyMatrixWithRep(
175 omitHidden, start, end, false);
177 redundancy = (float[]) rr[0];
178 redreps = (SequenceI[]) rr[1];
180 progress.setIndeterminate(false);
181 progress.setVisible(false);
184 label.setText(MessageManager
185 .getString("label.enter_redundancy_thereshold"));
186 slider.setVisible(true);
187 applyButton.setEnabled(true);
188 valueField.setVisible(true);
191 sliderValueChanged();
192 // System.out.println((System.currentTimeMillis()-start));
195 void sliderValueChanged()
197 if (redundancy == null)
202 float value = slider.getValue();
203 List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
204 for (int i = 0; i < redundancy.length; i++)
206 if (value <= redundancy[i])
208 redundantSequences.add(originalSequences[i]);
211 ap.getIdPanel().getIdCanvas().setHighlighted(redundantSequences);
221 public void applyButton_actionPerformed(ActionEvent e)
224 undoButton.setEnabled(true);
226 float value = slider.getValue();
227 SequenceGroup sg = ap.av.getSelectionGroup();
228 // delete_seqs(value, sg);
229 hide_seqs(value, sg);
231 private void hide_seqs(float value, SequenceGroup sg)
234 * hash to look up the representative for a sequence
236 HashMap<SequenceI, SequenceI> rep = new HashMap<SequenceI, SequenceI>();
238 * hash to collect lists of sequences represented by a sequence
240 HashMap<SequenceI, SequenceGroup> reps = new HashMap<SequenceI, SequenceGroup>();
241 for (int i = 0; i < redundancy.length; i++)
243 if (value <= redundancy[i])
245 // does this sequence represent other sequences ?
246 SequenceGroup repset;
247 // is the representative also redundant ?
248 SequenceI repForI = rep.get(redreps[i]);
250 // the representative is still in the alignment.
251 // is it representing anything already ?
252 repset = reps.get(redreps[i]);
255 repset = new SequenceGroup();
257 repset.addSequence(originalSequences[i], false);
258 rep.put(originalSequences[i], redreps[i]);
259 reps.put(redreps[i], repset);
260 // and save the representative sequence for originalSeq
261 repForI = redreps[i];
263 // already hidden the representative for this sequence, so look up its redundant peers
264 repset = reps.get(repForI);
267 throw new Error("Implementation failure for redundancy set creation");
269 // add the sequence to the peerset, and mark sequence's representative in hash
270 repset.addSequence(originalSequences[i], false);
271 rep.put(originalSequences[i], repForI);
273 // merge any sequences represented by this with its new containing group
274 SequenceGroup existingreps = reps.remove(originalSequences[i]);
275 if (existingreps!=null)
277 for (SequenceI sq:existingreps.getSequences())
279 rep.put(sq, repForI);
280 repset.addSequence(sq, false);
285 for (SequenceI repseq: reps.keySet())
287 sg = reps.get(repseq);
288 sg.addSequence(repseq, false);
289 sg.setSeqrep(repseq);
290 ap.av.hideRepSequences(repseq, sg);
294 private void delete_seqs(float value, SequenceGroup sg)
296 ArrayList<SequenceI> del = new ArrayList<SequenceI>();
298 for (int i = 0; i < redundancy.length; i++)
300 if (value <= redundancy[i])
302 del.add(originalSequences[i]);
305 // This has to be done before the restoreHistoryItem method of alignFrame
307 // actually restore these sequences.
310 SequenceI[] deleted = new SequenceI[del.size()];
313 for (int i = 0; i < del.size(); i++)
315 deleted[i] = del.get(i);
316 if (deleted[i].getLength() > width)
318 width = deleted[i].getLength();
322 EditCommand cut = new EditCommand(
323 MessageManager.getString("action.remove_redundancy"),
324 Action.CUT, deleted, 0, width, ap.av.getAlignment());
326 for (int i = 0; i < del.size(); i++)
328 ap.av.getAlignment().deleteSequence(deleted[i]);
331 sg.deleteSequence(deleted[i], false);
335 historyList.push(cut);
337 ap.alignFrame.addHistoryItem(cut);
339 PaintRefresher.Refresh(this, ap.av.getSequenceSetId(), true, true);
340 ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
353 public void undoButton_actionPerformed(ActionEvent e)
355 if (historyList == null || historyList.isEmpty())
357 undoButton.setEnabled(false);
361 CommandI command = historyList.pop();
362 if (ap.av.getHistoryList().contains(command))
364 command.undoCommand(af.getViewAlignments());
365 ap.av.getHistoryList().remove(command);
366 ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
368 af.updateEditMenuBar();
371 ap.paintAlignment(true);
373 if (historyList.size() == 0)
375 undoButton.setEnabled(false);
386 public void valueField_actionPerformed(ActionEvent e)
390 int i = Integer.parseInt(valueField.getText());
392 } catch (Exception ex)
394 valueField.setText(slider.getValue() + "");