Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.datamodel

File SearchResults.java

 

Coverage histogram

../../img/srcFileCovDistChart9.png
12% of files have more coverage

Code metrics

34
84
18
2
365
215
41
0.49
4.67
9
2.28

Classes

Class Line # Actions
SearchResults 34 62 29 13
0.8686868586.9%
SearchResults.Match 43 22 12 4
0.891891989.2%
 

Contributing tests

This file is covered by 60 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.datamodel;
22   
23    import java.util.ArrayList;
24    import java.util.BitSet;
25    import java.util.List;
26   
27    /**
28    * Holds a list of search result matches, where each match is a contiguous
29    * stretch of a single sequence.
30    *
31    * @author gmcarstairs amwaterhouse
32    *
33    */
 
34    public class SearchResults implements SearchResultsI
35    {
36   
37    private List<SearchResultMatchI> matches = new ArrayList<>();
38   
39    /**
40    * One match consists of a sequence reference, start and end positions.
41    * Discontiguous ranges in a sequence require two or more Match objects.
42    */
 
43    public class Match implements SearchResultMatchI
44    {
45    final SequenceI sequence;
46   
47    /**
48    * Start position of match in sequence (base 1)
49    */
50    final int start;
51   
52    /**
53    * End position (inclusive) (base 1)
54    */
55    final int end;
56   
57    /**
58    * create a Match on a range of sequence. Match always holds region in
59    * forwards order, even if given in reverse order (such as from a mapping to
60    * a reverse strand); this avoids trouble for routines that highlight search
61    * results etc
62    *
63    * @param seq
64    * a sequence
65    * @param start
66    * start position of matched range (base 1)
67    * @param end
68    * end of matched range (inclusive, base 1)
69    */
 
70  174 toggle public Match(SequenceI seq, int start, int end)
71    {
72  174 sequence = seq;
73   
74    /*
75    * always hold in forwards order, even if given in reverse order
76    * (such as from a mapping to a reverse strand); this avoids
77    * trouble for routines that highlight search results etc
78    */
79  174 if (start <= end)
80    {
81  173 this.start = start;
82  173 this.end = end;
83    }
84    else
85    {
86    // TODO: JBP could mark match as being specified in reverse direction
87    // for use
88    // by caller ? e.g. visualizing reverse strand highlight
89  1 this.start = end;
90  1 this.end = start;
91    }
92    }
93   
94    /* (non-Javadoc)
95    * @see jalview.datamodel.SearchResultMatchI#getSequence()
96    */
 
97  145 toggle @Override
98    public SequenceI getSequence()
99    {
100  145 return sequence;
101    }
102   
103    /* (non-Javadoc)
104    * @see jalview.datamodel.SearchResultMatchI#getStart()
105    */
 
106  170 toggle @Override
107    public int getStart()
108    {
109  170 return start;
110    }
111   
112    /* (non-Javadoc)
113    * @see jalview.datamodel.SearchResultMatchI#getEnd()
114    */
 
115  167 toggle @Override
116    public int getEnd()
117    {
118  167 return end;
119    }
120   
121    /**
122    * Returns a representation as "seqid/start-end"
123    */
 
124  7 toggle @Override
125    public String toString()
126    {
127  7 StringBuilder sb = new StringBuilder();
128  7 if (sequence != null)
129    {
130  7 sb.append(sequence.getName()).append("/");
131    }
132  7 sb.append(start).append("-").append(end);
133  7 return sb.toString();
134    }
135   
136    /**
137    * Hashcode is the hashcode of the matched sequence plus a hash of start and
138    * end positions. Match objects that pass the test for equals are guaranteed
139    * to have the same hashcode.
140    */
 
141  8 toggle @Override
142    public int hashCode()
143    {
144  8 int hash = sequence == null ? 0 : sequence.hashCode();
145  8 hash += 31 * start;
146  8 hash += 67 * end;
147  8 return hash;
148    }
149   
150    /**
151    * Two Match objects are equal if they are for the same sequence, start and
152    * end positions
153    */
 
154  22 toggle @Override
155    public boolean equals(Object obj)
156    {
157  22 if (obj == null || !(obj instanceof SearchResultMatchI))
158    {
159  0 return false;
160    }
161  22 SearchResultMatchI m = (SearchResultMatchI) obj;
162  22 return (sequence == m.getSequence() && start == m.getStart()
163    && end == m.getEnd());
164    }
165    }
166   
167    /* (non-Javadoc)
168    * @see jalview.datamodel.SearchResultsI#addResult(jalview.datamodel.SequenceI, int, int)
169    */
 
170  171 toggle @Override
171    public SearchResultMatchI addResult(SequenceI seq, int start, int end)
172    {
173  171 Match m = new Match(seq, start, end);
174  171 matches.add(m);
175  171 return m;
176    }
177   
178    /* (non-Javadoc)
179    * @see jalview.datamodel.SearchResultsI#involvesSequence(jalview.datamodel.SequenceI)
180    */
 
181  8 toggle @Override
182    public boolean involvesSequence(SequenceI sequence)
183    {
184  8 SequenceI ds = sequence.getDatasetSequence();
185  8 for (SearchResultMatchI _m : matches)
186    {
187  8 SequenceI matched = _m.getSequence();
188  8 if (matched != null && (matched == sequence || matched == ds))
189    {
190  1 return true;
191    }
192    }
193  7 return false;
194    }
195   
196    /* (non-Javadoc)
197    * @see jalview.datamodel.SearchResultsI#getResults(jalview.datamodel.SequenceI, int, int)
198    */
 
199  19 toggle @Override
200    public int[] getResults(SequenceI sequence, int start, int end)
201    {
202  19 if (matches.isEmpty())
203    {
204  0 return null;
205    }
206   
207  19 int[] result = null;
208  19 int[] tmp = null;
209  19 int resultLength, matchStart = 0, matchEnd = 0;
210  19 boolean mfound;
211  19 Match m;
212  19 for (SearchResultMatchI _m : matches)
213    {
214  43 m = (Match) _m;
215   
216  43 mfound = false;
217  43 if (m.sequence == sequence
218    || m.sequence == sequence.getDatasetSequence())
219    {
220  17 mfound = true;
221  17 matchStart = sequence.findIndex(m.start) - 1;
222  17 matchEnd = m.start == m.end ? matchStart : sequence
223    .findIndex(m.end) - 1;
224    }
225   
226  43 if (mfound)
227    {
228  17 if (matchStart <= end && matchEnd >= start)
229    {
230  17 if (matchStart < start)
231    {
232  1 matchStart = start;
233    }
234   
235  17 if (matchEnd > end)
236    {
237  1 matchEnd = end;
238    }
239   
240  17 if (result == null)
241    {
242  17 result = new int[] { matchStart, matchEnd };
243    }
244    else
245    {
246  0 resultLength = result.length;
247  0 tmp = new int[resultLength + 2];
248  0 System.arraycopy(result, 0, tmp, 0, resultLength);
249  0 result = tmp;
250  0 result[resultLength] = matchStart;
251  0 result[resultLength + 1] = matchEnd;
252    }
253    }
254    else
255    {
256    // debug
257    // System.err.println("Outwith bounds!" + matchStart+">"+end +" or "
258    // + matchEnd+"<"+start);
259    }
260    }
261    }
262  19 return result;
263    }
264   
 
265  7 toggle @Override
266    public int markColumns(SequenceCollectionI sqcol, BitSet bs)
267    {
268  7 int count = 0;
269  7 BitSet mask = new BitSet();
270  7 int startRes = sqcol.getStartRes();
271  7 int endRes = sqcol.getEndRes();
272   
273  7 for (SequenceI s : sqcol.getSequences())
274    {
275  12 int[] cols = getResults(s, startRes, endRes);
276  12 if (cols != null)
277    {
278  22 for (int pair = 0; pair < cols.length; pair += 2)
279    {
280  11 mask.set(cols[pair], cols[pair + 1] + 1);
281    }
282    }
283    }
284    // compute columns that were newly selected
285  7 BitSet original = (BitSet) bs.clone();
286  7 original.and(mask);
287  7 count = mask.cardinality() - original.cardinality();
288    // and mark ranges not already marked
289  7 bs.or(mask);
290  7 return count;
291    }
292   
293    /* (non-Javadoc)
294    * @see jalview.datamodel.SearchResultsI#getSize()
295    */
 
296  8 toggle @Override
297    public int getSize()
298    {
299  8 return matches.size();
300    }
301   
302    /* (non-Javadoc)
303    * @see jalview.datamodel.SearchResultsI#isEmpty()
304    */
 
305  460 toggle @Override
306    public boolean isEmpty()
307    {
308  460 return matches.isEmpty();
309    }
310   
311    /* (non-Javadoc)
312    * @see jalview.datamodel.SearchResultsI#getResults()
313    */
 
314  178 toggle @Override
315    public List<SearchResultMatchI> getResults()
316    {
317  178 return matches;
318    }
319   
320    /**
321    * Return the results as a list of matches [seq1/from-to, seq2/from-to, ...]
322    *
323    * @return
324    */
 
325  3 toggle @Override
326    public String toString()
327    {
328  3 return matches == null ? "" : matches.toString();
329    }
330   
331    /**
332    * Hashcode is derived from the list of matches. This ensures that when two
333    * SearchResults objects satisfy the test for equals(), then they have the
334    * same hashcode.
335    *
336    * @see Match#hashCode()
337    * @see java.util.AbstractList#hashCode()
338    */
 
339  6 toggle @Override
340    public int hashCode()
341    {
342  6 return matches.hashCode();
343    }
344   
345    /**
346    * Two SearchResults are considered equal if they contain the same matches in
347    * the same order.
348    */
 
349  36 toggle @Override
350    public boolean equals(Object obj)
351    {
352  36 if (obj == null || !(obj instanceof SearchResultsI))
353    {
354  7 return false;
355    }
356  29 SearchResultsI sr = (SearchResultsI) obj;
357  29 return matches.equals(sr.getResults());
358    }
359   
 
360  0 toggle @Override
361    public void addSearchResults(SearchResultsI toAdd)
362    {
363  0 matches.addAll(toAdd.getResults());
364    }
365    }