Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.controller

File AlignViewController.java

 

Coverage histogram

../../img/srcFileCovDistChart5.png
39% of files have more coverage

Code metrics

88
153
13
1
472
366
67
0.44
11.77
13
5.15

Classes

Class Line # Actions
AlignViewController 45 153 67
0.49606349.6%
 

Contributing tests

This file is covered by 95 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21    package jalview.controller;
22   
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.schemes.ColourSchemeI;
39    import jalview.util.MessageManager;
40   
41    import java.awt.Color;
42    import java.util.BitSet;
43    import java.util.List;
44   
 
45    public class AlignViewController implements AlignViewControllerI
46    {
47    AlignViewportI viewport = null;
48   
49    AlignmentViewPanel alignPanel = null;
50   
51    /**
52    * the GUI container that is handling interactions with the user
53    */
54    private AlignViewControllerGuiI avcg;
55   
 
56  526 toggle public AlignViewController(AlignViewControllerGuiI alignFrame,
57    AlignViewportI vp, AlignmentViewPanel ap)
58    {
59  526 this.avcg = alignFrame;
60  526 this.viewport = vp;
61  526 this.alignPanel = ap;
62    }
63   
 
64  89 toggle @Override
65    public void setViewportAndAlignmentPanel(AlignViewportI vp,
66    AlignmentViewPanel ap)
67    {
68  89 this.alignPanel = ap;
69  89 this.viewport = vp;
70    }
71   
 
72  0 toggle @Override
73    public boolean makeGroupsFromSelection()
74    {
75  0 SequenceGroup sg = viewport.getSelectionGroup();
76  0 ColumnSelection cs = viewport.getColumnSelection();
77  0 SequenceGroup[] gps = null;
78  0 if (sg != null && (cs == null || cs.isEmpty()))
79    {
80  0 gps = jalview.analysis.Grouping.makeGroupsFrom(
81    viewport.getSequenceSelection(),
82    viewport.getAlignmentView(true)
83    .getSequenceStrings(viewport.getGapCharacter()),
84    viewport.getAlignment().getGroups());
85    }
86    else
87    {
88  0 if (cs != null)
89    {
90  0 gps = jalview.analysis.Grouping.makeGroupsFromCols(
91  0 (sg == null) ? viewport.getAlignment().getSequencesArray()
92    : sg.getSequences().toArray(new SequenceI[0]),
93    cs, viewport.getAlignment().getGroups());
94    }
95    }
96  0 if (gps != null)
97    {
98  0 viewport.getAlignment().deleteAllGroups();
99  0 viewport.clearSequenceColours();
100  0 viewport.setSelectionGroup(null);
101  0 ColourSchemeI colours = viewport.getGlobalColourScheme();
102    // set view properties for each group
103  0 for (int g = 0; g < gps.length; g++)
104    {
105    // gps[g].setShowunconserved(viewport.getShowUnconserved());
106  0 gps[g].setshowSequenceLogo(viewport.isShowSequenceLogo());
107  0 viewport.getAlignment().addGroup(gps[g]);
108  0 if (colours != null)
109    {
110  0 gps[g].setColourScheme(colours.getInstance(viewport, gps[g]));
111    }
112  0 Color col = new Color((int) (Math.random() * 255),
113    (int) (Math.random() * 255), (int) (Math.random() * 255));
114  0 gps[g].idColour = col;
115  0 viewport.setUpdateStructures(true);
116  0 viewport.addSequenceGroup(gps[g]);
117    }
118  0 return true;
119    }
120  0 return false;
121    }
122   
 
123  0 toggle @Override
124    public boolean createGroup()
125    {
126   
127  0 SequenceGroup sg = viewport.getSelectionGroup();
128  0 if (sg != null)
129    {
130  0 viewport.getAlignment().addGroup(sg);
131  0 return true;
132    }
133  0 return false;
134    }
135   
 
136  0 toggle @Override
137    public boolean unGroup()
138    {
139  0 SequenceGroup sg = viewport.getSelectionGroup();
140  0 if (sg != null)
141    {
142  0 viewport.getAlignment().deleteGroup(sg);
143  0 return true;
144    }
145  0 return false;
146    }
147   
 
148  0 toggle @Override
149    public boolean deleteGroups()
150    {
151  0 if (viewport.getAlignment().getGroups() != null
152    && viewport.getAlignment().getGroups().size() > 0)
153    {
154  0 viewport.getAlignment().deleteAllGroups();
155  0 viewport.clearSequenceColours();
156  0 viewport.setSelectionGroup(null);
157  0 return true;
158    }
159  0 return false;
160    }
161   
 
162  12 toggle @Override
163    public boolean markColumnsContainingFeatures(boolean invert,
164    boolean extendCurrent, boolean toggle, String featureType)
165    {
166    // JBPNote this routine could also mark rows, not just columns.
167    // need a decent query structure to allow all types of feature searches
168  12 BitSet bs = new BitSet();
169  12 boolean searchSelection = viewport.getSelectionGroup() != null
170    && !extendCurrent;
171  12 SequenceCollectionI sqcol = searchSelection ? viewport
172    .getSelectionGroup() : viewport.getAlignment();
173   
174  12 int nseq = findColumnsWithFeature(featureType, sqcol, bs);
175   
176  12 ColumnSelection cs = viewport.getColumnSelection();
177  12 if (cs == null)
178    {
179  0 cs = new ColumnSelection();
180    }
181   
182  12 if (bs.cardinality() > 0 || invert)
183    {
184  10 boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
185    sqcol.getEndRes(), invert, extendCurrent, toggle);
186  10 if (changed)
187    {
188  9 viewport.setColumnSelection(cs);
189  9 alignPanel.paintAlignment(false, false);
190  9 int columnCount = invert
191    ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
192    - bs.cardinality()
193    : bs.cardinality();
194  9 avcg.setStatus(MessageManager.formatMessage(
195    "label.view_controller_toggled_marked", new String[]
196  9 { toggle ? MessageManager.getString("label.toggled")
197    : MessageManager.getString("label.marked"),
198    String.valueOf(columnCount),
199  9 invert ? MessageManager
200    .getString("label.not_containing")
201    : MessageManager.getString("label.containing"),
202    featureType, Integer.valueOf(nseq).toString() }));
203  9 return true;
204    }
205    }
206    else
207    {
208  2 String key = searchSelection ? "label.no_feature_found_selection"
209    : "label.no_feature_of_type_found";
210  2 avcg.setStatus(MessageManager.formatMessage(key,
211    new String[] { featureType }));
212  2 if (!extendCurrent)
213    {
214  2 cs.clear();
215  2 alignPanel.paintAlignment(false, false);
216    }
217    }
218  3 return false;
219    }
220   
221    /**
222    * Sets a bit in the BitSet for each column (base 0) in the sequence
223    * collection which includes a visible feature of the specified feature type.
224    * Returns the number of sequences which have the feature visible in the
225    * selected range.
226    *
227    * @param featureType
228    * @param sqcol
229    * @param bs
230    * @return
231    */
 
