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.
21 package jalview.controller;
23 import jalview.analysis.AlignmentSorter;
24 import jalview.api.AlignViewControllerGuiI;
25 import jalview.api.AlignViewControllerI;
26 import jalview.api.AlignViewportI;
27 import jalview.api.AlignmentViewPanel;
28 import jalview.api.FeatureRenderer;
29 import jalview.commands.OrderCommand;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.ColumnSelection;
32 import jalview.datamodel.SequenceCollectionI;
33 import jalview.datamodel.SequenceFeature;
34 import jalview.datamodel.SequenceGroup;
35 import jalview.datamodel.SequenceI;
36 import jalview.io.DataSourceType;
37 import jalview.io.FeaturesFile;
38 import jalview.util.MessageManager;
40 import java.awt.Color;
41 import java.util.Arrays;
42 import java.util.BitSet;
43 import java.util.List;
45 public class AlignViewController implements AlignViewControllerI
47 AlignViewportI viewport = null;
49 AlignmentViewPanel alignPanel = null;
52 * the GUI container that is handling interactions with the user
54 private AlignViewControllerGuiI avcg;
57 protected void finalize() throws Throwable
64 public AlignViewController(AlignViewControllerGuiI alignFrame,
65 AlignViewportI viewport, AlignmentViewPanel alignPanel)
67 this.avcg = alignFrame;
68 this.viewport = viewport;
69 this.alignPanel = alignPanel;
73 public void setViewportAndAlignmentPanel(AlignViewportI viewport,
74 AlignmentViewPanel alignPanel)
76 this.alignPanel = alignPanel;
77 this.viewport = viewport;
82 public boolean makeGroupsFromSelection()
84 SequenceGroup sg = viewport.getSelectionGroup();
85 ColumnSelection cs = viewport.getColumnSelection();
86 SequenceGroup[] gps = null;
87 if (sg != null && (cs == null || cs.isEmpty()))
89 gps = jalview.analysis.Grouping.makeGroupsFrom(
90 viewport.getSequenceSelection(),
91 viewport.getAlignmentView(true)
92 .getSequenceStrings(viewport.getGapCharacter()),
93 viewport.getAlignment().getGroups());
99 gps = jalview.analysis.Grouping.makeGroupsFromCols(
100 (sg == null) ? viewport.getAlignment().getSequencesArray()
101 : sg.getSequences().toArray(new SequenceI[0]),
102 cs, viewport.getAlignment().getGroups());
107 showRandomColoursForGroups(Arrays.asList(gps));
115 public void showRandomColoursForGroups(List<SequenceGroup> gps)
117 viewport.getAlignment().deleteAllGroups();
118 viewport.clearSequenceColours();
119 viewport.setSelectionGroup(null);
120 // set view properties for each group
121 for (SequenceGroup sg : gps)
123 // gps[g].setShowunconserved(viewport.getShowUnconserved());
124 sg.setshowSequenceLogo(viewport.isShowSequenceLogo());
125 viewport.getAlignment().addGroup(sg);
126 Color col = new Color((int) (Math.random() * 255),
127 (int) (Math.random() * 255), (int) (Math.random() * 255));
128 col = col.brighter();
129 for (SequenceI sq : sg.getSequences(null))
131 viewport.setSequenceColour(sq, col);
137 public boolean createGroup()
140 SequenceGroup sg = viewport.getSelectionGroup();
143 viewport.getAlignment().addGroup(sg);
150 public boolean unGroup()
152 SequenceGroup sg = viewport.getSelectionGroup();
155 viewport.getAlignment().deleteGroup(sg);
162 public boolean deleteGroups()
164 if (viewport.getAlignment().getGroups() != null
165 && viewport.getAlignment().getGroups().size() > 0)
167 viewport.getAlignment().deleteAllGroups();
168 viewport.clearSequenceColours();
169 viewport.setSelectionGroup(null);
176 public boolean markColumnsContainingFeatures(boolean invert,
177 boolean extendCurrent, boolean toggle, String featureType)
179 // JBPNote this routine could also mark rows, not just columns.
180 // need a decent query structure to allow all types of feature searches
181 BitSet bs = new BitSet();
182 SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null
183 || extendCurrent) ? viewport.getAlignment()
184 : viewport.getSelectionGroup();
186 int nseq = findColumnsWithFeature(featureType, sqcol, bs);
188 ColumnSelection cs = viewport.getColumnSelection();
191 cs = new ColumnSelection();
194 if (bs.cardinality() > 0 || invert)
196 boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
197 sqcol.getEndRes(), invert, extendCurrent, toggle);
200 viewport.setColumnSelection(cs);
201 alignPanel.paintAlignment(true);
202 int columnCount = invert
203 ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
206 avcg.setStatus(MessageManager.formatMessage(
207 "label.view_controller_toggled_marked", new String[]
208 { toggle ? MessageManager.getString("label.toggled")
209 : MessageManager.getString("label.marked"),
210 String.valueOf(columnCount),
211 invert ? MessageManager
212 .getString("label.not_containing")
213 : MessageManager.getString("label.containing"),
214 featureType, Integer.valueOf(nseq).toString() }));
220 avcg.setStatus(MessageManager
221 .formatMessage("label.no_feature_of_type_found", new String[]
226 alignPanel.paintAlignment(true);
233 * Sets a bit in the BitSet for each column (base 0) in the sequence
234 * collection which includes the specified feature type. Returns the number of
235 * sequences which have the feature in the selected range.
242 static int findColumnsWithFeature(String featureType,
243 SequenceCollectionI sqcol, BitSet bs)
245 final int startColumn = sqcol.getStartRes() + 1; // converted to base 1
246 final int endColumn = sqcol.getEndRes() + 1;
247 List<SequenceI> seqs = sqcol.getSequences();
249 for (SequenceI sq : seqs)
253 // int ist = sq.findPosition(sqcol.getStartRes());
254 List<SequenceFeature> sfs = sq.findFeatures(startColumn,
255 endColumn, featureType);
262 for (SequenceFeature sf : sfs)
264 int sfStartCol = sq.findIndex(sf.getBegin());
265 int sfEndCol = sq.findIndex(sf.getEnd());
267 if (sf.isContactFeature())
270 * 'contact' feature - check for 'start' or 'end'
271 * position within the selected region
273 if (sfStartCol >= startColumn && sfStartCol <= endColumn)
275 bs.set(sfStartCol - 1);
277 if (sfEndCol >= startColumn && sfEndCol <= endColumn)
279 bs.set(sfEndCol - 1);
285 * contiguous feature - select feature positions (if any)
286 * within the selected region
288 if (sfStartCol < startColumn)
290 sfStartCol = startColumn;
292 // not sure what the point of this is
293 // if (sfStartCol < ist)
297 if (sfEndCol > endColumn)
299 sfEndCol = endColumn;
301 for (; sfStartCol <= sfEndCol; sfStartCol++)
303 bs.set(sfStartCol - 1); // convert to base 0
312 public void sortAlignmentByFeatureDensity(List<String> typ)
314 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
317 protected void sortBy(List<String> typ, String methodText,
320 FeatureRenderer fr = alignPanel.getFeatureRenderer();
321 if (typ == null && fr != null)
323 typ = fr.getDisplayedFeatureTypes();
325 List<String> gps = null;
328 gps = fr.getDisplayedFeatureGroups();
330 AlignmentI al = viewport.getAlignment();
333 SequenceGroup sg = viewport.getSelectionGroup();
336 start = sg.getStartRes();
337 stop = sg.getEndRes();
342 stop = al.getWidth();
344 SequenceI[] oldOrder = al.getSequencesArray();
345 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
346 avcg.addHistoryItem(new OrderCommand(methodText, oldOrder,
347 viewport.getAlignment()));
348 alignPanel.paintAlignment(true);
353 public void sortAlignmentByFeatureScore(List<String> typ)
355 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
359 public boolean parseFeaturesFile(String file, DataSourceType protocol,
360 boolean relaxedIdMatching)
362 boolean featuresFile = false;
365 featuresFile = new FeaturesFile(false, file, protocol).parse(
366 viewport.getAlignment().getDataset(),
367 alignPanel.getFeatureRenderer().getFeatureColours(), false,
369 } catch (Exception ex)
371 ex.printStackTrace();
376 avcg.refreshFeatureUI(true);
377 if (alignPanel.getFeatureRenderer() != null)
379 // update the min/max ranges where necessary
380 alignPanel.getFeatureRenderer().findAllFeatures(true);
382 if (avcg.getFeatureSettingsUI() != null)
384 avcg.getFeatureSettingsUI().discoverAllFeatureData();
386 alignPanel.paintAlignment(true);
394 public boolean markHighlightedColumns(boolean invert,
395 boolean extendCurrent, boolean toggle)
397 if (!viewport.hasSearchResults())
399 // do nothing if no selection exists
402 // JBPNote this routine could also mark rows, not just columns.
403 BitSet bs = new BitSet();
404 SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null
405 || extendCurrent) ? viewport.getAlignment()
406 : viewport.getSelectionGroup();
408 // this could be a lambda... - the remains of the method is boilerplate,
409 // except for the different messages for reporting selection.
410 int nseq = viewport.getSearchResults().markColumns(sqcol, bs);
412 ColumnSelection cs = viewport.getColumnSelection();
415 cs = new ColumnSelection();
418 if (bs.cardinality() > 0 || invert)
420 boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
421 sqcol.getEndRes(), invert, extendCurrent, toggle);
424 viewport.setColumnSelection(cs);
425 alignPanel.paintAlignment(true);
426 int columnCount = invert
427 ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
430 avcg.setStatus(MessageManager.formatMessage(
431 "label.view_controller_toggled_marked", new String[]
432 { toggle ? MessageManager.getString("label.toggled")
433 : MessageManager.getString("label.marked"),
434 String.valueOf(columnCount),
435 invert ? MessageManager
436 .getString("label.not_containing")
437 : MessageManager.getString("label.containing"),
438 "Highlight", Integer.valueOf(nseq).toString() }));
444 avcg.setStatus(MessageManager
445 .formatMessage("No highlighted regions marked"));
449 alignPanel.paintAlignment(true);