tidy imports
[jalview.git] / src / jalview / controller / AlignViewController.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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 java.awt.Color;
24 import java.util.ArrayList;
25 import java.util.BitSet;
26 import java.util.List;
27
28 import jalview.analysis.AlignmentSorter;
29 import jalview.api.AlignViewControllerGuiI;
30 import jalview.api.AlignViewControllerI;
31 import jalview.api.AlignViewportI;
32 import jalview.api.AlignmentViewPanel;
33 import jalview.api.FeatureRenderer;
34 import jalview.commands.OrderCommand;
35 import jalview.datamodel.AlignmentI;
36 import jalview.datamodel.ColumnSelection;
37 import jalview.datamodel.SequenceCollectionI;
38 import jalview.datamodel.SequenceFeature;
39 import jalview.datamodel.SequenceGroup;
40 import jalview.datamodel.SequenceI;
41
42 public class AlignViewController implements AlignViewControllerI
43 {
44   AlignViewportI viewport = null;
45
46   AlignmentViewPanel alignPanel = null;
47
48   /**
49    * the GUI container that is handling interactions with the user
50    */
51   private AlignViewControllerGuiI avcg;
52
53   @Override
54   protected void finalize() throws Throwable
55   {
56     viewport = null;
57     alignPanel = null;
58     avcg = null;
59   };
60
61   public AlignViewController(AlignViewControllerGuiI alignFrame,
62           AlignViewportI viewport, AlignmentViewPanel alignPanel)
63   {
64     this.avcg = alignFrame;
65     this.viewport = viewport;
66     this.alignPanel = alignPanel;
67   }
68
69   @Override
70   public void setViewportAndAlignmentPanel(AlignViewportI viewport,
71           AlignmentViewPanel alignPanel)
72   {
73     this.alignPanel = alignPanel;
74     this.viewport = viewport;
75
76   }
77
78   @Override
79   public boolean makeGroupsFromSelection()
80   {
81
82     if (viewport.getSelectionGroup() != null)
83     {
84       SequenceGroup[] gps = jalview.analysis.Grouping.makeGroupsFrom(
85               viewport.getSequenceSelection(),
86               viewport.getAlignmentView(true).getSequenceStrings(
87                       viewport.getGapCharacter()), viewport.getAlignment()
88                       .getGroups());
89       viewport.getAlignment().deleteAllGroups();
90       viewport.clearSequenceColours();
91       viewport.setSelectionGroup(null);
92       // set view properties for each group
93       for (int g = 0; g < gps.length; g++)
94       {
95         // gps[g].setShowunconserved(viewport.getShowUnconserved());
96         gps[g].setshowSequenceLogo(viewport.isShowSequenceLogo());
97         viewport.getAlignment().addGroup(gps[g]);
98         Color col = new Color((int) (Math.random() * 255),
99                 (int) (Math.random() * 255), (int) (Math.random() * 255));
100         col = col.brighter();
101         for (SequenceI sq : gps[g].getSequences(null))
102           viewport.setSequenceColour(sq, col);
103       }
104       return true;
105     }
106     return false;
107   }
108
109   @Override
110   public boolean createGroup()
111   {
112
113     SequenceGroup sg = viewport.getSelectionGroup();
114     if (sg != null)
115     {
116       viewport.getAlignment().addGroup(sg);
117       return true;
118     }
119     return false;
120   }
121
122   @Override
123   public boolean unGroup()
124   {
125     SequenceGroup sg = viewport.getSelectionGroup();
126     if (sg != null)
127     {
128       viewport.getAlignment().deleteGroup(sg);
129       return true;
130     }
131     return false;
132   }
133
134   @Override
135   public boolean deleteGroups()
136   {
137     if (viewport.getAlignment().getGroups() != null
138             && viewport.getAlignment().getGroups().size() > 0)
139     {
140       viewport.getAlignment().deleteAllGroups();
141       viewport.clearSequenceColours();
142       viewport.setSelectionGroup(null);
143       return true;
144     }
145     return false;
146   }
147
148   @Override
149   public boolean markColumnsContainingFeatures(boolean invert,
150           boolean extendCurrent, boolean toggle, String featureType)
151   {
152     // JBPNote this routine could also mark rows, not just columns.
153     // need a decent query structure to allow all types of feature searches
154     BitSet bs = new BitSet();
155     int alw, alStart;
156     SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null ? viewport
157             .getAlignment() : viewport.getSelectionGroup());
158     alStart = sqcol.getStartRes();
159     alw = sqcol.getEndRes() + 1;
160     List<SequenceI> seqs = sqcol.getSequences();
161     int nseq = 0;
162     for (SequenceI sq : seqs)
163     {
164       int tfeat = 0;
165       if (sq != null)
166       {
167         SequenceI dsq = sq.getDatasetSequence();
168         while (dsq.getDatasetSequence() != null)
169         {
170           dsq = dsq.getDatasetSequence();
171         }
172         ;
173         SequenceFeature[] sf = dsq.getSequenceFeatures();
174         if (sf != null)
175         {
176           int ist = sq.findIndex(sq.getStart());
177           int iend = sq.findIndex(sq.getEnd());
178           if (iend < alStart || ist > alw)
179           {
180             // sequence not in region
181             continue;
182           }
183           for (SequenceFeature sfpos : sf)
184           {
185             // future functionalty - featureType == null means mark columns
186             // containing all displayed features
187             if (sfpos != null && (featureType.equals(sfpos.getType())))
188             {
189               tfeat++;
190               // optimisation - could consider 'spos,apos' like cursor argument
191               // - findIndex wastes time by starting from first character and
192               // counting
193
194               int i = sq.findIndex(sfpos.getBegin());
195               int j = sq.findIndex(sfpos.getEnd());
196               if (j < alStart || i > alw)
197               {
198                 // feature is outside selected region
199                 continue;
200               }
201               if (i < alStart)
202               {
203                 i = alStart;
204               }
205               if (i < ist)
206               {
207                 i = ist;
208               }
209               if (j > alw)
210               {
211                 j = alw;
212               }
213               for (; i <= j; i++)
214               {
215                 bs.set(i - 1);
216               }
217             }
218           }
219         }
220
221         if (tfeat > 0)
222         {
223           nseq++;
224         }
225       }
226     }
227     ColumnSelection cs = viewport.getColumnSelection();
228     if (bs.cardinality() > 0 || invert)
229     {
230       if (cs == null)
231       {
232         cs = new ColumnSelection();
233       }
234       else
235       {
236         if (!extendCurrent)
237         {
238           cs.clear();
239         }
240       }
241       if (invert)
242       {
243         // invert only in the currently selected sequence region
244         for (int i = bs.nextClearBit(alStart), ibs = bs.nextSetBit(alStart); i >= alStart
245                 && i < (alw);)
246         {
247           if (ibs < 0 || i < ibs)
248           {
249             if (toggle && cs.contains(i))
250             {
251               cs.removeElement(i++);
252             }
253             else
254             {
255               cs.addElement(i++);
256             }
257           }
258           else
259           {
260             i = bs.nextClearBit(ibs);
261             ibs = bs.nextSetBit(i);
262           }
263         }
264       }
265       else
266       {
267         for (int i = bs.nextSetBit(alStart); i >= alStart; i = bs
268                 .nextSetBit(i + 1))
269         {
270           if (toggle && cs.contains(i))
271           {
272             cs.removeElement(i);
273           }
274           else
275           {
276             cs.addElement(i);
277           }
278         }
279       }
280       viewport.setColumnSelection(cs);
281       alignPanel.paintAlignment(true);
282       avcg.setStatus((toggle ? "Toggled " : "Marked ")
283               + (invert ? (alw - alStart) - bs.cardinality() : bs
284                       .cardinality()) + " columns "
285               + (invert ? "not " : "") + "containing features of type "
286               + featureType + " across " + nseq + " sequence(s)");
287       return true;
288     }
289     else
290     {
291       avcg.setStatus("No features of type " + featureType + " found.");
292       if (!extendCurrent && cs != null)
293       {
294         cs.clear();
295         alignPanel.paintAlignment(true);
296       }
297       return false;
298     }
299   }
300
301   @Override
302   public void sortAlignmentByFeatureDensity(String[] typ)
303   {
304     sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
305   }
306
307   protected void sortBy(String[] typ, String methodText, final String method)
308   {
309     FeatureRenderer fr = alignPanel.getFeatureRenderer();
310     if (typ == null)
311     {
312       typ = fr==null ? null : fr.getDisplayedFeatureTypes();
313     }
314     String gps[] = null;
315     gps = fr==null ? null : fr.getDisplayedFeatureGroups();
316     if (typ != null)
317     {
318       ArrayList types = new ArrayList();
319       for (int i = 0; i < typ.length; i++)
320       {
321         if (typ[i] != null)
322         {
323           types.add(typ[i]);
324         }
325         typ = new String[types.size()];
326         types.toArray(typ);
327       }
328     }
329     if (gps != null)
330     {
331       ArrayList grps = new ArrayList();
332
333       for (int i = 0; i < gps.length; i++)
334       {
335         if (gps[i] != null)
336         {
337           grps.add(gps[i]);
338         }
339       }
340       gps = new String[grps.size()];
341       grps.toArray(gps);
342     }
343     AlignmentI al = viewport.getAlignment();
344
345     int start, stop;
346     SequenceGroup sg = viewport.getSelectionGroup();
347     if (sg != null)
348     {
349       start = sg.getStartRes();
350       stop = sg.getEndRes();
351     }
352     else
353     {
354       start = 0;
355       stop = al.getWidth();
356     }
357     SequenceI[] oldOrder = al.getSequencesArray();
358     AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
359     avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, viewport
360             .getAlignment()));
361     alignPanel.paintAlignment(true);
362
363   }
364
365   @Override
366   public void sortAlignmentByFeatureScore(String[] typ)
367   {
368     sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
369   }
370 }