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.datamodel;
23 import java.util.ArrayList;
24 import java.util.List;
27 public class HiddenSequences
30 * holds a list of hidden sequences associated with an alignment.
32 public SequenceI[] hiddenSequences;
37 * Constructor given a reference to an alignment (with no hidden sequences)
41 public HiddenSequences(AlignmentI al)
47 * Answers the number of hidden sequences
53 if (hiddenSequences == null)
58 for (SequenceI seq : hiddenSequences)
70 * Answers the length of the longest hidden sequence
76 if (hiddenSequences == null)
81 for (SequenceI seq : hiddenSequences)
83 if (seq != null && seq.getLength() > width)
85 width = seq.getLength();
93 * Call this method after a sequence is removed from the main alignment
95 public void adjustHeightSequenceDeleted(int seqIndex)
97 if (hiddenSequences == null)
102 int alHeight = alignment.getHeight();
104 SequenceI[] tmp = new SequenceI[alHeight + getSize()];
105 int deletionIndex = adjustForHiddenSeqs(seqIndex);
107 for (int i = 0; i < hiddenSequences.length; i++)
109 if (hiddenSequences[i] == null)
114 if (i > deletionIndex)
116 tmp[i - 1] = hiddenSequences[i];
120 tmp[i] = hiddenSequences[i];
124 hiddenSequences = tmp;
129 * Call this method after a sequence is added to the main alignment
131 public void adjustHeightSequenceAdded()
133 if (hiddenSequences == null)
138 int alHeight = alignment.getHeight();
140 SequenceI[] tmp = new SequenceI[alHeight + getSize()];
141 System.arraycopy(hiddenSequences, 0, tmp, 0, hiddenSequences.length);
142 hiddenSequences = tmp;
146 * Mark the specified sequence as hidden
150 public void hideSequence(SequenceI sequence)
152 if (hiddenSequences == null)
154 hiddenSequences = new SequenceI[alignment.getHeight()];
157 int absAlignmentIndex = alignment.findIndex(sequence);
158 int alignmentIndex = adjustForHiddenSeqs(absAlignmentIndex);
160 if (alignmentIndex < 0 || hiddenSequences[alignmentIndex] != null)
162 System.out.println("ERROR!!!!!!!!!!!");
166 hiddenSequences[alignmentIndex] = sequence;
168 alignment.deleteHiddenSequence(absAlignmentIndex);
171 public List<SequenceI> showAll(
172 Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
174 List<SequenceI> revealedSeqs = new ArrayList<>();
176 if (hiddenSequences == null)
181 for (int i = 0; i < hiddenSequences.length; i++)
183 if (hiddenSequences[i] != null)
185 List<SequenceI> tmp = showSequence(i, hiddenRepSequences);
186 for (SequenceI seq : tmp)
188 revealedSeqs.add(seq);
196 * Reveals (unhides) consecutive hidden sequences just above the given
197 * alignment index. The revealed sequences are selected (including their
198 * visible representative sequence if there was one and 'reveal' is being
201 * @param alignmentIndex
202 * @param hiddenRepSequences
203 * a map of representative sequences to the sequences they represent
206 public List<SequenceI> showSequence(int alignmentIndex,
207 Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
209 List<SequenceI> revealedSeqs = new ArrayList<>();
210 SequenceI repSequence = alignment.getSequenceAt(alignmentIndex);
211 if (repSequence != null && hiddenRepSequences != null
212 && hiddenRepSequences.containsKey(repSequence))
214 hiddenRepSequences.remove(repSequence);
215 revealedSeqs.add(repSequence);
218 int start = adjustForHiddenSeqs(alignmentIndex - 1);
219 int end = adjustForHiddenSeqs(alignmentIndex);
220 if (end >= hiddenSequences.length)
222 end = hiddenSequences.length - 1;
225 List<SequenceI> asequences;
226 synchronized (asequences = alignment.getSequences())
228 for (int index = end; index > start; index--)
230 SequenceI seq = hiddenSequences[index];
231 hiddenSequences[index] = null;
235 if (seq.getLength() > 0)
237 revealedSeqs.add(seq);
238 asequences.add(alignmentIndex, seq);
243 seq.getName() + " has been deleted whilst hidden");
251 public SequenceI getHiddenSequence(int alignmentIndex)
253 return hiddenSequences == null ? null : hiddenSequences[alignmentIndex];
257 * Convert absolute alignment index to visible alignment index (or -1 if
258 * before the first visible sequence)
260 * @param alignmentIndex
263 public int findIndexWithoutHiddenSeqs(int alignmentIndex)
265 if (hiddenSequences == null)
267 return alignmentIndex;
272 if (hiddenSequences.length <= alignmentIndex)
274 // if the alignmentIndex runs past the end of hidden sequences
275 // and therefore actually past the end of the alignment
276 // store the difference to add back on at the end, so that behaviour
277 // is consistent with hidden columns behaviour (used by overview panel)
278 diff = alignmentIndex - hiddenSequences.length + 1;
279 alignmentIndex = hiddenSequences.length - 1;
282 while (index <= alignmentIndex)
284 if (hiddenSequences[index] != null)
291 return (alignmentIndex - hiddenSeqs + diff);
295 * Find the visible row which is a given visible number of rows above another
296 * visible row. i.e. for a startRow x, the row which is distance 1 away will
299 * @param visibleDistance
300 * the number of visible rows to offset by
302 * the row to start from
303 * @return the position of the row in the visible alignment
305 public int subtractVisibleRows(int visibleDistance, int startRow)
307 // walk upwards through the alignment
308 // count all the non-null sequences until we have visibleDistance counted
309 // then return the next visible sequence
310 if (hiddenSequences == null)
312 return startRow - visibleDistance;
315 int index = Math.min(startRow, hiddenSequences.length - 1);
317 while ((index > -1) && (count < visibleDistance))
319 if (hiddenSequences[index] == null)
321 // count visible sequences
330 * Convert alignment index from visible alignment to absolute alignment
332 * @param alignmentIndex
335 public int adjustForHiddenSeqs(int alignmentIndex)
337 if (hiddenSequences == null)
339 return alignmentIndex;
342 int hSize = hiddenSequences.length;
343 while (index <= alignmentIndex && index < hSize)
345 if (hiddenSequences[index] != null)
353 return alignmentIndex;
357 * makes a copy of the alignment with hidden sequences included. Using the
358 * copy for anything other than simple output is not recommended. Note - this
359 * method DOES NOT USE THE AlignmentI COPY CONSTRUCTOR!
363 public AlignmentI getFullAlignment()
366 if (hiddenSequences == null)
368 seq = alignment.getSequencesArray();
372 int isize = hiddenSequences.length;
373 seq = new Sequence[isize];
376 for (int i = 0; i < hiddenSequences.length; i++)
378 if (hiddenSequences[i] != null)
380 seq[i] = hiddenSequences[i];
384 seq[i] = alignment.getSequenceAt(index);
389 Alignment fAlignmt = new Alignment(seq);
390 fAlignmt.annotations = alignment.getAlignmentAnnotation();
391 fAlignmt.alignmentProperties = alignment.getProperties();
392 fAlignmt.groups = alignment.getGroups();
393 fAlignmt.hasRNAStructure = alignment.hasRNAStructure();
394 fAlignmt.setSeqrep(alignment.getSeqrep());
399 public boolean isHidden(SequenceI seq)
401 if (hiddenSequences != null)
403 for (int i = 0; i < hiddenSequences.length; i++)
405 if (hiddenSequences[i] != null && hiddenSequences[i] == seq)
416 * Answers if a sequence is hidden
419 * (absolute) index to test
420 * @return true if sequence at index seq is hidden
422 public boolean isHidden(int seq)
424 if (hiddenSequences != null)
426 return (hiddenSequences[seq] != null);