232  20 toggle int findColumnsWithFeature(String featureType,
233    SequenceCollectionI sqcol, BitSet bs)
234    {
235  20 FeatureRenderer fr = alignPanel == null ? null : alignPanel
236    .getFeatureRenderer();
237   
238  20 final int startColumn = sqcol.getStartRes() + 1; // converted to base 1
239  20 final int endColumn = sqcol.getEndRes() + 1;
240  20 List<SequenceI> seqs = sqcol.getSequences();
241  20 int nseq = 0;
242  20 for (SequenceI sq : seqs)
243    {
244  92 if (sq != null)
245    {
246    // int ist = sq.findPosition(sqcol.getStartRes());
247  92 List<SequenceFeature> sfs = sq.findFeatures(startColumn,
248    endColumn, featureType);
249   
250  92 boolean found = false;
251  92 for (SequenceFeature sf : sfs)
252    {
253  545 if (fr.getColour(sf) == null)
254    {
255  3 continue;
256    }
257  542 if (!found)
258    {
259  58 nseq++;
260    }
261  542 found = true;
262   
263  542 int sfStartCol = sq.findIndex(sf.getBegin());
264  542 int sfEndCol = sq.findIndex(sf.getEnd());
265   
266  542 if (sf.isContactFeature())
267    {
268    /*
269    * 'contact' feature - check for 'start' or 'end'
270    * position within the selected region
271    */
272  1 if (sfStartCol >= startColumn && sfStartCol <= endColumn)
273    {
274  1 bs.set(sfStartCol - 1);
275    }
276  1 if (sfEndCol >= startColumn && sfEndCol <= endColumn)
277    {
278  1 bs.set(sfEndCol - 1);
279    }
280  1 continue;
281    }
282   
283    /*
284    * contiguous feature - select feature positions (if any)
285    * within the selected region
286    */
287  541 if (sfStartCol < startColumn)
288    {
289  1 sfStartCol = startColumn;
290    }
291    // not sure what the point of this is
292    // if (sfStartCol < ist)
293    // {
294    // sfStartCol = ist;
295    // }
296  541 if (sfEndCol > endColumn)
297    {
298  4 sfEndCol = endColumn;
299    }
300  25219 for (; sfStartCol <= sfEndCol; sfStartCol++)
301    {
302  24678 bs.set(sfStartCol - 1); // convert to base 0
303    }
304    }
305    }
306    }
307  20 return nseq;
308    }
309   
 
310  0 toggle @Override
311    public void sortAlignmentByFeatureDensity(List<String> typ)
312    {
313  0 String methodText = MessageManager.getString("label.sort_by_density");
314  0 sortByFeatures(typ, methodText, AlignmentSorter.FEATURE_DENSITY);
315    }
316   
317    /**
318    * Sorts the alignment (or current selection) by either average score or density
319    * of the specified feature types, and adds to the command history. If
320    * {@code types} is null, all visible feature types are used for the sort. If no
321    * feature types apply, does nothing.
322    *
323    * @param types
324    * @param methodText
325    * - text shown in Undo/Redo command
326    * @param method
327    * - passed to
328    * jalview.analysis.AlignmentSorter.sortByFeatures()
329    */
 
