X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FHiddenColumns.java;h=fe2907df694bf4f2a4e0b9a764c0e97a04e8539d;hb=8e640547def8e151db1fafafe93a2a0bb8078369;hp=169b0a4e4dca973dd5da9abd0d5ef1204243758a;hpb=834dcc21a8a324b092285c1295df9392654d526b;p=jalview.git diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index 169b0a4..fe2907d 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -21,7 +21,6 @@ package jalview.datamodel; import jalview.util.Comparison; -import jalview.util.ShiftList; import java.util.ArrayList; import java.util.BitSet; @@ -33,7 +32,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class HiddenColumns { private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock(); - + /* * list of hidden column [start, end] ranges; the list is maintained in * ascending start column order @@ -135,8 +134,7 @@ public class HiddenColumns } } return size; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -290,47 +288,47 @@ public class HiddenColumns { LOCK.readLock().lock(); - int distance = visibleDistance; + int distance = visibleDistance; - // in case startColumn is in a hidden region, move it to the left - int start = adjustForHiddenColumns(findColumnPosition(startColumn)); + // in case startColumn is in a hidden region, move it to the left + int start = adjustForHiddenColumns(findColumnPosition(startColumn)); - // get index of hidden region to left of start - int index = getHiddenIndexLeft(start); - if (index == -1) - { - // no hidden regions to left of startColumn - return start - distance; - } + // get index of hidden region to left of start + int index = getHiddenIndexLeft(start); + if (index == -1) + { + // no hidden regions to left of startColumn + return start - distance; + } - // walk backwards through the alignment subtracting the counts of visible - // columns from distance - int[] region; - int gap = 0; - int nextstart = start; + // walk backwards through the alignment subtracting the counts of visible + // columns from distance + int[] region; + int gap = 0; + int nextstart = start; - while ((index > -1) && (distance - gap > 0)) - { - // subtract the gap to right of region from distance - distance -= gap; - start = nextstart; + while ((index > -1) && (distance - gap > 0)) + { + // subtract the gap to right of region from distance + distance -= gap; + start = nextstart; - // calculate the next gap - region = hiddenColumns.get(index); - gap = start - region[1]; + // calculate the next gap + region = hiddenColumns.get(index); + gap = start - region[1]; - // set start to just to left of current region - nextstart = region[0] - 1; - index--; - } + // set start to just to left of current region + nextstart = region[0] - 1; + index--; + } - if (distance - gap > 0) - { - // fell out of loop because there are no more hidden regions - distance -= gap; - return nextstart - distance; - } - return start - distance; + if (distance - gap > 0) + { + // fell out of loop because there are no more hidden regions + distance -= gap; + return nextstart - distance; + } + return start - distance; } finally { LOCK.readLock().unlock(); @@ -382,8 +380,7 @@ public class HiddenColumns } return positions; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -437,22 +434,22 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - int index = hiddenColumns.size() - 1; - do + if (hiddenColumns != null) { - int[] region = hiddenColumns.get(index); - if (alPos > region[1]) + int index = hiddenColumns.size() - 1; + do { - return region[1]; - } + int[] region = hiddenColumns.get(index); + if (alPos > region[1]) + { + return region[1]; + } - index--; - } while (index > -1); - } + index--; + } while (index > -1); + } - return alPos; + return alPos; } finally { LOCK.readLock().unlock(); @@ -473,22 +470,22 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - int index = hiddenColumns.size() - 1; - do + if (hiddenColumns != null) { - int[] region = hiddenColumns.get(index); - if (pos > region[1]) + int index = hiddenColumns.size() - 1; + do { - return index; - } + int[] region = hiddenColumns.get(index); + if (pos > region[1]) + { + return index; + } - index--; - } while (index > -1); - } + index--; + } while (index > -1); + } - return -1; + return -1; } finally { LOCK.readLock().unlock(); @@ -578,11 +575,11 @@ public class HiddenColumns } return; } - } + } - /* - * remaining case is that the new range follows everything else - */ + /* + * remaining case is that the new range follows everything else + */ hiddenColumns.add(new int[] { start, end }); } finally { @@ -599,18 +596,18 @@ public class HiddenColumns { LOCK.readLock().lock(); - if (hiddenColumns != null) - { - for (int[] region : hiddenColumns) + if (hiddenColumns != null) { - if (column >= region[0] && column <= region[1]) + for (int[] region : hiddenColumns) { - return false; + if (column >= region[0] && column <= region[1]) + { + return false; + } } } - } - return true; + return true; } finally { LOCK.readLock().unlock(); @@ -641,7 +638,7 @@ public class HiddenColumns return copy; } - + /** * Returns a copy of the vector of hidden regions, as an ArrayList. Before * using this method please consider if you really need access to the hidden @@ -760,8 +757,7 @@ public class HiddenColumns } } } - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -828,8 +824,7 @@ public class HiddenColumns { return new int[] { start, end - 1 }; } - } - finally + } finally { LOCK.readLock().unlock(); } @@ -898,8 +893,7 @@ public class HiddenColumns } return selections; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -928,7 +922,7 @@ public class HiddenColumns { int ifpos = seq.findIndex(fpos) - 1; int ilpos = seq.findIndex(lpos) - 1; - return new int[] { ifpos, ilpos, fpos, lpos, ifpos, ilpos }; + return new int[] { ifpos, ifpos, ilpos }; } // Simply walk along the sequence whilst watching for hidden column @@ -987,13 +981,11 @@ public class HiddenColumns } if (foundStart) { - return new int[] { findColumnPosition(start), - findColumnPosition(lastvispos), fpos, lpos, firstP, lastP }; + return new int[] { findColumnPosition(start), firstP, lastP }; } // otherwise, sequence was completely hidden - return new int[] { visPrev, visNext, 0, 0, firstP, lastP }; - } - finally + return new int[] { visPrev, firstP, lastP }; + } finally { LOCK.readLock().unlock(); } @@ -1114,8 +1106,7 @@ public class HiddenColumns { alignmentAnnotation.restrict(start, end); } - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1196,8 +1187,7 @@ public class HiddenColumns } hiddenColumns = null; - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -1232,133 +1222,7 @@ public class HiddenColumns { hiddenColumns = null; } - } - finally - { - LOCK.writeLock().unlock(); - } - } - - /** - * removes intersection of position,length ranges in deletions from the - * start,end regions marked in intervals. - * - * @param shifts - * @param intervals - * @return - */ - private boolean pruneIntervalList(final List shifts, - ArrayList intervals) - { - boolean pruned = false; - int i = 0; - int j = intervals.size() - 1; - int s = 0; - int t = shifts.size() - 1; - int[] hr = intervals.get(i); - int[] sr = shifts.get(s); - while (i <= j && s <= t) - { - boolean trailinghn = hr[1] >= sr[0]; - if (!trailinghn) - { - if (i < j) - { - hr = intervals.get(++i); - } - else - { - i++; - } - continue; - } - int endshift = sr[0] + sr[1]; // deletion ranges - -ve means an insert - if (endshift < hr[0] || endshift < sr[0]) - { // leadinghc disjoint or not a deletion - if (s < t) - { - sr = shifts.get(++s); - } - else - { - s++; - } - continue; - } - boolean leadinghn = hr[0] >= sr[0]; - boolean leadinghc = hr[0] < endshift; - boolean trailinghc = hr[1] < endshift; - if (leadinghn) - { - if (trailinghc) - { // deleted hidden region. - intervals.remove(i); - pruned = true; - j--; - if (i <= j) - { - hr = intervals.get(i); - } - continue; - } - if (leadinghc) - { - hr[0] = endshift; // clip c terminal region - leadinghn = !leadinghn; - pruned = true; - } - } - if (!leadinghn) - { - if (trailinghc) - { - if (trailinghn) - { - hr[1] = sr[0] - 1; - pruned = true; - } - } - else - { - // sr contained in hr - if (s < t) - { - sr = shifts.get(++s); - } - else - { - s++; - } - continue; - } - } - } - return pruned; // true if any interval was removed or modified by - // operations. - } - - /** - * remove any hiddenColumns or selected columns and shift remaining based on a - * series of position, range deletions. - * - * @param deletions - */ - public void pruneDeletions(List shifts) - { - try - { - LOCK.writeLock().lock(); - // delete any intervals intersecting. - if (hiddenColumns != null) - { - pruneIntervalList(shifts, hiddenColumns); - if (hiddenColumns != null && hiddenColumns.size() == 0) - { - hiddenColumns = null; - } - } - } - finally + } finally { LOCK.writeLock().unlock(); } @@ -1404,153 +1268,113 @@ public class HiddenColumns SequenceI origseq) { char gc = al.getGapCharacter(); - // recover mapping between sequence's non-gap positions and positions - // mapping to view. - pruneDeletions(ShiftList.parseMap(origseq.gapMap())); - int[] viscontigs = getVisibleContigs(0, profileseq.getLength()); - int spos = 0; - int offset = 0; - // add profile to visible contigs - for (int v = 0; v < viscontigs.length; v += 2) - { - if (viscontigs[v] > spos) + // take the set of hidden columns, and the set of gaps in origseq, + // and remove all the hidden gaps from hiddenColumns + + // first get the gaps as a Bitset + BitSet gaps = origseq.gapBitset(); + + // now calculate hidden ^ not(gap) + BitSet hidden = new BitSet(); + markHiddenRegions(hidden); + hidden.andNot(gaps); + hiddenColumns = null; + this.hideMarkedBits(hidden); + + // for each sequence in the alignment, except the profile sequence, + // insert gaps corresponding to each hidden region + // but where each hidden column region is shifted backwards by the number of + // preceding visible gaps + // update hidden columns at the same time + ArrayList regions = getHiddenColumnsCopy(); + ArrayList newhidden = new ArrayList<>(); + + int numGapsBefore = 0; + int gapPosition = 0; + for (int[] region : regions) + { + // get region coordinates accounting for gaps + // we can rely on gaps not being *in* hidden regions because we already + // removed those + while (gapPosition < region[0]) { - StringBuffer sb = new StringBuffer(); - for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++) + gapPosition++; + if (gaps.get(gapPosition)) { - sb.append(gc); + numGapsBefore++; } - for (int s = 0, ns = al.getHeight(); s < ns; s++) - { - SequenceI sqobj = al.getSequenceAt(s); - if (sqobj != profileseq) - { - String sq = al.getSequenceAt(s).getSequenceAsString(); - if (sq.length() <= spos + offset) - { - // pad sequence - int diff = spos + offset - sq.length() - 1; - if (diff > 0) - { - // pad gaps - sq = sq + sb; - while ((diff = spos + offset - sq.length() - 1) > 0) - { - // sq = sq - // + ((diff >= sb.length()) ? sb.toString() : sb - // .substring(0, diff)); - if (diff >= sb.length()) - { - sq += sb.toString(); - } - else - { - char[] buf = new char[diff]; - sb.getChars(0, diff, buf, 0); - sq += buf.toString(); - } - } - } - sq += sb.toString(); - } - else - { - al.getSequenceAt(s).setSequence( - sq.substring(0, spos + offset) + sb.toString() - + sq.substring(spos + offset)); - } - } - } - // offset+=sb.length(); } - spos = viscontigs[v + 1] + 1; - } - if ((offset + spos) < profileseq.getLength()) - { - // pad the final region with gaps. + + int left = region[0] - numGapsBefore; + int right = region[1] - numGapsBefore; + newhidden.add(new int[] { left, right }); + + // make a string with number of gaps = length of hidden region StringBuffer sb = new StringBuffer(); - for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++) + for (int s = 0; s < right - left + 1; s++) { sb.append(gc); } - for (int s = 0, ns = al.getHeight(); s < ns; s++) - { - SequenceI sqobj = al.getSequenceAt(s); - if (sqobj == profileseq) - { - continue; - } - String sq = sqobj.getSequenceAsString(); - // pad sequence - int diff = origseq.getLength() - sq.length(); - while (diff > 0) - { - // sq = sq - // + ((diff >= sb.length()) ? sb.toString() : sb - // .substring(0, diff)); - if (diff >= sb.length()) - { - sq += sb.toString(); - } - else - { - char[] buf = new char[diff]; - sb.getChars(0, diff, buf, 0); - sq += buf.toString(); - } - diff = origseq.getLength() - sq.length(); - } - } - } - } - - /** - * remove any hiddenColumns or selected columns and shift remaining based on a - * series of position, range deletions. - * - * @param deletions - */ - private void pruneDeletions(ShiftList deletions) - { - if (deletions != null) - { - final List shifts = deletions.getShifts(); - if (shifts != null && shifts.size() > 0) - { - pruneDeletions(shifts); + padGaps(sb, left, profileseq, al); - // and shift the rest. - this.compensateForEdits(deletions); - } } + hiddenColumns = newhidden; } /** - * Adjust hidden column boundaries based on a series of column additions or - * deletions in visible regions. + * Pad gaps in all sequences in alignment except profileseq * - * @param shiftrecord - * @return + * @param sb + * gap string to insert + * @param left + * position to insert at + * @param profileseq + * sequence not to pad + * @param al + * alignment to pad sequences in */ - private ShiftList compensateForEdits(ShiftList shiftrecord) + private void padGaps(StringBuffer sb, int pos, SequenceI profileseq, + AlignmentI al) { - if (shiftrecord != null) + // loop over the sequences and pad with gaps where required + for (int s = 0, ns = al.getHeight(); s < ns; s++) { - final List shifts = shiftrecord.getShifts(); - if (shifts != null && shifts.size() > 0) + SequenceI sqobj = al.getSequenceAt(s); + if (sqobj != profileseq) { - int shifted = 0; - for (int i = 0, j = shifts.size(); i < j; i++) + String sq = al.getSequenceAt(s).getSequenceAsString(); + if (sq.length() <= pos) { - int[] sh = shifts.get(i); - compensateForDelEdits(shifted + sh[0], sh[1]); - shifted -= sh[1]; + // pad sequence + int diff = pos - sq.length() - 1; + if (diff > 0) + { + // pad gaps + sq = sq + sb; + while ((diff = pos - sq.length() - 1) > 0) + { + if (diff >= sb.length()) + { + sq += sb.toString(); + } + else + { + char[] buf = new char[diff]; + sb.getChars(0, diff, buf, 0); + sq += buf.toString(); + } + } + } + sq += sb.toString(); + } + else + { + al.getSequenceAt(s).setSequence( + sq.substring(0, pos) + sb.toString() + sq.substring(pos)); } } - return shiftrecord.getInverse(); } - return null; } /** @@ -1572,8 +1396,7 @@ public class HiddenColumns } } return hashCode; - } - finally + } finally { LOCK.readLock().unlock(); } @@ -1621,8 +1444,7 @@ public class HiddenColumns { inserts.set(range[0], range[1] + 1); } - } - finally + } finally { LOCK.readLock().unlock(); }