330  0 toggle protected void sortByFeatures(List<String> types, String methodText,
331    final String method)
332    {
333  0 FeatureRenderer fr = alignPanel.getFeatureRenderer();
334  0 if (types == null && fr != null)
335    {
336  0 types = fr.getDisplayedFeatureTypes();
337    }
338  0 if (types.isEmpty())
339    {
340  0 return; // nothing to do
341    }
342  0 List<String> gps = null;
343  0 if (fr != null)
344    {
345  0 gps = fr.getDisplayedFeatureGroups();
346    }
347  0 AlignmentI al = viewport.getAlignment();
348   
349  0 int start, stop;
350  0 SequenceGroup sg = viewport.getSelectionGroup();
351  0 if (sg != null)
352    {
353  0 start = sg.getStartRes();
354  0 stop = sg.getEndRes();
355    }
356    else
357    {
358  0 start = 0;
359  0 stop = al.getWidth();
360    }
361  0 SequenceI[] oldOrder = al.getSequencesArray();
362  0 AlignmentSorter.sortByFeature(types, gps, start, stop, al, method);
363  0 avcg.addHistoryItem(new OrderCommand(methodText, oldOrder,
364    viewport.getAlignment()));
365  0 alignPanel.paintAlignment(true, false);
366   
367    }
368   
 
369  0 toggle @Override
370    public void sortAlignmentByFeatureScore(List<String> typ)
371    {
372  0 String methodText = MessageManager.getString("label.sort_by_score");
373  0 sortByFeatures(typ, methodText, AlignmentSorter.FEATURE_SCORE);
374    }
375   
 
376  3 toggle @Override
377    public boolean parseFeaturesFile(Object file, DataSourceType protocol,
378    boolean relaxedIdMatching)
379    {
380  3 boolean featuresAdded = false;
381  3 FeatureRenderer fr = alignPanel.getFeatureRenderer();
382  3 try
383    {
384  3 featuresAdded = new FeaturesFile(false, file, protocol).parse(
385    viewport.getAlignment().getDataset(), fr.getFeatureColours(),
386    fr.getFeatureFilters(), false, relaxedIdMatching);
387    } catch (Exception ex)
388    {
389  0 ex.printStackTrace();
390    }
391   
392  3 if (featuresAdded)
393    {
394  3 avcg.refreshFeatureUI(true);
395  3 if (fr != null)
396    {
397    // update the min/max ranges where necessary
398  3 fr.findAllFeatures(true);
399    }
400  3 if (avcg.getFeatureSettingsUI() != null)
401    {
402  0 avcg.getFeatureSettingsUI().discoverAllFeatureData();
403    }
404  3 alignPanel.paintAlignment(true, true);
405    }
406   
407  3 return featuresAdded;
408   
409    }
410   
 
411  2 toggle @Override
412    public boolean markHighlightedColumns(boolean invert,
413    boolean extendCurrent, boolean toggle)
414    {
415  2 if (!viewport.hasSearchResults())
416    {
417    // do nothing if no selection exists
418  0 return false;
419    }
420    // JBPNote this routine could also mark rows, not just columns.
421  2 BitSet bs = new BitSet();
422  2 SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null
423    || extendCurrent) ? viewport.getAlignment()
424    : viewport.getSelectionGroup();
425   
426    // this could be a lambda... - the remains of the method is boilerplate,
427    // except for the different messages for reporting selection.
428  2 int nseq = viewport.getSearchResults().markColumns(sqcol, bs);
429   
430  2 ColumnSelection cs = viewport.getColumnSelection();
431  2 if (cs == null)
432    {
433  0 cs = new ColumnSelection();
434    }
435   
436  2 if (bs.cardinality() > 0 || invert)
437    {
438  2 boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
439    sqcol.getEndRes(), invert, extendCurrent, toggle);
440  2 if (changed)
441    {
442  2 viewport.setColumnSelection(cs);
443  2 alignPanel.paintAlignment(false, false);
444  2 int columnCount = invert
445    ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
446    - bs.cardinality()
447    : bs.cardinality();
448  2 avcg.setStatus(MessageManager.formatMessage(
449    "label.view_controller_toggled_marked", new String[]
450  2 { toggle ? MessageManager.getString("label.toggled")
451    : MessageManager.getString("label.marked"),
452    String.valueOf(columnCount),
453  2 invert ? MessageManager
454    .getString("label.not_containing")
455    : MessageManager.getString("label.containing"),
456    "Highlight", Integer.valueOf(nseq).toString() }));
457  2 return true;
458    }
459    }
460    else
461    {
462  0 avcg.setStatus(MessageManager.getString("label.no_highlighted_regions_marked"));
463  0 if (!extendCurrent)
464    {
465  0 cs.clear();
466  0 alignPanel.paintAlignment(false, false);
467    }
468    }
469  0 return false;
470    }
471   
472    }